1/* Expand builtin functions.
2 Copyright (C) 1988-2023 Free Software Foundation, Inc.
3
4This file is part of GCC.
5
6GCC is free software; you can redistribute it and/or modify it under
7the terms of the GNU General Public License as published by the Free
8Software Foundation; either version 3, or (at your option) any later
9version.
10
11GCC is distributed in the hope that it will be useful, but WITHOUT ANY
12WARRANTY; without even the implied warranty of MERCHANTABILITY or
13FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14for more details.
15
16You should have received a copy of the GNU General Public License
17along with GCC; see the file COPYING3. If not see
18<http://www.gnu.org/licenses/>. */
19
20/* Legacy warning! Please add no further builtin simplifications here
21 (apart from pure constant folding) - builtin simplifications should go
22 to match.pd or gimple-fold.cc instead. */
23
24#include "config.h"
25#include "system.h"
26#include "coretypes.h"
27#include "backend.h"
28#include "target.h"
29#include "rtl.h"
30#include "tree.h"
31#include "memmodel.h"
32#include "gimple.h"
33#include "predict.h"
34#include "tm_p.h"
35#include "stringpool.h"
36#include "tree-vrp.h"
37#include "tree-ssanames.h"
38#include "expmed.h"
39#include "optabs.h"
40#include "emit-rtl.h"
41#include "recog.h"
42#include "diagnostic-core.h"
43#include "alias.h"
44#include "fold-const.h"
45#include "fold-const-call.h"
46#include "gimple-ssa-warn-access.h"
47#include "stor-layout.h"
48#include "calls.h"
49#include "varasm.h"
50#include "tree-object-size.h"
51#include "tree-ssa-strlen.h"
52#include "realmpfr.h"
53#include "cfgrtl.h"
54#include "except.h"
55#include "dojump.h"
56#include "explow.h"
57#include "stmt.h"
58#include "expr.h"
59#include "libfuncs.h"
60#include "output.h"
61#include "typeclass.h"
62#include "langhooks.h"
63#include "value-prof.h"
64#include "builtins.h"
65#include "stringpool.h"
66#include "attribs.h"
67#include "asan.h"
68#include "internal-fn.h"
69#include "case-cfn-macros.h"
70#include "gimple-iterator.h"
71#include "gimple-fold.h"
72#include "intl.h"
73#include "file-prefix-map.h" /* remap_macro_filename() */
74#include "gomp-constants.h"
75#include "omp-general.h"
76#include "tree-dfa.h"
77#include "gimple-ssa.h"
78#include "tree-ssa-live.h"
79#include "tree-outof-ssa.h"
80#include "attr-fnspec.h"
81#include "demangle.h"
82#include "gimple-range.h"
83#include "pointer-query.h"
84
85struct target_builtins default_target_builtins;
86#if SWITCHABLE_TARGET
87struct target_builtins *this_target_builtins = &default_target_builtins;
88#endif
89
90/* Define the names of the builtin function types and codes. */
91const char *const built_in_class_names[BUILT_IN_LAST]
92 = {"NOT_BUILT_IN", "BUILT_IN_FRONTEND", "BUILT_IN_MD", "BUILT_IN_NORMAL"};
93
94#define DEF_BUILTIN(X, N, C, T, LT, B, F, NA, AT, IM, COND) #X,
95const char * built_in_names[(int) END_BUILTINS] =
96{
97#include "builtins.def"
98};
99
100/* Setup an array of builtin_info_type, make sure each element decl is
101 initialized to NULL_TREE. */
102builtin_info_type builtin_info[(int)END_BUILTINS];
103
104/* Non-zero if __builtin_constant_p should be folded right away. */
105bool force_folding_builtin_constant_p;
106
107static int target_char_cast (tree, char *);
108static int apply_args_size (void);
109static int apply_result_size (void);
110static rtx result_vector (int, rtx);
111static void expand_builtin_prefetch (tree);
112static rtx expand_builtin_apply_args (void);
113static rtx expand_builtin_apply_args_1 (void);
114static rtx expand_builtin_apply (rtx, rtx, rtx);
115static void expand_builtin_return (rtx);
116static rtx expand_builtin_classify_type (tree);
117static rtx expand_builtin_mathfn_3 (tree, rtx, rtx);
118static rtx expand_builtin_mathfn_ternary (tree, rtx, rtx);
119static rtx expand_builtin_interclass_mathfn (tree, rtx);
120static rtx expand_builtin_sincos (tree);
121static rtx expand_builtin_fegetround (tree, rtx, machine_mode);
122static rtx expand_builtin_feclear_feraise_except (tree, rtx, machine_mode,
123 optab);
124static rtx expand_builtin_cexpi (tree, rtx);
125static rtx expand_builtin_issignaling (tree, rtx);
126static rtx expand_builtin_int_roundingfn (tree, rtx);
127static rtx expand_builtin_int_roundingfn_2 (tree, rtx);
128static rtx expand_builtin_next_arg (void);
129static rtx expand_builtin_va_start (tree);
130static rtx expand_builtin_va_end (tree);
131static rtx expand_builtin_va_copy (tree);
132static rtx inline_expand_builtin_bytecmp (tree, rtx);
133static rtx expand_builtin_strcmp (tree, rtx);
134static rtx expand_builtin_strncmp (tree, rtx, machine_mode);
135static rtx expand_builtin_memcpy (tree, rtx);
136static rtx expand_builtin_memory_copy_args (tree dest, tree src, tree len,
137 rtx target, tree exp,
138 memop_ret retmode,
139 bool might_overlap);
140static rtx expand_builtin_memmove (tree, rtx);
141static rtx expand_builtin_mempcpy (tree, rtx);
142static rtx expand_builtin_mempcpy_args (tree, tree, tree, rtx, tree, memop_ret);
143static rtx expand_builtin_strcpy (tree, rtx);
144static rtx expand_builtin_strcpy_args (tree, tree, tree, rtx);
145static rtx expand_builtin_stpcpy (tree, rtx, machine_mode);
146static rtx expand_builtin_strncpy (tree, rtx);
147static rtx expand_builtin_memset_args (tree, tree, tree, rtx, machine_mode, tree);
148static rtx expand_builtin_bzero (tree);
149static rtx expand_builtin_strlen (tree, rtx, machine_mode);
150static rtx expand_builtin_strnlen (tree, rtx, machine_mode);
151static rtx expand_builtin_alloca (tree);
152static rtx expand_builtin_unop (machine_mode, tree, rtx, rtx, optab);
153static rtx expand_builtin_frame_address (tree, tree);
154static tree stabilize_va_list_loc (location_t, tree, int);
155static rtx expand_builtin_expect (tree, rtx);
156static rtx expand_builtin_expect_with_probability (tree, rtx);
157static tree fold_builtin_constant_p (tree);
158static tree fold_builtin_classify_type (tree);
159static tree fold_builtin_strlen (location_t, tree, tree, tree);
160static tree fold_builtin_inf (location_t, tree, int);
161static tree rewrite_call_expr (location_t, tree, int, tree, int, ...);
162static bool validate_arg (const_tree, enum tree_code code);
163static rtx expand_builtin_fabs (tree, rtx, rtx);
164static rtx expand_builtin_signbit (tree, rtx);
165static tree fold_builtin_memcmp (location_t, tree, tree, tree);
166static tree fold_builtin_isascii (location_t, tree);
167static tree fold_builtin_toascii (location_t, tree);
168static tree fold_builtin_isdigit (location_t, tree);
169static tree fold_builtin_fabs (location_t, tree, tree);
170static tree fold_builtin_abs (location_t, tree, tree);
171static tree fold_builtin_unordered_cmp (location_t, tree, tree, tree, enum tree_code,
172 enum tree_code);
173static tree fold_builtin_iseqsig (location_t, tree, tree);
174static tree fold_builtin_varargs (location_t, tree, tree*, int);
175
176static tree fold_builtin_strpbrk (location_t, tree, tree, tree, tree);
177static tree fold_builtin_strspn (location_t, tree, tree, tree);
178static tree fold_builtin_strcspn (location_t, tree, tree, tree);
179
180static rtx expand_builtin_object_size (tree);
181static rtx expand_builtin_memory_chk (tree, rtx, machine_mode,
182 enum built_in_function);
183static void maybe_emit_chk_warning (tree, enum built_in_function);
184static void maybe_emit_sprintf_chk_warning (tree, enum built_in_function);
185static tree fold_builtin_object_size (tree, tree, enum built_in_function);
186
187unsigned HOST_WIDE_INT target_newline;
188unsigned HOST_WIDE_INT target_percent;
189static unsigned HOST_WIDE_INT target_c;
190static unsigned HOST_WIDE_INT target_s;
191char target_percent_c[3];
192char target_percent_s[3];
193char target_percent_s_newline[4];
194static tree do_mpfr_remquo (tree, tree, tree);
195static tree do_mpfr_lgamma_r (tree, tree, tree);
196static void expand_builtin_sync_synchronize (void);
197
198/* Return true if NAME starts with __builtin_ or __sync_. */
199
200static bool
201is_builtin_name (const char *name)
202{
203 return (startswith (str: name, prefix: "__builtin_")
204 || startswith (str: name, prefix: "__sync_")
205 || startswith (str: name, prefix: "__atomic_"));
206}
207
208/* Return true if NODE should be considered for inline expansion regardless
209 of the optimization level. This means whenever a function is invoked with
210 its "internal" name, which normally contains the prefix "__builtin". */
211
212bool
213called_as_built_in (tree node)
214{
215 /* Note that we must use DECL_NAME, not DECL_ASSEMBLER_NAME_SET_P since
216 we want the name used to call the function, not the name it
217 will have. */
218 const char *name = IDENTIFIER_POINTER (DECL_NAME (node));
219 return is_builtin_name (name);
220}
221
222/* Compute values M and N such that M divides (address of EXP - N) and such
223 that N < M. If these numbers can be determined, store M in alignp and N in
224 *BITPOSP and return true. Otherwise return false and store BITS_PER_UNIT to
225 *alignp and any bit-offset to *bitposp.
226
227 Note that the address (and thus the alignment) computed here is based
228 on the address to which a symbol resolves, whereas DECL_ALIGN is based
229 on the address at which an object is actually located. These two
230 addresses are not always the same. For example, on ARM targets,
231 the address &foo of a Thumb function foo() has the lowest bit set,
232 whereas foo() itself starts on an even address.
233
234 If ADDR_P is true we are taking the address of the memory reference EXP
235 and thus cannot rely on the access taking place. */
236
237bool
238get_object_alignment_2 (tree exp, unsigned int *alignp,
239 unsigned HOST_WIDE_INT *bitposp, bool addr_p)
240{
241 poly_int64 bitsize, bitpos;
242 tree offset;
243 machine_mode mode;
244 int unsignedp, reversep, volatilep;
245 unsigned int align = BITS_PER_UNIT;
246 bool known_alignment = false;
247
248 /* Get the innermost object and the constant (bitpos) and possibly
249 variable (offset) offset of the access. */
250 exp = get_inner_reference (exp, &bitsize, &bitpos, &offset, &mode,
251 &unsignedp, &reversep, &volatilep);
252
253 /* Extract alignment information from the innermost object and
254 possibly adjust bitpos and offset. */
255 if (TREE_CODE (exp) == FUNCTION_DECL)
256 {
257 /* Function addresses can encode extra information besides their
258 alignment. However, if TARGET_PTRMEMFUNC_VBIT_LOCATION
259 allows the low bit to be used as a virtual bit, we know
260 that the address itself must be at least 2-byte aligned. */
261 if (TARGET_PTRMEMFUNC_VBIT_LOCATION == ptrmemfunc_vbit_in_pfn)
262 align = 2 * BITS_PER_UNIT;
263 }
264 else if (TREE_CODE (exp) == LABEL_DECL)
265 ;
266 else if (TREE_CODE (exp) == CONST_DECL)
267 {
268 /* The alignment of a CONST_DECL is determined by its initializer. */
269 exp = DECL_INITIAL (exp);
270 align = TYPE_ALIGN (TREE_TYPE (exp));
271 if (CONSTANT_CLASS_P (exp))
272 align = targetm.constant_alignment (exp, align);
273
274 known_alignment = true;
275 }
276 else if (DECL_P (exp))
277 {
278 align = DECL_ALIGN (exp);
279 known_alignment = true;
280 }
281 else if (TREE_CODE (exp) == INDIRECT_REF
282 || TREE_CODE (exp) == MEM_REF
283 || TREE_CODE (exp) == TARGET_MEM_REF)
284 {
285 tree addr = TREE_OPERAND (exp, 0);
286 unsigned ptr_align;
287 unsigned HOST_WIDE_INT ptr_bitpos;
288 unsigned HOST_WIDE_INT ptr_bitmask = ~0;
289
290 /* If the address is explicitely aligned, handle that. */
291 if (TREE_CODE (addr) == BIT_AND_EXPR
292 && TREE_CODE (TREE_OPERAND (addr, 1)) == INTEGER_CST)
293 {
294 ptr_bitmask = TREE_INT_CST_LOW (TREE_OPERAND (addr, 1));
295 ptr_bitmask *= BITS_PER_UNIT;
296 align = least_bit_hwi (x: ptr_bitmask);
297 addr = TREE_OPERAND (addr, 0);
298 }
299
300 known_alignment
301 = get_pointer_alignment_1 (addr, &ptr_align, &ptr_bitpos);
302 align = MAX (ptr_align, align);
303
304 /* Re-apply explicit alignment to the bitpos. */
305 ptr_bitpos &= ptr_bitmask;
306
307 /* The alignment of the pointer operand in a TARGET_MEM_REF
308 has to take the variable offset parts into account. */
309 if (TREE_CODE (exp) == TARGET_MEM_REF)
310 {
311 if (TMR_INDEX (exp))
312 {
313 unsigned HOST_WIDE_INT step = 1;
314 if (TMR_STEP (exp))
315 step = TREE_INT_CST_LOW (TMR_STEP (exp));
316 align = MIN (align, least_bit_hwi (step) * BITS_PER_UNIT);
317 }
318 if (TMR_INDEX2 (exp))
319 align = BITS_PER_UNIT;
320 known_alignment = false;
321 }
322
323 /* When EXP is an actual memory reference then we can use
324 TYPE_ALIGN of a pointer indirection to derive alignment.
325 Do so only if get_pointer_alignment_1 did not reveal absolute
326 alignment knowledge and if using that alignment would
327 improve the situation. */
328 unsigned int talign;
329 if (!addr_p && !known_alignment
330 && (talign = min_align_of_type (TREE_TYPE (exp)) * BITS_PER_UNIT)
331 && talign > align)
332 align = talign;
333 else
334 {
335 /* Else adjust bitpos accordingly. */
336 bitpos += ptr_bitpos;
337 if (TREE_CODE (exp) == MEM_REF
338 || TREE_CODE (exp) == TARGET_MEM_REF)
339 bitpos += mem_ref_offset (exp).force_shwi () * BITS_PER_UNIT;
340 }
341 }
342 else if (TREE_CODE (exp) == STRING_CST)
343 {
344 /* STRING_CST are the only constant objects we allow to be not
345 wrapped inside a CONST_DECL. */
346 align = TYPE_ALIGN (TREE_TYPE (exp));
347 if (CONSTANT_CLASS_P (exp))
348 align = targetm.constant_alignment (exp, align);
349
350 known_alignment = true;
351 }
352
353 /* If there is a non-constant offset part extract the maximum
354 alignment that can prevail. */
355 if (offset)
356 {
357 unsigned int trailing_zeros = tree_ctz (offset);
358 if (trailing_zeros < HOST_BITS_PER_INT)
359 {
360 unsigned int inner = (1U << trailing_zeros) * BITS_PER_UNIT;
361 if (inner)
362 align = MIN (align, inner);
363 }
364 }
365
366 /* Account for the alignment of runtime coefficients, so that the constant
367 bitpos is guaranteed to be accurate. */
368 unsigned int alt_align = ::known_alignment (a: bitpos - bitpos.coeffs[0]);
369 if (alt_align != 0 && alt_align < align)
370 {
371 align = alt_align;
372 known_alignment = false;
373 }
374
375 *alignp = align;
376 *bitposp = bitpos.coeffs[0] & (align - 1);
377 return known_alignment;
378}
379
380/* For a memory reference expression EXP compute values M and N such that M
381 divides (&EXP - N) and such that N < M. If these numbers can be determined,
382 store M in alignp and N in *BITPOSP and return true. Otherwise return false
383 and store BITS_PER_UNIT to *alignp and any bit-offset to *bitposp. */
384
385bool
386get_object_alignment_1 (tree exp, unsigned int *alignp,
387 unsigned HOST_WIDE_INT *bitposp)
388{
389 /* Strip a WITH_SIZE_EXPR, get_inner_reference doesn't know how to deal
390 with it. */
391 if (TREE_CODE (exp) == WITH_SIZE_EXPR)
392 exp = TREE_OPERAND (exp, 0);
393 return get_object_alignment_2 (exp, alignp, bitposp, addr_p: false);
394}
395
396/* Return the alignment in bits of EXP, an object. */
397
398unsigned int
399get_object_alignment (tree exp)
400{
401 unsigned HOST_WIDE_INT bitpos = 0;
402 unsigned int align;
403
404 get_object_alignment_1 (exp, alignp: &align, bitposp: &bitpos);
405
406 /* align and bitpos now specify known low bits of the pointer.
407 ptr & (align - 1) == bitpos. */
408
409 if (bitpos != 0)
410 align = least_bit_hwi (x: bitpos);
411 return align;
412}
413
414/* For a pointer valued expression EXP compute values M and N such that M
415 divides (EXP - N) and such that N < M. If these numbers can be determined,
416 store M in alignp and N in *BITPOSP and return true. Return false if
417 the results are just a conservative approximation.
418
419 If EXP is not a pointer, false is returned too. */
420
421bool
422get_pointer_alignment_1 (tree exp, unsigned int *alignp,
423 unsigned HOST_WIDE_INT *bitposp)
424{
425 STRIP_NOPS (exp);
426
427 if (TREE_CODE (exp) == ADDR_EXPR)
428 return get_object_alignment_2 (TREE_OPERAND (exp, 0),
429 alignp, bitposp, addr_p: true);
430 else if (TREE_CODE (exp) == POINTER_PLUS_EXPR)
431 {
432 unsigned int align;
433 unsigned HOST_WIDE_INT bitpos;
434 bool res = get_pointer_alignment_1 (TREE_OPERAND (exp, 0),
435 alignp: &align, bitposp: &bitpos);
436 if (TREE_CODE (TREE_OPERAND (exp, 1)) == INTEGER_CST)
437 bitpos += TREE_INT_CST_LOW (TREE_OPERAND (exp, 1)) * BITS_PER_UNIT;
438 else
439 {
440 unsigned int trailing_zeros = tree_ctz (TREE_OPERAND (exp, 1));
441 if (trailing_zeros < HOST_BITS_PER_INT)
442 {
443 unsigned int inner = (1U << trailing_zeros) * BITS_PER_UNIT;
444 if (inner)
445 align = MIN (align, inner);
446 }
447 }
448 *alignp = align;
449 *bitposp = bitpos & (align - 1);
450 return res;
451 }
452 else if (TREE_CODE (exp) == SSA_NAME
453 && POINTER_TYPE_P (TREE_TYPE (exp)))
454 {
455 unsigned int ptr_align, ptr_misalign;
456 struct ptr_info_def *pi = SSA_NAME_PTR_INFO (exp);
457
458 if (pi && get_ptr_info_alignment (pi, &ptr_align, &ptr_misalign))
459 {
460 *bitposp = ptr_misalign * BITS_PER_UNIT;
461 *alignp = ptr_align * BITS_PER_UNIT;
462 /* Make sure to return a sensible alignment when the multiplication
463 by BITS_PER_UNIT overflowed. */
464 if (*alignp == 0)
465 *alignp = 1u << (HOST_BITS_PER_INT - 1);
466 /* We cannot really tell whether this result is an approximation. */
467 return false;
468 }
469 else
470 {
471 *bitposp = 0;
472 *alignp = BITS_PER_UNIT;
473 return false;
474 }
475 }
476 else if (TREE_CODE (exp) == INTEGER_CST)
477 {
478 *alignp = BIGGEST_ALIGNMENT;
479 *bitposp = ((TREE_INT_CST_LOW (exp) * BITS_PER_UNIT)
480 & (BIGGEST_ALIGNMENT - 1));
481 return true;
482 }
483
484 *bitposp = 0;
485 *alignp = BITS_PER_UNIT;
486 return false;
487}
488
489/* Return the alignment in bits of EXP, a pointer valued expression.
490 The alignment returned is, by default, the alignment of the thing that
491 EXP points to. If it is not a POINTER_TYPE, 0 is returned.
492
493 Otherwise, look at the expression to see if we can do better, i.e., if the
494 expression is actually pointing at an object whose alignment is tighter. */
495
496unsigned int
497get_pointer_alignment (tree exp)
498{
499 unsigned HOST_WIDE_INT bitpos = 0;
500 unsigned int align;
501
502 get_pointer_alignment_1 (exp, alignp: &align, bitposp: &bitpos);
503
504 /* align and bitpos now specify known low bits of the pointer.
505 ptr & (align - 1) == bitpos. */
506
507 if (bitpos != 0)
508 align = least_bit_hwi (x: bitpos);
509
510 return align;
511}
512
513/* Return the number of leading non-zero elements in the sequence
514 [ PTR, PTR + MAXELTS ) where each element's size is ELTSIZE bytes.
515 ELTSIZE must be a power of 2 less than 8. Used by c_strlen. */
516
517unsigned
518string_length (const void *ptr, unsigned eltsize, unsigned maxelts)
519{
520 gcc_checking_assert (eltsize == 1 || eltsize == 2 || eltsize == 4);
521
522 unsigned n;
523
524 if (eltsize == 1)
525 {
526 /* Optimize the common case of plain char. */
527 for (n = 0; n < maxelts; n++)
528 {
529 const char *elt = (const char*) ptr + n;
530 if (!*elt)
531 break;
532 }
533 }
534 else
535 {
536 for (n = 0; n < maxelts; n++)
537 {
538 const char *elt = (const char*) ptr + n * eltsize;
539 if (!memcmp (s1: elt, s2: "\0\0\0\0", n: eltsize))
540 break;
541 }
542 }
543 return n;
544}
545
546/* Compute the length of a null-terminated character string or wide
547 character string handling character sizes of 1, 2, and 4 bytes.
548 TREE_STRING_LENGTH is not the right way because it evaluates to
549 the size of the character array in bytes (as opposed to characters)
550 and because it can contain a zero byte in the middle.
551
552 ONLY_VALUE should be nonzero if the result is not going to be emitted
553 into the instruction stream and zero if it is going to be expanded.
554 E.g. with i++ ? "foo" : "bar", if ONLY_VALUE is nonzero, constant 3
555 is returned, otherwise NULL, since
556 len = c_strlen (ARG, 1); if (len) expand_expr (len, ...); would not
557 evaluate the side-effects.
558
559 If ONLY_VALUE is two then we do not emit warnings about out-of-bound
560 accesses. Note that this implies the result is not going to be emitted
561 into the instruction stream.
562
563 Additional information about the string accessed may be recorded
564 in DATA. For example, if ARG references an unterminated string,
565 then the declaration will be stored in the DECL field. If the
566 length of the unterminated string can be determined, it'll be
567 stored in the LEN field. Note this length could well be different
568 than what a C strlen call would return.
569
570 ELTSIZE is 1 for normal single byte character strings, and 2 or
571 4 for wide characer strings. ELTSIZE is by default 1.
572
573 The value returned is of type `ssizetype'. */
574
575tree
576c_strlen (tree arg, int only_value, c_strlen_data *data, unsigned eltsize)
577{
578 /* If we were not passed a DATA pointer, then get one to a local
579 structure. That avoids having to check DATA for NULL before
580 each time we want to use it. */
581 c_strlen_data local_strlen_data = { };
582 if (!data)
583 data = &local_strlen_data;
584
585 gcc_checking_assert (eltsize == 1 || eltsize == 2 || eltsize == 4);
586
587 tree src = STRIP_NOPS (arg);
588 if (TREE_CODE (src) == COND_EXPR
589 && (only_value || !TREE_SIDE_EFFECTS (TREE_OPERAND (src, 0))))
590 {
591 tree len1, len2;
592
593 len1 = c_strlen (TREE_OPERAND (src, 1), only_value, data, eltsize);
594 len2 = c_strlen (TREE_OPERAND (src, 2), only_value, data, eltsize);
595 if (tree_int_cst_equal (len1, len2))
596 return len1;
597 }
598
599 if (TREE_CODE (src) == COMPOUND_EXPR
600 && (only_value || !TREE_SIDE_EFFECTS (TREE_OPERAND (src, 0))))
601 return c_strlen (TREE_OPERAND (src, 1), only_value, data, eltsize);
602
603 location_t loc = EXPR_LOC_OR_LOC (src, input_location);
604
605 /* Offset from the beginning of the string in bytes. */
606 tree byteoff;
607 tree memsize;
608 tree decl;
609 src = string_constant (src, &byteoff, &memsize, &decl);
610 if (src == 0)
611 return NULL_TREE;
612
613 /* Determine the size of the string element. */
614 if (eltsize != tree_to_uhwi (TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (src)))))
615 return NULL_TREE;
616
617 /* Set MAXELTS to ARRAY_SIZE (SRC) - 1, the maximum possible
618 length of SRC. Prefer TYPE_SIZE() to TREE_STRING_LENGTH() if possible
619 in case the latter is less than the size of the array, such as when
620 SRC refers to a short string literal used to initialize a large array.
621 In that case, the elements of the array after the terminating NUL are
622 all NUL. */
623 HOST_WIDE_INT strelts = TREE_STRING_LENGTH (src);
624 strelts = strelts / eltsize;
625
626 if (!tree_fits_uhwi_p (memsize))
627 return NULL_TREE;
628
629 HOST_WIDE_INT maxelts = tree_to_uhwi (memsize) / eltsize;
630
631 /* PTR can point to the byte representation of any string type, including
632 char* and wchar_t*. */
633 const char *ptr = TREE_STRING_POINTER (src);
634
635 if (byteoff && TREE_CODE (byteoff) != INTEGER_CST)
636 {
637 /* The code below works only for single byte character types. */
638 if (eltsize != 1)
639 return NULL_TREE;
640
641 /* If the string has an internal NUL character followed by any
642 non-NUL characters (e.g., "foo\0bar"), we can't compute
643 the offset to the following NUL if we don't know where to
644 start searching for it. */
645 unsigned len = string_length (ptr, eltsize, maxelts: strelts);
646
647 /* Return when an embedded null character is found or none at all.
648 In the latter case, set the DECL/LEN field in the DATA structure
649 so that callers may examine them. */
650 if (len + 1 < strelts)
651 return NULL_TREE;
652 else if (len >= maxelts)
653 {
654 data->decl = decl;
655 data->off = byteoff;
656 data->minlen = ssize_int (len);
657 return NULL_TREE;
658 }
659
660 /* For empty strings the result should be zero. */
661 if (len == 0)
662 return ssize_int (0);
663
664 /* We don't know the starting offset, but we do know that the string
665 has no internal zero bytes. If the offset falls within the bounds
666 of the string subtract the offset from the length of the string,
667 and return that. Otherwise the length is zero. Take care to
668 use SAVE_EXPR in case the OFFSET has side-effects. */
669 tree offsave = TREE_SIDE_EFFECTS (byteoff) ? save_expr (byteoff)
670 : byteoff;
671 offsave = fold_convert_loc (loc, sizetype, offsave);
672 tree condexp = fold_build2_loc (loc, LE_EXPR, boolean_type_node, offsave,
673 size_int (len));
674 tree lenexp = fold_build2_loc (loc, MINUS_EXPR, sizetype, size_int (len),
675 offsave);
676 lenexp = fold_convert_loc (loc, ssizetype, lenexp);
677 return fold_build3_loc (loc, COND_EXPR, ssizetype, condexp, lenexp,
678 build_zero_cst (ssizetype));
679 }
680
681 /* Offset from the beginning of the string in elements. */
682 HOST_WIDE_INT eltoff;
683
684 /* We have a known offset into the string. Start searching there for
685 a null character if we can represent it as a single HOST_WIDE_INT. */
686 if (byteoff == 0)
687 eltoff = 0;
688 else if (! tree_fits_uhwi_p (byteoff) || tree_to_uhwi (byteoff) % eltsize)
689 eltoff = -1;
690 else
691 eltoff = tree_to_uhwi (byteoff) / eltsize;
692
693 /* If the offset is known to be out of bounds, warn, and call strlen at
694 runtime. */
695 if (eltoff < 0 || eltoff >= maxelts)
696 {
697 /* Suppress multiple warnings for propagated constant strings. */
698 if (only_value != 2
699 && !warning_suppressed_p (arg, OPT_Warray_bounds_)
700 && warning_at (loc, OPT_Warray_bounds_,
701 "offset %qwi outside bounds of constant string",
702 eltoff))
703 {
704 if (decl)
705 inform (DECL_SOURCE_LOCATION (decl), "%qE declared here", decl);
706 suppress_warning (arg, OPT_Warray_bounds_);
707 }
708 return NULL_TREE;
709 }
710
711 /* If eltoff is larger than strelts but less than maxelts the
712 string length is zero, since the excess memory will be zero. */
713 if (eltoff > strelts)
714 return ssize_int (0);
715
716 /* Use strlen to search for the first zero byte. Since any strings
717 constructed with build_string will have nulls appended, we win even
718 if we get handed something like (char[4])"abcd".
719
720 Since ELTOFF is our starting index into the string, no further
721 calculation is needed. */
722 unsigned len = string_length (ptr: ptr + eltoff * eltsize, eltsize,
723 maxelts: strelts - eltoff);
724
725 /* Don't know what to return if there was no zero termination.
726 Ideally this would turn into a gcc_checking_assert over time.
727 Set DECL/LEN so callers can examine them. */
728 if (len >= maxelts - eltoff)
729 {
730 data->decl = decl;
731 data->off = byteoff;
732 data->minlen = ssize_int (len);
733 return NULL_TREE;
734 }
735
736 return ssize_int (len);
737}
738
739/* Return a constant integer corresponding to target reading
740 GET_MODE_BITSIZE (MODE) bits from string constant STR. If
741 NULL_TERMINATED_P, reading stops after '\0' character, all further ones
742 are assumed to be zero, otherwise it reads as many characters
743 as needed. */
744
745rtx
746c_readstr (const char *str, fixed_size_mode mode,
747 bool null_terminated_p/*=true*/)
748{
749 auto_vec<target_unit, MAX_BITSIZE_MODE_ANY_INT / BITS_PER_UNIT> bytes;
750
751 bytes.reserve (nelems: GET_MODE_SIZE (mode));
752
753 target_unit ch = 1;
754 for (unsigned int i = 0; i < GET_MODE_SIZE (mode); ++i)
755 {
756 if (ch || !null_terminated_p)
757 ch = (unsigned char) str[i];
758 bytes.quick_push (obj: ch);
759 }
760
761 return native_decode_rtx (mode, bytes, 0);
762}
763
764/* Cast a target constant CST to target CHAR and if that value fits into
765 host char type, return zero and put that value into variable pointed to by
766 P. */
767
768static int
769target_char_cast (tree cst, char *p)
770{
771 unsigned HOST_WIDE_INT val, hostval;
772
773 if (TREE_CODE (cst) != INTEGER_CST
774 || CHAR_TYPE_SIZE > HOST_BITS_PER_WIDE_INT)
775 return 1;
776
777 /* Do not care if it fits or not right here. */
778 val = TREE_INT_CST_LOW (cst);
779
780 if (CHAR_TYPE_SIZE < HOST_BITS_PER_WIDE_INT)
781 val &= (HOST_WIDE_INT_1U << CHAR_TYPE_SIZE) - 1;
782
783 hostval = val;
784 if (HOST_BITS_PER_CHAR < HOST_BITS_PER_WIDE_INT)
785 hostval &= (HOST_WIDE_INT_1U << HOST_BITS_PER_CHAR) - 1;
786
787 if (val != hostval)
788 return 1;
789
790 *p = hostval;
791 return 0;
792}
793
794/* Similar to save_expr, but assumes that arbitrary code is not executed
795 in between the multiple evaluations. In particular, we assume that a
796 non-addressable local variable will not be modified. */
797
798static tree
799builtin_save_expr (tree exp)
800{
801 if (TREE_CODE (exp) == SSA_NAME
802 || (TREE_ADDRESSABLE (exp) == 0
803 && (TREE_CODE (exp) == PARM_DECL
804 || (VAR_P (exp) && !TREE_STATIC (exp)))))
805 return exp;
806
807 return save_expr (exp);
808}
809
810/* Given TEM, a pointer to a stack frame, follow the dynamic chain COUNT
811 times to get the address of either a higher stack frame, or a return
812 address located within it (depending on FNDECL_CODE). */
813
814static rtx
815expand_builtin_return_addr (enum built_in_function fndecl_code, int count)
816{
817 int i;
818 rtx tem = INITIAL_FRAME_ADDRESS_RTX;
819 if (tem == NULL_RTX)
820 {
821 /* For a zero count with __builtin_return_address, we don't care what
822 frame address we return, because target-specific definitions will
823 override us. Therefore frame pointer elimination is OK, and using
824 the soft frame pointer is OK.
825
826 For a nonzero count, or a zero count with __builtin_frame_address,
827 we require a stable offset from the current frame pointer to the
828 previous one, so we must use the hard frame pointer, and
829 we must disable frame pointer elimination. */
830 if (count == 0 && fndecl_code == BUILT_IN_RETURN_ADDRESS)
831 tem = frame_pointer_rtx;
832 else
833 {
834 tem = hard_frame_pointer_rtx;
835
836 /* Tell reload not to eliminate the frame pointer. */
837 crtl->accesses_prior_frames = 1;
838 }
839 }
840
841 if (count > 0)
842 SETUP_FRAME_ADDRESSES ();
843
844 /* On the SPARC, the return address is not in the frame, it is in a
845 register. There is no way to access it off of the current frame
846 pointer, but it can be accessed off the previous frame pointer by
847 reading the value from the register window save area. */
848 if (RETURN_ADDR_IN_PREVIOUS_FRAME && fndecl_code == BUILT_IN_RETURN_ADDRESS)
849 count--;
850
851 /* Scan back COUNT frames to the specified frame. */
852 for (i = 0; i < count; i++)
853 {
854 /* Assume the dynamic chain pointer is in the word that the
855 frame address points to, unless otherwise specified. */
856 tem = DYNAMIC_CHAIN_ADDRESS (tem);
857 tem = memory_address (Pmode, tem);
858 tem = gen_frame_mem (Pmode, tem);
859 tem = copy_to_reg (tem);
860 }
861
862 /* For __builtin_frame_address, return what we've got. But, on
863 the SPARC for example, we may have to add a bias. */
864 if (fndecl_code == BUILT_IN_FRAME_ADDRESS)
865 return FRAME_ADDR_RTX (tem);
866
867 /* For __builtin_return_address, get the return address from that frame. */
868#ifdef RETURN_ADDR_RTX
869 tem = RETURN_ADDR_RTX (count, tem);
870#else
871 tem = memory_address (Pmode,
872 plus_constant (Pmode, tem, GET_MODE_SIZE (Pmode)));
873 tem = gen_frame_mem (Pmode, tem);
874#endif
875 return tem;
876}
877
878/* Alias set used for setjmp buffer. */
879static alias_set_type setjmp_alias_set = -1;
880
881/* Construct the leading half of a __builtin_setjmp call. Control will
882 return to RECEIVER_LABEL. This is also called directly by the SJLJ
883 exception handling code. */
884
885void
886expand_builtin_setjmp_setup (rtx buf_addr, rtx receiver_label)
887{
888 machine_mode sa_mode = STACK_SAVEAREA_MODE (SAVE_NONLOCAL);
889 rtx stack_save;
890 rtx mem;
891
892 if (setjmp_alias_set == -1)
893 setjmp_alias_set = new_alias_set ();
894
895 buf_addr = convert_memory_address (Pmode, buf_addr);
896
897 buf_addr = force_reg (Pmode, force_operand (buf_addr, NULL_RTX));
898
899 /* We store the frame pointer and the address of receiver_label in
900 the buffer and use the rest of it for the stack save area, which
901 is machine-dependent. */
902
903 mem = gen_rtx_MEM (Pmode, buf_addr);
904 set_mem_alias_set (mem, setjmp_alias_set);
905 emit_move_insn (mem, hard_frame_pointer_rtx);
906
907 mem = gen_rtx_MEM (Pmode, plus_constant (Pmode, buf_addr,
908 GET_MODE_SIZE (Pmode))),
909 set_mem_alias_set (mem, setjmp_alias_set);
910
911 emit_move_insn (validize_mem (mem),
912 force_reg (Pmode, gen_rtx_LABEL_REF (Pmode, receiver_label)));
913
914 stack_save = gen_rtx_MEM (sa_mode,
915 plus_constant (Pmode, buf_addr,
916 2 * GET_MODE_SIZE (Pmode)));
917 set_mem_alias_set (stack_save, setjmp_alias_set);
918 emit_stack_save (SAVE_NONLOCAL, &stack_save);
919
920 /* If there is further processing to do, do it. */
921 if (targetm.have_builtin_setjmp_setup ())
922 emit_insn (targetm.gen_builtin_setjmp_setup (buf_addr));
923
924 /* We have a nonlocal label. */
925 cfun->has_nonlocal_label = 1;
926}
927
928/* Construct the trailing part of a __builtin_setjmp call. This is
929 also called directly by the SJLJ exception handling code.
930 If RECEIVER_LABEL is NULL, instead contruct a nonlocal goto handler. */
931
932void
933expand_builtin_setjmp_receiver (rtx receiver_label)
934{
935 rtx chain;
936
937 /* Mark the FP as used when we get here, so we have to make sure it's
938 marked as used by this function. */
939 emit_use (hard_frame_pointer_rtx);
940
941 /* Mark the static chain as clobbered here so life information
942 doesn't get messed up for it. */
943 chain = rtx_for_static_chain (current_function_decl, true);
944 if (chain && REG_P (chain))
945 emit_clobber (chain);
946
947 if (!HARD_FRAME_POINTER_IS_ARG_POINTER && fixed_regs[ARG_POINTER_REGNUM])
948 {
949 /* If the argument pointer can be eliminated in favor of the
950 frame pointer, we don't need to restore it. We assume here
951 that if such an elimination is present, it can always be used.
952 This is the case on all known machines; if we don't make this
953 assumption, we do unnecessary saving on many machines. */
954 size_t i;
955 static const struct elims {const int from, to;} elim_regs[] = ELIMINABLE_REGS;
956
957 for (i = 0; i < ARRAY_SIZE (elim_regs); i++)
958 if (elim_regs[i].from == ARG_POINTER_REGNUM
959 && elim_regs[i].to == HARD_FRAME_POINTER_REGNUM)
960 break;
961
962 if (i == ARRAY_SIZE (elim_regs))
963 {
964 /* Now restore our arg pointer from the address at which it
965 was saved in our stack frame. */
966 emit_move_insn (crtl->args.internal_arg_pointer,
967 copy_to_reg (get_arg_pointer_save_area ()));
968 }
969 }
970
971 if (receiver_label != NULL && targetm.have_builtin_setjmp_receiver ())
972 emit_insn (targetm.gen_builtin_setjmp_receiver (receiver_label));
973 else if (targetm.have_nonlocal_goto_receiver ())
974 emit_insn (targetm.gen_nonlocal_goto_receiver ());
975 else
976 { /* Nothing */ }
977
978 /* We must not allow the code we just generated to be reordered by
979 scheduling. Specifically, the update of the frame pointer must
980 happen immediately, not later. */
981 emit_insn (gen_blockage ());
982}
983
984/* __builtin_longjmp is passed a pointer to an array of five words (not
985 all will be used on all machines). It operates similarly to the C
986 library function of the same name, but is more efficient. Much of
987 the code below is copied from the handling of non-local gotos. */
988
989static void
990expand_builtin_longjmp (rtx buf_addr, rtx value)
991{
992 rtx fp, lab, stack;
993 rtx_insn *insn, *last;
994 machine_mode sa_mode = STACK_SAVEAREA_MODE (SAVE_NONLOCAL);
995
996 /* DRAP is needed for stack realign if longjmp is expanded to current
997 function */
998 if (SUPPORTS_STACK_ALIGNMENT)
999 crtl->need_drap = true;
1000
1001 if (setjmp_alias_set == -1)
1002 setjmp_alias_set = new_alias_set ();
1003
1004 buf_addr = convert_memory_address (Pmode, buf_addr);
1005
1006 buf_addr = force_reg (Pmode, buf_addr);
1007
1008 /* We require that the user must pass a second argument of 1, because
1009 that is what builtin_setjmp will return. */
1010 gcc_assert (value == const1_rtx);
1011
1012 last = get_last_insn ();
1013 if (targetm.have_builtin_longjmp ())
1014 emit_insn (targetm.gen_builtin_longjmp (buf_addr));
1015 else
1016 {
1017 fp = gen_rtx_MEM (Pmode, buf_addr);
1018 lab = gen_rtx_MEM (Pmode, plus_constant (Pmode, buf_addr,
1019 GET_MODE_SIZE (Pmode)));
1020
1021 stack = gen_rtx_MEM (sa_mode, plus_constant (Pmode, buf_addr,
1022 2 * GET_MODE_SIZE (Pmode)));
1023 set_mem_alias_set (fp, setjmp_alias_set);
1024 set_mem_alias_set (lab, setjmp_alias_set);
1025 set_mem_alias_set (stack, setjmp_alias_set);
1026
1027 /* Pick up FP, label, and SP from the block and jump. This code is
1028 from expand_goto in stmt.cc; see there for detailed comments. */
1029 if (targetm.have_nonlocal_goto ())
1030 /* We have to pass a value to the nonlocal_goto pattern that will
1031 get copied into the static_chain pointer, but it does not matter
1032 what that value is, because builtin_setjmp does not use it. */
1033 emit_insn (targetm.gen_nonlocal_goto (value, lab, stack, fp));
1034 else
1035 {
1036 emit_clobber (gen_rtx_MEM (BLKmode, gen_rtx_SCRATCH (VOIDmode)));
1037 emit_clobber (gen_rtx_MEM (BLKmode, hard_frame_pointer_rtx));
1038
1039 lab = copy_to_reg (lab);
1040
1041 /* Restore the frame pointer and stack pointer. We must use a
1042 temporary since the setjmp buffer may be a local. */
1043 fp = copy_to_reg (fp);
1044 emit_stack_restore (SAVE_NONLOCAL, stack);
1045
1046 /* Ensure the frame pointer move is not optimized. */
1047 emit_insn (gen_blockage ());
1048 emit_clobber (hard_frame_pointer_rtx);
1049 emit_clobber (frame_pointer_rtx);
1050 emit_move_insn (hard_frame_pointer_rtx, fp);
1051
1052 emit_use (hard_frame_pointer_rtx);
1053 emit_use (stack_pointer_rtx);
1054 emit_indirect_jump (lab);
1055 }
1056 }
1057
1058 /* Search backwards and mark the jump insn as a non-local goto.
1059 Note that this precludes the use of __builtin_longjmp to a
1060 __builtin_setjmp target in the same function. However, we've
1061 already cautioned the user that these functions are for
1062 internal exception handling use only. */
1063 for (insn = get_last_insn (); insn; insn = PREV_INSN (insn))
1064 {
1065 gcc_assert (insn != last);
1066
1067 if (JUMP_P (insn))
1068 {
1069 add_reg_note (insn, REG_NON_LOCAL_GOTO, const0_rtx);
1070 break;
1071 }
1072 else if (CALL_P (insn))
1073 break;
1074 }
1075}
1076
1077static inline bool
1078more_const_call_expr_args_p (const const_call_expr_arg_iterator *iter)
1079{
1080 return (iter->i < iter->n);
1081}
1082
1083/* This function validates the types of a function call argument list
1084 against a specified list of tree_codes. If the last specifier is a 0,
1085 that represents an ellipsis, otherwise the last specifier must be a
1086 VOID_TYPE. */
1087
1088static bool
1089validate_arglist (const_tree callexpr, ...)
1090{
1091 enum tree_code code;
1092 bool res = 0;
1093 va_list ap;
1094 const_call_expr_arg_iterator iter;
1095 const_tree arg;
1096
1097 va_start (ap, callexpr);
1098 init_const_call_expr_arg_iterator (exp: callexpr, iter: &iter);
1099
1100 /* Get a bitmap of pointer argument numbers declared attribute nonnull. */
1101 tree fn = CALL_EXPR_FN (callexpr);
1102 bitmap argmap = get_nonnull_args (TREE_TYPE (TREE_TYPE (fn)));
1103
1104 for (unsigned argno = 1; ; ++argno)
1105 {
1106 code = (enum tree_code) va_arg (ap, int);
1107
1108 switch (code)
1109 {
1110 case 0:
1111 /* This signifies an ellipses, any further arguments are all ok. */
1112 res = true;
1113 goto end;
1114 case VOID_TYPE:
1115 /* This signifies an endlink, if no arguments remain, return
1116 true, otherwise return false. */
1117 res = !more_const_call_expr_args_p (iter: &iter);
1118 goto end;
1119 case POINTER_TYPE:
1120 /* The actual argument must be nonnull when either the whole
1121 called function has been declared nonnull, or when the formal
1122 argument corresponding to the actual argument has been. */
1123 if (argmap
1124 && (bitmap_empty_p (map: argmap) || bitmap_bit_p (argmap, argno)))
1125 {
1126 arg = next_const_call_expr_arg (iter: &iter);
1127 if (!validate_arg (arg, code) || integer_zerop (arg))
1128 goto end;
1129 break;
1130 }
1131 /* FALLTHRU */
1132 default:
1133 /* If no parameters remain or the parameter's code does not
1134 match the specified code, return false. Otherwise continue
1135 checking any remaining arguments. */
1136 arg = next_const_call_expr_arg (iter: &iter);
1137 if (!validate_arg (arg, code))
1138 goto end;
1139 break;
1140 }
1141 }
1142
1143 /* We need gotos here since we can only have one VA_CLOSE in a
1144 function. */
1145 end: ;
1146 va_end (ap);
1147
1148 BITMAP_FREE (argmap);
1149
1150 return res;
1151}
1152
1153/* Expand a call to __builtin_nonlocal_goto. We're passed the target label
1154 and the address of the save area. */
1155
1156static rtx
1157expand_builtin_nonlocal_goto (tree exp)
1158{
1159 tree t_label, t_save_area;
1160 rtx r_label, r_save_area, r_fp, r_sp;
1161 rtx_insn *insn;
1162
1163 if (!validate_arglist (callexpr: exp, POINTER_TYPE, POINTER_TYPE, VOID_TYPE))
1164 return NULL_RTX;
1165
1166 t_label = CALL_EXPR_ARG (exp, 0);
1167 t_save_area = CALL_EXPR_ARG (exp, 1);
1168
1169 r_label = expand_normal (exp: t_label);
1170 r_label = convert_memory_address (Pmode, r_label);
1171 r_save_area = expand_normal (exp: t_save_area);
1172 r_save_area = convert_memory_address (Pmode, r_save_area);
1173 /* Copy the address of the save location to a register just in case it was
1174 based on the frame pointer. */
1175 r_save_area = copy_to_reg (r_save_area);
1176 r_fp = gen_rtx_MEM (Pmode, r_save_area);
1177 r_sp = gen_rtx_MEM (STACK_SAVEAREA_MODE (SAVE_NONLOCAL),
1178 plus_constant (Pmode, r_save_area,
1179 GET_MODE_SIZE (Pmode)));
1180
1181 crtl->has_nonlocal_goto = 1;
1182
1183 /* ??? We no longer need to pass the static chain value, afaik. */
1184 if (targetm.have_nonlocal_goto ())
1185 emit_insn (targetm.gen_nonlocal_goto (const0_rtx, r_label, r_sp, r_fp));
1186 else
1187 {
1188 emit_clobber (gen_rtx_MEM (BLKmode, gen_rtx_SCRATCH (VOIDmode)));
1189 emit_clobber (gen_rtx_MEM (BLKmode, hard_frame_pointer_rtx));
1190
1191 r_label = copy_to_reg (r_label);
1192
1193 /* Restore the frame pointer and stack pointer. We must use a
1194 temporary since the setjmp buffer may be a local. */
1195 r_fp = copy_to_reg (r_fp);
1196 emit_stack_restore (SAVE_NONLOCAL, r_sp);
1197
1198 /* Ensure the frame pointer move is not optimized. */
1199 emit_insn (gen_blockage ());
1200 emit_clobber (hard_frame_pointer_rtx);
1201 emit_clobber (frame_pointer_rtx);
1202 emit_move_insn (hard_frame_pointer_rtx, r_fp);
1203
1204 /* USE of hard_frame_pointer_rtx added for consistency;
1205 not clear if really needed. */
1206 emit_use (hard_frame_pointer_rtx);
1207 emit_use (stack_pointer_rtx);
1208
1209 /* If the architecture is using a GP register, we must
1210 conservatively assume that the target function makes use of it.
1211 The prologue of functions with nonlocal gotos must therefore
1212 initialize the GP register to the appropriate value, and we
1213 must then make sure that this value is live at the point
1214 of the jump. (Note that this doesn't necessarily apply
1215 to targets with a nonlocal_goto pattern; they are free
1216 to implement it in their own way. Note also that this is
1217 a no-op if the GP register is a global invariant.) */
1218 unsigned regnum = PIC_OFFSET_TABLE_REGNUM;
1219 if (regnum != INVALID_REGNUM && fixed_regs[regnum])
1220 emit_use (pic_offset_table_rtx);
1221
1222 emit_indirect_jump (r_label);
1223 }
1224
1225 /* Search backwards to the jump insn and mark it as a
1226 non-local goto. */
1227 for (insn = get_last_insn (); insn; insn = PREV_INSN (insn))
1228 {
1229 if (JUMP_P (insn))
1230 {
1231 add_reg_note (insn, REG_NON_LOCAL_GOTO, const0_rtx);
1232 break;
1233 }
1234 else if (CALL_P (insn))
1235 break;
1236 }
1237
1238 return const0_rtx;
1239}
1240
1241/* __builtin_update_setjmp_buf is passed a pointer to an array of five words
1242 (not all will be used on all machines) that was passed to __builtin_setjmp.
1243 It updates the stack pointer in that block to the current value. This is
1244 also called directly by the SJLJ exception handling code. */
1245
1246void
1247expand_builtin_update_setjmp_buf (rtx buf_addr)
1248{
1249 machine_mode sa_mode = STACK_SAVEAREA_MODE (SAVE_NONLOCAL);
1250 buf_addr = convert_memory_address (Pmode, buf_addr);
1251 rtx stack_save
1252 = gen_rtx_MEM (sa_mode,
1253 memory_address
1254 (sa_mode,
1255 plus_constant (Pmode, buf_addr,
1256 2 * GET_MODE_SIZE (Pmode))));
1257
1258 emit_stack_save (SAVE_NONLOCAL, &stack_save);
1259}
1260
1261/* Expand a call to __builtin_prefetch. For a target that does not support
1262 data prefetch, evaluate the memory address argument in case it has side
1263 effects. */
1264
1265static void
1266expand_builtin_prefetch (tree exp)
1267{
1268 tree arg0, arg1, arg2;
1269 int nargs;
1270 rtx op0, op1, op2;
1271
1272 if (!validate_arglist (callexpr: exp, POINTER_TYPE, 0))
1273 return;
1274
1275 arg0 = CALL_EXPR_ARG (exp, 0);
1276
1277 /* Arguments 1 and 2 are optional; argument 1 (read/write) defaults to
1278 zero (read) and argument 2 (locality) defaults to 3 (high degree of
1279 locality). */
1280 nargs = call_expr_nargs (exp);
1281 if (nargs > 1)
1282 arg1 = CALL_EXPR_ARG (exp, 1);
1283 else
1284 arg1 = integer_zero_node;
1285 if (nargs > 2)
1286 arg2 = CALL_EXPR_ARG (exp, 2);
1287 else
1288 arg2 = integer_three_node;
1289
1290 /* Argument 0 is an address. */
1291 op0 = expand_expr (exp: arg0, NULL_RTX, Pmode, modifier: EXPAND_NORMAL);
1292
1293 /* Argument 1 (read/write flag) must be a compile-time constant int. */
1294 if (TREE_CODE (arg1) != INTEGER_CST)
1295 {
1296 error ("second argument to %<__builtin_prefetch%> must be a constant");
1297 arg1 = integer_zero_node;
1298 }
1299 op1 = expand_normal (exp: arg1);
1300 /* Argument 1 must be either zero or one. */
1301 if (INTVAL (op1) != 0 && INTVAL (op1) != 1)
1302 {
1303 warning (0, "invalid second argument to %<__builtin_prefetch%>;"
1304 " using zero");
1305 op1 = const0_rtx;
1306 }
1307
1308 /* Argument 2 (locality) must be a compile-time constant int. */
1309 if (TREE_CODE (arg2) != INTEGER_CST)
1310 {
1311 error ("third argument to %<__builtin_prefetch%> must be a constant");
1312 arg2 = integer_zero_node;
1313 }
1314 op2 = expand_normal (exp: arg2);
1315 /* Argument 2 must be 0, 1, 2, or 3. */
1316 if (INTVAL (op2) < 0 || INTVAL (op2) > 3)
1317 {
1318 warning (0, "invalid third argument to %<__builtin_prefetch%>; using zero");
1319 op2 = const0_rtx;
1320 }
1321
1322 if (targetm.have_prefetch ())
1323 {
1324 class expand_operand ops[3];
1325
1326 create_address_operand (op: &ops[0], value: op0);
1327 create_integer_operand (&ops[1], INTVAL (op1));
1328 create_integer_operand (&ops[2], INTVAL (op2));
1329 if (maybe_expand_insn (icode: targetm.code_for_prefetch, nops: 3, ops))
1330 return;
1331 }
1332
1333 /* Don't do anything with direct references to volatile memory, but
1334 generate code to handle other side effects. */
1335 if (!MEM_P (op0) && side_effects_p (op0))
1336 emit_insn (op0);
1337}
1338
1339/* Get a MEM rtx for expression EXP which is the address of an operand
1340 to be used in a string instruction (cmpstrsi, cpymemsi, ..). LEN is
1341 the maximum length of the block of memory that might be accessed or
1342 NULL if unknown. */
1343
1344rtx
1345get_memory_rtx (tree exp, tree len)
1346{
1347 tree orig_exp = exp, base;
1348 rtx addr, mem;
1349
1350 /* When EXP is not resolved SAVE_EXPR, MEM_ATTRS can be still derived
1351 from its expression, for expr->a.b only <variable>.a.b is recorded. */
1352 if (TREE_CODE (exp) == SAVE_EXPR && !SAVE_EXPR_RESOLVED_P (exp))
1353 exp = TREE_OPERAND (exp, 0);
1354
1355 addr = expand_expr (exp: orig_exp, NULL_RTX, mode: ptr_mode, modifier: EXPAND_NORMAL);
1356 mem = gen_rtx_MEM (BLKmode, memory_address (BLKmode, addr));
1357
1358 /* Get an expression we can use to find the attributes to assign to MEM.
1359 First remove any nops. */
1360 while (CONVERT_EXPR_P (exp)
1361 && POINTER_TYPE_P (TREE_TYPE (TREE_OPERAND (exp, 0))))
1362 exp = TREE_OPERAND (exp, 0);
1363
1364 /* Build a MEM_REF representing the whole accessed area as a byte blob,
1365 (as builtin stringops may alias with anything). */
1366 exp = fold_build2 (MEM_REF,
1367 build_array_type (char_type_node,
1368 build_range_type (sizetype,
1369 size_one_node, len)),
1370 exp, build_int_cst (ptr_type_node, 0));
1371
1372 /* If the MEM_REF has no acceptable address, try to get the base object
1373 from the original address we got, and build an all-aliasing
1374 unknown-sized access to that one. */
1375 if (is_gimple_mem_ref_addr (TREE_OPERAND (exp, 0)))
1376 set_mem_attributes (mem, exp, 0);
1377 else if (TREE_CODE (TREE_OPERAND (exp, 0)) == ADDR_EXPR
1378 && (base = get_base_address (TREE_OPERAND (TREE_OPERAND (exp, 0),
1379 0))))
1380 {
1381 unsigned int align = get_pointer_alignment (TREE_OPERAND (exp, 0));
1382 exp = build_fold_addr_expr (base);
1383 exp = fold_build2 (MEM_REF,
1384 build_array_type (char_type_node,
1385 build_range_type (sizetype,
1386 size_zero_node,
1387 NULL)),
1388 exp, build_int_cst (ptr_type_node, 0));
1389 set_mem_attributes (mem, exp, 0);
1390 /* Since we stripped parts make sure the offset is unknown and the
1391 alignment is computed from the original address. */
1392 clear_mem_offset (mem);
1393 set_mem_align (mem, align);
1394 }
1395 set_mem_alias_set (mem, 0);
1396 return mem;
1397}
1398
1399/* Built-in functions to perform an untyped call and return. */
1400
1401#define apply_args_mode \
1402 (this_target_builtins->x_apply_args_mode)
1403#define apply_result_mode \
1404 (this_target_builtins->x_apply_result_mode)
1405
1406/* Return the size required for the block returned by __builtin_apply_args,
1407 and initialize apply_args_mode. */
1408
1409static int
1410apply_args_size (void)
1411{
1412 static int size = -1;
1413 int align;
1414 unsigned int regno;
1415
1416 /* The values computed by this function never change. */
1417 if (size < 0)
1418 {
1419 /* The first value is the incoming arg-pointer. */
1420 size = GET_MODE_SIZE (Pmode);
1421
1422 /* The second value is the structure value address unless this is
1423 passed as an "invisible" first argument. */
1424 if (targetm.calls.struct_value_rtx (cfun ? TREE_TYPE (cfun->decl) : 0, 0))
1425 size += GET_MODE_SIZE (Pmode);
1426
1427 for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
1428 if (FUNCTION_ARG_REGNO_P (regno))
1429 {
1430 fixed_size_mode mode = targetm.calls.get_raw_arg_mode (regno);
1431
1432 if (mode != VOIDmode)
1433 {
1434 align = GET_MODE_ALIGNMENT (mode) / BITS_PER_UNIT;
1435 if (size % align != 0)
1436 size = CEIL (size, align) * align;
1437 size += GET_MODE_SIZE (mode);
1438 apply_args_mode[regno] = mode;
1439 }
1440 else
1441 apply_args_mode[regno] = as_a <fixed_size_mode> (VOIDmode);
1442 }
1443 else
1444 apply_args_mode[regno] = as_a <fixed_size_mode> (VOIDmode);
1445 }
1446 return size;
1447}
1448
1449/* Return the size required for the block returned by __builtin_apply,
1450 and initialize apply_result_mode. */
1451
1452static int
1453apply_result_size (void)
1454{
1455 static int size = -1;
1456 int align, regno;
1457
1458 /* The values computed by this function never change. */
1459 if (size < 0)
1460 {
1461 size = 0;
1462
1463 for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
1464 if (targetm.calls.function_value_regno_p (regno))
1465 {
1466 fixed_size_mode mode = targetm.calls.get_raw_result_mode (regno);
1467
1468 if (mode != VOIDmode)
1469 {
1470 align = GET_MODE_ALIGNMENT (mode) / BITS_PER_UNIT;
1471 if (size % align != 0)
1472 size = CEIL (size, align) * align;
1473 size += GET_MODE_SIZE (mode);
1474 apply_result_mode[regno] = mode;
1475 }
1476 else
1477 apply_result_mode[regno] = as_a <fixed_size_mode> (VOIDmode);
1478 }
1479 else
1480 apply_result_mode[regno] = as_a <fixed_size_mode> (VOIDmode);
1481
1482 /* Allow targets that use untyped_call and untyped_return to override
1483 the size so that machine-specific information can be stored here. */
1484#ifdef APPLY_RESULT_SIZE
1485 size = APPLY_RESULT_SIZE;
1486#endif
1487 }
1488 return size;
1489}
1490
1491/* Create a vector describing the result block RESULT. If SAVEP is true,
1492 the result block is used to save the values; otherwise it is used to
1493 restore the values. */
1494
1495static rtx
1496result_vector (int savep, rtx result)
1497{
1498 int regno, size, align, nelts;
1499 fixed_size_mode mode;
1500 rtx reg, mem;
1501 rtx *savevec = XALLOCAVEC (rtx, FIRST_PSEUDO_REGISTER);
1502
1503 size = nelts = 0;
1504 for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
1505 if ((mode = apply_result_mode[regno]) != VOIDmode)
1506 {
1507 align = GET_MODE_ALIGNMENT (mode) / BITS_PER_UNIT;
1508 if (size % align != 0)
1509 size = CEIL (size, align) * align;
1510 reg = gen_rtx_REG (mode, savep ? regno : INCOMING_REGNO (regno));
1511 mem = adjust_address (result, mode, size);
1512 savevec[nelts++] = (savep
1513 ? gen_rtx_SET (mem, reg)
1514 : gen_rtx_SET (reg, mem));
1515 size += GET_MODE_SIZE (mode);
1516 }
1517 return gen_rtx_PARALLEL (VOIDmode, gen_rtvec_v (nelts, savevec));
1518}
1519
1520/* Save the state required to perform an untyped call with the same
1521 arguments as were passed to the current function. */
1522
1523static rtx
1524expand_builtin_apply_args_1 (void)
1525{
1526 rtx registers, tem;
1527 int size, align, regno;
1528 fixed_size_mode mode;
1529 rtx struct_incoming_value = targetm.calls.struct_value_rtx (cfun ? TREE_TYPE (cfun->decl) : 0, 1);
1530
1531 /* Create a block where the arg-pointer, structure value address,
1532 and argument registers can be saved. */
1533 registers = assign_stack_local (BLKmode, apply_args_size (), -1);
1534
1535 /* Walk past the arg-pointer and structure value address. */
1536 size = GET_MODE_SIZE (Pmode);
1537 if (targetm.calls.struct_value_rtx (cfun ? TREE_TYPE (cfun->decl) : 0, 0))
1538 size += GET_MODE_SIZE (Pmode);
1539
1540 /* Save each register used in calling a function to the block. */
1541 for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
1542 if ((mode = apply_args_mode[regno]) != VOIDmode)
1543 {
1544 align = GET_MODE_ALIGNMENT (mode) / BITS_PER_UNIT;
1545 if (size % align != 0)
1546 size = CEIL (size, align) * align;
1547
1548 tem = gen_rtx_REG (mode, INCOMING_REGNO (regno));
1549
1550 emit_move_insn (adjust_address (registers, mode, size), tem);
1551 size += GET_MODE_SIZE (mode);
1552 }
1553
1554 /* Save the arg pointer to the block. */
1555 tem = copy_to_reg (crtl->args.internal_arg_pointer);
1556 /* We need the pointer as the caller actually passed them to us, not
1557 as we might have pretended they were passed. Make sure it's a valid
1558 operand, as emit_move_insn isn't expected to handle a PLUS. */
1559 if (STACK_GROWS_DOWNWARD)
1560 tem
1561 = force_operand (plus_constant (Pmode, tem,
1562 crtl->args.pretend_args_size),
1563 NULL_RTX);
1564 emit_move_insn (adjust_address (registers, Pmode, 0), tem);
1565
1566 size = GET_MODE_SIZE (Pmode);
1567
1568 /* Save the structure value address unless this is passed as an
1569 "invisible" first argument. */
1570 if (struct_incoming_value)
1571 emit_move_insn (adjust_address (registers, Pmode, size),
1572 copy_to_reg (struct_incoming_value));
1573
1574 /* Return the address of the block. */
1575 return copy_addr_to_reg (XEXP (registers, 0));
1576}
1577
1578/* __builtin_apply_args returns block of memory allocated on
1579 the stack into which is stored the arg pointer, structure
1580 value address, static chain, and all the registers that might
1581 possibly be used in performing a function call. The code is
1582 moved to the start of the function so the incoming values are
1583 saved. */
1584
1585static rtx
1586expand_builtin_apply_args (void)
1587{
1588 /* Don't do __builtin_apply_args more than once in a function.
1589 Save the result of the first call and reuse it. */
1590 if (apply_args_value != 0)
1591 return apply_args_value;
1592 {
1593 /* When this function is called, it means that registers must be
1594 saved on entry to this function. So we migrate the
1595 call to the first insn of this function. */
1596 rtx temp;
1597
1598 start_sequence ();
1599 temp = expand_builtin_apply_args_1 ();
1600 rtx_insn *seq = get_insns ();
1601 end_sequence ();
1602
1603 apply_args_value = temp;
1604
1605 /* Put the insns after the NOTE that starts the function.
1606 If this is inside a start_sequence, make the outer-level insn
1607 chain current, so the code is placed at the start of the
1608 function. If internal_arg_pointer is a non-virtual pseudo,
1609 it needs to be placed after the function that initializes
1610 that pseudo. */
1611 push_topmost_sequence ();
1612 if (REG_P (crtl->args.internal_arg_pointer)
1613 && REGNO (crtl->args.internal_arg_pointer) > LAST_VIRTUAL_REGISTER)
1614 emit_insn_before (seq, parm_birth_insn);
1615 else
1616 emit_insn_before (seq, NEXT_INSN (insn: entry_of_function ()));
1617 pop_topmost_sequence ();
1618 return temp;
1619 }
1620}
1621
1622/* Perform an untyped call and save the state required to perform an
1623 untyped return of whatever value was returned by the given function. */
1624
1625static rtx
1626expand_builtin_apply (rtx function, rtx arguments, rtx argsize)
1627{
1628 int size, align, regno;
1629 fixed_size_mode mode;
1630 rtx incoming_args, result, reg, dest, src;
1631 rtx_call_insn *call_insn;
1632 rtx old_stack_level = 0;
1633 rtx call_fusage = 0;
1634 rtx struct_value = targetm.calls.struct_value_rtx (cfun ? TREE_TYPE (cfun->decl) : 0, 0);
1635
1636 arguments = convert_memory_address (Pmode, arguments);
1637
1638 /* Create a block where the return registers can be saved. */
1639 result = assign_stack_local (BLKmode, apply_result_size (), -1);
1640
1641 /* Fetch the arg pointer from the ARGUMENTS block. */
1642 incoming_args = gen_reg_rtx (Pmode);
1643 emit_move_insn (incoming_args, gen_rtx_MEM (Pmode, arguments));
1644 if (!STACK_GROWS_DOWNWARD)
1645 incoming_args = expand_simple_binop (Pmode, MINUS, incoming_args, argsize,
1646 incoming_args, 0, OPTAB_LIB_WIDEN);
1647
1648 /* Push a new argument block and copy the arguments. Do not allow
1649 the (potential) memcpy call below to interfere with our stack
1650 manipulations. */
1651 do_pending_stack_adjust ();
1652 NO_DEFER_POP;
1653
1654 /* Save the stack with nonlocal if available. */
1655 if (targetm.have_save_stack_nonlocal ())
1656 emit_stack_save (SAVE_NONLOCAL, &old_stack_level);
1657 else
1658 emit_stack_save (SAVE_BLOCK, &old_stack_level);
1659
1660 /* Allocate a block of memory onto the stack and copy the memory
1661 arguments to the outgoing arguments address. We can pass TRUE
1662 as the 4th argument because we just saved the stack pointer
1663 and will restore it right after the call. */
1664 allocate_dynamic_stack_space (argsize, 0, BIGGEST_ALIGNMENT, -1, true);
1665
1666 /* Set DRAP flag to true, even though allocate_dynamic_stack_space
1667 may have already set current_function_calls_alloca to true.
1668 current_function_calls_alloca won't be set if argsize is zero,
1669 so we have to guarantee need_drap is true here. */
1670 if (SUPPORTS_STACK_ALIGNMENT)
1671 crtl->need_drap = true;
1672
1673 dest = virtual_outgoing_args_rtx;
1674 if (!STACK_GROWS_DOWNWARD)
1675 {
1676 if (CONST_INT_P (argsize))
1677 dest = plus_constant (Pmode, dest, -INTVAL (argsize));
1678 else
1679 dest = gen_rtx_PLUS (Pmode, dest, negate_rtx (Pmode, argsize));
1680 }
1681 dest = gen_rtx_MEM (BLKmode, dest);
1682 set_mem_align (dest, PARM_BOUNDARY);
1683 src = gen_rtx_MEM (BLKmode, incoming_args);
1684 set_mem_align (src, PARM_BOUNDARY);
1685 emit_block_move (dest, src, argsize, BLOCK_OP_NORMAL);
1686
1687 /* Refer to the argument block. */
1688 apply_args_size ();
1689 arguments = gen_rtx_MEM (BLKmode, arguments);
1690 set_mem_align (arguments, PARM_BOUNDARY);
1691
1692 /* Walk past the arg-pointer and structure value address. */
1693 size = GET_MODE_SIZE (Pmode);
1694 if (struct_value)
1695 size += GET_MODE_SIZE (Pmode);
1696
1697 /* Restore each of the registers previously saved. Make USE insns
1698 for each of these registers for use in making the call. */
1699 for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
1700 if ((mode = apply_args_mode[regno]) != VOIDmode)
1701 {
1702 align = GET_MODE_ALIGNMENT (mode) / BITS_PER_UNIT;
1703 if (size % align != 0)
1704 size = CEIL (size, align) * align;
1705 reg = gen_rtx_REG (mode, regno);
1706 emit_move_insn (reg, adjust_address (arguments, mode, size));
1707 use_reg (fusage: &call_fusage, reg);
1708 size += GET_MODE_SIZE (mode);
1709 }
1710
1711 /* Restore the structure value address unless this is passed as an
1712 "invisible" first argument. */
1713 size = GET_MODE_SIZE (Pmode);
1714 if (struct_value)
1715 {
1716 rtx value = gen_reg_rtx (Pmode);
1717 emit_move_insn (value, adjust_address (arguments, Pmode, size));
1718 emit_move_insn (struct_value, value);
1719 if (REG_P (struct_value))
1720 use_reg (fusage: &call_fusage, reg: struct_value);
1721 }
1722
1723 /* All arguments and registers used for the call are set up by now! */
1724 function = prepare_call_address (NULL, function, NULL, &call_fusage, 0, 0);
1725
1726 /* Ensure address is valid. SYMBOL_REF is already valid, so no need,
1727 and we don't want to load it into a register as an optimization,
1728 because prepare_call_address already did it if it should be done. */
1729 if (GET_CODE (function) != SYMBOL_REF)
1730 function = memory_address (FUNCTION_MODE, function);
1731
1732 /* Generate the actual call instruction and save the return value. */
1733 if (targetm.have_untyped_call ())
1734 {
1735 rtx mem = gen_rtx_MEM (FUNCTION_MODE, function);
1736 rtx_insn *seq = targetm.gen_untyped_call (mem, result,
1737 result_vector (savep: 1, result));
1738 for (rtx_insn *insn = seq; insn; insn = NEXT_INSN (insn))
1739 if (CALL_P (insn))
1740 add_reg_note (insn, REG_UNTYPED_CALL, NULL_RTX);
1741 emit_insn (seq);
1742 }
1743 else if (targetm.have_call_value ())
1744 {
1745 rtx valreg = 0;
1746
1747 /* Locate the unique return register. It is not possible to
1748 express a call that sets more than one return register using
1749 call_value; use untyped_call for that. In fact, untyped_call
1750 only needs to save the return registers in the given block. */
1751 for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
1752 if ((mode = apply_result_mode[regno]) != VOIDmode)
1753 {
1754 gcc_assert (!valreg); /* have_untyped_call required. */
1755
1756 valreg = gen_rtx_REG (mode, regno);
1757 }
1758
1759 emit_insn (targetm.gen_call_value (valreg,
1760 gen_rtx_MEM (FUNCTION_MODE, function),
1761 const0_rtx, NULL_RTX, const0_rtx));
1762
1763 emit_move_insn (adjust_address (result, GET_MODE (valreg), 0), valreg);
1764 }
1765 else
1766 gcc_unreachable ();
1767
1768 /* Find the CALL insn we just emitted, and attach the register usage
1769 information. */
1770 call_insn = last_call_insn ();
1771 add_function_usage_to (call_insn, call_fusage);
1772
1773 /* Restore the stack. */
1774 if (targetm.have_save_stack_nonlocal ())
1775 emit_stack_restore (SAVE_NONLOCAL, old_stack_level);
1776 else
1777 emit_stack_restore (SAVE_BLOCK, old_stack_level);
1778 fixup_args_size_notes (call_insn, get_last_insn (), 0);
1779
1780 OK_DEFER_POP;
1781
1782 /* Return the address of the result block. */
1783 result = copy_addr_to_reg (XEXP (result, 0));
1784 return convert_memory_address (ptr_mode, result);
1785}
1786
1787/* Perform an untyped return. */
1788
1789static void
1790expand_builtin_return (rtx result)
1791{
1792 int size, align, regno;
1793 fixed_size_mode mode;
1794 rtx reg;
1795 rtx_insn *call_fusage = 0;
1796
1797 result = convert_memory_address (Pmode, result);
1798
1799 apply_result_size ();
1800 result = gen_rtx_MEM (BLKmode, result);
1801
1802 if (targetm.have_untyped_return ())
1803 {
1804 rtx vector = result_vector (savep: 0, result);
1805 emit_jump_insn (targetm.gen_untyped_return (result, vector));
1806 emit_barrier ();
1807 return;
1808 }
1809
1810 /* Restore the return value and note that each value is used. */
1811 size = 0;
1812 for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
1813 if ((mode = apply_result_mode[regno]) != VOIDmode)
1814 {
1815 align = GET_MODE_ALIGNMENT (mode) / BITS_PER_UNIT;
1816 if (size % align != 0)
1817 size = CEIL (size, align) * align;
1818 reg = gen_rtx_REG (mode, INCOMING_REGNO (regno));
1819 emit_move_insn (reg, adjust_address (result, mode, size));
1820
1821 push_to_sequence (call_fusage);
1822 emit_use (reg);
1823 call_fusage = get_insns ();
1824 end_sequence ();
1825 size += GET_MODE_SIZE (mode);
1826 }
1827
1828 /* Put the USE insns before the return. */
1829 emit_insn (call_fusage);
1830
1831 /* Return whatever values was restored by jumping directly to the end
1832 of the function. */
1833 expand_naked_return ();
1834}
1835
1836/* Used by expand_builtin_classify_type and fold_builtin_classify_type. */
1837
1838int
1839type_to_class (tree type)
1840{
1841 switch (TREE_CODE (type))
1842 {
1843 case VOID_TYPE: return void_type_class;
1844 case INTEGER_TYPE: return integer_type_class;
1845 case ENUMERAL_TYPE: return enumeral_type_class;
1846 case BOOLEAN_TYPE: return boolean_type_class;
1847 case POINTER_TYPE: return pointer_type_class;
1848 case REFERENCE_TYPE: return reference_type_class;
1849 case OFFSET_TYPE: return offset_type_class;
1850 case REAL_TYPE: return real_type_class;
1851 case COMPLEX_TYPE: return complex_type_class;
1852 case FUNCTION_TYPE: return function_type_class;
1853 case METHOD_TYPE: return method_type_class;
1854 case RECORD_TYPE: return record_type_class;
1855 case UNION_TYPE:
1856 case QUAL_UNION_TYPE: return union_type_class;
1857 case ARRAY_TYPE: return (TYPE_STRING_FLAG (type)
1858 ? string_type_class : array_type_class);
1859 case LANG_TYPE: return lang_type_class;
1860 case OPAQUE_TYPE: return opaque_type_class;
1861 case BITINT_TYPE: return bitint_type_class;
1862 default: return no_type_class;
1863 }
1864}
1865
1866/* Expand a call EXP to __builtin_classify_type. */
1867
1868static rtx
1869expand_builtin_classify_type (tree exp)
1870{
1871 if (call_expr_nargs (exp))
1872 return GEN_INT (type_to_class (TREE_TYPE (CALL_EXPR_ARG (exp, 0))));
1873 return GEN_INT (no_type_class);
1874}
1875
1876/* This helper macro, meant to be used in mathfn_built_in below, determines
1877 which among a set of builtin math functions is appropriate for a given type
1878 mode. The `F' (float) and `L' (long double) are automatically generated
1879 from the 'double' case. If a function supports the _Float<N> and _Float<N>X
1880 types, there are additional types that are considered with 'F32', 'F64',
1881 'F128', etc. suffixes. */
1882#define CASE_MATHFN(MATHFN) \
1883 CASE_CFN_##MATHFN: \
1884 fcode = BUILT_IN_##MATHFN; fcodef = BUILT_IN_##MATHFN##F ; \
1885 fcodel = BUILT_IN_##MATHFN##L ; break;
1886/* Similar to the above, but also add support for the _Float<N> and _Float<N>X
1887 types. */
1888#define CASE_MATHFN_FLOATN(MATHFN) \
1889 CASE_CFN_##MATHFN: \
1890 fcode = BUILT_IN_##MATHFN; fcodef = BUILT_IN_##MATHFN##F ; \
1891 fcodel = BUILT_IN_##MATHFN##L ; fcodef16 = BUILT_IN_##MATHFN##F16 ; \
1892 fcodef32 = BUILT_IN_##MATHFN##F32; fcodef64 = BUILT_IN_##MATHFN##F64 ; \
1893 fcodef128 = BUILT_IN_##MATHFN##F128 ; fcodef32x = BUILT_IN_##MATHFN##F32X ; \
1894 fcodef64x = BUILT_IN_##MATHFN##F64X ; fcodef128x = BUILT_IN_##MATHFN##F128X ;\
1895 break;
1896/* Similar to above, but appends _R after any F/L suffix. */
1897#define CASE_MATHFN_REENT(MATHFN) \
1898 case CFN_BUILT_IN_##MATHFN##_R: \
1899 case CFN_BUILT_IN_##MATHFN##F_R: \
1900 case CFN_BUILT_IN_##MATHFN##L_R: \
1901 fcode = BUILT_IN_##MATHFN##_R; fcodef = BUILT_IN_##MATHFN##F_R ; \
1902 fcodel = BUILT_IN_##MATHFN##L_R ; break;
1903
1904/* Return a function equivalent to FN but operating on floating-point
1905 values of type TYPE, or END_BUILTINS if no such function exists.
1906 This is purely an operation on function codes; it does not guarantee
1907 that the target actually has an implementation of the function. */
1908
1909static built_in_function
1910mathfn_built_in_2 (tree type, combined_fn fn)
1911{
1912 tree mtype;
1913 built_in_function fcode, fcodef, fcodel;
1914 built_in_function fcodef16 = END_BUILTINS;
1915 built_in_function fcodef32 = END_BUILTINS;
1916 built_in_function fcodef64 = END_BUILTINS;
1917 built_in_function fcodef128 = END_BUILTINS;
1918 built_in_function fcodef32x = END_BUILTINS;
1919 built_in_function fcodef64x = END_BUILTINS;
1920 built_in_function fcodef128x = END_BUILTINS;
1921
1922 /* If <math.h> has been included somehow, HUGE_VAL and NAN definitions
1923 break the uses below. */
1924#undef HUGE_VAL
1925#undef NAN
1926
1927 switch (fn)
1928 {
1929#define SEQ_OF_CASE_MATHFN \
1930 CASE_MATHFN_FLOATN (ACOS) \
1931 CASE_MATHFN_FLOATN (ACOSH) \
1932 CASE_MATHFN_FLOATN (ASIN) \
1933 CASE_MATHFN_FLOATN (ASINH) \
1934 CASE_MATHFN_FLOATN (ATAN) \
1935 CASE_MATHFN_FLOATN (ATAN2) \
1936 CASE_MATHFN_FLOATN (ATANH) \
1937 CASE_MATHFN_FLOATN (CBRT) \
1938 CASE_MATHFN_FLOATN (CEIL) \
1939 CASE_MATHFN (CEXPI) \
1940 CASE_MATHFN_FLOATN (COPYSIGN) \
1941 CASE_MATHFN_FLOATN (COS) \
1942 CASE_MATHFN_FLOATN (COSH) \
1943 CASE_MATHFN (DREM) \
1944 CASE_MATHFN_FLOATN (ERF) \
1945 CASE_MATHFN_FLOATN (ERFC) \
1946 CASE_MATHFN_FLOATN (EXP) \
1947 CASE_MATHFN (EXP10) \
1948 CASE_MATHFN_FLOATN (EXP2) \
1949 CASE_MATHFN_FLOATN (EXPM1) \
1950 CASE_MATHFN_FLOATN (FABS) \
1951 CASE_MATHFN_FLOATN (FDIM) \
1952 CASE_MATHFN_FLOATN (FLOOR) \
1953 CASE_MATHFN_FLOATN (FMA) \
1954 CASE_MATHFN_FLOATN (FMAX) \
1955 CASE_MATHFN_FLOATN (FMIN) \
1956 CASE_MATHFN_FLOATN (FMOD) \
1957 CASE_MATHFN_FLOATN (FREXP) \
1958 CASE_MATHFN (GAMMA) \
1959 CASE_MATHFN_REENT (GAMMA) /* GAMMA_R */ \
1960 CASE_MATHFN_FLOATN (HUGE_VAL) \
1961 CASE_MATHFN_FLOATN (HYPOT) \
1962 CASE_MATHFN_FLOATN (ILOGB) \
1963 CASE_MATHFN (ICEIL) \
1964 CASE_MATHFN (IFLOOR) \
1965 CASE_MATHFN_FLOATN (INF) \
1966 CASE_MATHFN (IRINT) \
1967 CASE_MATHFN (IROUND) \
1968 CASE_MATHFN (ISINF) \
1969 CASE_MATHFN (J0) \
1970 CASE_MATHFN (J1) \
1971 CASE_MATHFN (JN) \
1972 CASE_MATHFN (LCEIL) \
1973 CASE_MATHFN_FLOATN (LDEXP) \
1974 CASE_MATHFN (LFLOOR) \
1975 CASE_MATHFN_FLOATN (LGAMMA) \
1976 CASE_MATHFN_REENT (LGAMMA) /* LGAMMA_R */ \
1977 CASE_MATHFN (LLCEIL) \
1978 CASE_MATHFN (LLFLOOR) \
1979 CASE_MATHFN_FLOATN (LLRINT) \
1980 CASE_MATHFN_FLOATN (LLROUND) \
1981 CASE_MATHFN_FLOATN (LOG) \
1982 CASE_MATHFN_FLOATN (LOG10) \
1983 CASE_MATHFN_FLOATN (LOG1P) \
1984 CASE_MATHFN_FLOATN (LOG2) \
1985 CASE_MATHFN_FLOATN (LOGB) \
1986 CASE_MATHFN_FLOATN (LRINT) \
1987 CASE_MATHFN_FLOATN (LROUND) \
1988 CASE_MATHFN_FLOATN (MODF) \
1989 CASE_MATHFN_FLOATN (NAN) \
1990 CASE_MATHFN_FLOATN (NANS) \
1991 CASE_MATHFN_FLOATN (NEARBYINT) \
1992 CASE_MATHFN_FLOATN (NEXTAFTER) \
1993 CASE_MATHFN (NEXTTOWARD) \
1994 CASE_MATHFN_FLOATN (POW) \
1995 CASE_MATHFN (POWI) \
1996 CASE_MATHFN (POW10) \
1997 CASE_MATHFN_FLOATN (REMAINDER) \
1998 CASE_MATHFN_FLOATN (REMQUO) \
1999 CASE_MATHFN_FLOATN (RINT) \
2000 CASE_MATHFN_FLOATN (ROUND) \
2001 CASE_MATHFN_FLOATN (ROUNDEVEN) \
2002 CASE_MATHFN (SCALB) \
2003 CASE_MATHFN_FLOATN (SCALBLN) \
2004 CASE_MATHFN_FLOATN (SCALBN) \
2005 CASE_MATHFN (SIGNBIT) \
2006 CASE_MATHFN (SIGNIFICAND) \
2007 CASE_MATHFN_FLOATN (SIN) \
2008 CASE_MATHFN (SINCOS) \
2009 CASE_MATHFN_FLOATN (SINH) \
2010 CASE_MATHFN_FLOATN (SQRT) \
2011 CASE_MATHFN_FLOATN (TAN) \
2012 CASE_MATHFN_FLOATN (TANH) \
2013 CASE_MATHFN_FLOATN (TGAMMA) \
2014 CASE_MATHFN_FLOATN (TRUNC) \
2015 CASE_MATHFN (Y0) \
2016 CASE_MATHFN (Y1) \
2017 CASE_MATHFN (YN)
2018
2019 SEQ_OF_CASE_MATHFN
2020
2021 default:
2022 return END_BUILTINS;
2023 }
2024
2025 mtype = TYPE_MAIN_VARIANT (type);
2026 if (mtype == double_type_node)
2027 return fcode;
2028 else if (mtype == float_type_node)
2029 return fcodef;
2030 else if (mtype == long_double_type_node)
2031 return fcodel;
2032 else if (mtype == float16_type_node)
2033 return fcodef16;
2034 else if (mtype == float32_type_node)
2035 return fcodef32;
2036 else if (mtype == float64_type_node)
2037 return fcodef64;
2038 else if (mtype == float128_type_node)
2039 return fcodef128;
2040 else if (mtype == float32x_type_node)
2041 return fcodef32x;
2042 else if (mtype == float64x_type_node)
2043 return fcodef64x;
2044 else if (mtype == float128x_type_node)
2045 return fcodef128x;
2046 else
2047 return END_BUILTINS;
2048}
2049
2050#undef CASE_MATHFN
2051#undef CASE_MATHFN_FLOATN
2052#undef CASE_MATHFN_REENT
2053
2054/* Return mathematic function equivalent to FN but operating directly on TYPE,
2055 if available. If IMPLICIT_P is true use the implicit builtin declaration,
2056 otherwise use the explicit declaration. If we can't do the conversion,
2057 return null. */
2058
2059static tree
2060mathfn_built_in_1 (tree type, combined_fn fn, bool implicit_p)
2061{
2062 built_in_function fcode2 = mathfn_built_in_2 (type, fn);
2063 if (fcode2 == END_BUILTINS)
2064 return NULL_TREE;
2065
2066 if (implicit_p && !builtin_decl_implicit_p (fncode: fcode2))
2067 return NULL_TREE;
2068
2069 return builtin_decl_explicit (fncode: fcode2);
2070}
2071
2072/* Like mathfn_built_in_1, but always use the implicit array. */
2073
2074tree
2075mathfn_built_in (tree type, combined_fn fn)
2076{
2077 return mathfn_built_in_1 (type, fn, /*implicit=*/ implicit_p: 1);
2078}
2079
2080/* Like mathfn_built_in_1, but always use the explicit array. */
2081
2082tree
2083mathfn_built_in_explicit (tree type, combined_fn fn)
2084{
2085 return mathfn_built_in_1 (type, fn, /*implicit=*/ implicit_p: 0);
2086}
2087
2088/* Like mathfn_built_in_1, but take a built_in_function and
2089 always use the implicit array. */
2090
2091tree
2092mathfn_built_in (tree type, enum built_in_function fn)
2093{
2094 return mathfn_built_in_1 (type, fn: as_combined_fn (fn), /*implicit=*/ implicit_p: 1);
2095}
2096
2097/* Return the type associated with a built in function, i.e., the one
2098 to be passed to mathfn_built_in to get the type-specific
2099 function. */
2100
2101tree
2102mathfn_built_in_type (combined_fn fn)
2103{
2104#define CASE_MATHFN(MATHFN) \
2105 case CFN_BUILT_IN_##MATHFN: \
2106 return double_type_node; \
2107 case CFN_BUILT_IN_##MATHFN##F: \
2108 return float_type_node; \
2109 case CFN_BUILT_IN_##MATHFN##L: \
2110 return long_double_type_node;
2111
2112#define CASE_MATHFN_FLOATN(MATHFN) \
2113 CASE_MATHFN(MATHFN) \
2114 case CFN_BUILT_IN_##MATHFN##F16: \
2115 return float16_type_node; \
2116 case CFN_BUILT_IN_##MATHFN##F32: \
2117 return float32_type_node; \
2118 case CFN_BUILT_IN_##MATHFN##F64: \
2119 return float64_type_node; \
2120 case CFN_BUILT_IN_##MATHFN##F128: \
2121 return float128_type_node; \
2122 case CFN_BUILT_IN_##MATHFN##F32X: \
2123 return float32x_type_node; \
2124 case CFN_BUILT_IN_##MATHFN##F64X: \
2125 return float64x_type_node; \
2126 case CFN_BUILT_IN_##MATHFN##F128X: \
2127 return float128x_type_node;
2128
2129/* Similar to above, but appends _R after any F/L suffix. */
2130#define CASE_MATHFN_REENT(MATHFN) \
2131 case CFN_BUILT_IN_##MATHFN##_R: \
2132 return double_type_node; \
2133 case CFN_BUILT_IN_##MATHFN##F_R: \
2134 return float_type_node; \
2135 case CFN_BUILT_IN_##MATHFN##L_R: \
2136 return long_double_type_node;
2137
2138 switch (fn)
2139 {
2140 SEQ_OF_CASE_MATHFN
2141
2142 default:
2143 return NULL_TREE;
2144 }
2145
2146#undef CASE_MATHFN
2147#undef CASE_MATHFN_FLOATN
2148#undef CASE_MATHFN_REENT
2149#undef SEQ_OF_CASE_MATHFN
2150}
2151
2152/* Check whether there is an internal function associated with function FN
2153 and return type RETURN_TYPE. Return the function if so, otherwise return
2154 IFN_LAST.
2155
2156 Note that this function only tests whether the function is defined in
2157 internals.def, not whether it is actually available on the target. */
2158
2159static internal_fn
2160associated_internal_fn (built_in_function fn, tree return_type)
2161{
2162 switch (fn)
2163 {
2164#define DEF_INTERNAL_FLT_FN(NAME, FLAGS, OPTAB, TYPE) \
2165 CASE_FLT_FN (BUILT_IN_##NAME): return IFN_##NAME;
2166#define DEF_INTERNAL_FLT_FLOATN_FN(NAME, FLAGS, OPTAB, TYPE) \
2167 CASE_FLT_FN (BUILT_IN_##NAME): return IFN_##NAME; \
2168 CASE_FLT_FN_FLOATN_NX (BUILT_IN_##NAME): return IFN_##NAME;
2169#define DEF_INTERNAL_INT_FN(NAME, FLAGS, OPTAB, TYPE) \
2170 CASE_INT_FN (BUILT_IN_##NAME): return IFN_##NAME;
2171#include "internal-fn.def"
2172
2173 CASE_FLT_FN (BUILT_IN_POW10):
2174 return IFN_EXP10;
2175
2176 CASE_FLT_FN (BUILT_IN_DREM):
2177 return IFN_REMAINDER;
2178
2179 CASE_FLT_FN (BUILT_IN_SCALBN):
2180 CASE_FLT_FN (BUILT_IN_SCALBLN):
2181 if (REAL_MODE_FORMAT (TYPE_MODE (return_type))->b == 2)
2182 return IFN_LDEXP;
2183 return IFN_LAST;
2184
2185 default:
2186 return IFN_LAST;
2187 }
2188}
2189
2190/* If BUILT_IN_NORMAL function FNDECL has an associated internal function,
2191 return its code, otherwise return IFN_LAST. Note that this function
2192 only tests whether the function is defined in internals.def, not whether
2193 it is actually available on the target. */
2194
2195internal_fn
2196associated_internal_fn (tree fndecl)
2197{
2198 gcc_checking_assert (DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_NORMAL);
2199 return associated_internal_fn (fn: DECL_FUNCTION_CODE (decl: fndecl),
2200 TREE_TYPE (TREE_TYPE (fndecl)));
2201}
2202
2203/* Check whether there is an internal function associated with function CFN
2204 and return type RETURN_TYPE. Return the function if so, otherwise return
2205 IFN_LAST.
2206
2207 Note that this function only tests whether the function is defined in
2208 internals.def, not whether it is actually available on the target. */
2209
2210internal_fn
2211associated_internal_fn (combined_fn cfn, tree return_type)
2212{
2213 if (internal_fn_p (code: cfn))
2214 return as_internal_fn (code: cfn);
2215 return associated_internal_fn (fn: as_builtin_fn (code: cfn), return_type);
2216}
2217
2218/* If CALL is a call to a BUILT_IN_NORMAL function that could be replaced
2219 on the current target by a call to an internal function, return the
2220 code of that internal function, otherwise return IFN_LAST. The caller
2221 is responsible for ensuring that any side-effects of the built-in
2222 call are dealt with correctly. E.g. if CALL sets errno, the caller
2223 must decide that the errno result isn't needed or make it available
2224 in some other way. */
2225
2226internal_fn
2227replacement_internal_fn (gcall *call)
2228{
2229 if (gimple_call_builtin_p (call, BUILT_IN_NORMAL))
2230 {
2231 internal_fn ifn = associated_internal_fn (fndecl: gimple_call_fndecl (gs: call));
2232 if (ifn != IFN_LAST)
2233 {
2234 tree_pair types = direct_internal_fn_types (ifn, call);
2235 optimization_type opt_type = bb_optimization_type (gimple_bb (g: call));
2236 if (direct_internal_fn_supported_p (ifn, types, opt_type))
2237 return ifn;
2238 }
2239 }
2240 return IFN_LAST;
2241}
2242
2243/* Expand a call to the builtin trinary math functions (fma).
2244 Return NULL_RTX if a normal call should be emitted rather than expanding the
2245 function in-line. EXP is the expression that is a call to the builtin
2246 function; if convenient, the result should be placed in TARGET.
2247 SUBTARGET may be used as the target for computing one of EXP's
2248 operands. */
2249
2250static rtx
2251expand_builtin_mathfn_ternary (tree exp, rtx target, rtx subtarget)
2252{
2253 optab builtin_optab;
2254 rtx op0, op1, op2, result;
2255 rtx_insn *insns;
2256 tree fndecl = get_callee_fndecl (exp);
2257 tree arg0, arg1, arg2;
2258 machine_mode mode;
2259
2260 if (!validate_arglist (callexpr: exp, REAL_TYPE, REAL_TYPE, REAL_TYPE, VOID_TYPE))
2261 return NULL_RTX;
2262
2263 arg0 = CALL_EXPR_ARG (exp, 0);
2264 arg1 = CALL_EXPR_ARG (exp, 1);
2265 arg2 = CALL_EXPR_ARG (exp, 2);
2266
2267 switch (DECL_FUNCTION_CODE (decl: fndecl))
2268 {
2269 CASE_FLT_FN (BUILT_IN_FMA):
2270 CASE_FLT_FN_FLOATN_NX (BUILT_IN_FMA):
2271 builtin_optab = fma_optab; break;
2272 default:
2273 gcc_unreachable ();
2274 }
2275
2276 /* Make a suitable register to place result in. */
2277 mode = TYPE_MODE (TREE_TYPE (exp));
2278
2279 /* Before working hard, check whether the instruction is available. */
2280 if (optab_handler (op: builtin_optab, mode) == CODE_FOR_nothing)
2281 return NULL_RTX;
2282
2283 result = gen_reg_rtx (mode);
2284
2285 /* Always stabilize the argument list. */
2286 CALL_EXPR_ARG (exp, 0) = arg0 = builtin_save_expr (exp: arg0);
2287 CALL_EXPR_ARG (exp, 1) = arg1 = builtin_save_expr (exp: arg1);
2288 CALL_EXPR_ARG (exp, 2) = arg2 = builtin_save_expr (exp: arg2);
2289
2290 op0 = expand_expr (exp: arg0, target: subtarget, VOIDmode, modifier: EXPAND_NORMAL);
2291 op1 = expand_normal (exp: arg1);
2292 op2 = expand_normal (exp: arg2);
2293
2294 start_sequence ();
2295
2296 /* Compute into RESULT.
2297 Set RESULT to wherever the result comes back. */
2298 result = expand_ternary_op (mode, ternary_optab: builtin_optab, op0, op1, op2,
2299 target: result, unsignedp: 0);
2300
2301 /* If we were unable to expand via the builtin, stop the sequence
2302 (without outputting the insns) and call to the library function
2303 with the stabilized argument list. */
2304 if (result == 0)
2305 {
2306 end_sequence ();
2307 return expand_call (exp, target, target == const0_rtx);
2308 }
2309
2310 /* Output the entire sequence. */
2311 insns = get_insns ();
2312 end_sequence ();
2313 emit_insn (insns);
2314
2315 return result;
2316}
2317
2318/* Expand a call to the builtin sin and cos math functions.
2319 Return NULL_RTX if a normal call should be emitted rather than expanding the
2320 function in-line. EXP is the expression that is a call to the builtin
2321 function; if convenient, the result should be placed in TARGET.
2322 SUBTARGET may be used as the target for computing one of EXP's
2323 operands. */
2324
2325static rtx
2326expand_builtin_mathfn_3 (tree exp, rtx target, rtx subtarget)
2327{
2328 optab builtin_optab;
2329 rtx op0;
2330 rtx_insn *insns;
2331 tree fndecl = get_callee_fndecl (exp);
2332 machine_mode mode;
2333 tree arg;
2334
2335 if (!validate_arglist (callexpr: exp, REAL_TYPE, VOID_TYPE))
2336 return NULL_RTX;
2337
2338 arg = CALL_EXPR_ARG (exp, 0);
2339
2340 switch (DECL_FUNCTION_CODE (decl: fndecl))
2341 {
2342 CASE_FLT_FN (BUILT_IN_SIN):
2343 CASE_FLT_FN (BUILT_IN_COS):
2344 builtin_optab = sincos_optab; break;
2345 default:
2346 gcc_unreachable ();
2347 }
2348
2349 /* Make a suitable register to place result in. */
2350 mode = TYPE_MODE (TREE_TYPE (exp));
2351
2352 /* Check if sincos insn is available, otherwise fallback
2353 to sin or cos insn. */
2354 if (optab_handler (op: builtin_optab, mode) == CODE_FOR_nothing)
2355 switch (DECL_FUNCTION_CODE (decl: fndecl))
2356 {
2357 CASE_FLT_FN (BUILT_IN_SIN):
2358 builtin_optab = sin_optab; break;
2359 CASE_FLT_FN (BUILT_IN_COS):
2360 builtin_optab = cos_optab; break;
2361 default:
2362 gcc_unreachable ();
2363 }
2364
2365 /* Before working hard, check whether the instruction is available. */
2366 if (optab_handler (op: builtin_optab, mode) != CODE_FOR_nothing)
2367 {
2368 rtx result = gen_reg_rtx (mode);
2369
2370 /* Wrap the computation of the argument in a SAVE_EXPR, as we may
2371 need to expand the argument again. This way, we will not perform
2372 side-effects more the once. */
2373 CALL_EXPR_ARG (exp, 0) = arg = builtin_save_expr (exp: arg);
2374
2375 op0 = expand_expr (exp: arg, target: subtarget, VOIDmode, modifier: EXPAND_NORMAL);
2376
2377 start_sequence ();
2378
2379 /* Compute into RESULT.
2380 Set RESULT to wherever the result comes back. */
2381 if (builtin_optab == sincos_optab)
2382 {
2383 int ok;
2384
2385 switch (DECL_FUNCTION_CODE (decl: fndecl))
2386 {
2387 CASE_FLT_FN (BUILT_IN_SIN):
2388 ok = expand_twoval_unop (builtin_optab, op0, 0, result, 0);
2389 break;
2390 CASE_FLT_FN (BUILT_IN_COS):
2391 ok = expand_twoval_unop (builtin_optab, op0, result, 0, 0);
2392 break;
2393 default:
2394 gcc_unreachable ();
2395 }
2396 gcc_assert (ok);
2397 }
2398 else
2399 result = expand_unop (mode, builtin_optab, op0, result, 0);
2400
2401 if (result != 0)
2402 {
2403 /* Output the entire sequence. */
2404 insns = get_insns ();
2405 end_sequence ();
2406 emit_insn (insns);
2407 return result;
2408 }
2409
2410 /* If we were unable to expand via the builtin, stop the sequence
2411 (without outputting the insns) and call to the library function
2412 with the stabilized argument list. */
2413 end_sequence ();
2414 }
2415
2416 return expand_call (exp, target, target == const0_rtx);
2417}
2418
2419/* Given an interclass math builtin decl FNDECL and it's argument ARG
2420 return an RTL instruction code that implements the functionality.
2421 If that isn't possible or available return CODE_FOR_nothing. */
2422
2423static enum insn_code
2424interclass_mathfn_icode (tree arg, tree fndecl)
2425{
2426 bool errno_set = false;
2427 optab builtin_optab = unknown_optab;
2428 machine_mode mode;
2429
2430 switch (DECL_FUNCTION_CODE (decl: fndecl))
2431 {
2432 CASE_FLT_FN (BUILT_IN_ILOGB):
2433 errno_set = true; builtin_optab = ilogb_optab; break;
2434 CASE_FLT_FN (BUILT_IN_ISINF):
2435 builtin_optab = isinf_optab; break;
2436 case BUILT_IN_ISNORMAL:
2437 case BUILT_IN_ISFINITE:
2438 CASE_FLT_FN (BUILT_IN_FINITE):
2439 case BUILT_IN_FINITED32:
2440 case BUILT_IN_FINITED64:
2441 case BUILT_IN_FINITED128:
2442 case BUILT_IN_ISINFD32:
2443 case BUILT_IN_ISINFD64:
2444 case BUILT_IN_ISINFD128:
2445 /* These builtins have no optabs (yet). */
2446 break;
2447 default:
2448 gcc_unreachable ();
2449 }
2450
2451 /* There's no easy way to detect the case we need to set EDOM. */
2452 if (flag_errno_math && errno_set)
2453 return CODE_FOR_nothing;
2454
2455 /* Optab mode depends on the mode of the input argument. */
2456 mode = TYPE_MODE (TREE_TYPE (arg));
2457
2458 if (builtin_optab)
2459 return optab_handler (op: builtin_optab, mode);
2460 return CODE_FOR_nothing;
2461}
2462
2463/* Expand a call to one of the builtin math functions that operate on
2464 floating point argument and output an integer result (ilogb, isinf,
2465 isnan, etc).
2466 Return 0 if a normal call should be emitted rather than expanding the
2467 function in-line. EXP is the expression that is a call to the builtin
2468 function; if convenient, the result should be placed in TARGET. */
2469
2470static rtx
2471expand_builtin_interclass_mathfn (tree exp, rtx target)
2472{
2473 enum insn_code icode = CODE_FOR_nothing;
2474 rtx op0;
2475 tree fndecl = get_callee_fndecl (exp);
2476 machine_mode mode;
2477 tree arg;
2478
2479 if (!validate_arglist (callexpr: exp, REAL_TYPE, VOID_TYPE))
2480 return NULL_RTX;
2481
2482 arg = CALL_EXPR_ARG (exp, 0);
2483 icode = interclass_mathfn_icode (arg, fndecl);
2484 mode = TYPE_MODE (TREE_TYPE (arg));
2485
2486 if (icode != CODE_FOR_nothing)
2487 {
2488 class expand_operand ops[1];
2489 rtx_insn *last = get_last_insn ();
2490 tree orig_arg = arg;
2491
2492 /* Wrap the computation of the argument in a SAVE_EXPR, as we may
2493 need to expand the argument again. This way, we will not perform
2494 side-effects more the once. */
2495 CALL_EXPR_ARG (exp, 0) = arg = builtin_save_expr (exp: arg);
2496
2497 op0 = expand_expr (exp: arg, NULL_RTX, VOIDmode, modifier: EXPAND_NORMAL);
2498
2499 if (mode != GET_MODE (op0))
2500 op0 = convert_to_mode (mode, op0, 0);
2501
2502 create_output_operand (op: &ops[0], x: target, TYPE_MODE (TREE_TYPE (exp)));
2503 if (maybe_legitimize_operands (icode, opno: 0, nops: 1, ops)
2504 && maybe_emit_unop_insn (icode, ops[0].value, op0, UNKNOWN))
2505 return ops[0].value;
2506
2507 delete_insns_since (last);
2508 CALL_EXPR_ARG (exp, 0) = orig_arg;
2509 }
2510
2511 return NULL_RTX;
2512}
2513
2514/* Expand a call to the builtin sincos math function.
2515 Return NULL_RTX if a normal call should be emitted rather than expanding the
2516 function in-line. EXP is the expression that is a call to the builtin
2517 function. */
2518
2519static rtx
2520expand_builtin_sincos (tree exp)
2521{
2522 rtx op0, op1, op2, target1, target2;
2523 machine_mode mode;
2524 tree arg, sinp, cosp;
2525 int result;
2526 location_t loc = EXPR_LOCATION (exp);
2527 tree alias_type, alias_off;
2528
2529 if (!validate_arglist (callexpr: exp, REAL_TYPE,
2530 POINTER_TYPE, POINTER_TYPE, VOID_TYPE))
2531 return NULL_RTX;
2532
2533 arg = CALL_EXPR_ARG (exp, 0);
2534 sinp = CALL_EXPR_ARG (exp, 1);
2535 cosp = CALL_EXPR_ARG (exp, 2);
2536
2537 /* Make a suitable register to place result in. */
2538 mode = TYPE_MODE (TREE_TYPE (arg));
2539
2540 /* Check if sincos insn is available, otherwise emit the call. */
2541 if (optab_handler (op: sincos_optab, mode) == CODE_FOR_nothing)
2542 return NULL_RTX;
2543
2544 target1 = gen_reg_rtx (mode);
2545 target2 = gen_reg_rtx (mode);
2546
2547 op0 = expand_normal (exp: arg);
2548 alias_type = build_pointer_type_for_mode (TREE_TYPE (arg), ptr_mode, true);
2549 alias_off = build_int_cst (alias_type, 0);
2550 op1 = expand_normal (exp: fold_build2_loc (loc, MEM_REF, TREE_TYPE (arg),
2551 sinp, alias_off));
2552 op2 = expand_normal (exp: fold_build2_loc (loc, MEM_REF, TREE_TYPE (arg),
2553 cosp, alias_off));
2554
2555 /* Compute into target1 and target2.
2556 Set TARGET to wherever the result comes back. */
2557 result = expand_twoval_unop (sincos_optab, op0, target2, target1, 0);
2558 gcc_assert (result);
2559
2560 /* Move target1 and target2 to the memory locations indicated
2561 by op1 and op2. */
2562 emit_move_insn (op1, target1);
2563 emit_move_insn (op2, target2);
2564
2565 return const0_rtx;
2566}
2567
2568/* Expand call EXP to the fegetround builtin (from C99 fenv.h), returning the
2569 result and setting it in TARGET. Otherwise return NULL_RTX on failure. */
2570static rtx
2571expand_builtin_fegetround (tree exp, rtx target, machine_mode target_mode)
2572{
2573 if (!validate_arglist (callexpr: exp, VOID_TYPE))
2574 return NULL_RTX;
2575
2576 insn_code icode = direct_optab_handler (op: fegetround_optab, SImode);
2577 if (icode == CODE_FOR_nothing)
2578 return NULL_RTX;
2579
2580 if (target == 0
2581 || GET_MODE (target) != target_mode
2582 || !(*insn_data[icode].operand[0].predicate) (target, target_mode))
2583 target = gen_reg_rtx (target_mode);
2584
2585 rtx pat = GEN_FCN (icode) (target);
2586 if (!pat)
2587 return NULL_RTX;
2588 emit_insn (pat);
2589
2590 return target;
2591}
2592
2593/* Expand call EXP to either feclearexcept or feraiseexcept builtins (from C99
2594 fenv.h), returning the result and setting it in TARGET. Otherwise return
2595 NULL_RTX on failure. */
2596static rtx
2597expand_builtin_feclear_feraise_except (tree exp, rtx target,
2598 machine_mode target_mode, optab op_optab)
2599{
2600 if (!validate_arglist (callexpr: exp, INTEGER_TYPE, VOID_TYPE))
2601 return NULL_RTX;
2602 rtx op0 = expand_normal (CALL_EXPR_ARG (exp, 0));
2603
2604 insn_code icode = direct_optab_handler (op: op_optab, SImode);
2605 if (icode == CODE_FOR_nothing)
2606 return NULL_RTX;
2607
2608 if (!(*insn_data[icode].operand[1].predicate) (op0, GET_MODE (op0)))
2609 return NULL_RTX;
2610
2611 if (target == 0
2612 || GET_MODE (target) != target_mode
2613 || !(*insn_data[icode].operand[0].predicate) (target, target_mode))
2614 target = gen_reg_rtx (target_mode);
2615
2616 rtx pat = GEN_FCN (icode) (target, op0);
2617 if (!pat)
2618 return NULL_RTX;
2619 emit_insn (pat);
2620
2621 return target;
2622}
2623
2624/* Expand a call to the internal cexpi builtin to the sincos math function.
2625 EXP is the expression that is a call to the builtin function; if convenient,
2626 the result should be placed in TARGET. */
2627
2628static rtx
2629expand_builtin_cexpi (tree exp, rtx target)
2630{
2631 tree fndecl = get_callee_fndecl (exp);
2632 tree arg, type;
2633 machine_mode mode;
2634 rtx op0, op1, op2;
2635 location_t loc = EXPR_LOCATION (exp);
2636
2637 if (!validate_arglist (callexpr: exp, REAL_TYPE, VOID_TYPE))
2638 return NULL_RTX;
2639
2640 arg = CALL_EXPR_ARG (exp, 0);
2641 type = TREE_TYPE (arg);
2642 mode = TYPE_MODE (TREE_TYPE (arg));
2643
2644 /* Try expanding via a sincos optab, fall back to emitting a libcall
2645 to sincos or cexp. We are sure we have sincos or cexp because cexpi
2646 is only generated from sincos, cexp or if we have either of them. */
2647 if (optab_handler (op: sincos_optab, mode) != CODE_FOR_nothing)
2648 {
2649 op1 = gen_reg_rtx (mode);
2650 op2 = gen_reg_rtx (mode);
2651
2652 op0 = expand_expr (exp: arg, NULL_RTX, VOIDmode, modifier: EXPAND_NORMAL);
2653
2654 /* Compute into op1 and op2. */
2655 expand_twoval_unop (sincos_optab, op0, op2, op1, 0);
2656 }
2657 else if (targetm.libc_has_function (function_sincos, type))
2658 {
2659 tree call, fn = NULL_TREE;
2660 tree top1, top2;
2661 rtx op1a, op2a;
2662
2663 if (DECL_FUNCTION_CODE (decl: fndecl) == BUILT_IN_CEXPIF)
2664 fn = builtin_decl_explicit (fncode: BUILT_IN_SINCOSF);
2665 else if (DECL_FUNCTION_CODE (decl: fndecl) == BUILT_IN_CEXPI)
2666 fn = builtin_decl_explicit (fncode: BUILT_IN_SINCOS);
2667 else if (DECL_FUNCTION_CODE (decl: fndecl) == BUILT_IN_CEXPIL)
2668 fn = builtin_decl_explicit (fncode: BUILT_IN_SINCOSL);
2669 else
2670 gcc_unreachable ();
2671
2672 op1 = assign_temp (TREE_TYPE (arg), 1, 1);
2673 op2 = assign_temp (TREE_TYPE (arg), 1, 1);
2674 op1a = copy_addr_to_reg (XEXP (op1, 0));
2675 op2a = copy_addr_to_reg (XEXP (op2, 0));
2676 top1 = make_tree (build_pointer_type (TREE_TYPE (arg)), op1a);
2677 top2 = make_tree (build_pointer_type (TREE_TYPE (arg)), op2a);
2678
2679 /* Make sure not to fold the sincos call again. */
2680 call = build1 (ADDR_EXPR, build_pointer_type (TREE_TYPE (fn)), fn);
2681 expand_normal (exp: build_call_nary (TREE_TYPE (TREE_TYPE (fn)),
2682 call, 3, arg, top1, top2));
2683 }
2684 else
2685 {
2686 tree call, fn = NULL_TREE, narg;
2687 tree ctype = build_complex_type (type);
2688
2689 if (DECL_FUNCTION_CODE (decl: fndecl) == BUILT_IN_CEXPIF)
2690 fn = builtin_decl_explicit (fncode: BUILT_IN_CEXPF);
2691 else if (DECL_FUNCTION_CODE (decl: fndecl) == BUILT_IN_CEXPI)
2692 fn = builtin_decl_explicit (fncode: BUILT_IN_CEXP);
2693 else if (DECL_FUNCTION_CODE (decl: fndecl) == BUILT_IN_CEXPIL)
2694 fn = builtin_decl_explicit (fncode: BUILT_IN_CEXPL);
2695 else
2696 gcc_unreachable ();
2697
2698 /* If we don't have a decl for cexp create one. This is the
2699 friendliest fallback if the user calls __builtin_cexpi
2700 without full target C99 function support. */
2701 if (fn == NULL_TREE)
2702 {
2703 tree fntype;
2704 const char *name = NULL;
2705
2706 if (DECL_FUNCTION_CODE (decl: fndecl) == BUILT_IN_CEXPIF)
2707 name = "cexpf";
2708 else if (DECL_FUNCTION_CODE (decl: fndecl) == BUILT_IN_CEXPI)
2709 name = "cexp";
2710 else if (DECL_FUNCTION_CODE (decl: fndecl) == BUILT_IN_CEXPIL)
2711 name = "cexpl";
2712
2713 fntype = build_function_type_list (ctype, ctype, NULL_TREE);
2714 fn = build_fn_decl (name, fntype);
2715 }
2716
2717 narg = fold_build2_loc (loc, COMPLEX_EXPR, ctype,
2718 build_real (type, dconst0), arg);
2719
2720 /* Make sure not to fold the cexp call again. */
2721 call = build1 (ADDR_EXPR, build_pointer_type (TREE_TYPE (fn)), fn);
2722 return expand_expr (exp: build_call_nary (ctype, call, 1, narg),
2723 target, VOIDmode, modifier: EXPAND_NORMAL);
2724 }
2725
2726 /* Now build the proper return type. */
2727 return expand_expr (exp: build2 (COMPLEX_EXPR, build_complex_type (type),
2728 make_tree (TREE_TYPE (arg), op2),
2729 make_tree (TREE_TYPE (arg), op1)),
2730 target, VOIDmode, modifier: EXPAND_NORMAL);
2731}
2732
2733/* Conveniently construct a function call expression. FNDECL names the
2734 function to be called, N is the number of arguments, and the "..."
2735 parameters are the argument expressions. Unlike build_call_exr
2736 this doesn't fold the call, hence it will always return a CALL_EXPR. */
2737
2738static tree
2739build_call_nofold_loc (location_t loc, tree fndecl, int n, ...)
2740{
2741 va_list ap;
2742 tree fntype = TREE_TYPE (fndecl);
2743 tree fn = build1 (ADDR_EXPR, build_pointer_type (fntype), fndecl);
2744
2745 va_start (ap, n);
2746 fn = build_call_valist (TREE_TYPE (fntype), fn, n, ap);
2747 va_end (ap);
2748 SET_EXPR_LOCATION (fn, loc);
2749 return fn;
2750}
2751
2752/* Expand the __builtin_issignaling builtin. This needs to handle
2753 all floating point formats that do support NaNs (for those that
2754 don't it just sets target to 0). */
2755
2756static rtx
2757expand_builtin_issignaling (tree exp, rtx target)
2758{
2759 if (!validate_arglist (callexpr: exp, REAL_TYPE, VOID_TYPE))
2760 return NULL_RTX;
2761
2762 tree arg = CALL_EXPR_ARG (exp, 0);
2763 scalar_float_mode fmode = SCALAR_FLOAT_TYPE_MODE (TREE_TYPE (arg));
2764 const struct real_format *fmt = REAL_MODE_FORMAT (fmode);
2765
2766 /* Expand the argument yielding a RTX expression. */
2767 rtx temp = expand_normal (exp: arg);
2768
2769 /* If mode doesn't support NaN, always return 0.
2770 Don't use !HONOR_SNANS (fmode) here, so there is some possibility of
2771 __builtin_issignaling working without -fsignaling-nans. Especially
2772 when -fno-signaling-nans is the default.
2773 On the other side, MODE_HAS_NANS (fmode) is unnecessary, with
2774 -ffinite-math-only even __builtin_isnan or __builtin_fpclassify
2775 fold to 0 or non-NaN/Inf classification. */
2776 if (!HONOR_NANS (fmode))
2777 {
2778 emit_move_insn (target, const0_rtx);
2779 return target;
2780 }
2781
2782 /* Check if the back end provides an insn that handles issignaling for the
2783 argument's mode. */
2784 enum insn_code icode = optab_handler (op: issignaling_optab, mode: fmode);
2785 if (icode != CODE_FOR_nothing)
2786 {
2787 rtx_insn *last = get_last_insn ();
2788 rtx this_target = gen_reg_rtx (TYPE_MODE (TREE_TYPE (exp)));
2789 if (maybe_emit_unop_insn (icode, this_target, temp, UNKNOWN))
2790 return this_target;
2791 delete_insns_since (last);
2792 }
2793
2794 if (DECIMAL_FLOAT_MODE_P (fmode))
2795 {
2796 scalar_int_mode imode;
2797 rtx hi;
2798 switch (fmt->ieee_bits)
2799 {
2800 case 32:
2801 case 64:
2802 imode = int_mode_for_mode (fmode).require ();
2803 temp = gen_lowpart (imode, temp);
2804 break;
2805 case 128:
2806 imode = int_mode_for_size (size: 64, limit: 1).require ();
2807 hi = NULL_RTX;
2808 /* For decimal128, TImode support isn't always there and even when
2809 it is, working on the DImode high part is usually better. */
2810 if (!MEM_P (temp))
2811 {
2812 if (rtx t = simplify_gen_subreg (outermode: imode, op: temp, innermode: fmode,
2813 byte: subreg_highpart_offset (outermode: imode,
2814 innermode: fmode)))
2815 hi = t;
2816 else
2817 {
2818 scalar_int_mode imode2;
2819 if (int_mode_for_mode (fmode).exists (mode: &imode2))
2820 {
2821 rtx temp2 = gen_lowpart (imode2, temp);
2822 poly_uint64 off = subreg_highpart_offset (outermode: imode, innermode: imode2);
2823 if (rtx t = simplify_gen_subreg (outermode: imode, op: temp2,
2824 innermode: imode2, byte: off))
2825 hi = t;
2826 }
2827 }
2828 if (!hi)
2829 {
2830 rtx mem = assign_stack_temp (fmode, GET_MODE_SIZE (mode: fmode));
2831 emit_move_insn (mem, temp);
2832 temp = mem;
2833 }
2834 }
2835 if (!hi)
2836 {
2837 poly_int64 offset
2838 = subreg_highpart_offset (outermode: imode, GET_MODE (temp));
2839 hi = adjust_address (temp, imode, offset);
2840 }
2841 temp = hi;
2842 break;
2843 default:
2844 gcc_unreachable ();
2845 }
2846 /* In all of decimal{32,64,128}, there is MSB sign bit and sNaN
2847 have 6 bits below it all set. */
2848 rtx val
2849 = GEN_INT (HOST_WIDE_INT_C (0x3f) << (GET_MODE_BITSIZE (imode) - 7));
2850 temp = expand_binop (imode, and_optab, temp, val,
2851 NULL_RTX, 1, OPTAB_LIB_WIDEN);
2852 temp = emit_store_flag_force (target, EQ, temp, val, imode, 1, 1);
2853 return temp;
2854 }
2855
2856 /* Only PDP11 has these defined differently but doesn't support NaNs. */
2857 gcc_assert (FLOAT_WORDS_BIG_ENDIAN == WORDS_BIG_ENDIAN);
2858 gcc_assert (fmt->signbit_ro > 0 && fmt->b == 2);
2859 gcc_assert (MODE_COMPOSITE_P (fmode)
2860 || (fmt->pnan == fmt->p
2861 && fmt->signbit_ro == fmt->signbit_rw));
2862
2863 switch (fmt->p)
2864 {
2865 case 106: /* IBM double double */
2866 /* For IBM double double, recurse on the most significant double. */
2867 gcc_assert (MODE_COMPOSITE_P (fmode));
2868 temp = convert_modes (DFmode, oldmode: fmode, x: temp, unsignedp: 0);
2869 fmode = DFmode;
2870 fmt = REAL_MODE_FORMAT (DFmode);
2871 /* FALLTHRU */
2872 case 8: /* bfloat */
2873 case 11: /* IEEE half */
2874 case 24: /* IEEE single */
2875 case 53: /* IEEE double or Intel extended with rounding to double */
2876 if (fmt->p == 53 && fmt->signbit_ro == 79)
2877 goto extended;
2878 {
2879 scalar_int_mode imode = int_mode_for_mode (fmode).require ();
2880 temp = gen_lowpart (imode, temp);
2881 rtx val = GEN_INT ((HOST_WIDE_INT_M1U << (fmt->p - 2))
2882 & ~(HOST_WIDE_INT_M1U << fmt->signbit_ro));
2883 if (fmt->qnan_msb_set)
2884 {
2885 rtx mask = GEN_INT (~(HOST_WIDE_INT_M1U << fmt->signbit_ro));
2886 rtx bit = GEN_INT (HOST_WIDE_INT_1U << (fmt->p - 2));
2887 /* For non-MIPS/PA IEEE single/double/half or bfloat, expand to:
2888 ((temp ^ bit) & mask) > val. */
2889 temp = expand_binop (imode, xor_optab, temp, bit,
2890 NULL_RTX, 1, OPTAB_LIB_WIDEN);
2891 temp = expand_binop (imode, and_optab, temp, mask,
2892 NULL_RTX, 1, OPTAB_LIB_WIDEN);
2893 temp = emit_store_flag_force (target, GTU, temp, val, imode,
2894 1, 1);
2895 }
2896 else
2897 {
2898 /* For MIPS/PA IEEE single/double, expand to:
2899 (temp & val) == val. */
2900 temp = expand_binop (imode, and_optab, temp, val,
2901 NULL_RTX, 1, OPTAB_LIB_WIDEN);
2902 temp = emit_store_flag_force (target, EQ, temp, val, imode,
2903 1, 1);
2904 }
2905 }
2906 break;
2907 case 113: /* IEEE quad */
2908 {
2909 rtx hi = NULL_RTX, lo = NULL_RTX;
2910 scalar_int_mode imode = int_mode_for_size (size: 64, limit: 1).require ();
2911 /* For IEEE quad, TImode support isn't always there and even when
2912 it is, working on DImode parts is usually better. */
2913 if (!MEM_P (temp))
2914 {
2915 hi = simplify_gen_subreg (outermode: imode, op: temp, innermode: fmode,
2916 byte: subreg_highpart_offset (outermode: imode, innermode: fmode));
2917 lo = simplify_gen_subreg (outermode: imode, op: temp, innermode: fmode,
2918 byte: subreg_lowpart_offset (outermode: imode, innermode: fmode));
2919 if (!hi || !lo)
2920 {
2921 scalar_int_mode imode2;
2922 if (int_mode_for_mode (fmode).exists (mode: &imode2))
2923 {
2924 rtx temp2 = gen_lowpart (imode2, temp);
2925 hi = simplify_gen_subreg (outermode: imode, op: temp2, innermode: imode2,
2926 byte: subreg_highpart_offset (outermode: imode,
2927 innermode: imode2));
2928 lo = simplify_gen_subreg (outermode: imode, op: temp2, innermode: imode2,
2929 byte: subreg_lowpart_offset (outermode: imode,
2930 innermode: imode2));
2931 }
2932 }
2933 if (!hi || !lo)
2934 {
2935 rtx mem = assign_stack_temp (fmode, GET_MODE_SIZE (mode: fmode));
2936 emit_move_insn (mem, temp);
2937 temp = mem;
2938 }
2939 }
2940 if (!hi || !lo)
2941 {
2942 poly_int64 offset
2943 = subreg_highpart_offset (outermode: imode, GET_MODE (temp));
2944 hi = adjust_address (temp, imode, offset);
2945 offset = subreg_lowpart_offset (outermode: imode, GET_MODE (temp));
2946 lo = adjust_address (temp, imode, offset);
2947 }
2948 rtx val = GEN_INT ((HOST_WIDE_INT_M1U << (fmt->p - 2 - 64))
2949 & ~(HOST_WIDE_INT_M1U << (fmt->signbit_ro - 64)));
2950 if (fmt->qnan_msb_set)
2951 {
2952 rtx mask = GEN_INT (~(HOST_WIDE_INT_M1U << (fmt->signbit_ro
2953 - 64)));
2954 rtx bit = GEN_INT (HOST_WIDE_INT_1U << (fmt->p - 2 - 64));
2955 /* For non-MIPS/PA IEEE quad, expand to:
2956 (((hi ^ bit) | ((lo | -lo) >> 63)) & mask) > val. */
2957 rtx nlo = expand_unop (imode, neg_optab, lo, NULL_RTX, 0);
2958 lo = expand_binop (imode, ior_optab, lo, nlo,
2959 NULL_RTX, 1, OPTAB_LIB_WIDEN);
2960 lo = expand_shift (RSHIFT_EXPR, imode, lo, 63, NULL_RTX, 1);
2961 temp = expand_binop (imode, xor_optab, hi, bit,
2962 NULL_RTX, 1, OPTAB_LIB_WIDEN);
2963 temp = expand_binop (imode, ior_optab, temp, lo,
2964 NULL_RTX, 1, OPTAB_LIB_WIDEN);
2965 temp = expand_binop (imode, and_optab, temp, mask,
2966 NULL_RTX, 1, OPTAB_LIB_WIDEN);
2967 temp = emit_store_flag_force (target, GTU, temp, val, imode,
2968 1, 1);
2969 }
2970 else
2971 {
2972 /* For MIPS/PA IEEE quad, expand to:
2973 (hi & val) == val. */
2974 temp = expand_binop (imode, and_optab, hi, val,
2975 NULL_RTX, 1, OPTAB_LIB_WIDEN);
2976 temp = emit_store_flag_force (target, EQ, temp, val, imode,
2977 1, 1);
2978 }
2979 }
2980 break;
2981 case 64: /* Intel or Motorola extended */
2982 extended:
2983 {
2984 rtx ex, hi, lo;
2985 scalar_int_mode imode = int_mode_for_size (size: 32, limit: 1).require ();
2986 scalar_int_mode iemode = int_mode_for_size (size: 16, limit: 1).require ();
2987 if (!MEM_P (temp))
2988 {
2989 rtx mem = assign_stack_temp (fmode, GET_MODE_SIZE (mode: fmode));
2990 emit_move_insn (mem, temp);
2991 temp = mem;
2992 }
2993 if (fmt->signbit_ro == 95)
2994 {
2995 /* Motorola, always big endian, with 16-bit gap in between
2996 16-bit sign+exponent and 64-bit mantissa. */
2997 ex = adjust_address (temp, iemode, 0);
2998 hi = adjust_address (temp, imode, 4);
2999 lo = adjust_address (temp, imode, 8);
3000 }
3001 else if (!WORDS_BIG_ENDIAN)
3002 {
3003 /* Intel little endian, 64-bit mantissa followed by 16-bit
3004 sign+exponent and then either 16 or 48 bits of gap. */
3005 ex = adjust_address (temp, iemode, 8);
3006 hi = adjust_address (temp, imode, 4);
3007 lo = adjust_address (temp, imode, 0);
3008 }
3009 else
3010 {
3011 /* Big endian Itanium. */
3012 ex = adjust_address (temp, iemode, 0);
3013 hi = adjust_address (temp, imode, 2);
3014 lo = adjust_address (temp, imode, 6);
3015 }
3016 rtx val = GEN_INT (HOST_WIDE_INT_M1U << 30);
3017 gcc_assert (fmt->qnan_msb_set);
3018 rtx mask = GEN_INT (0x7fff);
3019 rtx bit = GEN_INT (HOST_WIDE_INT_1U << 30);
3020 /* For Intel/Motorola extended format, expand to:
3021 (ex & mask) == mask && ((hi ^ bit) | ((lo | -lo) >> 31)) > val. */
3022 rtx nlo = expand_unop (imode, neg_optab, lo, NULL_RTX, 0);
3023 lo = expand_binop (imode, ior_optab, lo, nlo,
3024 NULL_RTX, 1, OPTAB_LIB_WIDEN);
3025 lo = expand_shift (RSHIFT_EXPR, imode, lo, 31, NULL_RTX, 1);
3026 temp = expand_binop (imode, xor_optab, hi, bit,
3027 NULL_RTX, 1, OPTAB_LIB_WIDEN);
3028 temp = expand_binop (imode, ior_optab, temp, lo,
3029 NULL_RTX, 1, OPTAB_LIB_WIDEN);
3030 temp = emit_store_flag_force (target, GTU, temp, val, imode, 1, 1);
3031 ex = expand_binop (iemode, and_optab, ex, mask,
3032 NULL_RTX, 1, OPTAB_LIB_WIDEN);
3033 ex = emit_store_flag_force (gen_reg_rtx (GET_MODE (temp)), EQ,
3034 ex, mask, iemode, 1, 1);
3035 temp = expand_binop (GET_MODE (temp), and_optab, temp, ex,
3036 NULL_RTX, 1, OPTAB_LIB_WIDEN);
3037 }
3038 break;
3039 default:
3040 gcc_unreachable ();
3041 }
3042
3043 return temp;
3044}
3045
3046/* Expand a call to one of the builtin rounding functions gcc defines
3047 as an extension (lfloor and lceil). As these are gcc extensions we
3048 do not need to worry about setting errno to EDOM.
3049 If expanding via optab fails, lower expression to (int)(floor(x)).
3050 EXP is the expression that is a call to the builtin function;
3051 if convenient, the result should be placed in TARGET. */
3052
3053static rtx
3054expand_builtin_int_roundingfn (tree exp, rtx target)
3055{
3056 convert_optab builtin_optab;
3057 rtx op0, tmp;
3058 rtx_insn *insns;
3059 tree fndecl = get_callee_fndecl (exp);
3060 enum built_in_function fallback_fn;
3061 tree fallback_fndecl;
3062 machine_mode mode;
3063 tree arg;
3064
3065 if (!validate_arglist (callexpr: exp, REAL_TYPE, VOID_TYPE))
3066 return NULL_RTX;
3067
3068 arg = CALL_EXPR_ARG (exp, 0);
3069
3070 switch (DECL_FUNCTION_CODE (decl: fndecl))
3071 {
3072 CASE_FLT_FN (BUILT_IN_ICEIL):
3073 CASE_FLT_FN (BUILT_IN_LCEIL):
3074 CASE_FLT_FN (BUILT_IN_LLCEIL):
3075 builtin_optab = lceil_optab;
3076 fallback_fn = BUILT_IN_CEIL;
3077 break;
3078
3079 CASE_FLT_FN (BUILT_IN_IFLOOR):
3080 CASE_FLT_FN (BUILT_IN_LFLOOR):
3081 CASE_FLT_FN (BUILT_IN_LLFLOOR):
3082 builtin_optab = lfloor_optab;
3083 fallback_fn = BUILT_IN_FLOOR;
3084 break;
3085
3086 default:
3087 gcc_unreachable ();
3088 }
3089
3090 /* Make a suitable register to place result in. */
3091 mode = TYPE_MODE (TREE_TYPE (exp));
3092
3093 target = gen_reg_rtx (mode);
3094
3095 /* Wrap the computation of the argument in a SAVE_EXPR, as we may
3096 need to expand the argument again. This way, we will not perform
3097 side-effects more the once. */
3098 CALL_EXPR_ARG (exp, 0) = arg = builtin_save_expr (exp: arg);
3099
3100 op0 = expand_expr (exp: arg, NULL, VOIDmode, modifier: EXPAND_NORMAL);
3101
3102 start_sequence ();
3103
3104 /* Compute into TARGET. */
3105 if (expand_sfix_optab (target, op0, builtin_optab))
3106 {
3107 /* Output the entire sequence. */
3108 insns = get_insns ();
3109 end_sequence ();
3110 emit_insn (insns);
3111 return target;
3112 }
3113
3114 /* If we were unable to expand via the builtin, stop the sequence
3115 (without outputting the insns). */
3116 end_sequence ();
3117
3118 /* Fall back to floating point rounding optab. */
3119 fallback_fndecl = mathfn_built_in (TREE_TYPE (arg), fn: fallback_fn);
3120
3121 /* For non-C99 targets we may end up without a fallback fndecl here
3122 if the user called __builtin_lfloor directly. In this case emit
3123 a call to the floor/ceil variants nevertheless. This should result
3124 in the best user experience for not full C99 targets. */
3125 if (fallback_fndecl == NULL_TREE)
3126 {
3127 tree fntype;
3128 const char *name = NULL;
3129
3130 switch (DECL_FUNCTION_CODE (decl: fndecl))
3131 {
3132 case BUILT_IN_ICEIL:
3133 case BUILT_IN_LCEIL:
3134 case BUILT_IN_LLCEIL:
3135 name = "ceil";
3136 break;
3137 case BUILT_IN_ICEILF:
3138 case BUILT_IN_LCEILF:
3139 case BUILT_IN_LLCEILF:
3140 name = "ceilf";
3141 break;
3142 case BUILT_IN_ICEILL:
3143 case BUILT_IN_LCEILL:
3144 case BUILT_IN_LLCEILL:
3145 name = "ceill";
3146 break;
3147 case BUILT_IN_IFLOOR:
3148 case BUILT_IN_LFLOOR:
3149 case BUILT_IN_LLFLOOR:
3150 name = "floor";
3151 break;
3152 case BUILT_IN_IFLOORF:
3153 case BUILT_IN_LFLOORF:
3154 case BUILT_IN_LLFLOORF:
3155 name = "floorf";
3156 break;
3157 case BUILT_IN_IFLOORL:
3158 case BUILT_IN_LFLOORL:
3159 case BUILT_IN_LLFLOORL:
3160 name = "floorl";
3161 break;
3162 default:
3163 gcc_unreachable ();
3164 }
3165
3166 fntype = build_function_type_list (TREE_TYPE (arg),
3167 TREE_TYPE (arg), NULL_TREE);
3168 fallback_fndecl = build_fn_decl (name, fntype);
3169 }
3170
3171 exp = build_call_nofold_loc (EXPR_LOCATION (exp), fndecl: fallback_fndecl, n: 1, arg);
3172
3173 tmp = expand_normal (exp);
3174 tmp = maybe_emit_group_store (tmp, TREE_TYPE (exp));
3175
3176 /* Truncate the result of floating point optab to integer
3177 via expand_fix (). */
3178 target = gen_reg_rtx (mode);
3179 expand_fix (target, tmp, 0);
3180
3181 return target;
3182}
3183
3184/* Expand a call to one of the builtin math functions doing integer
3185 conversion (lrint).
3186 Return 0 if a normal call should be emitted rather than expanding the
3187 function in-line. EXP is the expression that is a call to the builtin
3188 function; if convenient, the result should be placed in TARGET. */
3189
3190static rtx
3191expand_builtin_int_roundingfn_2 (tree exp, rtx target)
3192{
3193 convert_optab builtin_optab;
3194 rtx op0;
3195 rtx_insn *insns;
3196 tree fndecl = get_callee_fndecl (exp);
3197 tree arg;
3198 machine_mode mode;
3199 enum built_in_function fallback_fn = BUILT_IN_NONE;
3200
3201 if (!validate_arglist (callexpr: exp, REAL_TYPE, VOID_TYPE))
3202 return NULL_RTX;
3203
3204 arg = CALL_EXPR_ARG (exp, 0);
3205
3206 switch (DECL_FUNCTION_CODE (decl: fndecl))
3207 {
3208 CASE_FLT_FN (BUILT_IN_IRINT):
3209 fallback_fn = BUILT_IN_LRINT;
3210 gcc_fallthrough ();
3211 CASE_FLT_FN (BUILT_IN_LRINT):
3212 CASE_FLT_FN (BUILT_IN_LLRINT):
3213 builtin_optab = lrint_optab;
3214 break;
3215
3216 CASE_FLT_FN (BUILT_IN_IROUND):
3217 fallback_fn = BUILT_IN_LROUND;
3218 gcc_fallthrough ();
3219 CASE_FLT_FN (BUILT_IN_LROUND):
3220 CASE_FLT_FN (BUILT_IN_LLROUND):
3221 builtin_optab = lround_optab;
3222 break;
3223
3224 default:
3225 gcc_unreachable ();
3226 }
3227
3228 /* There's no easy way to detect the case we need to set EDOM. */
3229 if (flag_errno_math && fallback_fn == BUILT_IN_NONE)
3230 return NULL_RTX;
3231
3232 /* Make a suitable register to place result in. */
3233 mode = TYPE_MODE (TREE_TYPE (exp));
3234
3235 /* There's no easy way to detect the case we need to set EDOM. */
3236 if (!flag_errno_math)
3237 {
3238 rtx result = gen_reg_rtx (mode);
3239
3240 /* Wrap the computation of the argument in a SAVE_EXPR, as we may
3241 need to expand the argument again. This way, we will not perform
3242 side-effects more the once. */
3243 CALL_EXPR_ARG (exp, 0) = arg = builtin_save_expr (exp: arg);
3244
3245 op0 = expand_expr (exp: arg, NULL, VOIDmode, modifier: EXPAND_NORMAL);
3246
3247 start_sequence ();
3248
3249 if (expand_sfix_optab (result, op0, builtin_optab))
3250 {
3251 /* Output the entire sequence. */
3252 insns = get_insns ();
3253 end_sequence ();
3254 emit_insn (insns);
3255 return result;
3256 }
3257
3258 /* If we were unable to expand via the builtin, stop the sequence
3259 (without outputting the insns) and call to the library function
3260 with the stabilized argument list. */
3261 end_sequence ();
3262 }
3263
3264 if (fallback_fn != BUILT_IN_NONE)
3265 {
3266 /* Fall back to rounding to long int. Use implicit_p 0 - for non-C99
3267 targets, (int) round (x) should never be transformed into
3268 BUILT_IN_IROUND and if __builtin_iround is called directly, emit
3269 a call to lround in the hope that the target provides at least some
3270 C99 functions. This should result in the best user experience for
3271 not full C99 targets.
3272 As scalar float conversions with same mode are useless in GIMPLE,
3273 we can end up e.g. with _Float32 argument passed to float builtin,
3274 try to get the type from the builtin prototype first. */
3275 tree fallback_fndecl = NULL_TREE;
3276 if (tree argtypes = TYPE_ARG_TYPES (TREE_TYPE (fndecl)))
3277 fallback_fndecl
3278 = mathfn_built_in_1 (TREE_VALUE (argtypes),
3279 fn: as_combined_fn (fn: fallback_fn), implicit_p: 0);
3280 if (fallback_fndecl == NULL_TREE)
3281 fallback_fndecl
3282 = mathfn_built_in_1 (TREE_TYPE (arg),
3283 fn: as_combined_fn (fn: fallback_fn), implicit_p: 0);
3284 if (fallback_fndecl)
3285 {
3286 exp = build_call_nofold_loc (EXPR_LOCATION (exp),
3287 fndecl: fallback_fndecl, n: 1, arg);
3288
3289 target = expand_call (exp, NULL_RTX, target == const0_rtx);
3290 target = maybe_emit_group_store (target, TREE_TYPE (exp));
3291 return convert_to_mode (mode, target, 0);
3292 }
3293 }
3294
3295 return expand_call (exp, target, target == const0_rtx);
3296}
3297
3298/* Expand a call to the powi built-in mathematical function. Return NULL_RTX if
3299 a normal call should be emitted rather than expanding the function
3300 in-line. EXP is the expression that is a call to the builtin
3301 function; if convenient, the result should be placed in TARGET. */
3302
3303static rtx
3304expand_builtin_powi (tree exp, rtx target)
3305{
3306 tree arg0, arg1;
3307 rtx op0, op1;
3308 machine_mode mode;
3309 machine_mode mode2;
3310
3311 if (! validate_arglist (callexpr: exp, REAL_TYPE, INTEGER_TYPE, VOID_TYPE))
3312 return NULL_RTX;
3313
3314 arg0 = CALL_EXPR_ARG (exp, 0);
3315 arg1 = CALL_EXPR_ARG (exp, 1);
3316 mode = TYPE_MODE (TREE_TYPE (exp));
3317
3318 /* Emit a libcall to libgcc. */
3319
3320 /* Mode of the 2nd argument must match that of an int. */
3321 mode2 = int_mode_for_size (INT_TYPE_SIZE, limit: 0).require ();
3322
3323 if (target == NULL_RTX)
3324 target = gen_reg_rtx (mode);
3325
3326 op0 = expand_expr (exp: arg0, NULL_RTX, mode, modifier: EXPAND_NORMAL);
3327 if (GET_MODE (op0) != mode)
3328 op0 = convert_to_mode (mode, op0, 0);
3329 op1 = expand_expr (exp: arg1, NULL_RTX, mode: mode2, modifier: EXPAND_NORMAL);
3330 if (GET_MODE (op1) != mode2)
3331 op1 = convert_to_mode (mode2, op1, 0);
3332
3333 target = emit_library_call_value (fun: optab_libfunc (powi_optab, mode),
3334 value: target, fn_type: LCT_CONST, outmode: mode,
3335 arg1: op0, arg1_mode: mode, arg2: op1, arg2_mode: mode2);
3336
3337 return target;
3338}
3339
3340/* Expand expression EXP which is a call to the strlen builtin. Return
3341 NULL_RTX if we failed and the caller should emit a normal call, otherwise
3342 try to get the result in TARGET, if convenient. */
3343
3344static rtx
3345expand_builtin_strlen (tree exp, rtx target,
3346 machine_mode target_mode)
3347{
3348 if (!validate_arglist (callexpr: exp, POINTER_TYPE, VOID_TYPE))
3349 return NULL_RTX;
3350
3351 tree src = CALL_EXPR_ARG (exp, 0);
3352
3353 /* If the length can be computed at compile-time, return it. */
3354 if (tree len = c_strlen (arg: src, only_value: 0))
3355 return expand_expr (exp: len, target, mode: target_mode, modifier: EXPAND_NORMAL);
3356
3357 /* If the length can be computed at compile-time and is constant
3358 integer, but there are side-effects in src, evaluate
3359 src for side-effects, then return len.
3360 E.g. x = strlen (i++ ? "xfoo" + 1 : "bar");
3361 can be optimized into: i++; x = 3; */
3362 tree len = c_strlen (arg: src, only_value: 1);
3363 if (len && TREE_CODE (len) == INTEGER_CST)
3364 {
3365 expand_expr (exp: src, const0_rtx, VOIDmode, modifier: EXPAND_NORMAL);
3366 return expand_expr (exp: len, target, mode: target_mode, modifier: EXPAND_NORMAL);
3367 }
3368
3369 unsigned int align = get_pointer_alignment (exp: src) / BITS_PER_UNIT;
3370
3371 /* If SRC is not a pointer type, don't do this operation inline. */
3372 if (align == 0)
3373 return NULL_RTX;
3374
3375 /* Bail out if we can't compute strlen in the right mode. */
3376 machine_mode insn_mode;
3377 enum insn_code icode = CODE_FOR_nothing;
3378 FOR_EACH_MODE_FROM (insn_mode, target_mode)
3379 {
3380 icode = optab_handler (op: strlen_optab, mode: insn_mode);
3381 if (icode != CODE_FOR_nothing)
3382 break;
3383 }
3384 if (insn_mode == VOIDmode)
3385 return NULL_RTX;
3386
3387 /* Make a place to hold the source address. We will not expand
3388 the actual source until we are sure that the expansion will
3389 not fail -- there are trees that cannot be expanded twice. */
3390 rtx src_reg = gen_reg_rtx (Pmode);
3391
3392 /* Mark the beginning of the strlen sequence so we can emit the
3393 source operand later. */
3394 rtx_insn *before_strlen = get_last_insn ();
3395
3396 class expand_operand ops[4];
3397 create_output_operand (op: &ops[0], x: target, mode: insn_mode);
3398 create_fixed_operand (op: &ops[1], x: gen_rtx_MEM (BLKmode, src_reg));
3399 create_integer_operand (&ops[2], 0);
3400 create_integer_operand (&ops[3], align);
3401 if (!maybe_expand_insn (icode, nops: 4, ops))
3402 return NULL_RTX;
3403
3404 /* Check to see if the argument was declared attribute nonstring
3405 and if so, issue a warning since at this point it's not known
3406 to be nul-terminated. */
3407 maybe_warn_nonstring_arg (get_callee_fndecl (exp), exp);
3408
3409 /* Now that we are assured of success, expand the source. */
3410 start_sequence ();
3411 rtx pat = expand_expr (exp: src, target: src_reg, Pmode, modifier: EXPAND_NORMAL);
3412 if (pat != src_reg)
3413 {
3414#ifdef POINTERS_EXTEND_UNSIGNED
3415 if (GET_MODE (pat) != Pmode)
3416 pat = convert_to_mode (Pmode, pat,
3417 POINTERS_EXTEND_UNSIGNED);
3418#endif
3419 emit_move_insn (src_reg, pat);
3420 }
3421 pat = get_insns ();
3422 end_sequence ();
3423
3424 if (before_strlen)
3425 emit_insn_after (pat, before_strlen);
3426 else
3427 emit_insn_before (pat, get_insns ());
3428
3429 /* Return the value in the proper mode for this function. */
3430 if (GET_MODE (ops[0].value) == target_mode)
3431 target = ops[0].value;
3432 else if (target != 0)
3433 convert_move (target, ops[0].value, 0);
3434 else
3435 target = convert_to_mode (target_mode, ops[0].value, 0);
3436
3437 return target;
3438}
3439
3440/* Expand call EXP to the strnlen built-in, returning the result
3441 and setting it in TARGET. Otherwise return NULL_RTX on failure. */
3442
3443static rtx
3444expand_builtin_strnlen (tree exp, rtx target, machine_mode target_mode)
3445{
3446 if (!validate_arglist (callexpr: exp, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
3447 return NULL_RTX;
3448
3449 tree src = CALL_EXPR_ARG (exp, 0);
3450 tree bound = CALL_EXPR_ARG (exp, 1);
3451
3452 if (!bound)
3453 return NULL_RTX;
3454
3455 location_t loc = UNKNOWN_LOCATION;
3456 if (EXPR_HAS_LOCATION (exp))
3457 loc = EXPR_LOCATION (exp);
3458
3459 /* FIXME: Change c_strlen() to return sizetype instead of ssizetype
3460 so these conversions aren't necessary. */
3461 c_strlen_data lendata = { };
3462 tree len = c_strlen (arg: src, only_value: 0, data: &lendata, eltsize: 1);
3463 if (len)
3464 len = fold_convert_loc (loc, TREE_TYPE (bound), len);
3465
3466 if (TREE_CODE (bound) == INTEGER_CST)
3467 {
3468 if (!len)
3469 return NULL_RTX;
3470
3471 len = fold_build2_loc (loc, MIN_EXPR, size_type_node, len, bound);
3472 return expand_expr (exp: len, target, mode: target_mode, modifier: EXPAND_NORMAL);
3473 }
3474
3475 if (TREE_CODE (bound) != SSA_NAME)
3476 return NULL_RTX;
3477
3478 wide_int min, max;
3479 value_range r;
3480 get_global_range_query ()->range_of_expr (r, expr: bound);
3481 if (r.varying_p () || r.undefined_p ())
3482 return NULL_RTX;
3483 min = r.lower_bound ();
3484 max = r.upper_bound ();
3485
3486 if (!len || TREE_CODE (len) != INTEGER_CST)
3487 {
3488 bool exact;
3489 lendata.decl = unterminated_array (src, &len, &exact);
3490 if (!lendata.decl)
3491 return NULL_RTX;
3492 }
3493
3494 if (lendata.decl)
3495 return NULL_RTX;
3496
3497 if (wi::gtu_p (x: min, y: wi::to_wide (t: len)))
3498 return expand_expr (exp: len, target, mode: target_mode, modifier: EXPAND_NORMAL);
3499
3500 len = fold_build2_loc (loc, MIN_EXPR, TREE_TYPE (len), len, bound);
3501 return expand_expr (exp: len, target, mode: target_mode, modifier: EXPAND_NORMAL);
3502}
3503
3504/* Callback routine for store_by_pieces. Read GET_MODE_BITSIZE (MODE)
3505 bytes from bytes at DATA + OFFSET and return it reinterpreted as
3506 a target constant. */
3507
3508static rtx
3509builtin_memcpy_read_str (void *data, void *, HOST_WIDE_INT offset,
3510 fixed_size_mode mode)
3511{
3512 /* The REPresentation pointed to by DATA need not be a nul-terminated
3513 string but the caller guarantees it's large enough for MODE. */
3514 const char *rep = (const char *) data;
3515
3516 return c_readstr (str: rep + offset, mode, /*nul_terminated=*/null_terminated_p: false);
3517}
3518
3519/* LEN specify length of the block of memcpy/memset operation.
3520 Figure out its range and put it into MIN_SIZE/MAX_SIZE.
3521 In some cases we can make very likely guess on max size, then we
3522 set it into PROBABLE_MAX_SIZE. */
3523
3524static void
3525determine_block_size (tree len, rtx len_rtx,
3526 unsigned HOST_WIDE_INT *min_size,
3527 unsigned HOST_WIDE_INT *max_size,
3528 unsigned HOST_WIDE_INT *probable_max_size)
3529{
3530 if (CONST_INT_P (len_rtx))
3531 {
3532 *min_size = *max_size = *probable_max_size = UINTVAL (len_rtx);
3533 return;
3534 }
3535 else
3536 {
3537 wide_int min, max;
3538 enum value_range_kind range_type = VR_UNDEFINED;
3539
3540 /* Determine bounds from the type. */
3541 if (tree_fits_uhwi_p (TYPE_MIN_VALUE (TREE_TYPE (len))))
3542 *min_size = tree_to_uhwi (TYPE_MIN_VALUE (TREE_TYPE (len)));
3543 else
3544 *min_size = 0;
3545 if (tree_fits_uhwi_p (TYPE_MAX_VALUE (TREE_TYPE (len))))
3546 *probable_max_size = *max_size
3547 = tree_to_uhwi (TYPE_MAX_VALUE (TREE_TYPE (len)));
3548 else
3549 *probable_max_size = *max_size = GET_MODE_MASK (GET_MODE (len_rtx));
3550
3551 if (TREE_CODE (len) == SSA_NAME)
3552 {
3553 value_range r;
3554 tree tmin, tmax;
3555 get_global_range_query ()->range_of_expr (r, expr: len);
3556 range_type = get_legacy_range (r, min&: tmin, max&: tmax);
3557 if (range_type != VR_UNDEFINED)
3558 {
3559 min = wi::to_wide (t: tmin);
3560 max = wi::to_wide (t: tmax);
3561 }
3562 }
3563 if (range_type == VR_RANGE)
3564 {
3565 if (wi::fits_uhwi_p (x: min) && *min_size < min.to_uhwi ())
3566 *min_size = min.to_uhwi ();
3567 if (wi::fits_uhwi_p (x: max) && *max_size > max.to_uhwi ())
3568 *probable_max_size = *max_size = max.to_uhwi ();
3569 }
3570 else if (range_type == VR_ANTI_RANGE)
3571 {
3572 /* Code like
3573
3574 int n;
3575 if (n < 100)
3576 memcpy (a, b, n)
3577
3578 Produce anti range allowing negative values of N. We still
3579 can use the information and make a guess that N is not negative.
3580 */
3581 if (!wi::leu_p (x: max, y: 1 << 30) && wi::fits_uhwi_p (x: min))
3582 *probable_max_size = min.to_uhwi () - 1;
3583 }
3584 }
3585 gcc_checking_assert (*max_size <=
3586 (unsigned HOST_WIDE_INT)
3587 GET_MODE_MASK (GET_MODE (len_rtx)));
3588}
3589
3590/* Expand a call EXP to the memcpy builtin.
3591 Return NULL_RTX if we failed, the caller should emit a normal call,
3592 otherwise try to get the result in TARGET, if convenient (and in
3593 mode MODE if that's convenient). */
3594
3595static rtx
3596expand_builtin_memcpy (tree exp, rtx target)
3597{
3598 if (!validate_arglist (callexpr: exp,
3599 POINTER_TYPE, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
3600 return NULL_RTX;
3601
3602 tree dest = CALL_EXPR_ARG (exp, 0);
3603 tree src = CALL_EXPR_ARG (exp, 1);
3604 tree len = CALL_EXPR_ARG (exp, 2);
3605
3606 return expand_builtin_memory_copy_args (dest, src, len, target, exp,
3607 /*retmode=*/ RETURN_BEGIN, might_overlap: false);
3608}
3609
3610/* Check a call EXP to the memmove built-in for validity.
3611 Return NULL_RTX on both success and failure. */
3612
3613static rtx
3614expand_builtin_memmove (tree exp, rtx target)
3615{
3616 if (!validate_arglist (callexpr: exp,
3617 POINTER_TYPE, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
3618 return NULL_RTX;
3619
3620 tree dest = CALL_EXPR_ARG (exp, 0);
3621 tree src = CALL_EXPR_ARG (exp, 1);
3622 tree len = CALL_EXPR_ARG (exp, 2);
3623
3624 return expand_builtin_memory_copy_args (dest, src, len, target, exp,
3625 /*retmode=*/ RETURN_BEGIN, might_overlap: true);
3626}
3627
3628/* Expand a call EXP to the mempcpy builtin.
3629 Return NULL_RTX if we failed; the caller should emit a normal call,
3630 otherwise try to get the result in TARGET, if convenient (and in
3631 mode MODE if that's convenient). */
3632
3633static rtx
3634expand_builtin_mempcpy (tree exp, rtx target)
3635{
3636 if (!validate_arglist (callexpr: exp,
3637 POINTER_TYPE, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
3638 return NULL_RTX;
3639
3640 tree dest = CALL_EXPR_ARG (exp, 0);
3641 tree src = CALL_EXPR_ARG (exp, 1);
3642 tree len = CALL_EXPR_ARG (exp, 2);
3643
3644 /* Policy does not generally allow using compute_objsize (which
3645 is used internally by check_memop_size) to change code generation
3646 or drive optimization decisions.
3647
3648 In this instance it is safe because the code we generate has
3649 the same semantics regardless of the return value of
3650 check_memop_sizes. Exactly the same amount of data is copied
3651 and the return value is exactly the same in both cases.
3652
3653 Furthermore, check_memop_size always uses mode 0 for the call to
3654 compute_objsize, so the imprecise nature of compute_objsize is
3655 avoided. */
3656
3657 /* Avoid expanding mempcpy into memcpy when the call is determined
3658 to overflow the buffer. This also prevents the same overflow
3659 from being diagnosed again when expanding memcpy. */
3660
3661 return expand_builtin_mempcpy_args (dest, src, len,
3662 target, exp, /*retmode=*/ RETURN_END);
3663}
3664
3665/* Helper function to do the actual work for expand of memory copy family
3666 functions (memcpy, mempcpy, stpcpy). Expansing should assign LEN bytes
3667 of memory from SRC to DEST and assign to TARGET if convenient. Return
3668 value is based on RETMODE argument. */
3669
3670static rtx
3671expand_builtin_memory_copy_args (tree dest, tree src, tree len,
3672 rtx target, tree exp, memop_ret retmode,
3673 bool might_overlap)
3674{
3675 unsigned int src_align = get_pointer_alignment (exp: src);
3676 unsigned int dest_align = get_pointer_alignment (exp: dest);
3677 rtx dest_mem, src_mem, dest_addr, len_rtx;
3678 HOST_WIDE_INT expected_size = -1;
3679 unsigned int expected_align = 0;
3680 unsigned HOST_WIDE_INT min_size;
3681 unsigned HOST_WIDE_INT max_size;
3682 unsigned HOST_WIDE_INT probable_max_size;
3683
3684 bool is_move_done;
3685
3686 /* If DEST is not a pointer type, call the normal function. */
3687 if (dest_align == 0)
3688 return NULL_RTX;
3689
3690 /* If either SRC is not a pointer type, don't do this
3691 operation in-line. */
3692 if (src_align == 0)
3693 return NULL_RTX;
3694
3695 if (currently_expanding_gimple_stmt)
3696 stringop_block_profile (currently_expanding_gimple_stmt,
3697 &expected_align, &expected_size);
3698
3699 if (expected_align < dest_align)
3700 expected_align = dest_align;
3701 dest_mem = get_memory_rtx (exp: dest, len);
3702 set_mem_align (dest_mem, dest_align);
3703 len_rtx = expand_normal (exp: len);
3704 determine_block_size (len, len_rtx, min_size: &min_size, max_size: &max_size,
3705 probable_max_size: &probable_max_size);
3706
3707 /* Try to get the byte representation of the constant SRC points to,
3708 with its byte size in NBYTES. */
3709 unsigned HOST_WIDE_INT nbytes;
3710 const char *rep = getbyterep (src, &nbytes);
3711
3712 /* If the function's constant bound LEN_RTX is less than or equal
3713 to the byte size of the representation of the constant argument,
3714 and if block move would be done by pieces, we can avoid loading
3715 the bytes from memory and only store the computed constant.
3716 This works in the overlap (memmove) case as well because
3717 store_by_pieces just generates a series of stores of constants
3718 from the representation returned by getbyterep(). */
3719 if (rep
3720 && CONST_INT_P (len_rtx)
3721 && (unsigned HOST_WIDE_INT) INTVAL (len_rtx) <= nbytes
3722 && can_store_by_pieces (INTVAL (len_rtx), builtin_memcpy_read_str,
3723 CONST_CAST (char *, rep),
3724 dest_align, false))
3725 {
3726 dest_mem = store_by_pieces (dest_mem, INTVAL (len_rtx),
3727 builtin_memcpy_read_str,
3728 CONST_CAST (char *, rep),
3729 dest_align, false, retmode);
3730 dest_mem = force_operand (XEXP (dest_mem, 0), target);
3731 dest_mem = convert_memory_address (ptr_mode, dest_mem);
3732 return dest_mem;
3733 }
3734
3735 src_mem = get_memory_rtx (exp: src, len);
3736 set_mem_align (src_mem, src_align);
3737
3738 /* Copy word part most expediently. */
3739 enum block_op_methods method = BLOCK_OP_NORMAL;
3740 if (CALL_EXPR_TAILCALL (exp)
3741 && (retmode == RETURN_BEGIN || target == const0_rtx))
3742 method = BLOCK_OP_TAILCALL;
3743 bool use_mempcpy_call = (targetm.libc_has_fast_function (BUILT_IN_MEMPCPY)
3744 && retmode == RETURN_END
3745 && !might_overlap
3746 && target != const0_rtx);
3747 if (use_mempcpy_call)
3748 method = BLOCK_OP_NO_LIBCALL_RET;
3749 dest_addr = emit_block_move_hints (dest_mem, src_mem, len_rtx, method,
3750 expected_align, expected_size,
3751 min_size, max_size, probable_max_size,
3752 bail_out_libcall: use_mempcpy_call, is_move_done: &is_move_done,
3753 might_overlap);
3754
3755 /* Bail out when a mempcpy call would be expanded as libcall and when
3756 we have a target that provides a fast implementation
3757 of mempcpy routine. */
3758 if (!is_move_done)
3759 return NULL_RTX;
3760
3761 if (dest_addr == pc_rtx)
3762 return NULL_RTX;
3763
3764 if (dest_addr == 0)
3765 {
3766 dest_addr = force_operand (XEXP (dest_mem, 0), target);
3767 dest_addr = convert_memory_address (ptr_mode, dest_addr);
3768 }
3769
3770 if (retmode != RETURN_BEGIN && target != const0_rtx)
3771 {
3772 dest_addr = gen_rtx_PLUS (ptr_mode, dest_addr, len_rtx);
3773 /* stpcpy pointer to last byte. */
3774 if (retmode == RETURN_END_MINUS_ONE)
3775 dest_addr = gen_rtx_MINUS (ptr_mode, dest_addr, const1_rtx);
3776 }
3777
3778 return dest_addr;
3779}
3780
3781static rtx
3782expand_builtin_mempcpy_args (tree dest, tree src, tree len,
3783 rtx target, tree orig_exp, memop_ret retmode)
3784{
3785 return expand_builtin_memory_copy_args (dest, src, len, target, exp: orig_exp,
3786 retmode, might_overlap: false);
3787}
3788
3789/* Expand into a movstr instruction, if one is available. Return NULL_RTX if
3790 we failed, the caller should emit a normal call, otherwise try to
3791 get the result in TARGET, if convenient.
3792 Return value is based on RETMODE argument. */
3793
3794static rtx
3795expand_movstr (tree dest, tree src, rtx target, memop_ret retmode)
3796{
3797 class expand_operand ops[3];
3798 rtx dest_mem;
3799 rtx src_mem;
3800
3801 if (!targetm.have_movstr ())
3802 return NULL_RTX;
3803
3804 dest_mem = get_memory_rtx (exp: dest, NULL);
3805 src_mem = get_memory_rtx (exp: src, NULL);
3806 if (retmode == RETURN_BEGIN)
3807 {
3808 target = force_reg (Pmode, XEXP (dest_mem, 0));
3809 dest_mem = replace_equiv_address (dest_mem, target);
3810 }
3811
3812 create_output_operand (op: &ops[0],
3813 x: retmode != RETURN_BEGIN ? target : NULL_RTX, Pmode);
3814 create_fixed_operand (op: &ops[1], x: dest_mem);
3815 create_fixed_operand (op: &ops[2], x: src_mem);
3816 if (!maybe_expand_insn (icode: targetm.code_for_movstr, nops: 3, ops))
3817 return NULL_RTX;
3818
3819 if (retmode != RETURN_BEGIN && target != const0_rtx)
3820 {
3821 target = ops[0].value;
3822 /* movstr is supposed to set end to the address of the NUL
3823 terminator. If the caller requested a mempcpy-like return value,
3824 adjust it. */
3825 if (retmode == RETURN_END)
3826 {
3827 rtx tem = plus_constant (GET_MODE (target),
3828 gen_lowpart (GET_MODE (target), target), 1);
3829 emit_move_insn (target, force_operand (tem, NULL_RTX));
3830 }
3831 }
3832 return target;
3833}
3834
3835/* Expand expression EXP, which is a call to the strcpy builtin. Return
3836 NULL_RTX if we failed the caller should emit a normal call, otherwise
3837 try to get the result in TARGET, if convenient (and in mode MODE if that's
3838 convenient). */
3839
3840static rtx
3841expand_builtin_strcpy (tree exp, rtx target)
3842{
3843 if (!validate_arglist (callexpr: exp, POINTER_TYPE, POINTER_TYPE, VOID_TYPE))
3844 return NULL_RTX;
3845
3846 tree dest = CALL_EXPR_ARG (exp, 0);
3847 tree src = CALL_EXPR_ARG (exp, 1);
3848
3849 return expand_builtin_strcpy_args (exp, dest, src, target);
3850}
3851
3852/* Helper function to do the actual work for expand_builtin_strcpy. The
3853 arguments to the builtin_strcpy call DEST and SRC are broken out
3854 so that this can also be called without constructing an actual CALL_EXPR.
3855 The other arguments and return value are the same as for
3856 expand_builtin_strcpy. */
3857
3858static rtx
3859expand_builtin_strcpy_args (tree, tree dest, tree src, rtx target)
3860{
3861 return expand_movstr (dest, src, target, /*retmode=*/ RETURN_BEGIN);
3862}
3863
3864/* Expand a call EXP to the stpcpy builtin.
3865 Return NULL_RTX if we failed the caller should emit a normal call,
3866 otherwise try to get the result in TARGET, if convenient (and in
3867 mode MODE if that's convenient). */
3868
3869static rtx
3870expand_builtin_stpcpy_1 (tree exp, rtx target, machine_mode mode)
3871{
3872 tree dst, src;
3873 location_t loc = EXPR_LOCATION (exp);
3874
3875 if (!validate_arglist (callexpr: exp, POINTER_TYPE, POINTER_TYPE, VOID_TYPE))
3876 return NULL_RTX;
3877
3878 dst = CALL_EXPR_ARG (exp, 0);
3879 src = CALL_EXPR_ARG (exp, 1);
3880
3881 /* If return value is ignored, transform stpcpy into strcpy. */
3882 if (target == const0_rtx && builtin_decl_implicit (fncode: BUILT_IN_STRCPY))
3883 {
3884 tree fn = builtin_decl_implicit (fncode: BUILT_IN_STRCPY);
3885 tree result = build_call_nofold_loc (loc, fndecl: fn, n: 2, dst, src);
3886 return expand_expr (exp: result, target, mode, modifier: EXPAND_NORMAL);
3887 }
3888 else
3889 {
3890 tree len, lenp1;
3891 rtx ret;
3892
3893 /* Ensure we get an actual string whose length can be evaluated at
3894 compile-time, not an expression containing a string. This is
3895 because the latter will potentially produce pessimized code
3896 when used to produce the return value. */
3897 c_strlen_data lendata = { };
3898 if (!c_getstr (src)
3899 || !(len = c_strlen (arg: src, only_value: 0, data: &lendata, eltsize: 1)))
3900 return expand_movstr (dest: dst, src, target,
3901 /*retmode=*/ RETURN_END_MINUS_ONE);
3902
3903 lenp1 = size_binop_loc (loc, PLUS_EXPR, len, ssize_int (1));
3904 ret = expand_builtin_mempcpy_args (dest: dst, src, len: lenp1,
3905 target, orig_exp: exp,
3906 /*retmode=*/ RETURN_END_MINUS_ONE);
3907
3908 if (ret)
3909 return ret;
3910
3911 if (TREE_CODE (len) == INTEGER_CST)
3912 {
3913 rtx len_rtx = expand_normal (exp: len);
3914
3915 if (CONST_INT_P (len_rtx))
3916 {
3917 ret = expand_builtin_strcpy_args (exp, dest: dst, src, target);
3918
3919 if (ret)
3920 {
3921 if (! target)
3922 {
3923 if (mode != VOIDmode)
3924 target = gen_reg_rtx (mode);
3925 else
3926 target = gen_reg_rtx (GET_MODE (ret));
3927 }
3928 if (GET_MODE (target) != GET_MODE (ret))
3929 ret = gen_lowpart (GET_MODE (target), ret);
3930
3931 ret = plus_constant (GET_MODE (ret), ret, INTVAL (len_rtx));
3932 ret = emit_move_insn (target, force_operand (ret, NULL_RTX));
3933 gcc_assert (ret);
3934
3935 return target;
3936 }
3937 }
3938 }
3939
3940 return expand_movstr (dest: dst, src, target,
3941 /*retmode=*/ RETURN_END_MINUS_ONE);
3942 }
3943}
3944
3945/* Expand a call EXP to the stpcpy builtin and diagnose uses of nonstring
3946 arguments while being careful to avoid duplicate warnings (which could
3947 be issued if the expander were to expand the call, resulting in it
3948 being emitted in expand_call(). */
3949
3950static rtx
3951expand_builtin_stpcpy (tree exp, rtx target, machine_mode mode)
3952{
3953 if (rtx ret = expand_builtin_stpcpy_1 (exp, target, mode))
3954 {
3955 /* The call has been successfully expanded. Check for nonstring
3956 arguments and issue warnings as appropriate. */
3957 maybe_warn_nonstring_arg (get_callee_fndecl (exp), exp);
3958 return ret;
3959 }
3960
3961 return NULL_RTX;
3962}
3963
3964/* Callback routine for store_by_pieces. Read GET_MODE_BITSIZE (MODE)
3965 bytes from constant string DATA + OFFSET and return it as target
3966 constant. */
3967
3968rtx
3969builtin_strncpy_read_str (void *data, void *, HOST_WIDE_INT offset,
3970 fixed_size_mode mode)
3971{
3972 const char *str = (const char *) data;
3973
3974 if ((unsigned HOST_WIDE_INT) offset > strlen (s: str))
3975 return const0_rtx;
3976
3977 return c_readstr (str: str + offset, mode);
3978}
3979
3980/* Helper to check the sizes of sequences and the destination of calls
3981 to __builtin_strncat and __builtin___strncat_chk. Returns true on
3982 success (no overflow or invalid sizes), false otherwise. */
3983
3984static bool
3985check_strncat_sizes (tree exp, tree objsize)
3986{
3987 tree dest = CALL_EXPR_ARG (exp, 0);
3988 tree src = CALL_EXPR_ARG (exp, 1);
3989 tree maxread = CALL_EXPR_ARG (exp, 2);
3990
3991 /* Try to determine the range of lengths that the source expression
3992 refers to. */
3993 c_strlen_data lendata = { };
3994 get_range_strlen (src, &lendata, /* eltsize = */ 1);
3995
3996 /* Try to verify that the destination is big enough for the shortest
3997 string. */
3998
3999 access_data data (nullptr, exp, access_read_write, maxread, true);
4000 if (!objsize && warn_stringop_overflow)
4001 {
4002 /* If it hasn't been provided by __strncat_chk, try to determine
4003 the size of the destination object into which the source is
4004 being copied. */
4005 objsize = compute_objsize (ptr: dest, warn_stringop_overflow - 1, pref: &data.dst);
4006 }
4007
4008 /* Add one for the terminating nul. */
4009 tree srclen = (lendata.minlen
4010 ? fold_build2 (PLUS_EXPR, size_type_node, lendata.minlen,
4011 size_one_node)
4012 : NULL_TREE);
4013
4014 /* The strncat function copies at most MAXREAD bytes and always appends
4015 the terminating nul so the specified upper bound should never be equal
4016 to (or greater than) the size of the destination. */
4017 if (tree_fits_uhwi_p (maxread) && tree_fits_uhwi_p (objsize)
4018 && tree_int_cst_equal (objsize, maxread))
4019 {
4020 location_t loc = EXPR_LOCATION (exp);
4021 warning_at (loc, OPT_Wstringop_overflow_,
4022 "%qD specified bound %E equals destination size",
4023 get_callee_fndecl (exp), maxread);
4024
4025 return false;
4026 }
4027
4028 if (!srclen
4029 || (maxread && tree_fits_uhwi_p (maxread)
4030 && tree_fits_uhwi_p (srclen)
4031 && tree_int_cst_lt (t1: maxread, t2: srclen)))
4032 srclen = maxread;
4033
4034 /* The number of bytes to write is LEN but check_access will alsoa
4035 check SRCLEN if LEN's value isn't known. */
4036 return check_access (exp, /*dstwrite=*/NULL_TREE, maxread, srclen,
4037 objsize, data.mode, &data);
4038}
4039
4040/* Expand expression EXP, which is a call to the strncpy builtin. Return
4041 NULL_RTX if we failed the caller should emit a normal call. */
4042
4043static rtx
4044expand_builtin_strncpy (tree exp, rtx target)
4045{
4046 location_t loc = EXPR_LOCATION (exp);
4047
4048 if (!validate_arglist (callexpr: exp,
4049 POINTER_TYPE, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
4050 return NULL_RTX;
4051 tree dest = CALL_EXPR_ARG (exp, 0);
4052 tree src = CALL_EXPR_ARG (exp, 1);
4053 /* The number of bytes to write (not the maximum). */
4054 tree len = CALL_EXPR_ARG (exp, 2);
4055
4056 /* The length of the source sequence. */
4057 tree slen = c_strlen (arg: src, only_value: 1);
4058
4059 /* We must be passed a constant len and src parameter. */
4060 if (!tree_fits_uhwi_p (len) || !slen || !tree_fits_uhwi_p (slen))
4061 return NULL_RTX;
4062
4063 slen = size_binop_loc (loc, PLUS_EXPR, slen, ssize_int (1));
4064
4065 /* We're required to pad with trailing zeros if the requested
4066 len is greater than strlen(s2)+1. In that case try to
4067 use store_by_pieces, if it fails, punt. */
4068 if (tree_int_cst_lt (t1: slen, t2: len))
4069 {
4070 unsigned int dest_align = get_pointer_alignment (exp: dest);
4071 const char *p = c_getstr (src);
4072 rtx dest_mem;
4073
4074 if (!p || dest_align == 0 || !tree_fits_uhwi_p (len)
4075 || !can_store_by_pieces (tree_to_uhwi (len),
4076 builtin_strncpy_read_str,
4077 CONST_CAST (char *, p),
4078 dest_align, false))
4079 return NULL_RTX;
4080
4081 dest_mem = get_memory_rtx (exp: dest, len);
4082 store_by_pieces (dest_mem, tree_to_uhwi (len),
4083 builtin_strncpy_read_str,
4084 CONST_CAST (char *, p), dest_align, false,
4085 RETURN_BEGIN);
4086 dest_mem = force_operand (XEXP (dest_mem, 0), target);
4087 dest_mem = convert_memory_address (ptr_mode, dest_mem);
4088 return dest_mem;
4089 }
4090
4091 return NULL_RTX;
4092}
4093
4094/* Return the RTL of a register in MODE generated from PREV in the
4095 previous iteration. */
4096
4097static rtx
4098gen_memset_value_from_prev (by_pieces_prev *prev, fixed_size_mode mode)
4099{
4100 rtx target = nullptr;
4101 if (prev != nullptr && prev->data != nullptr)
4102 {
4103 /* Use the previous data in the same mode. */
4104 if (prev->mode == mode)
4105 return prev->data;
4106
4107 fixed_size_mode prev_mode = prev->mode;
4108
4109 /* Don't use the previous data to write QImode if it is in a
4110 vector mode. */
4111 if (VECTOR_MODE_P (prev_mode) && mode == QImode)
4112 return target;
4113
4114 rtx prev_rtx = prev->data;
4115
4116 if (REG_P (prev_rtx)
4117 && HARD_REGISTER_P (prev_rtx)
4118 && lowpart_subreg_regno (REGNO (prev_rtx), prev_mode, mode) < 0)
4119 {
4120 /* This case occurs when PREV_MODE is a vector and when
4121 MODE is too small to store using vector operations.
4122 After register allocation, the code will need to move the
4123 lowpart of the vector register into a non-vector register.
4124
4125 Also, the target has chosen to use a hard register
4126 instead of going with the default choice of using a
4127 pseudo register. We should respect that choice and try to
4128 avoid creating a pseudo register with the same mode as the
4129 current hard register.
4130
4131 In principle, we could just use a lowpart MODE subreg of
4132 the vector register. However, the vector register mode might
4133 be too wide for non-vector registers, and we already know
4134 that the non-vector mode is too small for vector registers.
4135 It's therefore likely that we'd need to spill to memory in
4136 the vector mode and reload the non-vector value from there.
4137
4138 Try to avoid that by reducing the vector register to the
4139 smallest size that it can hold. This should increase the
4140 chances that non-vector registers can hold both the inner
4141 and outer modes of the subreg that we generate later. */
4142 machine_mode m;
4143 fixed_size_mode candidate;
4144 FOR_EACH_MODE_IN_CLASS (m, GET_MODE_CLASS (mode))
4145 if (is_a<fixed_size_mode> (m, result: &candidate))
4146 {
4147 if (GET_MODE_SIZE (mode: candidate)
4148 >= GET_MODE_SIZE (mode: prev_mode))
4149 break;
4150 if (GET_MODE_SIZE (mode: candidate) >= GET_MODE_SIZE (mode)
4151 && lowpart_subreg_regno (REGNO (prev_rtx),
4152 prev_mode, candidate) >= 0)
4153 {
4154 target = lowpart_subreg (outermode: candidate, op: prev_rtx,
4155 innermode: prev_mode);
4156 prev_rtx = target;
4157 prev_mode = candidate;
4158 break;
4159 }
4160 }
4161 if (target == nullptr)
4162 prev_rtx = copy_to_reg (prev_rtx);
4163 }
4164
4165 target = lowpart_subreg (outermode: mode, op: prev_rtx, innermode: prev_mode);
4166 }
4167 return target;
4168}
4169
4170/* Callback routine for store_by_pieces. Read GET_MODE_BITSIZE (MODE)
4171 bytes from constant string DATA + OFFSET and return it as target
4172 constant. If PREV isn't nullptr, it has the RTL info from the
4173 previous iteration. */
4174
4175rtx
4176builtin_memset_read_str (void *data, void *prev,
4177 HOST_WIDE_INT offset ATTRIBUTE_UNUSED,
4178 fixed_size_mode mode)
4179{
4180 const char *c = (const char *) data;
4181 unsigned int size = GET_MODE_SIZE (mode);
4182
4183 rtx target = gen_memset_value_from_prev (prev: (by_pieces_prev *) prev,
4184 mode);
4185 if (target != nullptr)
4186 return target;
4187 rtx src = gen_int_mode (*c, QImode);
4188
4189 if (VECTOR_MODE_P (mode))
4190 {
4191 gcc_assert (GET_MODE_INNER (mode) == QImode);
4192
4193 rtx const_vec = gen_const_vec_duplicate (mode, src);
4194 if (prev == NULL)
4195 /* Return CONST_VECTOR when called by a query function. */
4196 return const_vec;
4197
4198 /* Use the move expander with CONST_VECTOR. */
4199 target = gen_reg_rtx (mode);
4200 emit_move_insn (target, const_vec);
4201 return target;
4202 }
4203
4204 char *p = XALLOCAVEC (char, size);
4205
4206 memset (s: p, c: *c, n: size);
4207
4208 return c_readstr (str: p, mode);
4209}
4210
4211/* Callback routine for store_by_pieces. Return the RTL of a register
4212 containing GET_MODE_SIZE (MODE) consecutive copies of the unsigned
4213 char value given in the RTL register data. For example, if mode is
4214 4 bytes wide, return the RTL for 0x01010101*data. If PREV isn't
4215 nullptr, it has the RTL info from the previous iteration. */
4216
4217static rtx
4218builtin_memset_gen_str (void *data, void *prev,
4219 HOST_WIDE_INT offset ATTRIBUTE_UNUSED,
4220 fixed_size_mode mode)
4221{
4222 rtx target, coeff;
4223 size_t size;
4224 char *p;
4225
4226 size = GET_MODE_SIZE (mode);
4227 if (size == 1)
4228 return (rtx) data;
4229
4230 target = gen_memset_value_from_prev (prev: (by_pieces_prev *) prev, mode);
4231 if (target != nullptr)
4232 return target;
4233
4234 if (VECTOR_MODE_P (mode))
4235 {
4236 gcc_assert (GET_MODE_INNER (mode) == QImode);
4237
4238 /* vec_duplicate_optab is a precondition to pick a vector mode for
4239 the memset expander. */
4240 insn_code icode = optab_handler (op: vec_duplicate_optab, mode);
4241
4242 target = gen_reg_rtx (mode);
4243 class expand_operand ops[2];
4244 create_output_operand (op: &ops[0], x: target, mode);
4245 create_input_operand (op: &ops[1], value: (rtx) data, QImode);
4246 expand_insn (icode, nops: 2, ops);
4247 if (!rtx_equal_p (target, ops[0].value))
4248 emit_move_insn (target, ops[0].value);
4249
4250 return target;
4251 }
4252
4253 p = XALLOCAVEC (char, size);
4254 memset (s: p, c: 1, n: size);
4255 coeff = c_readstr (str: p, mode);
4256
4257 target = convert_to_mode (mode, (rtx) data, 1);
4258 target = expand_mult (mode, target, coeff, NULL_RTX, 1);
4259 return force_reg (mode, target);
4260}
4261
4262/* Expand expression EXP, which is a call to the memset builtin. Return
4263 NULL_RTX if we failed the caller should emit a normal call, otherwise
4264 try to get the result in TARGET, if convenient (and in mode MODE if that's
4265 convenient). */
4266
4267rtx
4268expand_builtin_memset (tree exp, rtx target, machine_mode mode)
4269{
4270 if (!validate_arglist (callexpr: exp,
4271 POINTER_TYPE, INTEGER_TYPE, INTEGER_TYPE, VOID_TYPE))
4272 return NULL_RTX;
4273
4274 tree dest = CALL_EXPR_ARG (exp, 0);
4275 tree val = CALL_EXPR_ARG (exp, 1);
4276 tree len = CALL_EXPR_ARG (exp, 2);
4277
4278 return expand_builtin_memset_args (dest, val, len, target, mode, exp);
4279}
4280
4281/* Try to store VAL (or, if NULL_RTX, VALC) in LEN bytes starting at TO.
4282 Return TRUE if successful, FALSE otherwise. TO is assumed to be
4283 aligned at an ALIGN-bits boundary. LEN must be a multiple of
4284 1<<CTZ_LEN between MIN_LEN and MAX_LEN.
4285
4286 The strategy is to issue one store_by_pieces for each power of two,
4287 from most to least significant, guarded by a test on whether there
4288 are at least that many bytes left to copy in LEN.
4289
4290 ??? Should we skip some powers of two in favor of loops? Maybe start
4291 at the max of TO/LEN/word alignment, at least when optimizing for
4292 size, instead of ensuring O(log len) dynamic compares? */
4293
4294bool
4295try_store_by_multiple_pieces (rtx to, rtx len, unsigned int ctz_len,
4296 unsigned HOST_WIDE_INT min_len,
4297 unsigned HOST_WIDE_INT max_len,
4298 rtx val, char valc, unsigned int align)
4299{
4300 int max_bits = floor_log2 (x: max_len);
4301 int min_bits = floor_log2 (x: min_len);
4302 int sctz_len = ctz_len;
4303
4304 gcc_checking_assert (sctz_len >= 0);
4305
4306 if (val)
4307 valc = 1;
4308
4309 /* Bits more significant than TST_BITS are part of the shared prefix
4310 in the binary representation of both min_len and max_len. Since
4311 they're identical, we don't need to test them in the loop. */
4312 int tst_bits = (max_bits != min_bits ? max_bits
4313 : floor_log2 (x: max_len ^ min_len));
4314
4315 /* Check whether it's profitable to start by storing a fixed BLKSIZE
4316 bytes, to lower max_bits. In the unlikely case of a constant LEN
4317 (implied by identical MAX_LEN and MIN_LEN), we want to issue a
4318 single store_by_pieces, but otherwise, select the minimum multiple
4319 of the ALIGN (in bytes) and of the MCD of the possible LENs, that
4320 brings MAX_LEN below TST_BITS, if that's lower than min_len. */
4321 unsigned HOST_WIDE_INT blksize;
4322 if (max_len > min_len)
4323 {
4324 unsigned HOST_WIDE_INT alrng = MAX (HOST_WIDE_INT_1U << ctz_len,
4325 align / BITS_PER_UNIT);
4326 blksize = max_len - (HOST_WIDE_INT_1U << tst_bits) + alrng;
4327 blksize &= ~(alrng - 1);
4328 }
4329 else if (max_len == min_len)
4330 blksize = max_len;
4331 else
4332 /* Huh, max_len < min_len? Punt. See pr100843.c. */
4333 return false;
4334 if (min_len >= blksize)
4335 {
4336 min_len -= blksize;
4337 min_bits = floor_log2 (x: min_len);
4338 max_len -= blksize;
4339 max_bits = floor_log2 (x: max_len);
4340
4341 tst_bits = (max_bits != min_bits ? max_bits
4342 : floor_log2 (x: max_len ^ min_len));
4343 }
4344 else
4345 blksize = 0;
4346
4347 /* Check that we can use store by pieces for the maximum store count
4348 we may issue (initial fixed-size block, plus conditional
4349 power-of-two-sized from max_bits to ctz_len. */
4350 unsigned HOST_WIDE_INT xlenest = blksize;
4351 if (max_bits >= 0)
4352 xlenest += ((HOST_WIDE_INT_1U << max_bits) * 2
4353 - (HOST_WIDE_INT_1U << ctz_len));
4354 if (!can_store_by_pieces (xlenest, builtin_memset_read_str,
4355 &valc, align, true))
4356 return false;
4357
4358 by_pieces_constfn constfun;
4359 void *constfundata;
4360 if (val)
4361 {
4362 constfun = builtin_memset_gen_str;
4363 constfundata = val = force_reg (TYPE_MODE (unsigned_char_type_node),
4364 val);
4365 }
4366 else
4367 {
4368 constfun = builtin_memset_read_str;
4369 constfundata = &valc;
4370 }
4371
4372 rtx ptr = copy_addr_to_reg (XEXP (to, 0));
4373 rtx rem = copy_to_mode_reg (ptr_mode, convert_to_mode (ptr_mode, len, 0));
4374 to = replace_equiv_address (to, ptr);
4375 set_mem_align (to, align);
4376
4377 if (blksize)
4378 {
4379 to = store_by_pieces (to, blksize,
4380 constfun, constfundata,
4381 align, true,
4382 max_len != 0 ? RETURN_END : RETURN_BEGIN);
4383 if (max_len == 0)
4384 return true;
4385
4386 /* Adjust PTR, TO and REM. Since TO's address is likely
4387 PTR+offset, we have to replace it. */
4388 emit_move_insn (ptr, force_operand (XEXP (to, 0), NULL_RTX));
4389 to = replace_equiv_address (to, ptr);
4390 rtx rem_minus_blksize = plus_constant (ptr_mode, rem, -blksize);
4391 emit_move_insn (rem, force_operand (rem_minus_blksize, NULL_RTX));
4392 }
4393
4394 /* Iterate over power-of-two block sizes from the maximum length to
4395 the least significant bit possibly set in the length. */
4396 for (int i = max_bits; i >= sctz_len; i--)
4397 {
4398 rtx_code_label *label = NULL;
4399 blksize = HOST_WIDE_INT_1U << i;
4400
4401 /* If we're past the bits shared between min_ and max_len, expand
4402 a test on the dynamic length, comparing it with the
4403 BLKSIZE. */
4404 if (i <= tst_bits)
4405 {
4406 label = gen_label_rtx ();
4407 emit_cmp_and_jump_insns (rem, GEN_INT (blksize), LT, NULL,
4408 ptr_mode, 1, label,
4409 prob: profile_probability::even ());
4410 }
4411 /* If we are at a bit that is in the prefix shared by min_ and
4412 max_len, skip this BLKSIZE if the bit is clear. */
4413 else if ((max_len & blksize) == 0)
4414 continue;
4415
4416 /* Issue a store of BLKSIZE bytes. */
4417 to = store_by_pieces (to, blksize,
4418 constfun, constfundata,
4419 align, true,
4420 i != sctz_len ? RETURN_END : RETURN_BEGIN);
4421
4422 /* Adjust REM and PTR, unless this is the last iteration. */
4423 if (i != sctz_len)
4424 {
4425 emit_move_insn (ptr, force_operand (XEXP (to, 0), NULL_RTX));
4426 to = replace_equiv_address (to, ptr);
4427 rtx rem_minus_blksize = plus_constant (ptr_mode, rem, -blksize);
4428 emit_move_insn (rem, force_operand (rem_minus_blksize, NULL_RTX));
4429 }
4430
4431 if (label)
4432 {
4433 emit_label (label);
4434
4435 /* Given conditional stores, the offset can no longer be
4436 known, so clear it. */
4437 clear_mem_offset (to);
4438 }
4439 }
4440
4441 return true;
4442}
4443
4444/* Helper function to do the actual work for expand_builtin_memset. The
4445 arguments to the builtin_memset call DEST, VAL, and LEN are broken out
4446 so that this can also be called without constructing an actual CALL_EXPR.
4447 The other arguments and return value are the same as for
4448 expand_builtin_memset. */
4449
4450static rtx
4451expand_builtin_memset_args (tree dest, tree val, tree len,
4452 rtx target, machine_mode mode, tree orig_exp)
4453{
4454 tree fndecl, fn;
4455 enum built_in_function fcode;
4456 machine_mode val_mode;
4457 char c;
4458 unsigned int dest_align;
4459 rtx dest_mem, dest_addr, len_rtx;
4460 HOST_WIDE_INT expected_size = -1;
4461 unsigned int expected_align = 0;
4462 unsigned HOST_WIDE_INT min_size;
4463 unsigned HOST_WIDE_INT max_size;
4464 unsigned HOST_WIDE_INT probable_max_size;
4465
4466 dest_align = get_pointer_alignment (exp: dest);
4467
4468 /* If DEST is not a pointer type, don't do this operation in-line. */
4469 if (dest_align == 0)
4470 return NULL_RTX;
4471
4472 if (currently_expanding_gimple_stmt)
4473 stringop_block_profile (currently_expanding_gimple_stmt,
4474 &expected_align, &expected_size);
4475
4476 if (expected_align < dest_align)
4477 expected_align = dest_align;
4478
4479 /* If the LEN parameter is zero, return DEST. */
4480 if (integer_zerop (len))
4481 {
4482 /* Evaluate and ignore VAL in case it has side-effects. */
4483 expand_expr (exp: val, const0_rtx, VOIDmode, modifier: EXPAND_NORMAL);
4484 return expand_expr (exp: dest, target, mode, modifier: EXPAND_NORMAL);
4485 }
4486
4487 /* Stabilize the arguments in case we fail. */
4488 dest = builtin_save_expr (exp: dest);
4489 val = builtin_save_expr (exp: val);
4490 len = builtin_save_expr (exp: len);
4491
4492 len_rtx = expand_normal (exp: len);
4493 determine_block_size (len, len_rtx, min_size: &min_size, max_size: &max_size,
4494 probable_max_size: &probable_max_size);
4495 dest_mem = get_memory_rtx (exp: dest, len);
4496 val_mode = TYPE_MODE (unsigned_char_type_node);
4497
4498 if (TREE_CODE (val) != INTEGER_CST
4499 || target_char_cast (cst: val, p: &c))
4500 {
4501 rtx val_rtx;
4502
4503 val_rtx = expand_normal (exp: val);
4504 val_rtx = convert_to_mode (val_mode, val_rtx, 0);
4505
4506 /* Assume that we can memset by pieces if we can store
4507 * the coefficients by pieces (in the required modes).
4508 * We can't pass builtin_memset_gen_str as that emits RTL. */
4509 c = 1;
4510 if (tree_fits_uhwi_p (len)
4511 && can_store_by_pieces (tree_to_uhwi (len),
4512 builtin_memset_read_str, &c, dest_align,
4513 true))
4514 {
4515 val_rtx = force_reg (val_mode, val_rtx);
4516 store_by_pieces (dest_mem, tree_to_uhwi (len),
4517 builtin_memset_gen_str, val_rtx, dest_align,
4518 true, RETURN_BEGIN);
4519 }
4520 else if (!set_storage_via_setmem (dest_mem, len_rtx, val_rtx,
4521 dest_align, expected_align,
4522 expected_size, min_size, max_size,
4523 probable_max_size)
4524 && !try_store_by_multiple_pieces (to: dest_mem, len: len_rtx,
4525 ctz_len: tree_ctz (len),
4526 min_len: min_size, max_len: max_size,
4527 val: val_rtx, valc: 0,
4528 align: dest_align))
4529 goto do_libcall;
4530
4531 dest_mem = force_operand (XEXP (dest_mem, 0), NULL_RTX);
4532 dest_mem = convert_memory_address (ptr_mode, dest_mem);
4533 return dest_mem;
4534 }
4535
4536 if (c)
4537 {
4538 if (tree_fits_uhwi_p (len)
4539 && can_store_by_pieces (tree_to_uhwi (len),
4540 builtin_memset_read_str, &c, dest_align,
4541 true))
4542 store_by_pieces (dest_mem, tree_to_uhwi (len),
4543 builtin_memset_read_str, &c, dest_align, true,
4544 RETURN_BEGIN);
4545 else if (!set_storage_via_setmem (dest_mem, len_rtx,
4546 gen_int_mode (c, val_mode),
4547 dest_align, expected_align,
4548 expected_size, min_size, max_size,
4549 probable_max_size)
4550 && !try_store_by_multiple_pieces (to: dest_mem, len: len_rtx,
4551 ctz_len: tree_ctz (len),
4552 min_len: min_size, max_len: max_size,
4553 NULL_RTX, valc: c,
4554 align: dest_align))
4555 goto do_libcall;
4556
4557 dest_mem = force_operand (XEXP (dest_mem, 0), NULL_RTX);
4558 dest_mem = convert_memory_address (ptr_mode, dest_mem);
4559 return dest_mem;
4560 }
4561
4562 set_mem_align (dest_mem, dest_align);
4563 dest_addr = clear_storage_hints (dest_mem, len_rtx,
4564 CALL_EXPR_TAILCALL (orig_exp)
4565 ? BLOCK_OP_TAILCALL : BLOCK_OP_NORMAL,
4566 expected_align, expected_size,
4567 min_size, max_size,
4568 probable_max_size, tree_ctz (len));
4569
4570 if (dest_addr == 0)
4571 {
4572 dest_addr = force_operand (XEXP (dest_mem, 0), NULL_RTX);
4573 dest_addr = convert_memory_address (ptr_mode, dest_addr);
4574 }
4575
4576 return dest_addr;
4577
4578 do_libcall:
4579 fndecl = get_callee_fndecl (orig_exp);
4580 fcode = DECL_FUNCTION_CODE (decl: fndecl);
4581 if (fcode == BUILT_IN_MEMSET)
4582 fn = build_call_nofold_loc (EXPR_LOCATION (orig_exp), fndecl, n: 3,
4583 dest, val, len);
4584 else if (fcode == BUILT_IN_BZERO)
4585 fn = build_call_nofold_loc (EXPR_LOCATION (orig_exp), fndecl, n: 2,
4586 dest, len);
4587 else
4588 gcc_unreachable ();
4589 gcc_assert (TREE_CODE (fn) == CALL_EXPR);
4590 CALL_EXPR_TAILCALL (fn) = CALL_EXPR_TAILCALL (orig_exp);
4591 return expand_call (fn, target, target == const0_rtx);
4592}
4593
4594/* Expand expression EXP, which is a call to the bzero builtin. Return
4595 NULL_RTX if we failed the caller should emit a normal call. */
4596
4597static rtx
4598expand_builtin_bzero (tree exp)
4599{
4600 if (!validate_arglist (callexpr: exp, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
4601 return NULL_RTX;
4602
4603 tree dest = CALL_EXPR_ARG (exp, 0);
4604 tree size = CALL_EXPR_ARG (exp, 1);
4605
4606 /* New argument list transforming bzero(ptr x, int y) to
4607 memset(ptr x, int 0, size_t y). This is done this way
4608 so that if it isn't expanded inline, we fallback to
4609 calling bzero instead of memset. */
4610
4611 location_t loc = EXPR_LOCATION (exp);
4612
4613 return expand_builtin_memset_args (dest, integer_zero_node,
4614 len: fold_convert_loc (loc,
4615 size_type_node, size),
4616 const0_rtx, VOIDmode, orig_exp: exp);
4617}
4618
4619/* Try to expand cmpstr operation ICODE with the given operands.
4620 Return the result rtx on success, otherwise return null. */
4621
4622static rtx
4623expand_cmpstr (insn_code icode, rtx target, rtx arg1_rtx, rtx arg2_rtx,
4624 HOST_WIDE_INT align)
4625{
4626 machine_mode insn_mode = insn_data[icode].operand[0].mode;
4627
4628 if (target && (!REG_P (target) || HARD_REGISTER_P (target)))
4629 target = NULL_RTX;
4630
4631 class expand_operand ops[4];
4632 create_output_operand (op: &ops[0], x: target, mode: insn_mode);
4633 create_fixed_operand (op: &ops[1], x: arg1_rtx);
4634 create_fixed_operand (op: &ops[2], x: arg2_rtx);
4635 create_integer_operand (&ops[3], align);
4636 if (maybe_expand_insn (icode, nops: 4, ops))
4637 return ops[0].value;
4638 return NULL_RTX;
4639}
4640
4641/* Expand expression EXP, which is a call to the memcmp built-in function.
4642 Return NULL_RTX if we failed and the caller should emit a normal call,
4643 otherwise try to get the result in TARGET, if convenient.
4644 RESULT_EQ is true if we can relax the returned value to be either zero
4645 or nonzero, without caring about the sign. */
4646
4647static rtx
4648expand_builtin_memcmp (tree exp, rtx target, bool result_eq)
4649{
4650 if (!validate_arglist (callexpr: exp,
4651 POINTER_TYPE, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
4652 return NULL_RTX;
4653
4654 tree arg1 = CALL_EXPR_ARG (exp, 0);
4655 tree arg2 = CALL_EXPR_ARG (exp, 1);
4656 tree len = CALL_EXPR_ARG (exp, 2);
4657
4658 /* Due to the performance benefit, always inline the calls first
4659 when result_eq is false. */
4660 rtx result = NULL_RTX;
4661 enum built_in_function fcode = DECL_FUNCTION_CODE (decl: get_callee_fndecl (exp));
4662 if (!result_eq && fcode != BUILT_IN_BCMP)
4663 {
4664 result = inline_expand_builtin_bytecmp (exp, target);
4665 if (result)
4666 return result;
4667 }
4668
4669 machine_mode mode = TYPE_MODE (TREE_TYPE (exp));
4670 location_t loc = EXPR_LOCATION (exp);
4671
4672 unsigned int arg1_align = get_pointer_alignment (exp: arg1) / BITS_PER_UNIT;
4673 unsigned int arg2_align = get_pointer_alignment (exp: arg2) / BITS_PER_UNIT;
4674
4675 /* If we don't have POINTER_TYPE, call the function. */
4676 if (arg1_align == 0 || arg2_align == 0)
4677 return NULL_RTX;
4678
4679 rtx arg1_rtx = get_memory_rtx (exp: arg1, len);
4680 rtx arg2_rtx = get_memory_rtx (exp: arg2, len);
4681 rtx len_rtx = expand_normal (exp: fold_convert_loc (loc, sizetype, len));
4682
4683 /* Set MEM_SIZE as appropriate. */
4684 if (CONST_INT_P (len_rtx))
4685 {
4686 set_mem_size (arg1_rtx, INTVAL (len_rtx));
4687 set_mem_size (arg2_rtx, INTVAL (len_rtx));
4688 }
4689
4690 by_pieces_constfn constfn = NULL;
4691
4692 /* Try to get the byte representation of the constant ARG2 (or, only
4693 when the function's result is used for equality to zero, ARG1)
4694 points to, with its byte size in NBYTES. */
4695 unsigned HOST_WIDE_INT nbytes;
4696 const char *rep = getbyterep (arg2, &nbytes);
4697 if (result_eq && rep == NULL)
4698 {
4699 /* For equality to zero the arguments are interchangeable. */
4700 rep = getbyterep (arg1, &nbytes);
4701 if (rep != NULL)
4702 std::swap (a&: arg1_rtx, b&: arg2_rtx);
4703 }
4704
4705 /* If the function's constant bound LEN_RTX is less than or equal
4706 to the byte size of the representation of the constant argument,
4707 and if block move would be done by pieces, we can avoid loading
4708 the bytes from memory and only store the computed constant result. */
4709 if (rep
4710 && CONST_INT_P (len_rtx)
4711 && (unsigned HOST_WIDE_INT) INTVAL (len_rtx) <= nbytes)
4712 constfn = builtin_memcpy_read_str;
4713
4714 result = emit_block_cmp_hints (arg1_rtx, arg2_rtx, len_rtx,
4715 TREE_TYPE (len), target,
4716 result_eq, constfn,
4717 CONST_CAST (char *, rep));
4718
4719 if (result)
4720 {
4721 /* Return the value in the proper mode for this function. */
4722 if (GET_MODE (result) == mode)
4723 return result;
4724
4725 if (target != 0)
4726 {
4727 convert_move (target, result, 0);
4728 return target;
4729 }
4730
4731 return convert_to_mode (mode, result, 0);
4732 }
4733
4734 return NULL_RTX;
4735}
4736
4737/* Expand expression EXP, which is a call to the strcmp builtin. Return NULL_RTX
4738 if we failed the caller should emit a normal call, otherwise try to get
4739 the result in TARGET, if convenient. */
4740
4741static rtx
4742expand_builtin_strcmp (tree exp, ATTRIBUTE_UNUSED rtx target)
4743{
4744 if (!validate_arglist (callexpr: exp, POINTER_TYPE, POINTER_TYPE, VOID_TYPE))
4745 return NULL_RTX;
4746
4747 tree arg1 = CALL_EXPR_ARG (exp, 0);
4748 tree arg2 = CALL_EXPR_ARG (exp, 1);
4749
4750 /* Due to the performance benefit, always inline the calls first. */
4751 rtx result = NULL_RTX;
4752 result = inline_expand_builtin_bytecmp (exp, target);
4753 if (result)
4754 return result;
4755
4756 insn_code cmpstr_icode = direct_optab_handler (op: cmpstr_optab, SImode);
4757 insn_code cmpstrn_icode = direct_optab_handler (op: cmpstrn_optab, SImode);
4758 if (cmpstr_icode == CODE_FOR_nothing && cmpstrn_icode == CODE_FOR_nothing)
4759 return NULL_RTX;
4760
4761 unsigned int arg1_align = get_pointer_alignment (exp: arg1) / BITS_PER_UNIT;
4762 unsigned int arg2_align = get_pointer_alignment (exp: arg2) / BITS_PER_UNIT;
4763
4764 /* If we don't have POINTER_TYPE, call the function. */
4765 if (arg1_align == 0 || arg2_align == 0)
4766 return NULL_RTX;
4767
4768 /* Stabilize the arguments in case gen_cmpstr(n)si fail. */
4769 arg1 = builtin_save_expr (exp: arg1);
4770 arg2 = builtin_save_expr (exp: arg2);
4771
4772 rtx arg1_rtx = get_memory_rtx (exp: arg1, NULL);
4773 rtx arg2_rtx = get_memory_rtx (exp: arg2, NULL);
4774
4775 /* Try to call cmpstrsi. */
4776 if (cmpstr_icode != CODE_FOR_nothing)
4777 result = expand_cmpstr (icode: cmpstr_icode, target, arg1_rtx, arg2_rtx,
4778 MIN (arg1_align, arg2_align));
4779
4780 /* Try to determine at least one length and call cmpstrnsi. */
4781 if (!result && cmpstrn_icode != CODE_FOR_nothing)
4782 {
4783 tree len;
4784 rtx arg3_rtx;
4785
4786 tree len1 = c_strlen (arg: arg1, only_value: 1);
4787 tree len2 = c_strlen (arg: arg2, only_value: 1);
4788
4789 if (len1)
4790 len1 = size_binop (PLUS_EXPR, ssize_int (1), len1);
4791 if (len2)
4792 len2 = size_binop (PLUS_EXPR, ssize_int (1), len2);
4793
4794 /* If we don't have a constant length for the first, use the length
4795 of the second, if we know it. We don't require a constant for
4796 this case; some cost analysis could be done if both are available
4797 but neither is constant. For now, assume they're equally cheap,
4798 unless one has side effects. If both strings have constant lengths,
4799 use the smaller. */
4800
4801 if (!len1)
4802 len = len2;
4803 else if (!len2)
4804 len = len1;
4805 else if (TREE_SIDE_EFFECTS (len1))
4806 len = len2;
4807 else if (TREE_SIDE_EFFECTS (len2))
4808 len = len1;
4809 else if (TREE_CODE (len1) != INTEGER_CST)
4810 len = len2;
4811 else if (TREE_CODE (len2) != INTEGER_CST)
4812 len = len1;
4813 else if (tree_int_cst_lt (t1: len1, t2: len2))
4814 len = len1;
4815 else
4816 len = len2;
4817
4818 /* If both arguments have side effects, we cannot optimize. */
4819 if (len && !TREE_SIDE_EFFECTS (len))
4820 {
4821 arg3_rtx = expand_normal (exp: len);
4822 result = expand_cmpstrn_or_cmpmem
4823 (cmpstrn_icode, target, arg1_rtx, arg2_rtx, TREE_TYPE (len),
4824 arg3_rtx, MIN (arg1_align, arg2_align));
4825 }
4826 }
4827
4828 tree fndecl = get_callee_fndecl (exp);
4829 if (result)
4830 {
4831 /* Return the value in the proper mode for this function. */
4832 machine_mode mode = TYPE_MODE (TREE_TYPE (exp));
4833 if (GET_MODE (result) == mode)
4834 return result;
4835 if (target == 0)
4836 return convert_to_mode (mode, result, 0);
4837 convert_move (target, result, 0);
4838 return target;
4839 }
4840
4841 /* Expand the library call ourselves using a stabilized argument
4842 list to avoid re-evaluating the function's arguments twice. */
4843 tree fn = build_call_nofold_loc (EXPR_LOCATION (exp), fndecl, n: 2, arg1, arg2);
4844 copy_warning (fn, exp);
4845 gcc_assert (TREE_CODE (fn) == CALL_EXPR);
4846 CALL_EXPR_TAILCALL (fn) = CALL_EXPR_TAILCALL (exp);
4847 return expand_call (fn, target, target == const0_rtx);
4848}
4849
4850/* Expand expression EXP, which is a call to the strncmp builtin. Return
4851 NULL_RTX if we failed the caller should emit a normal call, otherwise
4852 try to get the result in TARGET, if convenient. */
4853
4854static rtx
4855expand_builtin_strncmp (tree exp, ATTRIBUTE_UNUSED rtx target,
4856 ATTRIBUTE_UNUSED machine_mode mode)
4857{
4858 if (!validate_arglist (callexpr: exp,
4859 POINTER_TYPE, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
4860 return NULL_RTX;
4861
4862 tree arg1 = CALL_EXPR_ARG (exp, 0);
4863 tree arg2 = CALL_EXPR_ARG (exp, 1);
4864 tree arg3 = CALL_EXPR_ARG (exp, 2);
4865
4866 location_t loc = EXPR_LOCATION (exp);
4867 tree len1 = c_strlen (arg: arg1, only_value: 1);
4868 tree len2 = c_strlen (arg: arg2, only_value: 1);
4869
4870 /* Due to the performance benefit, always inline the calls first. */
4871 rtx result = NULL_RTX;
4872 result = inline_expand_builtin_bytecmp (exp, target);
4873 if (result)
4874 return result;
4875
4876 /* If c_strlen can determine an expression for one of the string
4877 lengths, and it doesn't have side effects, then emit cmpstrnsi
4878 using length MIN(strlen(string)+1, arg3). */
4879 insn_code cmpstrn_icode = direct_optab_handler (op: cmpstrn_optab, SImode);
4880 if (cmpstrn_icode == CODE_FOR_nothing)
4881 return NULL_RTX;
4882
4883 tree len;
4884
4885 unsigned int arg1_align = get_pointer_alignment (exp: arg1) / BITS_PER_UNIT;
4886 unsigned int arg2_align = get_pointer_alignment (exp: arg2) / BITS_PER_UNIT;
4887
4888 if (len1)
4889 len1 = size_binop_loc (loc, PLUS_EXPR, ssize_int (1), len1);
4890 if (len2)
4891 len2 = size_binop_loc (loc, PLUS_EXPR, ssize_int (1), len2);
4892
4893 tree len3 = fold_convert_loc (loc, sizetype, arg3);
4894
4895 /* If we don't have a constant length for the first, use the length
4896 of the second, if we know it. If neither string is constant length,
4897 use the given length argument. We don't require a constant for
4898 this case; some cost analysis could be done if both are available
4899 but neither is constant. For now, assume they're equally cheap,
4900 unless one has side effects. If both strings have constant lengths,
4901 use the smaller. */
4902
4903 if (!len1 && !len2)
4904 len = len3;
4905 else if (!len1)
4906 len = len2;
4907 else if (!len2)
4908 len = len1;
4909 else if (TREE_SIDE_EFFECTS (len1))
4910 len = len2;
4911 else if (TREE_SIDE_EFFECTS (len2))
4912 len = len1;
4913 else if (TREE_CODE (len1) != INTEGER_CST)
4914 len = len2;
4915 else if (TREE_CODE (len2) != INTEGER_CST)
4916 len = len1;
4917 else if (tree_int_cst_lt (t1: len1, t2: len2))
4918 len = len1;
4919 else
4920 len = len2;
4921
4922 /* If we are not using the given length, we must incorporate it here.
4923 The actual new length parameter will be MIN(len,arg3) in this case. */
4924 if (len != len3)
4925 {
4926 len = fold_convert_loc (loc, sizetype, len);
4927 len = fold_build2_loc (loc, MIN_EXPR, TREE_TYPE (len), len, len3);
4928 }
4929 rtx arg1_rtx = get_memory_rtx (exp: arg1, len);
4930 rtx arg2_rtx = get_memory_rtx (exp: arg2, len);
4931 rtx arg3_rtx = expand_normal (exp: len);
4932 result = expand_cmpstrn_or_cmpmem (cmpstrn_icode, target, arg1_rtx,
4933 arg2_rtx, TREE_TYPE (len), arg3_rtx,
4934 MIN (arg1_align, arg2_align));
4935
4936 tree fndecl = get_callee_fndecl (exp);
4937 if (result)
4938 {
4939 /* Return the value in the proper mode for this function. */
4940 mode = TYPE_MODE (TREE_TYPE (exp));
4941 if (GET_MODE (result) == mode)
4942 return result;
4943 if (target == 0)
4944 return convert_to_mode (mode, result, 0);
4945 convert_move (target, result, 0);
4946 return target;
4947 }
4948
4949 /* Expand the library call ourselves using a stabilized argument
4950 list to avoid re-evaluating the function's arguments twice. */
4951 tree call = build_call_nofold_loc (loc, fndecl, n: 3, arg1, arg2, len);
4952 copy_warning (call, exp);
4953 gcc_assert (TREE_CODE (call) == CALL_EXPR);
4954 CALL_EXPR_TAILCALL (call) = CALL_EXPR_TAILCALL (exp);
4955 return expand_call (call, target, target == const0_rtx);
4956}
4957
4958/* Expand a call to __builtin_saveregs, generating the result in TARGET,
4959 if that's convenient. */
4960
4961rtx
4962expand_builtin_saveregs (void)
4963{
4964 rtx val;
4965 rtx_insn *seq;
4966
4967 /* Don't do __builtin_saveregs more than once in a function.
4968 Save the result of the first call and reuse it. */
4969 if (saveregs_value != 0)
4970 return saveregs_value;
4971
4972 /* When this function is called, it means that registers must be
4973 saved on entry to this function. So we migrate the call to the
4974 first insn of this function. */
4975
4976 start_sequence ();
4977
4978 /* Do whatever the machine needs done in this case. */
4979 val = targetm.calls.expand_builtin_saveregs ();
4980
4981 seq = get_insns ();
4982 end_sequence ();
4983
4984 saveregs_value = val;
4985
4986 /* Put the insns after the NOTE that starts the function. If this
4987 is inside a start_sequence, make the outer-level insn chain current, so
4988 the code is placed at the start of the function. */
4989 push_topmost_sequence ();
4990 emit_insn_after (seq, entry_of_function ());
4991 pop_topmost_sequence ();
4992
4993 return val;
4994}
4995
4996/* Expand a call to __builtin_next_arg. */
4997
4998static rtx
4999expand_builtin_next_arg (void)
5000{
5001 /* Checking arguments is already done in fold_builtin_next_arg
5002 that must be called before this function. */
5003 return expand_binop (ptr_mode, add_optab,
5004 crtl->args.internal_arg_pointer,
5005 crtl->args.arg_offset_rtx,
5006 NULL_RTX, 0, OPTAB_LIB_WIDEN);
5007}
5008
5009/* Make it easier for the backends by protecting the valist argument
5010 from multiple evaluations. */
5011
5012static tree
5013stabilize_va_list_loc (location_t loc, tree valist, int needs_lvalue)
5014{
5015 tree vatype = targetm.canonical_va_list_type (TREE_TYPE (valist));
5016
5017 /* The current way of determining the type of valist is completely
5018 bogus. We should have the information on the va builtin instead. */
5019 if (!vatype)
5020 vatype = targetm.fn_abi_va_list (cfun->decl);
5021
5022 if (TREE_CODE (vatype) == ARRAY_TYPE)
5023 {
5024 if (TREE_SIDE_EFFECTS (valist))
5025 valist = save_expr (valist);
5026
5027 /* For this case, the backends will be expecting a pointer to
5028 vatype, but it's possible we've actually been given an array
5029 (an actual TARGET_CANONICAL_VA_LIST_TYPE (valist)).
5030 So fix it. */
5031 if (TREE_CODE (TREE_TYPE (valist)) == ARRAY_TYPE)
5032 {
5033 tree p1 = build_pointer_type (TREE_TYPE (vatype));
5034 valist = build_fold_addr_expr_with_type_loc (loc, valist, p1);
5035 }
5036 }
5037 else
5038 {
5039 tree pt = build_pointer_type (vatype);
5040
5041 if (! needs_lvalue)
5042 {
5043 if (! TREE_SIDE_EFFECTS (valist))
5044 return valist;
5045
5046 valist = fold_build1_loc (loc, ADDR_EXPR, pt, valist);
5047 TREE_SIDE_EFFECTS (valist) = 1;
5048 }
5049
5050 if (TREE_SIDE_EFFECTS (valist))
5051 valist = save_expr (valist);
5052 valist = fold_build2_loc (loc, MEM_REF,
5053 vatype, valist, build_int_cst (pt, 0));
5054 }
5055
5056 return valist;
5057}
5058
5059/* The "standard" definition of va_list is void*. */
5060
5061tree
5062std_build_builtin_va_list (void)
5063{
5064 return ptr_type_node;
5065}
5066
5067/* The "standard" abi va_list is va_list_type_node. */
5068
5069tree
5070std_fn_abi_va_list (tree fndecl ATTRIBUTE_UNUSED)
5071{
5072 return va_list_type_node;
5073}
5074
5075/* The "standard" type of va_list is va_list_type_node. */
5076
5077tree
5078std_canonical_va_list_type (tree type)
5079{
5080 tree wtype, htype;
5081
5082 wtype = va_list_type_node;
5083 htype = type;
5084
5085 if (TREE_CODE (wtype) == ARRAY_TYPE)
5086 {
5087 /* If va_list is an array type, the argument may have decayed
5088 to a pointer type, e.g. by being passed to another function.
5089 In that case, unwrap both types so that we can compare the
5090 underlying records. */
5091 if (TREE_CODE (htype) == ARRAY_TYPE
5092 || POINTER_TYPE_P (htype))
5093 {
5094 wtype = TREE_TYPE (wtype);
5095 htype = TREE_TYPE (htype);
5096 }
5097 }
5098 if (TYPE_MAIN_VARIANT (wtype) == TYPE_MAIN_VARIANT (htype))
5099 return va_list_type_node;
5100
5101 return NULL_TREE;
5102}
5103
5104/* The "standard" implementation of va_start: just assign `nextarg' to
5105 the variable. */
5106
5107void
5108std_expand_builtin_va_start (tree valist, rtx nextarg)
5109{
5110 rtx va_r = expand_expr (exp: valist, NULL_RTX, VOIDmode, modifier: EXPAND_WRITE);
5111 convert_move (va_r, nextarg, 0);
5112}
5113
5114/* Expand EXP, a call to __builtin_va_start. */
5115
5116static rtx
5117expand_builtin_va_start (tree exp)
5118{
5119 rtx nextarg;
5120 tree valist;
5121 location_t loc = EXPR_LOCATION (exp);
5122
5123 if (call_expr_nargs (exp) < 2)
5124 {
5125 error_at (loc, "too few arguments to function %<va_start%>");
5126 return const0_rtx;
5127 }
5128
5129 if (fold_builtin_next_arg (exp, true))
5130 return const0_rtx;
5131
5132 nextarg = expand_builtin_next_arg ();
5133 valist = stabilize_va_list_loc (loc, CALL_EXPR_ARG (exp, 0), needs_lvalue: 1);
5134
5135 if (targetm.expand_builtin_va_start)
5136 targetm.expand_builtin_va_start (valist, nextarg);
5137 else
5138 std_expand_builtin_va_start (valist, nextarg);
5139
5140 return const0_rtx;
5141}
5142
5143/* Expand EXP, a call to __builtin_va_end. */
5144
5145static rtx
5146expand_builtin_va_end (tree exp)
5147{
5148 tree valist = CALL_EXPR_ARG (exp, 0);
5149
5150 /* Evaluate for side effects, if needed. I hate macros that don't
5151 do that. */
5152 if (TREE_SIDE_EFFECTS (valist))
5153 expand_expr (exp: valist, const0_rtx, VOIDmode, modifier: EXPAND_NORMAL);
5154
5155 return const0_rtx;
5156}
5157
5158/* Expand EXP, a call to __builtin_va_copy. We do this as a
5159 builtin rather than just as an assignment in stdarg.h because of the
5160 nastiness of array-type va_list types. */
5161
5162static rtx
5163expand_builtin_va_copy (tree exp)
5164{
5165 tree dst, src, t;
5166 location_t loc = EXPR_LOCATION (exp);
5167
5168 dst = CALL_EXPR_ARG (exp, 0);
5169 src = CALL_EXPR_ARG (exp, 1);
5170
5171 dst = stabilize_va_list_loc (loc, valist: dst, needs_lvalue: 1);
5172 src = stabilize_va_list_loc (loc, valist: src, needs_lvalue: 0);
5173
5174 gcc_assert (cfun != NULL && cfun->decl != NULL_TREE);
5175
5176 if (TREE_CODE (targetm.fn_abi_va_list (cfun->decl)) != ARRAY_TYPE)
5177 {
5178 t = build2 (MODIFY_EXPR, targetm.fn_abi_va_list (cfun->decl), dst, src);
5179 TREE_SIDE_EFFECTS (t) = 1;
5180 expand_expr (exp: t, const0_rtx, VOIDmode, modifier: EXPAND_NORMAL);
5181 }
5182 else
5183 {
5184 rtx dstb, srcb, size;
5185
5186 /* Evaluate to pointers. */
5187 dstb = expand_expr (exp: dst, NULL_RTX, Pmode, modifier: EXPAND_NORMAL);
5188 srcb = expand_expr (exp: src, NULL_RTX, Pmode, modifier: EXPAND_NORMAL);
5189 size = expand_expr (TYPE_SIZE_UNIT (targetm.fn_abi_va_list (cfun->decl)),
5190 NULL_RTX, VOIDmode, modifier: EXPAND_NORMAL);
5191
5192 dstb = convert_memory_address (Pmode, dstb);
5193 srcb = convert_memory_address (Pmode, srcb);
5194
5195 /* "Dereference" to BLKmode memories. */
5196 dstb = gen_rtx_MEM (BLKmode, dstb);
5197 set_mem_alias_set (dstb, get_alias_set (TREE_TYPE (TREE_TYPE (dst))));
5198 set_mem_align (dstb, TYPE_ALIGN (targetm.fn_abi_va_list (cfun->decl)));
5199 srcb = gen_rtx_MEM (BLKmode, srcb);
5200 set_mem_alias_set (srcb, get_alias_set (TREE_TYPE (TREE_TYPE (src))));
5201 set_mem_align (srcb, TYPE_ALIGN (targetm.fn_abi_va_list (cfun->decl)));
5202
5203 /* Copy. */
5204 emit_block_move (dstb, srcb, size, BLOCK_OP_NORMAL);
5205 }
5206
5207 return const0_rtx;
5208}
5209
5210/* Expand a call to one of the builtin functions __builtin_frame_address or
5211 __builtin_return_address. */
5212
5213static rtx
5214expand_builtin_frame_address (tree fndecl, tree exp)
5215{
5216 /* The argument must be a nonnegative integer constant.
5217 It counts the number of frames to scan up the stack.
5218 The value is either the frame pointer value or the return
5219 address saved in that frame. */
5220 if (call_expr_nargs (exp) == 0)
5221 /* Warning about missing arg was already issued. */
5222 return const0_rtx;
5223 else if (! tree_fits_uhwi_p (CALL_EXPR_ARG (exp, 0)))
5224 {
5225 error ("invalid argument to %qD", fndecl);
5226 return const0_rtx;
5227 }
5228 else
5229 {
5230 /* Number of frames to scan up the stack. */
5231 unsigned HOST_WIDE_INT count = tree_to_uhwi (CALL_EXPR_ARG (exp, 0));
5232
5233 rtx tem = expand_builtin_return_addr (fndecl_code: DECL_FUNCTION_CODE (decl: fndecl), count);
5234
5235 /* Some ports cannot access arbitrary stack frames. */
5236 if (tem == NULL)
5237 {
5238 warning (0, "unsupported argument to %qD", fndecl);
5239 return const0_rtx;
5240 }
5241
5242 if (count)
5243 {
5244 /* Warn since no effort is made to ensure that any frame
5245 beyond the current one exists or can be safely reached. */
5246 warning (OPT_Wframe_address, "calling %qD with "
5247 "a nonzero argument is unsafe", fndecl);
5248 }
5249
5250 /* For __builtin_frame_address, return what we've got. */
5251 if (DECL_FUNCTION_CODE (decl: fndecl) == BUILT_IN_FRAME_ADDRESS)
5252 return tem;
5253
5254 if (!REG_P (tem)
5255 && ! CONSTANT_P (tem))
5256 tem = copy_addr_to_reg (tem);
5257 return tem;
5258 }
5259}
5260
5261/* Expand EXP, a call to the alloca builtin. Return NULL_RTX if we
5262 failed and the caller should emit a normal call. */
5263
5264static rtx
5265expand_builtin_alloca (tree exp)
5266{
5267 rtx op0;
5268 rtx result;
5269 unsigned int align;
5270 tree fndecl = get_callee_fndecl (exp);
5271 HOST_WIDE_INT max_size;
5272 enum built_in_function fcode = DECL_FUNCTION_CODE (decl: fndecl);
5273 bool alloca_for_var = CALL_ALLOCA_FOR_VAR_P (exp);
5274 bool valid_arglist
5275 = (fcode == BUILT_IN_ALLOCA_WITH_ALIGN_AND_MAX
5276 ? validate_arglist (callexpr: exp, INTEGER_TYPE, INTEGER_TYPE, INTEGER_TYPE,
5277 VOID_TYPE)
5278 : fcode == BUILT_IN_ALLOCA_WITH_ALIGN
5279 ? validate_arglist (callexpr: exp, INTEGER_TYPE, INTEGER_TYPE, VOID_TYPE)
5280 : validate_arglist (callexpr: exp, INTEGER_TYPE, VOID_TYPE));
5281
5282 if (!valid_arglist)
5283 return NULL_RTX;
5284
5285 /* Compute the argument. */
5286 op0 = expand_normal (CALL_EXPR_ARG (exp, 0));
5287
5288 /* Compute the alignment. */
5289 align = (fcode == BUILT_IN_ALLOCA
5290 ? BIGGEST_ALIGNMENT
5291 : TREE_INT_CST_LOW (CALL_EXPR_ARG (exp, 1)));
5292
5293 /* Compute the maximum size. */
5294 max_size = (fcode == BUILT_IN_ALLOCA_WITH_ALIGN_AND_MAX
5295 ? TREE_INT_CST_LOW (CALL_EXPR_ARG (exp, 2))
5296 : -1);
5297
5298 /* Allocate the desired space. If the allocation stems from the declaration
5299 of a variable-sized object, it cannot accumulate. */
5300 result
5301 = allocate_dynamic_stack_space (op0, 0, align, max_size, alloca_for_var);
5302 result = convert_memory_address (ptr_mode, result);
5303
5304 /* Dynamic allocations for variables are recorded during gimplification. */
5305 if (!alloca_for_var && (flag_callgraph_info & CALLGRAPH_INFO_DYNAMIC_ALLOC))
5306 record_dynamic_alloc (decl_or_exp: exp);
5307
5308 return result;
5309}
5310
5311/* Emit a call to __asan_allocas_unpoison call in EXP. Add to second argument
5312 of the call virtual_stack_dynamic_rtx - stack_pointer_rtx, which is the
5313 STACK_DYNAMIC_OFFSET value. See motivation for this in comment to
5314 handle_builtin_stack_restore function. */
5315
5316static rtx
5317expand_asan_emit_allocas_unpoison (tree exp)
5318{
5319 tree arg0 = CALL_EXPR_ARG (exp, 0);
5320 tree arg1 = CALL_EXPR_ARG (exp, 1);
5321 rtx top = expand_expr (exp: arg0, NULL_RTX, mode: ptr_mode, modifier: EXPAND_NORMAL);
5322 rtx bot = expand_expr (exp: arg1, NULL_RTX, mode: ptr_mode, modifier: EXPAND_NORMAL);
5323 rtx off = expand_simple_binop (Pmode, MINUS, virtual_stack_dynamic_rtx,
5324 stack_pointer_rtx, NULL_RTX, 0,
5325 OPTAB_LIB_WIDEN);
5326 off = convert_modes (mode: ptr_mode, Pmode, x: off, unsignedp: 0);
5327 bot = expand_simple_binop (ptr_mode, PLUS, bot, off, NULL_RTX, 0,
5328 OPTAB_LIB_WIDEN);
5329 rtx ret = init_one_libfunc ("__asan_allocas_unpoison");
5330 ret = emit_library_call_value (fun: ret, NULL_RTX, fn_type: LCT_NORMAL, outmode: ptr_mode,
5331 arg1: top, arg1_mode: ptr_mode, arg2: bot, arg2_mode: ptr_mode);
5332 return ret;
5333}
5334
5335/* Expand a call to bswap builtin in EXP.
5336 Return NULL_RTX if a normal call should be emitted rather than expanding the
5337 function in-line. If convenient, the result should be placed in TARGET.
5338 SUBTARGET may be used as the target for computing one of EXP's operands. */
5339
5340static rtx
5341expand_builtin_bswap (machine_mode target_mode, tree exp, rtx target,
5342 rtx subtarget)
5343{
5344 tree arg;
5345 rtx op0;
5346
5347 if (!validate_arglist (callexpr: exp, INTEGER_TYPE, VOID_TYPE))
5348 return NULL_RTX;
5349
5350 arg = CALL_EXPR_ARG (exp, 0);
5351 op0 = expand_expr (exp: arg,
5352 target: subtarget && GET_MODE (subtarget) == target_mode
5353 ? subtarget : NULL_RTX,
5354 mode: target_mode, modifier: EXPAND_NORMAL);
5355 if (GET_MODE (op0) != target_mode)
5356 op0 = convert_to_mode (target_mode, op0, 1);
5357
5358 target = expand_unop (target_mode, bswap_optab, op0, target, 1);
5359
5360 gcc_assert (target);
5361
5362 return convert_to_mode (target_mode, target, 1);
5363}
5364
5365/* Expand a call to a unary builtin in EXP.
5366 Return NULL_RTX if a normal call should be emitted rather than expanding the
5367 function in-line. If convenient, the result should be placed in TARGET.
5368 SUBTARGET may be used as the target for computing one of EXP's operands. */
5369
5370static rtx
5371expand_builtin_unop (machine_mode target_mode, tree exp, rtx target,
5372 rtx subtarget, optab op_optab)
5373{
5374 rtx op0;
5375
5376 if (!validate_arglist (callexpr: exp, INTEGER_TYPE, VOID_TYPE))
5377 return NULL_RTX;
5378
5379 /* Compute the argument. */
5380 op0 = expand_expr (CALL_EXPR_ARG (exp, 0),
5381 target: (subtarget
5382 && (TYPE_MODE (TREE_TYPE (CALL_EXPR_ARG (exp, 0)))
5383 == GET_MODE (subtarget))) ? subtarget : NULL_RTX,
5384 VOIDmode, modifier: EXPAND_NORMAL);
5385 /* Compute op, into TARGET if possible.
5386 Set TARGET to wherever the result comes back. */
5387 target = expand_unop (TYPE_MODE (TREE_TYPE (CALL_EXPR_ARG (exp, 0))),
5388 op_optab, op0, target, op_optab != clrsb_optab);
5389 gcc_assert (target);
5390
5391 return convert_to_mode (target_mode, target, 0);
5392}
5393
5394/* Expand a call to __builtin_expect. We just return our argument
5395 as the builtin_expect semantic should've been already executed by
5396 tree branch prediction pass. */
5397
5398static rtx
5399expand_builtin_expect (tree exp, rtx target)
5400{
5401 tree arg;
5402
5403 if (call_expr_nargs (exp) < 2)
5404 return const0_rtx;
5405 arg = CALL_EXPR_ARG (exp, 0);
5406
5407 target = expand_expr (exp: arg, target, VOIDmode, modifier: EXPAND_NORMAL);
5408 /* When guessing was done, the hints should be already stripped away. */
5409 gcc_assert (!flag_guess_branch_prob
5410 || optimize == 0 || seen_error ());
5411 return target;
5412}
5413
5414/* Expand a call to __builtin_expect_with_probability. We just return our
5415 argument as the builtin_expect semantic should've been already executed by
5416 tree branch prediction pass. */
5417
5418static rtx
5419expand_builtin_expect_with_probability (tree exp, rtx target)
5420{
5421 tree arg;
5422
5423 if (call_expr_nargs (exp) < 3)
5424 return const0_rtx;
5425 arg = CALL_EXPR_ARG (exp, 0);
5426
5427 target = expand_expr (exp: arg, target, VOIDmode, modifier: EXPAND_NORMAL);
5428 /* When guessing was done, the hints should be already stripped away. */
5429 gcc_assert (!flag_guess_branch_prob
5430 || optimize == 0 || seen_error ());
5431 return target;
5432}
5433
5434
5435/* Expand a call to __builtin_assume_aligned. We just return our first
5436 argument as the builtin_assume_aligned semantic should've been already
5437 executed by CCP. */
5438
5439static rtx
5440expand_builtin_assume_aligned (tree exp, rtx target)
5441{
5442 if (call_expr_nargs (exp) < 2)
5443 return const0_rtx;
5444 target = expand_expr (CALL_EXPR_ARG (exp, 0), target, VOIDmode,
5445 modifier: EXPAND_NORMAL);
5446 gcc_assert (!TREE_SIDE_EFFECTS (CALL_EXPR_ARG (exp, 1))
5447 && (call_expr_nargs (exp) < 3
5448 || !TREE_SIDE_EFFECTS (CALL_EXPR_ARG (exp, 2))));
5449 return target;
5450}
5451
5452void
5453expand_builtin_trap (void)
5454{
5455 if (targetm.have_trap ())
5456 {
5457 rtx_insn *insn = emit_insn (targetm.gen_trap ());
5458 /* For trap insns when not accumulating outgoing args force
5459 REG_ARGS_SIZE note to prevent crossjumping of calls with
5460 different args sizes. */
5461 if (!ACCUMULATE_OUTGOING_ARGS)
5462 add_args_size_note (insn, stack_pointer_delta);
5463 }
5464 else
5465 {
5466 tree fn = builtin_decl_implicit (fncode: BUILT_IN_ABORT);
5467 tree call_expr = build_call_expr (fn, 0);
5468 expand_call (call_expr, NULL_RTX, false);
5469 }
5470
5471 emit_barrier ();
5472}
5473
5474/* Expand a call to __builtin_unreachable. We do nothing except emit
5475 a barrier saying that control flow will not pass here.
5476
5477 It is the responsibility of the program being compiled to ensure
5478 that control flow does never reach __builtin_unreachable. */
5479static void
5480expand_builtin_unreachable (void)
5481{
5482 /* Use gimple_build_builtin_unreachable or builtin_decl_unreachable
5483 to avoid this. */
5484 gcc_checking_assert (!sanitize_flags_p (SANITIZE_UNREACHABLE));
5485 emit_barrier ();
5486}
5487
5488/* Expand EXP, a call to fabs, fabsf or fabsl.
5489 Return NULL_RTX if a normal call should be emitted rather than expanding
5490 the function inline. If convenient, the result should be placed
5491 in TARGET. SUBTARGET may be used as the target for computing
5492 the operand. */
5493
5494static rtx
5495expand_builtin_fabs (tree exp, rtx target, rtx subtarget)
5496{
5497 machine_mode mode;
5498 tree arg;
5499 rtx op0;
5500
5501 if (!validate_arglist (callexpr: exp, REAL_TYPE, VOID_TYPE))
5502 return NULL_RTX;
5503
5504 arg = CALL_EXPR_ARG (exp, 0);
5505 CALL_EXPR_ARG (exp, 0) = arg = builtin_save_expr (exp: arg);
5506 mode = TYPE_MODE (TREE_TYPE (arg));
5507 op0 = expand_expr (exp: arg, target: subtarget, VOIDmode, modifier: EXPAND_NORMAL);
5508 return expand_abs (mode, op0, target, 0, safe_from_p (target, arg, 1));
5509}
5510
5511/* Expand EXP, a call to copysign, copysignf, or copysignl.
5512 Return NULL is a normal call should be emitted rather than expanding the
5513 function inline. If convenient, the result should be placed in TARGET.
5514 SUBTARGET may be used as the target for computing the operand. */
5515
5516static rtx
5517expand_builtin_copysign (tree exp, rtx target, rtx subtarget)
5518{
5519 rtx op0, op1;
5520 tree arg;
5521
5522 if (!validate_arglist (callexpr: exp, REAL_TYPE, REAL_TYPE, VOID_TYPE))
5523 return NULL_RTX;
5524
5525 arg = CALL_EXPR_ARG (exp, 0);
5526 op0 = expand_expr (exp: arg, target: subtarget, VOIDmode, modifier: EXPAND_NORMAL);
5527
5528 arg = CALL_EXPR_ARG (exp, 1);
5529 op1 = expand_normal (exp: arg);
5530
5531 return expand_copysign (op0, op1, target);
5532}
5533
5534/* Emit a call to __builtin___clear_cache. */
5535
5536void
5537default_emit_call_builtin___clear_cache (rtx begin, rtx end)
5538{
5539 rtx callee = gen_rtx_SYMBOL_REF (Pmode,
5540 BUILTIN_ASM_NAME_PTR
5541 (BUILT_IN_CLEAR_CACHE));
5542
5543 emit_library_call (fun: callee,
5544 fn_type: LCT_NORMAL, VOIDmode,
5545 convert_memory_address (ptr_mode, begin), arg1_mode: ptr_mode,
5546 convert_memory_address (ptr_mode, end), arg2_mode: ptr_mode);
5547}
5548
5549/* Emit a call to __builtin___clear_cache, unless the target specifies
5550 it as do-nothing. This function can be used by trampoline
5551 finalizers to duplicate the effects of expanding a call to the
5552 clear_cache builtin. */
5553
5554void
5555maybe_emit_call_builtin___clear_cache (rtx begin, rtx end)
5556{
5557 gcc_assert ((GET_MODE (begin) == ptr_mode || GET_MODE (begin) == Pmode
5558 || CONST_INT_P (begin))
5559 && (GET_MODE (end) == ptr_mode || GET_MODE (end) == Pmode
5560 || CONST_INT_P (end)));
5561
5562 if (targetm.have_clear_cache ())
5563 {
5564 /* We have a "clear_cache" insn, and it will handle everything. */
5565 class expand_operand ops[2];
5566
5567 create_address_operand (op: &ops[0], value: begin);
5568 create_address_operand (op: &ops[1], value: end);
5569
5570 if (maybe_expand_insn (icode: targetm.code_for_clear_cache, nops: 2, ops))
5571 return;
5572 }
5573 else
5574 {
5575#ifndef CLEAR_INSN_CACHE
5576 /* There is no "clear_cache" insn, and __clear_cache() in libgcc
5577 does nothing. There is no need to call it. Do nothing. */
5578 return;
5579#endif /* CLEAR_INSN_CACHE */
5580 }
5581
5582 targetm.calls.emit_call_builtin___clear_cache (begin, end);
5583}
5584
5585/* Expand a call to __builtin___clear_cache. */
5586
5587static void
5588expand_builtin___clear_cache (tree exp)
5589{
5590 tree begin, end;
5591 rtx begin_rtx, end_rtx;
5592
5593 /* We must not expand to a library call. If we did, any
5594 fallback library function in libgcc that might contain a call to
5595 __builtin___clear_cache() would recurse infinitely. */
5596 if (!validate_arglist (callexpr: exp, POINTER_TYPE, POINTER_TYPE, VOID_TYPE))
5597 {
5598 error ("both arguments to %<__builtin___clear_cache%> must be pointers");
5599 return;
5600 }
5601
5602 begin = CALL_EXPR_ARG (exp, 0);
5603 begin_rtx = expand_expr (exp: begin, NULL_RTX, Pmode, modifier: EXPAND_NORMAL);
5604
5605 end = CALL_EXPR_ARG (exp, 1);
5606 end_rtx = expand_expr (exp: end, NULL_RTX, Pmode, modifier: EXPAND_NORMAL);
5607
5608 maybe_emit_call_builtin___clear_cache (begin: begin_rtx, end: end_rtx);
5609}
5610
5611/* Given a trampoline address, make sure it satisfies TRAMPOLINE_ALIGNMENT. */
5612
5613static rtx
5614round_trampoline_addr (rtx tramp)
5615{
5616 rtx temp, addend, mask;
5617
5618 /* If we don't need too much alignment, we'll have been guaranteed
5619 proper alignment by get_trampoline_type. */
5620 if (TRAMPOLINE_ALIGNMENT <= STACK_BOUNDARY)
5621 return tramp;
5622
5623 /* Round address up to desired boundary. */
5624 temp = gen_reg_rtx (Pmode);
5625 addend = gen_int_mode (TRAMPOLINE_ALIGNMENT / BITS_PER_UNIT - 1, Pmode);
5626 mask = gen_int_mode (-TRAMPOLINE_ALIGNMENT / BITS_PER_UNIT, Pmode);
5627
5628 temp = expand_simple_binop (Pmode, PLUS, tramp, addend,
5629 temp, 0, OPTAB_LIB_WIDEN);
5630 tramp = expand_simple_binop (Pmode, AND, temp, mask,
5631 temp, 0, OPTAB_LIB_WIDEN);
5632
5633 return tramp;
5634}
5635
5636static rtx
5637expand_builtin_init_trampoline (tree exp, bool onstack)
5638{
5639 tree t_tramp, t_func, t_chain;
5640 rtx m_tramp, r_tramp, r_chain, tmp;
5641
5642 if (!validate_arglist (callexpr: exp, POINTER_TYPE, POINTER_TYPE,
5643 POINTER_TYPE, VOID_TYPE))
5644 return NULL_RTX;
5645
5646 t_tramp = CALL_EXPR_ARG (exp, 0);
5647 t_func = CALL_EXPR_ARG (exp, 1);
5648 t_chain = CALL_EXPR_ARG (exp, 2);
5649
5650 r_tramp = expand_normal (exp: t_tramp);
5651 m_tramp = gen_rtx_MEM (BLKmode, r_tramp);
5652 MEM_NOTRAP_P (m_tramp) = 1;
5653
5654 /* If ONSTACK, the TRAMP argument should be the address of a field
5655 within the local function's FRAME decl. Either way, let's see if
5656 we can fill in the MEM_ATTRs for this memory. */
5657 if (TREE_CODE (t_tramp) == ADDR_EXPR)
5658 set_mem_attributes (m_tramp, TREE_OPERAND (t_tramp, 0), true);
5659
5660 /* Creator of a heap trampoline is responsible for making sure the
5661 address is aligned to at least STACK_BOUNDARY. Normally malloc
5662 will ensure this anyhow. */
5663 tmp = round_trampoline_addr (tramp: r_tramp);
5664 if (tmp != r_tramp)
5665 {
5666 m_tramp = change_address (m_tramp, BLKmode, tmp);
5667 set_mem_align (m_tramp, TRAMPOLINE_ALIGNMENT);
5668 set_mem_size (m_tramp, TRAMPOLINE_SIZE);
5669 }
5670
5671 /* The FUNC argument should be the address of the nested function.
5672 Extract the actual function decl to pass to the hook. */
5673 gcc_assert (TREE_CODE (t_func) == ADDR_EXPR);
5674 t_func = TREE_OPERAND (t_func, 0);
5675 gcc_assert (TREE_CODE (t_func) == FUNCTION_DECL);
5676
5677 r_chain = expand_normal (exp: t_chain);
5678
5679 /* Generate insns to initialize the trampoline. */
5680 targetm.calls.trampoline_init (m_tramp, t_func, r_chain);
5681
5682 if (onstack)
5683 {
5684 trampolines_created = 1;
5685
5686 if (targetm.calls.custom_function_descriptors != 0)
5687 warning_at (DECL_SOURCE_LOCATION (t_func), OPT_Wtrampolines,
5688 "trampoline generated for nested function %qD", t_func);
5689 }
5690
5691 return const0_rtx;
5692}
5693
5694static rtx
5695expand_builtin_adjust_trampoline (tree exp)
5696{
5697 rtx tramp;
5698
5699 if (!validate_arglist (callexpr: exp, POINTER_TYPE, VOID_TYPE))
5700 return NULL_RTX;
5701
5702 tramp = expand_normal (CALL_EXPR_ARG (exp, 0));
5703 tramp = round_trampoline_addr (tramp);
5704 if (targetm.calls.trampoline_adjust_address)
5705 tramp = targetm.calls.trampoline_adjust_address (tramp);
5706
5707 return tramp;
5708}
5709
5710/* Expand a call to the builtin descriptor initialization routine.
5711 A descriptor is made up of a couple of pointers to the static
5712 chain and the code entry in this order. */
5713
5714static rtx
5715expand_builtin_init_descriptor (tree exp)
5716{
5717 tree t_descr, t_func, t_chain;
5718 rtx m_descr, r_descr, r_func, r_chain;
5719
5720 if (!validate_arglist (callexpr: exp, POINTER_TYPE, POINTER_TYPE, POINTER_TYPE,
5721 VOID_TYPE))
5722 return NULL_RTX;
5723
5724 t_descr = CALL_EXPR_ARG (exp, 0);
5725 t_func = CALL_EXPR_ARG (exp, 1);
5726 t_chain = CALL_EXPR_ARG (exp, 2);
5727
5728 r_descr = expand_normal (exp: t_descr);
5729 m_descr = gen_rtx_MEM (BLKmode, r_descr);
5730 MEM_NOTRAP_P (m_descr) = 1;
5731 set_mem_align (m_descr, GET_MODE_ALIGNMENT (ptr_mode));
5732
5733 r_func = expand_normal (exp: t_func);
5734 r_chain = expand_normal (exp: t_chain);
5735
5736 /* Generate insns to initialize the descriptor. */
5737 emit_move_insn (adjust_address_nv (m_descr, ptr_mode, 0), r_chain);
5738 emit_move_insn (adjust_address_nv (m_descr, ptr_mode,
5739 POINTER_SIZE / BITS_PER_UNIT), r_func);
5740
5741 return const0_rtx;
5742}
5743
5744/* Expand a call to the builtin descriptor adjustment routine. */
5745
5746static rtx
5747expand_builtin_adjust_descriptor (tree exp)
5748{
5749 rtx tramp;
5750
5751 if (!validate_arglist (callexpr: exp, POINTER_TYPE, VOID_TYPE))
5752 return NULL_RTX;
5753
5754 tramp = expand_normal (CALL_EXPR_ARG (exp, 0));
5755
5756 /* Unalign the descriptor to allow runtime identification. */
5757 tramp = plus_constant (ptr_mode, tramp,
5758 targetm.calls.custom_function_descriptors);
5759
5760 return force_operand (tramp, NULL_RTX);
5761}
5762
5763/* Expand the call EXP to the built-in signbit, signbitf or signbitl
5764 function. The function first checks whether the back end provides
5765 an insn to implement signbit for the respective mode. If not, it
5766 checks whether the floating point format of the value is such that
5767 the sign bit can be extracted. If that is not the case, error out.
5768 EXP is the expression that is a call to the builtin function; if
5769 convenient, the result should be placed in TARGET. */
5770static rtx
5771expand_builtin_signbit (tree exp, rtx target)
5772{
5773 const struct real_format *fmt;
5774 scalar_float_mode fmode;
5775 scalar_int_mode rmode, imode;
5776 tree arg;
5777 int word, bitpos;
5778 enum insn_code icode;
5779 rtx temp;
5780 location_t loc = EXPR_LOCATION (exp);
5781
5782 if (!validate_arglist (callexpr: exp, REAL_TYPE, VOID_TYPE))
5783 return NULL_RTX;
5784
5785 arg = CALL_EXPR_ARG (exp, 0);
5786 fmode = SCALAR_FLOAT_TYPE_MODE (TREE_TYPE (arg));
5787 rmode = SCALAR_INT_TYPE_MODE (TREE_TYPE (exp));
5788 fmt = REAL_MODE_FORMAT (fmode);
5789
5790 arg = builtin_save_expr (exp: arg);
5791
5792 /* Expand the argument yielding a RTX expression. */
5793 temp = expand_normal (exp: arg);
5794
5795 /* Check if the back end provides an insn that handles signbit for the
5796 argument's mode. */
5797 icode = optab_handler (op: signbit_optab, mode: fmode);
5798 if (icode != CODE_FOR_nothing)
5799 {
5800 rtx_insn *last = get_last_insn ();
5801 rtx this_target = gen_reg_rtx (TYPE_MODE (TREE_TYPE (exp)));
5802 if (maybe_emit_unop_insn (icode, this_target, temp, UNKNOWN))
5803 return this_target;
5804 delete_insns_since (last);
5805 }
5806
5807 /* For floating point formats without a sign bit, implement signbit
5808 as "ARG < 0.0". */
5809 bitpos = fmt->signbit_ro;
5810 if (bitpos < 0)
5811 {
5812 /* But we can't do this if the format supports signed zero. */
5813 gcc_assert (!fmt->has_signed_zero || !HONOR_SIGNED_ZEROS (fmode));
5814
5815 arg = fold_build2_loc (loc, LT_EXPR, TREE_TYPE (exp), arg,
5816 build_real (TREE_TYPE (arg), dconst0));
5817 return expand_expr (exp: arg, target, VOIDmode, modifier: EXPAND_NORMAL);
5818 }
5819
5820 if (GET_MODE_SIZE (mode: fmode) <= UNITS_PER_WORD)
5821 {
5822 imode = int_mode_for_mode (fmode).require ();
5823 temp = gen_lowpart (imode, temp);
5824 }
5825 else
5826 {
5827 imode = word_mode;
5828 /* Handle targets with different FP word orders. */
5829 if (FLOAT_WORDS_BIG_ENDIAN)
5830 word = (GET_MODE_BITSIZE (mode: fmode) - bitpos) / BITS_PER_WORD;
5831 else
5832 word = bitpos / BITS_PER_WORD;
5833 temp = operand_subword_force (temp, word, fmode);
5834 bitpos = bitpos % BITS_PER_WORD;
5835 }
5836
5837 /* Force the intermediate word_mode (or narrower) result into a
5838 register. This avoids attempting to create paradoxical SUBREGs
5839 of floating point modes below. */
5840 temp = force_reg (imode, temp);
5841
5842 /* If the bitpos is within the "result mode" lowpart, the operation
5843 can be implement with a single bitwise AND. Otherwise, we need
5844 a right shift and an AND. */
5845
5846 if (bitpos < GET_MODE_BITSIZE (mode: rmode))
5847 {
5848 wide_int mask = wi::set_bit_in_zero (bit: bitpos, precision: GET_MODE_PRECISION (mode: rmode));
5849
5850 if (GET_MODE_SIZE (mode: imode) > GET_MODE_SIZE (mode: rmode))
5851 temp = gen_lowpart (rmode, temp);
5852 temp = expand_binop (rmode, and_optab, temp,
5853 immed_wide_int_const (mask, rmode),
5854 NULL_RTX, 1, OPTAB_LIB_WIDEN);
5855 }
5856 else
5857 {
5858 /* Perform a logical right shift to place the signbit in the least
5859 significant bit, then truncate the result to the desired mode
5860 and mask just this bit. */
5861 temp = expand_shift (RSHIFT_EXPR, imode, temp, bitpos, NULL_RTX, 1);
5862 temp = gen_lowpart (rmode, temp);
5863 temp = expand_binop (rmode, and_optab, temp, const1_rtx,
5864 NULL_RTX, 1, OPTAB_LIB_WIDEN);
5865 }
5866
5867 return temp;
5868}
5869
5870/* Expand fork or exec calls. TARGET is the desired target of the
5871 call. EXP is the call. FN is the
5872 identificator of the actual function. IGNORE is nonzero if the
5873 value is to be ignored. */
5874
5875static rtx
5876expand_builtin_fork_or_exec (tree fn, tree exp, rtx target, int ignore)
5877{
5878 tree id, decl;
5879 tree call;
5880
5881 /* If we are not profiling, just call the function. */
5882 if (!profile_arc_flag)
5883 return NULL_RTX;
5884
5885 /* Otherwise call the wrapper. This should be equivalent for the rest of
5886 compiler, so the code does not diverge, and the wrapper may run the
5887 code necessary for keeping the profiling sane. */
5888
5889 switch (DECL_FUNCTION_CODE (decl: fn))
5890 {
5891 case BUILT_IN_FORK:
5892 id = get_identifier ("__gcov_fork");
5893 break;
5894
5895 case BUILT_IN_EXECL:
5896 id = get_identifier ("__gcov_execl");
5897 break;
5898
5899 case BUILT_IN_EXECV:
5900 id = get_identifier ("__gcov_execv");
5901 break;
5902
5903 case BUILT_IN_EXECLP:
5904 id = get_identifier ("__gcov_execlp");
5905 break;
5906
5907 case BUILT_IN_EXECLE:
5908 id = get_identifier ("__gcov_execle");
5909 break;
5910
5911 case BUILT_IN_EXECVP:
5912 id = get_identifier ("__gcov_execvp");
5913 break;
5914
5915 case BUILT_IN_EXECVE:
5916 id = get_identifier ("__gcov_execve");
5917 break;
5918
5919 default:
5920 gcc_unreachable ();
5921 }
5922
5923 decl = build_decl (DECL_SOURCE_LOCATION (fn),
5924 FUNCTION_DECL, id, TREE_TYPE (fn));
5925 DECL_EXTERNAL (decl) = 1;
5926 TREE_PUBLIC (decl) = 1;
5927 DECL_ARTIFICIAL (decl) = 1;
5928 TREE_NOTHROW (decl) = 1;
5929 DECL_VISIBILITY (decl) = VISIBILITY_DEFAULT;
5930 DECL_VISIBILITY_SPECIFIED (decl) = 1;
5931 call = rewrite_call_expr (EXPR_LOCATION (exp), exp, 0, decl, 0);
5932 return expand_call (call, target, ignore);
5933 }
5934
5935
5936
5937/* Reconstitute a mode for a __sync intrinsic operation. Since the type of
5938 the pointer in these functions is void*, the tree optimizers may remove
5939 casts. The mode computed in expand_builtin isn't reliable either, due
5940 to __sync_bool_compare_and_swap.
5941
5942 FCODE_DIFF should be fcode - base, where base is the FOO_1 code for the
5943 group of builtins. This gives us log2 of the mode size. */
5944
5945static inline machine_mode
5946get_builtin_sync_mode (int fcode_diff)
5947{
5948 /* The size is not negotiable, so ask not to get BLKmode in return
5949 if the target indicates that a smaller size would be better. */
5950 return int_mode_for_size (BITS_PER_UNIT << fcode_diff, limit: 0).require ();
5951}
5952
5953/* Expand the memory expression LOC and return the appropriate memory operand
5954 for the builtin_sync operations. */
5955
5956static rtx
5957get_builtin_sync_mem (tree loc, machine_mode mode)
5958{
5959 rtx addr, mem;
5960 int addr_space = TYPE_ADDR_SPACE (POINTER_TYPE_P (TREE_TYPE (loc))
5961 ? TREE_TYPE (TREE_TYPE (loc))
5962 : TREE_TYPE (loc));
5963 scalar_int_mode addr_mode = targetm.addr_space.address_mode (addr_space);
5964
5965 addr = expand_expr (exp: loc, NULL_RTX, mode: addr_mode, modifier: EXPAND_SUM);
5966 addr = convert_memory_address (addr_mode, addr);
5967
5968 /* Note that we explicitly do not want any alias information for this
5969 memory, so that we kill all other live memories. Otherwise we don't
5970 satisfy the full barrier semantics of the intrinsic. */
5971 mem = gen_rtx_MEM (mode, addr);
5972
5973 set_mem_addr_space (mem, addr_space);
5974
5975 mem = validize_mem (mem);
5976
5977 /* The alignment needs to be at least according to that of the mode. */
5978 set_mem_align (mem, MAX (GET_MODE_ALIGNMENT (mode),
5979 get_pointer_alignment (loc)));
5980 set_mem_alias_set (mem, ALIAS_SET_MEMORY_BARRIER);
5981 MEM_VOLATILE_P (mem) = 1;
5982
5983 return mem;
5984}
5985
5986/* Make sure an argument is in the right mode.
5987 EXP is the tree argument.
5988 MODE is the mode it should be in. */
5989
5990static rtx
5991expand_expr_force_mode (tree exp, machine_mode mode)
5992{
5993 rtx val;
5994 machine_mode old_mode;
5995
5996 if (TREE_CODE (exp) == SSA_NAME
5997 && TYPE_MODE (TREE_TYPE (exp)) != mode)
5998 {
5999 /* Undo argument promotion if possible, as combine might not
6000 be able to do it later due to MEM_VOLATILE_P uses in the
6001 patterns. */
6002 gimple *g = get_gimple_for_ssa_name (exp);
6003 if (g && gimple_assign_cast_p (s: g))
6004 {
6005 tree rhs = gimple_assign_rhs1 (gs: g);
6006 tree_code code = gimple_assign_rhs_code (gs: g);
6007 if (CONVERT_EXPR_CODE_P (code)
6008 && TYPE_MODE (TREE_TYPE (rhs)) == mode
6009 && INTEGRAL_TYPE_P (TREE_TYPE (exp))
6010 && INTEGRAL_TYPE_P (TREE_TYPE (rhs))
6011 && (TYPE_PRECISION (TREE_TYPE (exp))
6012 > TYPE_PRECISION (TREE_TYPE (rhs))))
6013 exp = rhs;
6014 }
6015 }
6016
6017 val = expand_expr (exp, NULL_RTX, mode, modifier: EXPAND_NORMAL);
6018 /* If VAL is promoted to a wider mode, convert it back to MODE. Take care
6019 of CONST_INTs, where we know the old_mode only from the call argument. */
6020
6021 old_mode = GET_MODE (val);
6022 if (old_mode == VOIDmode)
6023 old_mode = TYPE_MODE (TREE_TYPE (exp));
6024 val = convert_modes (mode, oldmode: old_mode, x: val, unsignedp: 1);
6025 return val;
6026}
6027
6028
6029/* Expand the __sync_xxx_and_fetch and __sync_fetch_and_xxx intrinsics.
6030 EXP is the CALL_EXPR. CODE is the rtx code
6031 that corresponds to the arithmetic or logical operation from the name;
6032 an exception here is that NOT actually means NAND. TARGET is an optional
6033 place for us to store the results; AFTER is true if this is the
6034 fetch_and_xxx form. */
6035
6036static rtx
6037expand_builtin_sync_operation (machine_mode mode, tree exp,
6038 enum rtx_code code, bool after,
6039 rtx target)
6040{
6041 rtx val, mem;
6042 location_t loc = EXPR_LOCATION (exp);
6043
6044 if (code == NOT && warn_sync_nand)
6045 {
6046 tree fndecl = get_callee_fndecl (exp);
6047 enum built_in_function fcode = DECL_FUNCTION_CODE (decl: fndecl);
6048
6049 static bool warned_f_a_n, warned_n_a_f;
6050
6051 switch (fcode)
6052 {
6053 case BUILT_IN_SYNC_FETCH_AND_NAND_1:
6054 case BUILT_IN_SYNC_FETCH_AND_NAND_2:
6055 case BUILT_IN_SYNC_FETCH_AND_NAND_4:
6056 case BUILT_IN_SYNC_FETCH_AND_NAND_8:
6057 case BUILT_IN_SYNC_FETCH_AND_NAND_16:
6058 if (warned_f_a_n)
6059 break;
6060
6061 fndecl = builtin_decl_implicit (fncode: BUILT_IN_SYNC_FETCH_AND_NAND_N);
6062 inform (loc, "%qD changed semantics in GCC 4.4", fndecl);
6063 warned_f_a_n = true;
6064 break;
6065
6066 case BUILT_IN_SYNC_NAND_AND_FETCH_1:
6067 case BUILT_IN_SYNC_NAND_AND_FETCH_2:
6068 case BUILT_IN_SYNC_NAND_AND_FETCH_4:
6069 case BUILT_IN_SYNC_NAND_AND_FETCH_8:
6070 case BUILT_IN_SYNC_NAND_AND_FETCH_16:
6071 if (warned_n_a_f)
6072 break;
6073
6074 fndecl = builtin_decl_implicit (fncode: BUILT_IN_SYNC_NAND_AND_FETCH_N);
6075 inform (loc, "%qD changed semantics in GCC 4.4", fndecl);
6076 warned_n_a_f = true;
6077 break;
6078
6079 default:
6080 gcc_unreachable ();
6081 }
6082 }
6083
6084 /* Expand the operands. */
6085 mem = get_builtin_sync_mem (CALL_EXPR_ARG (exp, 0), mode);
6086 val = expand_expr_force_mode (CALL_EXPR_ARG (exp, 1), mode);
6087
6088 return expand_atomic_fetch_op (target, mem, val, code, MEMMODEL_SYNC_SEQ_CST,
6089 after);
6090}
6091
6092/* Expand the __sync_val_compare_and_swap and __sync_bool_compare_and_swap
6093 intrinsics. EXP is the CALL_EXPR. IS_BOOL is
6094 true if this is the boolean form. TARGET is a place for us to store the
6095 results; this is NOT optional if IS_BOOL is true. */
6096
6097static rtx
6098expand_builtin_compare_and_swap (machine_mode mode, tree exp,
6099 bool is_bool, rtx target)
6100{
6101 rtx old_val, new_val, mem;
6102 rtx *pbool, *poval;
6103
6104 /* Expand the operands. */
6105 mem = get_builtin_sync_mem (CALL_EXPR_ARG (exp, 0), mode);
6106 old_val = expand_expr_force_mode (CALL_EXPR_ARG (exp, 1), mode);
6107 new_val = expand_expr_force_mode (CALL_EXPR_ARG (exp, 2), mode);
6108
6109 pbool = poval = NULL;
6110 if (target != const0_rtx)
6111 {
6112 if (is_bool)
6113 pbool = &target;
6114 else
6115 poval = &target;
6116 }
6117 if (!expand_atomic_compare_and_swap (pbool, poval, mem, old_val, new_val,
6118 false, MEMMODEL_SYNC_SEQ_CST,
6119 MEMMODEL_SYNC_SEQ_CST))
6120 return NULL_RTX;
6121
6122 return target;
6123}
6124
6125/* Expand the __sync_lock_test_and_set intrinsic. Note that the most
6126 general form is actually an atomic exchange, and some targets only
6127 support a reduced form with the second argument being a constant 1.
6128 EXP is the CALL_EXPR; TARGET is an optional place for us to store
6129 the results. */
6130
6131static rtx
6132expand_builtin_sync_lock_test_and_set (machine_mode mode, tree exp,
6133 rtx target)
6134{
6135 rtx val, mem;
6136
6137 /* Expand the operands. */
6138 mem = get_builtin_sync_mem (CALL_EXPR_ARG (exp, 0), mode);
6139 val = expand_expr_force_mode (CALL_EXPR_ARG (exp, 1), mode);
6140
6141 return expand_sync_lock_test_and_set (target, mem, val);
6142}
6143
6144/* Expand the __sync_lock_release intrinsic. EXP is the CALL_EXPR. */
6145
6146static void
6147expand_builtin_sync_lock_release (machine_mode mode, tree exp)
6148{
6149 rtx mem;
6150
6151 /* Expand the operands. */
6152 mem = get_builtin_sync_mem (CALL_EXPR_ARG (exp, 0), mode);
6153
6154 expand_atomic_store (mem, const0_rtx, MEMMODEL_SYNC_RELEASE, true);
6155}
6156
6157/* Given an integer representing an ``enum memmodel'', verify its
6158 correctness and return the memory model enum. */
6159
6160static enum memmodel
6161get_memmodel (tree exp)
6162{
6163 /* If the parameter is not a constant, it's a run time value so we'll just
6164 convert it to MEMMODEL_SEQ_CST to avoid annoying runtime checking. */
6165 if (TREE_CODE (exp) != INTEGER_CST)
6166 return MEMMODEL_SEQ_CST;
6167
6168 rtx op = expand_normal (exp);
6169
6170 unsigned HOST_WIDE_INT val = INTVAL (op);
6171 if (targetm.memmodel_check)
6172 val = targetm.memmodel_check (val);
6173 else if (val & ~MEMMODEL_MASK)
6174 return MEMMODEL_SEQ_CST;
6175
6176 /* Should never see a user explicit SYNC memodel model, so >= LAST works. */
6177 if (memmodel_base (val) >= MEMMODEL_LAST)
6178 return MEMMODEL_SEQ_CST;
6179
6180 /* Workaround for Bugzilla 59448. GCC doesn't track consume properly, so
6181 be conservative and promote consume to acquire. */
6182 if (val == MEMMODEL_CONSUME)
6183 val = MEMMODEL_ACQUIRE;
6184
6185 return (enum memmodel) val;
6186}
6187
6188/* Expand the __atomic_exchange intrinsic:
6189 TYPE __atomic_exchange (TYPE *object, TYPE desired, enum memmodel)
6190 EXP is the CALL_EXPR.
6191 TARGET is an optional place for us to store the results. */
6192
6193static rtx
6194expand_builtin_atomic_exchange (machine_mode mode, tree exp, rtx target)
6195{
6196 rtx val, mem;
6197 enum memmodel model;
6198
6199 model = get_memmodel (CALL_EXPR_ARG (exp, 2));
6200
6201 if (!flag_inline_atomics)
6202 return NULL_RTX;
6203
6204 /* Expand the operands. */
6205 mem = get_builtin_sync_mem (CALL_EXPR_ARG (exp, 0), mode);
6206 val = expand_expr_force_mode (CALL_EXPR_ARG (exp, 1), mode);
6207
6208 return expand_atomic_exchange (target, mem, val, model);
6209}
6210
6211/* Expand the __atomic_compare_exchange intrinsic:
6212 bool __atomic_compare_exchange (TYPE *object, TYPE *expect,
6213 TYPE desired, BOOL weak,
6214 enum memmodel success,
6215 enum memmodel failure)
6216 EXP is the CALL_EXPR.
6217 TARGET is an optional place for us to store the results. */
6218
6219static rtx
6220expand_builtin_atomic_compare_exchange (machine_mode mode, tree exp,
6221 rtx target)
6222{
6223 rtx expect, desired, mem, oldval;
6224 rtx_code_label *label;
6225 tree weak;
6226 bool is_weak;
6227
6228 memmodel success = get_memmodel (CALL_EXPR_ARG (exp, 4));
6229 memmodel failure = get_memmodel (CALL_EXPR_ARG (exp, 5));
6230
6231 if (failure > success)
6232 success = MEMMODEL_SEQ_CST;
6233
6234 if (is_mm_release (model: failure) || is_mm_acq_rel (model: failure))
6235 {
6236 failure = MEMMODEL_SEQ_CST;
6237 success = MEMMODEL_SEQ_CST;
6238 }
6239
6240
6241 if (!flag_inline_atomics)
6242 return NULL_RTX;
6243
6244 /* Expand the operands. */
6245 mem = get_builtin_sync_mem (CALL_EXPR_ARG (exp, 0), mode);
6246
6247 expect = expand_normal (CALL_EXPR_ARG (exp, 1));
6248 expect = convert_memory_address (Pmode, expect);
6249 expect = gen_rtx_MEM (mode, expect);
6250 desired = expand_expr_force_mode (CALL_EXPR_ARG (exp, 2), mode);
6251
6252 weak = CALL_EXPR_ARG (exp, 3);
6253 is_weak = false;
6254 if (tree_fits_shwi_p (weak) && tree_to_shwi (weak) != 0)
6255 is_weak = true;
6256
6257 if (target == const0_rtx)
6258 target = NULL;
6259
6260 /* Lest the rtl backend create a race condition with an imporoper store
6261 to memory, always create a new pseudo for OLDVAL. */
6262 oldval = NULL;
6263
6264 if (!expand_atomic_compare_and_swap (&target, &oldval, mem, expect, desired,
6265 is_weak, success, failure))
6266 return NULL_RTX;
6267
6268 /* Conditionally store back to EXPECT, lest we create a race condition
6269 with an improper store to memory. */
6270 /* ??? With a rearrangement of atomics at the gimple level, we can handle
6271 the normal case where EXPECT is totally private, i.e. a register. At
6272 which point the store can be unconditional. */
6273 label = gen_label_rtx ();
6274 emit_cmp_and_jump_insns (target, const0_rtx, NE, NULL,
6275 GET_MODE (target), 1, label);
6276 emit_move_insn (expect, oldval);
6277 emit_label (label);
6278
6279 return target;
6280}
6281
6282/* Helper function for expand_ifn_atomic_compare_exchange - expand
6283 internal ATOMIC_COMPARE_EXCHANGE call into __atomic_compare_exchange_N
6284 call. The weak parameter must be dropped to match the expected parameter
6285 list and the expected argument changed from value to pointer to memory
6286 slot. */
6287
6288static void
6289expand_ifn_atomic_compare_exchange_into_call (gcall *call, machine_mode mode)
6290{
6291 unsigned int z;
6292 vec<tree, va_gc> *vec;
6293
6294 vec_alloc (v&: vec, nelems: 5);
6295 vec->quick_push (obj: gimple_call_arg (gs: call, index: 0));
6296 tree expected = gimple_call_arg (gs: call, index: 1);
6297 rtx x = assign_stack_temp_for_type (mode, GET_MODE_SIZE (mode),
6298 TREE_TYPE (expected));
6299 rtx expd = expand_expr (exp: expected, target: x, mode, modifier: EXPAND_NORMAL);
6300 if (expd != x)
6301 emit_move_insn (x, expd);
6302 tree v = make_tree (TREE_TYPE (expected), x);
6303 vec->quick_push (obj: build1 (ADDR_EXPR,
6304 build_pointer_type (TREE_TYPE (expected)), v));
6305 vec->quick_push (obj: gimple_call_arg (gs: call, index: 2));
6306 /* Skip the boolean weak parameter. */
6307 for (z = 4; z < 6; z++)
6308 vec->quick_push (obj: gimple_call_arg (gs: call, index: z));
6309 /* At present we only have BUILT_IN_ATOMIC_COMPARE_EXCHANGE_{1,2,4,8,16}. */
6310 unsigned int bytes_log2 = exact_log2 (x: GET_MODE_SIZE (mode).to_constant ());
6311 gcc_assert (bytes_log2 < 5);
6312 built_in_function fncode
6313 = (built_in_function) ((int) BUILT_IN_ATOMIC_COMPARE_EXCHANGE_1
6314 + bytes_log2);
6315 tree fndecl = builtin_decl_explicit (fncode);
6316 tree fn = build1 (ADDR_EXPR, build_pointer_type (TREE_TYPE (fndecl)),
6317 fndecl);
6318 tree exp = build_call_vec (boolean_type_node, fn, vec);
6319 tree lhs = gimple_call_lhs (gs: call);
6320 rtx boolret = expand_call (exp, NULL_RTX, lhs == NULL_TREE);
6321 if (lhs)
6322 {
6323 rtx target = expand_expr (exp: lhs, NULL_RTX, VOIDmode, modifier: EXPAND_WRITE);
6324 if (GET_MODE (boolret) != mode)
6325 boolret = convert_modes (mode, GET_MODE (boolret), x: boolret, unsignedp: 1);
6326 x = force_reg (mode, x);
6327 write_complex_part (target, boolret, true, true);
6328 write_complex_part (target, x, false, false);
6329 }
6330}
6331
6332/* Expand IFN_ATOMIC_COMPARE_EXCHANGE internal function. */
6333
6334void
6335expand_ifn_atomic_compare_exchange (gcall *call)
6336{
6337 int size = tree_to_shwi (gimple_call_arg (gs: call, index: 3)) & 255;
6338 gcc_assert (size == 1 || size == 2 || size == 4 || size == 8 || size == 16);
6339 machine_mode mode = int_mode_for_size (BITS_PER_UNIT * size, limit: 0).require ();
6340
6341 memmodel success = get_memmodel (exp: gimple_call_arg (gs: call, index: 4));
6342 memmodel failure = get_memmodel (exp: gimple_call_arg (gs: call, index: 5));
6343
6344 if (failure > success)
6345 success = MEMMODEL_SEQ_CST;
6346
6347 if (is_mm_release (model: failure) || is_mm_acq_rel (model: failure))
6348 {
6349 failure = MEMMODEL_SEQ_CST;
6350 success = MEMMODEL_SEQ_CST;
6351 }
6352
6353 if (!flag_inline_atomics)
6354 {
6355 expand_ifn_atomic_compare_exchange_into_call (call, mode);
6356 return;
6357 }
6358
6359 /* Expand the operands. */
6360 rtx mem = get_builtin_sync_mem (loc: gimple_call_arg (gs: call, index: 0), mode);
6361
6362 rtx expect = expand_expr_force_mode (exp: gimple_call_arg (gs: call, index: 1), mode);
6363 rtx desired = expand_expr_force_mode (exp: gimple_call_arg (gs: call, index: 2), mode);
6364
6365 bool is_weak = (tree_to_shwi (gimple_call_arg (gs: call, index: 3)) & 256) != 0;
6366
6367 rtx boolret = NULL;
6368 rtx oldval = NULL;
6369
6370 if (!expand_atomic_compare_and_swap (&boolret, &oldval, mem, expect, desired,
6371 is_weak, success, failure))
6372 {
6373 expand_ifn_atomic_compare_exchange_into_call (call, mode);
6374 return;
6375 }
6376
6377 tree lhs = gimple_call_lhs (gs: call);
6378 if (lhs)
6379 {
6380 rtx target = expand_expr (exp: lhs, NULL_RTX, VOIDmode, modifier: EXPAND_WRITE);
6381 if (GET_MODE (boolret) != mode)
6382 boolret = convert_modes (mode, GET_MODE (boolret), x: boolret, unsignedp: 1);
6383 write_complex_part (target, boolret, true, true);
6384 write_complex_part (target, oldval, false, false);
6385 }
6386}
6387
6388/* Expand the __atomic_load intrinsic:
6389 TYPE __atomic_load (TYPE *object, enum memmodel)
6390 EXP is the CALL_EXPR.
6391 TARGET is an optional place for us to store the results. */
6392
6393static rtx
6394expand_builtin_atomic_load (machine_mode mode, tree exp, rtx target)
6395{
6396 memmodel model = get_memmodel (CALL_EXPR_ARG (exp, 1));
6397 if (is_mm_release (model) || is_mm_acq_rel (model))
6398 model = MEMMODEL_SEQ_CST;
6399
6400 if (!flag_inline_atomics)
6401 return NULL_RTX;
6402
6403 /* Expand the operand. */
6404 rtx mem = get_builtin_sync_mem (CALL_EXPR_ARG (exp, 0), mode);
6405
6406 return expand_atomic_load (target, mem, model);
6407}
6408
6409
6410/* Expand the __atomic_store intrinsic:
6411 void __atomic_store (TYPE *object, TYPE desired, enum memmodel)
6412 EXP is the CALL_EXPR.
6413 TARGET is an optional place for us to store the results. */
6414
6415static rtx
6416expand_builtin_atomic_store (machine_mode mode, tree exp)
6417{
6418 memmodel model = get_memmodel (CALL_EXPR_ARG (exp, 2));
6419 if (!(is_mm_relaxed (model) || is_mm_seq_cst (model)
6420 || is_mm_release (model)))
6421 model = MEMMODEL_SEQ_CST;
6422
6423 if (!flag_inline_atomics)
6424 return NULL_RTX;
6425
6426 /* Expand the operands. */
6427 rtx mem = get_builtin_sync_mem (CALL_EXPR_ARG (exp, 0), mode);
6428 rtx val = expand_expr_force_mode (CALL_EXPR_ARG (exp, 1), mode);
6429
6430 return expand_atomic_store (mem, val, model, false);
6431}
6432
6433/* Expand the __atomic_fetch_XXX intrinsic:
6434 TYPE __atomic_fetch_XXX (TYPE *object, TYPE val, enum memmodel)
6435 EXP is the CALL_EXPR.
6436 TARGET is an optional place for us to store the results.
6437 CODE is the operation, PLUS, MINUS, ADD, XOR, or IOR.
6438 FETCH_AFTER is true if returning the result of the operation.
6439 FETCH_AFTER is false if returning the value before the operation.
6440 IGNORE is true if the result is not used.
6441 EXT_CALL is the correct builtin for an external call if this cannot be
6442 resolved to an instruction sequence. */
6443
6444static rtx
6445expand_builtin_atomic_fetch_op (machine_mode mode, tree exp, rtx target,
6446 enum rtx_code code, bool fetch_after,
6447 bool ignore, enum built_in_function ext_call)
6448{
6449 rtx val, mem, ret;
6450 enum memmodel model;
6451 tree fndecl;
6452 tree addr;
6453
6454 model = get_memmodel (CALL_EXPR_ARG (exp, 2));
6455
6456 /* Expand the operands. */
6457 mem = get_builtin_sync_mem (CALL_EXPR_ARG (exp, 0), mode);
6458 val = expand_expr_force_mode (CALL_EXPR_ARG (exp, 1), mode);
6459
6460 /* Only try generating instructions if inlining is turned on. */
6461 if (flag_inline_atomics)
6462 {
6463 ret = expand_atomic_fetch_op (target, mem, val, code, model, fetch_after);
6464 if (ret)
6465 return ret;
6466 }
6467
6468 /* Return if a different routine isn't needed for the library call. */
6469 if (ext_call == BUILT_IN_NONE)
6470 return NULL_RTX;
6471
6472 /* Change the call to the specified function. */
6473 fndecl = get_callee_fndecl (exp);
6474 addr = CALL_EXPR_FN (exp);
6475 STRIP_NOPS (addr);
6476
6477 gcc_assert (TREE_OPERAND (addr, 0) == fndecl);
6478 TREE_OPERAND (addr, 0) = builtin_decl_explicit (fncode: ext_call);
6479
6480 /* If we will emit code after the call, the call cannot be a tail call.
6481 If it is emitted as a tail call, a barrier is emitted after it, and
6482 then all trailing code is removed. */
6483 if (!ignore)
6484 CALL_EXPR_TAILCALL (exp) = 0;
6485
6486 /* Expand the call here so we can emit trailing code. */
6487 ret = expand_call (exp, target, ignore);
6488
6489 /* Replace the original function just in case it matters. */
6490 TREE_OPERAND (addr, 0) = fndecl;
6491
6492 /* Then issue the arithmetic correction to return the right result. */
6493 if (!ignore)
6494 {
6495 if (code == NOT)
6496 {
6497 ret = expand_simple_binop (mode, AND, ret, val, NULL_RTX, true,
6498 OPTAB_LIB_WIDEN);
6499 ret = expand_simple_unop (mode, NOT, ret, target, true);
6500 }
6501 else
6502 ret = expand_simple_binop (mode, code, ret, val, target, true,
6503 OPTAB_LIB_WIDEN);
6504 }
6505 return ret;
6506}
6507
6508/* Expand IFN_ATOMIC_BIT_TEST_AND_* internal function. */
6509
6510void
6511expand_ifn_atomic_bit_test_and (gcall *call)
6512{
6513 tree ptr = gimple_call_arg (gs: call, index: 0);
6514 tree bit = gimple_call_arg (gs: call, index: 1);
6515 tree flag = gimple_call_arg (gs: call, index: 2);
6516 tree lhs = gimple_call_lhs (gs: call);
6517 enum memmodel model = MEMMODEL_SYNC_SEQ_CST;
6518 machine_mode mode = TYPE_MODE (TREE_TYPE (flag));
6519 enum rtx_code code;
6520 optab optab;
6521 class expand_operand ops[5];
6522
6523 gcc_assert (flag_inline_atomics);
6524
6525 if (gimple_call_num_args (gs: call) == 5)
6526 model = get_memmodel (exp: gimple_call_arg (gs: call, index: 3));
6527
6528 rtx mem = get_builtin_sync_mem (loc: ptr, mode);
6529 rtx val = expand_expr_force_mode (exp: bit, mode);
6530
6531 switch (gimple_call_internal_fn (gs: call))
6532 {
6533 case IFN_ATOMIC_BIT_TEST_AND_SET:
6534 code = IOR;
6535 optab = atomic_bit_test_and_set_optab;
6536 break;
6537 case IFN_ATOMIC_BIT_TEST_AND_COMPLEMENT:
6538 code = XOR;
6539 optab = atomic_bit_test_and_complement_optab;
6540 break;
6541 case IFN_ATOMIC_BIT_TEST_AND_RESET:
6542 code = AND;
6543 optab = atomic_bit_test_and_reset_optab;
6544 break;
6545 default:
6546 gcc_unreachable ();
6547 }
6548
6549 if (lhs == NULL_TREE)
6550 {
6551 rtx val2 = expand_simple_binop (mode, ASHIFT, const1_rtx,
6552 val, NULL_RTX, true, OPTAB_DIRECT);
6553 if (code == AND)
6554 val2 = expand_simple_unop (mode, NOT, val2, NULL_RTX, true);
6555 if (expand_atomic_fetch_op (const0_rtx, mem, val2, code, model, false))
6556 return;
6557 }
6558
6559 rtx target;
6560 if (lhs)
6561 target = expand_expr (exp: lhs, NULL_RTX, VOIDmode, modifier: EXPAND_WRITE);
6562 else
6563 target = gen_reg_rtx (mode);
6564 enum insn_code icode = direct_optab_handler (op: optab, mode);
6565 gcc_assert (icode != CODE_FOR_nothing);
6566 create_output_operand (op: &ops[0], x: target, mode);
6567 create_fixed_operand (op: &ops[1], x: mem);
6568 create_convert_operand_to (op: &ops[2], value: val, mode, unsigned_p: true);
6569 create_integer_operand (&ops[3], model);
6570 create_integer_operand (&ops[4], integer_onep (flag));
6571 if (maybe_expand_insn (icode, nops: 5, ops))
6572 return;
6573
6574 rtx bitval = val;
6575 val = expand_simple_binop (mode, ASHIFT, const1_rtx,
6576 val, NULL_RTX, true, OPTAB_DIRECT);
6577 rtx maskval = val;
6578 if (code == AND)
6579 val = expand_simple_unop (mode, NOT, val, NULL_RTX, true);
6580 rtx result = expand_atomic_fetch_op (gen_reg_rtx (mode), mem, val,
6581 code, model, false);
6582 if (!result)
6583 {
6584 bool is_atomic = gimple_call_num_args (gs: call) == 5;
6585 tree tcall = gimple_call_arg (gs: call, index: 3 + is_atomic);
6586 tree fndecl = gimple_call_addr_fndecl (fn: tcall);
6587 tree type = TREE_TYPE (TREE_TYPE (fndecl));
6588 tree exp = build_call_nary (type, tcall, 2 + is_atomic, ptr,
6589 make_tree (type, val),
6590 is_atomic
6591 ? gimple_call_arg (gs: call, index: 3)
6592 : integer_zero_node);
6593 result = expand_builtin (exp, gen_reg_rtx (mode), NULL_RTX,
6594 mode, !lhs);
6595 }
6596 if (!lhs)
6597 return;
6598 if (integer_onep (flag))
6599 {
6600 result = expand_simple_binop (mode, ASHIFTRT, result, bitval,
6601 NULL_RTX, true, OPTAB_DIRECT);
6602 result = expand_simple_binop (mode, AND, result, const1_rtx, target,
6603 true, OPTAB_DIRECT);
6604 }
6605 else
6606 result = expand_simple_binop (mode, AND, result, maskval, target, true,
6607 OPTAB_DIRECT);
6608 if (result != target)
6609 emit_move_insn (target, result);
6610}
6611
6612/* Expand IFN_ATOMIC_*_FETCH_CMP_0 internal function. */
6613
6614void
6615expand_ifn_atomic_op_fetch_cmp_0 (gcall *call)
6616{
6617 tree cmp = gimple_call_arg (gs: call, index: 0);
6618 tree ptr = gimple_call_arg (gs: call, index: 1);
6619 tree arg = gimple_call_arg (gs: call, index: 2);
6620 tree lhs = gimple_call_lhs (gs: call);
6621 enum memmodel model = MEMMODEL_SYNC_SEQ_CST;
6622 machine_mode mode = TYPE_MODE (TREE_TYPE (cmp));
6623 optab optab;
6624 rtx_code code;
6625 class expand_operand ops[5];
6626
6627 gcc_assert (flag_inline_atomics);
6628
6629 if (gimple_call_num_args (gs: call) == 5)
6630 model = get_memmodel (exp: gimple_call_arg (gs: call, index: 3));
6631
6632 rtx mem = get_builtin_sync_mem (loc: ptr, mode);
6633 rtx op = expand_expr_force_mode (exp: arg, mode);
6634
6635 switch (gimple_call_internal_fn (gs: call))
6636 {
6637 case IFN_ATOMIC_ADD_FETCH_CMP_0:
6638 code = PLUS;
6639 optab = atomic_add_fetch_cmp_0_optab;
6640 break;
6641 case IFN_ATOMIC_SUB_FETCH_CMP_0:
6642 code = MINUS;
6643 optab = atomic_sub_fetch_cmp_0_optab;
6644 break;
6645 case IFN_ATOMIC_AND_FETCH_CMP_0:
6646 code = AND;
6647 optab = atomic_and_fetch_cmp_0_optab;
6648 break;
6649 case IFN_ATOMIC_OR_FETCH_CMP_0:
6650 code = IOR;
6651 optab = atomic_or_fetch_cmp_0_optab;
6652 break;
6653 case IFN_ATOMIC_XOR_FETCH_CMP_0:
6654 code = XOR;
6655 optab = atomic_xor_fetch_cmp_0_optab;
6656 break;
6657 default:
6658 gcc_unreachable ();
6659 }
6660
6661 enum rtx_code comp = UNKNOWN;
6662 switch (tree_to_uhwi (cmp))
6663 {
6664 case ATOMIC_OP_FETCH_CMP_0_EQ: comp = EQ; break;
6665 case ATOMIC_OP_FETCH_CMP_0_NE: comp = NE; break;
6666 case ATOMIC_OP_FETCH_CMP_0_GT: comp = GT; break;
6667 case ATOMIC_OP_FETCH_CMP_0_GE: comp = GE; break;
6668 case ATOMIC_OP_FETCH_CMP_0_LT: comp = LT; break;
6669 case ATOMIC_OP_FETCH_CMP_0_LE: comp = LE; break;
6670 default: gcc_unreachable ();
6671 }
6672
6673 rtx target;
6674 if (lhs == NULL_TREE)
6675 target = gen_reg_rtx (TYPE_MODE (boolean_type_node));
6676 else
6677 target = expand_expr (exp: lhs, NULL_RTX, VOIDmode, modifier: EXPAND_WRITE);
6678 enum insn_code icode = direct_optab_handler (op: optab, mode);
6679 gcc_assert (icode != CODE_FOR_nothing);
6680 create_output_operand (op: &ops[0], x: target, TYPE_MODE (boolean_type_node));
6681 create_fixed_operand (op: &ops[1], x: mem);
6682 create_convert_operand_to (op: &ops[2], value: op, mode, unsigned_p: true);
6683 create_integer_operand (&ops[3], model);
6684 create_integer_operand (&ops[4], comp);
6685 if (maybe_expand_insn (icode, nops: 5, ops))
6686 return;
6687
6688 rtx result = expand_atomic_fetch_op (gen_reg_rtx (mode), mem, op,
6689 code, model, true);
6690 if (!result)
6691 {
6692 bool is_atomic = gimple_call_num_args (gs: call) == 5;
6693 tree tcall = gimple_call_arg (gs: call, index: 3 + is_atomic);
6694 tree fndecl = gimple_call_addr_fndecl (fn: tcall);
6695 tree type = TREE_TYPE (TREE_TYPE (fndecl));
6696 tree exp = build_call_nary (type, tcall,
6697 2 + is_atomic, ptr, arg,
6698 is_atomic
6699 ? gimple_call_arg (gs: call, index: 3)
6700 : integer_zero_node);
6701 result = expand_builtin (exp, gen_reg_rtx (mode), NULL_RTX,
6702 mode, !lhs);
6703 }
6704
6705 if (lhs)
6706 {
6707 result = emit_store_flag_force (target, comp, result, const0_rtx, mode,
6708 0, 1);
6709 if (result != target)
6710 emit_move_insn (target, result);
6711 }
6712}
6713
6714/* Expand an atomic clear operation.
6715 void _atomic_clear (BOOL *obj, enum memmodel)
6716 EXP is the call expression. */
6717
6718static rtx
6719expand_builtin_atomic_clear (tree exp)
6720{
6721 machine_mode mode = int_mode_for_size (BOOL_TYPE_SIZE, limit: 0).require ();
6722 rtx mem = get_builtin_sync_mem (CALL_EXPR_ARG (exp, 0), mode);
6723 memmodel model = get_memmodel (CALL_EXPR_ARG (exp, 1));
6724
6725 if (is_mm_consume (model) || is_mm_acquire (model) || is_mm_acq_rel (model))
6726 model = MEMMODEL_SEQ_CST;
6727
6728 /* Try issuing an __atomic_store, and allow fallback to __sync_lock_release.
6729 Failing that, a store is issued by __atomic_store. The only way this can
6730 fail is if the bool type is larger than a word size. Unlikely, but
6731 handle it anyway for completeness. Assume a single threaded model since
6732 there is no atomic support in this case, and no barriers are required. */
6733 rtx ret = expand_atomic_store (mem, const0_rtx, model, true);
6734 if (!ret)
6735 emit_move_insn (mem, const0_rtx);
6736 return const0_rtx;
6737}
6738
6739/* Expand an atomic test_and_set operation.
6740 bool _atomic_test_and_set (BOOL *obj, enum memmodel)
6741 EXP is the call expression. */
6742
6743static rtx
6744expand_builtin_atomic_test_and_set (tree exp, rtx target)
6745{
6746 rtx mem;
6747 enum memmodel model;
6748 machine_mode mode;
6749
6750 mode = int_mode_for_size (BOOL_TYPE_SIZE, limit: 0).require ();
6751 mem = get_builtin_sync_mem (CALL_EXPR_ARG (exp, 0), mode);
6752 model = get_memmodel (CALL_EXPR_ARG (exp, 1));
6753
6754 return expand_atomic_test_and_set (target, mem, model);
6755}
6756
6757
6758/* Return true if (optional) argument ARG1 of size ARG0 is always lock free on
6759 this architecture. If ARG1 is NULL, use typical alignment for size ARG0. */
6760
6761static tree
6762fold_builtin_atomic_always_lock_free (tree arg0, tree arg1)
6763{
6764 int size;
6765 machine_mode mode;
6766 unsigned int mode_align, type_align;
6767
6768 if (TREE_CODE (arg0) != INTEGER_CST)
6769 return NULL_TREE;
6770
6771 /* We need a corresponding integer mode for the access to be lock-free. */
6772 size = INTVAL (expand_normal (arg0)) * BITS_PER_UNIT;
6773 if (!int_mode_for_size (size, limit: 0).exists (mode: &mode))
6774 return boolean_false_node;
6775
6776 mode_align = GET_MODE_ALIGNMENT (mode);
6777
6778 if (TREE_CODE (arg1) == INTEGER_CST)
6779 {
6780 unsigned HOST_WIDE_INT val = UINTVAL (expand_normal (arg1));
6781
6782 /* Either this argument is null, or it's a fake pointer encoding
6783 the alignment of the object. */
6784 val = least_bit_hwi (x: val);
6785 val *= BITS_PER_UNIT;
6786
6787 if (val == 0 || mode_align < val)
6788 type_align = mode_align;
6789 else
6790 type_align = val;
6791 }
6792 else
6793 {
6794 tree ttype = TREE_TYPE (arg1);
6795
6796 /* This function is usually invoked and folded immediately by the front
6797 end before anything else has a chance to look at it. The pointer
6798 parameter at this point is usually cast to a void *, so check for that
6799 and look past the cast. */
6800 if (CONVERT_EXPR_P (arg1)
6801 && POINTER_TYPE_P (ttype)
6802 && VOID_TYPE_P (TREE_TYPE (ttype))
6803 && POINTER_TYPE_P (TREE_TYPE (TREE_OPERAND (arg1, 0))))
6804 arg1 = TREE_OPERAND (arg1, 0);
6805
6806 ttype = TREE_TYPE (arg1);
6807 gcc_assert (POINTER_TYPE_P (ttype));
6808
6809 /* Get the underlying type of the object. */
6810 ttype = TREE_TYPE (ttype);
6811 type_align = TYPE_ALIGN (ttype);
6812 }
6813
6814 /* If the object has smaller alignment, the lock free routines cannot
6815 be used. */
6816 if (type_align < mode_align)
6817 return boolean_false_node;
6818
6819 /* Check if a compare_and_swap pattern exists for the mode which represents
6820 the required size. The pattern is not allowed to fail, so the existence
6821 of the pattern indicates support is present. Also require that an
6822 atomic load exists for the required size. */
6823 if (can_compare_and_swap_p (mode, true) && can_atomic_load_p (mode))
6824 return boolean_true_node;
6825 else
6826 return boolean_false_node;
6827}
6828
6829/* Return true if the parameters to call EXP represent an object which will
6830 always generate lock free instructions. The first argument represents the
6831 size of the object, and the second parameter is a pointer to the object
6832 itself. If NULL is passed for the object, then the result is based on
6833 typical alignment for an object of the specified size. Otherwise return
6834 false. */
6835
6836static rtx
6837expand_builtin_atomic_always_lock_free (tree exp)
6838{
6839 tree size;
6840 tree arg0 = CALL_EXPR_ARG (exp, 0);
6841 tree arg1 = CALL_EXPR_ARG (exp, 1);
6842
6843 if (TREE_CODE (arg0) != INTEGER_CST)
6844 {
6845 error ("non-constant argument 1 to %qs", "__atomic_always_lock_free");
6846 return const0_rtx;
6847 }
6848
6849 size = fold_builtin_atomic_always_lock_free (arg0, arg1);
6850 if (size == boolean_true_node)
6851 return const1_rtx;
6852 return const0_rtx;
6853}
6854
6855/* Return a one or zero if it can be determined that object ARG1 of size ARG
6856 is lock free on this architecture. */
6857
6858static tree
6859fold_builtin_atomic_is_lock_free (tree arg0, tree arg1)
6860{
6861 if (!flag_inline_atomics)
6862 return NULL_TREE;
6863
6864 /* If it isn't always lock free, don't generate a result. */
6865 if (fold_builtin_atomic_always_lock_free (arg0, arg1) == boolean_true_node)
6866 return boolean_true_node;
6867
6868 return NULL_TREE;
6869}
6870
6871/* Return true if the parameters to call EXP represent an object which will
6872 always generate lock free instructions. The first argument represents the
6873 size of the object, and the second parameter is a pointer to the object
6874 itself. If NULL is passed for the object, then the result is based on
6875 typical alignment for an object of the specified size. Otherwise return
6876 NULL*/
6877
6878static rtx
6879expand_builtin_atomic_is_lock_free (tree exp)
6880{
6881 tree size;
6882 tree arg0 = CALL_EXPR_ARG (exp, 0);
6883 tree arg1 = CALL_EXPR_ARG (exp, 1);
6884
6885 if (!INTEGRAL_TYPE_P (TREE_TYPE (arg0)))
6886 {
6887 error ("non-integer argument 1 to %qs", "__atomic_is_lock_free");
6888 return NULL_RTX;
6889 }
6890
6891 if (!flag_inline_atomics)
6892 return NULL_RTX;
6893
6894 /* If the value is known at compile time, return the RTX for it. */
6895 size = fold_builtin_atomic_is_lock_free (arg0, arg1);
6896 if (size == boolean_true_node)
6897 return const1_rtx;
6898
6899 return NULL_RTX;
6900}
6901
6902/* Expand the __atomic_thread_fence intrinsic:
6903 void __atomic_thread_fence (enum memmodel)
6904 EXP is the CALL_EXPR. */
6905
6906static void
6907expand_builtin_atomic_thread_fence (tree exp)
6908{
6909 enum memmodel model = get_memmodel (CALL_EXPR_ARG (exp, 0));
6910 expand_mem_thread_fence (model);
6911}
6912
6913/* Expand the __atomic_signal_fence intrinsic:
6914 void __atomic_signal_fence (enum memmodel)
6915 EXP is the CALL_EXPR. */
6916
6917static void
6918expand_builtin_atomic_signal_fence (tree exp)
6919{
6920 enum memmodel model = get_memmodel (CALL_EXPR_ARG (exp, 0));
6921 expand_mem_signal_fence (model);
6922}
6923
6924/* Expand the __sync_synchronize intrinsic. */
6925
6926static void
6927expand_builtin_sync_synchronize (void)
6928{
6929 expand_mem_thread_fence (MEMMODEL_SYNC_SEQ_CST);
6930}
6931
6932static rtx
6933expand_builtin_thread_pointer (tree exp, rtx target)
6934{
6935 enum insn_code icode;
6936 if (!validate_arglist (callexpr: exp, VOID_TYPE))
6937 return const0_rtx;
6938 icode = direct_optab_handler (op: get_thread_pointer_optab, Pmode);
6939 if (icode != CODE_FOR_nothing)
6940 {
6941 class expand_operand op;
6942 /* If the target is not sutitable then create a new target. */
6943 if (target == NULL_RTX
6944 || !REG_P (target)
6945 || GET_MODE (target) != Pmode)
6946 target = gen_reg_rtx (Pmode);
6947 create_output_operand (op: &op, x: target, Pmode);
6948 expand_insn (icode, nops: 1, ops: &op);
6949 return target;
6950 }
6951 error ("%<__builtin_thread_pointer%> is not supported on this target");
6952 return const0_rtx;
6953}
6954
6955static void
6956expand_builtin_set_thread_pointer (tree exp)
6957{
6958 enum insn_code icode;
6959 if (!validate_arglist (callexpr: exp, POINTER_TYPE, VOID_TYPE))
6960 return;
6961 icode = direct_optab_handler (op: set_thread_pointer_optab, Pmode);
6962 if (icode != CODE_FOR_nothing)
6963 {
6964 class expand_operand op;
6965 rtx val = expand_expr (CALL_EXPR_ARG (exp, 0), NULL_RTX,
6966 Pmode, modifier: EXPAND_NORMAL);
6967 create_input_operand (op: &op, value: val, Pmode);
6968 expand_insn (icode, nops: 1, ops: &op);
6969 return;
6970 }
6971 error ("%<__builtin_set_thread_pointer%> is not supported on this target");
6972}
6973
6974
6975/* Emit code to restore the current value of stack. */
6976
6977static void
6978expand_stack_restore (tree var)
6979{
6980 rtx_insn *prev;
6981 rtx sa = expand_normal (exp: var);
6982
6983 sa = convert_memory_address (Pmode, sa);
6984
6985 prev = get_last_insn ();
6986 emit_stack_restore (SAVE_BLOCK, sa);
6987
6988 record_new_stack_level ();
6989
6990 fixup_args_size_notes (prev, get_last_insn (), 0);
6991}
6992
6993/* Emit code to save the current value of stack. */
6994
6995static rtx
6996expand_stack_save (void)
6997{
6998 rtx ret = NULL_RTX;
6999
7000 emit_stack_save (SAVE_BLOCK, &ret);
7001 return ret;
7002}
7003
7004/* Emit code to get the openacc gang, worker or vector id or size. */
7005
7006static rtx
7007expand_builtin_goacc_parlevel_id_size (tree exp, rtx target, int ignore)
7008{
7009 const char *name;
7010 rtx fallback_retval;
7011 rtx_insn *(*gen_fn) (rtx, rtx);
7012 switch (DECL_FUNCTION_CODE (decl: get_callee_fndecl (exp)))
7013 {
7014 case BUILT_IN_GOACC_PARLEVEL_ID:
7015 name = "__builtin_goacc_parlevel_id";
7016 fallback_retval = const0_rtx;
7017 gen_fn = targetm.gen_oacc_dim_pos;
7018 break;
7019 case BUILT_IN_GOACC_PARLEVEL_SIZE:
7020 name = "__builtin_goacc_parlevel_size";
7021 fallback_retval = const1_rtx;
7022 gen_fn = targetm.gen_oacc_dim_size;
7023 break;
7024 default:
7025 gcc_unreachable ();
7026 }
7027
7028 if (oacc_get_fn_attrib (fn: current_function_decl) == NULL_TREE)
7029 {
7030 error ("%qs only supported in OpenACC code", name);
7031 return const0_rtx;
7032 }
7033
7034 tree arg = CALL_EXPR_ARG (exp, 0);
7035 if (TREE_CODE (arg) != INTEGER_CST)
7036 {
7037 error ("non-constant argument 0 to %qs", name);
7038 return const0_rtx;
7039 }
7040
7041 int dim = TREE_INT_CST_LOW (arg);
7042 switch (dim)
7043 {
7044 case GOMP_DIM_GANG:
7045 case GOMP_DIM_WORKER:
7046 case GOMP_DIM_VECTOR:
7047 break;
7048 default:
7049 error ("illegal argument 0 to %qs", name);
7050 return const0_rtx;
7051 }
7052
7053 if (ignore)
7054 return target;
7055
7056 if (target == NULL_RTX)
7057 target = gen_reg_rtx (TYPE_MODE (TREE_TYPE (exp)));
7058
7059 if (!targetm.have_oacc_dim_size ())
7060 {
7061 emit_move_insn (target, fallback_retval);
7062 return target;
7063 }
7064
7065 rtx reg = MEM_P (target) ? gen_reg_rtx (GET_MODE (target)) : target;
7066 emit_insn (gen_fn (reg, GEN_INT (dim)));
7067 if (reg != target)
7068 emit_move_insn (target, reg);
7069
7070 return target;
7071}
7072
7073/* Expand a string compare operation using a sequence of char comparison
7074 to get rid of the calling overhead, with result going to TARGET if
7075 that's convenient.
7076
7077 VAR_STR is the variable string source;
7078 CONST_STR is the constant string source;
7079 LENGTH is the number of chars to compare;
7080 CONST_STR_N indicates which source string is the constant string;
7081 IS_MEMCMP indicates whether it's a memcmp or strcmp.
7082
7083 to: (assume const_str_n is 2, i.e., arg2 is a constant string)
7084
7085 target = (int) (unsigned char) var_str[0]
7086 - (int) (unsigned char) const_str[0];
7087 if (target != 0)
7088 goto ne_label;
7089 ...
7090 target = (int) (unsigned char) var_str[length - 2]
7091 - (int) (unsigned char) const_str[length - 2];
7092 if (target != 0)
7093 goto ne_label;
7094 target = (int) (unsigned char) var_str[length - 1]
7095 - (int) (unsigned char) const_str[length - 1];
7096 ne_label:
7097 */
7098
7099static rtx
7100inline_string_cmp (rtx target, tree var_str, const char *const_str,
7101 unsigned HOST_WIDE_INT length,
7102 int const_str_n, machine_mode mode)
7103{
7104 HOST_WIDE_INT offset = 0;
7105 rtx var_rtx_array
7106 = get_memory_rtx (exp: var_str, len: build_int_cst (unsigned_type_node,length));
7107 rtx var_rtx = NULL_RTX;
7108 rtx const_rtx = NULL_RTX;
7109 rtx result = target ? target : gen_reg_rtx (mode);
7110 rtx_code_label *ne_label = gen_label_rtx ();
7111 tree unit_type_node = unsigned_char_type_node;
7112 scalar_int_mode unit_mode
7113 = as_a <scalar_int_mode> TYPE_MODE (unit_type_node);
7114
7115 start_sequence ();
7116
7117 for (unsigned HOST_WIDE_INT i = 0; i < length; i++)
7118 {
7119 var_rtx
7120 = adjust_address (var_rtx_array, TYPE_MODE (unit_type_node), offset);
7121 const_rtx = c_readstr (str: const_str + offset, mode: unit_mode);
7122 rtx op0 = (const_str_n == 1) ? const_rtx : var_rtx;
7123 rtx op1 = (const_str_n == 1) ? var_rtx : const_rtx;
7124
7125 op0 = convert_modes (mode, oldmode: unit_mode, x: op0, unsignedp: 1);
7126 op1 = convert_modes (mode, oldmode: unit_mode, x: op1, unsignedp: 1);
7127 rtx diff = expand_simple_binop (mode, MINUS, op0, op1,
7128 result, 1, OPTAB_WIDEN);
7129
7130 /* Force the difference into result register. We cannot reassign
7131 result here ("result = diff") or we may end up returning
7132 uninitialized result when expand_simple_binop allocates a new
7133 pseudo-register for returning. */
7134 if (diff != result)
7135 emit_move_insn (result, diff);
7136
7137 if (i < length - 1)
7138 emit_cmp_and_jump_insns (result, CONST0_RTX (mode), NE, NULL_RTX,
7139 mode, true, ne_label);
7140 offset += GET_MODE_SIZE (mode: unit_mode);
7141 }
7142
7143 emit_label (ne_label);
7144 rtx_insn *insns = get_insns ();
7145 end_sequence ();
7146 emit_insn (insns);
7147
7148 return result;
7149}
7150
7151/* Inline expansion of a call to str(n)cmp and memcmp, with result going
7152 to TARGET if that's convenient.
7153 If the call is not been inlined, return NULL_RTX. */
7154
7155static rtx
7156inline_expand_builtin_bytecmp (tree exp, rtx target)
7157{
7158 tree fndecl = get_callee_fndecl (exp);
7159 enum built_in_function fcode = DECL_FUNCTION_CODE (decl: fndecl);
7160 bool is_ncmp = (fcode == BUILT_IN_STRNCMP || fcode == BUILT_IN_MEMCMP);
7161
7162 /* Do NOT apply this inlining expansion when optimizing for size or
7163 optimization level below 2 or if unused *cmp hasn't been DCEd. */
7164 if (optimize < 2 || optimize_insn_for_size_p () || target == const0_rtx)
7165 return NULL_RTX;
7166
7167 gcc_checking_assert (fcode == BUILT_IN_STRCMP
7168 || fcode == BUILT_IN_STRNCMP
7169 || fcode == BUILT_IN_MEMCMP);
7170
7171 /* On a target where the type of the call (int) has same or narrower presicion
7172 than unsigned char, give up the inlining expansion. */
7173 if (TYPE_PRECISION (unsigned_char_type_node)
7174 >= TYPE_PRECISION (TREE_TYPE (exp)))
7175 return NULL_RTX;
7176
7177 tree arg1 = CALL_EXPR_ARG (exp, 0);
7178 tree arg2 = CALL_EXPR_ARG (exp, 1);
7179 tree len3_tree = is_ncmp ? CALL_EXPR_ARG (exp, 2) : NULL_TREE;
7180
7181 unsigned HOST_WIDE_INT len1 = 0;
7182 unsigned HOST_WIDE_INT len2 = 0;
7183 unsigned HOST_WIDE_INT len3 = 0;
7184
7185 /* Get the object representation of the initializers of ARG1 and ARG2
7186 as strings, provided they refer to constant objects, with their byte
7187 sizes in LEN1 and LEN2, respectively. */
7188 const char *bytes1 = getbyterep (arg1, &len1);
7189 const char *bytes2 = getbyterep (arg2, &len2);
7190
7191 /* Fail if neither argument refers to an initialized constant. */
7192 if (!bytes1 && !bytes2)
7193 return NULL_RTX;
7194
7195 if (is_ncmp)
7196 {
7197 /* Fail if the memcmp/strncmp bound is not a constant. */
7198 if (!tree_fits_uhwi_p (len3_tree))
7199 return NULL_RTX;
7200
7201 len3 = tree_to_uhwi (len3_tree);
7202
7203 if (fcode == BUILT_IN_MEMCMP)
7204 {
7205 /* Fail if the memcmp bound is greater than the size of either
7206 of the two constant objects. */
7207 if ((bytes1 && len1 < len3)
7208 || (bytes2 && len2 < len3))
7209 return NULL_RTX;
7210 }
7211 }
7212
7213 if (fcode != BUILT_IN_MEMCMP)
7214 {
7215 /* For string functions (i.e., strcmp and strncmp) reduce LEN1
7216 and LEN2 to the length of the nul-terminated string stored
7217 in each. */
7218 if (bytes1 != NULL)
7219 len1 = strnlen (string: bytes1, maxlen: len1) + 1;
7220 if (bytes2 != NULL)
7221 len2 = strnlen (string: bytes2, maxlen: len2) + 1;
7222 }
7223
7224 /* See inline_string_cmp. */
7225 int const_str_n;
7226 if (!len1)
7227 const_str_n = 2;
7228 else if (!len2)
7229 const_str_n = 1;
7230 else if (len2 > len1)
7231 const_str_n = 1;
7232 else
7233 const_str_n = 2;
7234
7235 /* For strncmp only, compute the new bound as the smallest of
7236 the lengths of the two strings (plus 1) and the bound provided
7237 to the function. */
7238 unsigned HOST_WIDE_INT bound = (const_str_n == 1) ? len1 : len2;
7239 if (is_ncmp && len3 < bound)
7240 bound = len3;
7241
7242 /* If the bound of the comparison is larger than the threshold,
7243 do nothing. */
7244 if (bound > (unsigned HOST_WIDE_INT) param_builtin_string_cmp_inline_length)
7245 return NULL_RTX;
7246
7247 machine_mode mode = TYPE_MODE (TREE_TYPE (exp));
7248
7249 /* Now, start inline expansion the call. */
7250 return inline_string_cmp (target, var_str: (const_str_n == 1) ? arg2 : arg1,
7251 const_str: (const_str_n == 1) ? bytes1 : bytes2, length: bound,
7252 const_str_n, mode);
7253}
7254
7255/* Expand a call to __builtin_speculation_safe_value_<N>. MODE
7256 represents the size of the first argument to that call, or VOIDmode
7257 if the argument is a pointer. IGNORE will be true if the result
7258 isn't used. */
7259static rtx
7260expand_speculation_safe_value (machine_mode mode, tree exp, rtx target,
7261 bool ignore)
7262{
7263 rtx val, failsafe;
7264 unsigned nargs = call_expr_nargs (exp);
7265
7266 tree arg0 = CALL_EXPR_ARG (exp, 0);
7267
7268 if (mode == VOIDmode)
7269 {
7270 mode = TYPE_MODE (TREE_TYPE (arg0));
7271 gcc_assert (GET_MODE_CLASS (mode) == MODE_INT);
7272 }
7273
7274 val = expand_expr (exp: arg0, NULL_RTX, mode, modifier: EXPAND_NORMAL);
7275
7276 /* An optional second argument can be used as a failsafe value on
7277 some machines. If it isn't present, then the failsafe value is
7278 assumed to be 0. */
7279 if (nargs > 1)
7280 {
7281 tree arg1 = CALL_EXPR_ARG (exp, 1);
7282 failsafe = expand_expr (exp: arg1, NULL_RTX, mode, modifier: EXPAND_NORMAL);
7283 }
7284 else
7285 failsafe = const0_rtx;
7286
7287 /* If the result isn't used, the behavior is undefined. It would be
7288 nice to emit a warning here, but path splitting means this might
7289 happen with legitimate code. So simply drop the builtin
7290 expansion in that case; we've handled any side-effects above. */
7291 if (ignore)
7292 return const0_rtx;
7293
7294 /* If we don't have a suitable target, create one to hold the result. */
7295 if (target == NULL || GET_MODE (target) != mode)
7296 target = gen_reg_rtx (mode);
7297
7298 if (GET_MODE (val) != mode && GET_MODE (val) != VOIDmode)
7299 val = convert_modes (mode, VOIDmode, x: val, unsignedp: false);
7300
7301 return targetm.speculation_safe_value (mode, target, val, failsafe);
7302}
7303
7304/* Expand an expression EXP that calls a built-in function,
7305 with result going to TARGET if that's convenient
7306 (and in mode MODE if that's convenient).
7307 SUBTARGET may be used as the target for computing one of EXP's operands.
7308 IGNORE is nonzero if the value is to be ignored. */
7309
7310rtx
7311expand_builtin (tree exp, rtx target, rtx subtarget, machine_mode mode,
7312 int ignore)
7313{
7314 tree fndecl = get_callee_fndecl (exp);
7315 machine_mode target_mode = TYPE_MODE (TREE_TYPE (exp));
7316 int flags;
7317
7318 if (DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_MD)
7319 return targetm.expand_builtin (exp, target, subtarget, mode, ignore);
7320
7321 /* When ASan is enabled, we don't want to expand some memory/string
7322 builtins and rely on libsanitizer's hooks. This allows us to avoid
7323 redundant checks and be sure, that possible overflow will be detected
7324 by ASan. */
7325
7326 enum built_in_function fcode = DECL_FUNCTION_CODE (decl: fndecl);
7327 if (param_asan_kernel_mem_intrinsic_prefix
7328 && sanitize_flags_p (flag: SANITIZE_KERNEL_ADDRESS
7329 | SANITIZE_KERNEL_HWADDRESS))
7330 switch (fcode)
7331 {
7332 rtx save_decl_rtl, ret;
7333 case BUILT_IN_MEMCPY:
7334 case BUILT_IN_MEMMOVE:
7335 case BUILT_IN_MEMSET:
7336 save_decl_rtl = DECL_RTL (fndecl);
7337 DECL_RTL (fndecl) = asan_memfn_rtl (fndecl);
7338 ret = expand_call (exp, target, ignore);
7339 DECL_RTL (fndecl) = save_decl_rtl;
7340 return ret;
7341 default:
7342 break;
7343 }
7344 if (sanitize_flags_p (flag: SANITIZE_ADDRESS) && asan_intercepted_p (fcode))
7345 return expand_call (exp, target, ignore);
7346
7347 /* When not optimizing, generate calls to library functions for a certain
7348 set of builtins. */
7349 if (!optimize
7350 && !called_as_built_in (node: fndecl)
7351 && fcode != BUILT_IN_FORK
7352 && fcode != BUILT_IN_EXECL
7353 && fcode != BUILT_IN_EXECV
7354 && fcode != BUILT_IN_EXECLP
7355 && fcode != BUILT_IN_EXECLE
7356 && fcode != BUILT_IN_EXECVP
7357 && fcode != BUILT_IN_EXECVE
7358 && fcode != BUILT_IN_CLEAR_CACHE
7359 && !ALLOCA_FUNCTION_CODE_P (fcode)
7360 && fcode != BUILT_IN_FREE)
7361 return expand_call (exp, target, ignore);
7362
7363 /* The built-in function expanders test for target == const0_rtx
7364 to determine whether the function's result will be ignored. */
7365 if (ignore)
7366 target = const0_rtx;
7367
7368 /* If the result of a pure or const built-in function is ignored, and
7369 none of its arguments are volatile, we can avoid expanding the
7370 built-in call and just evaluate the arguments for side-effects. */
7371 if (target == const0_rtx
7372 && ((flags = flags_from_decl_or_type (fndecl)) & (ECF_CONST | ECF_PURE))
7373 && !(flags & ECF_LOOPING_CONST_OR_PURE))
7374 {
7375 bool volatilep = false;
7376 tree arg;
7377 call_expr_arg_iterator iter;
7378
7379 FOR_EACH_CALL_EXPR_ARG (arg, iter, exp)
7380 if (TREE_THIS_VOLATILE (arg))
7381 {
7382 volatilep = true;
7383 break;
7384 }
7385
7386 if (! volatilep)
7387 {
7388 FOR_EACH_CALL_EXPR_ARG (arg, iter, exp)
7389 expand_expr (exp: arg, const0_rtx, VOIDmode, modifier: EXPAND_NORMAL);
7390 return const0_rtx;
7391 }
7392 }
7393
7394 switch (fcode)
7395 {
7396 CASE_FLT_FN (BUILT_IN_FABS):
7397 CASE_FLT_FN_FLOATN_NX (BUILT_IN_FABS):
7398 case BUILT_IN_FABSD32:
7399 case BUILT_IN_FABSD64:
7400 case BUILT_IN_FABSD128:
7401 target = expand_builtin_fabs (exp, target, subtarget);
7402 if (target)
7403 return target;
7404 break;
7405
7406 CASE_FLT_FN (BUILT_IN_COPYSIGN):
7407 CASE_FLT_FN_FLOATN_NX (BUILT_IN_COPYSIGN):
7408 target = expand_builtin_copysign (exp, target, subtarget);
7409 if (target)
7410 return target;
7411 break;
7412
7413 /* Just do a normal library call if we were unable to fold
7414 the values. */
7415 CASE_FLT_FN (BUILT_IN_CABS):
7416 CASE_FLT_FN_FLOATN_NX (BUILT_IN_CABS):
7417 break;
7418
7419 CASE_FLT_FN (BUILT_IN_FMA):
7420 CASE_FLT_FN_FLOATN_NX (BUILT_IN_FMA):
7421 target = expand_builtin_mathfn_ternary (exp, target, subtarget);
7422 if (target)
7423 return target;
7424 break;
7425
7426 CASE_FLT_FN (BUILT_IN_ILOGB):
7427 if (! flag_unsafe_math_optimizations)
7428 break;
7429 gcc_fallthrough ();
7430 CASE_FLT_FN (BUILT_IN_ISINF):
7431 CASE_FLT_FN (BUILT_IN_FINITE):
7432 case BUILT_IN_ISFINITE:
7433 case BUILT_IN_ISNORMAL:
7434 target = expand_builtin_interclass_mathfn (exp, target);
7435 if (target)
7436 return target;
7437 break;
7438
7439 case BUILT_IN_ISSIGNALING:
7440 target = expand_builtin_issignaling (exp, target);
7441 if (target)
7442 return target;
7443 break;
7444
7445 CASE_FLT_FN (BUILT_IN_ICEIL):
7446 CASE_FLT_FN (BUILT_IN_LCEIL):
7447 CASE_FLT_FN (BUILT_IN_LLCEIL):
7448 CASE_FLT_FN (BUILT_IN_LFLOOR):
7449 CASE_FLT_FN (BUILT_IN_IFLOOR):
7450 CASE_FLT_FN (BUILT_IN_LLFLOOR):
7451 target = expand_builtin_int_roundingfn (exp, target);
7452 if (target)
7453 return target;
7454 break;
7455
7456 CASE_FLT_FN (BUILT_IN_IRINT):
7457 CASE_FLT_FN (BUILT_IN_LRINT):
7458 CASE_FLT_FN (BUILT_IN_LLRINT):
7459 CASE_FLT_FN (BUILT_IN_IROUND):
7460 CASE_FLT_FN (BUILT_IN_LROUND):
7461 CASE_FLT_FN (BUILT_IN_LLROUND):
7462 target = expand_builtin_int_roundingfn_2 (exp, target);
7463 if (target)
7464 return target;
7465 break;
7466
7467 CASE_FLT_FN (BUILT_IN_POWI):
7468 target = expand_builtin_powi (exp, target);
7469 if (target)
7470 return target;
7471 break;
7472
7473 CASE_FLT_FN (BUILT_IN_CEXPI):
7474 target = expand_builtin_cexpi (exp, target);
7475 gcc_assert (target);
7476 return target;
7477
7478 CASE_FLT_FN (BUILT_IN_SIN):
7479 CASE_FLT_FN (BUILT_IN_COS):
7480 if (! flag_unsafe_math_optimizations)
7481 break;
7482 target = expand_builtin_mathfn_3 (exp, target, subtarget);
7483 if (target)
7484 return target;
7485 break;
7486
7487 CASE_FLT_FN (BUILT_IN_SINCOS):
7488 if (! flag_unsafe_math_optimizations)
7489 break;
7490 target = expand_builtin_sincos (exp);
7491 if (target)
7492 return target;
7493 break;
7494
7495 case BUILT_IN_FEGETROUND:
7496 target = expand_builtin_fegetround (exp, target, target_mode);
7497 if (target)
7498 return target;
7499 break;
7500
7501 case BUILT_IN_FECLEAREXCEPT:
7502 target = expand_builtin_feclear_feraise_except (exp, target, target_mode,
7503 op_optab: feclearexcept_optab);
7504 if (target)
7505 return target;
7506 break;
7507
7508 case BUILT_IN_FERAISEEXCEPT:
7509 target = expand_builtin_feclear_feraise_except (exp, target, target_mode,
7510 op_optab: feraiseexcept_optab);
7511 if (target)
7512 return target;
7513 break;
7514
7515 case BUILT_IN_APPLY_ARGS:
7516 return expand_builtin_apply_args ();
7517
7518 /* __builtin_apply (FUNCTION, ARGUMENTS, ARGSIZE) invokes
7519 FUNCTION with a copy of the parameters described by
7520 ARGUMENTS, and ARGSIZE. It returns a block of memory
7521 allocated on the stack into which is stored all the registers
7522 that might possibly be used for returning the result of a
7523 function. ARGUMENTS is the value returned by
7524 __builtin_apply_args. ARGSIZE is the number of bytes of
7525 arguments that must be copied. ??? How should this value be
7526 computed? We'll also need a safe worst case value for varargs
7527 functions. */
7528 case BUILT_IN_APPLY:
7529 if (!validate_arglist (callexpr: exp, POINTER_TYPE,
7530 POINTER_TYPE, INTEGER_TYPE, VOID_TYPE)
7531 && !validate_arglist (callexpr: exp, REFERENCE_TYPE,
7532 POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
7533 return const0_rtx;
7534 else
7535 {
7536 rtx ops[3];
7537
7538 ops[0] = expand_normal (CALL_EXPR_ARG (exp, 0));
7539 ops[1] = expand_normal (CALL_EXPR_ARG (exp, 1));
7540 ops[2] = expand_normal (CALL_EXPR_ARG (exp, 2));
7541
7542 return expand_builtin_apply (function: ops[0], arguments: ops[1], argsize: ops[2]);
7543 }
7544
7545 /* __builtin_return (RESULT) causes the function to return the
7546 value described by RESULT. RESULT is address of the block of
7547 memory returned by __builtin_apply. */
7548 case BUILT_IN_RETURN:
7549 if (validate_arglist (callexpr: exp, POINTER_TYPE, VOID_TYPE))
7550 expand_builtin_return (result: expand_normal (CALL_EXPR_ARG (exp, 0)));
7551 return const0_rtx;
7552
7553 case BUILT_IN_SAVEREGS:
7554 return expand_builtin_saveregs ();
7555
7556 case BUILT_IN_VA_ARG_PACK:
7557 /* All valid uses of __builtin_va_arg_pack () are removed during
7558 inlining. */
7559 error ("invalid use of %<__builtin_va_arg_pack ()%>");
7560 return const0_rtx;
7561
7562 case BUILT_IN_VA_ARG_PACK_LEN:
7563 /* All valid uses of __builtin_va_arg_pack_len () are removed during
7564 inlining. */
7565 error ("invalid use of %<__builtin_va_arg_pack_len ()%>");
7566 return const0_rtx;
7567
7568 /* Return the address of the first anonymous stack arg. */
7569 case BUILT_IN_NEXT_ARG:
7570 if (fold_builtin_next_arg (exp, false))
7571 return const0_rtx;
7572 return expand_builtin_next_arg ();
7573
7574 case BUILT_IN_CLEAR_CACHE:
7575 expand_builtin___clear_cache (exp);
7576 return const0_rtx;
7577
7578 case BUILT_IN_CLASSIFY_TYPE:
7579 return expand_builtin_classify_type (exp);
7580
7581 case BUILT_IN_CONSTANT_P:
7582 return const0_rtx;
7583
7584 case BUILT_IN_FRAME_ADDRESS:
7585 case BUILT_IN_RETURN_ADDRESS:
7586 return expand_builtin_frame_address (fndecl, exp);
7587
7588 /* Returns the address of the area where the structure is returned.
7589 0 otherwise. */
7590 case BUILT_IN_AGGREGATE_INCOMING_ADDRESS:
7591 if (call_expr_nargs (exp) != 0
7592 || ! AGGREGATE_TYPE_P (TREE_TYPE (TREE_TYPE (current_function_decl)))
7593 || !MEM_P (DECL_RTL (DECL_RESULT (current_function_decl))))
7594 return const0_rtx;
7595 else
7596 return XEXP (DECL_RTL (DECL_RESULT (current_function_decl)), 0);
7597
7598 CASE_BUILT_IN_ALLOCA:
7599 target = expand_builtin_alloca (exp);
7600 if (target)
7601 return target;
7602 break;
7603
7604 case BUILT_IN_ASAN_ALLOCAS_UNPOISON:
7605 return expand_asan_emit_allocas_unpoison (exp);
7606
7607 case BUILT_IN_STACK_SAVE:
7608 return expand_stack_save ();
7609
7610 case BUILT_IN_STACK_RESTORE:
7611 expand_stack_restore (CALL_EXPR_ARG (exp, 0));
7612 return const0_rtx;
7613
7614 case BUILT_IN_BSWAP16:
7615 case BUILT_IN_BSWAP32:
7616 case BUILT_IN_BSWAP64:
7617 case BUILT_IN_BSWAP128:
7618 target = expand_builtin_bswap (target_mode, exp, target, subtarget);
7619 if (target)
7620 return target;
7621 break;
7622
7623 CASE_INT_FN (BUILT_IN_FFS):
7624 target = expand_builtin_unop (target_mode, exp, target,
7625 subtarget, op_optab: ffs_optab);
7626 if (target)
7627 return target;
7628 break;
7629
7630 CASE_INT_FN (BUILT_IN_CLZ):
7631 target = expand_builtin_unop (target_mode, exp, target,
7632 subtarget, op_optab: clz_optab);
7633 if (target)
7634 return target;
7635 break;
7636
7637 CASE_INT_FN (BUILT_IN_CTZ):
7638 target = expand_builtin_unop (target_mode, exp, target,
7639 subtarget, op_optab: ctz_optab);
7640 if (target)
7641 return target;
7642 break;
7643
7644 CASE_INT_FN (BUILT_IN_CLRSB):
7645 target = expand_builtin_unop (target_mode, exp, target,
7646 subtarget, op_optab: clrsb_optab);
7647 if (target)
7648 return target;
7649 break;
7650
7651 CASE_INT_FN (BUILT_IN_POPCOUNT):
7652 target = expand_builtin_unop (target_mode, exp, target,
7653 subtarget, op_optab: popcount_optab);
7654 if (target)
7655 return target;
7656 break;
7657
7658 CASE_INT_FN (BUILT_IN_PARITY):
7659 target = expand_builtin_unop (target_mode, exp, target,
7660 subtarget, op_optab: parity_optab);
7661 if (target)
7662 return target;
7663 break;
7664
7665 case BUILT_IN_STRLEN:
7666 target = expand_builtin_strlen (exp, target, target_mode);
7667 if (target)
7668 return target;
7669 break;
7670
7671 case BUILT_IN_STRNLEN:
7672 target = expand_builtin_strnlen (exp, target, target_mode);
7673 if (target)
7674 return target;
7675 break;
7676
7677 case BUILT_IN_STRCPY:
7678 target = expand_builtin_strcpy (exp, target);
7679 if (target)
7680 return target;
7681 break;
7682
7683 case BUILT_IN_STRNCPY:
7684 target = expand_builtin_strncpy (exp, target);
7685 if (target)
7686 return target;
7687 break;
7688
7689 case BUILT_IN_STPCPY:
7690 target = expand_builtin_stpcpy (exp, target, mode);
7691 if (target)
7692 return target;
7693 break;
7694
7695 case BUILT_IN_MEMCPY:
7696 target = expand_builtin_memcpy (exp, target);
7697 if (target)
7698 return target;
7699 break;
7700
7701 case BUILT_IN_MEMMOVE:
7702 target = expand_builtin_memmove (exp, target);
7703 if (target)
7704 return target;
7705 break;
7706
7707 case BUILT_IN_MEMPCPY:
7708 target = expand_builtin_mempcpy (exp, target);
7709 if (target)
7710 return target;
7711 break;
7712
7713 case BUILT_IN_MEMSET:
7714 target = expand_builtin_memset (exp, target, mode);
7715 if (target)
7716 return target;
7717 break;
7718
7719 case BUILT_IN_BZERO:
7720 target = expand_builtin_bzero (exp);
7721 if (target)
7722 return target;
7723 break;
7724
7725 /* Expand it as BUILT_IN_MEMCMP_EQ first. If not successful, change it
7726 back to a BUILT_IN_STRCMP. Remember to delete the 3rd parameter
7727 when changing it to a strcmp call. */
7728 case BUILT_IN_STRCMP_EQ:
7729 target = expand_builtin_memcmp (exp, target, result_eq: true);
7730 if (target)
7731 return target;
7732
7733 /* Change this call back to a BUILT_IN_STRCMP. */
7734 TREE_OPERAND (exp, 1)
7735 = build_fold_addr_expr (builtin_decl_explicit (BUILT_IN_STRCMP));
7736
7737 /* Delete the last parameter. */
7738 unsigned int i;
7739 vec<tree, va_gc> *arg_vec;
7740 vec_alloc (v&: arg_vec, nelems: 2);
7741 for (i = 0; i < 2; i++)
7742 arg_vec->quick_push (CALL_EXPR_ARG (exp, i));
7743 exp = build_call_vec (TREE_TYPE (exp), CALL_EXPR_FN (exp), arg_vec);
7744 /* FALLTHROUGH */
7745
7746 case BUILT_IN_STRCMP:
7747 target = expand_builtin_strcmp (exp, target);
7748 if (target)
7749 return target;
7750 break;
7751
7752 /* Expand it as BUILT_IN_MEMCMP_EQ first. If not successful, change it
7753 back to a BUILT_IN_STRNCMP. */
7754 case BUILT_IN_STRNCMP_EQ:
7755 target = expand_builtin_memcmp (exp, target, result_eq: true);
7756 if (target)
7757 return target;
7758
7759 /* Change it back to a BUILT_IN_STRNCMP. */
7760 TREE_OPERAND (exp, 1)
7761 = build_fold_addr_expr (builtin_decl_explicit (BUILT_IN_STRNCMP));
7762 /* FALLTHROUGH */
7763
7764 case BUILT_IN_STRNCMP:
7765 target = expand_builtin_strncmp (exp, target, mode);
7766 if (target)
7767 return target;
7768 break;
7769
7770 case BUILT_IN_BCMP:
7771 case BUILT_IN_MEMCMP:
7772 case BUILT_IN_MEMCMP_EQ:
7773 target = expand_builtin_memcmp (exp, target, result_eq: fcode == BUILT_IN_MEMCMP_EQ);
7774 if (target)
7775 return target;
7776 if (fcode == BUILT_IN_MEMCMP_EQ)
7777 {
7778 tree newdecl = builtin_decl_explicit (fncode: BUILT_IN_MEMCMP);
7779 TREE_OPERAND (exp, 1) = build_fold_addr_expr (newdecl);
7780 }
7781 break;
7782
7783 case BUILT_IN_SETJMP:
7784 /* This should have been lowered to the builtins below. */
7785 gcc_unreachable ();
7786
7787 case BUILT_IN_SETJMP_SETUP:
7788 /* __builtin_setjmp_setup is passed a pointer to an array of five words
7789 and the receiver label. */
7790 if (validate_arglist (callexpr: exp, POINTER_TYPE, POINTER_TYPE, VOID_TYPE))
7791 {
7792 rtx buf_addr = expand_expr (CALL_EXPR_ARG (exp, 0), target: subtarget,
7793 VOIDmode, modifier: EXPAND_NORMAL);
7794 tree label = TREE_OPERAND (CALL_EXPR_ARG (exp, 1), 0);
7795 rtx_insn *label_r = label_rtx (label);
7796
7797 expand_builtin_setjmp_setup (buf_addr, receiver_label: label_r);
7798 return const0_rtx;
7799 }
7800 break;
7801
7802 case BUILT_IN_SETJMP_RECEIVER:
7803 /* __builtin_setjmp_receiver is passed the receiver label. */
7804 if (validate_arglist (callexpr: exp, POINTER_TYPE, VOID_TYPE))
7805 {
7806 tree label = TREE_OPERAND (CALL_EXPR_ARG (exp, 0), 0);
7807 rtx_insn *label_r = label_rtx (label);
7808
7809 expand_builtin_setjmp_receiver (receiver_label: label_r);
7810 nonlocal_goto_handler_labels
7811 = gen_rtx_INSN_LIST (VOIDmode, label_r,
7812 nonlocal_goto_handler_labels);
7813 /* ??? Do not let expand_label treat us as such since we would
7814 not want to be both on the list of non-local labels and on
7815 the list of forced labels. */
7816 FORCED_LABEL (label) = 0;
7817 return const0_rtx;
7818 }
7819 break;
7820
7821 /* __builtin_longjmp is passed a pointer to an array of five words.
7822 It's similar to the C library longjmp function but works with
7823 __builtin_setjmp above. */
7824 case BUILT_IN_LONGJMP:
7825 if (validate_arglist (callexpr: exp, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
7826 {
7827 rtx buf_addr = expand_expr (CALL_EXPR_ARG (exp, 0), target: subtarget,
7828 VOIDmode, modifier: EXPAND_NORMAL);
7829 rtx value = expand_normal (CALL_EXPR_ARG (exp, 1));
7830
7831 if (value != const1_rtx)
7832 {
7833 error ("%<__builtin_longjmp%> second argument must be 1");
7834 return const0_rtx;
7835 }
7836
7837 expand_builtin_longjmp (buf_addr, value);
7838 return const0_rtx;
7839 }
7840 break;
7841
7842 case BUILT_IN_NONLOCAL_GOTO:
7843 target = expand_builtin_nonlocal_goto (exp);
7844 if (target)
7845 return target;
7846 break;
7847
7848 /* This updates the setjmp buffer that is its argument with the value
7849 of the current stack pointer. */
7850 case BUILT_IN_UPDATE_SETJMP_BUF:
7851 if (validate_arglist (callexpr: exp, POINTER_TYPE, VOID_TYPE))
7852 {
7853 rtx buf_addr
7854 = expand_normal (CALL_EXPR_ARG (exp, 0));
7855
7856 expand_builtin_update_setjmp_buf (buf_addr);
7857 return const0_rtx;
7858 }
7859 break;
7860
7861 case BUILT_IN_TRAP:
7862 case BUILT_IN_UNREACHABLE_TRAP:
7863 expand_builtin_trap ();
7864 return const0_rtx;
7865
7866 case BUILT_IN_UNREACHABLE:
7867 expand_builtin_unreachable ();
7868 return const0_rtx;
7869
7870 CASE_FLT_FN (BUILT_IN_SIGNBIT):
7871 case BUILT_IN_SIGNBITD32:
7872 case BUILT_IN_SIGNBITD64:
7873 case BUILT_IN_SIGNBITD128:
7874 target = expand_builtin_signbit (exp, target);
7875 if (target)
7876 return target;
7877 break;
7878
7879 /* Various hooks for the DWARF 2 __throw routine. */
7880 case BUILT_IN_UNWIND_INIT:
7881 expand_builtin_unwind_init ();
7882 return const0_rtx;
7883 case BUILT_IN_DWARF_CFA:
7884 return virtual_cfa_rtx;
7885#ifdef DWARF2_UNWIND_INFO
7886 case BUILT_IN_DWARF_SP_COLUMN:
7887 return expand_builtin_dwarf_sp_column ();
7888 case BUILT_IN_INIT_DWARF_REG_SIZES:
7889 expand_builtin_init_dwarf_reg_sizes (CALL_EXPR_ARG (exp, 0));
7890 return const0_rtx;
7891#endif
7892 case BUILT_IN_FROB_RETURN_ADDR:
7893 return expand_builtin_frob_return_addr (CALL_EXPR_ARG (exp, 0));
7894 case BUILT_IN_EXTRACT_RETURN_ADDR:
7895 return expand_builtin_extract_return_addr (CALL_EXPR_ARG (exp, 0));
7896 case BUILT_IN_EH_RETURN:
7897 expand_builtin_eh_return (CALL_EXPR_ARG (exp, 0),
7898 CALL_EXPR_ARG (exp, 1));
7899 return const0_rtx;
7900 case BUILT_IN_EH_RETURN_DATA_REGNO:
7901 return expand_builtin_eh_return_data_regno (exp);
7902 case BUILT_IN_EXTEND_POINTER:
7903 return expand_builtin_extend_pointer (CALL_EXPR_ARG (exp, 0));
7904 case BUILT_IN_EH_POINTER:
7905 return expand_builtin_eh_pointer (exp);
7906 case BUILT_IN_EH_FILTER:
7907 return expand_builtin_eh_filter (exp);
7908 case BUILT_IN_EH_COPY_VALUES:
7909 return expand_builtin_eh_copy_values (exp);
7910
7911 case BUILT_IN_VA_START:
7912 return expand_builtin_va_start (exp);
7913 case BUILT_IN_VA_END:
7914 return expand_builtin_va_end (exp);
7915 case BUILT_IN_VA_COPY:
7916 return expand_builtin_va_copy (exp);
7917 case BUILT_IN_EXPECT:
7918 return expand_builtin_expect (exp, target);
7919 case BUILT_IN_EXPECT_WITH_PROBABILITY:
7920 return expand_builtin_expect_with_probability (exp, target);
7921 case BUILT_IN_ASSUME_ALIGNED:
7922 return expand_builtin_assume_aligned (exp, target);
7923 case BUILT_IN_PREFETCH:
7924 expand_builtin_prefetch (exp);
7925 return const0_rtx;
7926
7927 case BUILT_IN_INIT_TRAMPOLINE:
7928 return expand_builtin_init_trampoline (exp, onstack: true);
7929 case BUILT_IN_INIT_HEAP_TRAMPOLINE:
7930 return expand_builtin_init_trampoline (exp, onstack: false);
7931 case BUILT_IN_ADJUST_TRAMPOLINE:
7932 return expand_builtin_adjust_trampoline (exp);
7933
7934 case BUILT_IN_INIT_DESCRIPTOR:
7935 return expand_builtin_init_descriptor (exp);
7936 case BUILT_IN_ADJUST_DESCRIPTOR:
7937 return expand_builtin_adjust_descriptor (exp);
7938
7939 case BUILT_IN_FORK:
7940 case BUILT_IN_EXECL:
7941 case BUILT_IN_EXECV:
7942 case BUILT_IN_EXECLP:
7943 case BUILT_IN_EXECLE:
7944 case BUILT_IN_EXECVP:
7945 case BUILT_IN_EXECVE:
7946 target = expand_builtin_fork_or_exec (fn: fndecl, exp, target, ignore);
7947 if (target)
7948 return target;
7949 break;
7950
7951 case BUILT_IN_SYNC_FETCH_AND_ADD_1:
7952 case BUILT_IN_SYNC_FETCH_AND_ADD_2:
7953 case BUILT_IN_SYNC_FETCH_AND_ADD_4:
7954 case BUILT_IN_SYNC_FETCH_AND_ADD_8:
7955 case BUILT_IN_SYNC_FETCH_AND_ADD_16:
7956 mode = get_builtin_sync_mode (fcode_diff: fcode - BUILT_IN_SYNC_FETCH_AND_ADD_1);
7957 target = expand_builtin_sync_operation (mode, exp, code: PLUS, after: false, target);
7958 if (target)
7959 return target;
7960 break;
7961
7962 case BUILT_IN_SYNC_FETCH_AND_SUB_1:
7963 case BUILT_IN_SYNC_FETCH_AND_SUB_2:
7964 case BUILT_IN_SYNC_FETCH_AND_SUB_4:
7965 case BUILT_IN_SYNC_FETCH_AND_SUB_8:
7966 case BUILT_IN_SYNC_FETCH_AND_SUB_16:
7967 mode = get_builtin_sync_mode (fcode_diff: fcode - BUILT_IN_SYNC_FETCH_AND_SUB_1);
7968 target = expand_builtin_sync_operation (mode, exp, code: MINUS, after: false, target);
7969 if (target)
7970 return target;
7971 break;
7972
7973 case BUILT_IN_SYNC_FETCH_AND_OR_1:
7974 case BUILT_IN_SYNC_FETCH_AND_OR_2:
7975 case BUILT_IN_SYNC_FETCH_AND_OR_4:
7976 case BUILT_IN_SYNC_FETCH_AND_OR_8:
7977 case BUILT_IN_SYNC_FETCH_AND_OR_16:
7978 mode = get_builtin_sync_mode (fcode_diff: fcode - BUILT_IN_SYNC_FETCH_AND_OR_1);
7979 target = expand_builtin_sync_operation (mode, exp, code: IOR, after: false, target);
7980 if (target)
7981 return target;
7982 break;
7983
7984 case BUILT_IN_SYNC_FETCH_AND_AND_1:
7985 case BUILT_IN_SYNC_FETCH_AND_AND_2:
7986 case BUILT_IN_SYNC_FETCH_AND_AND_4:
7987 case BUILT_IN_SYNC_FETCH_AND_AND_8:
7988 case BUILT_IN_SYNC_FETCH_AND_AND_16:
7989 mode = get_builtin_sync_mode (fcode_diff: fcode - BUILT_IN_SYNC_FETCH_AND_AND_1);
7990 target = expand_builtin_sync_operation (mode, exp, code: AND, after: false, target);
7991 if (target)
7992 return target;
7993 break;
7994
7995 case BUILT_IN_SYNC_FETCH_AND_XOR_1:
7996 case BUILT_IN_SYNC_FETCH_AND_XOR_2:
7997 case BUILT_IN_SYNC_FETCH_AND_XOR_4:
7998 case BUILT_IN_SYNC_FETCH_AND_XOR_8:
7999 case BUILT_IN_SYNC_FETCH_AND_XOR_16:
8000 mode = get_builtin_sync_mode (fcode_diff: fcode - BUILT_IN_SYNC_FETCH_AND_XOR_1);
8001 target = expand_builtin_sync_operation (mode, exp, code: XOR, after: false, target);
8002 if (target)
8003 return target;
8004 break;
8005
8006 case BUILT_IN_SYNC_FETCH_AND_NAND_1:
8007 case BUILT_IN_SYNC_FETCH_AND_NAND_2:
8008 case BUILT_IN_SYNC_FETCH_AND_NAND_4:
8009 case BUILT_IN_SYNC_FETCH_AND_NAND_8:
8010 case BUILT_IN_SYNC_FETCH_AND_NAND_16:
8011 mode = get_builtin_sync_mode (fcode_diff: fcode - BUILT_IN_SYNC_FETCH_AND_NAND_1);
8012 target = expand_builtin_sync_operation (mode, exp, code: NOT, after: false, target);
8013 if (target)
8014 return target;
8015 break;
8016
8017 case BUILT_IN_SYNC_ADD_AND_FETCH_1:
8018 case BUILT_IN_SYNC_ADD_AND_FETCH_2:
8019 case BUILT_IN_SYNC_ADD_AND_FETCH_4:
8020 case BUILT_IN_SYNC_ADD_AND_FETCH_8:
8021 case BUILT_IN_SYNC_ADD_AND_FETCH_16:
8022 mode = get_builtin_sync_mode (fcode_diff: fcode - BUILT_IN_SYNC_ADD_AND_FETCH_1);
8023 target = expand_builtin_sync_operation (mode, exp, code: PLUS, after: true, target);
8024 if (target)
8025 return target;
8026 break;
8027
8028 case BUILT_IN_SYNC_SUB_AND_FETCH_1:
8029 case BUILT_IN_SYNC_SUB_AND_FETCH_2:
8030 case BUILT_IN_SYNC_SUB_AND_FETCH_4:
8031 case BUILT_IN_SYNC_SUB_AND_FETCH_8:
8032 case BUILT_IN_SYNC_SUB_AND_FETCH_16:
8033 mode = get_builtin_sync_mode (fcode_diff: fcode - BUILT_IN_SYNC_SUB_AND_FETCH_1);
8034 target = expand_builtin_sync_operation (mode, exp, code: MINUS, after: true, target);
8035 if (target)
8036 return target;
8037 break;
8038
8039 case BUILT_IN_SYNC_OR_AND_FETCH_1:
8040 case BUILT_IN_SYNC_OR_AND_FETCH_2:
8041 case BUILT_IN_SYNC_OR_AND_FETCH_4:
8042 case BUILT_IN_SYNC_OR_AND_FETCH_8:
8043 case BUILT_IN_SYNC_OR_AND_FETCH_16:
8044 mode = get_builtin_sync_mode (fcode_diff: fcode - BUILT_IN_SYNC_OR_AND_FETCH_1);
8045 target = expand_builtin_sync_operation (mode, exp, code: IOR, after: true, target);
8046 if (target)
8047 return target;
8048 break;
8049
8050 case BUILT_IN_SYNC_AND_AND_FETCH_1:
8051 case BUILT_IN_SYNC_AND_AND_FETCH_2:
8052 case BUILT_IN_SYNC_AND_AND_FETCH_4:
8053 case BUILT_IN_SYNC_AND_AND_FETCH_8:
8054 case BUILT_IN_SYNC_AND_AND_FETCH_16:
8055 mode = get_builtin_sync_mode (fcode_diff: fcode - BUILT_IN_SYNC_AND_AND_FETCH_1);
8056 target = expand_builtin_sync_operation (mode, exp, code: AND, after: true, target);
8057 if (target)
8058 return target;
8059 break;
8060
8061 case BUILT_IN_SYNC_XOR_AND_FETCH_1:
8062 case BUILT_IN_SYNC_XOR_AND_FETCH_2:
8063 case BUILT_IN_SYNC_XOR_AND_FETCH_4:
8064 case BUILT_IN_SYNC_XOR_AND_FETCH_8:
8065 case BUILT_IN_SYNC_XOR_AND_FETCH_16:
8066 mode = get_builtin_sync_mode (fcode_diff: fcode - BUILT_IN_SYNC_XOR_AND_FETCH_1);
8067 target = expand_builtin_sync_operation (mode, exp, code: XOR, after: true, target);
8068 if (target)
8069 return target;
8070 break;
8071
8072 case BUILT_IN_SYNC_NAND_AND_FETCH_1:
8073 case BUILT_IN_SYNC_NAND_AND_FETCH_2:
8074 case BUILT_IN_SYNC_NAND_AND_FETCH_4:
8075 case BUILT_IN_SYNC_NAND_AND_FETCH_8:
8076 case BUILT_IN_SYNC_NAND_AND_FETCH_16:
8077 mode = get_builtin_sync_mode (fcode_diff: fcode - BUILT_IN_SYNC_NAND_AND_FETCH_1);
8078 target = expand_builtin_sync_operation (mode, exp, code: NOT, after: true, target);
8079 if (target)
8080 return target;
8081 break;
8082
8083 case BUILT_IN_SYNC_BOOL_COMPARE_AND_SWAP_1:
8084 case BUILT_IN_SYNC_BOOL_COMPARE_AND_SWAP_2:
8085 case BUILT_IN_SYNC_BOOL_COMPARE_AND_SWAP_4:
8086 case BUILT_IN_SYNC_BOOL_COMPARE_AND_SWAP_8:
8087 case BUILT_IN_SYNC_BOOL_COMPARE_AND_SWAP_16:
8088 if (mode == VOIDmode)
8089 mode = TYPE_MODE (boolean_type_node);
8090 if (!target || !register_operand (target, mode))
8091 target = gen_reg_rtx (mode);
8092
8093 mode = get_builtin_sync_mode
8094 (fcode_diff: fcode - BUILT_IN_SYNC_BOOL_COMPARE_AND_SWAP_1);
8095 target = expand_builtin_compare_and_swap (mode, exp, is_bool: true, target);
8096 if (target)
8097 return target;
8098 break;
8099
8100 case BUILT_IN_SYNC_VAL_COMPARE_AND_SWAP_1:
8101 case BUILT_IN_SYNC_VAL_COMPARE_AND_SWAP_2:
8102 case BUILT_IN_SYNC_VAL_COMPARE_AND_SWAP_4:
8103 case BUILT_IN_SYNC_VAL_COMPARE_AND_SWAP_8:
8104 case BUILT_IN_SYNC_VAL_COMPARE_AND_SWAP_16:
8105 mode = get_builtin_sync_mode
8106 (fcode_diff: fcode - BUILT_IN_SYNC_VAL_COMPARE_AND_SWAP_1);
8107 target = expand_builtin_compare_and_swap (mode, exp, is_bool: false, target);
8108 if (target)
8109 return target;
8110 break;
8111
8112 case BUILT_IN_SYNC_LOCK_TEST_AND_SET_1:
8113 case BUILT_IN_SYNC_LOCK_TEST_AND_SET_2:
8114 case BUILT_IN_SYNC_LOCK_TEST_AND_SET_4:
8115 case BUILT_IN_SYNC_LOCK_TEST_AND_SET_8:
8116 case BUILT_IN_SYNC_LOCK_TEST_AND_SET_16:
8117 mode = get_builtin_sync_mode (fcode_diff: fcode - BUILT_IN_SYNC_LOCK_TEST_AND_SET_1);
8118 target = expand_builtin_sync_lock_test_and_set (mode, exp, target);
8119 if (target)
8120 return target;
8121 break;
8122
8123 case BUILT_IN_SYNC_LOCK_RELEASE_1:
8124 case BUILT_IN_SYNC_LOCK_RELEASE_2:
8125 case BUILT_IN_SYNC_LOCK_RELEASE_4:
8126 case BUILT_IN_SYNC_LOCK_RELEASE_8:
8127 case BUILT_IN_SYNC_LOCK_RELEASE_16:
8128 mode = get_builtin_sync_mode (fcode_diff: fcode - BUILT_IN_SYNC_LOCK_RELEASE_1);
8129 expand_builtin_sync_lock_release (mode, exp);
8130 return const0_rtx;
8131
8132 case BUILT_IN_SYNC_SYNCHRONIZE:
8133 expand_builtin_sync_synchronize ();
8134 return const0_rtx;
8135
8136 case BUILT_IN_ATOMIC_EXCHANGE_1:
8137 case BUILT_IN_ATOMIC_EXCHANGE_2:
8138 case BUILT_IN_ATOMIC_EXCHANGE_4:
8139 case BUILT_IN_ATOMIC_EXCHANGE_8:
8140 case BUILT_IN_ATOMIC_EXCHANGE_16:
8141 mode = get_builtin_sync_mode (fcode_diff: fcode - BUILT_IN_ATOMIC_EXCHANGE_1);
8142 target = expand_builtin_atomic_exchange (mode, exp, target);
8143 if (target)
8144 return target;
8145 break;
8146
8147 case BUILT_IN_ATOMIC_COMPARE_EXCHANGE_1:
8148 case BUILT_IN_ATOMIC_COMPARE_EXCHANGE_2:
8149 case BUILT_IN_ATOMIC_COMPARE_EXCHANGE_4:
8150 case BUILT_IN_ATOMIC_COMPARE_EXCHANGE_8:
8151 case BUILT_IN_ATOMIC_COMPARE_EXCHANGE_16:
8152 {
8153 unsigned int nargs, z;
8154 vec<tree, va_gc> *vec;
8155
8156 mode =
8157 get_builtin_sync_mode (fcode_diff: fcode - BUILT_IN_ATOMIC_COMPARE_EXCHANGE_1);
8158 target = expand_builtin_atomic_compare_exchange (mode, exp, target);
8159 if (target)
8160 return target;
8161
8162 /* If this is turned into an external library call, the weak parameter
8163 must be dropped to match the expected parameter list. */
8164 nargs = call_expr_nargs (exp);
8165 vec_alloc (v&: vec, nelems: nargs - 1);
8166 for (z = 0; z < 3; z++)
8167 vec->quick_push (CALL_EXPR_ARG (exp, z));
8168 /* Skip the boolean weak parameter. */
8169 for (z = 4; z < 6; z++)
8170 vec->quick_push (CALL_EXPR_ARG (exp, z));
8171 exp = build_call_vec (TREE_TYPE (exp), CALL_EXPR_FN (exp), vec);
8172 break;
8173 }
8174
8175 case BUILT_IN_ATOMIC_LOAD_1:
8176 case BUILT_IN_ATOMIC_LOAD_2:
8177 case BUILT_IN_ATOMIC_LOAD_4:
8178 case BUILT_IN_ATOMIC_LOAD_8:
8179 case BUILT_IN_ATOMIC_LOAD_16:
8180 mode = get_builtin_sync_mode (fcode_diff: fcode - BUILT_IN_ATOMIC_LOAD_1);
8181 target = expand_builtin_atomic_load (mode, exp, target);
8182 if (target)
8183 return target;
8184 break;
8185
8186 case BUILT_IN_ATOMIC_STORE_1:
8187 case BUILT_IN_ATOMIC_STORE_2:
8188 case BUILT_IN_ATOMIC_STORE_4:
8189 case BUILT_IN_ATOMIC_STORE_8:
8190 case BUILT_IN_ATOMIC_STORE_16:
8191 mode = get_builtin_sync_mode (fcode_diff: fcode - BUILT_IN_ATOMIC_STORE_1);
8192 target = expand_builtin_atomic_store (mode, exp);
8193 if (target)
8194 return const0_rtx;
8195 break;
8196
8197 case BUILT_IN_ATOMIC_ADD_FETCH_1:
8198 case BUILT_IN_ATOMIC_ADD_FETCH_2:
8199 case BUILT_IN_ATOMIC_ADD_FETCH_4:
8200 case BUILT_IN_ATOMIC_ADD_FETCH_8:
8201 case BUILT_IN_ATOMIC_ADD_FETCH_16:
8202 {
8203 enum built_in_function lib;
8204 mode = get_builtin_sync_mode (fcode_diff: fcode - BUILT_IN_ATOMIC_ADD_FETCH_1);
8205 lib = (enum built_in_function)((int)BUILT_IN_ATOMIC_FETCH_ADD_1 +
8206 (fcode - BUILT_IN_ATOMIC_ADD_FETCH_1));
8207 target = expand_builtin_atomic_fetch_op (mode, exp, target, code: PLUS, fetch_after: true,
8208 ignore, ext_call: lib);
8209 if (target)
8210 return target;
8211 break;
8212 }
8213 case BUILT_IN_ATOMIC_SUB_FETCH_1:
8214 case BUILT_IN_ATOMIC_SUB_FETCH_2:
8215 case BUILT_IN_ATOMIC_SUB_FETCH_4:
8216 case BUILT_IN_ATOMIC_SUB_FETCH_8:
8217 case BUILT_IN_ATOMIC_SUB_FETCH_16:
8218 {
8219 enum built_in_function lib;
8220 mode = get_builtin_sync_mode (fcode_diff: fcode - BUILT_IN_ATOMIC_SUB_FETCH_1);
8221 lib = (enum built_in_function)((int)BUILT_IN_ATOMIC_FETCH_SUB_1 +
8222 (fcode - BUILT_IN_ATOMIC_SUB_FETCH_1));
8223 target = expand_builtin_atomic_fetch_op (mode, exp, target, code: MINUS, fetch_after: true,
8224 ignore, ext_call: lib);
8225 if (target)
8226 return target;
8227 break;
8228 }
8229 case BUILT_IN_ATOMIC_AND_FETCH_1:
8230 case BUILT_IN_ATOMIC_AND_FETCH_2:
8231 case BUILT_IN_ATOMIC_AND_FETCH_4:
8232 case BUILT_IN_ATOMIC_AND_FETCH_8:
8233 case BUILT_IN_ATOMIC_AND_FETCH_16:
8234 {
8235 enum built_in_function lib;
8236 mode = get_builtin_sync_mode (fcode_diff: fcode - BUILT_IN_ATOMIC_AND_FETCH_1);
8237 lib = (enum built_in_function)((int)BUILT_IN_ATOMIC_FETCH_AND_1 +
8238 (fcode - BUILT_IN_ATOMIC_AND_FETCH_1));
8239 target = expand_builtin_atomic_fetch_op (mode, exp, target, code: AND, fetch_after: true,
8240 ignore, ext_call: lib);
8241 if (target)
8242 return target;
8243 break;
8244 }
8245 case BUILT_IN_ATOMIC_NAND_FETCH_1:
8246 case BUILT_IN_ATOMIC_NAND_FETCH_2:
8247 case BUILT_IN_ATOMIC_NAND_FETCH_4:
8248 case BUILT_IN_ATOMIC_NAND_FETCH_8:
8249 case BUILT_IN_ATOMIC_NAND_FETCH_16:
8250 {
8251 enum built_in_function lib;
8252 mode = get_builtin_sync_mode (fcode_diff: fcode - BUILT_IN_ATOMIC_NAND_FETCH_1);
8253 lib = (enum built_in_function)((int)BUILT_IN_ATOMIC_FETCH_NAND_1 +
8254 (fcode - BUILT_IN_ATOMIC_NAND_FETCH_1));
8255 target = expand_builtin_atomic_fetch_op (mode, exp, target, code: NOT, fetch_after: true,
8256 ignore, ext_call: lib);
8257 if (target)
8258 return target;
8259 break;
8260 }
8261 case BUILT_IN_ATOMIC_XOR_FETCH_1:
8262 case BUILT_IN_ATOMIC_XOR_FETCH_2:
8263 case BUILT_IN_ATOMIC_XOR_FETCH_4:
8264 case BUILT_IN_ATOMIC_XOR_FETCH_8:
8265 case BUILT_IN_ATOMIC_XOR_FETCH_16:
8266 {
8267 enum built_in_function lib;
8268 mode = get_builtin_sync_mode (fcode_diff: fcode - BUILT_IN_ATOMIC_XOR_FETCH_1);
8269 lib = (enum built_in_function)((int)BUILT_IN_ATOMIC_FETCH_XOR_1 +
8270 (fcode - BUILT_IN_ATOMIC_XOR_FETCH_1));
8271 target = expand_builtin_atomic_fetch_op (mode, exp, target, code: XOR, fetch_after: true,
8272 ignore, ext_call: lib);
8273 if (target)
8274 return target;
8275 break;
8276 }
8277 case BUILT_IN_ATOMIC_OR_FETCH_1:
8278 case BUILT_IN_ATOMIC_OR_FETCH_2:
8279 case BUILT_IN_ATOMIC_OR_FETCH_4:
8280 case BUILT_IN_ATOMIC_OR_FETCH_8:
8281 case BUILT_IN_ATOMIC_OR_FETCH_16:
8282 {
8283 enum built_in_function lib;
8284 mode = get_builtin_sync_mode (fcode_diff: fcode - BUILT_IN_ATOMIC_OR_FETCH_1);
8285 lib = (enum built_in_function)((int)BUILT_IN_ATOMIC_FETCH_OR_1 +
8286 (fcode - BUILT_IN_ATOMIC_OR_FETCH_1));
8287 target = expand_builtin_atomic_fetch_op (mode, exp, target, code: IOR, fetch_after: true,
8288 ignore, ext_call: lib);
8289 if (target)
8290 return target;
8291 break;
8292 }
8293 case BUILT_IN_ATOMIC_FETCH_ADD_1:
8294 case BUILT_IN_ATOMIC_FETCH_ADD_2:
8295 case BUILT_IN_ATOMIC_FETCH_ADD_4:
8296 case BUILT_IN_ATOMIC_FETCH_ADD_8:
8297 case BUILT_IN_ATOMIC_FETCH_ADD_16:
8298 mode = get_builtin_sync_mode (fcode_diff: fcode - BUILT_IN_ATOMIC_FETCH_ADD_1);
8299 target = expand_builtin_atomic_fetch_op (mode, exp, target, code: PLUS, fetch_after: false,
8300 ignore, ext_call: BUILT_IN_NONE);
8301 if (target)
8302 return target;
8303 break;
8304
8305 case BUILT_IN_ATOMIC_FETCH_SUB_1:
8306 case BUILT_IN_ATOMIC_FETCH_SUB_2:
8307 case BUILT_IN_ATOMIC_FETCH_SUB_4:
8308 case BUILT_IN_ATOMIC_FETCH_SUB_8:
8309 case BUILT_IN_ATOMIC_FETCH_SUB_16:
8310 mode = get_builtin_sync_mode (fcode_diff: fcode - BUILT_IN_ATOMIC_FETCH_SUB_1);
8311 target = expand_builtin_atomic_fetch_op (mode, exp, target, code: MINUS, fetch_after: false,
8312 ignore, ext_call: BUILT_IN_NONE);
8313 if (target)
8314 return target;
8315 break;
8316
8317 case BUILT_IN_ATOMIC_FETCH_AND_1:
8318 case BUILT_IN_ATOMIC_FETCH_AND_2:
8319 case BUILT_IN_ATOMIC_FETCH_AND_4:
8320 case BUILT_IN_ATOMIC_FETCH_AND_8:
8321 case BUILT_IN_ATOMIC_FETCH_AND_16:
8322 mode = get_builtin_sync_mode (fcode_diff: fcode - BUILT_IN_ATOMIC_FETCH_AND_1);
8323 target = expand_builtin_atomic_fetch_op (mode, exp, target, code: AND, fetch_after: false,
8324 ignore, ext_call: BUILT_IN_NONE);
8325 if (target)
8326 return target;
8327 break;
8328
8329 case BUILT_IN_ATOMIC_FETCH_NAND_1:
8330 case BUILT_IN_ATOMIC_FETCH_NAND_2:
8331 case BUILT_IN_ATOMIC_FETCH_NAND_4:
8332 case BUILT_IN_ATOMIC_FETCH_NAND_8:
8333 case BUILT_IN_ATOMIC_FETCH_NAND_16:
8334 mode = get_builtin_sync_mode (fcode_diff: fcode - BUILT_IN_ATOMIC_FETCH_NAND_1);
8335 target = expand_builtin_atomic_fetch_op (mode, exp, target, code: NOT, fetch_after: false,
8336 ignore, ext_call: BUILT_IN_NONE);
8337 if (target)
8338 return target;
8339 break;
8340
8341 case BUILT_IN_ATOMIC_FETCH_XOR_1:
8342 case BUILT_IN_ATOMIC_FETCH_XOR_2:
8343 case BUILT_IN_ATOMIC_FETCH_XOR_4:
8344 case BUILT_IN_ATOMIC_FETCH_XOR_8:
8345 case BUILT_IN_ATOMIC_FETCH_XOR_16:
8346 mode = get_builtin_sync_mode (fcode_diff: fcode - BUILT_IN_ATOMIC_FETCH_XOR_1);
8347 target = expand_builtin_atomic_fetch_op (mode, exp, target, code: XOR, fetch_after: false,
8348 ignore, ext_call: BUILT_IN_NONE);
8349 if (target)
8350 return target;
8351 break;
8352
8353 case BUILT_IN_ATOMIC_FETCH_OR_1:
8354 case BUILT_IN_ATOMIC_FETCH_OR_2:
8355 case BUILT_IN_ATOMIC_FETCH_OR_4:
8356 case BUILT_IN_ATOMIC_FETCH_OR_8:
8357 case BUILT_IN_ATOMIC_FETCH_OR_16:
8358 mode = get_builtin_sync_mode (fcode_diff: fcode - BUILT_IN_ATOMIC_FETCH_OR_1);
8359 target = expand_builtin_atomic_fetch_op (mode, exp, target, code: IOR, fetch_after: false,
8360 ignore, ext_call: BUILT_IN_NONE);
8361 if (target)
8362 return target;
8363 break;
8364
8365 case BUILT_IN_ATOMIC_TEST_AND_SET:
8366 target = expand_builtin_atomic_test_and_set (exp, target);
8367 if (target)
8368 return target;
8369 break;
8370
8371 case BUILT_IN_ATOMIC_CLEAR:
8372 return expand_builtin_atomic_clear (exp);
8373
8374 case BUILT_IN_ATOMIC_ALWAYS_LOCK_FREE:
8375 return expand_builtin_atomic_always_lock_free (exp);
8376
8377 case BUILT_IN_ATOMIC_IS_LOCK_FREE:
8378 target = expand_builtin_atomic_is_lock_free (exp);
8379 if (target)
8380 return target;
8381 break;
8382
8383 case BUILT_IN_ATOMIC_THREAD_FENCE:
8384 expand_builtin_atomic_thread_fence (exp);
8385 return const0_rtx;
8386
8387 case BUILT_IN_ATOMIC_SIGNAL_FENCE:
8388 expand_builtin_atomic_signal_fence (exp);
8389 return const0_rtx;
8390
8391 case BUILT_IN_OBJECT_SIZE:
8392 case BUILT_IN_DYNAMIC_OBJECT_SIZE:
8393 return expand_builtin_object_size (exp);
8394
8395 case BUILT_IN_MEMCPY_CHK:
8396 case BUILT_IN_MEMPCPY_CHK:
8397 case BUILT_IN_MEMMOVE_CHK:
8398 case BUILT_IN_MEMSET_CHK:
8399 target = expand_builtin_memory_chk (exp, target, mode, fcode);
8400 if (target)
8401 return target;
8402 break;
8403
8404 case BUILT_IN_STRCPY_CHK:
8405 case BUILT_IN_STPCPY_CHK:
8406 case BUILT_IN_STRNCPY_CHK:
8407 case BUILT_IN_STPNCPY_CHK:
8408 case BUILT_IN_STRCAT_CHK:
8409 case BUILT_IN_STRNCAT_CHK:
8410 case BUILT_IN_SNPRINTF_CHK:
8411 case BUILT_IN_VSNPRINTF_CHK:
8412 maybe_emit_chk_warning (exp, fcode);
8413 break;
8414
8415 case BUILT_IN_SPRINTF_CHK:
8416 case BUILT_IN_VSPRINTF_CHK:
8417 maybe_emit_sprintf_chk_warning (exp, fcode);
8418 break;
8419
8420 case BUILT_IN_THREAD_POINTER:
8421 return expand_builtin_thread_pointer (exp, target);
8422
8423 case BUILT_IN_SET_THREAD_POINTER:
8424 expand_builtin_set_thread_pointer (exp);
8425 return const0_rtx;
8426
8427 case BUILT_IN_ACC_ON_DEVICE:
8428 /* Do library call, if we failed to expand the builtin when
8429 folding. */
8430 break;
8431
8432 case BUILT_IN_GOACC_PARLEVEL_ID:
8433 case BUILT_IN_GOACC_PARLEVEL_SIZE:
8434 return expand_builtin_goacc_parlevel_id_size (exp, target, ignore);
8435
8436 case BUILT_IN_SPECULATION_SAFE_VALUE_PTR:
8437 return expand_speculation_safe_value (VOIDmode, exp, target, ignore);
8438
8439 case BUILT_IN_SPECULATION_SAFE_VALUE_1:
8440 case BUILT_IN_SPECULATION_SAFE_VALUE_2:
8441 case BUILT_IN_SPECULATION_SAFE_VALUE_4:
8442 case BUILT_IN_SPECULATION_SAFE_VALUE_8:
8443 case BUILT_IN_SPECULATION_SAFE_VALUE_16:
8444 mode = get_builtin_sync_mode (fcode_diff: fcode - BUILT_IN_SPECULATION_SAFE_VALUE_1);
8445 return expand_speculation_safe_value (mode, exp, target, ignore);
8446
8447 default: /* just do library call, if unknown builtin */
8448 break;
8449 }
8450
8451 /* The switch statement above can drop through to cause the function
8452 to be called normally. */
8453 return expand_call (exp, target, ignore);
8454}
8455
8456/* Determine whether a tree node represents a call to a built-in
8457 function. If the tree T is a call to a built-in function with
8458 the right number of arguments of the appropriate types, return
8459 the DECL_FUNCTION_CODE of the call, e.g. BUILT_IN_SQRT.
8460 Otherwise the return value is END_BUILTINS. */
8461
8462enum built_in_function
8463builtin_mathfn_code (const_tree t)
8464{
8465 const_tree fndecl, arg, parmlist;
8466 const_tree argtype, parmtype;
8467 const_call_expr_arg_iterator iter;
8468
8469 if (TREE_CODE (t) != CALL_EXPR)
8470 return END_BUILTINS;
8471
8472 fndecl = get_callee_fndecl (t);
8473 if (fndecl == NULL_TREE || !fndecl_built_in_p (node: fndecl, klass: BUILT_IN_NORMAL))
8474 return END_BUILTINS;
8475
8476 parmlist = TYPE_ARG_TYPES (TREE_TYPE (fndecl));
8477 init_const_call_expr_arg_iterator (exp: t, iter: &iter);
8478 for (; parmlist; parmlist = TREE_CHAIN (parmlist))
8479 {
8480 /* If a function doesn't take a variable number of arguments,
8481 the last element in the list will have type `void'. */
8482 parmtype = TREE_VALUE (parmlist);
8483 if (VOID_TYPE_P (parmtype))
8484 {
8485 if (more_const_call_expr_args_p (iter: &iter))
8486 return END_BUILTINS;
8487 return DECL_FUNCTION_CODE (decl: fndecl);
8488 }
8489
8490 if (! more_const_call_expr_args_p (iter: &iter))
8491 return END_BUILTINS;
8492
8493 arg = next_const_call_expr_arg (iter: &iter);
8494 argtype = TREE_TYPE (arg);
8495
8496 if (SCALAR_FLOAT_TYPE_P (parmtype))
8497 {
8498 if (! SCALAR_FLOAT_TYPE_P (argtype))
8499 return END_BUILTINS;
8500 }
8501 else if (COMPLEX_FLOAT_TYPE_P (parmtype))
8502 {
8503 if (! COMPLEX_FLOAT_TYPE_P (argtype))
8504 return END_BUILTINS;
8505 }
8506 else if (POINTER_TYPE_P (parmtype))
8507 {
8508 if (! POINTER_TYPE_P (argtype))
8509 return END_BUILTINS;
8510 }
8511 else if (INTEGRAL_TYPE_P (parmtype))
8512 {
8513 if (! INTEGRAL_TYPE_P (argtype))
8514 return END_BUILTINS;
8515 }
8516 else
8517 return END_BUILTINS;
8518 }
8519
8520 /* Variable-length argument list. */
8521 return DECL_FUNCTION_CODE (decl: fndecl);
8522}
8523
8524/* Fold a call to __builtin_constant_p, if we know its argument ARG will
8525 evaluate to a constant. */
8526
8527static tree
8528fold_builtin_constant_p (tree arg)
8529{
8530 /* We return 1 for a numeric type that's known to be a constant
8531 value at compile-time or for an aggregate type that's a
8532 literal constant. */
8533 STRIP_NOPS (arg);
8534
8535 /* If we know this is a constant, emit the constant of one. */
8536 if (CONSTANT_CLASS_P (arg)
8537 || (TREE_CODE (arg) == CONSTRUCTOR
8538 && TREE_CONSTANT (arg)))
8539 return integer_one_node;
8540 if (TREE_CODE (arg) == ADDR_EXPR)
8541 {
8542 tree op = TREE_OPERAND (arg, 0);
8543 if (TREE_CODE (op) == STRING_CST
8544 || (TREE_CODE (op) == ARRAY_REF
8545 && integer_zerop (TREE_OPERAND (op, 1))
8546 && TREE_CODE (TREE_OPERAND (op, 0)) == STRING_CST))
8547 return integer_one_node;
8548 }
8549
8550 /* If this expression has side effects, show we don't know it to be a
8551 constant. Likewise if it's a pointer or aggregate type since in
8552 those case we only want literals, since those are only optimized
8553 when generating RTL, not later.
8554 And finally, if we are compiling an initializer, not code, we
8555 need to return a definite result now; there's not going to be any
8556 more optimization done. */
8557 if (TREE_SIDE_EFFECTS (arg)
8558 || AGGREGATE_TYPE_P (TREE_TYPE (arg))
8559 || POINTER_TYPE_P (TREE_TYPE (arg))
8560 || cfun == 0
8561 || folding_initializer
8562 || force_folding_builtin_constant_p)
8563 return integer_zero_node;
8564
8565 return NULL_TREE;
8566}
8567
8568/* Create builtin_expect or builtin_expect_with_probability
8569 with PRED and EXPECTED as its arguments and return it as a truthvalue.
8570 Fortran FE can also produce builtin_expect with PREDICTOR as third argument.
8571 builtin_expect_with_probability instead uses third argument as PROBABILITY
8572 value. */
8573
8574static tree
8575build_builtin_expect_predicate (location_t loc, tree pred, tree expected,
8576 tree predictor, tree probability)
8577{
8578 tree fn, arg_types, pred_type, expected_type, call_expr, ret_type;
8579
8580 fn = builtin_decl_explicit (fncode: probability == NULL_TREE ? BUILT_IN_EXPECT
8581 : BUILT_IN_EXPECT_WITH_PROBABILITY);
8582 arg_types = TYPE_ARG_TYPES (TREE_TYPE (fn));
8583 ret_type = TREE_TYPE (TREE_TYPE (fn));
8584 pred_type = TREE_VALUE (arg_types);
8585 expected_type = TREE_VALUE (TREE_CHAIN (arg_types));
8586
8587 pred = fold_convert_loc (loc, pred_type, pred);
8588 expected = fold_convert_loc (loc, expected_type, expected);
8589
8590 if (probability)
8591 call_expr = build_call_expr_loc (loc, fn, 3, pred, expected, probability);
8592 else
8593 call_expr = build_call_expr_loc (loc, fn, predictor ? 3 : 2, pred, expected,
8594 predictor);
8595
8596 return build2 (NE_EXPR, TREE_TYPE (pred), call_expr,
8597 build_int_cst (ret_type, 0));
8598}
8599
8600/* Fold a call to builtin_expect with arguments ARG0, ARG1, ARG2, ARG3. Return
8601 NULL_TREE if no simplification is possible. */
8602
8603tree
8604fold_builtin_expect (location_t loc, tree arg0, tree arg1, tree arg2,
8605 tree arg3)
8606{
8607 tree inner, fndecl, inner_arg0;
8608 enum tree_code code;
8609
8610 /* Distribute the expected value over short-circuiting operators.
8611 See through the cast from truthvalue_type_node to long. */
8612 inner_arg0 = arg0;
8613 while (CONVERT_EXPR_P (inner_arg0)
8614 && INTEGRAL_TYPE_P (TREE_TYPE (inner_arg0))
8615 && INTEGRAL_TYPE_P (TREE_TYPE (TREE_OPERAND (inner_arg0, 0))))
8616 inner_arg0 = TREE_OPERAND (inner_arg0, 0);
8617
8618 /* If this is a builtin_expect within a builtin_expect keep the
8619 inner one. See through a comparison against a constant. It
8620 might have been added to create a thruthvalue. */
8621 inner = inner_arg0;
8622
8623 if (COMPARISON_CLASS_P (inner)
8624 && TREE_CODE (TREE_OPERAND (inner, 1)) == INTEGER_CST)
8625 inner = TREE_OPERAND (inner, 0);
8626
8627 if (TREE_CODE (inner) == CALL_EXPR
8628 && (fndecl = get_callee_fndecl (inner))
8629 && fndecl_built_in_p (node: fndecl, name1: BUILT_IN_EXPECT,
8630 names: BUILT_IN_EXPECT_WITH_PROBABILITY))
8631 return arg0;
8632
8633 inner = inner_arg0;
8634 code = TREE_CODE (inner);
8635 if (code == TRUTH_ANDIF_EXPR || code == TRUTH_ORIF_EXPR)
8636 {
8637 tree op0 = TREE_OPERAND (inner, 0);
8638 tree op1 = TREE_OPERAND (inner, 1);
8639 arg1 = save_expr (arg1);
8640
8641 op0 = build_builtin_expect_predicate (loc, pred: op0, expected: arg1, predictor: arg2, probability: arg3);
8642 op1 = build_builtin_expect_predicate (loc, pred: op1, expected: arg1, predictor: arg2, probability: arg3);
8643 inner = build2 (code, TREE_TYPE (inner), op0, op1);
8644
8645 return fold_convert_loc (loc, TREE_TYPE (arg0), inner);
8646 }
8647
8648 /* If the argument isn't invariant then there's nothing else we can do. */
8649 if (!TREE_CONSTANT (inner_arg0))
8650 return NULL_TREE;
8651
8652 /* If we expect that a comparison against the argument will fold to
8653 a constant return the constant. In practice, this means a true
8654 constant or the address of a non-weak symbol. */
8655 inner = inner_arg0;
8656 STRIP_NOPS (inner);
8657 if (TREE_CODE (inner) == ADDR_EXPR)
8658 {
8659 do
8660 {
8661 inner = TREE_OPERAND (inner, 0);
8662 }
8663 while (TREE_CODE (inner) == COMPONENT_REF
8664 || TREE_CODE (inner) == ARRAY_REF);
8665 if (VAR_OR_FUNCTION_DECL_P (inner) && DECL_WEAK (inner))
8666 return NULL_TREE;
8667 }
8668
8669 /* Otherwise, ARG0 already has the proper type for the return value. */
8670 return arg0;
8671}
8672
8673/* Fold a call to __builtin_classify_type with argument ARG. */
8674
8675static tree
8676fold_builtin_classify_type (tree arg)
8677{
8678 if (arg == 0)
8679 return build_int_cst (integer_type_node, no_type_class);
8680
8681 return build_int_cst (integer_type_node, type_to_class (TREE_TYPE (arg)));
8682}
8683
8684/* Fold a call EXPR (which may be null) to __builtin_strlen with argument
8685 ARG. */
8686
8687static tree
8688fold_builtin_strlen (location_t loc, tree expr, tree type, tree arg)
8689{
8690 if (!validate_arg (arg, code: POINTER_TYPE))
8691 return NULL_TREE;
8692 else
8693 {
8694 c_strlen_data lendata = { };
8695 tree len = c_strlen (arg, only_value: 0, data: &lendata);
8696
8697 if (len)
8698 return fold_convert_loc (loc, type, len);
8699
8700 /* TODO: Move this to gimple-ssa-warn-access once the pass runs
8701 also early enough to detect invalid reads in multimensional
8702 arrays and struct members. */
8703 if (!lendata.decl)
8704 c_strlen (arg, only_value: 1, data: &lendata);
8705
8706 if (lendata.decl)
8707 {
8708 if (EXPR_HAS_LOCATION (arg))
8709 loc = EXPR_LOCATION (arg);
8710 else if (loc == UNKNOWN_LOCATION)
8711 loc = input_location;
8712 warn_string_no_nul (loc, expr, "strlen", arg, lendata.decl);
8713 }
8714
8715 return NULL_TREE;
8716 }
8717}
8718
8719/* Fold a call to __builtin_inf or __builtin_huge_val. */
8720
8721static tree
8722fold_builtin_inf (location_t loc, tree type, int warn)
8723{
8724 /* __builtin_inff is intended to be usable to define INFINITY on all
8725 targets. If an infinity is not available, INFINITY expands "to a
8726 positive constant of type float that overflows at translation
8727 time", footnote "In this case, using INFINITY will violate the
8728 constraint in 6.4.4 and thus require a diagnostic." (C99 7.12#4).
8729 Thus we pedwarn to ensure this constraint violation is
8730 diagnosed. */
8731 if (!MODE_HAS_INFINITIES (TYPE_MODE (type)) && warn)
8732 pedwarn (loc, 0, "target format does not support infinity");
8733
8734 return build_real (type, dconstinf);
8735}
8736
8737/* Fold function call to builtin sincos, sincosf, or sincosl. Return
8738 NULL_TREE if no simplification can be made. */
8739
8740static tree
8741fold_builtin_sincos (location_t loc,
8742 tree arg0, tree arg1, tree arg2)
8743{
8744 tree type;
8745 tree fndecl, call = NULL_TREE;
8746
8747 if (!validate_arg (arg0, code: REAL_TYPE)
8748 || !validate_arg (arg1, code: POINTER_TYPE)
8749 || !validate_arg (arg2, code: POINTER_TYPE))
8750 return NULL_TREE;
8751
8752 type = TREE_TYPE (arg0);
8753
8754 /* Calculate the result when the argument is a constant. */
8755 built_in_function fn = mathfn_built_in_2 (type, fn: CFN_BUILT_IN_CEXPI);
8756 if (fn == END_BUILTINS)
8757 return NULL_TREE;
8758
8759 /* Canonicalize sincos to cexpi. */
8760 if (TREE_CODE (arg0) == REAL_CST)
8761 {
8762 tree complex_type = build_complex_type (type);
8763 call = fold_const_call (as_combined_fn (fn), complex_type, arg0);
8764 }
8765 if (!call)
8766 {
8767 if (!targetm.libc_has_function (function_c99_math_complex, type)
8768 || !builtin_decl_implicit_p (fncode: fn))
8769 return NULL_TREE;
8770 fndecl = builtin_decl_explicit (fncode: fn);
8771 call = build_call_expr_loc (loc, fndecl, 1, arg0);
8772 call = builtin_save_expr (exp: call);
8773 }
8774
8775 tree ptype = build_pointer_type (type);
8776 arg1 = fold_convert (ptype, arg1);
8777 arg2 = fold_convert (ptype, arg2);
8778 return build2 (COMPOUND_EXPR, void_type_node,
8779 build2 (MODIFY_EXPR, void_type_node,
8780 build_fold_indirect_ref_loc (loc, arg1),
8781 fold_build1_loc (loc, IMAGPART_EXPR, type, call)),
8782 build2 (MODIFY_EXPR, void_type_node,
8783 build_fold_indirect_ref_loc (loc, arg2),
8784 fold_build1_loc (loc, REALPART_EXPR, type, call)));
8785}
8786
8787/* Fold function call to builtin memcmp with arguments ARG1 and ARG2.
8788 Return NULL_TREE if no simplification can be made. */
8789
8790static tree
8791fold_builtin_memcmp (location_t loc, tree arg1, tree arg2, tree len)
8792{
8793 if (!validate_arg (arg1, code: POINTER_TYPE)
8794 || !validate_arg (arg2, code: POINTER_TYPE)
8795 || !validate_arg (len, code: INTEGER_TYPE))
8796 return NULL_TREE;
8797
8798 /* If the LEN parameter is zero, return zero. */
8799 if (integer_zerop (len))
8800 return omit_two_operands_loc (loc, integer_type_node, integer_zero_node,
8801 arg1, arg2);
8802
8803 /* If ARG1 and ARG2 are the same (and not volatile), return zero. */
8804 if (operand_equal_p (arg1, arg2, flags: 0))
8805 return omit_one_operand_loc (loc, integer_type_node, integer_zero_node, len);
8806
8807 /* If len parameter is one, return an expression corresponding to
8808 (*(const unsigned char*)arg1 - (const unsigned char*)arg2). */
8809 if (tree_fits_uhwi_p (len) && tree_to_uhwi (len) == 1)
8810 {
8811 tree cst_uchar_node = build_type_variant (unsigned_char_type_node, 1, 0);
8812 tree cst_uchar_ptr_node
8813 = build_pointer_type_for_mode (cst_uchar_node, ptr_mode, true);
8814
8815 tree ind1
8816 = fold_convert_loc (loc, integer_type_node,
8817 build1 (INDIRECT_REF, cst_uchar_node,
8818 fold_convert_loc (loc,
8819 cst_uchar_ptr_node,
8820 arg1)));
8821 tree ind2
8822 = fold_convert_loc (loc, integer_type_node,
8823 build1 (INDIRECT_REF, cst_uchar_node,
8824 fold_convert_loc (loc,
8825 cst_uchar_ptr_node,
8826 arg2)));
8827 return fold_build2_loc (loc, MINUS_EXPR, integer_type_node, ind1, ind2);
8828 }
8829
8830 return NULL_TREE;
8831}
8832
8833/* Fold a call to builtin isascii with argument ARG. */
8834
8835static tree
8836fold_builtin_isascii (location_t loc, tree arg)
8837{
8838 if (!validate_arg (arg, code: INTEGER_TYPE))
8839 return NULL_TREE;
8840 else
8841 {
8842 /* Transform isascii(c) -> ((c & ~0x7f) == 0). */
8843 arg = fold_build2 (BIT_AND_EXPR, integer_type_node, arg,
8844 build_int_cst (integer_type_node,
8845 ~ (unsigned HOST_WIDE_INT) 0x7f));
8846 return fold_build2_loc (loc, EQ_EXPR, integer_type_node,
8847 arg, integer_zero_node);
8848 }
8849}
8850
8851/* Fold a call to builtin toascii with argument ARG. */
8852
8853static tree
8854fold_builtin_toascii (location_t loc, tree arg)
8855{
8856 if (!validate_arg (arg, code: INTEGER_TYPE))
8857 return NULL_TREE;
8858
8859 /* Transform toascii(c) -> (c & 0x7f). */
8860 return fold_build2_loc (loc, BIT_AND_EXPR, integer_type_node, arg,
8861 build_int_cst (integer_type_node, 0x7f));
8862}
8863
8864/* Fold a call to builtin isdigit with argument ARG. */
8865
8866static tree
8867fold_builtin_isdigit (location_t loc, tree arg)
8868{
8869 if (!validate_arg (arg, code: INTEGER_TYPE))
8870 return NULL_TREE;
8871 else
8872 {
8873 /* Transform isdigit(c) -> (unsigned)(c) - '0' <= 9. */
8874 /* According to the C standard, isdigit is unaffected by locale.
8875 However, it definitely is affected by the target character set. */
8876 unsigned HOST_WIDE_INT target_digit0
8877 = lang_hooks.to_target_charset ('0');
8878
8879 if (target_digit0 == 0)
8880 return NULL_TREE;
8881
8882 arg = fold_convert_loc (loc, unsigned_type_node, arg);
8883 arg = fold_build2 (MINUS_EXPR, unsigned_type_node, arg,
8884 build_int_cst (unsigned_type_node, target_digit0));
8885 return fold_build2_loc (loc, LE_EXPR, integer_type_node, arg,
8886 build_int_cst (unsigned_type_node, 9));
8887 }
8888}
8889
8890/* Fold a call to fabs, fabsf or fabsl with argument ARG. */
8891
8892static tree
8893fold_builtin_fabs (location_t loc, tree arg, tree type)
8894{
8895 if (!validate_arg (arg, code: REAL_TYPE))
8896 return NULL_TREE;
8897
8898 arg = fold_convert_loc (loc, type, arg);
8899 return fold_build1_loc (loc, ABS_EXPR, type, arg);
8900}
8901
8902/* Fold a call to abs, labs, llabs or imaxabs with argument ARG. */
8903
8904static tree
8905fold_builtin_abs (location_t loc, tree arg, tree type)
8906{
8907 if (!validate_arg (arg, code: INTEGER_TYPE))
8908 return NULL_TREE;
8909
8910 arg = fold_convert_loc (loc, type, arg);
8911 return fold_build1_loc (loc, ABS_EXPR, type, arg);
8912}
8913
8914/* Fold a call to builtin carg(a+bi) -> atan2(b,a). */
8915
8916static tree
8917fold_builtin_carg (location_t loc, tree arg, tree type)
8918{
8919 if (validate_arg (arg, code: COMPLEX_TYPE)
8920 && SCALAR_FLOAT_TYPE_P (TREE_TYPE (TREE_TYPE (arg))))
8921 {
8922 tree atan2_fn = mathfn_built_in (type, fn: BUILT_IN_ATAN2);
8923
8924 if (atan2_fn)
8925 {
8926 tree new_arg = builtin_save_expr (exp: arg);
8927 tree r_arg = fold_build1_loc (loc, REALPART_EXPR, type, new_arg);
8928 tree i_arg = fold_build1_loc (loc, IMAGPART_EXPR, type, new_arg);
8929 return build_call_expr_loc (loc, atan2_fn, 2, i_arg, r_arg);
8930 }
8931 }
8932
8933 return NULL_TREE;
8934}
8935
8936/* Fold a call to builtin frexp, we can assume the base is 2. */
8937
8938static tree
8939fold_builtin_frexp (location_t loc, tree arg0, tree arg1, tree rettype)
8940{
8941 if (! validate_arg (arg0, code: REAL_TYPE) || ! validate_arg (arg1, code: POINTER_TYPE))
8942 return NULL_TREE;
8943
8944 STRIP_NOPS (arg0);
8945
8946 if (!(TREE_CODE (arg0) == REAL_CST && ! TREE_OVERFLOW (arg0)))
8947 return NULL_TREE;
8948
8949 arg1 = build_fold_indirect_ref_loc (loc, arg1);
8950
8951 /* Proceed if a valid pointer type was passed in. */
8952 if (TYPE_MAIN_VARIANT (TREE_TYPE (arg1)) == integer_type_node)
8953 {
8954 const REAL_VALUE_TYPE *const value = TREE_REAL_CST_PTR (arg0);
8955 tree frac, exp, res;
8956
8957 switch (value->cl)
8958 {
8959 case rvc_zero:
8960 /* For +-0, return (*exp = 0, +-0). */
8961 exp = integer_zero_node;
8962 frac = arg0;
8963 break;
8964 case rvc_nan:
8965 case rvc_inf:
8966 /* For +-NaN or +-Inf, *exp is unspecified, return arg0. */
8967 return omit_one_operand_loc (loc, rettype, arg0, arg1);
8968 case rvc_normal:
8969 {
8970 /* Since the frexp function always expects base 2, and in
8971 GCC normalized significands are already in the range
8972 [0.5, 1.0), we have exactly what frexp wants. */
8973 REAL_VALUE_TYPE frac_rvt = *value;
8974 SET_REAL_EXP (&frac_rvt, 0);
8975 frac = build_real (rettype, frac_rvt);
8976 exp = build_int_cst (integer_type_node, REAL_EXP (value));
8977 }
8978 break;
8979 default:
8980 gcc_unreachable ();
8981 }
8982
8983 /* Create the COMPOUND_EXPR (*arg1 = trunc, frac). */
8984 arg1 = fold_build2_loc (loc, MODIFY_EXPR, rettype, arg1, exp);
8985 TREE_SIDE_EFFECTS (arg1) = 1;
8986 res = fold_build2_loc (loc, COMPOUND_EXPR, rettype, arg1, frac);
8987 suppress_warning (res, OPT_Wunused_value);
8988 return res;
8989 }
8990
8991 return NULL_TREE;
8992}
8993
8994/* Fold a call to builtin modf. */
8995
8996static tree
8997fold_builtin_modf (location_t loc, tree arg0, tree arg1, tree rettype)
8998{
8999 if (! validate_arg (arg0, code: REAL_TYPE) || ! validate_arg (arg1, code: POINTER_TYPE))
9000 return NULL_TREE;
9001
9002 STRIP_NOPS (arg0);
9003
9004 if (!(TREE_CODE (arg0) == REAL_CST && ! TREE_OVERFLOW (arg0)))
9005 return NULL_TREE;
9006
9007 arg1 = build_fold_indirect_ref_loc (loc, arg1);
9008
9009 /* Proceed if a valid pointer type was passed in. */
9010 if (TYPE_MAIN_VARIANT (TREE_TYPE (arg1)) == TYPE_MAIN_VARIANT (rettype))
9011 {
9012 const REAL_VALUE_TYPE *const value = TREE_REAL_CST_PTR (arg0);
9013 REAL_VALUE_TYPE trunc, frac;
9014 tree res;
9015
9016 switch (value->cl)
9017 {
9018 case rvc_nan:
9019 case rvc_zero:
9020 /* For +-NaN or +-0, return (*arg1 = arg0, arg0). */
9021 trunc = frac = *value;
9022 break;
9023 case rvc_inf:
9024 /* For +-Inf, return (*arg1 = arg0, +-0). */
9025 frac = dconst0;
9026 frac.sign = value->sign;
9027 trunc = *value;
9028 break;
9029 case rvc_normal:
9030 /* Return (*arg1 = trunc(arg0), arg0-trunc(arg0)). */
9031 real_trunc (&trunc, VOIDmode, value);
9032 real_arithmetic (&frac, MINUS_EXPR, value, &trunc);
9033 /* If the original number was negative and already
9034 integral, then the fractional part is -0.0. */
9035 if (value->sign && frac.cl == rvc_zero)
9036 frac.sign = value->sign;
9037 break;
9038 }
9039
9040 /* Create the COMPOUND_EXPR (*arg1 = trunc, frac). */
9041 arg1 = fold_build2_loc (loc, MODIFY_EXPR, rettype, arg1,
9042 build_real (rettype, trunc));
9043 TREE_SIDE_EFFECTS (arg1) = 1;
9044 res = fold_build2_loc (loc, COMPOUND_EXPR, rettype, arg1,
9045 build_real (rettype, frac));
9046 suppress_warning (res, OPT_Wunused_value);
9047 return res;
9048 }
9049
9050 return NULL_TREE;
9051}
9052
9053/* Given a location LOC, an interclass builtin function decl FNDECL
9054 and its single argument ARG, return an folded expression computing
9055 the same, or NULL_TREE if we either couldn't or didn't want to fold
9056 (the latter happen if there's an RTL instruction available). */
9057
9058static tree
9059fold_builtin_interclass_mathfn (location_t loc, tree fndecl, tree arg)
9060{
9061 machine_mode mode;
9062
9063 if (!validate_arg (arg, code: REAL_TYPE))
9064 return NULL_TREE;
9065
9066 if (interclass_mathfn_icode (arg, fndecl) != CODE_FOR_nothing)
9067 return NULL_TREE;
9068
9069 mode = TYPE_MODE (TREE_TYPE (arg));
9070
9071 bool is_ibm_extended = MODE_COMPOSITE_P (mode);
9072
9073 /* If there is no optab, try generic code. */
9074 switch (DECL_FUNCTION_CODE (decl: fndecl))
9075 {
9076 tree result;
9077
9078 CASE_FLT_FN (BUILT_IN_ISINF):
9079 {
9080 /* isinf(x) -> isgreater(fabs(x),DBL_MAX). */
9081 tree const isgr_fn = builtin_decl_explicit (fncode: BUILT_IN_ISGREATER);
9082 tree type = TREE_TYPE (arg);
9083 REAL_VALUE_TYPE r;
9084 char buf[128];
9085
9086 if (is_ibm_extended)
9087 {
9088 /* NaN and Inf are encoded in the high-order double value
9089 only. The low-order value is not significant. */
9090 type = double_type_node;
9091 mode = DFmode;
9092 arg = fold_build1_loc (loc, NOP_EXPR, type, arg);
9093 }
9094 get_max_float (REAL_MODE_FORMAT (mode), buf, sizeof (buf), false);
9095 real_from_string (&r, buf);
9096 result = build_call_expr (isgr_fn, 2,
9097 fold_build1_loc (loc, ABS_EXPR, type, arg),
9098 build_real (type, r));
9099 return result;
9100 }
9101 CASE_FLT_FN (BUILT_IN_FINITE):
9102 case BUILT_IN_ISFINITE:
9103 {
9104 /* isfinite(x) -> islessequal(fabs(x),DBL_MAX). */
9105 tree const isle_fn = builtin_decl_explicit (fncode: BUILT_IN_ISLESSEQUAL);
9106 tree type = TREE_TYPE (arg);
9107 REAL_VALUE_TYPE r;
9108 char buf[128];
9109
9110 if (is_ibm_extended)
9111 {
9112 /* NaN and Inf are encoded in the high-order double value
9113 only. The low-order value is not significant. */
9114 type = double_type_node;
9115 mode = DFmode;
9116 arg = fold_build1_loc (loc, NOP_EXPR, type, arg);
9117 }
9118 get_max_float (REAL_MODE_FORMAT (mode), buf, sizeof (buf), false);
9119 real_from_string (&r, buf);
9120 result = build_call_expr (isle_fn, 2,
9121 fold_build1_loc (loc, ABS_EXPR, type, arg),
9122 build_real (type, r));
9123 /*result = fold_build2_loc (loc, UNGT_EXPR,
9124 TREE_TYPE (TREE_TYPE (fndecl)),
9125 fold_build1_loc (loc, ABS_EXPR, type, arg),
9126 build_real (type, r));
9127 result = fold_build1_loc (loc, TRUTH_NOT_EXPR,
9128 TREE_TYPE (TREE_TYPE (fndecl)),
9129 result);*/
9130 return result;
9131 }
9132 case BUILT_IN_ISNORMAL:
9133 {
9134 /* isnormal(x) -> isgreaterequal(fabs(x),DBL_MIN) &
9135 islessequal(fabs(x),DBL_MAX). */
9136 tree const isle_fn = builtin_decl_explicit (fncode: BUILT_IN_ISLESSEQUAL);
9137 tree type = TREE_TYPE (arg);
9138 tree orig_arg, max_exp, min_exp;
9139 machine_mode orig_mode = mode;
9140 REAL_VALUE_TYPE rmax, rmin;
9141 char buf[128];
9142
9143 orig_arg = arg = builtin_save_expr (exp: arg);
9144 if (is_ibm_extended)
9145 {
9146 /* Use double to test the normal range of IBM extended
9147 precision. Emin for IBM extended precision is
9148 different to emin for IEEE double, being 53 higher
9149 since the low double exponent is at least 53 lower
9150 than the high double exponent. */
9151 type = double_type_node;
9152 mode = DFmode;
9153 arg = fold_build1_loc (loc, NOP_EXPR, type, arg);
9154 }
9155 arg = fold_build1_loc (loc, ABS_EXPR, type, arg);
9156
9157 get_max_float (REAL_MODE_FORMAT (mode), buf, sizeof (buf), false);
9158 real_from_string (&rmax, buf);
9159 sprintf (s: buf, format: "0x1p%d", REAL_MODE_FORMAT (orig_mode)->emin - 1);
9160 real_from_string (&rmin, buf);
9161 max_exp = build_real (type, rmax);
9162 min_exp = build_real (type, rmin);
9163
9164 max_exp = build_call_expr (isle_fn, 2, arg, max_exp);
9165 if (is_ibm_extended)
9166 {
9167 /* Testing the high end of the range is done just using
9168 the high double, using the same test as isfinite().
9169 For the subnormal end of the range we first test the
9170 high double, then if its magnitude is equal to the
9171 limit of 0x1p-969, we test whether the low double is
9172 non-zero and opposite sign to the high double. */
9173 tree const islt_fn = builtin_decl_explicit (fncode: BUILT_IN_ISLESS);
9174 tree const isgt_fn = builtin_decl_explicit (fncode: BUILT_IN_ISGREATER);
9175 tree gt_min = build_call_expr (isgt_fn, 2, arg, min_exp);
9176 tree eq_min = fold_build2 (EQ_EXPR, integer_type_node,
9177 arg, min_exp);
9178 tree as_complex = build1 (VIEW_CONVERT_EXPR,
9179 complex_double_type_node, orig_arg);
9180 tree hi_dbl = build1 (REALPART_EXPR, type, as_complex);
9181 tree lo_dbl = build1 (IMAGPART_EXPR, type, as_complex);
9182 tree zero = build_real (type, dconst0);
9183 tree hilt = build_call_expr (islt_fn, 2, hi_dbl, zero);
9184 tree lolt = build_call_expr (islt_fn, 2, lo_dbl, zero);
9185 tree logt = build_call_expr (isgt_fn, 2, lo_dbl, zero);
9186 tree ok_lo = fold_build1 (TRUTH_NOT_EXPR, integer_type_node,
9187 fold_build3 (COND_EXPR,
9188 integer_type_node,
9189 hilt, logt, lolt));
9190 eq_min = fold_build2 (TRUTH_ANDIF_EXPR, integer_type_node,
9191 eq_min, ok_lo);
9192 min_exp = fold_build2 (TRUTH_ORIF_EXPR, integer_type_node,
9193 gt_min, eq_min);
9194 }
9195 else
9196 {
9197 tree const isge_fn
9198 = builtin_decl_explicit (fncode: BUILT_IN_ISGREATEREQUAL);
9199 min_exp = build_call_expr (isge_fn, 2, arg, min_exp);
9200 }
9201 result = fold_build2 (BIT_AND_EXPR, integer_type_node,
9202 max_exp, min_exp);
9203 return result;
9204 }
9205 default:
9206 break;
9207 }
9208
9209 return NULL_TREE;
9210}
9211
9212/* Fold a call to __builtin_isnan(), __builtin_isinf, __builtin_finite.
9213 ARG is the argument for the call. */
9214
9215static tree
9216fold_builtin_classify (location_t loc, tree fndecl, tree arg, int builtin_index)
9217{
9218 tree type = TREE_TYPE (TREE_TYPE (fndecl));
9219
9220 if (!validate_arg (arg, code: REAL_TYPE))
9221 return NULL_TREE;
9222
9223 switch (builtin_index)
9224 {
9225 case BUILT_IN_ISINF:
9226 if (tree_expr_infinite_p (arg))
9227 return omit_one_operand_loc (loc, type, integer_one_node, arg);
9228 if (!tree_expr_maybe_infinite_p (arg))
9229 return omit_one_operand_loc (loc, type, integer_zero_node, arg);
9230 return NULL_TREE;
9231
9232 case BUILT_IN_ISINF_SIGN:
9233 {
9234 /* isinf_sign(x) -> isinf(x) ? (signbit(x) ? -1 : 1) : 0 */
9235 /* In a boolean context, GCC will fold the inner COND_EXPR to
9236 1. So e.g. "if (isinf_sign(x))" would be folded to just
9237 "if (isinf(x) ? 1 : 0)" which becomes "if (isinf(x))". */
9238 tree signbit_fn = builtin_decl_explicit (fncode: BUILT_IN_SIGNBIT);
9239 tree isinf_fn = builtin_decl_explicit (fncode: BUILT_IN_ISINF);
9240 tree tmp = NULL_TREE;
9241
9242 arg = builtin_save_expr (exp: arg);
9243
9244 if (signbit_fn && isinf_fn)
9245 {
9246 tree signbit_call = build_call_expr_loc (loc, signbit_fn, 1, arg);
9247 tree isinf_call = build_call_expr_loc (loc, isinf_fn, 1, arg);
9248
9249 signbit_call = fold_build2_loc (loc, NE_EXPR, integer_type_node,
9250 signbit_call, integer_zero_node);
9251 isinf_call = fold_build2_loc (loc, NE_EXPR, integer_type_node,
9252 isinf_call, integer_zero_node);
9253
9254 tmp = fold_build3_loc (loc, COND_EXPR, integer_type_node, signbit_call,
9255 integer_minus_one_node, integer_one_node);
9256 tmp = fold_build3_loc (loc, COND_EXPR, integer_type_node,
9257 isinf_call, tmp,
9258 integer_zero_node);
9259 }
9260
9261 return tmp;
9262 }
9263
9264 case BUILT_IN_ISFINITE:
9265 if (tree_expr_finite_p (arg))
9266 return omit_one_operand_loc (loc, type, integer_one_node, arg);
9267 if (tree_expr_nan_p (arg) || tree_expr_infinite_p (arg))
9268 return omit_one_operand_loc (loc, type, integer_zero_node, arg);
9269 return NULL_TREE;
9270
9271 case BUILT_IN_ISNAN:
9272 if (tree_expr_nan_p (arg))
9273 return omit_one_operand_loc (loc, type, integer_one_node, arg);
9274 if (!tree_expr_maybe_nan_p (arg))
9275 return omit_one_operand_loc (loc, type, integer_zero_node, arg);
9276
9277 {
9278 bool is_ibm_extended = MODE_COMPOSITE_P (TYPE_MODE (TREE_TYPE (arg)));
9279 if (is_ibm_extended)
9280 {
9281 /* NaN and Inf are encoded in the high-order double value
9282 only. The low-order value is not significant. */
9283 arg = fold_build1_loc (loc, NOP_EXPR, double_type_node, arg);
9284 }
9285 }
9286 arg = builtin_save_expr (exp: arg);
9287 return fold_build2_loc (loc, UNORDERED_EXPR, type, arg, arg);
9288
9289 case BUILT_IN_ISSIGNALING:
9290 /* Folding to true for REAL_CST is done in fold_const_call_ss.
9291 Don't use tree_expr_signaling_nan_p (arg) -> integer_one_node
9292 and !tree_expr_maybe_signaling_nan_p (arg) -> integer_zero_node
9293 here, so there is some possibility of __builtin_issignaling working
9294 without -fsignaling-nans. Especially when -fno-signaling-nans is
9295 the default. */
9296 if (!tree_expr_maybe_nan_p (arg))
9297 return omit_one_operand_loc (loc, type, integer_zero_node, arg);
9298 return NULL_TREE;
9299
9300 default:
9301 gcc_unreachable ();
9302 }
9303}
9304
9305/* Fold a call to __builtin_fpclassify(int, int, int, int, int, ...).
9306 This builtin will generate code to return the appropriate floating
9307 point classification depending on the value of the floating point
9308 number passed in. The possible return values must be supplied as
9309 int arguments to the call in the following order: FP_NAN, FP_INFINITE,
9310 FP_NORMAL, FP_SUBNORMAL and FP_ZERO. The ellipses is for exactly
9311 one floating point argument which is "type generic". */
9312
9313static tree
9314fold_builtin_fpclassify (location_t loc, tree *args, int nargs)
9315{
9316 tree fp_nan, fp_infinite, fp_normal, fp_subnormal, fp_zero,
9317 arg, type, res, tmp;
9318 machine_mode mode;
9319 REAL_VALUE_TYPE r;
9320 char buf[128];
9321
9322 /* Verify the required arguments in the original call. */
9323 if (nargs != 6
9324 || !validate_arg (args[0], code: INTEGER_TYPE)
9325 || !validate_arg (args[1], code: INTEGER_TYPE)
9326 || !validate_arg (args[2], code: INTEGER_TYPE)
9327 || !validate_arg (args[3], code: INTEGER_TYPE)
9328 || !validate_arg (args[4], code: INTEGER_TYPE)
9329 || !validate_arg (args[5], code: REAL_TYPE))
9330 return NULL_TREE;
9331
9332 fp_nan = args[0];
9333 fp_infinite = args[1];
9334 fp_normal = args[2];
9335 fp_subnormal = args[3];
9336 fp_zero = args[4];
9337 arg = args[5];
9338 type = TREE_TYPE (arg);
9339 mode = TYPE_MODE (type);
9340 arg = builtin_save_expr (exp: fold_build1_loc (loc, ABS_EXPR, type, arg));
9341
9342 /* fpclassify(x) ->
9343 isnan(x) ? FP_NAN :
9344 (fabs(x) == Inf ? FP_INFINITE :
9345 (fabs(x) >= DBL_MIN ? FP_NORMAL :
9346 (x == 0 ? FP_ZERO : FP_SUBNORMAL))). */
9347
9348 tmp = fold_build2_loc (loc, EQ_EXPR, integer_type_node, arg,
9349 build_real (type, dconst0));
9350 res = fold_build3_loc (loc, COND_EXPR, integer_type_node,
9351 tmp, fp_zero, fp_subnormal);
9352
9353 sprintf (s: buf, format: "0x1p%d", REAL_MODE_FORMAT (mode)->emin - 1);
9354 real_from_string (&r, buf);
9355 tmp = fold_build2_loc (loc, GE_EXPR, integer_type_node,
9356 arg, build_real (type, r));
9357 res = fold_build3_loc (loc, COND_EXPR, integer_type_node, tmp, fp_normal, res);
9358
9359 if (tree_expr_maybe_infinite_p (arg))
9360 {
9361 tmp = fold_build2_loc (loc, EQ_EXPR, integer_type_node, arg,
9362 build_real (type, dconstinf));
9363 res = fold_build3_loc (loc, COND_EXPR, integer_type_node, tmp,
9364 fp_infinite, res);
9365 }
9366
9367 if (tree_expr_maybe_nan_p (arg))
9368 {
9369 tmp = fold_build2_loc (loc, ORDERED_EXPR, integer_type_node, arg, arg);
9370 res = fold_build3_loc (loc, COND_EXPR, integer_type_node, tmp, res, fp_nan);
9371 }
9372
9373 return res;
9374}
9375
9376/* Fold a call to an unordered comparison function such as
9377 __builtin_isgreater(). FNDECL is the FUNCTION_DECL for the function
9378 being called and ARG0 and ARG1 are the arguments for the call.
9379 UNORDERED_CODE and ORDERED_CODE are comparison codes that give
9380 the opposite of the desired result. UNORDERED_CODE is used
9381 for modes that can hold NaNs and ORDERED_CODE is used for
9382 the rest. */
9383
9384static tree
9385fold_builtin_unordered_cmp (location_t loc, tree fndecl, tree arg0, tree arg1,
9386 enum tree_code unordered_code,
9387 enum tree_code ordered_code)
9388{
9389 tree type = TREE_TYPE (TREE_TYPE (fndecl));
9390 enum tree_code code;
9391 tree type0, type1;
9392 enum tree_code code0, code1;
9393 tree cmp_type = NULL_TREE;
9394
9395 type0 = TREE_TYPE (arg0);
9396 type1 = TREE_TYPE (arg1);
9397
9398 code0 = TREE_CODE (type0);
9399 code1 = TREE_CODE (type1);
9400
9401 if (code0 == REAL_TYPE && code1 == REAL_TYPE)
9402 /* Choose the wider of two real types. */
9403 cmp_type = TYPE_PRECISION (type0) >= TYPE_PRECISION (type1)
9404 ? type0 : type1;
9405 else if (code0 == REAL_TYPE
9406 && (code1 == INTEGER_TYPE || code1 == BITINT_TYPE))
9407 cmp_type = type0;
9408 else if ((code0 == INTEGER_TYPE || code0 == BITINT_TYPE)
9409 && code1 == REAL_TYPE)
9410 cmp_type = type1;
9411
9412 arg0 = fold_convert_loc (loc, cmp_type, arg0);
9413 arg1 = fold_convert_loc (loc, cmp_type, arg1);
9414
9415 if (unordered_code == UNORDERED_EXPR)
9416 {
9417 if (tree_expr_nan_p (arg0) || tree_expr_nan_p (arg1))
9418 return omit_two_operands_loc (loc, type, integer_one_node, arg0, arg1);
9419 if (!tree_expr_maybe_nan_p (arg0) && !tree_expr_maybe_nan_p (arg1))
9420 return omit_two_operands_loc (loc, type, integer_zero_node, arg0, arg1);
9421 return fold_build2_loc (loc, UNORDERED_EXPR, type, arg0, arg1);
9422 }
9423
9424 code = (tree_expr_maybe_nan_p (arg0) || tree_expr_maybe_nan_p (arg1))
9425 ? unordered_code : ordered_code;
9426 return fold_build1_loc (loc, TRUTH_NOT_EXPR, type,
9427 fold_build2_loc (loc, code, type, arg0, arg1));
9428}
9429
9430/* Fold a call to __builtin_iseqsig(). ARG0 and ARG1 are the arguments.
9431 After choosing the wider floating-point type for the comparison,
9432 the code is folded to:
9433 SAVE_EXPR<ARG0> >= SAVE_EXPR<ARG1> && SAVE_EXPR<ARG0> <= SAVE_EXPR<ARG1> */
9434
9435static tree
9436fold_builtin_iseqsig (location_t loc, tree arg0, tree arg1)
9437{
9438 tree type0, type1;
9439 enum tree_code code0, code1;
9440 tree cmp1, cmp2, cmp_type = NULL_TREE;
9441
9442 type0 = TREE_TYPE (arg0);
9443 type1 = TREE_TYPE (arg1);
9444
9445 code0 = TREE_CODE (type0);
9446 code1 = TREE_CODE (type1);
9447
9448 if (code0 == REAL_TYPE && code1 == REAL_TYPE)
9449 /* Choose the wider of two real types. */
9450 cmp_type = TYPE_PRECISION (type0) >= TYPE_PRECISION (type1)
9451 ? type0 : type1;
9452 else if (code0 == REAL_TYPE && code1 == INTEGER_TYPE)
9453 cmp_type = type0;
9454 else if (code0 == INTEGER_TYPE && code1 == REAL_TYPE)
9455 cmp_type = type1;
9456
9457 arg0 = builtin_save_expr (exp: fold_convert_loc (loc, cmp_type, arg0));
9458 arg1 = builtin_save_expr (exp: fold_convert_loc (loc, cmp_type, arg1));
9459
9460 cmp1 = fold_build2_loc (loc, GE_EXPR, integer_type_node, arg0, arg1);
9461 cmp2 = fold_build2_loc (loc, LE_EXPR, integer_type_node, arg0, arg1);
9462
9463 return fold_build2_loc (loc, TRUTH_AND_EXPR, integer_type_node, cmp1, cmp2);
9464}
9465
9466/* Fold __builtin_{,s,u}{add,sub,mul}{,l,ll}_overflow, either into normal
9467 arithmetics if it can never overflow, or into internal functions that
9468 return both result of arithmetics and overflowed boolean flag in
9469 a complex integer result, or some other check for overflow.
9470 Similarly fold __builtin_{add,sub,mul}_overflow_p to just the overflow
9471 checking part of that. */
9472
9473static tree
9474fold_builtin_arith_overflow (location_t loc, enum built_in_function fcode,
9475 tree arg0, tree arg1, tree arg2)
9476{
9477 enum internal_fn ifn = IFN_LAST;
9478 /* The code of the expression corresponding to the built-in. */
9479 enum tree_code opcode = ERROR_MARK;
9480 bool ovf_only = false;
9481
9482 switch (fcode)
9483 {
9484 case BUILT_IN_ADD_OVERFLOW_P:
9485 ovf_only = true;
9486 /* FALLTHRU */
9487 case BUILT_IN_ADD_OVERFLOW:
9488 case BUILT_IN_SADD_OVERFLOW:
9489 case BUILT_IN_SADDL_OVERFLOW:
9490 case BUILT_IN_SADDLL_OVERFLOW:
9491 case BUILT_IN_UADD_OVERFLOW:
9492 case BUILT_IN_UADDL_OVERFLOW:
9493 case BUILT_IN_UADDLL_OVERFLOW:
9494 opcode = PLUS_EXPR;
9495 ifn = IFN_ADD_OVERFLOW;
9496 break;
9497 case BUILT_IN_SUB_OVERFLOW_P:
9498 ovf_only = true;
9499 /* FALLTHRU */
9500 case BUILT_IN_SUB_OVERFLOW:
9501 case BUILT_IN_SSUB_OVERFLOW:
9502 case BUILT_IN_SSUBL_OVERFLOW:
9503 case BUILT_IN_SSUBLL_OVERFLOW:
9504 case BUILT_IN_USUB_OVERFLOW:
9505 case BUILT_IN_USUBL_OVERFLOW:
9506 case BUILT_IN_USUBLL_OVERFLOW:
9507 opcode = MINUS_EXPR;
9508 ifn = IFN_SUB_OVERFLOW;
9509 break;
9510 case BUILT_IN_MUL_OVERFLOW_P:
9511 ovf_only = true;
9512 /* FALLTHRU */
9513 case BUILT_IN_MUL_OVERFLOW:
9514 case BUILT_IN_SMUL_OVERFLOW:
9515 case BUILT_IN_SMULL_OVERFLOW:
9516 case BUILT_IN_SMULLL_OVERFLOW:
9517 case BUILT_IN_UMUL_OVERFLOW:
9518 case BUILT_IN_UMULL_OVERFLOW:
9519 case BUILT_IN_UMULLL_OVERFLOW:
9520 opcode = MULT_EXPR;
9521 ifn = IFN_MUL_OVERFLOW;
9522 break;
9523 default:
9524 gcc_unreachable ();
9525 }
9526
9527 /* For the "generic" overloads, the first two arguments can have different
9528 types and the last argument determines the target type to use to check
9529 for overflow. The arguments of the other overloads all have the same
9530 type. */
9531 tree type = ovf_only ? TREE_TYPE (arg2) : TREE_TYPE (TREE_TYPE (arg2));
9532
9533 /* For the __builtin_{add,sub,mul}_overflow_p builtins, when the first two
9534 arguments are constant, attempt to fold the built-in call into a constant
9535 expression indicating whether or not it detected an overflow. */
9536 if (ovf_only
9537 && TREE_CODE (arg0) == INTEGER_CST
9538 && TREE_CODE (arg1) == INTEGER_CST)
9539 /* Perform the computation in the target type and check for overflow. */
9540 return omit_one_operand_loc (loc, boolean_type_node,
9541 arith_overflowed_p (opcode, type, arg0, arg1)
9542 ? boolean_true_node : boolean_false_node,
9543 arg2);
9544
9545 tree intres, ovfres;
9546 if (TREE_CODE (arg0) == INTEGER_CST && TREE_CODE (arg1) == INTEGER_CST)
9547 {
9548 intres = fold_binary_loc (loc, opcode, type,
9549 fold_convert_loc (loc, type, arg0),
9550 fold_convert_loc (loc, type, arg1));
9551 if (TREE_OVERFLOW (intres))
9552 intres = drop_tree_overflow (intres);
9553 ovfres = (arith_overflowed_p (opcode, type, arg0, arg1)
9554 ? boolean_true_node : boolean_false_node);
9555 }
9556 else
9557 {
9558 tree ctype = build_complex_type (type);
9559 tree call = build_call_expr_internal_loc (loc, ifn, ctype, 2,
9560 arg0, arg1);
9561 tree tgt = save_expr (call);
9562 intres = build1_loc (loc, code: REALPART_EXPR, type, arg1: tgt);
9563 ovfres = build1_loc (loc, code: IMAGPART_EXPR, type, arg1: tgt);
9564 ovfres = fold_convert_loc (loc, boolean_type_node, ovfres);
9565 }
9566
9567 if (ovf_only)
9568 return omit_one_operand_loc (loc, boolean_type_node, ovfres, arg2);
9569
9570 tree mem_arg2 = build_fold_indirect_ref_loc (loc, arg2);
9571 tree store
9572 = fold_build2_loc (loc, MODIFY_EXPR, void_type_node, mem_arg2, intres);
9573 return build2_loc (loc, code: COMPOUND_EXPR, boolean_type_node, arg0: store, arg1: ovfres);
9574}
9575
9576/* Fold __builtin_{add,sub}c{,l,ll} into pair of internal functions
9577 that return both result of arithmetics and overflowed boolean
9578 flag in a complex integer result. */
9579
9580static tree
9581fold_builtin_addc_subc (location_t loc, enum built_in_function fcode,
9582 tree *args)
9583{
9584 enum internal_fn ifn;
9585
9586 switch (fcode)
9587 {
9588 case BUILT_IN_ADDC:
9589 case BUILT_IN_ADDCL:
9590 case BUILT_IN_ADDCLL:
9591 ifn = IFN_ADD_OVERFLOW;
9592 break;
9593 case BUILT_IN_SUBC:
9594 case BUILT_IN_SUBCL:
9595 case BUILT_IN_SUBCLL:
9596 ifn = IFN_SUB_OVERFLOW;
9597 break;
9598 default:
9599 gcc_unreachable ();
9600 }
9601
9602 tree type = TREE_TYPE (args[0]);
9603 tree ctype = build_complex_type (type);
9604 tree call = build_call_expr_internal_loc (loc, ifn, ctype, 2,
9605 args[0], args[1]);
9606 tree tgt = save_expr (call);
9607 tree intres = build1_loc (loc, code: REALPART_EXPR, type, arg1: tgt);
9608 tree ovfres = build1_loc (loc, code: IMAGPART_EXPR, type, arg1: tgt);
9609 call = build_call_expr_internal_loc (loc, ifn, ctype, 2,
9610 intres, args[2]);
9611 tgt = save_expr (call);
9612 intres = build1_loc (loc, code: REALPART_EXPR, type, arg1: tgt);
9613 tree ovfres2 = build1_loc (loc, code: IMAGPART_EXPR, type, arg1: tgt);
9614 ovfres = build2_loc (loc, code: BIT_IOR_EXPR, type, arg0: ovfres, arg1: ovfres2);
9615 tree mem_arg3 = build_fold_indirect_ref_loc (loc, args[3]);
9616 tree store
9617 = fold_build2_loc (loc, MODIFY_EXPR, void_type_node, mem_arg3, ovfres);
9618 return build2_loc (loc, code: COMPOUND_EXPR, type, arg0: store, arg1: intres);
9619}
9620
9621/* Fold a call to __builtin_FILE to a constant string. */
9622
9623static inline tree
9624fold_builtin_FILE (location_t loc)
9625{
9626 if (const char *fname = LOCATION_FILE (loc))
9627 {
9628 /* The documentation says this builtin is equivalent to the preprocessor
9629 __FILE__ macro so it appears appropriate to use the same file prefix
9630 mappings. */
9631 fname = remap_macro_filename (fname);
9632 return build_string_literal (p: fname);
9633 }
9634
9635 return build_string_literal (p: "");
9636}
9637
9638/* Fold a call to __builtin_FUNCTION to a constant string. */
9639
9640static inline tree
9641fold_builtin_FUNCTION ()
9642{
9643 const char *name = "";
9644
9645 if (current_function_decl)
9646 name = lang_hooks.decl_printable_name (current_function_decl, 0);
9647
9648 return build_string_literal (p: name);
9649}
9650
9651/* Fold a call to __builtin_LINE to an integer constant. */
9652
9653static inline tree
9654fold_builtin_LINE (location_t loc, tree type)
9655{
9656 return build_int_cst (type, LOCATION_LINE (loc));
9657}
9658
9659/* Fold a call to built-in function FNDECL with 0 arguments.
9660 This function returns NULL_TREE if no simplification was possible. */
9661
9662static tree
9663fold_builtin_0 (location_t loc, tree fndecl)
9664{
9665 tree type = TREE_TYPE (TREE_TYPE (fndecl));
9666 enum built_in_function fcode = DECL_FUNCTION_CODE (decl: fndecl);
9667 switch (fcode)
9668 {
9669 case BUILT_IN_FILE:
9670 return fold_builtin_FILE (loc);
9671
9672 case BUILT_IN_FUNCTION:
9673 return fold_builtin_FUNCTION ();
9674
9675 case BUILT_IN_LINE:
9676 return fold_builtin_LINE (loc, type);
9677
9678 CASE_FLT_FN (BUILT_IN_INF):
9679 CASE_FLT_FN_FLOATN_NX (BUILT_IN_INF):
9680 case BUILT_IN_INFD32:
9681 case BUILT_IN_INFD64:
9682 case BUILT_IN_INFD128:
9683 return fold_builtin_inf (loc, type, warn: true);
9684
9685 CASE_FLT_FN (BUILT_IN_HUGE_VAL):
9686 CASE_FLT_FN_FLOATN_NX (BUILT_IN_HUGE_VAL):
9687 return fold_builtin_inf (loc, type, warn: false);
9688
9689 case BUILT_IN_CLASSIFY_TYPE:
9690 return fold_builtin_classify_type (NULL_TREE);
9691
9692 case BUILT_IN_UNREACHABLE:
9693 /* Rewrite any explicit calls to __builtin_unreachable. */
9694 if (sanitize_flags_p (flag: SANITIZE_UNREACHABLE))
9695 return build_builtin_unreachable (loc);
9696 break;
9697
9698 default:
9699 break;
9700 }
9701 return NULL_TREE;
9702}
9703
9704/* Fold a call to built-in function FNDECL with 1 argument, ARG0.
9705 This function returns NULL_TREE if no simplification was possible. */
9706
9707static tree
9708fold_builtin_1 (location_t loc, tree expr, tree fndecl, tree arg0)
9709{
9710 tree type = TREE_TYPE (TREE_TYPE (fndecl));
9711 enum built_in_function fcode = DECL_FUNCTION_CODE (decl: fndecl);
9712
9713 if (TREE_CODE (arg0) == ERROR_MARK)
9714 return NULL_TREE;
9715
9716 if (tree ret = fold_const_call (as_combined_fn (fn: fcode), type, arg0))
9717 return ret;
9718
9719 switch (fcode)
9720 {
9721 case BUILT_IN_CONSTANT_P:
9722 {
9723 tree val = fold_builtin_constant_p (arg: arg0);
9724
9725 /* Gimplification will pull the CALL_EXPR for the builtin out of
9726 an if condition. When not optimizing, we'll not CSE it back.
9727 To avoid link error types of regressions, return false now. */
9728 if (!val && !optimize)
9729 val = integer_zero_node;
9730
9731 return val;
9732 }
9733
9734 case BUILT_IN_CLASSIFY_TYPE:
9735 return fold_builtin_classify_type (arg: arg0);
9736
9737 case BUILT_IN_STRLEN:
9738 return fold_builtin_strlen (loc, expr, type, arg: arg0);
9739
9740 CASE_FLT_FN (BUILT_IN_FABS):
9741 CASE_FLT_FN_FLOATN_NX (BUILT_IN_FABS):
9742 case BUILT_IN_FABSD32:
9743 case BUILT_IN_FABSD64:
9744 case BUILT_IN_FABSD128:
9745 return fold_builtin_fabs (loc, arg: arg0, type);
9746
9747 case BUILT_IN_ABS:
9748 case BUILT_IN_LABS:
9749 case BUILT_IN_LLABS:
9750 case BUILT_IN_IMAXABS:
9751 return fold_builtin_abs (loc, arg: arg0, type);
9752
9753 CASE_FLT_FN (BUILT_IN_CONJ):
9754 if (validate_arg (arg0, code: COMPLEX_TYPE)
9755 && TREE_CODE (TREE_TYPE (TREE_TYPE (arg0))) == REAL_TYPE)
9756 return fold_build1_loc (loc, CONJ_EXPR, type, arg0);
9757 break;
9758
9759 CASE_FLT_FN (BUILT_IN_CREAL):
9760 if (validate_arg (arg0, code: COMPLEX_TYPE)
9761 && TREE_CODE (TREE_TYPE (TREE_TYPE (arg0))) == REAL_TYPE)
9762 return non_lvalue_loc (loc, fold_build1_loc (loc, REALPART_EXPR, type, arg0));
9763 break;
9764
9765 CASE_FLT_FN (BUILT_IN_CIMAG):
9766 if (validate_arg (arg0, code: COMPLEX_TYPE)
9767 && TREE_CODE (TREE_TYPE (TREE_TYPE (arg0))) == REAL_TYPE)
9768 return non_lvalue_loc (loc, fold_build1_loc (loc, IMAGPART_EXPR, type, arg0));
9769 break;
9770
9771 CASE_FLT_FN (BUILT_IN_CARG):
9772 CASE_FLT_FN_FLOATN_NX (BUILT_IN_CARG):
9773 return fold_builtin_carg (loc, arg: arg0, type);
9774
9775 case BUILT_IN_ISASCII:
9776 return fold_builtin_isascii (loc, arg: arg0);
9777
9778 case BUILT_IN_TOASCII:
9779 return fold_builtin_toascii (loc, arg: arg0);
9780
9781 case BUILT_IN_ISDIGIT:
9782 return fold_builtin_isdigit (loc, arg: arg0);
9783
9784 CASE_FLT_FN (BUILT_IN_FINITE):
9785 case BUILT_IN_FINITED32:
9786 case BUILT_IN_FINITED64:
9787 case BUILT_IN_FINITED128:
9788 case BUILT_IN_ISFINITE:
9789 {
9790 tree ret = fold_builtin_classify (loc, fndecl, arg: arg0, builtin_index: BUILT_IN_ISFINITE);
9791 if (ret)
9792 return ret;
9793 return fold_builtin_interclass_mathfn (loc, fndecl, arg: arg0);
9794 }
9795
9796 CASE_FLT_FN (BUILT_IN_ISINF):
9797 case BUILT_IN_ISINFD32:
9798 case BUILT_IN_ISINFD64:
9799 case BUILT_IN_ISINFD128:
9800 {
9801 tree ret = fold_builtin_classify (loc, fndecl, arg: arg0, builtin_index: BUILT_IN_ISINF);
9802 if (ret)
9803 return ret;
9804 return fold_builtin_interclass_mathfn (loc, fndecl, arg: arg0);
9805 }
9806
9807 case BUILT_IN_ISNORMAL:
9808 return fold_builtin_interclass_mathfn (loc, fndecl, arg: arg0);
9809
9810 case BUILT_IN_ISINF_SIGN:
9811 return fold_builtin_classify (loc, fndecl, arg: arg0, builtin_index: BUILT_IN_ISINF_SIGN);
9812
9813 CASE_FLT_FN (BUILT_IN_ISNAN):
9814 case BUILT_IN_ISNAND32:
9815 case BUILT_IN_ISNAND64:
9816 case BUILT_IN_ISNAND128:
9817 return fold_builtin_classify (loc, fndecl, arg: arg0, builtin_index: BUILT_IN_ISNAN);
9818
9819 case BUILT_IN_ISSIGNALING:
9820 return fold_builtin_classify (loc, fndecl, arg: arg0, builtin_index: BUILT_IN_ISSIGNALING);
9821
9822 case BUILT_IN_FREE:
9823 if (integer_zerop (arg0))
9824 return build_empty_stmt (loc);
9825 break;
9826
9827 default:
9828 break;
9829 }
9830
9831 return NULL_TREE;
9832
9833}
9834
9835/* Folds a call EXPR (which may be null) to built-in function FNDECL
9836 with 2 arguments, ARG0 and ARG1. This function returns NULL_TREE
9837 if no simplification was possible. */
9838
9839static tree
9840fold_builtin_2 (location_t loc, tree expr, tree fndecl, tree arg0, tree arg1)
9841{
9842 tree type = TREE_TYPE (TREE_TYPE (fndecl));
9843 enum built_in_function fcode = DECL_FUNCTION_CODE (decl: fndecl);
9844
9845 if (TREE_CODE (arg0) == ERROR_MARK
9846 || TREE_CODE (arg1) == ERROR_MARK)
9847 return NULL_TREE;
9848
9849 if (tree ret = fold_const_call (as_combined_fn (fn: fcode), type, arg0, arg1))
9850 return ret;
9851
9852 switch (fcode)
9853 {
9854 CASE_FLT_FN_REENT (BUILT_IN_GAMMA): /* GAMMA_R */
9855 CASE_FLT_FN_REENT (BUILT_IN_LGAMMA): /* LGAMMA_R */
9856 if (validate_arg (arg0, code: REAL_TYPE)
9857 && validate_arg (arg1, code: POINTER_TYPE))
9858 return do_mpfr_lgamma_r (arg0, arg1, type);
9859 break;
9860
9861 CASE_FLT_FN (BUILT_IN_FREXP):
9862 return fold_builtin_frexp (loc, arg0, arg1, rettype: type);
9863
9864 CASE_FLT_FN (BUILT_IN_MODF):
9865 return fold_builtin_modf (loc, arg0, arg1, rettype: type);
9866
9867 case BUILT_IN_STRSPN:
9868 return fold_builtin_strspn (loc, expr, arg0, arg1);
9869
9870 case BUILT_IN_STRCSPN:
9871 return fold_builtin_strcspn (loc, expr, arg0, arg1);
9872
9873 case BUILT_IN_STRPBRK:
9874 return fold_builtin_strpbrk (loc, expr, arg0, arg1, type);
9875
9876 case BUILT_IN_EXPECT:
9877 return fold_builtin_expect (loc, arg0, arg1, NULL_TREE, NULL_TREE);
9878
9879 case BUILT_IN_ISGREATER:
9880 return fold_builtin_unordered_cmp (loc, fndecl,
9881 arg0, arg1, unordered_code: UNLE_EXPR, ordered_code: LE_EXPR);
9882 case BUILT_IN_ISGREATEREQUAL:
9883 return fold_builtin_unordered_cmp (loc, fndecl,
9884 arg0, arg1, unordered_code: UNLT_EXPR, ordered_code: LT_EXPR);
9885 case BUILT_IN_ISLESS:
9886 return fold_builtin_unordered_cmp (loc, fndecl,
9887 arg0, arg1, unordered_code: UNGE_EXPR, ordered_code: GE_EXPR);
9888 case BUILT_IN_ISLESSEQUAL:
9889 return fold_builtin_unordered_cmp (loc, fndecl,
9890 arg0, arg1, unordered_code: UNGT_EXPR, ordered_code: GT_EXPR);
9891 case BUILT_IN_ISLESSGREATER:
9892 return fold_builtin_unordered_cmp (loc, fndecl,
9893 arg0, arg1, unordered_code: UNEQ_EXPR, ordered_code: EQ_EXPR);
9894 case BUILT_IN_ISUNORDERED:
9895 return fold_builtin_unordered_cmp (loc, fndecl,
9896 arg0, arg1, unordered_code: UNORDERED_EXPR,
9897 ordered_code: NOP_EXPR);
9898
9899 case BUILT_IN_ISEQSIG:
9900 return fold_builtin_iseqsig (loc, arg0, arg1);
9901
9902 /* We do the folding for va_start in the expander. */
9903 case BUILT_IN_VA_START:
9904 break;
9905
9906 case BUILT_IN_OBJECT_SIZE:
9907 case BUILT_IN_DYNAMIC_OBJECT_SIZE:
9908 return fold_builtin_object_size (arg0, arg1, fcode);
9909
9910 case BUILT_IN_ATOMIC_ALWAYS_LOCK_FREE:
9911 return fold_builtin_atomic_always_lock_free (arg0, arg1);
9912
9913 case BUILT_IN_ATOMIC_IS_LOCK_FREE:
9914 return fold_builtin_atomic_is_lock_free (arg0, arg1);
9915
9916 default:
9917 break;
9918 }
9919 return NULL_TREE;
9920}
9921
9922/* Fold a call to built-in function FNDECL with 3 arguments, ARG0, ARG1,
9923 and ARG2.
9924 This function returns NULL_TREE if no simplification was possible. */
9925
9926static tree
9927fold_builtin_3 (location_t loc, tree fndecl,
9928 tree arg0, tree arg1, tree arg2)
9929{
9930 tree type = TREE_TYPE (TREE_TYPE (fndecl));
9931 enum built_in_function fcode = DECL_FUNCTION_CODE (decl: fndecl);
9932
9933 if (TREE_CODE (arg0) == ERROR_MARK
9934 || TREE_CODE (arg1) == ERROR_MARK
9935 || TREE_CODE (arg2) == ERROR_MARK)
9936 return NULL_TREE;
9937
9938 if (tree ret = fold_const_call (as_combined_fn (fn: fcode), type,
9939 arg0, arg1, arg2))
9940 return ret;
9941
9942 switch (fcode)
9943 {
9944
9945 CASE_FLT_FN (BUILT_IN_SINCOS):
9946 return fold_builtin_sincos (loc, arg0, arg1, arg2);
9947
9948 CASE_FLT_FN (BUILT_IN_REMQUO):
9949 if (validate_arg (arg0, code: REAL_TYPE)
9950 && validate_arg (arg1, code: REAL_TYPE)
9951 && validate_arg (arg2, code: POINTER_TYPE))
9952 return do_mpfr_remquo (arg0, arg1, arg2);
9953 break;
9954
9955 case BUILT_IN_MEMCMP:
9956 return fold_builtin_memcmp (loc, arg1: arg0, arg2: arg1, len: arg2);
9957
9958 case BUILT_IN_EXPECT:
9959 return fold_builtin_expect (loc, arg0, arg1, arg2, NULL_TREE);
9960
9961 case BUILT_IN_EXPECT_WITH_PROBABILITY:
9962 return fold_builtin_expect (loc, arg0, arg1, NULL_TREE, arg3: arg2);
9963
9964 case BUILT_IN_ADD_OVERFLOW:
9965 case BUILT_IN_SUB_OVERFLOW:
9966 case BUILT_IN_MUL_OVERFLOW:
9967 case BUILT_IN_ADD_OVERFLOW_P:
9968 case BUILT_IN_SUB_OVERFLOW_P:
9969 case BUILT_IN_MUL_OVERFLOW_P:
9970 case BUILT_IN_SADD_OVERFLOW:
9971 case BUILT_IN_SADDL_OVERFLOW:
9972 case BUILT_IN_SADDLL_OVERFLOW:
9973 case BUILT_IN_SSUB_OVERFLOW:
9974 case BUILT_IN_SSUBL_OVERFLOW:
9975 case BUILT_IN_SSUBLL_OVERFLOW:
9976 case BUILT_IN_SMUL_OVERFLOW:
9977 case BUILT_IN_SMULL_OVERFLOW:
9978 case BUILT_IN_SMULLL_OVERFLOW:
9979 case BUILT_IN_UADD_OVERFLOW:
9980 case BUILT_IN_UADDL_OVERFLOW:
9981 case BUILT_IN_UADDLL_OVERFLOW:
9982 case BUILT_IN_USUB_OVERFLOW:
9983 case BUILT_IN_USUBL_OVERFLOW:
9984 case BUILT_IN_USUBLL_OVERFLOW:
9985 case BUILT_IN_UMUL_OVERFLOW:
9986 case BUILT_IN_UMULL_OVERFLOW:
9987 case BUILT_IN_UMULLL_OVERFLOW:
9988 return fold_builtin_arith_overflow (loc, fcode, arg0, arg1, arg2);
9989
9990 default:
9991 break;
9992 }
9993 return NULL_TREE;
9994}
9995
9996/* Folds a call EXPR (which may be null) to built-in function FNDECL.
9997 ARGS is an array of NARGS arguments. IGNORE is true if the result
9998 of the function call is ignored. This function returns NULL_TREE
9999 if no simplification was possible. */
10000
10001static tree
10002fold_builtin_n (location_t loc, tree expr, tree fndecl, tree *args,
10003 int nargs, bool)
10004{
10005 tree ret = NULL_TREE;
10006
10007 switch (nargs)
10008 {
10009 case 0:
10010 ret = fold_builtin_0 (loc, fndecl);
10011 break;
10012 case 1:
10013 ret = fold_builtin_1 (loc, expr, fndecl, arg0: args[0]);
10014 break;
10015 case 2:
10016 ret = fold_builtin_2 (loc, expr, fndecl, arg0: args[0], arg1: args[1]);
10017 break;
10018 case 3:
10019 ret = fold_builtin_3 (loc, fndecl, arg0: args[0], arg1: args[1], arg2: args[2]);
10020 break;
10021 default:
10022 ret = fold_builtin_varargs (loc, fndecl, args, nargs);
10023 break;
10024 }
10025 if (ret)
10026 {
10027 ret = build1 (NOP_EXPR, TREE_TYPE (ret), ret);
10028 SET_EXPR_LOCATION (ret, loc);
10029 return ret;
10030 }
10031 return NULL_TREE;
10032}
10033
10034/* Construct a new CALL_EXPR to FNDECL using the tail of the argument
10035 list ARGS along with N new arguments in NEWARGS. SKIP is the number
10036 of arguments in ARGS to be omitted. OLDNARGS is the number of
10037 elements in ARGS. */
10038
10039static tree
10040rewrite_call_expr_valist (location_t loc, int oldnargs, tree *args,
10041 int skip, tree fndecl, int n, va_list newargs)
10042{
10043 int nargs = oldnargs - skip + n;
10044 tree *buffer;
10045
10046 if (n > 0)
10047 {
10048 int i, j;
10049
10050 buffer = XALLOCAVEC (tree, nargs);
10051 for (i = 0; i < n; i++)
10052 buffer[i] = va_arg (newargs, tree);
10053 for (j = skip; j < oldnargs; j++, i++)
10054 buffer[i] = args[j];
10055 }
10056 else
10057 buffer = args + skip;
10058
10059 return build_call_expr_loc_array (loc, fndecl, nargs, buffer);
10060}
10061
10062/* Return true if FNDECL shouldn't be folded right now.
10063 If a built-in function has an inline attribute always_inline
10064 wrapper, defer folding it after always_inline functions have
10065 been inlined, otherwise e.g. -D_FORTIFY_SOURCE checking
10066 might not be performed. */
10067
10068bool
10069avoid_folding_inline_builtin (tree fndecl)
10070{
10071 return (DECL_DECLARED_INLINE_P (fndecl)
10072 && DECL_DISREGARD_INLINE_LIMITS (fndecl)
10073 && cfun
10074 && !cfun->always_inline_functions_inlined
10075 && lookup_attribute (attr_name: "always_inline", DECL_ATTRIBUTES (fndecl)));
10076}
10077
10078/* A wrapper function for builtin folding that prevents warnings for
10079 "statement without effect" and the like, caused by removing the
10080 call node earlier than the warning is generated. */
10081
10082tree
10083fold_call_expr (location_t loc, tree exp, bool ignore)
10084{
10085 tree ret = NULL_TREE;
10086 tree fndecl = get_callee_fndecl (exp);
10087 if (fndecl && fndecl_built_in_p (node: fndecl)
10088 /* If CALL_EXPR_VA_ARG_PACK is set, the arguments aren't finalized
10089 yet. Defer folding until we see all the arguments
10090 (after inlining). */
10091 && !CALL_EXPR_VA_ARG_PACK (exp))
10092 {
10093 int nargs = call_expr_nargs (exp);
10094
10095 /* Before gimplification CALL_EXPR_VA_ARG_PACK is not set, but
10096 instead last argument is __builtin_va_arg_pack (). Defer folding
10097 even in that case, until arguments are finalized. */
10098 if (nargs && TREE_CODE (CALL_EXPR_ARG (exp, nargs - 1)) == CALL_EXPR)
10099 {
10100 tree fndecl2 = get_callee_fndecl (CALL_EXPR_ARG (exp, nargs - 1));
10101 if (fndecl2 && fndecl_built_in_p (node: fndecl2, name1: BUILT_IN_VA_ARG_PACK))
10102 return NULL_TREE;
10103 }
10104
10105 if (avoid_folding_inline_builtin (fndecl))
10106 return NULL_TREE;
10107
10108 if (DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_MD)
10109 return targetm.fold_builtin (fndecl, call_expr_nargs (exp),
10110 CALL_EXPR_ARGP (exp), ignore);
10111 else
10112 {
10113 tree *args = CALL_EXPR_ARGP (exp);
10114 ret = fold_builtin_n (loc, expr: exp, fndecl, args, nargs, ignore);
10115 if (ret)
10116 return ret;
10117 }
10118 }
10119 return NULL_TREE;
10120}
10121
10122/* Fold a CALL_EXPR with type TYPE with FN as the function expression.
10123 N arguments are passed in the array ARGARRAY. Return a folded
10124 expression or NULL_TREE if no simplification was possible. */
10125
10126tree
10127fold_builtin_call_array (location_t loc, tree,
10128 tree fn,
10129 int n,
10130 tree *argarray)
10131{
10132 if (TREE_CODE (fn) != ADDR_EXPR)
10133 return NULL_TREE;
10134
10135 tree fndecl = TREE_OPERAND (fn, 0);
10136 if (TREE_CODE (fndecl) == FUNCTION_DECL
10137 && fndecl_built_in_p (node: fndecl))
10138 {
10139 /* If last argument is __builtin_va_arg_pack (), arguments to this
10140 function are not finalized yet. Defer folding until they are. */
10141 if (n && TREE_CODE (argarray[n - 1]) == CALL_EXPR)
10142 {
10143 tree fndecl2 = get_callee_fndecl (argarray[n - 1]);
10144 if (fndecl2 && fndecl_built_in_p (node: fndecl2, name1: BUILT_IN_VA_ARG_PACK))
10145 return NULL_TREE;
10146 }
10147 if (avoid_folding_inline_builtin (fndecl))
10148 return NULL_TREE;
10149 if (DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_MD)
10150 return targetm.fold_builtin (fndecl, n, argarray, false);
10151 else
10152 return fold_builtin_n (loc, NULL_TREE, fndecl, args: argarray, nargs: n, false);
10153 }
10154
10155 return NULL_TREE;
10156}
10157
10158/* Construct a new CALL_EXPR using the tail of the argument list of EXP
10159 along with N new arguments specified as the "..." parameters. SKIP
10160 is the number of arguments in EXP to be omitted. This function is used
10161 to do varargs-to-varargs transformations. */
10162
10163static tree
10164rewrite_call_expr (location_t loc, tree exp, int skip, tree fndecl, int n, ...)
10165{
10166 va_list ap;
10167 tree t;
10168
10169 va_start (ap, n);
10170 t = rewrite_call_expr_valist (loc, call_expr_nargs (exp),
10171 CALL_EXPR_ARGP (exp), skip, fndecl, n, newargs: ap);
10172 va_end (ap);
10173
10174 return t;
10175}
10176
10177/* Validate a single argument ARG against a tree code CODE representing
10178 a type. Return true when argument is valid. */
10179
10180static bool
10181validate_arg (const_tree arg, enum tree_code code)
10182{
10183 if (!arg)
10184 return false;
10185 else if (code == POINTER_TYPE)
10186 return POINTER_TYPE_P (TREE_TYPE (arg));
10187 else if (code == INTEGER_TYPE)
10188 return INTEGRAL_TYPE_P (TREE_TYPE (arg));
10189 return code == TREE_CODE (TREE_TYPE (arg));
10190}
10191
10192/* This function validates the types of a function call argument list
10193 against a specified list of tree_codes. If the last specifier is a 0,
10194 that represents an ellipses, otherwise the last specifier must be a
10195 VOID_TYPE.
10196
10197 This is the GIMPLE version of validate_arglist. Eventually we want to
10198 completely convert builtins.cc to work from GIMPLEs and the tree based
10199 validate_arglist will then be removed. */
10200
10201bool
10202validate_gimple_arglist (const gcall *call, ...)
10203{
10204 enum tree_code code;
10205 bool res = 0;
10206 va_list ap;
10207 const_tree arg;
10208 size_t i;
10209
10210 va_start (ap, call);
10211 i = 0;
10212
10213 do
10214 {
10215 code = (enum tree_code) va_arg (ap, int);
10216 switch (code)
10217 {
10218 case 0:
10219 /* This signifies an ellipses, any further arguments are all ok. */
10220 res = true;
10221 goto end;
10222 case VOID_TYPE:
10223 /* This signifies an endlink, if no arguments remain, return
10224 true, otherwise return false. */
10225 res = (i == gimple_call_num_args (gs: call));
10226 goto end;
10227 default:
10228 /* If no parameters remain or the parameter's code does not
10229 match the specified code, return false. Otherwise continue
10230 checking any remaining arguments. */
10231 arg = gimple_call_arg (gs: call, index: i++);
10232 if (!validate_arg (arg, code))
10233 goto end;
10234 break;
10235 }
10236 }
10237 while (1);
10238
10239 /* We need gotos here since we can only have one VA_CLOSE in a
10240 function. */
10241 end: ;
10242 va_end (ap);
10243
10244 return res;
10245}
10246
10247/* Default target-specific builtin expander that does nothing. */
10248
10249rtx
10250default_expand_builtin (tree exp ATTRIBUTE_UNUSED,
10251 rtx target ATTRIBUTE_UNUSED,
10252 rtx subtarget ATTRIBUTE_UNUSED,
10253 machine_mode mode ATTRIBUTE_UNUSED,
10254 int ignore ATTRIBUTE_UNUSED)
10255{
10256 return NULL_RTX;
10257}
10258
10259/* Returns true is EXP represents data that would potentially reside
10260 in a readonly section. */
10261
10262bool
10263readonly_data_expr (tree exp)
10264{
10265 STRIP_NOPS (exp);
10266
10267 if (TREE_CODE (exp) != ADDR_EXPR)
10268 return false;
10269
10270 exp = get_base_address (TREE_OPERAND (exp, 0));
10271 if (!exp)
10272 return false;
10273
10274 /* Make sure we call decl_readonly_section only for trees it
10275 can handle (since it returns true for everything it doesn't
10276 understand). */
10277 if (TREE_CODE (exp) == STRING_CST
10278 || TREE_CODE (exp) == CONSTRUCTOR
10279 || (VAR_P (exp) && TREE_STATIC (exp)))
10280 return decl_readonly_section (exp, 0);
10281 else
10282 return false;
10283}
10284
10285/* Simplify a call to the strpbrk builtin. S1 and S2 are the arguments
10286 to the call, and TYPE is its return type.
10287
10288 Return NULL_TREE if no simplification was possible, otherwise return the
10289 simplified form of the call as a tree.
10290
10291 The simplified form may be a constant or other expression which
10292 computes the same value, but in a more efficient manner (including
10293 calls to other builtin functions).
10294
10295 The call may contain arguments which need to be evaluated, but
10296 which are not useful to determine the result of the call. In
10297 this case we return a chain of COMPOUND_EXPRs. The LHS of each
10298 COMPOUND_EXPR will be an argument which must be evaluated.
10299 COMPOUND_EXPRs are chained through their RHS. The RHS of the last
10300 COMPOUND_EXPR in the chain will contain the tree for the simplified
10301 form of the builtin function call. */
10302
10303static tree
10304fold_builtin_strpbrk (location_t loc, tree, tree s1, tree s2, tree type)
10305{
10306 if (!validate_arg (arg: s1, code: POINTER_TYPE)
10307 || !validate_arg (arg: s2, code: POINTER_TYPE))
10308 return NULL_TREE;
10309
10310 tree fn;
10311 const char *p1, *p2;
10312
10313 p2 = c_getstr (s2);
10314 if (p2 == NULL)
10315 return NULL_TREE;
10316
10317 p1 = c_getstr (s1);
10318 if (p1 != NULL)
10319 {
10320 const char *r = strpbrk (s: p1, accept: p2);
10321 tree tem;
10322
10323 if (r == NULL)
10324 return build_int_cst (TREE_TYPE (s1), 0);
10325
10326 /* Return an offset into the constant string argument. */
10327 tem = fold_build_pointer_plus_hwi_loc (loc, ptr: s1, off: r - p1);
10328 return fold_convert_loc (loc, type, tem);
10329 }
10330
10331 if (p2[0] == '\0')
10332 /* strpbrk(x, "") == NULL.
10333 Evaluate and ignore s1 in case it had side-effects. */
10334 return omit_one_operand_loc (loc, type, integer_zero_node, s1);
10335
10336 if (p2[1] != '\0')
10337 return NULL_TREE; /* Really call strpbrk. */
10338
10339 fn = builtin_decl_implicit (fncode: BUILT_IN_STRCHR);
10340 if (!fn)
10341 return NULL_TREE;
10342
10343 /* New argument list transforming strpbrk(s1, s2) to
10344 strchr(s1, s2[0]). */
10345 return build_call_expr_loc (loc, fn, 2, s1,
10346 build_int_cst (integer_type_node, p2[0]));
10347}
10348
10349/* Simplify a call to the strspn builtin. S1 and S2 are the arguments
10350 to the call.
10351
10352 Return NULL_TREE if no simplification was possible, otherwise return the
10353 simplified form of the call as a tree.
10354
10355 The simplified form may be a constant or other expression which
10356 computes the same value, but in a more efficient manner (including
10357 calls to other builtin functions).
10358
10359 The call may contain arguments which need to be evaluated, but
10360 which are not useful to determine the result of the call. In
10361 this case we return a chain of COMPOUND_EXPRs. The LHS of each
10362 COMPOUND_EXPR will be an argument which must be evaluated.
10363 COMPOUND_EXPRs are chained through their RHS. The RHS of the last
10364 COMPOUND_EXPR in the chain will contain the tree for the simplified
10365 form of the builtin function call. */
10366
10367static tree
10368fold_builtin_strspn (location_t loc, tree expr, tree s1, tree s2)
10369{
10370 if (!validate_arg (arg: s1, code: POINTER_TYPE)
10371 || !validate_arg (arg: s2, code: POINTER_TYPE))
10372 return NULL_TREE;
10373
10374 if (!check_nul_terminated_array (expr, s1)
10375 || !check_nul_terminated_array (expr, s2))
10376 return NULL_TREE;
10377
10378 const char *p1 = c_getstr (s1), *p2 = c_getstr (s2);
10379
10380 /* If either argument is "", return NULL_TREE. */
10381 if ((p1 && *p1 == '\0') || (p2 && *p2 == '\0'))
10382 /* Evaluate and ignore both arguments in case either one has
10383 side-effects. */
10384 return omit_two_operands_loc (loc, size_type_node, size_zero_node,
10385 s1, s2);
10386 return NULL_TREE;
10387}
10388
10389/* Simplify a call to the strcspn builtin. S1 and S2 are the arguments
10390 to the call.
10391
10392 Return NULL_TREE if no simplification was possible, otherwise return the
10393 simplified form of the call as a tree.
10394
10395 The simplified form may be a constant or other expression which
10396 computes the same value, but in a more efficient manner (including
10397 calls to other builtin functions).
10398
10399 The call may contain arguments which need to be evaluated, but
10400 which are not useful to determine the result of the call. In
10401 this case we return a chain of COMPOUND_EXPRs. The LHS of each
10402 COMPOUND_EXPR will be an argument which must be evaluated.
10403 COMPOUND_EXPRs are chained through their RHS. The RHS of the last
10404 COMPOUND_EXPR in the chain will contain the tree for the simplified
10405 form of the builtin function call. */
10406
10407static tree
10408fold_builtin_strcspn (location_t loc, tree expr, tree s1, tree s2)
10409{
10410 if (!validate_arg (arg: s1, code: POINTER_TYPE)
10411 || !validate_arg (arg: s2, code: POINTER_TYPE))
10412 return NULL_TREE;
10413
10414 if (!check_nul_terminated_array (expr, s1)
10415 || !check_nul_terminated_array (expr, s2))
10416 return NULL_TREE;
10417
10418 /* If the first argument is "", return NULL_TREE. */
10419 const char *p1 = c_getstr (s1);
10420 if (p1 && *p1 == '\0')
10421 {
10422 /* Evaluate and ignore argument s2 in case it has
10423 side-effects. */
10424 return omit_one_operand_loc (loc, size_type_node,
10425 size_zero_node, s2);
10426 }
10427
10428 /* If the second argument is "", return __builtin_strlen(s1). */
10429 const char *p2 = c_getstr (s2);
10430 if (p2 && *p2 == '\0')
10431 {
10432 tree fn = builtin_decl_implicit (fncode: BUILT_IN_STRLEN);
10433
10434 /* If the replacement _DECL isn't initialized, don't do the
10435 transformation. */
10436 if (!fn)
10437 return NULL_TREE;
10438
10439 return build_call_expr_loc (loc, fn, 1, s1);
10440 }
10441 return NULL_TREE;
10442}
10443
10444/* Fold the next_arg or va_start call EXP. Returns true if there was an error
10445 produced. False otherwise. This is done so that we don't output the error
10446 or warning twice or three times. */
10447
10448bool
10449fold_builtin_next_arg (tree exp, bool va_start_p)
10450{
10451 tree fntype = TREE_TYPE (current_function_decl);
10452 int nargs = call_expr_nargs (exp);
10453 tree arg;
10454 /* There is good chance the current input_location points inside the
10455 definition of the va_start macro (perhaps on the token for
10456 builtin) in a system header, so warnings will not be emitted.
10457 Use the location in real source code. */
10458 location_t current_location =
10459 linemap_unwind_to_first_non_reserved_loc (line_table, loc: input_location,
10460 NULL);
10461
10462 if (!stdarg_p (fntype))
10463 {
10464 error ("%<va_start%> used in function with fixed arguments");
10465 return true;
10466 }
10467
10468 if (va_start_p)
10469 {
10470 if (va_start_p && (nargs != 2))
10471 {
10472 error ("wrong number of arguments to function %<va_start%>");
10473 return true;
10474 }
10475 arg = CALL_EXPR_ARG (exp, 1);
10476 }
10477 /* We use __builtin_va_start (ap, 0, 0) or __builtin_next_arg (0, 0)
10478 when we checked the arguments and if needed issued a warning. */
10479 else
10480 {
10481 if (nargs == 0)
10482 {
10483 /* Evidently an out of date version of <stdarg.h>; can't validate
10484 va_start's second argument, but can still work as intended. */
10485 warning_at (current_location,
10486 OPT_Wvarargs,
10487 "%<__builtin_next_arg%> called without an argument");
10488 return true;
10489 }
10490 else if (nargs > 1)
10491 {
10492 error ("wrong number of arguments to function %<__builtin_next_arg%>");
10493 return true;
10494 }
10495 arg = CALL_EXPR_ARG (exp, 0);
10496 }
10497
10498 if (TREE_CODE (arg) == SSA_NAME
10499 && SSA_NAME_VAR (arg))
10500 arg = SSA_NAME_VAR (arg);
10501
10502 /* We destructively modify the call to be __builtin_va_start (ap, 0)
10503 or __builtin_next_arg (0) the first time we see it, after checking
10504 the arguments and if needed issuing a warning. */
10505 if (!integer_zerop (arg))
10506 {
10507 tree last_parm = tree_last (DECL_ARGUMENTS (current_function_decl));
10508
10509 /* Strip off all nops for the sake of the comparison. This
10510 is not quite the same as STRIP_NOPS. It does more.
10511 We must also strip off INDIRECT_EXPR for C++ reference
10512 parameters. */
10513 while (CONVERT_EXPR_P (arg)
10514 || INDIRECT_REF_P (arg))
10515 arg = TREE_OPERAND (arg, 0);
10516 if (arg != last_parm)
10517 {
10518 /* FIXME: Sometimes with the tree optimizers we can get the
10519 not the last argument even though the user used the last
10520 argument. We just warn and set the arg to be the last
10521 argument so that we will get wrong-code because of
10522 it. */
10523 warning_at (current_location,
10524 OPT_Wvarargs,
10525 "second parameter of %<va_start%> not last named argument");
10526 }
10527
10528 /* Undefined by C99 7.15.1.4p4 (va_start):
10529 "If the parameter parmN is declared with the register storage
10530 class, with a function or array type, or with a type that is
10531 not compatible with the type that results after application of
10532 the default argument promotions, the behavior is undefined."
10533 */
10534 else if (DECL_REGISTER (arg))
10535 {
10536 warning_at (current_location,
10537 OPT_Wvarargs,
10538 "undefined behavior when second parameter of "
10539 "%<va_start%> is declared with %<register%> storage");
10540 }
10541
10542 /* We want to verify the second parameter just once before the tree
10543 optimizers are run and then avoid keeping it in the tree,
10544 as otherwise we could warn even for correct code like:
10545 void foo (int i, ...)
10546 { va_list ap; i++; va_start (ap, i); va_end (ap); } */
10547 if (va_start_p)
10548 CALL_EXPR_ARG (exp, 1) = integer_zero_node;
10549 else
10550 CALL_EXPR_ARG (exp, 0) = integer_zero_node;
10551 }
10552 return false;
10553}
10554
10555
10556/* Expand a call EXP to __builtin_object_size. */
10557
10558static rtx
10559expand_builtin_object_size (tree exp)
10560{
10561 tree ost;
10562 int object_size_type;
10563 tree fndecl = get_callee_fndecl (exp);
10564
10565 if (!validate_arglist (callexpr: exp, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
10566 {
10567 error ("first argument of %qD must be a pointer, second integer constant",
10568 fndecl);
10569 expand_builtin_trap ();
10570 return const0_rtx;
10571 }
10572
10573 ost = CALL_EXPR_ARG (exp, 1);
10574 STRIP_NOPS (ost);
10575
10576 if (TREE_CODE (ost) != INTEGER_CST
10577 || tree_int_cst_sgn (ost) < 0
10578 || compare_tree_int (ost, 3) > 0)
10579 {
10580 error ("last argument of %qD is not integer constant between 0 and 3",
10581 fndecl);
10582 expand_builtin_trap ();
10583 return const0_rtx;
10584 }
10585
10586 object_size_type = tree_to_shwi (ost);
10587
10588 return object_size_type < 2 ? constm1_rtx : const0_rtx;
10589}
10590
10591/* Expand EXP, a call to the __mem{cpy,pcpy,move,set}_chk builtin.
10592 FCODE is the BUILT_IN_* to use.
10593 Return NULL_RTX if we failed; the caller should emit a normal call,
10594 otherwise try to get the result in TARGET, if convenient (and in
10595 mode MODE if that's convenient). */
10596
10597static rtx
10598expand_builtin_memory_chk (tree exp, rtx target, machine_mode mode,
10599 enum built_in_function fcode)
10600{
10601 if (!validate_arglist (callexpr: exp,
10602 POINTER_TYPE,
10603 fcode == BUILT_IN_MEMSET_CHK
10604 ? INTEGER_TYPE : POINTER_TYPE,
10605 INTEGER_TYPE, INTEGER_TYPE, VOID_TYPE))
10606 return NULL_RTX;
10607
10608 tree dest = CALL_EXPR_ARG (exp, 0);
10609 tree src = CALL_EXPR_ARG (exp, 1);
10610 tree len = CALL_EXPR_ARG (exp, 2);
10611 tree size = CALL_EXPR_ARG (exp, 3);
10612
10613 /* FIXME: Set access mode to write only for memset et al. */
10614 bool sizes_ok = check_access (exp, len, /*maxread=*/NULL_TREE,
10615 /*srcstr=*/NULL_TREE, size, access_read_write);
10616
10617 if (!tree_fits_uhwi_p (size))
10618 return NULL_RTX;
10619
10620 if (tree_fits_uhwi_p (len) || integer_all_onesp (size))
10621 {
10622 /* Avoid transforming the checking call to an ordinary one when
10623 an overflow has been detected or when the call couldn't be
10624 validated because the size is not constant. */
10625 if (!sizes_ok && !integer_all_onesp (size) && tree_int_cst_lt (t1: size, t2: len))
10626 return NULL_RTX;
10627
10628 tree fn = NULL_TREE;
10629 /* If __builtin_mem{cpy,pcpy,move,set}_chk is used, assume
10630 mem{cpy,pcpy,move,set} is available. */
10631 switch (fcode)
10632 {
10633 case BUILT_IN_MEMCPY_CHK:
10634 fn = builtin_decl_explicit (fncode: BUILT_IN_MEMCPY);
10635 break;
10636 case BUILT_IN_MEMPCPY_CHK:
10637 fn = builtin_decl_explicit (fncode: BUILT_IN_MEMPCPY);
10638 break;
10639 case BUILT_IN_MEMMOVE_CHK:
10640 fn = builtin_decl_explicit (fncode: BUILT_IN_MEMMOVE);
10641 break;
10642 case BUILT_IN_MEMSET_CHK:
10643 fn = builtin_decl_explicit (fncode: BUILT_IN_MEMSET);
10644 break;
10645 default:
10646 break;
10647 }
10648
10649 if (! fn)
10650 return NULL_RTX;
10651
10652 fn = build_call_nofold_loc (EXPR_LOCATION (exp), fndecl: fn, n: 3, dest, src, len);
10653 gcc_assert (TREE_CODE (fn) == CALL_EXPR);
10654 CALL_EXPR_TAILCALL (fn) = CALL_EXPR_TAILCALL (exp);
10655 return expand_expr (exp: fn, target, mode, modifier: EXPAND_NORMAL);
10656 }
10657 else if (fcode == BUILT_IN_MEMSET_CHK)
10658 return NULL_RTX;
10659 else
10660 {
10661 unsigned int dest_align = get_pointer_alignment (exp: dest);
10662
10663 /* If DEST is not a pointer type, call the normal function. */
10664 if (dest_align == 0)
10665 return NULL_RTX;
10666
10667 /* If SRC and DEST are the same (and not volatile), do nothing. */
10668 if (operand_equal_p (src, dest, flags: 0))
10669 {
10670 tree expr;
10671
10672 if (fcode != BUILT_IN_MEMPCPY_CHK)
10673 {
10674 /* Evaluate and ignore LEN in case it has side-effects. */
10675 expand_expr (exp: len, const0_rtx, VOIDmode, modifier: EXPAND_NORMAL);
10676 return expand_expr (exp: dest, target, mode, modifier: EXPAND_NORMAL);
10677 }
10678
10679 expr = fold_build_pointer_plus (dest, len);
10680 return expand_expr (exp: expr, target, mode, modifier: EXPAND_NORMAL);
10681 }
10682
10683 /* __memmove_chk special case. */
10684 if (fcode == BUILT_IN_MEMMOVE_CHK)
10685 {
10686 unsigned int src_align = get_pointer_alignment (exp: src);
10687
10688 if (src_align == 0)
10689 return NULL_RTX;
10690
10691 /* If src is categorized for a readonly section we can use
10692 normal __memcpy_chk. */
10693 if (readonly_data_expr (exp: src))
10694 {
10695 tree fn = builtin_decl_explicit (fncode: BUILT_IN_MEMCPY_CHK);
10696 if (!fn)
10697 return NULL_RTX;
10698 fn = build_call_nofold_loc (EXPR_LOCATION (exp), fndecl: fn, n: 4,
10699 dest, src, len, size);
10700 gcc_assert (TREE_CODE (fn) == CALL_EXPR);
10701 CALL_EXPR_TAILCALL (fn) = CALL_EXPR_TAILCALL (exp);
10702 return expand_expr (exp: fn, target, mode, modifier: EXPAND_NORMAL);
10703 }
10704 }
10705 return NULL_RTX;
10706 }
10707}
10708
10709/* Emit warning if a buffer overflow is detected at compile time. */
10710
10711static void
10712maybe_emit_chk_warning (tree exp, enum built_in_function fcode)
10713{
10714 /* The source string. */
10715 tree srcstr = NULL_TREE;
10716 /* The size of the destination object returned by __builtin_object_size. */
10717 tree objsize = NULL_TREE;
10718 /* The string that is being concatenated with (as in __strcat_chk)
10719 or null if it isn't. */
10720 tree catstr = NULL_TREE;
10721 /* The maximum length of the source sequence in a bounded operation
10722 (such as __strncat_chk) or null if the operation isn't bounded
10723 (such as __strcat_chk). */
10724 tree maxread = NULL_TREE;
10725 /* The exact size of the access (such as in __strncpy_chk). */
10726 tree size = NULL_TREE;
10727 /* The access by the function that's checked. Except for snprintf
10728 both writing and reading is checked. */
10729 access_mode mode = access_read_write;
10730
10731 switch (fcode)
10732 {
10733 case BUILT_IN_STRCPY_CHK:
10734 case BUILT_IN_STPCPY_CHK:
10735 srcstr = CALL_EXPR_ARG (exp, 1);
10736 objsize = CALL_EXPR_ARG (exp, 2);
10737 break;
10738
10739 case BUILT_IN_STRCAT_CHK:
10740 /* For __strcat_chk the warning will be emitted only if overflowing
10741 by at least strlen (dest) + 1 bytes. */
10742 catstr = CALL_EXPR_ARG (exp, 0);
10743 srcstr = CALL_EXPR_ARG (exp, 1);
10744 objsize = CALL_EXPR_ARG (exp, 2);
10745 break;
10746
10747 case BUILT_IN_STRNCAT_CHK:
10748 catstr = CALL_EXPR_ARG (exp, 0);
10749 srcstr = CALL_EXPR_ARG (exp, 1);
10750 maxread = CALL_EXPR_ARG (exp, 2);
10751 objsize = CALL_EXPR_ARG (exp, 3);
10752 break;
10753
10754 case BUILT_IN_STRNCPY_CHK:
10755 case BUILT_IN_STPNCPY_CHK:
10756 srcstr = CALL_EXPR_ARG (exp, 1);
10757 size = CALL_EXPR_ARG (exp, 2);
10758 objsize = CALL_EXPR_ARG (exp, 3);
10759 break;
10760
10761 case BUILT_IN_SNPRINTF_CHK:
10762 case BUILT_IN_VSNPRINTF_CHK:
10763 maxread = CALL_EXPR_ARG (exp, 1);
10764 objsize = CALL_EXPR_ARG (exp, 3);
10765 /* The only checked access the write to the destination. */
10766 mode = access_write_only;
10767 break;
10768 default:
10769 gcc_unreachable ();
10770 }
10771
10772 if (catstr && maxread)
10773 {
10774 /* Check __strncat_chk. There is no way to determine the length
10775 of the string to which the source string is being appended so
10776 just warn when the length of the source string is not known. */
10777 check_strncat_sizes (exp, objsize);
10778 return;
10779 }
10780
10781 check_access (exp, size, maxread, srcstr, objsize, mode);
10782}
10783
10784/* Emit warning if a buffer overflow is detected at compile time
10785 in __sprintf_chk/__vsprintf_chk calls. */
10786
10787static void
10788maybe_emit_sprintf_chk_warning (tree exp, enum built_in_function fcode)
10789{
10790 tree size, len, fmt;
10791 const char *fmt_str;
10792 int nargs = call_expr_nargs (exp);
10793
10794 /* Verify the required arguments in the original call. */
10795
10796 if (nargs < 4)
10797 return;
10798 size = CALL_EXPR_ARG (exp, 2);
10799 fmt = CALL_EXPR_ARG (exp, 3);
10800
10801 if (! tree_fits_uhwi_p (size) || integer_all_onesp (size))
10802 return;
10803
10804 /* Check whether the format is a literal string constant. */
10805 fmt_str = c_getstr (fmt);
10806 if (fmt_str == NULL)
10807 return;
10808
10809 if (!init_target_chars ())
10810 return;
10811
10812 /* If the format doesn't contain % args or %%, we know its size. */
10813 if (strchr (s: fmt_str, c: target_percent) == 0)
10814 len = build_int_cstu (size_type_node, strlen (s: fmt_str));
10815 /* If the format is "%s" and first ... argument is a string literal,
10816 we know it too. */
10817 else if (fcode == BUILT_IN_SPRINTF_CHK
10818 && strcmp (s1: fmt_str, s2: target_percent_s) == 0)
10819 {
10820 tree arg;
10821
10822 if (nargs < 5)
10823 return;
10824 arg = CALL_EXPR_ARG (exp, 4);
10825 if (! POINTER_TYPE_P (TREE_TYPE (arg)))
10826 return;
10827
10828 len = c_strlen (arg, only_value: 1);
10829 if (!len || ! tree_fits_uhwi_p (len))
10830 return;
10831 }
10832 else
10833 return;
10834
10835 /* Add one for the terminating nul. */
10836 len = fold_build2 (PLUS_EXPR, TREE_TYPE (len), len, size_one_node);
10837
10838 check_access (exp, /*size=*/NULL_TREE, /*maxread=*/NULL_TREE, len, size,
10839 access_write_only);
10840}
10841
10842/* Fold a call to __builtin_object_size with arguments PTR and OST,
10843 if possible. */
10844
10845static tree
10846fold_builtin_object_size (tree ptr, tree ost, enum built_in_function fcode)
10847{
10848 tree bytes;
10849 int object_size_type;
10850
10851 if (!validate_arg (arg: ptr, code: POINTER_TYPE)
10852 || !validate_arg (arg: ost, code: INTEGER_TYPE))
10853 return NULL_TREE;
10854
10855 STRIP_NOPS (ost);
10856
10857 if (TREE_CODE (ost) != INTEGER_CST
10858 || tree_int_cst_sgn (ost) < 0
10859 || compare_tree_int (ost, 3) > 0)
10860 return NULL_TREE;
10861
10862 object_size_type = tree_to_shwi (ost);
10863
10864 /* __builtin_object_size doesn't evaluate side-effects in its arguments;
10865 if there are any side-effects, it returns (size_t) -1 for types 0 and 1
10866 and (size_t) 0 for types 2 and 3. */
10867 if (TREE_SIDE_EFFECTS (ptr))
10868 return build_int_cst_type (size_type_node, object_size_type < 2 ? -1 : 0);
10869
10870 if (fcode == BUILT_IN_DYNAMIC_OBJECT_SIZE)
10871 object_size_type |= OST_DYNAMIC;
10872
10873 if (TREE_CODE (ptr) == ADDR_EXPR)
10874 {
10875 compute_builtin_object_size (ptr, object_size_type, &bytes);
10876 if ((object_size_type & OST_DYNAMIC)
10877 || int_fits_type_p (bytes, size_type_node))
10878 return fold_convert (size_type_node, bytes);
10879 }
10880 else if (TREE_CODE (ptr) == SSA_NAME)
10881 {
10882 /* If object size is not known yet, delay folding until
10883 later. Maybe subsequent passes will help determining
10884 it. */
10885 if (compute_builtin_object_size (ptr, object_size_type, &bytes)
10886 && ((object_size_type & OST_DYNAMIC)
10887 || int_fits_type_p (bytes, size_type_node)))
10888 return fold_convert (size_type_node, bytes);
10889 }
10890
10891 return NULL_TREE;
10892}
10893
10894/* Builtins with folding operations that operate on "..." arguments
10895 need special handling; we need to store the arguments in a convenient
10896 data structure before attempting any folding. Fortunately there are
10897 only a few builtins that fall into this category. FNDECL is the
10898 function, EXP is the CALL_EXPR for the call. */
10899
10900static tree
10901fold_builtin_varargs (location_t loc, tree fndecl, tree *args, int nargs)
10902{
10903 enum built_in_function fcode = DECL_FUNCTION_CODE (decl: fndecl);
10904 tree ret = NULL_TREE;
10905
10906 switch (fcode)
10907 {
10908 case BUILT_IN_FPCLASSIFY:
10909 ret = fold_builtin_fpclassify (loc, args, nargs);
10910 break;
10911
10912 case BUILT_IN_ADDC:
10913 case BUILT_IN_ADDCL:
10914 case BUILT_IN_ADDCLL:
10915 case BUILT_IN_SUBC:
10916 case BUILT_IN_SUBCL:
10917 case BUILT_IN_SUBCLL:
10918 return fold_builtin_addc_subc (loc, fcode, args);
10919
10920 default:
10921 break;
10922 }
10923 if (ret)
10924 {
10925 ret = build1 (NOP_EXPR, TREE_TYPE (ret), ret);
10926 SET_EXPR_LOCATION (ret, loc);
10927 suppress_warning (ret);
10928 return ret;
10929 }
10930 return NULL_TREE;
10931}
10932
10933/* Initialize format string characters in the target charset. */
10934
10935bool
10936init_target_chars (void)
10937{
10938 static bool init;
10939 if (!init)
10940 {
10941 target_newline = lang_hooks.to_target_charset ('\n');
10942 target_percent = lang_hooks.to_target_charset ('%');
10943 target_c = lang_hooks.to_target_charset ('c');
10944 target_s = lang_hooks.to_target_charset ('s');
10945 if (target_newline == 0 || target_percent == 0 || target_c == 0
10946 || target_s == 0)
10947 return false;
10948
10949 target_percent_c[0] = target_percent;
10950 target_percent_c[1] = target_c;
10951 target_percent_c[2] = '\0';
10952
10953 target_percent_s[0] = target_percent;
10954 target_percent_s[1] = target_s;
10955 target_percent_s[2] = '\0';
10956
10957 target_percent_s_newline[0] = target_percent;
10958 target_percent_s_newline[1] = target_s;
10959 target_percent_s_newline[2] = target_newline;
10960 target_percent_s_newline[3] = '\0';
10961
10962 init = true;
10963 }
10964 return true;
10965}
10966
10967/* Helper function for do_mpfr_arg*(). Ensure M is a normal number
10968 and no overflow/underflow occurred. INEXACT is true if M was not
10969 exactly calculated. TYPE is the tree type for the result. This
10970 function assumes that you cleared the MPFR flags and then
10971 calculated M to see if anything subsequently set a flag prior to
10972 entering this function. Return NULL_TREE if any checks fail. */
10973
10974static tree
10975do_mpfr_ckconv (mpfr_srcptr m, tree type, int inexact)
10976{
10977 /* Proceed iff we get a normal number, i.e. not NaN or Inf and no
10978 overflow/underflow occurred. If -frounding-math, proceed iff the
10979 result of calling FUNC was exact. */
10980 if (mpfr_number_p (m) && !mpfr_overflow_p () && !mpfr_underflow_p ()
10981 && (!flag_rounding_math || !inexact))
10982 {
10983 REAL_VALUE_TYPE rr;
10984
10985 real_from_mpfr (&rr, m, type, MPFR_RNDN);
10986 /* Proceed iff GCC's REAL_VALUE_TYPE can hold the MPFR value,
10987 check for overflow/underflow. If the REAL_VALUE_TYPE is zero
10988 but the mpfr_t is not, then we underflowed in the
10989 conversion. */
10990 if (real_isfinite (&rr)
10991 && (rr.cl == rvc_zero) == (mpfr_zero_p (m) != 0))
10992 {
10993 REAL_VALUE_TYPE rmode;
10994
10995 real_convert (&rmode, TYPE_MODE (type), &rr);
10996 /* Proceed iff the specified mode can hold the value. */
10997 if (real_identical (&rmode, &rr))
10998 return build_real (type, rmode);
10999 }
11000 }
11001 return NULL_TREE;
11002}
11003
11004/* Helper function for do_mpc_arg*(). Ensure M is a normal complex
11005 number and no overflow/underflow occurred. INEXACT is true if M
11006 was not exactly calculated. TYPE is the tree type for the result.
11007 This function assumes that you cleared the MPFR flags and then
11008 calculated M to see if anything subsequently set a flag prior to
11009 entering this function. Return NULL_TREE if any checks fail, if
11010 FORCE_CONVERT is true, then bypass the checks. */
11011
11012static tree
11013do_mpc_ckconv (mpc_srcptr m, tree type, int inexact, int force_convert)
11014{
11015 /* Proceed iff we get a normal number, i.e. not NaN or Inf and no
11016 overflow/underflow occurred. If -frounding-math, proceed iff the
11017 result of calling FUNC was exact. */
11018 if (force_convert
11019 || (mpfr_number_p (mpc_realref (m)) && mpfr_number_p (mpc_imagref (m))
11020 && !mpfr_overflow_p () && !mpfr_underflow_p ()
11021 && (!flag_rounding_math || !inexact)))
11022 {
11023 REAL_VALUE_TYPE re, im;
11024
11025 real_from_mpfr (&re, mpc_realref (m), TREE_TYPE (type), MPFR_RNDN);
11026 real_from_mpfr (&im, mpc_imagref (m), TREE_TYPE (type), MPFR_RNDN);
11027 /* Proceed iff GCC's REAL_VALUE_TYPE can hold the MPFR values,
11028 check for overflow/underflow. If the REAL_VALUE_TYPE is zero
11029 but the mpfr_t is not, then we underflowed in the
11030 conversion. */
11031 if (force_convert
11032 || (real_isfinite (&re) && real_isfinite (&im)
11033 && (re.cl == rvc_zero) == (mpfr_zero_p (mpc_realref (m)) != 0)
11034 && (im.cl == rvc_zero) == (mpfr_zero_p (mpc_imagref (m)) != 0)))
11035 {
11036 REAL_VALUE_TYPE re_mode, im_mode;
11037
11038 real_convert (&re_mode, TYPE_MODE (TREE_TYPE (type)), &re);
11039 real_convert (&im_mode, TYPE_MODE (TREE_TYPE (type)), &im);
11040 /* Proceed iff the specified mode can hold the value. */
11041 if (force_convert
11042 || (real_identical (&re_mode, &re)
11043 && real_identical (&im_mode, &im)))
11044 return build_complex (type, build_real (TREE_TYPE (type), re_mode),
11045 build_real (TREE_TYPE (type), im_mode));
11046 }
11047 }
11048 return NULL_TREE;
11049}
11050
11051/* If arguments ARG0 and ARG1 are REAL_CSTs, call mpfr_remquo() to set
11052 the pointer *(ARG_QUO) and return the result. The type is taken
11053 from the type of ARG0 and is used for setting the precision of the
11054 calculation and results. */
11055
11056static tree
11057do_mpfr_remquo (tree arg0, tree arg1, tree arg_quo)
11058{
11059 tree const type = TREE_TYPE (arg0);
11060 tree result = NULL_TREE;
11061
11062 STRIP_NOPS (arg0);
11063 STRIP_NOPS (arg1);
11064
11065 /* To proceed, MPFR must exactly represent the target floating point
11066 format, which only happens when the target base equals two. */
11067 if (REAL_MODE_FORMAT (TYPE_MODE (type))->b == 2
11068 && TREE_CODE (arg0) == REAL_CST && !TREE_OVERFLOW (arg0)
11069 && TREE_CODE (arg1) == REAL_CST && !TREE_OVERFLOW (arg1))
11070 {
11071 const REAL_VALUE_TYPE *const ra0 = TREE_REAL_CST_PTR (arg0);
11072 const REAL_VALUE_TYPE *const ra1 = TREE_REAL_CST_PTR (arg1);
11073
11074 if (real_isfinite (ra0) && real_isfinite (ra1))
11075 {
11076 const struct real_format *fmt = REAL_MODE_FORMAT (TYPE_MODE (type));
11077 const int prec = fmt->p;
11078 const mpfr_rnd_t rnd = fmt->round_towards_zero? MPFR_RNDZ : MPFR_RNDN;
11079 tree result_rem;
11080 long integer_quo;
11081 mpfr_t m0, m1;
11082
11083 mpfr_inits2 (prec, m0, m1, NULL);
11084 mpfr_from_real (m0, ra0, MPFR_RNDN);
11085 mpfr_from_real (m1, ra1, MPFR_RNDN);
11086 mpfr_clear_flags ();
11087 mpfr_remquo (m0, &integer_quo, m0, m1, rnd);
11088 /* Remquo is independent of the rounding mode, so pass
11089 inexact=0 to do_mpfr_ckconv(). */
11090 result_rem = do_mpfr_ckconv (m: m0, type, /*inexact=*/ 0);
11091 mpfr_clears (m0, m1, NULL);
11092 if (result_rem)
11093 {
11094 /* MPFR calculates quo in the host's long so it may
11095 return more bits in quo than the target int can hold
11096 if sizeof(host long) > sizeof(target int). This can
11097 happen even for native compilers in LP64 mode. In
11098 these cases, modulo the quo value with the largest
11099 number that the target int can hold while leaving one
11100 bit for the sign. */
11101 if (sizeof (integer_quo) * CHAR_BIT > INT_TYPE_SIZE)
11102 integer_quo %= (long)(1UL << (INT_TYPE_SIZE - 1));
11103
11104 /* Dereference the quo pointer argument. */
11105 arg_quo = build_fold_indirect_ref (arg_quo);
11106 /* Proceed iff a valid pointer type was passed in. */
11107 if (TYPE_MAIN_VARIANT (TREE_TYPE (arg_quo)) == integer_type_node)
11108 {
11109 /* Set the value. */
11110 tree result_quo
11111 = fold_build2 (MODIFY_EXPR, TREE_TYPE (arg_quo), arg_quo,
11112 build_int_cst (TREE_TYPE (arg_quo),
11113 integer_quo));
11114 TREE_SIDE_EFFECTS (result_quo) = 1;
11115 /* Combine the quo assignment with the rem. */
11116 result = fold_build2 (COMPOUND_EXPR, type,
11117 result_quo, result_rem);
11118 suppress_warning (result, OPT_Wunused_value);
11119 result = non_lvalue (result);
11120 }
11121 }
11122 }
11123 }
11124 return result;
11125}
11126
11127/* If ARG is a REAL_CST, call mpfr_lgamma() on it and return the
11128 resulting value as a tree with type TYPE. The mpfr precision is
11129 set to the precision of TYPE. We assume that this mpfr function
11130 returns zero if the result could be calculated exactly within the
11131 requested precision. In addition, the integer pointer represented
11132 by ARG_SG will be dereferenced and set to the appropriate signgam
11133 (-1,1) value. */
11134
11135static tree
11136do_mpfr_lgamma_r (tree arg, tree arg_sg, tree type)
11137{
11138 tree result = NULL_TREE;
11139
11140 STRIP_NOPS (arg);
11141
11142 /* To proceed, MPFR must exactly represent the target floating point
11143 format, which only happens when the target base equals two. Also
11144 verify ARG is a constant and that ARG_SG is an int pointer. */
11145 if (REAL_MODE_FORMAT (TYPE_MODE (type))->b == 2
11146 && TREE_CODE (arg) == REAL_CST && !TREE_OVERFLOW (arg)
11147 && TREE_CODE (TREE_TYPE (arg_sg)) == POINTER_TYPE
11148 && TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (arg_sg))) == integer_type_node)
11149 {
11150 const REAL_VALUE_TYPE *const ra = TREE_REAL_CST_PTR (arg);
11151
11152 /* In addition to NaN and Inf, the argument cannot be zero or a
11153 negative integer. */
11154 if (real_isfinite (ra)
11155 && ra->cl != rvc_zero
11156 && !(real_isneg (ra) && real_isinteger (ra, TYPE_MODE (type))))
11157 {
11158 const struct real_format *fmt = REAL_MODE_FORMAT (TYPE_MODE (type));
11159 const int prec = fmt->p;
11160 const mpfr_rnd_t rnd = fmt->round_towards_zero? MPFR_RNDZ : MPFR_RNDN;
11161 int inexact, sg;
11162 tree result_lg;
11163
11164 auto_mpfr m (prec);
11165 mpfr_from_real (m, ra, MPFR_RNDN);
11166 mpfr_clear_flags ();
11167 inexact = mpfr_lgamma (m, &sg, m, rnd);
11168 result_lg = do_mpfr_ckconv (m, type, inexact);
11169 if (result_lg)
11170 {
11171 tree result_sg;
11172
11173 /* Dereference the arg_sg pointer argument. */
11174 arg_sg = build_fold_indirect_ref (arg_sg);
11175 /* Assign the signgam value into *arg_sg. */
11176 result_sg = fold_build2 (MODIFY_EXPR,
11177 TREE_TYPE (arg_sg), arg_sg,
11178 build_int_cst (TREE_TYPE (arg_sg), sg));
11179 TREE_SIDE_EFFECTS (result_sg) = 1;
11180 /* Combine the signgam assignment with the lgamma result. */
11181 result = non_lvalue (fold_build2 (COMPOUND_EXPR, type,
11182 result_sg, result_lg));
11183 }
11184 }
11185 }
11186
11187 return result;
11188}
11189
11190/* If arguments ARG0 and ARG1 are a COMPLEX_CST, call the two-argument
11191 mpc function FUNC on it and return the resulting value as a tree
11192 with type TYPE. The mpfr precision is set to the precision of
11193 TYPE. We assume that function FUNC returns zero if the result
11194 could be calculated exactly within the requested precision. If
11195 DO_NONFINITE is true, then fold expressions containing Inf or NaN
11196 in the arguments and/or results. */
11197
11198tree
11199do_mpc_arg2 (tree arg0, tree arg1, tree type, int do_nonfinite,
11200 int (*func)(mpc_ptr, mpc_srcptr, mpc_srcptr, mpc_rnd_t))
11201{
11202 tree result = NULL_TREE;
11203
11204 STRIP_NOPS (arg0);
11205 STRIP_NOPS (arg1);
11206
11207 /* To proceed, MPFR must exactly represent the target floating point
11208 format, which only happens when the target base equals two. */
11209 if (TREE_CODE (arg0) == COMPLEX_CST && !TREE_OVERFLOW (arg0)
11210 && SCALAR_FLOAT_TYPE_P (TREE_TYPE (TREE_TYPE (arg0)))
11211 && TREE_CODE (arg1) == COMPLEX_CST && !TREE_OVERFLOW (arg1)
11212 && SCALAR_FLOAT_TYPE_P (TREE_TYPE (TREE_TYPE (arg1)))
11213 && REAL_MODE_FORMAT (TYPE_MODE (TREE_TYPE (TREE_TYPE (arg0))))->b == 2)
11214 {
11215 const REAL_VALUE_TYPE *const re0 = TREE_REAL_CST_PTR (TREE_REALPART (arg0));
11216 const REAL_VALUE_TYPE *const im0 = TREE_REAL_CST_PTR (TREE_IMAGPART (arg0));
11217 const REAL_VALUE_TYPE *const re1 = TREE_REAL_CST_PTR (TREE_REALPART (arg1));
11218 const REAL_VALUE_TYPE *const im1 = TREE_REAL_CST_PTR (TREE_IMAGPART (arg1));
11219
11220 if (do_nonfinite
11221 || (real_isfinite (re0) && real_isfinite (im0)
11222 && real_isfinite (re1) && real_isfinite (im1)))
11223 {
11224 const struct real_format *const fmt =
11225 REAL_MODE_FORMAT (TYPE_MODE (TREE_TYPE (type)));
11226 const int prec = fmt->p;
11227 const mpfr_rnd_t rnd = fmt->round_towards_zero
11228 ? MPFR_RNDZ : MPFR_RNDN;
11229 const mpc_rnd_t crnd = fmt->round_towards_zero ? MPC_RNDZZ : MPC_RNDNN;
11230 int inexact;
11231 mpc_t m0, m1;
11232
11233 mpc_init2 (m0, prec);
11234 mpc_init2 (m1, prec);
11235 mpfr_from_real (mpc_realref (m0), re0, rnd);
11236 mpfr_from_real (mpc_imagref (m0), im0, rnd);
11237 mpfr_from_real (mpc_realref (m1), re1, rnd);
11238 mpfr_from_real (mpc_imagref (m1), im1, rnd);
11239 mpfr_clear_flags ();
11240 inexact = func (m0, m0, m1, crnd);
11241 result = do_mpc_ckconv (m: m0, type, inexact, force_convert: do_nonfinite);
11242 mpc_clear (m0);
11243 mpc_clear (m1);
11244 }
11245 }
11246
11247 return result;
11248}
11249
11250/* A wrapper function for builtin folding that prevents warnings for
11251 "statement without effect" and the like, caused by removing the
11252 call node earlier than the warning is generated. */
11253
11254tree
11255fold_call_stmt (gcall *stmt, bool ignore)
11256{
11257 tree ret = NULL_TREE;
11258 tree fndecl = gimple_call_fndecl (gs: stmt);
11259 location_t loc = gimple_location (g: stmt);
11260 if (fndecl && fndecl_built_in_p (node: fndecl)
11261 && !gimple_call_va_arg_pack_p (s: stmt))
11262 {
11263 int nargs = gimple_call_num_args (gs: stmt);
11264 tree *args = (nargs > 0
11265 ? gimple_call_arg_ptr (gs: stmt, index: 0)
11266 : &error_mark_node);
11267
11268 if (avoid_folding_inline_builtin (fndecl))
11269 return NULL_TREE;
11270 if (DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_MD)
11271 {
11272 return targetm.fold_builtin (fndecl, nargs, args, ignore);
11273 }
11274 else
11275 {
11276 ret = fold_builtin_n (loc, NULL_TREE, fndecl, args, nargs, ignore);
11277 if (ret)
11278 {
11279 /* Propagate location information from original call to
11280 expansion of builtin. Otherwise things like
11281 maybe_emit_chk_warning, that operate on the expansion
11282 of a builtin, will use the wrong location information. */
11283 if (gimple_has_location (g: stmt))
11284 {
11285 tree realret = ret;
11286 if (TREE_CODE (ret) == NOP_EXPR)
11287 realret = TREE_OPERAND (ret, 0);
11288 if (CAN_HAVE_LOCATION_P (realret)
11289 && !EXPR_HAS_LOCATION (realret))
11290 SET_EXPR_LOCATION (realret, loc);
11291 return realret;
11292 }
11293 return ret;
11294 }
11295 }
11296 }
11297 return NULL_TREE;
11298}
11299
11300/* Look up the function in builtin_decl that corresponds to DECL
11301 and set ASMSPEC as its user assembler name. DECL must be a
11302 function decl that declares a builtin. */
11303
11304void
11305set_builtin_user_assembler_name (tree decl, const char *asmspec)
11306{
11307 gcc_assert (fndecl_built_in_p (decl, BUILT_IN_NORMAL)
11308 && asmspec != 0);
11309
11310 tree builtin = builtin_decl_explicit (fncode: DECL_FUNCTION_CODE (decl));
11311 set_user_assembler_name (builtin, asmspec);
11312
11313 if (DECL_FUNCTION_CODE (decl) == BUILT_IN_FFS
11314 && INT_TYPE_SIZE < BITS_PER_WORD)
11315 {
11316 scalar_int_mode mode = int_mode_for_size (INT_TYPE_SIZE, limit: 0).require ();
11317 set_user_assembler_libfunc ("ffs", asmspec);
11318 set_optab_libfunc (ffs_optab, mode, "ffs");
11319 }
11320}
11321
11322/* Return true if DECL is a builtin that expands to a constant or similarly
11323 simple code. */
11324bool
11325is_simple_builtin (tree decl)
11326{
11327 if (decl && fndecl_built_in_p (node: decl, klass: BUILT_IN_NORMAL))
11328 switch (DECL_FUNCTION_CODE (decl))
11329 {
11330 /* Builtins that expand to constants. */
11331 case BUILT_IN_CONSTANT_P:
11332 case BUILT_IN_EXPECT:
11333 case BUILT_IN_OBJECT_SIZE:
11334 case BUILT_IN_UNREACHABLE:
11335 /* Simple register moves or loads from stack. */
11336 case BUILT_IN_ASSUME_ALIGNED:
11337 case BUILT_IN_RETURN_ADDRESS:
11338 case BUILT_IN_EXTRACT_RETURN_ADDR:
11339 case BUILT_IN_FROB_RETURN_ADDR:
11340 case BUILT_IN_RETURN:
11341 case BUILT_IN_AGGREGATE_INCOMING_ADDRESS:
11342 case BUILT_IN_FRAME_ADDRESS:
11343 case BUILT_IN_VA_END:
11344 case BUILT_IN_STACK_SAVE:
11345 case BUILT_IN_STACK_RESTORE:
11346 case BUILT_IN_DWARF_CFA:
11347 /* Exception state returns or moves registers around. */
11348 case BUILT_IN_EH_FILTER:
11349 case BUILT_IN_EH_POINTER:
11350 case BUILT_IN_EH_COPY_VALUES:
11351 return true;
11352
11353 default:
11354 return false;
11355 }
11356
11357 return false;
11358}
11359
11360/* Return true if DECL is a builtin that is not expensive, i.e., they are
11361 most probably expanded inline into reasonably simple code. This is a
11362 superset of is_simple_builtin. */
11363bool
11364is_inexpensive_builtin (tree decl)
11365{
11366 if (!decl)
11367 return false;
11368 else if (DECL_BUILT_IN_CLASS (decl) == BUILT_IN_MD)
11369 return true;
11370 else if (DECL_BUILT_IN_CLASS (decl) == BUILT_IN_NORMAL)
11371 switch (DECL_FUNCTION_CODE (decl))
11372 {
11373 case BUILT_IN_ABS:
11374 CASE_BUILT_IN_ALLOCA:
11375 case BUILT_IN_BSWAP16:
11376 case BUILT_IN_BSWAP32:
11377 case BUILT_IN_BSWAP64:
11378 case BUILT_IN_BSWAP128:
11379 case BUILT_IN_CLZ:
11380 case BUILT_IN_CLZIMAX:
11381 case BUILT_IN_CLZL:
11382 case BUILT_IN_CLZLL:
11383 case BUILT_IN_CTZ:
11384 case BUILT_IN_CTZIMAX:
11385 case BUILT_IN_CTZL:
11386 case BUILT_IN_CTZLL:
11387 case BUILT_IN_FFS:
11388 case BUILT_IN_FFSIMAX:
11389 case BUILT_IN_FFSL:
11390 case BUILT_IN_FFSLL:
11391 case BUILT_IN_IMAXABS:
11392 case BUILT_IN_FINITE:
11393 case BUILT_IN_FINITEF:
11394 case BUILT_IN_FINITEL:
11395 case BUILT_IN_FINITED32:
11396 case BUILT_IN_FINITED64:
11397 case BUILT_IN_FINITED128:
11398 case BUILT_IN_FPCLASSIFY:
11399 case BUILT_IN_ISFINITE:
11400 case BUILT_IN_ISINF_SIGN:
11401 case BUILT_IN_ISINF:
11402 case BUILT_IN_ISINFF:
11403 case BUILT_IN_ISINFL:
11404 case BUILT_IN_ISINFD32:
11405 case BUILT_IN_ISINFD64:
11406 case BUILT_IN_ISINFD128:
11407 case BUILT_IN_ISNAN:
11408 case BUILT_IN_ISNANF:
11409 case BUILT_IN_ISNANL:
11410 case BUILT_IN_ISNAND32:
11411 case BUILT_IN_ISNAND64:
11412 case BUILT_IN_ISNAND128:
11413 case BUILT_IN_ISNORMAL:
11414 case BUILT_IN_ISGREATER:
11415 case BUILT_IN_ISGREATEREQUAL:
11416 case BUILT_IN_ISLESS:
11417 case BUILT_IN_ISLESSEQUAL:
11418 case BUILT_IN_ISLESSGREATER:
11419 case BUILT_IN_ISUNORDERED:
11420 case BUILT_IN_ISEQSIG:
11421 case BUILT_IN_VA_ARG_PACK:
11422 case BUILT_IN_VA_ARG_PACK_LEN:
11423 case BUILT_IN_VA_COPY:
11424 case BUILT_IN_TRAP:
11425 case BUILT_IN_UNREACHABLE_TRAP:
11426 case BUILT_IN_SAVEREGS:
11427 case BUILT_IN_POPCOUNTL:
11428 case BUILT_IN_POPCOUNTLL:
11429 case BUILT_IN_POPCOUNTIMAX:
11430 case BUILT_IN_POPCOUNT:
11431 case BUILT_IN_PARITYL:
11432 case BUILT_IN_PARITYLL:
11433 case BUILT_IN_PARITYIMAX:
11434 case BUILT_IN_PARITY:
11435 case BUILT_IN_LABS:
11436 case BUILT_IN_LLABS:
11437 case BUILT_IN_PREFETCH:
11438 case BUILT_IN_ACC_ON_DEVICE:
11439 return true;
11440
11441 default:
11442 return is_simple_builtin (decl);
11443 }
11444
11445 return false;
11446}
11447
11448/* Return true if T is a constant and the value cast to a target char
11449 can be represented by a host char.
11450 Store the casted char constant in *P if so. */
11451
11452bool
11453target_char_cst_p (tree t, char *p)
11454{
11455 if (!tree_fits_uhwi_p (t) || CHAR_TYPE_SIZE != HOST_BITS_PER_CHAR)
11456 return false;
11457
11458 *p = (char)tree_to_uhwi (t);
11459 return true;
11460}
11461
11462/* Return true if the builtin DECL is implemented in a standard library.
11463 Otherwise return false which doesn't guarantee it is not (thus the list
11464 of handled builtins below may be incomplete). */
11465
11466bool
11467builtin_with_linkage_p (tree decl)
11468{
11469 if (DECL_BUILT_IN_CLASS (decl) == BUILT_IN_NORMAL)
11470 switch (DECL_FUNCTION_CODE (decl))
11471 {
11472 CASE_FLT_FN (BUILT_IN_ACOS):
11473 CASE_FLT_FN_FLOATN_NX (BUILT_IN_ACOS):
11474 CASE_FLT_FN (BUILT_IN_ACOSH):
11475 CASE_FLT_FN_FLOATN_NX (BUILT_IN_ACOSH):
11476 CASE_FLT_FN (BUILT_IN_ASIN):
11477 CASE_FLT_FN_FLOATN_NX (BUILT_IN_ASIN):
11478 CASE_FLT_FN (BUILT_IN_ASINH):
11479 CASE_FLT_FN_FLOATN_NX (BUILT_IN_ASINH):
11480 CASE_FLT_FN (BUILT_IN_ATAN):
11481 CASE_FLT_FN_FLOATN_NX (BUILT_IN_ATAN):
11482 CASE_FLT_FN (BUILT_IN_ATANH):
11483 CASE_FLT_FN_FLOATN_NX (BUILT_IN_ATANH):
11484 CASE_FLT_FN (BUILT_IN_ATAN2):
11485 CASE_FLT_FN_FLOATN_NX (BUILT_IN_ATAN2):
11486 CASE_FLT_FN (BUILT_IN_CBRT):
11487 CASE_FLT_FN_FLOATN_NX (BUILT_IN_CBRT):
11488 CASE_FLT_FN (BUILT_IN_CEIL):
11489 CASE_FLT_FN_FLOATN_NX (BUILT_IN_CEIL):
11490 CASE_FLT_FN (BUILT_IN_COPYSIGN):
11491 CASE_FLT_FN_FLOATN_NX (BUILT_IN_COPYSIGN):
11492 CASE_FLT_FN (BUILT_IN_COS):
11493 CASE_FLT_FN_FLOATN_NX (BUILT_IN_COS):
11494 CASE_FLT_FN (BUILT_IN_COSH):
11495 CASE_FLT_FN_FLOATN_NX (BUILT_IN_COSH):
11496 CASE_FLT_FN (BUILT_IN_ERF):
11497 CASE_FLT_FN_FLOATN_NX (BUILT_IN_ERF):
11498 CASE_FLT_FN (BUILT_IN_ERFC):
11499 CASE_FLT_FN_FLOATN_NX (BUILT_IN_ERFC):
11500 CASE_FLT_FN (BUILT_IN_EXP):
11501 CASE_FLT_FN_FLOATN_NX (BUILT_IN_EXP):
11502 CASE_FLT_FN (BUILT_IN_EXP2):
11503 CASE_FLT_FN_FLOATN_NX (BUILT_IN_EXP2):
11504 CASE_FLT_FN (BUILT_IN_EXPM1):
11505 CASE_FLT_FN_FLOATN_NX (BUILT_IN_EXPM1):
11506 CASE_FLT_FN (BUILT_IN_FABS):
11507 CASE_FLT_FN_FLOATN_NX (BUILT_IN_FABS):
11508 CASE_FLT_FN (BUILT_IN_FDIM):
11509 CASE_FLT_FN_FLOATN_NX (BUILT_IN_FDIM):
11510 CASE_FLT_FN (BUILT_IN_FLOOR):
11511 CASE_FLT_FN_FLOATN_NX (BUILT_IN_FLOOR):
11512 CASE_FLT_FN (BUILT_IN_FMA):
11513 CASE_FLT_FN_FLOATN_NX (BUILT_IN_FMA):
11514 CASE_FLT_FN (BUILT_IN_FMAX):
11515 CASE_FLT_FN_FLOATN_NX (BUILT_IN_FMAX):
11516 CASE_FLT_FN (BUILT_IN_FMIN):
11517 CASE_FLT_FN_FLOATN_NX (BUILT_IN_FMIN):
11518 CASE_FLT_FN (BUILT_IN_FMOD):
11519 CASE_FLT_FN_FLOATN_NX (BUILT_IN_FMOD):
11520 CASE_FLT_FN (BUILT_IN_FREXP):
11521 CASE_FLT_FN_FLOATN_NX (BUILT_IN_FREXP):
11522 CASE_FLT_FN (BUILT_IN_HYPOT):
11523 CASE_FLT_FN_FLOATN_NX (BUILT_IN_HYPOT):
11524 CASE_FLT_FN (BUILT_IN_ILOGB):
11525 CASE_FLT_FN_FLOATN_NX (BUILT_IN_ILOGB):
11526 CASE_FLT_FN (BUILT_IN_LDEXP):
11527 CASE_FLT_FN_FLOATN_NX (BUILT_IN_LDEXP):
11528 CASE_FLT_FN (BUILT_IN_LGAMMA):
11529 CASE_FLT_FN_FLOATN_NX (BUILT_IN_LGAMMA):
11530 CASE_FLT_FN (BUILT_IN_LLRINT):
11531 CASE_FLT_FN_FLOATN_NX (BUILT_IN_LLRINT):
11532 CASE_FLT_FN (BUILT_IN_LLROUND):
11533 CASE_FLT_FN_FLOATN_NX (BUILT_IN_LLROUND):
11534 CASE_FLT_FN (BUILT_IN_LOG):
11535 CASE_FLT_FN_FLOATN_NX (BUILT_IN_LOG):
11536 CASE_FLT_FN (BUILT_IN_LOG10):
11537 CASE_FLT_FN_FLOATN_NX (BUILT_IN_LOG10):
11538 CASE_FLT_FN (BUILT_IN_LOG1P):
11539 CASE_FLT_FN_FLOATN_NX (BUILT_IN_LOG1P):
11540 CASE_FLT_FN (BUILT_IN_LOG2):
11541 CASE_FLT_FN_FLOATN_NX (BUILT_IN_LOG2):
11542 CASE_FLT_FN (BUILT_IN_LOGB):
11543 CASE_FLT_FN_FLOATN_NX (BUILT_IN_LOGB):
11544 CASE_FLT_FN (BUILT_IN_LRINT):
11545 CASE_FLT_FN_FLOATN_NX (BUILT_IN_LRINT):
11546 CASE_FLT_FN (BUILT_IN_LROUND):
11547 CASE_FLT_FN_FLOATN_NX (BUILT_IN_LROUND):
11548 CASE_FLT_FN (BUILT_IN_MODF):
11549 CASE_FLT_FN_FLOATN_NX (BUILT_IN_MODF):
11550 CASE_FLT_FN (BUILT_IN_NAN):
11551 CASE_FLT_FN_FLOATN_NX (BUILT_IN_NAN):
11552 CASE_FLT_FN (BUILT_IN_NEARBYINT):
11553 CASE_FLT_FN_FLOATN_NX (BUILT_IN_NEARBYINT):
11554 CASE_FLT_FN (BUILT_IN_NEXTAFTER):
11555 CASE_FLT_FN_FLOATN_NX (BUILT_IN_NEXTAFTER):
11556 CASE_FLT_FN (BUILT_IN_NEXTTOWARD):
11557 CASE_FLT_FN (BUILT_IN_POW):
11558 CASE_FLT_FN_FLOATN_NX (BUILT_IN_POW):
11559 CASE_FLT_FN (BUILT_IN_REMAINDER):
11560 CASE_FLT_FN_FLOATN_NX (BUILT_IN_REMAINDER):
11561 CASE_FLT_FN (BUILT_IN_REMQUO):
11562 CASE_FLT_FN_FLOATN_NX (BUILT_IN_REMQUO):
11563 CASE_FLT_FN (BUILT_IN_RINT):
11564 CASE_FLT_FN_FLOATN_NX (BUILT_IN_RINT):
11565 CASE_FLT_FN (BUILT_IN_ROUND):
11566 CASE_FLT_FN_FLOATN_NX (BUILT_IN_ROUND):
11567 CASE_FLT_FN (BUILT_IN_SCALBLN):
11568 CASE_FLT_FN_FLOATN_NX (BUILT_IN_SCALBLN):
11569 CASE_FLT_FN (BUILT_IN_SCALBN):
11570 CASE_FLT_FN_FLOATN_NX (BUILT_IN_SCALBN):
11571 CASE_FLT_FN (BUILT_IN_SIN):
11572 CASE_FLT_FN_FLOATN_NX (BUILT_IN_SIN):
11573 CASE_FLT_FN (BUILT_IN_SINH):
11574 CASE_FLT_FN_FLOATN_NX (BUILT_IN_SINH):
11575 CASE_FLT_FN (BUILT_IN_SINCOS):
11576 CASE_FLT_FN (BUILT_IN_SQRT):
11577 CASE_FLT_FN_FLOATN_NX (BUILT_IN_SQRT):
11578 CASE_FLT_FN (BUILT_IN_TAN):
11579 CASE_FLT_FN_FLOATN_NX (BUILT_IN_TAN):
11580 CASE_FLT_FN (BUILT_IN_TANH):
11581 CASE_FLT_FN_FLOATN_NX (BUILT_IN_TANH):
11582 CASE_FLT_FN (BUILT_IN_TGAMMA):
11583 CASE_FLT_FN_FLOATN_NX (BUILT_IN_TGAMMA):
11584 CASE_FLT_FN (BUILT_IN_TRUNC):
11585 CASE_FLT_FN_FLOATN_NX (BUILT_IN_TRUNC):
11586 return true;
11587
11588 case BUILT_IN_STPCPY:
11589 case BUILT_IN_STPNCPY:
11590 /* stpcpy is both referenced in libiberty's pex-win32.c and provided
11591 by libiberty's stpcpy.c for MinGW targets so we need to return true
11592 in order to be able to build libiberty in LTO mode for them. */
11593 return true;
11594
11595 default:
11596 break;
11597 }
11598 return false;
11599}
11600
11601/* Return true if OFFRNG is bounded to a subrange of offset values
11602 valid for the largest possible object. */
11603
11604bool
11605access_ref::offset_bounded () const
11606{
11607 tree min = TYPE_MIN_VALUE (ptrdiff_type_node);
11608 tree max = TYPE_MAX_VALUE (ptrdiff_type_node);
11609 return wi::to_offset (t: min) <= offrng[0] && offrng[1] <= wi::to_offset (t: max);
11610}
11611
11612/* If CALLEE has known side effects, fill in INFO and return true.
11613 See tree-ssa-structalias.cc:find_func_aliases
11614 for the list of builtins we might need to handle here. */
11615
11616attr_fnspec
11617builtin_fnspec (tree callee)
11618{
11619 built_in_function code = DECL_FUNCTION_CODE (decl: callee);
11620
11621 switch (code)
11622 {
11623 /* All the following functions read memory pointed to by
11624 their second argument and write memory pointed to by first
11625 argument.
11626 strcat/strncat additionally reads memory pointed to by the first
11627 argument. */
11628 case BUILT_IN_STRCAT:
11629 case BUILT_IN_STRCAT_CHK:
11630 return "1cW 1 ";
11631 case BUILT_IN_STRNCAT:
11632 case BUILT_IN_STRNCAT_CHK:
11633 return "1cW 13";
11634 case BUILT_IN_STRCPY:
11635 case BUILT_IN_STRCPY_CHK:
11636 return "1cO 1 ";
11637 case BUILT_IN_STPCPY:
11638 case BUILT_IN_STPCPY_CHK:
11639 return ".cO 1 ";
11640 case BUILT_IN_STRNCPY:
11641 case BUILT_IN_MEMCPY:
11642 case BUILT_IN_MEMMOVE:
11643 case BUILT_IN_TM_MEMCPY:
11644 case BUILT_IN_TM_MEMMOVE:
11645 case BUILT_IN_STRNCPY_CHK:
11646 case BUILT_IN_MEMCPY_CHK:
11647 case BUILT_IN_MEMMOVE_CHK:
11648 return "1cO313";
11649 case BUILT_IN_MEMPCPY:
11650 case BUILT_IN_MEMPCPY_CHK:
11651 return ".cO313";
11652 case BUILT_IN_STPNCPY:
11653 case BUILT_IN_STPNCPY_CHK:
11654 return ".cO313";
11655 case BUILT_IN_BCOPY:
11656 return ".c23O3";
11657 case BUILT_IN_BZERO:
11658 return ".cO2";
11659 case BUILT_IN_MEMCMP:
11660 case BUILT_IN_MEMCMP_EQ:
11661 case BUILT_IN_BCMP:
11662 case BUILT_IN_STRNCMP:
11663 case BUILT_IN_STRNCMP_EQ:
11664 case BUILT_IN_STRNCASECMP:
11665 return ".cR3R3";
11666
11667 /* The following functions read memory pointed to by their
11668 first argument. */
11669 CASE_BUILT_IN_TM_LOAD (1):
11670 CASE_BUILT_IN_TM_LOAD (2):
11671 CASE_BUILT_IN_TM_LOAD (4):
11672 CASE_BUILT_IN_TM_LOAD (8):
11673 CASE_BUILT_IN_TM_LOAD (FLOAT):
11674 CASE_BUILT_IN_TM_LOAD (DOUBLE):
11675 CASE_BUILT_IN_TM_LOAD (LDOUBLE):
11676 CASE_BUILT_IN_TM_LOAD (M64):
11677 CASE_BUILT_IN_TM_LOAD (M128):
11678 CASE_BUILT_IN_TM_LOAD (M256):
11679 case BUILT_IN_TM_LOG:
11680 case BUILT_IN_TM_LOG_1:
11681 case BUILT_IN_TM_LOG_2:
11682 case BUILT_IN_TM_LOG_4:
11683 case BUILT_IN_TM_LOG_8:
11684 case BUILT_IN_TM_LOG_FLOAT:
11685 case BUILT_IN_TM_LOG_DOUBLE:
11686 case BUILT_IN_TM_LOG_LDOUBLE:
11687 case BUILT_IN_TM_LOG_M64:
11688 case BUILT_IN_TM_LOG_M128:
11689 case BUILT_IN_TM_LOG_M256:
11690 return ".cR ";
11691
11692 case BUILT_IN_INDEX:
11693 case BUILT_IN_RINDEX:
11694 case BUILT_IN_STRCHR:
11695 case BUILT_IN_STRLEN:
11696 case BUILT_IN_STRRCHR:
11697 return ".cR ";
11698 case BUILT_IN_STRNLEN:
11699 return ".cR2";
11700
11701 /* These read memory pointed to by the first argument.
11702 Allocating memory does not have any side-effects apart from
11703 being the definition point for the pointer.
11704 Unix98 specifies that errno is set on allocation failure. */
11705 case BUILT_IN_STRDUP:
11706 return "mCR ";
11707 case BUILT_IN_STRNDUP:
11708 return "mCR2";
11709 /* Allocating memory does not have any side-effects apart from
11710 being the definition point for the pointer. */
11711 case BUILT_IN_MALLOC:
11712 case BUILT_IN_ALIGNED_ALLOC:
11713 case BUILT_IN_CALLOC:
11714 case BUILT_IN_GOMP_ALLOC:
11715 return "mC";
11716 CASE_BUILT_IN_ALLOCA:
11717 return "mc";
11718 /* These read memory pointed to by the first argument with size
11719 in the third argument. */
11720 case BUILT_IN_MEMCHR:
11721 return ".cR3";
11722 /* These read memory pointed to by the first and second arguments. */
11723 case BUILT_IN_STRSTR:
11724 case BUILT_IN_STRPBRK:
11725 case BUILT_IN_STRCASECMP:
11726 case BUILT_IN_STRCSPN:
11727 case BUILT_IN_STRSPN:
11728 case BUILT_IN_STRCMP:
11729 case BUILT_IN_STRCMP_EQ:
11730 return ".cR R ";
11731 /* Freeing memory kills the pointed-to memory. More importantly
11732 the call has to serve as a barrier for moving loads and stores
11733 across it. */
11734 case BUILT_IN_STACK_RESTORE:
11735 case BUILT_IN_FREE:
11736 case BUILT_IN_GOMP_FREE:
11737 return ".co ";
11738 case BUILT_IN_VA_END:
11739 return ".cO ";
11740 /* Realloc serves both as allocation point and deallocation point. */
11741 case BUILT_IN_REALLOC:
11742 return ".Cw ";
11743 case BUILT_IN_GAMMA_R:
11744 case BUILT_IN_GAMMAF_R:
11745 case BUILT_IN_GAMMAL_R:
11746 case BUILT_IN_LGAMMA_R:
11747 case BUILT_IN_LGAMMAF_R:
11748 case BUILT_IN_LGAMMAL_R:
11749 return ".C. Ot";
11750 case BUILT_IN_FREXP:
11751 case BUILT_IN_FREXPF:
11752 case BUILT_IN_FREXPL:
11753 case BUILT_IN_MODF:
11754 case BUILT_IN_MODFF:
11755 case BUILT_IN_MODFL:
11756 return ".c. Ot";
11757 case BUILT_IN_REMQUO:
11758 case BUILT_IN_REMQUOF:
11759 case BUILT_IN_REMQUOL:
11760 return ".c. . Ot";
11761 case BUILT_IN_SINCOS:
11762 case BUILT_IN_SINCOSF:
11763 case BUILT_IN_SINCOSL:
11764 return ".c. OtOt";
11765 case BUILT_IN_MEMSET:
11766 case BUILT_IN_MEMSET_CHK:
11767 case BUILT_IN_TM_MEMSET:
11768 return "1cO3";
11769 CASE_BUILT_IN_TM_STORE (1):
11770 CASE_BUILT_IN_TM_STORE (2):
11771 CASE_BUILT_IN_TM_STORE (4):
11772 CASE_BUILT_IN_TM_STORE (8):
11773 CASE_BUILT_IN_TM_STORE (FLOAT):
11774 CASE_BUILT_IN_TM_STORE (DOUBLE):
11775 CASE_BUILT_IN_TM_STORE (LDOUBLE):
11776 CASE_BUILT_IN_TM_STORE (M64):
11777 CASE_BUILT_IN_TM_STORE (M128):
11778 CASE_BUILT_IN_TM_STORE (M256):
11779 return ".cO ";
11780 case BUILT_IN_STACK_SAVE:
11781 case BUILT_IN_RETURN:
11782 case BUILT_IN_EH_POINTER:
11783 case BUILT_IN_EH_FILTER:
11784 case BUILT_IN_UNWIND_RESUME:
11785 case BUILT_IN_CXA_END_CLEANUP:
11786 case BUILT_IN_EH_COPY_VALUES:
11787 case BUILT_IN_FRAME_ADDRESS:
11788 case BUILT_IN_APPLY_ARGS:
11789 case BUILT_IN_ASAN_BEFORE_DYNAMIC_INIT:
11790 case BUILT_IN_ASAN_AFTER_DYNAMIC_INIT:
11791 case BUILT_IN_PREFETCH:
11792 case BUILT_IN_DWARF_CFA:
11793 case BUILT_IN_RETURN_ADDRESS:
11794 return ".c";
11795 case BUILT_IN_ASSUME_ALIGNED:
11796 case BUILT_IN_EXPECT:
11797 case BUILT_IN_EXPECT_WITH_PROBABILITY:
11798 return "1cX ";
11799 /* But posix_memalign stores a pointer into the memory pointed to
11800 by its first argument. */
11801 case BUILT_IN_POSIX_MEMALIGN:
11802 return ".cOt";
11803
11804 default:
11805 return "";
11806 }
11807}
11808

source code of gcc/builtins.cc