Line data Source code
1 : /* Expand builtin functions.
2 : Copyright (C) 1988-2026 Free Software Foundation, Inc.
3 :
4 : This file is part of GCC.
5 :
6 : GCC is free software; you can redistribute it and/or modify it under
7 : the terms of the GNU General Public License as published by the Free
8 : Software Foundation; either version 3, or (at your option) any later
9 : version.
10 :
11 : GCC is distributed in the hope that it will be useful, but WITHOUT ANY
12 : WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 : FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 : for more details.
15 :
16 : You should have received a copy of the GNU General Public License
17 : along 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 "tree-eh.h"
34 : #include "predict.h"
35 : #include "tm_p.h"
36 : #include "stringpool.h"
37 : #include "tree-vrp.h"
38 : #include "tree-ssanames.h"
39 : #include "expmed.h"
40 : #include "optabs.h"
41 : #include "emit-rtl.h"
42 : #include "recog.h"
43 : #include "diagnostic-core.h"
44 : #include "alias.h"
45 : #include "fold-const.h"
46 : #include "fold-const-call.h"
47 : #include "gimple-ssa-warn-access.h"
48 : #include "stor-layout.h"
49 : #include "calls.h"
50 : #include "varasm.h"
51 : #include "tree-object-size.h"
52 : #include "tree-ssa-strlen.h"
53 : #include "realmpfr.h"
54 : #include "cfgrtl.h"
55 : #include "except.h"
56 : #include "dojump.h"
57 : #include "explow.h"
58 : #include "stmt.h"
59 : #include "expr.h"
60 : #include "libfuncs.h"
61 : #include "output.h"
62 : #include "typeclass.h"
63 : #include "langhooks.h"
64 : #include "value-prof.h"
65 : #include "builtins.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 "ipa-strub.h" /* strub_watermark_parm() */
75 : #include "gomp-constants.h"
76 : #include "omp-general.h"
77 : #include "tree-dfa.h"
78 : #include "gimple-ssa.h"
79 : #include "tree-ssa-live.h"
80 : #include "tree-outof-ssa.h"
81 : #include "attr-fnspec.h"
82 : #include "demangle.h"
83 : #include "gimple-range.h"
84 : #include "pointer-query.h"
85 :
86 : struct target_builtins default_target_builtins;
87 : #if SWITCHABLE_TARGET
88 : struct target_builtins *this_target_builtins = &default_target_builtins;
89 : #endif
90 :
91 : /* Define the names of the builtin function types and codes. */
92 : const char *const built_in_class_names[BUILT_IN_LAST]
93 : = {"NOT_BUILT_IN", "BUILT_IN_FRONTEND", "BUILT_IN_MD", "BUILT_IN_NORMAL"};
94 :
95 : #define DEF_BUILTIN(X, N, C, T, LT, B, F, NA, AT, IM, COND) #X,
96 : const char * built_in_names[(int) END_BUILTINS] =
97 : {
98 : #include "builtins.def"
99 : };
100 :
101 : /* Setup an array of builtin_info_type, make sure each element decl is
102 : initialized to NULL_TREE. */
103 : builtin_info_type builtin_info[(int)END_BUILTINS];
104 :
105 : /* Non-zero if __builtin_constant_p should be folded right away. */
106 : bool force_folding_builtin_constant_p;
107 :
108 : static int target_char_cast (tree, char *);
109 : static int apply_args_size (void);
110 : static int apply_result_size (void);
111 : static rtx result_vector (int, rtx);
112 : static void expand_builtin_prefetch (tree);
113 : static rtx expand_builtin_apply_args (void);
114 : static rtx expand_builtin_apply_args_1 (void);
115 : static rtx expand_builtin_apply (rtx, rtx, rtx);
116 : static void expand_builtin_return (rtx);
117 : static rtx expand_builtin_classify_type (tree);
118 : static rtx expand_builtin_mathfn_3 (tree, rtx, rtx);
119 : static rtx expand_builtin_mathfn_ternary (tree, rtx, rtx);
120 : static rtx expand_builtin_interclass_mathfn (tree, rtx);
121 : static rtx expand_builtin_sincos (tree);
122 : static rtx expand_builtin_fegetround (tree, rtx, machine_mode);
123 : static rtx expand_builtin_feclear_feraise_except (tree, rtx, machine_mode,
124 : optab);
125 : static rtx expand_builtin_cexpi (tree, rtx);
126 : static rtx expand_builtin_issignaling (tree, rtx);
127 : static rtx expand_builtin_int_roundingfn (tree, rtx);
128 : static rtx expand_builtin_int_roundingfn_2 (tree, rtx);
129 : static rtx expand_builtin_next_arg (void);
130 : static rtx expand_builtin_va_start (tree);
131 : static rtx expand_builtin_va_end (tree);
132 : static rtx expand_builtin_va_copy (tree);
133 : static rtx inline_expand_builtin_bytecmp (tree, rtx);
134 : static rtx expand_builtin_strcmp (tree, rtx);
135 : static rtx expand_builtin_strncmp (tree, rtx, machine_mode);
136 : static rtx expand_builtin_memcpy (tree, rtx);
137 : static rtx expand_builtin_memory_copy_args (tree dest, tree src, tree len,
138 : rtx target, tree exp,
139 : memop_ret retmode,
140 : bool might_overlap);
141 : static rtx expand_builtin_memmove (tree, rtx);
142 : static rtx expand_builtin_mempcpy (tree, rtx);
143 : static rtx expand_builtin_mempcpy_args (tree, tree, tree, rtx, tree, memop_ret);
144 : static rtx expand_builtin_strcpy (tree, rtx);
145 : static rtx expand_builtin_strcpy_args (tree, tree, tree, rtx);
146 : static rtx expand_builtin_stpcpy (tree, rtx, machine_mode);
147 : static rtx expand_builtin_strncpy (tree, rtx);
148 : static rtx expand_builtin_memset_args (tree, tree, tree, rtx, machine_mode, tree);
149 : static rtx expand_builtin_bzero (tree);
150 : static rtx expand_builtin_strlen (tree, rtx, machine_mode);
151 : static rtx expand_builtin_strnlen (tree, rtx, machine_mode);
152 : static rtx expand_builtin_alloca (tree);
153 : static rtx expand_builtin_unop (machine_mode, tree, rtx, rtx, optab);
154 : static rtx expand_builtin_frame_address (tree, tree);
155 : static rtx expand_builtin_stack_address ();
156 : static tree stabilize_va_list_loc (location_t, tree, int);
157 : static rtx expand_builtin_expect (tree, rtx);
158 : static rtx expand_builtin_expect_with_probability (tree, rtx);
159 : static tree fold_builtin_classify_type (tree);
160 : static tree fold_builtin_strlen (location_t, tree, tree, tree);
161 : static tree fold_builtin_inf (location_t, tree, int);
162 : static tree rewrite_call_expr (location_t, tree, int, tree, int, ...);
163 : static bool validate_arg (const_tree, enum tree_code code);
164 : static rtx expand_builtin_fabs (tree, rtx, rtx);
165 : static rtx expand_builtin_signbit (tree, rtx);
166 : static tree fold_builtin_memcmp (location_t, tree, tree, tree);
167 : static tree fold_builtin_isascii (location_t, tree);
168 : static tree fold_builtin_toascii (location_t, tree);
169 : static tree fold_builtin_isdigit (location_t, tree);
170 : static tree fold_builtin_fabs (location_t, tree, tree);
171 : static tree fold_builtin_abs (location_t, tree, tree);
172 : static tree fold_builtin_unordered_cmp (location_t, tree, tree, tree, enum tree_code,
173 : enum tree_code);
174 : static tree fold_builtin_iseqsig (location_t, tree, tree);
175 : static tree fold_builtin_varargs (location_t, tree, tree*, int);
176 :
177 : static tree fold_builtin_strpbrk (location_t, tree, tree, tree, tree);
178 : static tree fold_builtin_strspn (location_t, tree, tree, tree, tree);
179 : static tree fold_builtin_strcspn (location_t, tree, tree, tree, tree);
180 :
181 : static rtx expand_builtin_object_size (tree);
182 : static rtx expand_builtin_memory_chk (tree, rtx, machine_mode,
183 : enum built_in_function);
184 : static void maybe_emit_chk_warning (tree, enum built_in_function);
185 : static void maybe_emit_sprintf_chk_warning (tree, enum built_in_function);
186 : static tree fold_builtin_object_size (tree, tree, enum built_in_function);
187 :
188 : unsigned HOST_WIDE_INT target_newline;
189 : unsigned HOST_WIDE_INT target_percent;
190 : static unsigned HOST_WIDE_INT target_c;
191 : static unsigned HOST_WIDE_INT target_s;
192 : char target_percent_c[3];
193 : char target_percent_s[3];
194 : char target_percent_s_newline[4];
195 : static tree do_mpfr_remquo (tree, tree, tree);
196 : static tree do_mpfr_lgamma_r (tree, tree, tree);
197 : static void expand_builtin_sync_synchronize (void);
198 :
199 : /* Return true if NAME starts with __builtin_ or __sync_. */
200 :
201 : static bool
202 536578 : is_builtin_name (const char *name)
203 : {
204 536578 : return (startswith (name, "__builtin_")
205 194775 : || startswith (name, "__sync_")
206 730488 : || startswith (name, "__atomic_"));
207 : }
208 :
209 : /* Return true if NODE should be considered for inline expansion regardless
210 : of the optimization level. This means whenever a function is invoked with
211 : its "internal" name, which normally contains the prefix "__builtin". */
212 :
213 : bool
214 536578 : called_as_built_in (tree node)
215 : {
216 : /* Note that we must use DECL_NAME, not DECL_ASSEMBLER_NAME_SET_P since
217 : we want the name used to call the function, not the name it
218 : will have. */
219 536578 : const char *name = IDENTIFIER_POINTER (DECL_NAME (node));
220 536578 : return is_builtin_name (name);
221 : }
222 :
223 : /* Compute values M and N such that M divides (address of EXP - N) and such
224 : that N < M. If these numbers can be determined, store M in alignp and N in
225 : *BITPOSP and return true. Otherwise return false and store BITS_PER_UNIT to
226 : *alignp and any bit-offset to *bitposp.
227 :
228 : Note that the address (and thus the alignment) computed here is based
229 : on the address to which a symbol resolves, whereas DECL_ALIGN is based
230 : on the address at which an object is actually located. These two
231 : addresses are not always the same. For example, on ARM targets,
232 : the address &foo of a Thumb function foo() has the lowest bit set,
233 : whereas foo() itself starts on an even address.
234 :
235 : If ADDR_P is true we are taking the address of the memory reference EXP
236 : and thus cannot rely on the access taking place. */
237 :
238 : bool
239 113259061 : get_object_alignment_2 (tree exp, unsigned int *alignp,
240 : unsigned HOST_WIDE_INT *bitposp, bool addr_p)
241 : {
242 113259061 : poly_int64 bitsize, bitpos;
243 113259061 : tree offset;
244 113259061 : machine_mode mode;
245 113259061 : int unsignedp, reversep, volatilep;
246 113259061 : unsigned int align = BITS_PER_UNIT;
247 113259061 : bool known_alignment = false;
248 :
249 : /* Get the innermost object and the constant (bitpos) and possibly
250 : variable (offset) offset of the access. */
251 113259061 : exp = get_inner_reference (exp, &bitsize, &bitpos, &offset, &mode,
252 : &unsignedp, &reversep, &volatilep);
253 :
254 : /* Extract alignment information from the innermost object and
255 : possibly adjust bitpos and offset. */
256 113259061 : if (TREE_CODE (exp) == FUNCTION_DECL)
257 : {
258 : /* Function addresses can encode extra information besides their
259 : alignment. However, if TARGET_PTRMEMFUNC_VBIT_LOCATION
260 : allows the low bit to be used as a virtual bit, we know
261 : that the address itself must be at least 2-byte aligned. */
262 : if (TARGET_PTRMEMFUNC_VBIT_LOCATION == ptrmemfunc_vbit_in_pfn)
263 : align = 2 * BITS_PER_UNIT;
264 : }
265 112792431 : else if (TREE_CODE (exp) == LABEL_DECL)
266 : ;
267 112755512 : else if (TREE_CODE (exp) == CONST_DECL)
268 : {
269 : /* The alignment of a CONST_DECL is determined by its initializer. */
270 59818 : exp = DECL_INITIAL (exp);
271 59818 : align = TYPE_ALIGN (TREE_TYPE (exp));
272 59818 : if (CONSTANT_CLASS_P (exp))
273 59817 : align = targetm.constant_alignment (exp, align);
274 :
275 : known_alignment = true;
276 : }
277 112695694 : else if (DECL_P (exp))
278 : {
279 67441785 : align = DECL_ALIGN (exp);
280 : known_alignment = true;
281 : }
282 45253909 : else if (TREE_CODE (exp) == INDIRECT_REF
283 45252853 : || TREE_CODE (exp) == MEM_REF
284 5424235 : || TREE_CODE (exp) == TARGET_MEM_REF)
285 : {
286 43534513 : tree addr = TREE_OPERAND (exp, 0);
287 43534513 : unsigned ptr_align;
288 43534513 : unsigned HOST_WIDE_INT ptr_bitpos;
289 43534513 : unsigned HOST_WIDE_INT ptr_bitmask = ~0;
290 :
291 : /* If the address is explicitly aligned, handle that. */
292 43534513 : if (TREE_CODE (addr) == BIT_AND_EXPR
293 43534513 : && TREE_CODE (TREE_OPERAND (addr, 1)) == INTEGER_CST)
294 : {
295 88 : ptr_bitmask = TREE_INT_CST_LOW (TREE_OPERAND (addr, 1));
296 88 : ptr_bitmask *= BITS_PER_UNIT;
297 88 : align = least_bit_hwi (ptr_bitmask);
298 88 : addr = TREE_OPERAND (addr, 0);
299 : }
300 :
301 43534513 : known_alignment
302 43534513 : = get_pointer_alignment_1 (addr, &ptr_align, &ptr_bitpos);
303 43534513 : align = MAX (ptr_align, align);
304 :
305 : /* Re-apply explicit alignment to the bitpos. */
306 43534513 : ptr_bitpos &= ptr_bitmask;
307 :
308 : /* The alignment of the pointer operand in a TARGET_MEM_REF
309 : has to take the variable offset parts into account. */
310 43534513 : if (TREE_CODE (exp) == TARGET_MEM_REF)
311 : {
312 3704839 : if (TMR_INDEX (exp))
313 : {
314 1607280 : unsigned HOST_WIDE_INT step = 1;
315 1607280 : if (TMR_STEP (exp))
316 1474699 : step = TREE_INT_CST_LOW (TMR_STEP (exp));
317 1607280 : align = MIN (align, least_bit_hwi (step) * BITS_PER_UNIT);
318 : }
319 3704839 : if (TMR_INDEX2 (exp))
320 41779 : align = BITS_PER_UNIT;
321 : known_alignment = false;
322 : }
323 :
324 : /* When EXP is an actual memory reference then we can use
325 : TYPE_ALIGN of a pointer indirection to derive alignment.
326 : Do so only if get_pointer_alignment_1 did not reveal absolute
327 : alignment knowledge and if using that alignment would
328 : improve the situation. */
329 43534513 : unsigned int talign;
330 43534513 : if (!addr_p && !known_alignment
331 41047675 : && (talign = min_align_of_type (TREE_TYPE (exp)) * BITS_PER_UNIT)
332 84582182 : && talign > align)
333 : align = talign;
334 : else
335 : {
336 : /* Else adjust bitpos accordingly. */
337 11861408 : bitpos += ptr_bitpos;
338 11861408 : if (TREE_CODE (exp) == MEM_REF
339 11861408 : || TREE_CODE (exp) == TARGET_MEM_REF)
340 11860352 : bitpos += mem_ref_offset (exp).force_shwi () * BITS_PER_UNIT;
341 : }
342 43534513 : }
343 1719396 : else if (TREE_CODE (exp) == STRING_CST)
344 : {
345 : /* STRING_CST are the only constant objects we allow to be not
346 : wrapped inside a CONST_DECL. */
347 1718776 : align = TYPE_ALIGN (TREE_TYPE (exp));
348 1718776 : if (CONSTANT_CLASS_P (exp))
349 1718776 : align = targetm.constant_alignment (exp, align);
350 :
351 : known_alignment = true;
352 : }
353 :
354 : /* If there is a non-constant offset part extract the maximum
355 : alignment that can prevail. */
356 113259061 : if (offset)
357 : {
358 10028514 : unsigned int trailing_zeros = tree_ctz (offset);
359 10028514 : if (trailing_zeros < HOST_BITS_PER_INT)
360 : {
361 10028436 : unsigned int inner = (1U << trailing_zeros) * BITS_PER_UNIT;
362 10028436 : if (inner)
363 10028436 : align = MIN (align, inner);
364 : }
365 : }
366 :
367 : /* Account for the alignment of runtime coefficients, so that the constant
368 : bitpos is guaranteed to be accurate. */
369 113259061 : unsigned int alt_align = ::known_alignment (bitpos - bitpos.coeffs[0]);
370 113259061 : if (alt_align != 0 && alt_align < align)
371 : {
372 : align = alt_align;
373 : known_alignment = false;
374 : }
375 :
376 113259061 : *alignp = align;
377 113259061 : *bitposp = bitpos.coeffs[0] & (align - 1);
378 113259061 : return known_alignment;
379 : }
380 :
381 : /* For a memory reference expression EXP compute values M and N such that M
382 : divides (&EXP - N) and such that N < M. If these numbers can be determined,
383 : store M in alignp and N in *BITPOSP and return true. Otherwise return false
384 : and store BITS_PER_UNIT to *alignp and any bit-offset to *bitposp. */
385 :
386 : bool
387 89834413 : get_object_alignment_1 (tree exp, unsigned int *alignp,
388 : unsigned HOST_WIDE_INT *bitposp)
389 : {
390 : /* Strip a WITH_SIZE_EXPR, get_inner_reference doesn't know how to deal
391 : with it. */
392 89834413 : if (TREE_CODE (exp) == WITH_SIZE_EXPR)
393 0 : exp = TREE_OPERAND (exp, 0);
394 89834413 : return get_object_alignment_2 (exp, alignp, bitposp, false);
395 : }
396 :
397 : /* Return the alignment in bits of EXP, an object. */
398 :
399 : unsigned int
400 37092734 : get_object_alignment (tree exp)
401 : {
402 37092734 : unsigned HOST_WIDE_INT bitpos = 0;
403 37092734 : unsigned int align;
404 :
405 37092734 : get_object_alignment_1 (exp, &align, &bitpos);
406 :
407 : /* align and bitpos now specify known low bits of the pointer.
408 : ptr & (align - 1) == bitpos. */
409 :
410 37092734 : if (bitpos != 0)
411 2777629 : align = least_bit_hwi (bitpos);
412 37092734 : return align;
413 : }
414 :
415 : /* For a pointer valued expression EXP compute values M and N such that M
416 : divides (EXP - N) and such that N < M. If these numbers can be determined,
417 : store M in alignp and N in *BITPOSP and return true. Return false if
418 : the results are just a conservative approximation.
419 :
420 : If EXP is not a pointer, false is returned too. */
421 :
422 : bool
423 86052519 : get_pointer_alignment_1 (tree exp, unsigned int *alignp,
424 : unsigned HOST_WIDE_INT *bitposp)
425 : {
426 86052519 : STRIP_NOPS (exp);
427 :
428 86052519 : if (TREE_CODE (exp) == ADDR_EXPR)
429 23423009 : return get_object_alignment_2 (TREE_OPERAND (exp, 0),
430 23423009 : alignp, bitposp, true);
431 62629510 : else if (TREE_CODE (exp) == POINTER_PLUS_EXPR)
432 : {
433 1032010 : unsigned int align;
434 1032010 : unsigned HOST_WIDE_INT bitpos;
435 1032010 : bool res = get_pointer_alignment_1 (TREE_OPERAND (exp, 0),
436 : &align, &bitpos);
437 1032010 : if (TREE_CODE (TREE_OPERAND (exp, 1)) == INTEGER_CST)
438 3758 : bitpos += TREE_INT_CST_LOW (TREE_OPERAND (exp, 1)) * BITS_PER_UNIT;
439 : else
440 : {
441 1028252 : unsigned int trailing_zeros = tree_ctz (TREE_OPERAND (exp, 1));
442 1028252 : if (trailing_zeros < HOST_BITS_PER_INT)
443 : {
444 1028244 : unsigned int inner = (1U << trailing_zeros) * BITS_PER_UNIT;
445 1028244 : if (inner)
446 1028244 : align = MIN (align, inner);
447 : }
448 : }
449 1032010 : *alignp = align;
450 1032010 : *bitposp = bitpos & (align - 1);
451 1032010 : return res;
452 : }
453 61597500 : else if (TREE_CODE (exp) == SSA_NAME
454 61597500 : && POINTER_TYPE_P (TREE_TYPE (exp)))
455 : {
456 59224138 : unsigned int ptr_align, ptr_misalign;
457 59224138 : struct ptr_info_def *pi = SSA_NAME_PTR_INFO (exp);
458 :
459 59224138 : if (pi && get_ptr_info_alignment (pi, &ptr_align, &ptr_misalign))
460 : {
461 6501205 : *bitposp = ptr_misalign * BITS_PER_UNIT;
462 6501205 : *alignp = ptr_align * BITS_PER_UNIT;
463 : /* Make sure to return a sensible alignment when the multiplication
464 : by BITS_PER_UNIT overflowed. */
465 6501205 : if (*alignp == 0)
466 30 : *alignp = 1u << (HOST_BITS_PER_INT - 1);
467 : /* We cannot really tell whether this result is an approximation. */
468 : return false;
469 : }
470 : else
471 : {
472 52722933 : *bitposp = 0;
473 52722933 : *alignp = BITS_PER_UNIT;
474 52722933 : return false;
475 : }
476 : }
477 2373362 : else if (TREE_CODE (exp) == INTEGER_CST)
478 : {
479 18212 : *alignp = BIGGEST_ALIGNMENT;
480 18212 : *bitposp = ((TREE_INT_CST_LOW (exp) * BITS_PER_UNIT)
481 18212 : & (BIGGEST_ALIGNMENT - 1));
482 18212 : return true;
483 : }
484 :
485 2355150 : *bitposp = 0;
486 2355150 : *alignp = BITS_PER_UNIT;
487 2355150 : return false;
488 : }
489 :
490 : /* Return the alignment in bits of EXP, a pointer valued expression.
491 : The alignment returned is, by default, the alignment of the thing that
492 : EXP points to. If it is not a POINTER_TYPE, 0 is returned.
493 :
494 : Otherwise, look at the expression to see if we can do better, i.e., if the
495 : expression is actually pointing at an object whose alignment is tighter. */
496 :
497 : unsigned int
498 11718229 : get_pointer_alignment (tree exp)
499 : {
500 11718229 : unsigned HOST_WIDE_INT bitpos = 0;
501 11718229 : unsigned int align;
502 :
503 11718229 : get_pointer_alignment_1 (exp, &align, &bitpos);
504 :
505 : /* align and bitpos now specify known low bits of the pointer.
506 : ptr & (align - 1) == bitpos. */
507 :
508 11718229 : if (bitpos != 0)
509 79994 : align = least_bit_hwi (bitpos);
510 :
511 11718229 : return align;
512 : }
513 :
514 : /* Return the number of leading non-zero elements in the sequence
515 : [ PTR, PTR + MAXELTS ) where each element's size is ELTSIZE bytes.
516 : ELTSIZE must be a power of 2 less than 8. Used by c_strlen. */
517 :
518 : unsigned
519 775613 : string_length (const void *ptr, unsigned eltsize, unsigned maxelts)
520 : {
521 775613 : gcc_checking_assert (eltsize == 1 || eltsize == 2 || eltsize == 4);
522 :
523 775613 : unsigned n;
524 :
525 775613 : if (eltsize == 1)
526 : {
527 : /* Optimize the common case of plain char. */
528 244955405 : for (n = 0; n < maxelts; n++)
529 : {
530 244864951 : const char *elt = (const char*) ptr + n;
531 244864951 : if (!*elt)
532 : break;
533 : }
534 : }
535 : else
536 : {
537 590 : for (n = 0; n < maxelts; n++)
538 : {
539 566 : const char *elt = (const char*) ptr + n * eltsize;
540 566 : if (!memcmp (elt, "\0\0\0\0", eltsize))
541 : break;
542 : }
543 : }
544 775613 : return n;
545 : }
546 :
547 : /* Compute the length of a null-terminated character string or wide
548 : character string handling character sizes of 1, 2, and 4 bytes.
549 : TREE_STRING_LENGTH is not the right way because it evaluates to
550 : the size of the character array in bytes (as opposed to characters)
551 : and because it can contain a zero byte in the middle.
552 :
553 : ONLY_VALUE should be nonzero if the result is not going to be emitted
554 : into the instruction stream and zero if it is going to be expanded.
555 : E.g. with i++ ? "foo" : "bar", if ONLY_VALUE is nonzero, constant 3
556 : is returned, otherwise NULL, since
557 : len = c_strlen (ARG, 1); if (len) expand_expr (len, ...); would not
558 : evaluate the side-effects.
559 :
560 : If ONLY_VALUE is two then we do not emit warnings about out-of-bound
561 : accesses. Note that this implies the result is not going to be emitted
562 : into the instruction stream.
563 :
564 : Additional information about the string accessed may be recorded
565 : in DATA. For example, if ARG references an unterminated string,
566 : then the declaration will be stored in the DECL field. If the
567 : length of the unterminated string can be determined, it'll be
568 : stored in the LEN field. Note this length could well be different
569 : than what a C strlen call would return.
570 :
571 : ELTSIZE is 1 for normal single byte character strings, and 2 or
572 : 4 for wide character strings. ELTSIZE is by default 1.
573 :
574 : The value returned is of type `ssizetype'. */
575 :
576 : tree
577 2640648 : c_strlen (tree arg, int only_value, c_strlen_data *data, unsigned eltsize)
578 : {
579 : /* If we were not passed a DATA pointer, then get one to a local
580 : structure. That avoids having to check DATA for NULL before
581 : each time we want to use it. */
582 2640648 : c_strlen_data local_strlen_data = { };
583 2640648 : if (!data)
584 606624 : data = &local_strlen_data;
585 :
586 2640648 : gcc_checking_assert (eltsize == 1 || eltsize == 2 || eltsize == 4);
587 :
588 2640648 : tree src = STRIP_NOPS (arg);
589 2640648 : if (TREE_CODE (src) == COND_EXPR
590 2640648 : && (only_value || !TREE_SIDE_EFFECTS (TREE_OPERAND (src, 0))))
591 : {
592 690 : tree len1, len2;
593 :
594 690 : len1 = c_strlen (TREE_OPERAND (src, 1), only_value, data, eltsize);
595 690 : len2 = c_strlen (TREE_OPERAND (src, 2), only_value, data, eltsize);
596 690 : if (tree_int_cst_equal (len1, len2))
597 : return len1;
598 : }
599 :
600 2640482 : if (TREE_CODE (src) == COMPOUND_EXPR
601 2640482 : && (only_value || !TREE_SIDE_EFFECTS (TREE_OPERAND (src, 0))))
602 45 : return c_strlen (TREE_OPERAND (src, 1), only_value, data, eltsize);
603 :
604 2640437 : location_t loc = EXPR_LOC_OR_LOC (src, input_location);
605 :
606 : /* Offset from the beginning of the string in bytes. */
607 2640437 : tree byteoff;
608 2640437 : tree memsize;
609 2640437 : tree decl;
610 2640437 : src = string_constant (src, &byteoff, &memsize, &decl);
611 2640437 : if (src == 0)
612 : return NULL_TREE;
613 :
614 : /* Determine the size of the string element. */
615 791860 : if (eltsize != tree_to_uhwi (TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (src)))))
616 : return NULL_TREE;
617 :
618 : /* Set MAXELTS to ARRAY_SIZE (SRC) - 1, the maximum possible
619 : length of SRC. Prefer TYPE_SIZE() to TREE_STRING_LENGTH() if possible
620 : in case the latter is less than the size of the array, such as when
621 : SRC refers to a short string literal used to initialize a large array.
622 : In that case, the elements of the array after the terminating NUL are
623 : all NUL. */
624 779441 : HOST_WIDE_INT strelts = TREE_STRING_LENGTH (src);
625 779441 : strelts = strelts / eltsize;
626 :
627 779441 : if (!tree_fits_uhwi_p (memsize))
628 : return NULL_TREE;
629 :
630 779441 : HOST_WIDE_INT maxelts = tree_to_uhwi (memsize) / eltsize;
631 :
632 : /* PTR can point to the byte representation of any string type, including
633 : char* and wchar_t*. */
634 779441 : const char *ptr = TREE_STRING_POINTER (src);
635 :
636 779441 : if (byteoff && TREE_CODE (byteoff) != INTEGER_CST)
637 : {
638 : /* The code below works only for single byte character types. */
639 5050 : if (eltsize != 1)
640 : return NULL_TREE;
641 :
642 : /* If the string has an internal NUL character followed by any
643 : non-NUL characters (e.g., "foo\0bar"), we can't compute
644 : the offset to the following NUL if we don't know where to
645 : start searching for it. */
646 5050 : unsigned len = string_length (ptr, eltsize, strelts);
647 :
648 : /* Return when an embedded null character is found or none at all.
649 : In the latter case, set the DECL/LEN field in the DATA structure
650 : so that callers may examine them. */
651 5050 : if (len + 1 < strelts)
652 : return NULL_TREE;
653 4480 : else if (len >= maxelts)
654 : {
655 1102 : data->decl = decl;
656 1102 : data->off = byteoff;
657 1102 : data->minlen = ssize_int (len);
658 1102 : return NULL_TREE;
659 : }
660 :
661 : /* For empty strings the result should be zero. */
662 3378 : if (len == 0)
663 39 : return ssize_int (0);
664 :
665 : /* We don't know the starting offset, but we do know that the string
666 : has no internal zero bytes. If the offset falls within the bounds
667 : of the string subtract the offset from the length of the string,
668 : and return that. Otherwise the length is zero. Take care to
669 : use SAVE_EXPR in case the OFFSET has side-effects. */
670 3339 : tree offsave = TREE_SIDE_EFFECTS (byteoff) ? save_expr (byteoff)
671 : : byteoff;
672 3339 : offsave = fold_convert_loc (loc, sizetype, offsave);
673 3339 : tree condexp = fold_build2_loc (loc, LE_EXPR, boolean_type_node, offsave,
674 3339 : size_int (len));
675 3339 : tree lenexp = fold_build2_loc (loc, MINUS_EXPR, sizetype, size_int (len),
676 : offsave);
677 3339 : lenexp = fold_convert_loc (loc, ssizetype, lenexp);
678 3339 : return fold_build3_loc (loc, COND_EXPR, ssizetype, condexp, lenexp,
679 3339 : build_zero_cst (ssizetype));
680 : }
681 :
682 : /* Offset from the beginning of the string in elements. */
683 774391 : HOST_WIDE_INT eltoff;
684 :
685 : /* We have a known offset into the string. Start searching there for
686 : a null character if we can represent it as a single HOST_WIDE_INT. */
687 774391 : if (byteoff == 0)
688 : eltoff = 0;
689 774391 : else if (! tree_fits_uhwi_p (byteoff) || tree_to_uhwi (byteoff) % eltsize)
690 : eltoff = -1;
691 : else
692 773203 : eltoff = tree_to_uhwi (byteoff) / eltsize;
693 :
694 : /* If the offset is known to be out of bounds, warn, and call strlen at
695 : runtime. */
696 774391 : if (eltoff < 0 || eltoff >= maxelts)
697 : {
698 : /* Suppress multiple warnings for propagated constant strings. */
699 3828 : if (only_value != 2
700 3828 : && !warning_suppressed_p (arg, OPT_Warray_bounds_)
701 7656 : && warning_at (loc, OPT_Warray_bounds_,
702 : "offset %qwi outside bounds of constant string",
703 : eltoff))
704 : {
705 679 : if (decl)
706 678 : inform (DECL_SOURCE_LOCATION (decl), "%qE declared here", decl);
707 679 : suppress_warning (arg, OPT_Warray_bounds_);
708 : }
709 : return NULL_TREE;
710 : }
711 :
712 : /* If eltoff is larger than strelts but less than maxelts the
713 : string length is zero, since the excess memory will be zero. */
714 770563 : if (eltoff > strelts)
715 0 : return ssize_int (0);
716 :
717 : /* Use strlen to search for the first zero byte. Since any strings
718 : constructed with build_string will have nulls appended, we win even
719 : if we get handed something like (char[4])"abcd".
720 :
721 : Since ELTOFF is our starting index into the string, no further
722 : calculation is needed. */
723 770563 : unsigned len = string_length (ptr + eltoff * eltsize, eltsize,
724 770563 : strelts - eltoff);
725 :
726 : /* Don't know what to return if there was no zero termination.
727 : Ideally this would turn into a gcc_checking_assert over time.
728 : Set DECL/LEN so callers can examine them. */
729 770563 : if (len >= maxelts - eltoff)
730 : {
731 84856 : data->decl = decl;
732 84856 : data->off = byteoff;
733 84856 : data->minlen = ssize_int (len);
734 84856 : return NULL_TREE;
735 : }
736 :
737 685707 : return ssize_int (len);
738 : }
739 :
740 : /* Return a constant integer corresponding to target reading
741 : GET_MODE_BITSIZE (MODE) bits from string constant STR. If
742 : NULL_TERMINATED_P, reading stops after '\0' character, all further ones
743 : are assumed to be zero, otherwise it reads as many characters
744 : as needed. */
745 :
746 : rtx
747 298361 : c_readstr (const char *str, fixed_size_mode mode,
748 : bool null_terminated_p/*=true*/)
749 : {
750 298361 : auto_vec<target_unit, MAX_BITSIZE_MODE_ANY_INT / BITS_PER_UNIT> bytes;
751 :
752 596722 : bytes.reserve (GET_MODE_SIZE (mode));
753 :
754 298361 : target_unit ch = 1;
755 4954346 : for (unsigned int i = 0; i < GET_MODE_SIZE (mode); ++i)
756 : {
757 2178812 : if (ch || !null_terminated_p)
758 2090070 : ch = (unsigned char) str[i];
759 2178812 : bytes.quick_push (ch);
760 : }
761 :
762 298361 : return native_decode_rtx (mode, bytes, 0);
763 298361 : }
764 :
765 : /* Cast a target constant CST to target CHAR and if that value fits into
766 : host char type, return zero and put that value into variable pointed to by
767 : P. */
768 :
769 : static int
770 60996 : target_char_cast (tree cst, char *p)
771 : {
772 60996 : unsigned HOST_WIDE_INT val, hostval;
773 :
774 60996 : if (TREE_CODE (cst) != INTEGER_CST
775 : || CHAR_TYPE_SIZE > HOST_BITS_PER_WIDE_INT)
776 : return 1;
777 :
778 : /* Do not care if it fits or not right here. */
779 60996 : val = TREE_INT_CST_LOW (cst);
780 :
781 60996 : if (CHAR_TYPE_SIZE < HOST_BITS_PER_WIDE_INT)
782 60996 : val &= (HOST_WIDE_INT_1U << CHAR_TYPE_SIZE) - 1;
783 :
784 60996 : hostval = val;
785 60996 : if (HOST_BITS_PER_CHAR < HOST_BITS_PER_WIDE_INT)
786 60996 : hostval &= (HOST_WIDE_INT_1U << HOST_BITS_PER_CHAR) - 1;
787 :
788 60996 : if (val != hostval)
789 : return 1;
790 :
791 60996 : *p = hostval;
792 60996 : return 0;
793 : }
794 :
795 : /* Similar to save_expr, but assumes that arbitrary code is not executed
796 : in between the multiple evaluations. In particular, we assume that a
797 : non-addressable local variable will not be modified. */
798 :
799 : static tree
800 1138207 : builtin_save_expr (tree exp)
801 : {
802 1138207 : if (TREE_CODE (exp) == SSA_NAME
803 973862 : || (TREE_ADDRESSABLE (exp) == 0
804 973670 : && (TREE_CODE (exp) == PARM_DECL
805 435239 : || (VAR_P (exp) && !TREE_STATIC (exp)))))
806 : return exp;
807 :
808 433430 : return save_expr (exp);
809 : }
810 :
811 : /* Given TEM, a pointer to a stack frame, follow the dynamic chain COUNT
812 : times to get the address of either a higher stack frame, or a return
813 : address located within it (depending on FNDECL_CODE). */
814 :
815 : static rtx
816 15936 : expand_builtin_return_addr (enum built_in_function fndecl_code, int count)
817 : {
818 15936 : int i;
819 15936 : rtx tem = INITIAL_FRAME_ADDRESS_RTX;
820 15936 : if (tem == NULL_RTX)
821 : {
822 : /* For a zero count with __builtin_return_address, we don't care what
823 : frame address we return, because target-specific definitions will
824 : override us. Therefore frame pointer elimination is OK, and using
825 : the soft frame pointer is OK.
826 :
827 : For a nonzero count, or a zero count with __builtin_frame_address,
828 : we require a stable offset from the current frame pointer to the
829 : previous one, so we must use the hard frame pointer, and
830 : we must disable frame pointer elimination. */
831 15936 : if (count == 0 && fndecl_code == BUILT_IN_RETURN_ADDRESS)
832 4333 : tem = frame_pointer_rtx;
833 : else
834 : {
835 11603 : tem = hard_frame_pointer_rtx;
836 :
837 : /* Tell reload not to eliminate the frame pointer. */
838 11603 : crtl->accesses_prior_frames = 1;
839 : }
840 : }
841 :
842 15936 : if (count > 0)
843 938 : SETUP_FRAME_ADDRESSES ();
844 :
845 : /* On the SPARC, the return address is not in the frame, it is in a
846 : register. There is no way to access it off of the current frame
847 : pointer, but it can be accessed off the previous frame pointer by
848 : reading the value from the register window save area. */
849 15936 : if (RETURN_ADDR_IN_PREVIOUS_FRAME && fndecl_code == BUILT_IN_RETURN_ADDRESS)
850 : count--;
851 :
852 : /* Scan back COUNT frames to the specified frame. */
853 51818 : for (i = 0; i < count; i++)
854 : {
855 : /* Assume the dynamic chain pointer is in the word that the
856 : frame address points to, unless otherwise specified. */
857 35882 : tem = DYNAMIC_CHAIN_ADDRESS (tem);
858 35882 : tem = memory_address (Pmode, tem);
859 35882 : tem = gen_frame_mem (Pmode, tem);
860 35882 : tem = copy_to_reg (tem);
861 : }
862 :
863 : /* For __builtin_frame_address, return what we've got. But, on
864 : the SPARC for example, we may have to add a bias. */
865 15936 : if (fndecl_code == BUILT_IN_FRAME_ADDRESS)
866 : return FRAME_ADDR_RTX (count, tem);
867 :
868 : /* For __builtin_return_address, get the return address from that frame. */
869 : #ifdef RETURN_ADDR_RTX
870 7402 : tem = RETURN_ADDR_RTX (count, tem);
871 : #else
872 : tem = memory_address (Pmode,
873 : plus_constant (Pmode, tem, GET_MODE_SIZE (Pmode)));
874 : tem = gen_frame_mem (Pmode, tem);
875 : #endif
876 5173 : return tem;
877 : }
878 :
879 : /* Alias set used for setjmp buffer. */
880 : static alias_set_type setjmp_alias_set = -1;
881 :
882 : /* Construct the leading half of a __builtin_setjmp call. Control will
883 : return to RECEIVER_LABEL. This is also called directly by the SJLJ
884 : exception handling code. */
885 :
886 : void
887 842 : expand_builtin_setjmp_setup (rtx buf_addr, rtx receiver_label)
888 : {
889 842 : machine_mode sa_mode = STACK_SAVEAREA_MODE (SAVE_NONLOCAL);
890 842 : rtx stack_save;
891 842 : rtx mem;
892 :
893 842 : if (setjmp_alias_set == -1)
894 241 : setjmp_alias_set = new_alias_set ();
895 :
896 843 : buf_addr = convert_memory_address (Pmode, buf_addr);
897 :
898 843 : buf_addr = force_reg (Pmode, force_operand (buf_addr, NULL_RTX));
899 :
900 : /* We store the frame pointer and the address of receiver_label in
901 : the buffer and use the rest of it for the stack save area, which
902 : is machine-dependent. */
903 :
904 843 : mem = gen_rtx_MEM (Pmode, buf_addr);
905 842 : set_mem_alias_set (mem, setjmp_alias_set);
906 842 : emit_move_insn (mem, hard_frame_pointer_rtx);
907 :
908 843 : mem = gen_rtx_MEM (Pmode, plus_constant (Pmode, buf_addr,
909 1684 : GET_MODE_SIZE (Pmode))),
910 842 : set_mem_alias_set (mem, setjmp_alias_set);
911 :
912 1684 : emit_move_insn (validize_mem (mem),
913 1684 : force_reg (Pmode, gen_rtx_LABEL_REF (Pmode, receiver_label)));
914 :
915 842 : stack_save = gen_rtx_MEM (sa_mode,
916 : plus_constant (Pmode, buf_addr,
917 1684 : 2 * GET_MODE_SIZE (Pmode)));
918 842 : set_mem_alias_set (stack_save, setjmp_alias_set);
919 842 : emit_stack_save (SAVE_NONLOCAL, &stack_save);
920 :
921 : /* If there is further processing to do, do it. */
922 842 : if (targetm.have_builtin_setjmp_setup ())
923 0 : emit_insn (targetm.gen_builtin_setjmp_setup (buf_addr));
924 :
925 : /* We have a nonlocal label. */
926 842 : cfun->has_nonlocal_label = 1;
927 842 : }
928 :
929 : /* Construct the trailing part of a __builtin_setjmp call. This is
930 : also called directly by the SJLJ exception handling code.
931 : If RECEIVER_LABEL is NULL, instead construct a nonlocal goto handler. */
932 :
933 : void
934 1346 : expand_builtin_setjmp_receiver (rtx receiver_label)
935 : {
936 1346 : rtx chain;
937 :
938 : /* Mark the FP as used when we get here, so we have to make sure it's
939 : marked as used by this function. */
940 1346 : emit_use (hard_frame_pointer_rtx);
941 :
942 : /* Mark the static chain as clobbered here so life information
943 : doesn't get messed up for it. */
944 1346 : chain = rtx_for_static_chain (current_function_decl, true);
945 1346 : if (chain && REG_P (chain))
946 1 : emit_clobber (chain);
947 :
948 1346 : if (!HARD_FRAME_POINTER_IS_ARG_POINTER && fixed_regs[ARG_POINTER_REGNUM])
949 : {
950 : /* If the argument pointer can be eliminated in favor of the
951 : frame pointer, we don't need to restore it. We assume here
952 : that if such an elimination is present, it can always be used.
953 : This is the case on all known machines; if we don't make this
954 : assumption, we do unnecessary saving on many machines. */
955 : size_t i;
956 : static const struct elims {const int from, to;} elim_regs[] = ELIMINABLE_REGS;
957 :
958 2692 : for (i = 0; i < ARRAY_SIZE (elim_regs); i++)
959 2692 : if (elim_regs[i].from == ARG_POINTER_REGNUM
960 2692 : && elim_regs[i].to == HARD_FRAME_POINTER_REGNUM)
961 : break;
962 :
963 1346 : if (i == ARRAY_SIZE (elim_regs))
964 : {
965 : /* Now restore our arg pointer from the address at which it
966 : was saved in our stack frame. */
967 0 : emit_move_insn (crtl->args.internal_arg_pointer,
968 : copy_to_reg (get_arg_pointer_save_area ()));
969 : }
970 : }
971 :
972 1346 : if (receiver_label != NULL && targetm.have_builtin_setjmp_receiver ())
973 0 : emit_insn (targetm.gen_builtin_setjmp_receiver (receiver_label));
974 1346 : else if (targetm.have_nonlocal_goto_receiver ())
975 0 : emit_insn (targetm.gen_nonlocal_goto_receiver ());
976 : else
977 : { /* Nothing */ }
978 :
979 : /* We must not allow the code we just generated to be reordered by
980 : scheduling. Specifically, the update of the frame pointer must
981 : happen immediately, not later. */
982 1346 : emit_insn (gen_blockage ());
983 1346 : }
984 :
985 : /* __builtin_longjmp is passed a pointer to an array of five words (not
986 : all will be used on all machines). It operates similarly to the C
987 : library function of the same name, but is more efficient. Much of
988 : the code below is copied from the handling of non-local gotos. */
989 :
990 : static void
991 392 : expand_builtin_longjmp (rtx buf_addr, rtx value)
992 : {
993 392 : rtx fp, lab, stack;
994 392 : rtx_insn *insn, *last;
995 392 : machine_mode sa_mode = STACK_SAVEAREA_MODE (SAVE_NONLOCAL);
996 :
997 : /* DRAP is needed for stack realign if longjmp is expanded to current
998 : function */
999 392 : if (SUPPORTS_STACK_ALIGNMENT)
1000 392 : crtl->need_drap = true;
1001 :
1002 392 : if (setjmp_alias_set == -1)
1003 331 : setjmp_alias_set = new_alias_set ();
1004 :
1005 393 : buf_addr = convert_memory_address (Pmode, buf_addr);
1006 :
1007 393 : buf_addr = force_reg (Pmode, buf_addr);
1008 :
1009 : /* We require that the user must pass a second argument of 1, because
1010 : that is what builtin_setjmp will return. */
1011 392 : gcc_assert (value == const1_rtx);
1012 :
1013 392 : last = get_last_insn ();
1014 392 : if (targetm.have_builtin_longjmp ())
1015 0 : emit_insn (targetm.gen_builtin_longjmp (buf_addr));
1016 : else
1017 : {
1018 393 : fp = gen_rtx_MEM (Pmode, buf_addr);
1019 393 : lab = gen_rtx_MEM (Pmode, plus_constant (Pmode, buf_addr,
1020 784 : GET_MODE_SIZE (Pmode)));
1021 :
1022 392 : stack = gen_rtx_MEM (sa_mode, plus_constant (Pmode, buf_addr,
1023 784 : 2 * GET_MODE_SIZE (Pmode)));
1024 392 : set_mem_alias_set (fp, setjmp_alias_set);
1025 392 : set_mem_alias_set (lab, setjmp_alias_set);
1026 392 : set_mem_alias_set (stack, setjmp_alias_set);
1027 :
1028 : /* Pick up FP, label, and SP from the block and jump. This code is
1029 : from expand_goto in stmt.cc; see there for detailed comments. */
1030 392 : if (targetm.have_nonlocal_goto ())
1031 : /* We have to pass a value to the nonlocal_goto pattern that will
1032 : get copied into the static_chain pointer, but it does not matter
1033 : what that value is, because builtin_setjmp does not use it. */
1034 0 : emit_insn (targetm.gen_nonlocal_goto (value, lab, stack, fp));
1035 : else
1036 : {
1037 392 : emit_clobber (gen_rtx_MEM (BLKmode, gen_rtx_SCRATCH (VOIDmode)));
1038 392 : emit_clobber (gen_rtx_MEM (BLKmode, hard_frame_pointer_rtx));
1039 :
1040 392 : lab = copy_to_reg (lab);
1041 :
1042 : /* Restore the frame pointer and stack pointer. We must use a
1043 : temporary since the setjmp buffer may be a local. */
1044 392 : fp = copy_to_reg (fp);
1045 392 : emit_stack_restore (SAVE_NONLOCAL, stack);
1046 :
1047 : /* Ensure the frame pointer move is not optimized. */
1048 392 : emit_insn (gen_blockage ());
1049 392 : emit_clobber (hard_frame_pointer_rtx);
1050 392 : emit_clobber (frame_pointer_rtx);
1051 392 : emit_move_insn (hard_frame_pointer_rtx, fp);
1052 :
1053 392 : emit_use (hard_frame_pointer_rtx);
1054 392 : emit_use (stack_pointer_rtx);
1055 392 : emit_indirect_jump (lab);
1056 : }
1057 : }
1058 :
1059 : /* Search backwards and mark the jump insn as a non-local goto.
1060 : Note that this precludes the use of __builtin_longjmp to a
1061 : __builtin_setjmp target in the same function. However, we've
1062 : already cautioned the user that these functions are for
1063 : internal exception handling use only. */
1064 784 : for (insn = get_last_insn (); insn; insn = PREV_INSN (insn))
1065 : {
1066 784 : gcc_assert (insn != last);
1067 :
1068 784 : if (JUMP_P (insn))
1069 : {
1070 392 : add_reg_note (insn, REG_NON_LOCAL_GOTO, const0_rtx);
1071 392 : break;
1072 : }
1073 392 : else if (CALL_P (insn))
1074 : break;
1075 : }
1076 392 : }
1077 :
1078 : static inline bool
1079 1960109 : more_const_call_expr_args_p (const const_call_expr_arg_iterator *iter)
1080 : {
1081 1960109 : return (iter->i < iter->n);
1082 : }
1083 :
1084 : /* This function validates the types of a function call argument list
1085 : against a specified list of tree_codes. If the last specifier is a 0,
1086 : that represents an ellipsis, otherwise the last specifier must be a
1087 : VOID_TYPE. */
1088 :
1089 : static bool
1090 509770 : validate_arglist (const_tree callexpr, ...)
1091 : {
1092 509770 : enum tree_code code;
1093 509770 : bool res = 0;
1094 509770 : va_list ap;
1095 509770 : const_call_expr_arg_iterator iter;
1096 509770 : const_tree arg;
1097 :
1098 509770 : va_start (ap, callexpr);
1099 509770 : init_const_call_expr_arg_iterator (callexpr, &iter);
1100 :
1101 : /* Get a bitmap of pointer argument numbers declared attribute nonnull. */
1102 509770 : tree fn = CALL_EXPR_FN (callexpr);
1103 509770 : bitmap argmap = get_nonnull_args (TREE_TYPE (TREE_TYPE (fn)));
1104 :
1105 1779848 : for (unsigned argno = 1; ; ++argno)
1106 : {
1107 1779848 : code = (enum tree_code) va_arg (ap, int);
1108 :
1109 1779848 : switch (code)
1110 : {
1111 2058 : case 0:
1112 : /* This signifies an ellipses, any further arguments are all ok. */
1113 2058 : res = true;
1114 2058 : goto end;
1115 507480 : case VOID_TYPE:
1116 : /* This signifies an endlink, if no arguments remain, return
1117 : true, otherwise return false. */
1118 507480 : res = !more_const_call_expr_args_p (&iter);
1119 507480 : goto end;
1120 836468 : case POINTER_TYPE:
1121 : /* The actual argument must be nonnull when either the whole
1122 : called function has been declared nonnull, or when the formal
1123 : argument corresponding to the actual argument has been. */
1124 836468 : if (argmap
1125 836468 : && (bitmap_empty_p (argmap) || bitmap_bit_p (argmap, argno)))
1126 : {
1127 281938 : arg = next_const_call_expr_arg (&iter);
1128 281938 : if (!validate_arg (arg, code) || integer_zerop (arg))
1129 58 : goto end;
1130 : break;
1131 : }
1132 : /* FALLTHRU */
1133 988372 : default:
1134 : /* If no parameters remain or the parameter's code does not
1135 : match the specified code, return false. Otherwise continue
1136 : checking any remaining arguments. */
1137 988372 : arg = next_const_call_expr_arg (&iter);
1138 988372 : if (!validate_arg (arg, code))
1139 174 : goto end;
1140 : break;
1141 : }
1142 : }
1143 :
1144 : /* We need gotos here since we can only have one VA_CLOSE in a
1145 : function. */
1146 509770 : end: ;
1147 509770 : va_end (ap);
1148 :
1149 509770 : BITMAP_FREE (argmap);
1150 :
1151 509770 : if (res)
1152 509538 : for (tree attrs = TYPE_ATTRIBUTES (TREE_TYPE (TREE_TYPE (fn)));
1153 743356 : (attrs = lookup_attribute ("nonnull_if_nonzero", attrs));
1154 233818 : attrs = TREE_CHAIN (attrs))
1155 : {
1156 233840 : tree args = TREE_VALUE (attrs);
1157 233840 : unsigned int idx = TREE_INT_CST_LOW (TREE_VALUE (args)) - 1;
1158 233840 : unsigned int idx2
1159 233840 : = TREE_INT_CST_LOW (TREE_VALUE (TREE_CHAIN (args))) - 1;
1160 233840 : unsigned int idx3 = idx2;
1161 233840 : if (tree chain2 = TREE_CHAIN (TREE_CHAIN (args)))
1162 0 : idx3 = TREE_INT_CST_LOW (TREE_VALUE (chain2)) - 1;
1163 233840 : if (idx < (unsigned) call_expr_nargs (callexpr)
1164 233840 : && idx2 < (unsigned) call_expr_nargs (callexpr)
1165 233840 : && idx3 < (unsigned) call_expr_nargs (callexpr)
1166 233840 : && POINTER_TYPE_P (TREE_TYPE (CALL_EXPR_ARG (callexpr, idx)))
1167 233840 : && integer_zerop (CALL_EXPR_ARG (callexpr, idx))
1168 101 : && INTEGRAL_TYPE_P (TREE_TYPE (CALL_EXPR_ARG (callexpr, idx2)))
1169 101 : && integer_nonzerop (CALL_EXPR_ARG (callexpr, idx2))
1170 22 : && INTEGRAL_TYPE_P (TREE_TYPE (CALL_EXPR_ARG (callexpr, idx3)))
1171 233862 : && integer_nonzerop (CALL_EXPR_ARG (callexpr, idx3)))
1172 : return false;
1173 : }
1174 :
1175 : return res;
1176 : }
1177 :
1178 : /* Expand a call to __builtin_nonlocal_goto. We're passed the target label
1179 : and the address of the save area. */
1180 :
1181 : static rtx
1182 512 : expand_builtin_nonlocal_goto (tree exp)
1183 : {
1184 512 : tree t_label, t_save_area;
1185 512 : rtx r_label, r_save_area, r_fp, r_sp;
1186 512 : rtx_insn *insn;
1187 :
1188 512 : if (!validate_arglist (exp, POINTER_TYPE, POINTER_TYPE, VOID_TYPE))
1189 : return NULL_RTX;
1190 :
1191 512 : t_label = CALL_EXPR_ARG (exp, 0);
1192 512 : t_save_area = CALL_EXPR_ARG (exp, 1);
1193 :
1194 512 : r_label = expand_normal (t_label);
1195 512 : r_label = convert_memory_address (Pmode, r_label);
1196 512 : r_save_area = expand_normal (t_save_area);
1197 512 : r_save_area = convert_memory_address (Pmode, r_save_area);
1198 : /* Copy the address of the save location to a register just in case it was
1199 : based on the frame pointer. */
1200 512 : r_save_area = copy_to_reg (r_save_area);
1201 512 : r_fp = gen_rtx_MEM (Pmode, r_save_area);
1202 512 : r_sp = gen_rtx_MEM (STACK_SAVEAREA_MODE (SAVE_NONLOCAL),
1203 : plus_constant (Pmode, r_save_area,
1204 1024 : GET_MODE_SIZE (Pmode)));
1205 :
1206 512 : crtl->has_nonlocal_goto = 1;
1207 :
1208 : /* ??? We no longer need to pass the static chain value, afaik. */
1209 512 : if (targetm.have_nonlocal_goto ())
1210 0 : emit_insn (targetm.gen_nonlocal_goto (const0_rtx, r_label, r_sp, r_fp));
1211 : else
1212 : {
1213 512 : emit_clobber (gen_rtx_MEM (BLKmode, gen_rtx_SCRATCH (VOIDmode)));
1214 512 : emit_clobber (gen_rtx_MEM (BLKmode, hard_frame_pointer_rtx));
1215 :
1216 512 : r_label = copy_to_reg (r_label);
1217 :
1218 : /* Restore the frame pointer and stack pointer. We must use a
1219 : temporary since the setjmp buffer may be a local. */
1220 512 : r_fp = copy_to_reg (r_fp);
1221 512 : emit_stack_restore (SAVE_NONLOCAL, r_sp);
1222 :
1223 : /* Ensure the frame pointer move is not optimized. */
1224 512 : emit_insn (gen_blockage ());
1225 512 : emit_clobber (hard_frame_pointer_rtx);
1226 512 : emit_clobber (frame_pointer_rtx);
1227 512 : emit_move_insn (hard_frame_pointer_rtx, r_fp);
1228 :
1229 : /* USE of hard_frame_pointer_rtx added for consistency;
1230 : not clear if really needed. */
1231 512 : emit_use (hard_frame_pointer_rtx);
1232 512 : emit_use (stack_pointer_rtx);
1233 :
1234 : /* If the architecture is using a GP register, we must
1235 : conservatively assume that the target function makes use of it.
1236 : The prologue of functions with nonlocal gotos must therefore
1237 : initialize the GP register to the appropriate value, and we
1238 : must then make sure that this value is live at the point
1239 : of the jump. (Note that this doesn't necessarily apply
1240 : to targets with a nonlocal_goto pattern; they are free
1241 : to implement it in their own way. Note also that this is
1242 : a no-op if the GP register is a global invariant.) */
1243 512 : unsigned regnum = PIC_OFFSET_TABLE_REGNUM;
1244 0 : if (regnum != INVALID_REGNUM && fixed_regs[regnum])
1245 0 : emit_use (pic_offset_table_rtx);
1246 :
1247 512 : emit_indirect_jump (r_label);
1248 : }
1249 :
1250 : /* Search backwards to the jump insn and mark it as a
1251 : non-local goto. */
1252 1024 : for (insn = get_last_insn (); insn; insn = PREV_INSN (insn))
1253 : {
1254 1024 : if (JUMP_P (insn))
1255 : {
1256 512 : add_reg_note (insn, REG_NON_LOCAL_GOTO, const0_rtx);
1257 512 : break;
1258 : }
1259 512 : else if (CALL_P (insn))
1260 : break;
1261 : }
1262 :
1263 512 : return const0_rtx;
1264 : }
1265 :
1266 : /* __builtin_update_setjmp_buf is passed a pointer to an array of five words
1267 : (not all will be used on all machines) that was passed to __builtin_setjmp.
1268 : It updates the stack pointer in that block to the current value. This is
1269 : also called directly by the SJLJ exception handling code. */
1270 :
1271 : void
1272 0 : expand_builtin_update_setjmp_buf (rtx buf_addr)
1273 : {
1274 0 : machine_mode sa_mode = STACK_SAVEAREA_MODE (SAVE_NONLOCAL);
1275 0 : buf_addr = convert_memory_address (Pmode, buf_addr);
1276 0 : rtx stack_save
1277 0 : = gen_rtx_MEM (sa_mode,
1278 0 : memory_address
1279 : (sa_mode,
1280 : plus_constant (Pmode, buf_addr,
1281 0 : 2 * GET_MODE_SIZE (Pmode))));
1282 :
1283 0 : emit_stack_save (SAVE_NONLOCAL, &stack_save);
1284 0 : }
1285 :
1286 : /* Expand a call to __builtin_prefetch. For a target that does not support
1287 : data prefetch, evaluate the memory address argument in case it has side
1288 : effects. */
1289 :
1290 : static void
1291 2058 : expand_builtin_prefetch (tree exp)
1292 : {
1293 2058 : tree arg0, arg1, arg2;
1294 2058 : int nargs;
1295 2058 : rtx op0, op1, op2;
1296 :
1297 2058 : if (!validate_arglist (exp, POINTER_TYPE, 0))
1298 : return;
1299 :
1300 2058 : arg0 = CALL_EXPR_ARG (exp, 0);
1301 :
1302 : /* Arguments 1 and 2 are optional; argument 1 (read/write) defaults to
1303 : zero (read) and argument 2 (locality) defaults to 3 (high degree of
1304 : locality). */
1305 2058 : nargs = call_expr_nargs (exp);
1306 2058 : arg1 = nargs > 1 ? CALL_EXPR_ARG (exp, 1) : NULL_TREE;
1307 2018 : arg2 = nargs > 2 ? CALL_EXPR_ARG (exp, 2) : NULL_TREE;
1308 :
1309 : /* Argument 0 is an address. */
1310 2154 : op0 = expand_expr (arg0, NULL_RTX, Pmode, EXPAND_NORMAL);
1311 :
1312 : /* Argument 1 (read/write flag) must be a compile-time constant int. */
1313 2058 : if (arg1 == NULL_TREE)
1314 40 : op1 = const0_rtx;
1315 2018 : else if (TREE_CODE (arg1) != INTEGER_CST)
1316 : {
1317 0 : error ("second argument to %<__builtin_prefetch%> must be a constant");
1318 0 : op1 = const0_rtx;
1319 : }
1320 : else
1321 2018 : op1 = expand_normal (arg1);
1322 : /* Argument 1 must be 0, 1 or 2. */
1323 2058 : if (!IN_RANGE (INTVAL (op1), 0, 2))
1324 : {
1325 3 : warning (0, "invalid second argument to %<__builtin_prefetch%>;"
1326 : " using zero");
1327 3 : op1 = const0_rtx;
1328 : }
1329 :
1330 : /* Argument 2 (locality) must be a compile-time constant int. */
1331 2058 : if (arg2 == NULL_TREE)
1332 77 : op2 = GEN_INT (3);
1333 1981 : else if (TREE_CODE (arg2) != INTEGER_CST)
1334 : {
1335 0 : error ("third argument to %<__builtin_prefetch%> must be a constant");
1336 0 : op2 = const0_rtx;
1337 : }
1338 : else
1339 1981 : op2 = expand_normal (arg2);
1340 : /* Argument 2 must be 0, 1, 2, or 3. */
1341 2058 : if (!IN_RANGE (INTVAL (op2), 0, 3))
1342 : {
1343 3 : warning (0, "invalid third argument to %<__builtin_prefetch%>; using zero");
1344 3 : op2 = const0_rtx;
1345 : }
1346 :
1347 2058 : if (targetm.have_prefetch ())
1348 : {
1349 2058 : class expand_operand ops[3];
1350 :
1351 2058 : create_address_operand (&ops[0], op0);
1352 2058 : create_integer_operand (&ops[1], INTVAL (op1));
1353 2058 : create_integer_operand (&ops[2], INTVAL (op2));
1354 2058 : if (maybe_expand_insn (targetm.code_for_prefetch, 3, ops))
1355 2058 : return;
1356 : }
1357 :
1358 : /* Don't do anything with direct references to volatile memory, but
1359 : generate code to handle other side effects. */
1360 0 : if (!MEM_P (op0) && side_effects_p (op0))
1361 0 : emit_insn (op0);
1362 : }
1363 :
1364 : /* Get a MEM rtx for expression EXP which is the address of an operand
1365 : to be used in a string instruction (cmpstrsi, cpymemsi, ..). LEN is
1366 : the maximum length of the block of memory that might be accessed or
1367 : NULL if unknown. STORE_P is true when EXP is the destination. */
1368 :
1369 : rtx
1370 765942 : get_memory_rtx (tree exp, tree len, bool store_p)
1371 : {
1372 765942 : tree orig_exp = exp, base;
1373 765942 : rtx addr, mem;
1374 :
1375 765942 : gcc_checking_assert
1376 : (ADDR_SPACE_GENERIC_P (TYPE_ADDR_SPACE (TREE_TYPE (TREE_TYPE (exp)))));
1377 :
1378 : /* When EXP is not resolved SAVE_EXPR, MEM_ATTRS can be still derived
1379 : from its expression, for expr->a.b only <variable>.a.b is recorded. */
1380 765942 : if (TREE_CODE (exp) == SAVE_EXPR && !SAVE_EXPR_RESOLVED_P (exp))
1381 1630 : exp = TREE_OPERAND (exp, 0);
1382 :
1383 765942 : addr = expand_expr (orig_exp, NULL_RTX, ptr_mode, EXPAND_NORMAL);
1384 765942 : mem = gen_rtx_MEM (BLKmode, memory_address (BLKmode, addr));
1385 :
1386 : /* Get an expression we can use to find the attributes to assign to MEM.
1387 : First remove any nops. */
1388 1531884 : while (CONVERT_EXPR_P (exp)
1389 765945 : && POINTER_TYPE_P (TREE_TYPE (TREE_OPERAND (exp, 0))))
1390 3 : exp = TREE_OPERAND (exp, 0);
1391 :
1392 : /* Build a MEM_REF representing the whole accessed area as a byte blob,
1393 : (as builtin stringops may alias with anything). */
1394 765942 : exp = fold_build2 (MEM_REF,
1395 : build_array_type (char_type_node,
1396 : build_range_type (sizetype,
1397 : size_one_node, len)),
1398 : exp, build_int_cst (ptr_type_node, 0));
1399 :
1400 : /* If the MEM_REF has no acceptable address, try to get the base object
1401 : from the original address we got, and build an all-aliasing
1402 : unknown-sized access to that one. */
1403 765942 : if (is_gimple_mem_ref_addr (TREE_OPERAND (exp, 0)))
1404 765930 : set_mem_attributes (mem, exp, 0, store_p);
1405 12 : else if (TREE_CODE (TREE_OPERAND (exp, 0)) == ADDR_EXPR
1406 12 : && (base = get_base_address (TREE_OPERAND (TREE_OPERAND (exp, 0),
1407 : 0))))
1408 : {
1409 12 : unsigned int align = get_pointer_alignment (TREE_OPERAND (exp, 0));
1410 12 : exp = build_fold_addr_expr (base);
1411 12 : exp = fold_build2 (MEM_REF,
1412 : build_array_type (char_type_node,
1413 : build_range_type (sizetype,
1414 : size_zero_node,
1415 : NULL)),
1416 : exp, build_int_cst (ptr_type_node, 0));
1417 12 : set_mem_attributes (mem, exp, 0, store_p);
1418 : /* Since we stripped parts make sure the offset is unknown and the
1419 : alignment is computed from the original address. */
1420 12 : clear_mem_offset (mem);
1421 12 : set_mem_align (mem, align);
1422 : }
1423 765942 : set_mem_alias_set (mem, 0);
1424 765942 : return mem;
1425 : }
1426 :
1427 : /* Built-in functions to perform an untyped call and return. */
1428 :
1429 : /* Wrapper that implicitly applies a delta when getting or setting the
1430 : enclosed value. */
1431 : template <typename T>
1432 : class delta_type
1433 : {
1434 : T &value; T const delta;
1435 : public:
1436 2524 : delta_type (T &val, T dlt) : value (val), delta (dlt) {}
1437 1809 : operator T () const { return value + delta; }
1438 715 : T operator = (T val) const { value = val - delta; return val; }
1439 : };
1440 :
1441 : #define saved_apply_args_size \
1442 : (delta_type<int> (this_target_builtins->x_apply_args_size_plus_one, -1))
1443 : #define apply_args_mode \
1444 : (this_target_builtins->x_apply_args_mode)
1445 : #define saved_apply_result_size \
1446 : (delta_type<int> (this_target_builtins->x_apply_result_size_plus_one, -1))
1447 : #define apply_result_mode \
1448 : (this_target_builtins->x_apply_result_mode)
1449 :
1450 : /* Return the size required for the block returned by __builtin_apply_args,
1451 : and initialize apply_args_mode. */
1452 :
1453 : static int
1454 947 : apply_args_size (void)
1455 : {
1456 947 : int size = saved_apply_args_size;
1457 947 : int align;
1458 947 : unsigned int regno;
1459 :
1460 : /* The values computed by this function never change. */
1461 947 : if (size < 0)
1462 : {
1463 : /* The first value is the incoming arg-pointer. */
1464 360 : size = GET_MODE_SIZE (Pmode);
1465 :
1466 : /* The second value is the structure value address unless this is
1467 : passed as an "invisible" first argument. */
1468 360 : if (targetm.calls.struct_value_rtx (cfun ? TREE_TYPE (cfun->decl) : 0, 0))
1469 0 : size += GET_MODE_SIZE (Pmode);
1470 :
1471 34200 : for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
1472 33840 : if (FUNCTION_ARG_REGNO_P (regno))
1473 : {
1474 5400 : fixed_size_mode mode = targetm.calls.get_raw_arg_mode (regno);
1475 :
1476 5400 : if (mode != VOIDmode)
1477 : {
1478 5400 : align = GET_MODE_ALIGNMENT (mode) / BITS_PER_UNIT;
1479 5400 : if (size % align != 0)
1480 1 : size = CEIL (size, align) * align;
1481 5400 : size += GET_MODE_SIZE (mode);
1482 5400 : apply_args_mode[regno] = mode;
1483 : }
1484 : else
1485 0 : apply_args_mode[regno] = as_a <fixed_size_mode> (VOIDmode);
1486 : }
1487 : else
1488 28440 : apply_args_mode[regno] = as_a <fixed_size_mode> (VOIDmode);
1489 :
1490 360 : saved_apply_args_size = size;
1491 : }
1492 947 : return size;
1493 : }
1494 :
1495 : /* Return the size required for the block returned by __builtin_apply,
1496 : and initialize apply_result_mode. */
1497 :
1498 : static int
1499 862 : apply_result_size (void)
1500 : {
1501 862 : int size = saved_apply_result_size;
1502 862 : int align, regno;
1503 :
1504 : /* The values computed by this function never change. */
1505 862 : if (size < 0)
1506 : {
1507 : size = 0;
1508 :
1509 33725 : for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
1510 33370 : if (targetm.calls.function_value_regno_p (regno))
1511 : {
1512 2130 : fixed_size_mode mode = targetm.calls.get_raw_result_mode (regno);
1513 :
1514 2130 : if (mode != VOIDmode)
1515 : {
1516 2130 : align = GET_MODE_ALIGNMENT (mode) / BITS_PER_UNIT;
1517 2130 : if (size % align != 0)
1518 : size = CEIL (size, align) * align;
1519 2130 : size += GET_MODE_SIZE (mode);
1520 2130 : apply_result_mode[regno] = mode;
1521 : }
1522 : else
1523 0 : apply_result_mode[regno] = as_a <fixed_size_mode> (VOIDmode);
1524 : }
1525 : else
1526 31240 : apply_result_mode[regno] = as_a <fixed_size_mode> (VOIDmode);
1527 :
1528 : /* Allow targets that use untyped_call and untyped_return to override
1529 : the size so that machine-specific information can be stored here. */
1530 : #ifdef APPLY_RESULT_SIZE
1531 355 : size = APPLY_RESULT_SIZE;
1532 : #endif
1533 :
1534 355 : saved_apply_result_size = size;
1535 : }
1536 862 : return size;
1537 : }
1538 :
1539 : /* Create a vector describing the result block RESULT. If SAVEP is true,
1540 : the result block is used to save the values; otherwise it is used to
1541 : restore the values. */
1542 :
1543 : static rtx
1544 483 : result_vector (int savep, rtx result)
1545 : {
1546 483 : int regno, size, align, nelts;
1547 483 : fixed_size_mode mode;
1548 483 : rtx reg, mem;
1549 483 : rtx *savevec = XALLOCAVEC (rtx, FIRST_PSEUDO_REGISTER);
1550 :
1551 483 : size = nelts = 0;
1552 45885 : for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
1553 45402 : if ((mode = apply_result_mode[regno]) != VOIDmode)
1554 : {
1555 2898 : align = GET_MODE_ALIGNMENT (mode) / BITS_PER_UNIT;
1556 2898 : if (size % align != 0)
1557 0 : size = CEIL (size, align) * align;
1558 2898 : reg = gen_rtx_REG (mode, savep ? regno : INCOMING_REGNO (regno));
1559 2898 : mem = adjust_address (result, mode, size);
1560 5796 : savevec[nelts++] = (savep
1561 5796 : ? gen_rtx_SET (mem, reg)
1562 0 : : gen_rtx_SET (reg, mem));
1563 5796 : size += GET_MODE_SIZE (mode);
1564 : }
1565 483 : return gen_rtx_PARALLEL (VOIDmode, gen_rtvec_v (nelts, savevec));
1566 : }
1567 :
1568 : /* Save the state required to perform an untyped call with the same
1569 : arguments as were passed to the current function. */
1570 :
1571 : static rtx
1572 464 : expand_builtin_apply_args_1 (void)
1573 : {
1574 464 : rtx registers, tem;
1575 464 : int size, align, regno;
1576 464 : fixed_size_mode mode;
1577 464 : rtx struct_incoming_value = targetm.calls.struct_value_rtx (cfun ? TREE_TYPE (cfun->decl) : 0, 1);
1578 :
1579 : /* Create a block where the arg-pointer, structure value address,
1580 : and argument registers can be saved. */
1581 464 : registers = assign_stack_local (BLKmode, apply_args_size (), -1);
1582 :
1583 : /* Walk past the arg-pointer and structure value address. */
1584 464 : size = GET_MODE_SIZE (Pmode);
1585 464 : if (targetm.calls.struct_value_rtx (cfun ? TREE_TYPE (cfun->decl) : 0, 0))
1586 0 : size += GET_MODE_SIZE (Pmode);
1587 :
1588 : /* Save each register used in calling a function to the block. */
1589 44080 : for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
1590 43616 : if ((mode = apply_args_mode[regno]) != VOIDmode)
1591 : {
1592 6960 : align = GET_MODE_ALIGNMENT (mode) / BITS_PER_UNIT;
1593 6960 : if (size % align != 0)
1594 1 : size = CEIL (size, align) * align;
1595 :
1596 6960 : tem = gen_rtx_REG (mode, INCOMING_REGNO (regno));
1597 :
1598 6960 : emit_move_insn (adjust_address (registers, mode, size), tem);
1599 13920 : size += GET_MODE_SIZE (mode);
1600 : }
1601 :
1602 : /* Save the arg pointer to the block. */
1603 464 : tem = copy_to_reg (crtl->args.internal_arg_pointer);
1604 : /* We need the pointer as the caller actually passed them to us, not
1605 : as we might have pretended they were passed. Make sure it's a valid
1606 : operand, as emit_move_insn isn't expected to handle a PLUS. */
1607 464 : if (STACK_GROWS_DOWNWARD)
1608 464 : tem
1609 464 : = force_operand (plus_constant (Pmode, tem,
1610 464 : crtl->args.pretend_args_size),
1611 : NULL_RTX);
1612 464 : emit_move_insn (adjust_address (registers, Pmode, 0), tem);
1613 :
1614 464 : size = GET_MODE_SIZE (Pmode);
1615 :
1616 : /* Save the structure value address unless this is passed as an
1617 : "invisible" first argument. */
1618 464 : if (struct_incoming_value)
1619 0 : emit_move_insn (adjust_address (registers, Pmode, size),
1620 : copy_to_reg (struct_incoming_value));
1621 :
1622 : /* Return the address of the block. */
1623 464 : return copy_addr_to_reg (XEXP (registers, 0));
1624 : }
1625 :
1626 : /* __builtin_apply_args returns block of memory allocated on
1627 : the stack into which is stored the arg pointer, structure
1628 : value address, static chain, and all the registers that might
1629 : possibly be used in performing a function call. The code is
1630 : moved to the start of the function so the incoming values are
1631 : saved. */
1632 :
1633 : static rtx
1634 464 : expand_builtin_apply_args (void)
1635 : {
1636 : /* Don't do __builtin_apply_args more than once in a function.
1637 : Save the result of the first call and reuse it. */
1638 464 : if (apply_args_value != 0)
1639 : return apply_args_value;
1640 464 : {
1641 : /* When this function is called, it means that registers must be
1642 : saved on entry to this function. So we migrate the
1643 : call to the first insn of this function. */
1644 464 : rtx temp;
1645 :
1646 464 : start_sequence ();
1647 464 : temp = expand_builtin_apply_args_1 ();
1648 464 : rtx_insn *seq = end_sequence ();
1649 :
1650 464 : apply_args_value = temp;
1651 :
1652 : /* Put the insns after the NOTE that starts the function.
1653 : If this is inside a start_sequence, make the outer-level insn
1654 : chain current, so the code is placed at the start of the
1655 : function. If internal_arg_pointer is a non-virtual pseudo,
1656 : it needs to be placed after the function that initializes
1657 : that pseudo. */
1658 464 : push_topmost_sequence ();
1659 464 : if (REG_P (crtl->args.internal_arg_pointer)
1660 464 : && REGNO (crtl->args.internal_arg_pointer) > LAST_VIRTUAL_REGISTER)
1661 0 : emit_insn_before (seq, parm_birth_insn);
1662 : else
1663 464 : emit_insn_before (seq, NEXT_INSN (entry_of_function ()));
1664 464 : pop_topmost_sequence ();
1665 464 : return temp;
1666 : }
1667 : }
1668 :
1669 : /* Perform an untyped call and save the state required to perform an
1670 : untyped return of whatever value was returned by the given function. */
1671 :
1672 : static rtx
1673 483 : expand_builtin_apply (rtx function, rtx arguments, rtx argsize)
1674 : {
1675 483 : int size, align, regno;
1676 483 : fixed_size_mode mode;
1677 483 : rtx incoming_args, result, reg, dest, src;
1678 483 : rtx_call_insn *call_insn;
1679 483 : rtx old_stack_level = 0;
1680 483 : rtx call_fusage = 0;
1681 483 : rtx struct_value = targetm.calls.struct_value_rtx (cfun ? TREE_TYPE (cfun->decl) : 0, 0);
1682 :
1683 483 : arguments = convert_memory_address (Pmode, arguments);
1684 :
1685 : /* Create a block where the return registers can be saved. */
1686 483 : result = assign_stack_local (BLKmode, apply_result_size (), -1);
1687 :
1688 : /* Fetch the arg pointer from the ARGUMENTS block. */
1689 483 : incoming_args = gen_reg_rtx (Pmode);
1690 483 : emit_move_insn (incoming_args, gen_rtx_MEM (Pmode, arguments));
1691 483 : if (!STACK_GROWS_DOWNWARD)
1692 : incoming_args = expand_simple_binop (Pmode, MINUS, incoming_args, argsize,
1693 : incoming_args, 0, OPTAB_LIB_WIDEN);
1694 :
1695 : /* Push a new argument block and copy the arguments. Do not allow
1696 : the (potential) memcpy call below to interfere with our stack
1697 : manipulations. */
1698 483 : do_pending_stack_adjust ();
1699 483 : NO_DEFER_POP;
1700 :
1701 : /* Save the stack with nonlocal if available. */
1702 483 : if (targetm.have_save_stack_nonlocal ())
1703 483 : emit_stack_save (SAVE_NONLOCAL, &old_stack_level);
1704 : else
1705 0 : emit_stack_save (SAVE_BLOCK, &old_stack_level);
1706 :
1707 : /* Allocate a block of memory onto the stack and copy the memory
1708 : arguments to the outgoing arguments address. We can pass TRUE
1709 : as the 4th argument because we just saved the stack pointer
1710 : and will restore it right after the call. */
1711 966 : allocate_dynamic_stack_space (argsize, 0, BIGGEST_ALIGNMENT, -1, true);
1712 :
1713 : /* Set DRAP flag to true, even though allocate_dynamic_stack_space
1714 : may have already set current_function_calls_alloca to true.
1715 : current_function_calls_alloca won't be set if argsize is zero,
1716 : so we have to guarantee need_drap is true here. */
1717 483 : if (SUPPORTS_STACK_ALIGNMENT)
1718 483 : crtl->need_drap = true;
1719 :
1720 483 : dest = virtual_outgoing_args_rtx;
1721 483 : if (!STACK_GROWS_DOWNWARD)
1722 : {
1723 : if (CONST_INT_P (argsize))
1724 : dest = plus_constant (Pmode, dest, -INTVAL (argsize));
1725 : else
1726 : dest = gen_rtx_PLUS (Pmode, dest, negate_rtx (Pmode, argsize));
1727 : }
1728 483 : dest = gen_rtx_MEM (BLKmode, dest);
1729 483 : set_mem_align (dest, PARM_BOUNDARY);
1730 483 : src = gen_rtx_MEM (BLKmode, incoming_args);
1731 483 : set_mem_align (src, PARM_BOUNDARY);
1732 483 : emit_block_move (dest, src, argsize, BLOCK_OP_NORMAL);
1733 :
1734 : /* Refer to the argument block. */
1735 483 : apply_args_size ();
1736 483 : arguments = gen_rtx_MEM (BLKmode, arguments);
1737 483 : set_mem_align (arguments, PARM_BOUNDARY);
1738 :
1739 : /* Walk past the arg-pointer and structure value address. */
1740 483 : size = GET_MODE_SIZE (Pmode);
1741 483 : if (struct_value)
1742 0 : size += GET_MODE_SIZE (Pmode);
1743 :
1744 : /* Restore each of the registers previously saved. Make USE insns
1745 : for each of these registers for use in making the call. */
1746 45885 : for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
1747 45402 : if ((mode = apply_args_mode[regno]) != VOIDmode)
1748 : {
1749 7245 : align = GET_MODE_ALIGNMENT (mode) / BITS_PER_UNIT;
1750 7245 : if (size % align != 0)
1751 0 : size = CEIL (size, align) * align;
1752 7245 : reg = gen_rtx_REG (mode, regno);
1753 7245 : emit_move_insn (reg, adjust_address (arguments, mode, size));
1754 7245 : use_reg (&call_fusage, reg);
1755 14490 : size += GET_MODE_SIZE (mode);
1756 : }
1757 :
1758 : /* Restore the structure value address unless this is passed as an
1759 : "invisible" first argument. */
1760 483 : size = GET_MODE_SIZE (Pmode);
1761 483 : if (struct_value)
1762 : {
1763 0 : rtx value = gen_reg_rtx (Pmode);
1764 0 : emit_move_insn (value, adjust_address (arguments, Pmode, size));
1765 0 : emit_move_insn (struct_value, value);
1766 0 : if (REG_P (struct_value))
1767 0 : use_reg (&call_fusage, struct_value);
1768 : }
1769 :
1770 : /* All arguments and registers used for the call are set up by now! */
1771 483 : function = prepare_call_address (NULL, function, NULL, &call_fusage, 0, 0);
1772 :
1773 : /* Ensure address is valid. SYMBOL_REF is already valid, so no need,
1774 : and we don't want to load it into a register as an optimization,
1775 : because prepare_call_address already did it if it should be done. */
1776 483 : if (GET_CODE (function) != SYMBOL_REF)
1777 29 : function = memory_address (FUNCTION_MODE, function);
1778 :
1779 : /* Generate the actual call instruction and save the return value. */
1780 483 : if (targetm.have_untyped_call ())
1781 : {
1782 483 : rtx mem = gen_rtx_MEM (FUNCTION_MODE, function);
1783 483 : rtx_insn *seq = targetm.gen_untyped_call (mem, result,
1784 : result_vector (1, result));
1785 5317 : for (rtx_insn *insn = seq; insn; insn = NEXT_INSN (insn))
1786 4351 : if (CALL_P (insn))
1787 483 : add_reg_note (insn, REG_UNTYPED_CALL, NULL_RTX);
1788 483 : emit_insn (seq);
1789 : }
1790 0 : else if (targetm.have_call_value ())
1791 : {
1792 : rtx valreg = 0;
1793 :
1794 : /* Locate the unique return register. It is not possible to
1795 : express a call that sets more than one return register using
1796 : call_value; use untyped_call for that. In fact, untyped_call
1797 : only needs to save the return registers in the given block. */
1798 0 : for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
1799 0 : if ((mode = apply_result_mode[regno]) != VOIDmode)
1800 : {
1801 0 : gcc_assert (!valreg); /* have_untyped_call required. */
1802 :
1803 0 : valreg = gen_rtx_REG (mode, regno);
1804 : }
1805 :
1806 0 : emit_insn (targetm.gen_call_value (valreg,
1807 : gen_rtx_MEM (FUNCTION_MODE, function),
1808 : const0_rtx, NULL_RTX, const0_rtx));
1809 :
1810 0 : emit_move_insn (adjust_address (result, GET_MODE (valreg), 0), valreg);
1811 : }
1812 : else
1813 0 : gcc_unreachable ();
1814 :
1815 : /* Find the CALL insn we just emitted, and attach the register usage
1816 : information. */
1817 483 : call_insn = last_call_insn ();
1818 483 : add_function_usage_to (call_insn, call_fusage);
1819 :
1820 : /* Restore the stack. */
1821 483 : if (targetm.have_save_stack_nonlocal ())
1822 483 : emit_stack_restore (SAVE_NONLOCAL, old_stack_level);
1823 : else
1824 0 : emit_stack_restore (SAVE_BLOCK, old_stack_level);
1825 483 : fixup_args_size_notes (call_insn, get_last_insn (), 0);
1826 :
1827 483 : OK_DEFER_POP;
1828 :
1829 : /* Return the address of the result block. */
1830 483 : result = copy_addr_to_reg (XEXP (result, 0));
1831 483 : return convert_memory_address (ptr_mode, result);
1832 : }
1833 :
1834 : /* Perform an untyped return. */
1835 :
1836 : static void
1837 379 : expand_builtin_return (rtx result)
1838 : {
1839 379 : int size, align, regno;
1840 379 : fixed_size_mode mode;
1841 379 : rtx reg;
1842 379 : rtx_insn *call_fusage = 0;
1843 :
1844 379 : result = convert_memory_address (Pmode, result);
1845 :
1846 379 : apply_result_size ();
1847 379 : result = gen_rtx_MEM (BLKmode, result);
1848 :
1849 379 : if (targetm.have_untyped_return ())
1850 : {
1851 0 : rtx vector = result_vector (0, result);
1852 0 : emit_jump_insn (targetm.gen_untyped_return (result, vector));
1853 0 : emit_barrier ();
1854 0 : return;
1855 : }
1856 :
1857 : /* Restore the return value and note that each value is used. */
1858 : size = 0;
1859 36005 : for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
1860 35626 : if ((mode = apply_result_mode[regno]) != VOIDmode)
1861 : {
1862 2274 : align = GET_MODE_ALIGNMENT (mode) / BITS_PER_UNIT;
1863 2274 : if (size % align != 0)
1864 7 : size = CEIL (size, align) * align;
1865 2274 : reg = gen_rtx_REG (mode, INCOMING_REGNO (regno));
1866 2274 : emit_move_insn (reg, adjust_address (result, mode, size));
1867 :
1868 2274 : push_to_sequence (call_fusage);
1869 2274 : emit_use (reg);
1870 2274 : call_fusage = end_sequence ();
1871 4548 : size += GET_MODE_SIZE (mode);
1872 : }
1873 :
1874 : /* Put the USE insns before the return. */
1875 379 : emit_insn (call_fusage);
1876 :
1877 : /* Return whatever values was restored by jumping directly to the end
1878 : of the function. */
1879 379 : expand_naked_return ();
1880 : }
1881 :
1882 : /* Used by expand_builtin_classify_type and fold_builtin_classify_type. */
1883 :
1884 : int
1885 2355 : type_to_class (tree type)
1886 : {
1887 2355 : switch (TREE_CODE (type))
1888 : {
1889 : case VOID_TYPE: return void_type_class;
1890 891 : case INTEGER_TYPE: return integer_type_class;
1891 39 : case ENUMERAL_TYPE: return enumeral_type_class;
1892 38 : case BOOLEAN_TYPE: return boolean_type_class;
1893 977 : case POINTER_TYPE: return pointer_type_class;
1894 27 : case REFERENCE_TYPE: return reference_type_class;
1895 36 : case OFFSET_TYPE: return offset_type_class;
1896 132 : case REAL_TYPE: return real_type_class;
1897 40 : case COMPLEX_TYPE: return complex_type_class;
1898 20 : case FUNCTION_TYPE: return function_type_class;
1899 0 : case METHOD_TYPE: return method_type_class;
1900 44 : case RECORD_TYPE: return record_type_class;
1901 44 : case UNION_TYPE:
1902 44 : case QUAL_UNION_TYPE: return union_type_class;
1903 24 : case ARRAY_TYPE: return (TYPE_STRING_FLAG (type)
1904 24 : ? string_type_class : array_type_class);
1905 0 : case LANG_TYPE: return lang_type_class;
1906 0 : case OPAQUE_TYPE: return opaque_type_class;
1907 0 : case BITINT_TYPE: return bitint_type_class;
1908 30 : case VECTOR_TYPE: return vector_type_class;
1909 3 : default: return no_type_class;
1910 : }
1911 : }
1912 :
1913 : /* Expand a call EXP to __builtin_classify_type. */
1914 :
1915 : static rtx
1916 0 : expand_builtin_classify_type (tree exp)
1917 : {
1918 0 : if (call_expr_nargs (exp))
1919 0 : return GEN_INT (type_to_class (TREE_TYPE (CALL_EXPR_ARG (exp, 0))));
1920 0 : return GEN_INT (no_type_class);
1921 : }
1922 :
1923 : /* This helper macro, meant to be used in mathfn_built_in below, determines
1924 : which among a set of builtin math functions is appropriate for a given type
1925 : mode. The `F' (float) and `L' (long double) are automatically generated
1926 : from the 'double' case. If a function supports the _Float<N> and _Float<N>X
1927 : types, there are additional types that are considered with 'F32', 'F64',
1928 : 'F128', etc. suffixes. */
1929 : #define CASE_MATHFN(MATHFN) \
1930 : CASE_CFN_##MATHFN: \
1931 : fcode = BUILT_IN_##MATHFN; fcodef = BUILT_IN_##MATHFN##F ; \
1932 : fcodel = BUILT_IN_##MATHFN##L ; break;
1933 : /* Similar to the above, but also add support for the _Float<N> and _Float<N>X
1934 : types. */
1935 : #define CASE_MATHFN_FLOATN(MATHFN) \
1936 : CASE_CFN_##MATHFN: \
1937 : fcode = BUILT_IN_##MATHFN; fcodef = BUILT_IN_##MATHFN##F ; \
1938 : fcodel = BUILT_IN_##MATHFN##L ; fcodef16 = BUILT_IN_##MATHFN##F16 ; \
1939 : fcodef32 = BUILT_IN_##MATHFN##F32; fcodef64 = BUILT_IN_##MATHFN##F64 ; \
1940 : fcodef128 = BUILT_IN_##MATHFN##F128 ; fcodef32x = BUILT_IN_##MATHFN##F32X ; \
1941 : fcodef64x = BUILT_IN_##MATHFN##F64X ; fcodef128x = BUILT_IN_##MATHFN##F128X ;\
1942 : break;
1943 : /* Similar to above, but appends _R after any F/L suffix. */
1944 : #define CASE_MATHFN_REENT(MATHFN) \
1945 : case CFN_BUILT_IN_##MATHFN##_R: \
1946 : case CFN_BUILT_IN_##MATHFN##F_R: \
1947 : case CFN_BUILT_IN_##MATHFN##L_R: \
1948 : fcode = BUILT_IN_##MATHFN##_R; fcodef = BUILT_IN_##MATHFN##F_R ; \
1949 : fcodel = BUILT_IN_##MATHFN##L_R ; break;
1950 :
1951 : /* Return a function equivalent to FN but operating on floating-point
1952 : values of type TYPE, or END_BUILTINS if no such function exists.
1953 : This is purely an operation on function codes; it does not guarantee
1954 : that the target actually has an implementation of the function. */
1955 :
1956 : static built_in_function
1957 610544 : mathfn_built_in_2 (tree type, combined_fn fn)
1958 : {
1959 610544 : tree mtype;
1960 610544 : built_in_function fcode, fcodef, fcodel;
1961 610544 : built_in_function fcodef16 = END_BUILTINS;
1962 610544 : built_in_function fcodef32 = END_BUILTINS;
1963 610544 : built_in_function fcodef64 = END_BUILTINS;
1964 610544 : built_in_function fcodef128 = END_BUILTINS;
1965 610544 : built_in_function fcodef32x = END_BUILTINS;
1966 610544 : built_in_function fcodef64x = END_BUILTINS;
1967 610544 : built_in_function fcodef128x = END_BUILTINS;
1968 :
1969 : /* If <math.h> has been included somehow, HUGE_VAL and NAN definitions
1970 : break the uses below. */
1971 : #undef HUGE_VAL
1972 : #undef NAN
1973 :
1974 610544 : switch (fn)
1975 : {
1976 : #define SEQ_OF_CASE_MATHFN \
1977 : CASE_MATHFN_FLOATN (ACOS) \
1978 : CASE_MATHFN_FLOATN (ACOSH) \
1979 : CASE_MATHFN_FLOATN (ACOSPI) \
1980 : CASE_MATHFN_FLOATN (ASIN) \
1981 : CASE_MATHFN_FLOATN (ASINH) \
1982 : CASE_MATHFN_FLOATN (ASINPI) \
1983 : CASE_MATHFN_FLOATN (ATAN) \
1984 : CASE_MATHFN_FLOATN (ATAN2) \
1985 : CASE_MATHFN_FLOATN (ATAN2PI) \
1986 : CASE_MATHFN_FLOATN (ATANH) \
1987 : CASE_MATHFN_FLOATN (ATANPI) \
1988 : CASE_MATHFN_FLOATN (CBRT) \
1989 : CASE_MATHFN_FLOATN (CEIL) \
1990 : CASE_MATHFN (CEXPI) \
1991 : CASE_MATHFN_FLOATN (COPYSIGN) \
1992 : CASE_MATHFN_FLOATN (COS) \
1993 : CASE_MATHFN_FLOATN (COSH) \
1994 : CASE_MATHFN_FLOATN (COSPI) \
1995 : CASE_MATHFN (DREM) \
1996 : CASE_MATHFN_FLOATN (ERF) \
1997 : CASE_MATHFN_FLOATN (ERFC) \
1998 : CASE_MATHFN_FLOATN (EXP) \
1999 : CASE_MATHFN (EXP10) \
2000 : CASE_MATHFN_FLOATN (EXP2) \
2001 : CASE_MATHFN_FLOATN (EXPM1) \
2002 : CASE_MATHFN_FLOATN (FABS) \
2003 : CASE_MATHFN_FLOATN (FDIM) \
2004 : CASE_MATHFN_FLOATN (FLOOR) \
2005 : CASE_MATHFN_FLOATN (FMA) \
2006 : CASE_MATHFN_FLOATN (FMAX) \
2007 : CASE_MATHFN_FLOATN (FMIN) \
2008 : CASE_MATHFN_FLOATN (FMOD) \
2009 : CASE_MATHFN_FLOATN (FREXP) \
2010 : CASE_MATHFN (GAMMA) \
2011 : CASE_MATHFN_REENT (GAMMA) /* GAMMA_R */ \
2012 : CASE_MATHFN_FLOATN (HUGE_VAL) \
2013 : CASE_MATHFN_FLOATN (HYPOT) \
2014 : CASE_MATHFN_FLOATN (ILOGB) \
2015 : CASE_MATHFN (ICEIL) \
2016 : CASE_MATHFN (IFLOOR) \
2017 : CASE_MATHFN_FLOATN (INF) \
2018 : CASE_MATHFN (IRINT) \
2019 : CASE_MATHFN (IROUND) \
2020 : CASE_MATHFN (ISINF) \
2021 : CASE_MATHFN (J0) \
2022 : CASE_MATHFN (J1) \
2023 : CASE_MATHFN (JN) \
2024 : CASE_MATHFN (LCEIL) \
2025 : CASE_MATHFN_FLOATN (LDEXP) \
2026 : CASE_MATHFN (LFLOOR) \
2027 : CASE_MATHFN_FLOATN (LGAMMA) \
2028 : CASE_MATHFN_REENT (LGAMMA) /* LGAMMA_R */ \
2029 : CASE_MATHFN (LLCEIL) \
2030 : CASE_MATHFN (LLFLOOR) \
2031 : CASE_MATHFN_FLOATN (LLRINT) \
2032 : CASE_MATHFN_FLOATN (LLROUND) \
2033 : CASE_MATHFN_FLOATN (LOG) \
2034 : CASE_MATHFN_FLOATN (LOG10) \
2035 : CASE_MATHFN_FLOATN (LOG1P) \
2036 : CASE_MATHFN_FLOATN (LOG2) \
2037 : CASE_MATHFN_FLOATN (LOGB) \
2038 : CASE_MATHFN_FLOATN (LRINT) \
2039 : CASE_MATHFN_FLOATN (LROUND) \
2040 : CASE_MATHFN_FLOATN (MODF) \
2041 : CASE_MATHFN_FLOATN (NAN) \
2042 : CASE_MATHFN_FLOATN (NANS) \
2043 : CASE_MATHFN_FLOATN (NEARBYINT) \
2044 : CASE_MATHFN_FLOATN (NEXTAFTER) \
2045 : CASE_MATHFN (NEXTTOWARD) \
2046 : CASE_MATHFN_FLOATN (POW) \
2047 : CASE_MATHFN (POWI) \
2048 : CASE_MATHFN (POW10) \
2049 : CASE_MATHFN_FLOATN (REMAINDER) \
2050 : CASE_MATHFN_FLOATN (REMQUO) \
2051 : CASE_MATHFN_FLOATN (RINT) \
2052 : CASE_MATHFN_FLOATN (ROUND) \
2053 : CASE_MATHFN_FLOATN (ROUNDEVEN) \
2054 : CASE_MATHFN (SCALB) \
2055 : CASE_MATHFN_FLOATN (SCALBLN) \
2056 : CASE_MATHFN_FLOATN (SCALBN) \
2057 : CASE_MATHFN (SIGNBIT) \
2058 : CASE_MATHFN (SIGNIFICAND) \
2059 : CASE_MATHFN_FLOATN (SIN) \
2060 : CASE_MATHFN (SINCOS) \
2061 : CASE_MATHFN_FLOATN (SINH) \
2062 : CASE_MATHFN_FLOATN (SINPI) \
2063 : CASE_MATHFN_FLOATN (SQRT) \
2064 : CASE_MATHFN_FLOATN (TAN) \
2065 : CASE_MATHFN_FLOATN (TANH) \
2066 : CASE_MATHFN_FLOATN (TANPI) \
2067 : CASE_MATHFN_FLOATN (TGAMMA) \
2068 : CASE_MATHFN_FLOATN (TRUNC) \
2069 : CASE_MATHFN (Y0) \
2070 : CASE_MATHFN (Y1) \
2071 : CASE_MATHFN (YN)
2072 :
2073 610480 : SEQ_OF_CASE_MATHFN
2074 :
2075 : default:
2076 : return END_BUILTINS;
2077 : }
2078 :
2079 610544 : mtype = TYPE_MAIN_VARIANT (type);
2080 610544 : if (mtype == double_type_node)
2081 : return fcode;
2082 570846 : else if (mtype == float_type_node)
2083 : return fcodef;
2084 525152 : else if (mtype == long_double_type_node)
2085 : return fcodel;
2086 492527 : else if (mtype == float16_type_node)
2087 : return fcodef16;
2088 492479 : else if (mtype == float32_type_node)
2089 : return fcodef32;
2090 492479 : else if (mtype == float64_type_node)
2091 : return fcodef64;
2092 492479 : else if (mtype == float128_type_node)
2093 : return fcodef128;
2094 484975 : else if (mtype == float32x_type_node)
2095 : return fcodef32x;
2096 484975 : else if (mtype == float64x_type_node)
2097 : return fcodef64x;
2098 484975 : else if (mtype == float128x_type_node)
2099 : return fcodef128x;
2100 : else
2101 484975 : return END_BUILTINS;
2102 : }
2103 :
2104 : #undef CASE_MATHFN
2105 : #undef CASE_MATHFN_FLOATN
2106 : #undef CASE_MATHFN_REENT
2107 :
2108 : /* Return mathematic function equivalent to FN but operating directly on TYPE,
2109 : if available. If IMPLICIT_P is true use the implicit builtin declaration,
2110 : otherwise use the explicit declaration. If we can't do the conversion,
2111 : return null. */
2112 :
2113 : static tree
2114 610399 : mathfn_built_in_1 (tree type, combined_fn fn, bool implicit_p)
2115 : {
2116 610399 : built_in_function fcode2 = mathfn_built_in_2 (type, fn);
2117 610399 : if (fcode2 == END_BUILTINS)
2118 : return NULL_TREE;
2119 :
2120 121776 : if (implicit_p && !builtin_decl_implicit_p (fcode2))
2121 : return NULL_TREE;
2122 :
2123 117823 : return builtin_decl_explicit (fcode2);
2124 : }
2125 :
2126 : /* Like mathfn_built_in_1, but always use the implicit array. */
2127 :
2128 : tree
2129 276 : mathfn_built_in (tree type, combined_fn fn)
2130 : {
2131 276 : return mathfn_built_in_1 (type, fn, /*implicit=*/ 1);
2132 : }
2133 :
2134 : /* Like mathfn_built_in_1, but always use the explicit array. */
2135 :
2136 : tree
2137 0 : mathfn_built_in_explicit (tree type, combined_fn fn)
2138 : {
2139 0 : return mathfn_built_in_1 (type, fn, /*implicit=*/ 0);
2140 : }
2141 :
2142 : /* Like mathfn_built_in_1, but take a built_in_function and
2143 : always use the implicit array. */
2144 :
2145 : tree
2146 609900 : mathfn_built_in (tree type, enum built_in_function fn)
2147 : {
2148 609900 : return mathfn_built_in_1 (type, as_combined_fn (fn), /*implicit=*/ 1);
2149 : }
2150 :
2151 : /* Return the type associated with a built in function, i.e., the one
2152 : to be passed to mathfn_built_in to get the type-specific
2153 : function. */
2154 :
2155 : tree
2156 1290 : mathfn_built_in_type (combined_fn fn)
2157 : {
2158 : #define CASE_MATHFN(MATHFN) \
2159 : case CFN_BUILT_IN_##MATHFN: \
2160 : return double_type_node; \
2161 : case CFN_BUILT_IN_##MATHFN##F: \
2162 : return float_type_node; \
2163 : case CFN_BUILT_IN_##MATHFN##L: \
2164 : return long_double_type_node;
2165 :
2166 : #define CASE_MATHFN_FLOATN(MATHFN) \
2167 : CASE_MATHFN(MATHFN) \
2168 : case CFN_BUILT_IN_##MATHFN##F16: \
2169 : return float16_type_node; \
2170 : case CFN_BUILT_IN_##MATHFN##F32: \
2171 : return float32_type_node; \
2172 : case CFN_BUILT_IN_##MATHFN##F64: \
2173 : return float64_type_node; \
2174 : case CFN_BUILT_IN_##MATHFN##F128: \
2175 : return float128_type_node; \
2176 : case CFN_BUILT_IN_##MATHFN##F32X: \
2177 : return float32x_type_node; \
2178 : case CFN_BUILT_IN_##MATHFN##F64X: \
2179 : return float64x_type_node; \
2180 : case CFN_BUILT_IN_##MATHFN##F128X: \
2181 : return float128x_type_node;
2182 :
2183 : /* Similar to above, but appends _R after any F/L suffix. */
2184 : #define CASE_MATHFN_REENT(MATHFN) \
2185 : case CFN_BUILT_IN_##MATHFN##_R: \
2186 : return double_type_node; \
2187 : case CFN_BUILT_IN_##MATHFN##F_R: \
2188 : return float_type_node; \
2189 : case CFN_BUILT_IN_##MATHFN##L_R: \
2190 : return long_double_type_node;
2191 :
2192 1290 : switch (fn)
2193 : {
2194 1288 : SEQ_OF_CASE_MATHFN
2195 :
2196 : default:
2197 : return NULL_TREE;
2198 : }
2199 :
2200 : #undef CASE_MATHFN
2201 : #undef CASE_MATHFN_FLOATN
2202 : #undef CASE_MATHFN_REENT
2203 : #undef SEQ_OF_CASE_MATHFN
2204 : }
2205 :
2206 : /* Check whether there is an internal function associated with function FN
2207 : and return type RETURN_TYPE. Return the function if so, otherwise return
2208 : IFN_LAST.
2209 :
2210 : Note that this function only tests whether the function is defined in
2211 : internals.def, not whether it is actually available on the target. */
2212 :
2213 : static internal_fn
2214 14153889 : associated_internal_fn (built_in_function fn, tree return_type)
2215 : {
2216 14153889 : switch (fn)
2217 : {
2218 : #define DEF_INTERNAL_FLT_FN(NAME, FLAGS, OPTAB, TYPE) \
2219 : CASE_FLT_FN (BUILT_IN_##NAME): return IFN_##NAME;
2220 : #define DEF_INTERNAL_FLT_FLOATN_FN(NAME, FLAGS, OPTAB, TYPE) \
2221 : CASE_FLT_FN (BUILT_IN_##NAME): return IFN_##NAME; \
2222 : CASE_FLT_FN_FLOATN_NX (BUILT_IN_##NAME): return IFN_##NAME;
2223 : #define DEF_INTERNAL_INT_FN(NAME, FLAGS, OPTAB, TYPE) \
2224 : CASE_INT_FN (BUILT_IN_##NAME): return IFN_##NAME;
2225 : #include "internal-fn.def"
2226 :
2227 : CASE_FLT_FN (BUILT_IN_POW10):
2228 : return IFN_EXP10;
2229 :
2230 : CASE_FLT_FN (BUILT_IN_DREM):
2231 : return IFN_REMAINDER;
2232 :
2233 19587 : CASE_FLT_FN (BUILT_IN_SCALBN):
2234 19587 : CASE_FLT_FN (BUILT_IN_SCALBLN):
2235 19587 : if (REAL_MODE_FORMAT (TYPE_MODE (return_type))->b == 2)
2236 : return IFN_LDEXP;
2237 : return IFN_LAST;
2238 715 : case BUILT_IN_CRC8_DATA8:
2239 715 : case BUILT_IN_CRC16_DATA8:
2240 715 : case BUILT_IN_CRC16_DATA16:
2241 715 : case BUILT_IN_CRC32_DATA8:
2242 715 : case BUILT_IN_CRC32_DATA16:
2243 715 : case BUILT_IN_CRC32_DATA32:
2244 715 : case BUILT_IN_CRC64_DATA8:
2245 715 : case BUILT_IN_CRC64_DATA16:
2246 715 : case BUILT_IN_CRC64_DATA32:
2247 715 : case BUILT_IN_CRC64_DATA64:
2248 715 : return IFN_CRC;
2249 369 : case BUILT_IN_REV_CRC8_DATA8:
2250 369 : case BUILT_IN_REV_CRC16_DATA8:
2251 369 : case BUILT_IN_REV_CRC16_DATA16:
2252 369 : case BUILT_IN_REV_CRC32_DATA8:
2253 369 : case BUILT_IN_REV_CRC32_DATA16:
2254 369 : case BUILT_IN_REV_CRC32_DATA32:
2255 369 : case BUILT_IN_REV_CRC64_DATA8:
2256 369 : case BUILT_IN_REV_CRC64_DATA16:
2257 369 : case BUILT_IN_REV_CRC64_DATA32:
2258 369 : case BUILT_IN_REV_CRC64_DATA64:
2259 369 : return IFN_CRC_REV;
2260 : default:
2261 : return IFN_LAST;
2262 : }
2263 : }
2264 :
2265 : /* If BUILT_IN_NORMAL function FNDECL has an associated internal function,
2266 : return its code, otherwise return IFN_LAST. Note that this function
2267 : only tests whether the function is defined in internals.def, not whether
2268 : it is actually available on the target. */
2269 :
2270 : internal_fn
2271 642368 : associated_internal_fn (tree fndecl)
2272 : {
2273 642368 : gcc_checking_assert (DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_NORMAL);
2274 642368 : return associated_internal_fn (DECL_FUNCTION_CODE (fndecl),
2275 642368 : TREE_TYPE (TREE_TYPE (fndecl)));
2276 : }
2277 :
2278 : /* Check whether there is an internal function associated with function CFN
2279 : and return type RETURN_TYPE. Return the function if so, otherwise return
2280 : IFN_LAST.
2281 :
2282 : Note that this function only tests whether the function is defined in
2283 : internals.def, not whether it is actually available on the target. */
2284 :
2285 : internal_fn
2286 34758488 : associated_internal_fn (combined_fn cfn, tree return_type)
2287 : {
2288 34758488 : if (internal_fn_p (cfn))
2289 21246967 : return as_internal_fn (cfn);
2290 13511521 : return associated_internal_fn (as_builtin_fn (cfn), return_type);
2291 : }
2292 :
2293 : /* If CALL is a call to a BUILT_IN_NORMAL function that could be replaced
2294 : on the current target by a call to an internal function, return the
2295 : code of that internal function, otherwise return IFN_LAST. The caller
2296 : is responsible for ensuring that any side-effects of the built-in
2297 : call are dealt with correctly. E.g. if CALL sets errno, the caller
2298 : must decide that the errno result isn't needed or make it available
2299 : in some other way. */
2300 :
2301 : internal_fn
2302 878024 : replacement_internal_fn (gcall *call)
2303 : {
2304 878024 : if (gimple_call_builtin_p (call, BUILT_IN_NORMAL))
2305 : {
2306 639478 : internal_fn ifn = associated_internal_fn (gimple_call_fndecl (call));
2307 639478 : if (ifn != IFN_LAST)
2308 : {
2309 59402 : tree_pair types = direct_internal_fn_types (ifn, call);
2310 59402 : optimization_type opt_type = bb_optimization_type (gimple_bb (call));
2311 59402 : if (direct_internal_fn_supported_p (ifn, types, opt_type))
2312 37313 : return ifn;
2313 : }
2314 : }
2315 : return IFN_LAST;
2316 : }
2317 :
2318 : /* Expand a call to the builtin trinary math functions (fma).
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 :
2325 : static rtx
2326 368 : expand_builtin_mathfn_ternary (tree exp, rtx target, rtx subtarget)
2327 : {
2328 368 : optab builtin_optab;
2329 368 : rtx op0, op1, op2, result;
2330 368 : rtx_insn *insns;
2331 368 : tree fndecl = get_callee_fndecl (exp);
2332 368 : tree arg0, arg1, arg2;
2333 368 : machine_mode mode;
2334 :
2335 368 : if (!validate_arglist (exp, REAL_TYPE, REAL_TYPE, REAL_TYPE, VOID_TYPE))
2336 : return NULL_RTX;
2337 :
2338 368 : arg0 = CALL_EXPR_ARG (exp, 0);
2339 368 : arg1 = CALL_EXPR_ARG (exp, 1);
2340 368 : arg2 = CALL_EXPR_ARG (exp, 2);
2341 :
2342 368 : switch (DECL_FUNCTION_CODE (fndecl))
2343 : {
2344 368 : CASE_FLT_FN (BUILT_IN_FMA):
2345 368 : CASE_FLT_FN_FLOATN_NX (BUILT_IN_FMA):
2346 368 : builtin_optab = fma_optab; break;
2347 0 : default:
2348 0 : gcc_unreachable ();
2349 : }
2350 :
2351 : /* Make a suitable register to place result in. */
2352 368 : mode = TYPE_MODE (TREE_TYPE (exp));
2353 :
2354 : /* Before working hard, check whether the instruction is available. */
2355 368 : if (optab_handler (builtin_optab, mode) == CODE_FOR_nothing)
2356 : return NULL_RTX;
2357 :
2358 0 : result = gen_reg_rtx (mode);
2359 :
2360 : /* Always stabilize the argument list. */
2361 0 : CALL_EXPR_ARG (exp, 0) = arg0 = builtin_save_expr (arg0);
2362 0 : CALL_EXPR_ARG (exp, 1) = arg1 = builtin_save_expr (arg1);
2363 0 : CALL_EXPR_ARG (exp, 2) = arg2 = builtin_save_expr (arg2);
2364 :
2365 0 : op0 = expand_expr (arg0, subtarget, VOIDmode, EXPAND_NORMAL);
2366 0 : op1 = expand_normal (arg1);
2367 0 : op2 = expand_normal (arg2);
2368 :
2369 0 : start_sequence ();
2370 :
2371 : /* Compute into RESULT.
2372 : Set RESULT to wherever the result comes back. */
2373 0 : result = expand_ternary_op (mode, builtin_optab, op0, op1, op2,
2374 : result, 0);
2375 :
2376 : /* If we were unable to expand via the builtin, stop the sequence
2377 : (without outputting the insns) and call to the library function
2378 : with the stabilized argument list. */
2379 0 : if (result == 0)
2380 : {
2381 0 : end_sequence ();
2382 0 : return expand_call (exp, target, target == const0_rtx);
2383 : }
2384 :
2385 : /* Output the entire sequence. */
2386 0 : insns = end_sequence ();
2387 0 : emit_insn (insns);
2388 :
2389 0 : return result;
2390 : }
2391 :
2392 : /* Expand a call to the builtin sin and cos math functions.
2393 : Return NULL_RTX if a normal call should be emitted rather than expanding the
2394 : function in-line. EXP is the expression that is a call to the builtin
2395 : function; if convenient, the result should be placed in TARGET.
2396 : SUBTARGET may be used as the target for computing one of EXP's
2397 : operands. */
2398 :
2399 : static rtx
2400 47 : expand_builtin_mathfn_3 (tree exp, rtx target, rtx subtarget)
2401 : {
2402 47 : optab builtin_optab;
2403 47 : rtx op0;
2404 47 : rtx_insn *insns;
2405 47 : tree fndecl = get_callee_fndecl (exp);
2406 47 : machine_mode mode;
2407 47 : tree arg;
2408 :
2409 47 : if (!validate_arglist (exp, REAL_TYPE, VOID_TYPE))
2410 : return NULL_RTX;
2411 :
2412 39 : arg = CALL_EXPR_ARG (exp, 0);
2413 :
2414 39 : switch (DECL_FUNCTION_CODE (fndecl))
2415 : {
2416 39 : CASE_FLT_FN (BUILT_IN_SIN):
2417 39 : CASE_FLT_FN (BUILT_IN_COS):
2418 39 : builtin_optab = sincos_optab; break;
2419 0 : default:
2420 0 : gcc_unreachable ();
2421 : }
2422 :
2423 : /* Make a suitable register to place result in. */
2424 39 : mode = TYPE_MODE (TREE_TYPE (exp));
2425 :
2426 : /* Check if sincos insn is available, otherwise fallback
2427 : to sin or cos insn. */
2428 39 : if (optab_handler (builtin_optab, mode) == CODE_FOR_nothing)
2429 39 : switch (DECL_FUNCTION_CODE (fndecl))
2430 : {
2431 : CASE_FLT_FN (BUILT_IN_SIN):
2432 : builtin_optab = sin_optab; break;
2433 14 : CASE_FLT_FN (BUILT_IN_COS):
2434 14 : builtin_optab = cos_optab; break;
2435 0 : default:
2436 0 : gcc_unreachable ();
2437 : }
2438 :
2439 : /* Before working hard, check whether the instruction is available. */
2440 39 : if (optab_handler (builtin_optab, mode) != CODE_FOR_nothing)
2441 : {
2442 0 : rtx result = gen_reg_rtx (mode);
2443 :
2444 : /* Wrap the computation of the argument in a SAVE_EXPR, as we may
2445 : need to expand the argument again. This way, we will not perform
2446 : side-effects more the once. */
2447 0 : CALL_EXPR_ARG (exp, 0) = arg = builtin_save_expr (arg);
2448 :
2449 0 : op0 = expand_expr (arg, subtarget, VOIDmode, EXPAND_NORMAL);
2450 :
2451 0 : start_sequence ();
2452 :
2453 : /* Compute into RESULT.
2454 : Set RESULT to wherever the result comes back. */
2455 0 : if (builtin_optab == sincos_optab)
2456 : {
2457 0 : int ok;
2458 :
2459 0 : switch (DECL_FUNCTION_CODE (fndecl))
2460 : {
2461 0 : CASE_FLT_FN (BUILT_IN_SIN):
2462 0 : ok = expand_twoval_unop (builtin_optab, op0, 0, result, 0);
2463 0 : break;
2464 0 : CASE_FLT_FN (BUILT_IN_COS):
2465 0 : ok = expand_twoval_unop (builtin_optab, op0, result, 0, 0);
2466 0 : break;
2467 0 : default:
2468 0 : gcc_unreachable ();
2469 : }
2470 0 : gcc_assert (ok);
2471 : }
2472 : else
2473 0 : result = expand_unop (mode, builtin_optab, op0, result, 0);
2474 :
2475 0 : if (result != 0)
2476 : {
2477 : /* Output the entire sequence. */
2478 0 : insns = end_sequence ();
2479 0 : emit_insn (insns);
2480 0 : return result;
2481 : }
2482 :
2483 : /* If we were unable to expand via the builtin, stop the sequence
2484 : (without outputting the insns) and call to the library function
2485 : with the stabilized argument list. */
2486 0 : end_sequence ();
2487 : }
2488 :
2489 39 : return expand_call (exp, target, target == const0_rtx);
2490 : }
2491 :
2492 : /* Given an interclass math builtin decl FNDECL and it's argument ARG
2493 : return an RTL instruction code that implements the functionality.
2494 : If that isn't possible or available return CODE_FOR_nothing. */
2495 :
2496 : static enum insn_code
2497 1826619 : interclass_mathfn_icode (tree arg, tree fndecl)
2498 : {
2499 1826619 : bool errno_set = false;
2500 1826619 : optab builtin_optab = unknown_optab;
2501 1826619 : machine_mode mode;
2502 :
2503 1826619 : switch (DECL_FUNCTION_CODE (fndecl))
2504 : {
2505 4 : CASE_FLT_FN (BUILT_IN_ILOGB):
2506 4 : errno_set = true;
2507 4 : builtin_optab = ilogb_optab;
2508 4 : break;
2509 711704 : CASE_FLT_FN (BUILT_IN_ISINF):
2510 711704 : builtin_optab = isinf_optab;
2511 711704 : break;
2512 628227 : case BUILT_IN_ISFINITE:
2513 628227 : builtin_optab = isfinite_optab;
2514 628227 : break;
2515 240988 : case BUILT_IN_ISNORMAL:
2516 240988 : builtin_optab = isnormal_optab;
2517 240988 : break;
2518 243619 : CASE_FLT_FN (BUILT_IN_ISNAN):
2519 243619 : builtin_optab = isnan_optab;
2520 243619 : break;
2521 : CASE_FLT_FN (BUILT_IN_FINITE):
2522 : case BUILT_IN_FINITED32:
2523 : case BUILT_IN_FINITED64:
2524 : case BUILT_IN_FINITED128:
2525 : case BUILT_IN_ISINFD32:
2526 : case BUILT_IN_ISINFD64:
2527 : case BUILT_IN_ISINFD128:
2528 : case BUILT_IN_ISNAND32:
2529 : case BUILT_IN_ISNAND64:
2530 : case BUILT_IN_ISNAND128:
2531 : /* These builtins have no optabs (yet). */
2532 : break;
2533 0 : default:
2534 0 : gcc_unreachable ();
2535 : }
2536 :
2537 : /* There's no easy way to detect the case we need to set EDOM. */
2538 1826619 : if (flag_errno_math && errno_set)
2539 : return CODE_FOR_nothing;
2540 :
2541 : /* Optab mode depends on the mode of the input argument. */
2542 1826619 : mode = TYPE_MODE (TREE_TYPE (arg));
2543 :
2544 1826619 : if (builtin_optab)
2545 1824542 : return optab_handler (builtin_optab, mode);
2546 : return CODE_FOR_nothing;
2547 : }
2548 :
2549 : /* Expand a call to one of the builtin math functions that operate on
2550 : floating point argument and output an integer result (ilogb, isinf,
2551 : isnan, etc).
2552 : Return 0 if a normal call should be emitted rather than expanding the
2553 : function in-line. EXP is the expression that is a call to the builtin
2554 : function; if convenient, the result should be placed in TARGET. */
2555 :
2556 : static rtx
2557 4 : expand_builtin_interclass_mathfn (tree exp, rtx target)
2558 : {
2559 4 : enum insn_code icode = CODE_FOR_nothing;
2560 4 : rtx op0;
2561 4 : tree fndecl = get_callee_fndecl (exp);
2562 4 : machine_mode mode;
2563 4 : tree arg;
2564 :
2565 4 : if (!validate_arglist (exp, REAL_TYPE, VOID_TYPE))
2566 : return NULL_RTX;
2567 :
2568 4 : arg = CALL_EXPR_ARG (exp, 0);
2569 4 : icode = interclass_mathfn_icode (arg, fndecl);
2570 4 : mode = TYPE_MODE (TREE_TYPE (arg));
2571 :
2572 4 : if (icode != CODE_FOR_nothing)
2573 : {
2574 2 : class expand_operand ops[1];
2575 2 : rtx_insn *last = get_last_insn ();
2576 2 : tree orig_arg = arg;
2577 :
2578 : /* Wrap the computation of the argument in a SAVE_EXPR, as we may
2579 : need to expand the argument again. This way, we will not perform
2580 : side-effects more the once. */
2581 2 : CALL_EXPR_ARG (exp, 0) = arg = builtin_save_expr (arg);
2582 :
2583 2 : op0 = expand_expr (arg, NULL_RTX, VOIDmode, EXPAND_NORMAL);
2584 :
2585 2 : if (mode != GET_MODE (op0))
2586 0 : op0 = convert_to_mode (mode, op0, 0);
2587 :
2588 2 : create_output_operand (&ops[0], target, TYPE_MODE (TREE_TYPE (exp)));
2589 2 : if (maybe_legitimize_operands (icode, 0, 1, ops)
2590 2 : && maybe_emit_unop_insn (icode, ops[0].value, op0, UNKNOWN))
2591 1 : return ops[0].value;
2592 :
2593 1 : delete_insns_since (last);
2594 1 : CALL_EXPR_ARG (exp, 0) = orig_arg;
2595 : }
2596 :
2597 : return NULL_RTX;
2598 : }
2599 :
2600 : /* Expand a call to the builtin sincos math function.
2601 : Return NULL_RTX if a normal call should be emitted rather than expanding the
2602 : function in-line. EXP is the expression that is a call to the builtin
2603 : function. */
2604 :
2605 : static rtx
2606 3 : expand_builtin_sincos (tree exp)
2607 : {
2608 3 : rtx op0, op1, op2, target1, target2;
2609 3 : machine_mode mode;
2610 3 : tree arg, sinp, cosp;
2611 3 : int result;
2612 3 : location_t loc = EXPR_LOCATION (exp);
2613 3 : tree alias_type, alias_off;
2614 :
2615 3 : if (!validate_arglist (exp, REAL_TYPE,
2616 : POINTER_TYPE, POINTER_TYPE, VOID_TYPE))
2617 : return NULL_RTX;
2618 :
2619 3 : arg = CALL_EXPR_ARG (exp, 0);
2620 3 : sinp = CALL_EXPR_ARG (exp, 1);
2621 3 : cosp = CALL_EXPR_ARG (exp, 2);
2622 :
2623 : /* Make a suitable register to place result in. */
2624 3 : mode = TYPE_MODE (TREE_TYPE (arg));
2625 :
2626 : /* Check if sincos insn is available, otherwise emit the call. */
2627 3 : if (optab_handler (sincos_optab, mode) == CODE_FOR_nothing)
2628 : return NULL_RTX;
2629 :
2630 0 : target1 = gen_reg_rtx (mode);
2631 0 : target2 = gen_reg_rtx (mode);
2632 :
2633 0 : op0 = expand_normal (arg);
2634 0 : alias_type = build_pointer_type_for_mode (TREE_TYPE (arg), ptr_mode, true);
2635 0 : alias_off = build_int_cst (alias_type, 0);
2636 0 : op1 = expand_normal (fold_build2_loc (loc, MEM_REF, TREE_TYPE (arg),
2637 : sinp, alias_off));
2638 0 : op2 = expand_normal (fold_build2_loc (loc, MEM_REF, TREE_TYPE (arg),
2639 : cosp, alias_off));
2640 :
2641 : /* Compute into target1 and target2.
2642 : Set TARGET to wherever the result comes back. */
2643 0 : result = expand_twoval_unop (sincos_optab, op0, target2, target1, 0);
2644 0 : gcc_assert (result);
2645 :
2646 : /* Move target1 and target2 to the memory locations indicated
2647 : by op1 and op2. */
2648 0 : emit_move_insn (op1, target1);
2649 0 : emit_move_insn (op2, target2);
2650 :
2651 0 : return const0_rtx;
2652 : }
2653 :
2654 : /* Expand call EXP to the fegetround builtin (from C99 fenv.h), returning the
2655 : result and setting it in TARGET. Otherwise return NULL_RTX on failure. */
2656 : static rtx
2657 60 : expand_builtin_fegetround (tree exp, rtx target, machine_mode target_mode)
2658 : {
2659 60 : if (!validate_arglist (exp, VOID_TYPE))
2660 : return NULL_RTX;
2661 :
2662 60 : insn_code icode = direct_optab_handler (fegetround_optab, SImode);
2663 60 : if (icode == CODE_FOR_nothing)
2664 : return NULL_RTX;
2665 :
2666 0 : if (target == 0
2667 0 : || GET_MODE (target) != target_mode
2668 0 : || !(*insn_data[icode].operand[0].predicate) (target, target_mode))
2669 0 : target = gen_reg_rtx (target_mode);
2670 :
2671 0 : rtx pat = GEN_FCN (icode) (target);
2672 0 : if (!pat)
2673 : return NULL_RTX;
2674 0 : emit_insn (pat);
2675 :
2676 0 : return target;
2677 : }
2678 :
2679 : /* Expand call EXP to either feclearexcept or feraiseexcept builtins (from C99
2680 : fenv.h), returning the result and setting it in TARGET. Otherwise return
2681 : NULL_RTX on failure. */
2682 : static rtx
2683 1896 : expand_builtin_feclear_feraise_except (tree exp, rtx target,
2684 : machine_mode target_mode, optab op_optab)
2685 : {
2686 1896 : if (!validate_arglist (exp, INTEGER_TYPE, VOID_TYPE))
2687 : return NULL_RTX;
2688 1896 : rtx op0 = expand_normal (CALL_EXPR_ARG (exp, 0));
2689 :
2690 1896 : insn_code icode = direct_optab_handler (op_optab, SImode);
2691 1896 : if (icode == CODE_FOR_nothing)
2692 : return NULL_RTX;
2693 :
2694 0 : if (!(*insn_data[icode].operand[1].predicate) (op0, GET_MODE (op0)))
2695 : return NULL_RTX;
2696 :
2697 0 : if (target == 0
2698 0 : || GET_MODE (target) != target_mode
2699 0 : || !(*insn_data[icode].operand[0].predicate) (target, target_mode))
2700 0 : target = gen_reg_rtx (target_mode);
2701 :
2702 0 : rtx pat = GEN_FCN (icode) (target, op0);
2703 0 : if (!pat)
2704 : return NULL_RTX;
2705 0 : emit_insn (pat);
2706 :
2707 0 : return target;
2708 : }
2709 :
2710 : /* Expand a call to the internal cexpi builtin to the sincos math function.
2711 : EXP is the expression that is a call to the builtin function; if convenient,
2712 : the result should be placed in TARGET. */
2713 :
2714 : static rtx
2715 170 : expand_builtin_cexpi (tree exp, rtx target)
2716 : {
2717 170 : tree fndecl = get_callee_fndecl (exp);
2718 170 : tree arg, type;
2719 170 : machine_mode mode;
2720 170 : rtx op0, op1, op2;
2721 170 : location_t loc = EXPR_LOCATION (exp);
2722 :
2723 170 : if (!validate_arglist (exp, REAL_TYPE, VOID_TYPE))
2724 : return NULL_RTX;
2725 :
2726 170 : arg = CALL_EXPR_ARG (exp, 0);
2727 170 : type = TREE_TYPE (arg);
2728 170 : mode = TYPE_MODE (TREE_TYPE (arg));
2729 :
2730 : /* Try expanding via a sincos optab, fall back to emitting a libcall
2731 : to sincos or cexp. We are sure we have sincos or cexp because cexpi
2732 : is only generated from sincos, cexp or if we have either of them. */
2733 170 : if (optab_handler (sincos_optab, mode) != CODE_FOR_nothing)
2734 : {
2735 6 : op1 = gen_reg_rtx (mode);
2736 6 : op2 = gen_reg_rtx (mode);
2737 :
2738 6 : op0 = expand_expr (arg, NULL_RTX, VOIDmode, EXPAND_NORMAL);
2739 :
2740 : /* Compute into op1 and op2. */
2741 6 : expand_twoval_unop (sincos_optab, op0, op2, op1, 0);
2742 : }
2743 164 : else if (targetm.libc_has_function (function_sincos, type))
2744 : {
2745 164 : tree call, fn = NULL_TREE;
2746 164 : tree top1, top2;
2747 164 : rtx op1a, op2a;
2748 :
2749 164 : if (DECL_FUNCTION_CODE (fndecl) == BUILT_IN_CEXPIF)
2750 54 : fn = builtin_decl_explicit (BUILT_IN_SINCOSF);
2751 110 : else if (DECL_FUNCTION_CODE (fndecl) == BUILT_IN_CEXPI)
2752 89 : fn = builtin_decl_explicit (BUILT_IN_SINCOS);
2753 21 : else if (DECL_FUNCTION_CODE (fndecl) == BUILT_IN_CEXPIL)
2754 21 : fn = builtin_decl_explicit (BUILT_IN_SINCOSL);
2755 : else
2756 0 : gcc_unreachable ();
2757 :
2758 164 : op1 = assign_temp (TREE_TYPE (arg), 1, 1);
2759 164 : op2 = assign_temp (TREE_TYPE (arg), 1, 1);
2760 164 : op1a = copy_addr_to_reg (XEXP (op1, 0));
2761 164 : op2a = copy_addr_to_reg (XEXP (op2, 0));
2762 164 : top1 = make_tree (build_pointer_type (TREE_TYPE (arg)), op1a);
2763 164 : top2 = make_tree (build_pointer_type (TREE_TYPE (arg)), op2a);
2764 :
2765 : /* Make sure not to fold the sincos call again. */
2766 164 : call = build1 (ADDR_EXPR, build_pointer_type (TREE_TYPE (fn)), fn);
2767 164 : expand_normal (build_call_nary (TREE_TYPE (TREE_TYPE (fn)),
2768 : call, 3, arg, top1, top2));
2769 : }
2770 : else
2771 : {
2772 0 : tree call, fn = NULL_TREE, narg;
2773 0 : tree ctype = build_complex_type (type);
2774 :
2775 0 : if (DECL_FUNCTION_CODE (fndecl) == BUILT_IN_CEXPIF)
2776 0 : fn = builtin_decl_explicit (BUILT_IN_CEXPF);
2777 0 : else if (DECL_FUNCTION_CODE (fndecl) == BUILT_IN_CEXPI)
2778 0 : fn = builtin_decl_explicit (BUILT_IN_CEXP);
2779 0 : else if (DECL_FUNCTION_CODE (fndecl) == BUILT_IN_CEXPIL)
2780 0 : fn = builtin_decl_explicit (BUILT_IN_CEXPL);
2781 : else
2782 0 : gcc_unreachable ();
2783 :
2784 : /* If we don't have a decl for cexp create one. This is the
2785 : friendliest fallback if the user calls __builtin_cexpi
2786 : without full target C99 function support. */
2787 0 : if (fn == NULL_TREE)
2788 : {
2789 0 : tree fntype;
2790 0 : const char *name = NULL;
2791 :
2792 0 : if (DECL_FUNCTION_CODE (fndecl) == BUILT_IN_CEXPIF)
2793 : name = "cexpf";
2794 0 : else if (DECL_FUNCTION_CODE (fndecl) == BUILT_IN_CEXPI)
2795 : name = "cexp";
2796 0 : else if (DECL_FUNCTION_CODE (fndecl) == BUILT_IN_CEXPIL)
2797 0 : name = "cexpl";
2798 :
2799 0 : fntype = build_function_type_list (ctype, ctype, NULL_TREE);
2800 0 : fn = build_fn_decl (name, fntype);
2801 : }
2802 :
2803 0 : narg = fold_build2_loc (loc, COMPLEX_EXPR, ctype,
2804 : build_real (type, dconst0), arg);
2805 :
2806 : /* Make sure not to fold the cexp call again. */
2807 0 : call = build1 (ADDR_EXPR, build_pointer_type (TREE_TYPE (fn)), fn);
2808 0 : return expand_expr (build_call_nary (ctype, call, 1, narg),
2809 0 : target, VOIDmode, EXPAND_NORMAL);
2810 : }
2811 :
2812 : /* Now build the proper return type. */
2813 340 : return expand_expr (build2 (COMPLEX_EXPR, build_complex_type (type),
2814 170 : make_tree (TREE_TYPE (arg), op2),
2815 170 : make_tree (TREE_TYPE (arg), op1)),
2816 170 : target, VOIDmode, EXPAND_NORMAL);
2817 : }
2818 :
2819 : /* Conveniently construct a function call expression. FNDECL names the
2820 : function to be called, N is the number of arguments, and the "..."
2821 : parameters are the argument expressions. Unlike build_call_exr
2822 : this doesn't fold the call, hence it will always return a CALL_EXPR. */
2823 :
2824 : static tree
2825 136167 : build_call_nofold_loc (location_t loc, tree fndecl, int n, ...)
2826 : {
2827 136167 : va_list ap;
2828 136167 : tree fntype = TREE_TYPE (fndecl);
2829 136167 : tree fn = build1 (ADDR_EXPR, build_pointer_type (fntype), fndecl);
2830 :
2831 136167 : va_start (ap, n);
2832 136167 : fn = build_call_valist (TREE_TYPE (fntype), fn, n, ap);
2833 136167 : va_end (ap);
2834 136167 : SET_EXPR_LOCATION (fn, loc);
2835 136167 : return fn;
2836 : }
2837 :
2838 : /* Expand the __builtin_issignaling builtin. This needs to handle
2839 : all floating point formats that do support NaNs (for those that
2840 : don't it just sets target to 0). */
2841 :
2842 : static rtx
2843 784 : expand_builtin_issignaling (tree exp, rtx target)
2844 : {
2845 784 : if (!validate_arglist (exp, REAL_TYPE, VOID_TYPE))
2846 : return NULL_RTX;
2847 :
2848 784 : tree arg = CALL_EXPR_ARG (exp, 0);
2849 784 : scalar_float_mode fmode = SCALAR_FLOAT_TYPE_MODE (TREE_TYPE (arg));
2850 784 : const struct real_format *fmt = REAL_MODE_FORMAT (fmode);
2851 :
2852 : /* Expand the argument yielding a RTX expression. */
2853 784 : rtx temp = expand_normal (arg);
2854 :
2855 : /* If mode doesn't support NaN, always return 0.
2856 : Don't use !HONOR_SNANS (fmode) here, so there is some possibility of
2857 : __builtin_issignaling working without -fsignaling-nans. Especially
2858 : when -fno-signaling-nans is the default.
2859 : On the other side, MODE_HAS_NANS (fmode) is unnecessary, with
2860 : -ffinite-math-only even __builtin_isnan or __builtin_fpclassify
2861 : fold to 0 or non-NaN/Inf classification. */
2862 784 : if (!HONOR_NANS (fmode))
2863 : {
2864 0 : emit_move_insn (target, const0_rtx);
2865 0 : return target;
2866 : }
2867 :
2868 : /* Check if the back end provides an insn that handles issignaling for the
2869 : argument's mode. */
2870 784 : enum insn_code icode = optab_handler (issignaling_optab, fmode);
2871 784 : if (icode != CODE_FOR_nothing)
2872 : {
2873 142 : rtx_insn *last = get_last_insn ();
2874 142 : rtx this_target = gen_reg_rtx (TYPE_MODE (TREE_TYPE (exp)));
2875 142 : if (maybe_emit_unop_insn (icode, this_target, temp, UNKNOWN))
2876 : return this_target;
2877 0 : delete_insns_since (last);
2878 : }
2879 :
2880 642 : if (DECIMAL_FLOAT_MODE_P (fmode))
2881 : {
2882 63 : scalar_int_mode imode;
2883 63 : rtx hi;
2884 63 : switch (fmt->ieee_bits)
2885 : {
2886 42 : case 32:
2887 42 : case 64:
2888 42 : imode = int_mode_for_mode (fmode).require ();
2889 42 : temp = gen_lowpart (imode, temp);
2890 42 : break;
2891 21 : case 128:
2892 21 : imode = int_mode_for_size (64, 1).require ();
2893 21 : hi = NULL_RTX;
2894 : /* For decimal128, TImode support isn't always there and even when
2895 : it is, working on the DImode high part is usually better. */
2896 21 : if (!MEM_P (temp))
2897 : {
2898 6 : if (rtx t = force_highpart_subreg (imode, temp, fmode))
2899 : hi = t;
2900 : else
2901 : {
2902 0 : scalar_int_mode imode2;
2903 0 : if (int_mode_for_mode (fmode).exists (&imode2))
2904 : {
2905 0 : rtx temp2 = gen_lowpart (imode2, temp);
2906 0 : if (rtx t = force_highpart_subreg (imode, temp2, imode2))
2907 : hi = t;
2908 : }
2909 : }
2910 0 : if (!hi)
2911 : {
2912 0 : rtx mem = assign_stack_temp (fmode, GET_MODE_SIZE (fmode));
2913 0 : emit_move_insn (mem, temp);
2914 0 : temp = mem;
2915 : }
2916 : }
2917 0 : if (!hi)
2918 : {
2919 15 : poly_int64 offset
2920 15 : = subreg_highpart_offset (imode, GET_MODE (temp));
2921 15 : hi = adjust_address (temp, imode, offset);
2922 : }
2923 : temp = hi;
2924 : break;
2925 0 : default:
2926 0 : gcc_unreachable ();
2927 : }
2928 : /* In all of decimal{32,64,128}, there is MSB sign bit and sNaN
2929 : have 6 bits below it all set. */
2930 63 : rtx val
2931 63 : = GEN_INT (HOST_WIDE_INT_C (0x3f) << (GET_MODE_BITSIZE (imode) - 7));
2932 63 : temp = expand_binop (imode, and_optab, temp, val,
2933 : NULL_RTX, 1, OPTAB_LIB_WIDEN);
2934 63 : temp = emit_store_flag_force (target, EQ, temp, val, imode, 1, 1);
2935 63 : return temp;
2936 : }
2937 :
2938 : /* Only PDP11 has these defined differently but doesn't support NaNs. */
2939 579 : gcc_assert (FLOAT_WORDS_BIG_ENDIAN == WORDS_BIG_ENDIAN);
2940 579 : gcc_assert (fmt->signbit_ro > 0 && fmt->b == 2);
2941 4053 : gcc_assert (MODE_COMPOSITE_P (fmode)
2942 : || (fmt->pnan == fmt->p
2943 : && fmt->signbit_ro == fmt->signbit_rw));
2944 :
2945 579 : switch (fmt->p)
2946 : {
2947 0 : case 106: /* IBM double double */
2948 : /* For IBM double double, recurse on the most significant double. */
2949 0 : gcc_assert (MODE_COMPOSITE_P (fmode));
2950 0 : temp = convert_modes (DFmode, fmode, temp, 0);
2951 0 : fmode = DFmode;
2952 0 : fmt = REAL_MODE_FORMAT (DFmode);
2953 : /* FALLTHRU */
2954 479 : case 8: /* bfloat */
2955 479 : case 11: /* IEEE half */
2956 479 : case 24: /* IEEE single */
2957 479 : case 53: /* IEEE double or Intel extended with rounding to double */
2958 479 : if (fmt->p == 53 && fmt->signbit_ro == 79)
2959 0 : goto extended;
2960 479 : {
2961 479 : scalar_int_mode imode = int_mode_for_mode (fmode).require ();
2962 479 : temp = gen_lowpart (imode, temp);
2963 479 : rtx val = GEN_INT ((HOST_WIDE_INT_M1U << (fmt->p - 2))
2964 : & ~(HOST_WIDE_INT_M1U << fmt->signbit_ro));
2965 479 : if (fmt->qnan_msb_set)
2966 : {
2967 479 : rtx mask = GEN_INT (~(HOST_WIDE_INT_M1U << fmt->signbit_ro));
2968 479 : rtx bit = GEN_INT (HOST_WIDE_INT_1U << (fmt->p - 2));
2969 : /* For non-MIPS/PA IEEE single/double/half or bfloat, expand to:
2970 : ((temp ^ bit) & mask) > val. */
2971 479 : temp = expand_binop (imode, xor_optab, temp, bit,
2972 : NULL_RTX, 1, OPTAB_LIB_WIDEN);
2973 479 : temp = expand_binop (imode, and_optab, temp, mask,
2974 : NULL_RTX, 1, OPTAB_LIB_WIDEN);
2975 479 : temp = emit_store_flag_force (target, GTU, temp, val, imode,
2976 : 1, 1);
2977 : }
2978 : else
2979 : {
2980 : /* For MIPS/PA IEEE single/double, expand to:
2981 : (temp & val) == val. */
2982 0 : temp = expand_binop (imode, and_optab, temp, val,
2983 : NULL_RTX, 1, OPTAB_LIB_WIDEN);
2984 0 : temp = emit_store_flag_force (target, EQ, temp, val, imode,
2985 : 1, 1);
2986 : }
2987 : }
2988 : break;
2989 100 : case 113: /* IEEE quad */
2990 100 : {
2991 100 : rtx hi = NULL_RTX, lo = NULL_RTX;
2992 100 : scalar_int_mode imode = int_mode_for_size (64, 1).require ();
2993 : /* For IEEE quad, TImode support isn't always there and even when
2994 : it is, working on DImode parts is usually better. */
2995 100 : if (!MEM_P (temp))
2996 : {
2997 85 : hi = force_highpart_subreg (imode, temp, fmode);
2998 85 : lo = force_lowpart_subreg (imode, temp, fmode);
2999 85 : if (!hi || !lo)
3000 : {
3001 0 : scalar_int_mode imode2;
3002 0 : if (int_mode_for_mode (fmode).exists (&imode2))
3003 : {
3004 0 : rtx temp2 = gen_lowpart (imode2, temp);
3005 0 : hi = force_highpart_subreg (imode, temp2, imode2);
3006 0 : lo = force_lowpart_subreg (imode, temp2, imode2);
3007 : }
3008 : }
3009 85 : if (!hi || !lo)
3010 : {
3011 0 : rtx mem = assign_stack_temp (fmode, GET_MODE_SIZE (fmode));
3012 0 : emit_move_insn (mem, temp);
3013 0 : temp = mem;
3014 : }
3015 : }
3016 100 : if (!hi || !lo)
3017 : {
3018 15 : poly_int64 offset
3019 15 : = subreg_highpart_offset (imode, GET_MODE (temp));
3020 15 : hi = adjust_address (temp, imode, offset);
3021 15 : offset = subreg_lowpart_offset (imode, GET_MODE (temp));
3022 15 : lo = adjust_address (temp, imode, offset);
3023 : }
3024 100 : rtx val = GEN_INT ((HOST_WIDE_INT_M1U << (fmt->p - 2 - 64))
3025 : & ~(HOST_WIDE_INT_M1U << (fmt->signbit_ro - 64)));
3026 100 : if (fmt->qnan_msb_set)
3027 : {
3028 100 : rtx mask = GEN_INT (~(HOST_WIDE_INT_M1U << (fmt->signbit_ro
3029 : - 64)));
3030 100 : rtx bit = GEN_INT (HOST_WIDE_INT_1U << (fmt->p - 2 - 64));
3031 : /* For non-MIPS/PA IEEE quad, expand to:
3032 : (((hi ^ bit) | ((lo | -lo) >> 63)) & mask) > val. */
3033 100 : rtx nlo = expand_unop (imode, neg_optab, lo, NULL_RTX, 0);
3034 100 : lo = expand_binop (imode, ior_optab, lo, nlo,
3035 : NULL_RTX, 1, OPTAB_LIB_WIDEN);
3036 100 : lo = expand_shift (RSHIFT_EXPR, imode, lo, 63, NULL_RTX, 1);
3037 100 : temp = expand_binop (imode, xor_optab, hi, bit,
3038 : NULL_RTX, 1, OPTAB_LIB_WIDEN);
3039 100 : temp = expand_binop (imode, ior_optab, temp, lo,
3040 : NULL_RTX, 1, OPTAB_LIB_WIDEN);
3041 100 : temp = expand_binop (imode, and_optab, temp, mask,
3042 : NULL_RTX, 1, OPTAB_LIB_WIDEN);
3043 100 : temp = emit_store_flag_force (target, GTU, temp, val, imode,
3044 : 1, 1);
3045 : }
3046 : else
3047 : {
3048 : /* For MIPS/PA IEEE quad, expand to:
3049 : (hi & val) == val. */
3050 0 : temp = expand_binop (imode, and_optab, hi, val,
3051 : NULL_RTX, 1, OPTAB_LIB_WIDEN);
3052 0 : temp = emit_store_flag_force (target, EQ, temp, val, imode,
3053 : 1, 1);
3054 : }
3055 : }
3056 : break;
3057 0 : case 64: /* Intel or Motorola extended */
3058 0 : extended:
3059 0 : {
3060 0 : rtx ex, hi, lo;
3061 0 : scalar_int_mode imode = int_mode_for_size (32, 1).require ();
3062 0 : scalar_int_mode iemode = int_mode_for_size (16, 1).require ();
3063 0 : if (!MEM_P (temp))
3064 : {
3065 0 : rtx mem = assign_stack_temp (fmode, GET_MODE_SIZE (fmode));
3066 0 : emit_move_insn (mem, temp);
3067 0 : temp = mem;
3068 : }
3069 0 : if (fmt->signbit_ro == 95)
3070 : {
3071 : /* Motorola, always big endian, with 16-bit gap in between
3072 : 16-bit sign+exponent and 64-bit mantissa. */
3073 0 : ex = adjust_address (temp, iemode, 0);
3074 0 : hi = adjust_address (temp, imode, 4);
3075 0 : lo = adjust_address (temp, imode, 8);
3076 : }
3077 0 : else if (!WORDS_BIG_ENDIAN)
3078 : {
3079 : /* Intel little endian, 64-bit mantissa followed by 16-bit
3080 : sign+exponent and then either 16 or 48 bits of gap. */
3081 0 : ex = adjust_address (temp, iemode, 8);
3082 0 : hi = adjust_address (temp, imode, 4);
3083 0 : lo = adjust_address (temp, imode, 0);
3084 : }
3085 : else
3086 : {
3087 : /* Big endian Itanium. */
3088 : ex = adjust_address (temp, iemode, 0);
3089 : hi = adjust_address (temp, imode, 2);
3090 : lo = adjust_address (temp, imode, 6);
3091 : }
3092 0 : rtx val = GEN_INT (HOST_WIDE_INT_M1U << 30);
3093 0 : gcc_assert (fmt->qnan_msb_set);
3094 0 : rtx mask = GEN_INT (0x7fff);
3095 0 : rtx bit = GEN_INT (HOST_WIDE_INT_1U << 30);
3096 : /* For Intel/Motorola extended format, expand to:
3097 : (ex & mask) == mask && ((hi ^ bit) | ((lo | -lo) >> 31)) > val. */
3098 0 : rtx nlo = expand_unop (imode, neg_optab, lo, NULL_RTX, 0);
3099 0 : lo = expand_binop (imode, ior_optab, lo, nlo,
3100 : NULL_RTX, 1, OPTAB_LIB_WIDEN);
3101 0 : lo = expand_shift (RSHIFT_EXPR, imode, lo, 31, NULL_RTX, 1);
3102 0 : temp = expand_binop (imode, xor_optab, hi, bit,
3103 : NULL_RTX, 1, OPTAB_LIB_WIDEN);
3104 0 : temp = expand_binop (imode, ior_optab, temp, lo,
3105 : NULL_RTX, 1, OPTAB_LIB_WIDEN);
3106 0 : temp = emit_store_flag_force (target, GTU, temp, val, imode, 1, 1);
3107 0 : ex = expand_binop (iemode, and_optab, ex, mask,
3108 : NULL_RTX, 1, OPTAB_LIB_WIDEN);
3109 0 : ex = emit_store_flag_force (gen_reg_rtx (GET_MODE (temp)), EQ,
3110 : ex, mask, iemode, 1, 1);
3111 0 : temp = expand_binop (GET_MODE (temp), and_optab, temp, ex,
3112 : NULL_RTX, 1, OPTAB_LIB_WIDEN);
3113 : }
3114 0 : break;
3115 0 : default:
3116 0 : gcc_unreachable ();
3117 : }
3118 :
3119 : return temp;
3120 : }
3121 :
3122 : /* Expand a call to one of the builtin rounding functions gcc defines
3123 : as an extension (lfloor and lceil). As these are gcc extensions we
3124 : do not need to worry about setting errno to EDOM.
3125 : If expanding via optab fails, lower expression to (int)(floor(x)).
3126 : EXP is the expression that is a call to the builtin function;
3127 : if convenient, the result should be placed in TARGET. */
3128 :
3129 : static rtx
3130 223 : expand_builtin_int_roundingfn (tree exp, rtx target)
3131 : {
3132 223 : convert_optab builtin_optab;
3133 223 : rtx op0, tmp;
3134 223 : rtx_insn *insns;
3135 223 : tree fndecl = get_callee_fndecl (exp);
3136 223 : enum built_in_function fallback_fn;
3137 223 : tree fallback_fndecl;
3138 223 : machine_mode mode;
3139 223 : tree arg;
3140 :
3141 223 : if (!validate_arglist (exp, REAL_TYPE, VOID_TYPE))
3142 : return NULL_RTX;
3143 :
3144 223 : arg = CALL_EXPR_ARG (exp, 0);
3145 :
3146 223 : switch (DECL_FUNCTION_CODE (fndecl))
3147 : {
3148 : CASE_FLT_FN (BUILT_IN_ICEIL):
3149 : CASE_FLT_FN (BUILT_IN_LCEIL):
3150 : CASE_FLT_FN (BUILT_IN_LLCEIL):
3151 : builtin_optab = lceil_optab;
3152 : fallback_fn = BUILT_IN_CEIL;
3153 : break;
3154 :
3155 112 : CASE_FLT_FN (BUILT_IN_IFLOOR):
3156 112 : CASE_FLT_FN (BUILT_IN_LFLOOR):
3157 112 : CASE_FLT_FN (BUILT_IN_LLFLOOR):
3158 112 : builtin_optab = lfloor_optab;
3159 112 : fallback_fn = BUILT_IN_FLOOR;
3160 112 : break;
3161 :
3162 0 : default:
3163 0 : gcc_unreachable ();
3164 : }
3165 :
3166 : /* Make a suitable register to place result in. */
3167 223 : mode = TYPE_MODE (TREE_TYPE (exp));
3168 :
3169 223 : target = gen_reg_rtx (mode);
3170 :
3171 : /* Wrap the computation of the argument in a SAVE_EXPR, as we may
3172 : need to expand the argument again. This way, we will not perform
3173 : side-effects more the once. */
3174 223 : CALL_EXPR_ARG (exp, 0) = arg = builtin_save_expr (arg);
3175 :
3176 223 : op0 = expand_expr (arg, NULL, VOIDmode, EXPAND_NORMAL);
3177 :
3178 223 : start_sequence ();
3179 :
3180 : /* Compute into TARGET. */
3181 223 : if (expand_sfix_optab (target, op0, builtin_optab))
3182 : {
3183 : /* Output the entire sequence. */
3184 32 : insns = end_sequence ();
3185 32 : emit_insn (insns);
3186 32 : return target;
3187 : }
3188 :
3189 : /* If we were unable to expand via the builtin, stop the sequence
3190 : (without outputting the insns). */
3191 191 : end_sequence ();
3192 :
3193 : /* Fall back to floating point rounding optab. */
3194 191 : fallback_fndecl = mathfn_built_in (TREE_TYPE (arg), fallback_fn);
3195 :
3196 : /* For non-C99 targets we may end up without a fallback fndecl here
3197 : if the user called __builtin_lfloor directly. In this case emit
3198 : a call to the floor/ceil variants nevertheless. This should result
3199 : in the best user experience for not full C99 targets. */
3200 191 : if (fallback_fndecl == NULL_TREE)
3201 : {
3202 0 : tree fntype;
3203 0 : const char *name = NULL;
3204 :
3205 0 : switch (DECL_FUNCTION_CODE (fndecl))
3206 : {
3207 : case BUILT_IN_ICEIL:
3208 : case BUILT_IN_LCEIL:
3209 : case BUILT_IN_LLCEIL:
3210 : name = "ceil";
3211 : break;
3212 0 : case BUILT_IN_ICEILF:
3213 0 : case BUILT_IN_LCEILF:
3214 0 : case BUILT_IN_LLCEILF:
3215 0 : name = "ceilf";
3216 0 : break;
3217 0 : case BUILT_IN_ICEILL:
3218 0 : case BUILT_IN_LCEILL:
3219 0 : case BUILT_IN_LLCEILL:
3220 0 : name = "ceill";
3221 0 : break;
3222 0 : case BUILT_IN_IFLOOR:
3223 0 : case BUILT_IN_LFLOOR:
3224 0 : case BUILT_IN_LLFLOOR:
3225 0 : name = "floor";
3226 0 : break;
3227 0 : case BUILT_IN_IFLOORF:
3228 0 : case BUILT_IN_LFLOORF:
3229 0 : case BUILT_IN_LLFLOORF:
3230 0 : name = "floorf";
3231 0 : break;
3232 0 : case BUILT_IN_IFLOORL:
3233 0 : case BUILT_IN_LFLOORL:
3234 0 : case BUILT_IN_LLFLOORL:
3235 0 : name = "floorl";
3236 0 : break;
3237 0 : default:
3238 0 : gcc_unreachable ();
3239 : }
3240 :
3241 0 : fntype = build_function_type_list (TREE_TYPE (arg),
3242 0 : TREE_TYPE (arg), NULL_TREE);
3243 0 : fallback_fndecl = build_fn_decl (name, fntype);
3244 : }
3245 :
3246 191 : exp = build_call_nofold_loc (EXPR_LOCATION (exp), fallback_fndecl, 1, arg);
3247 :
3248 191 : tmp = expand_normal (exp);
3249 191 : tmp = maybe_emit_group_store (tmp, TREE_TYPE (exp));
3250 :
3251 : /* Truncate the result of floating point optab to integer
3252 : via expand_fix (). */
3253 191 : target = gen_reg_rtx (mode);
3254 191 : expand_fix (target, tmp, 0);
3255 :
3256 191 : return target;
3257 : }
3258 :
3259 : /* Expand a call to one of the builtin math functions doing integer
3260 : conversion (lrint).
3261 : Return 0 if a normal call should be emitted rather than expanding the
3262 : function in-line. EXP is the expression that is a call to the builtin
3263 : function; if convenient, the result should be placed in TARGET. */
3264 :
3265 : static rtx
3266 588 : expand_builtin_int_roundingfn_2 (tree exp, rtx target)
3267 : {
3268 588 : convert_optab builtin_optab;
3269 588 : rtx op0;
3270 588 : rtx_insn *insns;
3271 588 : tree fndecl = get_callee_fndecl (exp);
3272 588 : tree arg;
3273 588 : machine_mode mode;
3274 588 : enum built_in_function fallback_fn = BUILT_IN_NONE;
3275 :
3276 588 : if (!validate_arglist (exp, REAL_TYPE, VOID_TYPE))
3277 : return NULL_RTX;
3278 :
3279 488 : arg = CALL_EXPR_ARG (exp, 0);
3280 :
3281 488 : switch (DECL_FUNCTION_CODE (fndecl))
3282 : {
3283 4 : CASE_FLT_FN (BUILT_IN_IRINT):
3284 4 : fallback_fn = BUILT_IN_LRINT;
3285 : gcc_fallthrough ();
3286 : CASE_FLT_FN (BUILT_IN_LRINT):
3287 : CASE_FLT_FN (BUILT_IN_LLRINT):
3288 : builtin_optab = lrint_optab;
3289 : break;
3290 :
3291 223 : CASE_FLT_FN (BUILT_IN_IROUND):
3292 223 : fallback_fn = BUILT_IN_LROUND;
3293 : gcc_fallthrough ();
3294 : CASE_FLT_FN (BUILT_IN_LROUND):
3295 : CASE_FLT_FN (BUILT_IN_LLROUND):
3296 : builtin_optab = lround_optab;
3297 : break;
3298 :
3299 0 : default:
3300 0 : gcc_unreachable ();
3301 : }
3302 :
3303 : /* There's no easy way to detect the case we need to set EDOM. */
3304 488 : if (flag_errno_math && fallback_fn == BUILT_IN_NONE)
3305 : return NULL_RTX;
3306 :
3307 : /* Make a suitable register to place result in. */
3308 257 : mode = TYPE_MODE (TREE_TYPE (exp));
3309 :
3310 : /* There's no easy way to detect the case we need to set EDOM. */
3311 257 : if (!flag_errno_math)
3312 : {
3313 257 : rtx result = gen_reg_rtx (mode);
3314 :
3315 : /* Wrap the computation of the argument in a SAVE_EXPR, as we may
3316 : need to expand the argument again. This way, we will not perform
3317 : side-effects more the once. */
3318 257 : CALL_EXPR_ARG (exp, 0) = arg = builtin_save_expr (arg);
3319 :
3320 257 : op0 = expand_expr (arg, NULL, VOIDmode, EXPAND_NORMAL);
3321 :
3322 257 : start_sequence ();
3323 :
3324 257 : if (expand_sfix_optab (result, op0, builtin_optab))
3325 : {
3326 : /* Output the entire sequence. */
3327 20 : insns = end_sequence ();
3328 20 : emit_insn (insns);
3329 20 : return result;
3330 : }
3331 :
3332 : /* If we were unable to expand via the builtin, stop the sequence
3333 : (without outputting the insns) and call to the library function
3334 : with the stabilized argument list. */
3335 237 : end_sequence ();
3336 : }
3337 :
3338 237 : if (fallback_fn != BUILT_IN_NONE)
3339 : {
3340 : /* Fall back to rounding to long int. Use implicit_p 0 - for non-C99
3341 : targets, (int) round (x) should never be transformed into
3342 : BUILT_IN_IROUND and if __builtin_iround is called directly, emit
3343 : a call to lround in the hope that the target provides at least some
3344 : C99 functions. This should result in the best user experience for
3345 : not full C99 targets.
3346 : As scalar float conversions with same mode are useless in GIMPLE,
3347 : we can end up e.g. with _Float32 argument passed to float builtin,
3348 : try to get the type from the builtin prototype first. */
3349 223 : tree fallback_fndecl = NULL_TREE;
3350 223 : if (tree argtypes = TYPE_ARG_TYPES (TREE_TYPE (fndecl)))
3351 223 : fallback_fndecl
3352 223 : = mathfn_built_in_1 (TREE_VALUE (argtypes),
3353 : as_combined_fn (fallback_fn), 0);
3354 223 : if (fallback_fndecl == NULL_TREE)
3355 0 : fallback_fndecl
3356 0 : = mathfn_built_in_1 (TREE_TYPE (arg),
3357 : as_combined_fn (fallback_fn), 0);
3358 0 : if (fallback_fndecl)
3359 : {
3360 223 : exp = build_call_nofold_loc (EXPR_LOCATION (exp),
3361 : fallback_fndecl, 1, arg);
3362 :
3363 223 : target = expand_call (exp, NULL_RTX, target == const0_rtx);
3364 223 : target = maybe_emit_group_store (target, TREE_TYPE (exp));
3365 223 : return convert_to_mode (mode, target, 0);
3366 : }
3367 : }
3368 :
3369 14 : return expand_call (exp, target, target == const0_rtx);
3370 : }
3371 :
3372 : /* Expand a call to the powi built-in mathematical function. Return NULL_RTX if
3373 : a normal call should be emitted rather than expanding the function
3374 : in-line. EXP is the expression that is a call to the builtin
3375 : function; if convenient, the result should be placed in TARGET. */
3376 :
3377 : static rtx
3378 292 : expand_builtin_powi (tree exp, rtx target)
3379 : {
3380 292 : tree arg0, arg1;
3381 292 : rtx op0, op1;
3382 292 : machine_mode mode;
3383 292 : machine_mode mode2;
3384 :
3385 292 : if (! validate_arglist (exp, REAL_TYPE, INTEGER_TYPE, VOID_TYPE))
3386 : return NULL_RTX;
3387 :
3388 292 : arg0 = CALL_EXPR_ARG (exp, 0);
3389 292 : arg1 = CALL_EXPR_ARG (exp, 1);
3390 292 : mode = TYPE_MODE (TREE_TYPE (exp));
3391 :
3392 : /* Emit a libcall to libgcc. */
3393 :
3394 : /* Mode of the 2nd argument must match that of an int. */
3395 292 : mode2 = int_mode_for_size (INT_TYPE_SIZE, 0).require ();
3396 :
3397 292 : if (target == NULL_RTX)
3398 0 : target = gen_reg_rtx (mode);
3399 :
3400 292 : op0 = expand_expr (arg0, NULL_RTX, mode, EXPAND_NORMAL);
3401 292 : if (GET_MODE (op0) != mode)
3402 0 : op0 = convert_to_mode (mode, op0, 0);
3403 292 : op1 = expand_expr (arg1, NULL_RTX, mode2, EXPAND_NORMAL);
3404 292 : if (GET_MODE (op1) != mode2)
3405 52 : op1 = convert_to_mode (mode2, op1, 0);
3406 :
3407 292 : target = emit_library_call_value (optab_libfunc (powi_optab, mode),
3408 : target, LCT_CONST, mode,
3409 : op0, mode, op1, mode2);
3410 :
3411 292 : return target;
3412 : }
3413 :
3414 : /* Expand expression EXP which is a call to the strlen builtin. Return
3415 : NULL_RTX if we failed and the caller should emit a normal call, otherwise
3416 : try to get the result in TARGET, if convenient. */
3417 :
3418 : static rtx
3419 14752 : expand_builtin_strlen (tree exp, rtx target,
3420 : machine_mode target_mode)
3421 : {
3422 14752 : if (!validate_arglist (exp, POINTER_TYPE, VOID_TYPE))
3423 : return NULL_RTX;
3424 :
3425 14733 : tree src = CALL_EXPR_ARG (exp, 0);
3426 :
3427 : /* If the length can be computed at compile-time, return it. */
3428 14733 : if (tree len = c_strlen (src, 0))
3429 141 : return expand_expr (len, target, target_mode, EXPAND_NORMAL);
3430 :
3431 : /* If the length can be computed at compile-time and is constant
3432 : integer, but there are side-effects in src, evaluate
3433 : src for side-effects, then return len.
3434 : E.g. x = strlen (i++ ? "xfoo" + 1 : "bar");
3435 : can be optimized into: i++; x = 3; */
3436 14592 : tree len = c_strlen (src, 1);
3437 14592 : if (len && TREE_CODE (len) == INTEGER_CST)
3438 : {
3439 0 : expand_expr (src, const0_rtx, VOIDmode, EXPAND_NORMAL);
3440 0 : return expand_expr (len, target, target_mode, EXPAND_NORMAL);
3441 : }
3442 :
3443 14592 : unsigned int align = get_pointer_alignment (src) / BITS_PER_UNIT;
3444 :
3445 : /* If SRC is not a pointer type, don't do this operation inline. */
3446 14592 : if (align == 0)
3447 : return NULL_RTX;
3448 :
3449 : /* Bail out if we can't compute strlen in the right mode. */
3450 : machine_mode insn_mode;
3451 : enum insn_code icode = CODE_FOR_nothing;
3452 14592 : FOR_EACH_MODE_FROM (insn_mode, target_mode)
3453 : {
3454 14592 : icode = optab_handler (strlen_optab, insn_mode);
3455 14592 : if (icode != CODE_FOR_nothing)
3456 : break;
3457 : }
3458 14592 : if (insn_mode == VOIDmode)
3459 : return NULL_RTX;
3460 :
3461 : /* Make a place to hold the source address. We will not expand
3462 : the actual source until we are sure that the expansion will
3463 : not fail -- there are trees that cannot be expanded twice. */
3464 15208 : rtx src_reg = gen_reg_rtx (Pmode);
3465 :
3466 : /* Mark the beginning of the strlen sequence so we can emit the
3467 : source operand later. */
3468 14592 : rtx_insn *before_strlen = get_last_insn ();
3469 :
3470 14592 : class expand_operand ops[4];
3471 14592 : create_output_operand (&ops[0], target, insn_mode);
3472 14592 : create_fixed_operand (&ops[1], gen_rtx_MEM (BLKmode, src_reg));
3473 14592 : create_integer_operand (&ops[2], 0);
3474 14592 : create_integer_operand (&ops[3], align);
3475 14592 : if (!maybe_expand_insn (icode, 4, ops))
3476 : return NULL_RTX;
3477 :
3478 : /* Check to see if the argument was declared attribute nonstring
3479 : and if so, issue a warning since at this point it's not known
3480 : to be nul-terminated. */
3481 11 : maybe_warn_nonstring_arg (get_callee_fndecl (exp), exp);
3482 :
3483 : /* Now that we are assured of success, expand the source. */
3484 11 : start_sequence ();
3485 15 : rtx pat = expand_expr (src, src_reg, Pmode, EXPAND_NORMAL);
3486 11 : if (pat != src_reg)
3487 : {
3488 : #ifdef POINTERS_EXTEND_UNSIGNED
3489 15 : if (GET_MODE (pat) != Pmode)
3490 0 : pat = convert_to_mode (Pmode, pat,
3491 : POINTERS_EXTEND_UNSIGNED);
3492 : #endif
3493 11 : emit_move_insn (src_reg, pat);
3494 : }
3495 11 : pat = end_sequence ();
3496 :
3497 11 : if (before_strlen)
3498 11 : emit_insn_after (pat, before_strlen);
3499 : else
3500 0 : emit_insn_before (pat, get_insns ());
3501 :
3502 : /* Return the value in the proper mode for this function. */
3503 11 : if (GET_MODE (ops[0].value) == target_mode)
3504 : target = ops[0].value;
3505 0 : else if (target != 0)
3506 0 : convert_move (target, ops[0].value, 0);
3507 : else
3508 0 : target = convert_to_mode (target_mode, ops[0].value, 0);
3509 :
3510 : return target;
3511 : }
3512 :
3513 : /* Expand call EXP to the strnlen built-in, returning the result
3514 : and setting it in TARGET. Otherwise return NULL_RTX on failure. */
3515 :
3516 : static rtx
3517 580 : expand_builtin_strnlen (tree exp, rtx target, machine_mode target_mode)
3518 : {
3519 580 : if (!validate_arglist (exp, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
3520 : return NULL_RTX;
3521 :
3522 571 : tree src = CALL_EXPR_ARG (exp, 0);
3523 571 : tree bound = CALL_EXPR_ARG (exp, 1);
3524 :
3525 571 : if (!bound)
3526 : return NULL_RTX;
3527 :
3528 571 : location_t loc = UNKNOWN_LOCATION;
3529 571 : if (EXPR_HAS_LOCATION (exp))
3530 571 : loc = EXPR_LOCATION (exp);
3531 :
3532 : /* FIXME: Change c_strlen() to return sizetype instead of ssizetype
3533 : so these conversions aren't necessary. */
3534 571 : c_strlen_data lendata = { };
3535 571 : tree len = c_strlen (src, 0, &lendata, 1);
3536 571 : if (len)
3537 63 : len = fold_convert_loc (loc, TREE_TYPE (bound), len);
3538 :
3539 571 : if (TREE_CODE (bound) == INTEGER_CST)
3540 : {
3541 304 : if (!len)
3542 : return NULL_RTX;
3543 :
3544 23 : len = fold_build2_loc (loc, MIN_EXPR, size_type_node, len, bound);
3545 23 : return expand_expr (len, target, target_mode, EXPAND_NORMAL);
3546 : }
3547 :
3548 267 : if (TREE_CODE (bound) != SSA_NAME)
3549 : return NULL_RTX;
3550 :
3551 267 : wide_int min, max;
3552 267 : int_range_max r;
3553 534 : get_range_query (cfun)->range_of_expr (r, bound,
3554 : currently_expanding_gimple_stmt);
3555 267 : if (r.varying_p () || r.undefined_p ())
3556 : return NULL_RTX;
3557 152 : min = r.lower_bound ();
3558 152 : max = r.upper_bound ();
3559 :
3560 152 : if (!len || TREE_CODE (len) != INTEGER_CST)
3561 : {
3562 115 : bool exact;
3563 115 : lendata.decl = unterminated_array (src, &len, &exact);
3564 115 : if (!lendata.decl)
3565 95 : return NULL_RTX;
3566 : }
3567 :
3568 57 : if (lendata.decl)
3569 : return NULL_RTX;
3570 :
3571 37 : if (wi::gtu_p (min, wi::to_wide (len)))
3572 7 : return expand_expr (len, target, target_mode, EXPAND_NORMAL);
3573 :
3574 30 : len = fold_build2_loc (loc, MIN_EXPR, TREE_TYPE (len), len, bound);
3575 30 : return expand_expr (len, target, target_mode, EXPAND_NORMAL);
3576 267 : }
3577 :
3578 : /* Callback routine for store_by_pieces. Read GET_MODE_BITSIZE (MODE)
3579 : bytes from bytes at DATA + OFFSET and return it reinterpreted as
3580 : a target constant. */
3581 :
3582 : static rtx
3583 172450 : builtin_memcpy_read_str (void *data, void *, HOST_WIDE_INT offset,
3584 : fixed_size_mode mode)
3585 : {
3586 : /* The REPresentation pointed to by DATA need not be a nul-terminated
3587 : string but the caller guarantees it's large enough for MODE. */
3588 172450 : const char *rep = (const char *) data;
3589 :
3590 172450 : return c_readstr (rep + offset, mode, /*nul_terminated=*/false);
3591 : }
3592 :
3593 : /* LEN specify length of the block of memcpy/memset operation.
3594 : Figure out its range and put it into MIN_SIZE/MAX_SIZE.
3595 : In some cases we can make very likely guess on max size, then we
3596 : set it into PROBABLE_MAX_SIZE. */
3597 :
3598 : static void
3599 191851 : determine_block_size (tree len, rtx &len_rtx,
3600 : unsigned HOST_WIDE_INT *min_size,
3601 : unsigned HOST_WIDE_INT *max_size,
3602 : unsigned HOST_WIDE_INT *probable_max_size)
3603 : {
3604 191851 : if (CONST_INT_P (len_rtx))
3605 : {
3606 96241 : *min_size = *max_size = *probable_max_size = UINTVAL (len_rtx);
3607 96241 : return;
3608 : }
3609 : else
3610 : {
3611 95610 : wide_int min, max;
3612 95610 : enum value_range_kind range_type = VR_UNDEFINED;
3613 :
3614 : /* Determine bounds from the type. */
3615 95610 : if (tree_fits_uhwi_p (TYPE_MIN_VALUE (TREE_TYPE (len))))
3616 95609 : *min_size = tree_to_uhwi (TYPE_MIN_VALUE (TREE_TYPE (len)));
3617 : else
3618 : *min_size = 0;
3619 95610 : if (tree_fits_uhwi_p (TYPE_MAX_VALUE (TREE_TYPE (len))))
3620 95610 : *probable_max_size = *max_size
3621 95610 : = tree_to_uhwi (TYPE_MAX_VALUE (TREE_TYPE (len)));
3622 : else
3623 0 : *probable_max_size = *max_size = GET_MODE_MASK (GET_MODE (len_rtx));
3624 :
3625 95610 : if (TREE_CODE (len) == SSA_NAME)
3626 : {
3627 95610 : int_range_max r;
3628 95610 : tree tmin, tmax;
3629 95610 : gimple *cg = currently_expanding_gimple_stmt;
3630 191220 : get_range_query (cfun)->range_of_expr (r, len, cg);
3631 95610 : range_type = get_legacy_range (r, tmin, tmax);
3632 95610 : if (range_type != VR_UNDEFINED)
3633 : {
3634 95608 : min = wi::to_wide (tmin);
3635 95608 : max = wi::to_wide (tmax);
3636 : }
3637 95610 : }
3638 95610 : if (range_type == VR_RANGE)
3639 : {
3640 69257 : if (wi::fits_uhwi_p (min) && *min_size < min.to_uhwi ())
3641 56513 : *min_size = min.to_uhwi ();
3642 69257 : if (wi::fits_uhwi_p (max) && *max_size > max.to_uhwi ())
3643 62506 : *probable_max_size = *max_size = max.to_uhwi ();
3644 : }
3645 26353 : else if (range_type == VR_ANTI_RANGE)
3646 : {
3647 : /* Code like
3648 :
3649 : int n;
3650 : if (n < 100)
3651 : memcpy (a, b, n)
3652 :
3653 : Produce anti range allowing negative values of N. We still
3654 : can use the information and make a guess that N is not negative.
3655 : */
3656 3077 : if (!wi::leu_p (max, 1 << 30) && wi::fits_uhwi_p (min))
3657 2928 : *probable_max_size = min.to_uhwi () - 1;
3658 : }
3659 95610 : }
3660 :
3661 95610 : if (*min_size == *max_size)
3662 13 : len_rtx = GEN_INT (*min_size);
3663 : else
3664 95597 : gcc_checking_assert (*max_size <=
3665 : (unsigned HOST_WIDE_INT)
3666 : GET_MODE_MASK (GET_MODE (len_rtx)));
3667 : }
3668 :
3669 : /* Expand a call EXP to the memcpy builtin.
3670 : Return NULL_RTX if we failed, the caller should emit a normal call,
3671 : otherwise try to get the result in TARGET, if convenient (and in
3672 : mode MODE if that's convenient). */
3673 :
3674 : static rtx
3675 110102 : expand_builtin_memcpy (tree exp, rtx target)
3676 : {
3677 110102 : if (!validate_arglist (exp,
3678 : POINTER_TYPE, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
3679 : return NULL_RTX;
3680 :
3681 110084 : tree dest = CALL_EXPR_ARG (exp, 0);
3682 110084 : tree src = CALL_EXPR_ARG (exp, 1);
3683 110084 : tree len = CALL_EXPR_ARG (exp, 2);
3684 :
3685 110084 : return expand_builtin_memory_copy_args (dest, src, len, target, exp,
3686 110084 : /*retmode=*/ RETURN_BEGIN, false);
3687 : }
3688 :
3689 : /* Check a call EXP to the memmove built-in for validity.
3690 : Return NULL_RTX on both success and failure. */
3691 :
3692 : static rtx
3693 17646 : expand_builtin_memmove (tree exp, rtx target)
3694 : {
3695 17646 : if (!validate_arglist (exp,
3696 : POINTER_TYPE, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
3697 : return NULL_RTX;
3698 :
3699 17631 : tree dest = CALL_EXPR_ARG (exp, 0);
3700 17631 : tree src = CALL_EXPR_ARG (exp, 1);
3701 17631 : tree len = CALL_EXPR_ARG (exp, 2);
3702 :
3703 17631 : return expand_builtin_memory_copy_args (dest, src, len, target, exp,
3704 17631 : /*retmode=*/ RETURN_BEGIN, true);
3705 : }
3706 :
3707 : /* Expand a call EXP to the mempcpy builtin.
3708 : Return NULL_RTX if we failed; the caller should emit a normal call,
3709 : otherwise try to get the result in TARGET, if convenient (and in
3710 : mode MODE if that's convenient). */
3711 :
3712 : static rtx
3713 1395 : expand_builtin_mempcpy (tree exp, rtx target)
3714 : {
3715 1395 : if (!validate_arglist (exp,
3716 : POINTER_TYPE, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
3717 : return NULL_RTX;
3718 :
3719 1390 : tree dest = CALL_EXPR_ARG (exp, 0);
3720 1390 : tree src = CALL_EXPR_ARG (exp, 1);
3721 1390 : tree len = CALL_EXPR_ARG (exp, 2);
3722 :
3723 : /* Policy does not generally allow using compute_objsize (which
3724 : is used internally by check_memop_size) to change code generation
3725 : or drive optimization decisions.
3726 :
3727 : In this instance it is safe because the code we generate has
3728 : the same semantics regardless of the return value of
3729 : check_memop_sizes. Exactly the same amount of data is copied
3730 : and the return value is exactly the same in both cases.
3731 :
3732 : Furthermore, check_memop_size always uses mode 0 for the call to
3733 : compute_objsize, so the imprecise nature of compute_objsize is
3734 : avoided. */
3735 :
3736 : /* Avoid expanding mempcpy into memcpy when the call is determined
3737 : to overflow the buffer. This also prevents the same overflow
3738 : from being diagnosed again when expanding memcpy. */
3739 :
3740 1390 : return expand_builtin_mempcpy_args (dest, src, len,
3741 1390 : target, exp, /*retmode=*/ RETURN_END);
3742 : }
3743 :
3744 : /* Helper function to do the actual work for expand of memory copy family
3745 : functions (memcpy, mempcpy, stpcpy). Expansing should assign LEN bytes
3746 : of memory from SRC to DEST and assign to TARGET if convenient. Return
3747 : value is based on RETMODE argument. */
3748 :
3749 : static rtx
3750 129128 : expand_builtin_memory_copy_args (tree dest, tree src, tree len,
3751 : rtx target, tree exp, memop_ret retmode,
3752 : bool might_overlap)
3753 : {
3754 129128 : unsigned int src_align = get_pointer_alignment (src);
3755 129128 : unsigned int dest_align = get_pointer_alignment (dest);
3756 129128 : rtx dest_mem, src_mem, dest_addr, len_rtx;
3757 129128 : HOST_WIDE_INT expected_size = -1;
3758 129128 : unsigned int expected_align = 0;
3759 129128 : unsigned HOST_WIDE_INT min_size;
3760 129128 : unsigned HOST_WIDE_INT max_size;
3761 129128 : unsigned HOST_WIDE_INT probable_max_size;
3762 :
3763 129128 : bool is_move_done;
3764 :
3765 : /* If DEST is not a pointer type, call the normal function. */
3766 129128 : if (dest_align == 0)
3767 : return NULL_RTX;
3768 :
3769 : /* If either SRC is not a pointer type, don't do this
3770 : operation in-line. */
3771 129128 : if (src_align == 0)
3772 : return NULL_RTX;
3773 :
3774 129128 : if (currently_expanding_gimple_stmt)
3775 129128 : stringop_block_profile (currently_expanding_gimple_stmt,
3776 : &expected_align, &expected_size);
3777 :
3778 129128 : if (expected_align < dest_align)
3779 129106 : expected_align = dest_align;
3780 129128 : dest_mem = get_memory_rtx (dest, len, true);
3781 129128 : set_mem_align (dest_mem, dest_align);
3782 129128 : len_rtx = expand_normal (len);
3783 129128 : determine_block_size (len, len_rtx, &min_size, &max_size,
3784 : &probable_max_size);
3785 :
3786 : /* Try to get the byte representation of the constant SRC points to,
3787 : with its byte size in NBYTES. */
3788 129128 : unsigned HOST_WIDE_INT nbytes;
3789 129128 : const char *rep = getbyterep (src, &nbytes);
3790 :
3791 : /* If the function's constant bound LEN_RTX is less than or equal
3792 : to the byte size of the representation of the constant argument,
3793 : and if block move would be done by pieces, we can avoid loading
3794 : the bytes from memory and only store the computed constant.
3795 : This works in the overlap (memmove) case as well because
3796 : store_by_pieces just generates a series of stores of constants
3797 : from the representation returned by getbyterep(). */
3798 129128 : if (rep
3799 31380 : && CONST_INT_P (len_rtx)
3800 29717 : && (unsigned HOST_WIDE_INT) INTVAL (len_rtx) <= nbytes
3801 158579 : && can_store_by_pieces (INTVAL (len_rtx), builtin_memcpy_read_str,
3802 : const_cast<char *> (rep),
3803 : dest_align, false))
3804 : {
3805 28972 : dest_mem = store_by_pieces (dest_mem, INTVAL (len_rtx),
3806 : builtin_memcpy_read_str,
3807 : const_cast<char *> (rep),
3808 : dest_align, false, retmode);
3809 28972 : dest_mem = force_operand (XEXP (dest_mem, 0), target);
3810 28972 : dest_mem = convert_memory_address (ptr_mode, dest_mem);
3811 28972 : return dest_mem;
3812 : }
3813 :
3814 100156 : src_mem = get_memory_rtx (src, len, false);
3815 100156 : set_mem_align (src_mem, src_align);
3816 :
3817 : /* Copy word part most expediently. */
3818 100156 : enum block_op_methods method = BLOCK_OP_NORMAL;
3819 100156 : if (CALL_EXPR_TAILCALL (exp)
3820 100156 : && (retmode == RETURN_BEGIN || target == const0_rtx))
3821 : method = BLOCK_OP_TAILCALL;
3822 100156 : bool use_mempcpy_call = (targetm.libc_has_fast_function (BUILT_IN_MEMPCPY)
3823 100156 : && retmode == RETURN_END
3824 100156 : && !might_overlap
3825 101231 : && target != const0_rtx);
3826 : if (use_mempcpy_call)
3827 100156 : method = BLOCK_OP_NO_LIBCALL_RET;
3828 100156 : dest_addr = emit_block_move_hints (dest_mem, src_mem, len_rtx, method,
3829 : expected_align, expected_size,
3830 : min_size, max_size, probable_max_size,
3831 : use_mempcpy_call, &is_move_done,
3832 : might_overlap, tree_ctz (len));
3833 :
3834 : /* Bail out when a mempcpy call would be expanded as libcall and when
3835 : we have a target that provides a fast implementation
3836 : of mempcpy routine. */
3837 100156 : if (!is_move_done)
3838 : return NULL_RTX;
3839 :
3840 87000 : if (dest_addr == pc_rtx)
3841 : return NULL_RTX;
3842 :
3843 87000 : if (dest_addr == 0)
3844 : {
3845 33516 : dest_addr = force_operand (XEXP (dest_mem, 0), target);
3846 33516 : dest_addr = convert_memory_address (ptr_mode, dest_addr);
3847 : }
3848 :
3849 87000 : if (retmode != RETURN_BEGIN && target != const0_rtx)
3850 : {
3851 815 : dest_addr = gen_rtx_PLUS (ptr_mode, dest_addr, len_rtx);
3852 : /* stpcpy pointer to last byte. */
3853 815 : if (retmode == RETURN_END_MINUS_ONE)
3854 0 : dest_addr = gen_rtx_MINUS (ptr_mode, dest_addr, const1_rtx);
3855 : }
3856 :
3857 : return dest_addr;
3858 : }
3859 :
3860 : static rtx
3861 1413 : expand_builtin_mempcpy_args (tree dest, tree src, tree len,
3862 : rtx target, tree orig_exp, memop_ret retmode)
3863 : {
3864 1390 : return expand_builtin_memory_copy_args (dest, src, len, target, orig_exp,
3865 0 : retmode, false);
3866 : }
3867 :
3868 : /* Expand into a movstr instruction, if one is available. Return NULL_RTX if
3869 : we failed, the caller should emit a normal call, otherwise try to
3870 : get the result in TARGET, if convenient.
3871 : Return value is based on RETMODE argument. */
3872 :
3873 : static rtx
3874 2267 : expand_movstr (tree dest, tree src, rtx target, memop_ret retmode)
3875 : {
3876 2267 : class expand_operand ops[3];
3877 2267 : rtx dest_mem;
3878 2267 : rtx src_mem;
3879 :
3880 2267 : if (!targetm.have_movstr ())
3881 : return NULL_RTX;
3882 :
3883 0 : dest_mem = get_memory_rtx (dest, NULL, true);
3884 0 : src_mem = get_memory_rtx (src, NULL, false);
3885 0 : if (retmode == RETURN_BEGIN)
3886 : {
3887 0 : target = force_reg (Pmode, XEXP (dest_mem, 0));
3888 0 : dest_mem = replace_equiv_address (dest_mem, target);
3889 : }
3890 :
3891 0 : create_output_operand (&ops[0],
3892 0 : retmode != RETURN_BEGIN ? target : NULL_RTX, Pmode);
3893 0 : create_fixed_operand (&ops[1], dest_mem);
3894 0 : create_fixed_operand (&ops[2], src_mem);
3895 0 : if (!maybe_expand_insn (targetm.code_for_movstr, 3, ops))
3896 : return NULL_RTX;
3897 :
3898 0 : if (retmode != RETURN_BEGIN && target != const0_rtx)
3899 : {
3900 0 : target = ops[0].value;
3901 : /* movstr is supposed to set end to the address of the NUL
3902 : terminator. If the caller requested a mempcpy-like return value,
3903 : adjust it. */
3904 0 : if (retmode == RETURN_END)
3905 : {
3906 0 : rtx tem = plus_constant (GET_MODE (target),
3907 0 : gen_lowpart (GET_MODE (target), target), 1);
3908 0 : emit_move_insn (target, force_operand (tem, NULL_RTX));
3909 : }
3910 : }
3911 : return target;
3912 : }
3913 :
3914 : /* Expand expression EXP, which is a call to the strcpy builtin. Return
3915 : NULL_RTX if we failed the caller should emit a normal call, otherwise
3916 : try to get the result in TARGET, if convenient (and in mode MODE if that's
3917 : convenient). */
3918 :
3919 : static rtx
3920 1860 : expand_builtin_strcpy (tree exp, rtx target)
3921 : {
3922 1860 : if (!validate_arglist (exp, POINTER_TYPE, POINTER_TYPE, VOID_TYPE))
3923 : return NULL_RTX;
3924 :
3925 1845 : tree dest = CALL_EXPR_ARG (exp, 0);
3926 1845 : tree src = CALL_EXPR_ARG (exp, 1);
3927 :
3928 1845 : return expand_builtin_strcpy_args (exp, dest, src, target);
3929 : }
3930 :
3931 : /* Helper function to do the actual work for expand_builtin_strcpy. The
3932 : arguments to the builtin_strcpy call DEST and SRC are broken out
3933 : so that this can also be called without constructing an actual CALL_EXPR.
3934 : The other arguments and return value are the same as for
3935 : expand_builtin_strcpy. */
3936 :
3937 : static rtx
3938 1845 : expand_builtin_strcpy_args (tree, tree dest, tree src, rtx target)
3939 : {
3940 1845 : return expand_movstr (dest, src, target, /*retmode=*/ RETURN_BEGIN);
3941 : }
3942 :
3943 : /* Expand a call EXP to the stpcpy builtin.
3944 : Return NULL_RTX if we failed the caller should emit a normal call,
3945 : otherwise try to get the result in TARGET, if convenient (and in
3946 : mode MODE if that's convenient). */
3947 :
3948 : static rtx
3949 454 : expand_builtin_stpcpy_1 (tree exp, rtx target, machine_mode mode)
3950 : {
3951 454 : tree dst, src;
3952 454 : location_t loc = EXPR_LOCATION (exp);
3953 :
3954 454 : if (!validate_arglist (exp, POINTER_TYPE, POINTER_TYPE, VOID_TYPE))
3955 : return NULL_RTX;
3956 :
3957 445 : dst = CALL_EXPR_ARG (exp, 0);
3958 445 : src = CALL_EXPR_ARG (exp, 1);
3959 :
3960 : /* If return value is ignored, transform stpcpy into strcpy. */
3961 445 : if (target == const0_rtx && builtin_decl_implicit (BUILT_IN_STRCPY))
3962 : {
3963 0 : tree fn = builtin_decl_implicit (BUILT_IN_STRCPY);
3964 0 : tree result = build_call_nofold_loc (loc, fn, 2, dst, src);
3965 0 : return expand_expr (result, target, mode, EXPAND_NORMAL);
3966 : }
3967 : else
3968 : {
3969 445 : tree len, lenp1;
3970 445 : rtx ret;
3971 :
3972 : /* Ensure we get an actual string whose length can be evaluated at
3973 : compile-time, not an expression containing a string. This is
3974 : because the latter will potentially produce pessimized code
3975 : when used to produce the return value. */
3976 445 : c_strlen_data lendata = { };
3977 445 : if (!c_getstr (src)
3978 445 : || !(len = c_strlen (src, 0, &lendata, 1)))
3979 422 : return expand_movstr (dst, src, target,
3980 422 : /*retmode=*/ RETURN_END_MINUS_ONE);
3981 :
3982 23 : lenp1 = size_binop_loc (loc, PLUS_EXPR, len, ssize_int (1));
3983 23 : ret = expand_builtin_mempcpy_args (dst, src, lenp1,
3984 : target, exp,
3985 : /*retmode=*/ RETURN_END_MINUS_ONE);
3986 :
3987 23 : if (ret)
3988 : return ret;
3989 :
3990 0 : if (TREE_CODE (len) == INTEGER_CST)
3991 : {
3992 0 : rtx len_rtx = expand_normal (len);
3993 :
3994 0 : if (CONST_INT_P (len_rtx))
3995 : {
3996 0 : ret = expand_builtin_strcpy_args (exp, dst, src, target);
3997 :
3998 0 : if (ret)
3999 : {
4000 0 : if (! target)
4001 : {
4002 0 : if (mode != VOIDmode)
4003 0 : target = gen_reg_rtx (mode);
4004 : else
4005 0 : target = gen_reg_rtx (GET_MODE (ret));
4006 : }
4007 0 : if (GET_MODE (target) != GET_MODE (ret))
4008 0 : ret = gen_lowpart (GET_MODE (target), ret);
4009 :
4010 0 : ret = plus_constant (GET_MODE (ret), ret, INTVAL (len_rtx));
4011 0 : ret = emit_move_insn (target, force_operand (ret, NULL_RTX));
4012 0 : gcc_assert (ret);
4013 :
4014 : return target;
4015 : }
4016 : }
4017 : }
4018 :
4019 0 : return expand_movstr (dst, src, target,
4020 0 : /*retmode=*/ RETURN_END_MINUS_ONE);
4021 : }
4022 : }
4023 :
4024 : /* Expand a call EXP to the stpcpy builtin and diagnose uses of nonstring
4025 : arguments while being careful to avoid duplicate warnings (which could
4026 : be issued if the expander were to expand the call, resulting in it
4027 : being emitted in expand_call(). */
4028 :
4029 : static rtx
4030 454 : expand_builtin_stpcpy (tree exp, rtx target, machine_mode mode)
4031 : {
4032 454 : if (rtx ret = expand_builtin_stpcpy_1 (exp, target, mode))
4033 : {
4034 : /* The call has been successfully expanded. Check for nonstring
4035 : arguments and issue warnings as appropriate. */
4036 23 : maybe_warn_nonstring_arg (get_callee_fndecl (exp), exp);
4037 23 : return ret;
4038 : }
4039 :
4040 : return NULL_RTX;
4041 : }
4042 :
4043 : /* Callback routine for store_by_pieces. Read GET_MODE_BITSIZE (MODE)
4044 : bytes from constant string DATA + OFFSET and return it as target
4045 : constant. */
4046 :
4047 : rtx
4048 9879 : builtin_strncpy_read_str (void *data, void *, HOST_WIDE_INT offset,
4049 : fixed_size_mode mode)
4050 : {
4051 9879 : const char *str = (const char *) data;
4052 :
4053 9879 : if ((unsigned HOST_WIDE_INT) offset > strlen (str))
4054 260 : return const0_rtx;
4055 :
4056 9619 : return c_readstr (str + offset, mode);
4057 : }
4058 :
4059 : /* Helper to check the sizes of sequences and the destination of calls
4060 : to __builtin_strncat and __builtin___strncat_chk. Returns true on
4061 : success (no overflow or invalid sizes), false otherwise. */
4062 :
4063 : static bool
4064 108 : check_strncat_sizes (tree exp, tree objsize)
4065 : {
4066 108 : tree dest = CALL_EXPR_ARG (exp, 0);
4067 108 : tree src = CALL_EXPR_ARG (exp, 1);
4068 108 : tree maxread = CALL_EXPR_ARG (exp, 2);
4069 :
4070 : /* Try to determine the range of lengths that the source expression
4071 : refers to. */
4072 108 : c_strlen_data lendata = { };
4073 108 : get_range_strlen (src, &lendata, /* eltsize = */ 1);
4074 :
4075 : /* Try to verify that the destination is big enough for the shortest
4076 : string. */
4077 :
4078 108 : access_data data (nullptr, exp, access_read_write, maxread, true);
4079 108 : if (!objsize && warn_stringop_overflow)
4080 : {
4081 : /* If it hasn't been provided by __strncat_chk, try to determine
4082 : the size of the destination object into which the source is
4083 : being copied. */
4084 0 : objsize = compute_objsize (dest, warn_stringop_overflow - 1, &data.dst);
4085 : }
4086 :
4087 : /* Add one for the terminating nul. */
4088 108 : tree srclen = (lendata.minlen
4089 108 : ? fold_build2 (PLUS_EXPR, size_type_node, lendata.minlen,
4090 : size_one_node)
4091 : : NULL_TREE);
4092 :
4093 : /* The strncat function copies at most MAXREAD bytes and always appends
4094 : the terminating nul so the specified upper bound should never be equal
4095 : to (or greater than) the size of the destination. */
4096 55 : if (tree_fits_uhwi_p (maxread) && tree_fits_uhwi_p (objsize)
4097 155 : && tree_int_cst_equal (objsize, maxread))
4098 : {
4099 23 : location_t loc = EXPR_LOCATION (exp);
4100 23 : warning_at (loc, OPT_Wstringop_overflow_,
4101 : "%qD specified bound %E equals destination size",
4102 : get_callee_fndecl (exp), maxread);
4103 :
4104 23 : return false;
4105 : }
4106 :
4107 85 : if (!srclen
4108 85 : || (maxread && tree_fits_uhwi_p (maxread)
4109 32 : && tree_fits_uhwi_p (srclen)
4110 32 : && tree_int_cst_lt (maxread, srclen)))
4111 : srclen = maxread;
4112 :
4113 : /* The number of bytes to write is LEN but check_access will alsoa
4114 : check SRCLEN if LEN's value isn't known. */
4115 85 : return check_access (exp, /*dstwrite=*/NULL_TREE, maxread, srclen,
4116 85 : objsize, data.mode, &data);
4117 : }
4118 :
4119 : /* Expand expression EXP, which is a call to the strncpy builtin. Return
4120 : NULL_RTX if we failed the caller should emit a normal call. */
4121 :
4122 : static rtx
4123 2177 : expand_builtin_strncpy (tree exp, rtx target)
4124 : {
4125 2177 : location_t loc = EXPR_LOCATION (exp);
4126 :
4127 2177 : if (!validate_arglist (exp,
4128 : POINTER_TYPE, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
4129 : return NULL_RTX;
4130 2165 : tree dest = CALL_EXPR_ARG (exp, 0);
4131 2165 : tree src = CALL_EXPR_ARG (exp, 1);
4132 : /* The number of bytes to write (not the maximum). */
4133 2165 : tree len = CALL_EXPR_ARG (exp, 2);
4134 :
4135 : /* The length of the source sequence. */
4136 2165 : tree slen = c_strlen (src, 1);
4137 :
4138 : /* We must be passed a constant len and src parameter. */
4139 2165 : if (!tree_fits_uhwi_p (len) || !slen || !tree_fits_uhwi_p (slen))
4140 : return NULL_RTX;
4141 :
4142 237 : slen = size_binop_loc (loc, PLUS_EXPR, slen, ssize_int (1));
4143 :
4144 : /* We're required to pad with trailing zeros if the requested
4145 : len is greater than strlen(s2)+1. In that case try to
4146 : use store_by_pieces, if it fails, punt. */
4147 237 : if (tree_int_cst_lt (slen, len))
4148 : {
4149 142 : unsigned int dest_align = get_pointer_alignment (dest);
4150 142 : const char *p = c_getstr (src);
4151 142 : rtx dest_mem;
4152 :
4153 136 : if (!p || dest_align == 0 || !tree_fits_uhwi_p (len)
4154 278 : || !can_store_by_pieces (tree_to_uhwi (len),
4155 : builtin_strncpy_read_str,
4156 : const_cast<char *> (p),
4157 : dest_align, false))
4158 : return NULL_RTX;
4159 :
4160 128 : dest_mem = get_memory_rtx (dest, len, true);
4161 128 : store_by_pieces (dest_mem, tree_to_uhwi (len),
4162 : builtin_strncpy_read_str,
4163 : const_cast<char *> (p), dest_align, false,
4164 : RETURN_BEGIN);
4165 128 : dest_mem = force_operand (XEXP (dest_mem, 0), target);
4166 128 : dest_mem = convert_memory_address (ptr_mode, dest_mem);
4167 128 : return dest_mem;
4168 : }
4169 :
4170 : return NULL_RTX;
4171 : }
4172 :
4173 : /* Return the RTL of a register in MODE generated from PREV in the
4174 : previous iteration. */
4175 :
4176 : static rtx
4177 254009 : gen_memset_value_from_prev (by_pieces_prev *prev, fixed_size_mode mode)
4178 : {
4179 254009 : rtx target = nullptr;
4180 254009 : if (prev != nullptr && prev->data != nullptr)
4181 : {
4182 : /* Use the previous data in the same mode. */
4183 140512 : if (prev->mode == mode)
4184 254009 : return prev->data;
4185 :
4186 32538 : fixed_size_mode prev_mode = prev->mode;
4187 :
4188 : /* Don't use the previous data to write QImode if it is in a
4189 : vector mode. */
4190 32538 : if (VECTOR_MODE_P (prev_mode) && mode == QImode)
4191 : return target;
4192 :
4193 32139 : rtx prev_rtx = prev->data;
4194 :
4195 32139 : if (REG_P (prev_rtx)
4196 23694 : && HARD_REGISTER_P (prev_rtx)
4197 32139 : && lowpart_subreg_regno (REGNO (prev_rtx), prev_mode, mode) < 0)
4198 : {
4199 : /* This case occurs when PREV_MODE is a vector and when
4200 : MODE is too small to store using vector operations.
4201 : After register allocation, the code will need to move the
4202 : lowpart of the vector register into a non-vector register.
4203 :
4204 : Also, the target has chosen to use a hard register
4205 : instead of going with the default choice of using a
4206 : pseudo register. We should respect that choice and try to
4207 : avoid creating a pseudo register with the same mode as the
4208 : current hard register.
4209 :
4210 : In principle, we could just use a lowpart MODE subreg of
4211 : the vector register. However, the vector register mode might
4212 : be too wide for non-vector registers, and we already know
4213 : that the non-vector mode is too small for vector registers.
4214 : It's therefore likely that we'd need to spill to memory in
4215 : the vector mode and reload the non-vector value from there.
4216 :
4217 : Try to avoid that by reducing the vector register to the
4218 : smallest size that it can hold. This should increase the
4219 : chances that non-vector registers can hold both the inner
4220 : and outer modes of the subreg that we generate later. */
4221 0 : machine_mode m;
4222 0 : fixed_size_mode candidate;
4223 0 : FOR_EACH_MODE_IN_CLASS (m, GET_MODE_CLASS (mode))
4224 0 : if (is_a<fixed_size_mode> (m, &candidate))
4225 : {
4226 0 : if (GET_MODE_SIZE (candidate)
4227 0 : >= GET_MODE_SIZE (prev_mode))
4228 : break;
4229 0 : if (GET_MODE_SIZE (candidate) >= GET_MODE_SIZE (mode)
4230 0 : && lowpart_subreg_regno (REGNO (prev_rtx),
4231 : prev_mode, candidate) >= 0)
4232 : {
4233 0 : target = lowpart_subreg (candidate, prev_rtx,
4234 : prev_mode);
4235 0 : prev_rtx = target;
4236 0 : prev_mode = candidate;
4237 0 : break;
4238 : }
4239 : }
4240 0 : if (target == nullptr)
4241 0 : prev_rtx = copy_to_reg (prev_rtx);
4242 : }
4243 :
4244 32139 : target = lowpart_subreg (mode, prev_rtx, prev_mode);
4245 : }
4246 : return target;
4247 : }
4248 :
4249 : /* Callback routine for store_by_pieces. Read GET_MODE_BITSIZE (MODE)
4250 : bytes from constant string DATA + OFFSET and return it as target
4251 : constant. If PREV isn't nullptr, it has the RTL info from the
4252 : previous iteration. */
4253 :
4254 : rtx
4255 252741 : builtin_memset_read_str (void *data, void *prev,
4256 : HOST_WIDE_INT offset ATTRIBUTE_UNUSED,
4257 : fixed_size_mode mode)
4258 : {
4259 252741 : const char *c = (const char *) data;
4260 252741 : unsigned int size = GET_MODE_SIZE (mode);
4261 :
4262 252741 : rtx target = gen_memset_value_from_prev ((by_pieces_prev *) prev,
4263 : mode);
4264 252741 : if (target != nullptr)
4265 : return target;
4266 113173 : rtx src = gen_int_mode (*c, QImode);
4267 :
4268 113173 : if (VECTOR_MODE_P (mode))
4269 : {
4270 164238 : gcc_assert (GET_MODE_INNER (mode) == QImode);
4271 :
4272 82119 : rtx const_vec = gen_const_vec_duplicate (mode, src);
4273 82119 : if (prev == NULL)
4274 : /* Return CONST_VECTOR when called by a query function. */
4275 : return const_vec;
4276 :
4277 : /* Use the move expander with CONST_VECTOR. */
4278 61257 : target = gen_reg_rtx (mode);
4279 61257 : emit_move_insn (target, const_vec);
4280 61257 : return target;
4281 : }
4282 :
4283 31054 : char *p = XALLOCAVEC (char, size);
4284 :
4285 31054 : memset (p, *c, size);
4286 :
4287 31054 : return c_readstr (p, mode);
4288 : }
4289 :
4290 : /* Callback routine for store_by_pieces. Return the RTL of a register
4291 : containing GET_MODE_SIZE (MODE) consecutive copies of the unsigned
4292 : char value given in the RTL register data. For example, if mode is
4293 : 4 bytes wide, return the RTL for 0x01010101*data. If PREV isn't
4294 : nullptr, it has the RTL info from the previous iteration. */
4295 :
4296 : static rtx
4297 1407 : builtin_memset_gen_str (void *data, void *prev,
4298 : HOST_WIDE_INT offset ATTRIBUTE_UNUSED,
4299 : fixed_size_mode mode)
4300 : {
4301 1407 : rtx target, coeff;
4302 1407 : size_t size;
4303 1407 : char *p;
4304 :
4305 1407 : size = GET_MODE_SIZE (mode);
4306 1407 : if (size == 1)
4307 : return (rtx) data;
4308 :
4309 1268 : target = gen_memset_value_from_prev ((by_pieces_prev *) prev, mode);
4310 1268 : if (target != nullptr)
4311 : return target;
4312 :
4313 723 : if (VECTOR_MODE_P (mode))
4314 : {
4315 366 : gcc_assert (GET_MODE_INNER (mode) == QImode);
4316 :
4317 : /* vec_duplicate_optab is a precondition to pick a vector mode for
4318 : the memset expander. */
4319 183 : insn_code icode = optab_handler (vec_duplicate_optab, mode);
4320 :
4321 183 : target = gen_reg_rtx (mode);
4322 183 : class expand_operand ops[2];
4323 183 : create_output_operand (&ops[0], target, mode);
4324 183 : create_input_operand (&ops[1], (rtx) data, QImode);
4325 183 : expand_insn (icode, 2, ops);
4326 183 : if (!rtx_equal_p (target, ops[0].value))
4327 0 : emit_move_insn (target, ops[0].value);
4328 :
4329 183 : return target;
4330 : }
4331 :
4332 540 : p = XALLOCAVEC (char, size);
4333 540 : memset (p, 1, size);
4334 540 : coeff = c_readstr (p, mode);
4335 :
4336 540 : target = convert_to_mode (mode, (rtx) data, 1);
4337 540 : target = expand_mult (mode, target, coeff, NULL_RTX, 1);
4338 540 : return force_reg (mode, target);
4339 : }
4340 :
4341 : /* Expand expression EXP, which is a call to the memset builtin. Return
4342 : NULL_RTX if we failed the caller should emit a normal call, otherwise
4343 : try to get the result in TARGET, if convenient (and in mode MODE if that's
4344 : convenient). */
4345 :
4346 : rtx
4347 62732 : expand_builtin_memset (tree exp, rtx target, machine_mode mode)
4348 : {
4349 62732 : if (!validate_arglist (exp,
4350 : POINTER_TYPE, INTEGER_TYPE, INTEGER_TYPE, VOID_TYPE))
4351 : return NULL_RTX;
4352 :
4353 62723 : tree dest = CALL_EXPR_ARG (exp, 0);
4354 62723 : tree val = CALL_EXPR_ARG (exp, 1);
4355 62723 : tree len = CALL_EXPR_ARG (exp, 2);
4356 :
4357 62723 : return expand_builtin_memset_args (dest, val, len, target, mode, exp);
4358 : }
4359 :
4360 : /* Check that store_by_pieces allows BITS + LEN (so that we don't
4361 : expand something too unreasonably long), and every power of 2 in
4362 : BITS. It is assumed that LEN has already been tested by
4363 : itself. */
4364 : static bool
4365 24868 : can_store_by_multiple_pieces (unsigned HOST_WIDE_INT bits,
4366 : by_pieces_constfn constfun,
4367 : void *constfundata, unsigned int align,
4368 : bool memsetp,
4369 : unsigned HOST_WIDE_INT len)
4370 : {
4371 24868 : if (bits
4372 24868 : && !can_store_by_pieces (bits + len, constfun, constfundata,
4373 : align, memsetp))
4374 : return false;
4375 :
4376 : /* BITS set are expected to be generally in the low range and
4377 : contiguous. We do NOT want to repeat the test above in case BITS
4378 : has a single bit set, so we terminate the loop when BITS == BIT.
4379 : In the unlikely case that BITS has the MSB set, also terminate in
4380 : case BIT gets shifted out. */
4381 1122 : for (unsigned HOST_WIDE_INT bit = 1; bit < bits && bit; bit <<= 1)
4382 : {
4383 840 : if ((bits & bit) == 0)
4384 504 : continue;
4385 :
4386 336 : if (!can_store_by_pieces (bit, constfun, constfundata,
4387 : align, memsetp))
4388 : return false;
4389 : }
4390 :
4391 : return true;
4392 : }
4393 :
4394 : /* Try to store VAL (or, if NULL_RTX, VALC) in LEN bytes starting at TO.
4395 : Return TRUE if successful, FALSE otherwise. TO is assumed to be
4396 : aligned at an ALIGN-bits boundary. LEN must be a multiple of
4397 : 1<<CTZ_LEN between MIN_LEN and MAX_LEN.
4398 :
4399 : The strategy is to issue one store_by_pieces for each power of two,
4400 : from most to least significant, guarded by a test on whether there
4401 : are at least that many bytes left to copy in LEN.
4402 :
4403 : ??? Should we skip some powers of two in favor of loops? Maybe start
4404 : at the max of TO/LEN/word alignment, at least when optimizing for
4405 : size, instead of ensuring O(log len) dynamic compares? */
4406 :
4407 : bool
4408 22727 : try_store_by_multiple_pieces (rtx to, rtx len, unsigned int ctz_len,
4409 : unsigned HOST_WIDE_INT min_len,
4410 : unsigned HOST_WIDE_INT max_len,
4411 : rtx val, char valc, unsigned int align)
4412 : {
4413 22727 : int max_bits = floor_log2 (max_len);
4414 22727 : int min_bits = floor_log2 (min_len);
4415 22727 : int sctz_len = ctz_len;
4416 :
4417 22727 : gcc_checking_assert (sctz_len >= 0);
4418 :
4419 22727 : if (val)
4420 640 : valc = 1;
4421 :
4422 : /* Bits more significant than TST_BITS are part of the shared prefix
4423 : in the binary representation of both min_len and max_len. Since
4424 : they're identical, we don't need to test them in the loop. */
4425 22727 : int tst_bits = (max_bits != min_bits ? max_bits
4426 10115 : : floor_log2 (max_len ^ min_len));
4427 :
4428 : /* Save the pre-blksize values. */
4429 22727 : int orig_max_bits = max_bits;
4430 22727 : int orig_tst_bits = tst_bits;
4431 :
4432 : /* Check whether it's profitable to start by storing a fixed BLKSIZE
4433 : bytes, to lower max_bits. In the unlikely case of a constant LEN
4434 : (implied by identical MAX_LEN and MIN_LEN), we want to issue a
4435 : single store_by_pieces, but otherwise, select the minimum multiple
4436 : of the ALIGN (in bytes) and of the MCD of the possible LENs, that
4437 : brings MAX_LEN below TST_BITS, if that's lower than min_len. */
4438 22727 : unsigned HOST_WIDE_INT blksize;
4439 22727 : if (max_len > min_len)
4440 : {
4441 12625 : unsigned HOST_WIDE_INT alrng = MAX (HOST_WIDE_INT_1U << ctz_len,
4442 : align / BITS_PER_UNIT);
4443 12625 : blksize = max_len - (HOST_WIDE_INT_1U << tst_bits) + alrng;
4444 12625 : blksize &= ~(alrng - 1);
4445 : }
4446 10102 : else if (max_len == min_len)
4447 : blksize = max_len;
4448 : else
4449 : /* Huh, max_len < min_len? Punt. See pr100843.c. */
4450 : return false;
4451 22726 : if (min_len >= blksize
4452 : /* ??? Maybe try smaller fixed-prefix blksizes before
4453 : punting? */
4454 22726 : && can_store_by_pieces (blksize, builtin_memset_read_str,
4455 : &valc, align, true))
4456 : {
4457 281 : min_len -= blksize;
4458 281 : min_bits = floor_log2 (min_len);
4459 281 : max_len -= blksize;
4460 281 : max_bits = floor_log2 (max_len);
4461 :
4462 281 : tst_bits = (max_bits != min_bits ? max_bits
4463 175 : : floor_log2 (max_len ^ min_len));
4464 : }
4465 : else
4466 : blksize = 0;
4467 :
4468 : /* Check that we can use store by pieces for the maximum store count
4469 : we may issue (initial fixed-size block, plus conditional
4470 : power-of-two-sized from max_bits to ctz_len. */
4471 22726 : unsigned HOST_WIDE_INT xlenest = blksize;
4472 22726 : if (max_bits >= 0)
4473 22551 : xlenest += ((HOST_WIDE_INT_1U << max_bits) * 2
4474 22551 : - (HOST_WIDE_INT_1U << ctz_len));
4475 22726 : bool max_loop = false;
4476 22726 : bool use_store_by_pieces = true;
4477 : /* Skip the test in case of overflow in xlenest. It shouldn't
4478 : happen because of the way max_bits and blksize are related, but
4479 : it doesn't hurt to test. */
4480 22726 : if (blksize > xlenest
4481 22726 : || !can_store_by_multiple_pieces (xlenest - blksize,
4482 : builtin_memset_read_str,
4483 : &valc, align, true, blksize))
4484 : {
4485 22551 : if (!(flag_inline_stringops & ILSOP_MEMSET))
4486 : return false;
4487 :
4488 2067 : for (max_bits = orig_max_bits;
4489 2174 : max_bits >= sctz_len;
4490 : --max_bits)
4491 : {
4492 2174 : xlenest = ((HOST_WIDE_INT_1U << max_bits) * 2
4493 2174 : - (HOST_WIDE_INT_1U << ctz_len));
4494 : /* Check that blksize plus the bits to be stored as blocks
4495 : sized at powers of two can be stored by pieces. This is
4496 : like the test above, but with smaller max_bits. Skip
4497 : orig_max_bits (it would be redundant). Also skip in case
4498 : of overflow. */
4499 2174 : if (max_bits < orig_max_bits
4500 2067 : && xlenest + blksize >= xlenest
4501 4241 : && can_store_by_multiple_pieces (xlenest,
4502 : builtin_memset_read_str,
4503 : &valc, align, true, blksize))
4504 : {
4505 : max_loop = true;
4506 : break;
4507 : }
4508 2067 : if (blksize
4509 2067 : && can_store_by_multiple_pieces (xlenest,
4510 : builtin_memset_read_str,
4511 : &valc, align, true, 0))
4512 : {
4513 0 : max_len += blksize;
4514 0 : min_len += blksize;
4515 0 : tst_bits = orig_tst_bits;
4516 0 : blksize = 0;
4517 0 : max_loop = true;
4518 0 : break;
4519 : }
4520 2067 : if (max_bits == sctz_len)
4521 : {
4522 : /* We'll get here if can_store_by_pieces refuses to
4523 : store even a single QImode. We'll fall back to
4524 : QImode stores then. */
4525 98 : if (!sctz_len)
4526 : {
4527 : blksize = 0;
4528 : max_loop = true;
4529 : use_store_by_pieces = false;
4530 : break;
4531 : }
4532 98 : --sctz_len;
4533 98 : --ctz_len;
4534 : }
4535 : }
4536 107 : if (!max_loop)
4537 : return false;
4538 : /* If the boundaries are such that min and max may run a
4539 : different number of trips in the initial loop, the remainder
4540 : needs not be between the moduli, so set tst_bits to cover all
4541 : bits. Otherwise, if the trip counts are the same, max_len
4542 : has the common prefix, and the previously-computed tst_bits
4543 : is usable. */
4544 107 : if (max_len >> max_bits > min_len >> max_bits)
4545 64 : tst_bits = max_bits;
4546 : }
4547 :
4548 282 : by_pieces_constfn constfun;
4549 282 : void *constfundata;
4550 282 : if (val)
4551 : {
4552 1 : constfun = builtin_memset_gen_str;
4553 1 : constfundata = val = force_reg (TYPE_MODE (unsigned_char_type_node),
4554 : val);
4555 : }
4556 : else
4557 : {
4558 : constfun = builtin_memset_read_str;
4559 : constfundata = &valc;
4560 : }
4561 :
4562 282 : rtx ptr = copy_addr_to_reg (XEXP (to, 0));
4563 282 : rtx rem = copy_to_mode_reg (ptr_mode, convert_to_mode (ptr_mode, len, 0));
4564 282 : to = replace_equiv_address (to, ptr);
4565 282 : set_mem_align (to, align);
4566 :
4567 282 : if (blksize)
4568 : {
4569 363 : to = store_by_pieces (to, blksize,
4570 : constfun, constfundata,
4571 : align, true,
4572 : max_len != 0 ? RETURN_END : RETURN_BEGIN);
4573 189 : if (max_len == 0)
4574 : return true;
4575 :
4576 : /* Adjust PTR, TO and REM. Since TO's address is likely
4577 : PTR+offset, we have to replace it. */
4578 15 : emit_move_insn (ptr, force_operand (XEXP (to, 0), NULL_RTX));
4579 15 : to = replace_equiv_address (to, ptr);
4580 15 : rtx rem_minus_blksize = plus_constant (ptr_mode, rem, -blksize);
4581 15 : emit_move_insn (rem, force_operand (rem_minus_blksize, NULL_RTX));
4582 : }
4583 :
4584 : /* Iterate over power-of-two block sizes from the maximum length to
4585 : the least significant bit possibly set in the length. */
4586 493 : for (int i = max_bits; i >= sctz_len; i--)
4587 : {
4588 385 : rtx_code_label *loop_label = NULL;
4589 385 : rtx_code_label *label = NULL;
4590 :
4591 385 : blksize = HOST_WIDE_INT_1U << i;
4592 :
4593 : /* If we're past the bits shared between min_ and max_len, expand
4594 : a test on the dynamic length, comparing it with the
4595 : BLKSIZE. */
4596 385 : if (i <= tst_bits)
4597 : {
4598 275 : label = gen_label_rtx ();
4599 275 : emit_cmp_and_jump_insns (rem, GEN_INT (blksize), LT, NULL,
4600 : ptr_mode, 1, label,
4601 : profile_probability::even ());
4602 : }
4603 : /* If we are at a bit that is in the prefix shared by min_ and
4604 : max_len, skip the current BLKSIZE if the bit is clear, but do
4605 : not skip the loop, even if it doesn't require
4606 : prechecking. */
4607 110 : else if ((max_len & blksize) == 0
4608 69 : && !(max_loop && i == max_bits))
4609 39 : continue;
4610 :
4611 346 : if (max_loop && i == max_bits)
4612 : {
4613 107 : loop_label = gen_label_rtx ();
4614 107 : emit_label (loop_label);
4615 : /* Since we may run this multiple times, don't assume we
4616 : know anything about the offset. */
4617 107 : clear_mem_offset (to);
4618 : }
4619 :
4620 346 : bool update_needed = i != sctz_len || loop_label;
4621 346 : rtx next_ptr = NULL_RTX;
4622 346 : if (!use_store_by_pieces)
4623 : {
4624 0 : gcc_checking_assert (blksize == 1);
4625 0 : if (!val)
4626 0 : val = gen_int_mode (valc, QImode);
4627 0 : to = change_address (to, QImode, 0);
4628 0 : emit_move_insn (to, val);
4629 0 : if (update_needed)
4630 0 : next_ptr = plus_constant (GET_MODE (ptr), ptr, blksize);
4631 : }
4632 : else
4633 : {
4634 : /* Issue a store of BLKSIZE bytes. */
4635 404 : to = store_by_pieces (to, blksize,
4636 : constfun, constfundata,
4637 : align, true,
4638 : update_needed ? RETURN_END : RETURN_BEGIN);
4639 346 : next_ptr = XEXP (to, 0);
4640 : }
4641 : /* Adjust REM and PTR, unless this is the last iteration. */
4642 346 : if (update_needed)
4643 : {
4644 288 : emit_move_insn (ptr, force_operand (next_ptr, NULL_RTX));
4645 288 : to = replace_equiv_address (to, ptr);
4646 288 : rtx rem_minus_blksize = plus_constant (ptr_mode, rem, -blksize);
4647 288 : emit_move_insn (rem, force_operand (rem_minus_blksize, NULL_RTX));
4648 : }
4649 :
4650 288 : if (loop_label)
4651 107 : emit_cmp_and_jump_insns (rem, GEN_INT (blksize), GE, NULL,
4652 : ptr_mode, 1, loop_label,
4653 : profile_probability::likely ());
4654 :
4655 346 : if (label)
4656 : {
4657 275 : emit_label (label);
4658 :
4659 : /* Given conditional stores, the offset can no longer be
4660 : known, so clear it. */
4661 275 : clear_mem_offset (to);
4662 : }
4663 : }
4664 :
4665 : return true;
4666 : }
4667 :
4668 : /* Helper function to do the actual work for expand_builtin_memset. The
4669 : arguments to the builtin_memset call DEST, VAL, and LEN are broken out
4670 : so that this can also be called without constructing an actual CALL_EXPR.
4671 : The other arguments and return value are the same as for
4672 : expand_builtin_memset. */
4673 :
4674 : static rtx
4675 62723 : expand_builtin_memset_args (tree dest, tree val, tree len,
4676 : rtx target, machine_mode mode, tree orig_exp)
4677 : {
4678 62723 : tree fndecl, fn;
4679 62723 : enum built_in_function fcode;
4680 62723 : machine_mode val_mode;
4681 62723 : char c;
4682 62723 : unsigned int dest_align;
4683 62723 : rtx dest_mem, dest_addr, len_rtx;
4684 62723 : HOST_WIDE_INT expected_size = -1;
4685 62723 : unsigned int expected_align = 0;
4686 62723 : unsigned HOST_WIDE_INT min_size;
4687 62723 : unsigned HOST_WIDE_INT max_size;
4688 62723 : unsigned HOST_WIDE_INT probable_max_size;
4689 :
4690 62723 : dest_align = get_pointer_alignment (dest);
4691 :
4692 : /* If DEST is not a pointer type, don't do this operation in-line. */
4693 62723 : if (dest_align == 0)
4694 : return NULL_RTX;
4695 :
4696 62723 : if (currently_expanding_gimple_stmt)
4697 62723 : stringop_block_profile (currently_expanding_gimple_stmt,
4698 : &expected_align, &expected_size);
4699 :
4700 62723 : if (expected_align < dest_align)
4701 62715 : expected_align = dest_align;
4702 :
4703 : /* If the LEN parameter is zero, return DEST. */
4704 62723 : if (integer_zerop (len))
4705 : {
4706 : /* Evaluate and ignore VAL in case it has side-effects. */
4707 0 : expand_expr (val, const0_rtx, VOIDmode, EXPAND_NORMAL);
4708 0 : return expand_expr (dest, target, mode, EXPAND_NORMAL);
4709 : }
4710 :
4711 : /* Stabilize the arguments in case we fail. */
4712 62723 : dest = builtin_save_expr (dest);
4713 62723 : val = builtin_save_expr (val);
4714 62723 : len = builtin_save_expr (len);
4715 :
4716 62723 : len_rtx = expand_normal (len);
4717 62723 : determine_block_size (len, len_rtx, &min_size, &max_size,
4718 : &probable_max_size);
4719 62723 : dest_mem = get_memory_rtx (dest, len, true);
4720 62723 : val_mode = TYPE_MODE (unsigned_char_type_node);
4721 :
4722 62723 : if (TREE_CODE (val) != INTEGER_CST
4723 62723 : || target_char_cast (val, &c))
4724 : {
4725 1727 : rtx val_rtx;
4726 :
4727 1727 : val_rtx = expand_normal (val);
4728 1727 : val_rtx = convert_to_mode (val_mode, val_rtx, 0);
4729 :
4730 : /* Assume that we can memset by pieces if we can store
4731 : * the coefficients by pieces (in the required modes).
4732 : * We can't pass builtin_memset_gen_str as that emits RTL. */
4733 1727 : c = 1;
4734 1727 : if (tree_fits_uhwi_p (len)
4735 1727 : && can_store_by_pieces (tree_to_uhwi (len),
4736 : builtin_memset_read_str, &c, dest_align,
4737 : true))
4738 : {
4739 726 : val_rtx = force_reg (val_mode, val_rtx);
4740 726 : store_by_pieces (dest_mem, tree_to_uhwi (len),
4741 : builtin_memset_gen_str, val_rtx, dest_align,
4742 : true, RETURN_BEGIN);
4743 : }
4744 1001 : else if (!set_storage_via_setmem (dest_mem, len_rtx, val_rtx,
4745 : dest_align, expected_align,
4746 : expected_size, min_size, max_size,
4747 : probable_max_size)
4748 1001 : && !try_store_by_multiple_pieces (dest_mem, len_rtx,
4749 : tree_ctz (len),
4750 : min_size, max_size,
4751 : val_rtx, 0,
4752 : dest_align))
4753 639 : goto do_libcall;
4754 :
4755 1088 : dest_mem = force_operand (XEXP (dest_mem, 0), NULL_RTX);
4756 1088 : dest_mem = convert_memory_address (ptr_mode, dest_mem);
4757 1088 : return dest_mem;
4758 : }
4759 :
4760 60996 : if (c)
4761 : {
4762 13492 : if (tree_fits_uhwi_p (len)
4763 13492 : && can_store_by_pieces (tree_to_uhwi (len),
4764 : builtin_memset_read_str, &c, dest_align,
4765 : true))
4766 5752 : store_by_pieces (dest_mem, tree_to_uhwi (len),
4767 : builtin_memset_read_str, &c, dest_align, true,
4768 : RETURN_BEGIN);
4769 9661 : else if (!set_storage_via_setmem (dest_mem, len_rtx,
4770 7740 : gen_int_mode (c, val_mode),
4771 : dest_align, expected_align,
4772 : expected_size, min_size, max_size,
4773 : probable_max_size)
4774 7740 : && !try_store_by_multiple_pieces (dest_mem, len_rtx,
4775 : tree_ctz (len),
4776 : min_size, max_size,
4777 : NULL_RTX, c,
4778 : dest_align))
4779 5819 : goto do_libcall;
4780 :
4781 7673 : dest_mem = force_operand (XEXP (dest_mem, 0), NULL_RTX);
4782 7673 : dest_mem = convert_memory_address (ptr_mode, dest_mem);
4783 7673 : return dest_mem;
4784 : }
4785 :
4786 47504 : set_mem_align (dest_mem, dest_align);
4787 95008 : dest_addr = clear_storage_hints (dest_mem, len_rtx,
4788 47504 : CALL_EXPR_TAILCALL (orig_exp)
4789 : ? BLOCK_OP_TAILCALL : BLOCK_OP_NORMAL,
4790 : expected_align, expected_size,
4791 : min_size, max_size,
4792 : probable_max_size, tree_ctz (len));
4793 :
4794 47504 : if (dest_addr == 0)
4795 : {
4796 37445 : dest_addr = force_operand (XEXP (dest_mem, 0), NULL_RTX);
4797 37445 : dest_addr = convert_memory_address (ptr_mode, dest_addr);
4798 : }
4799 :
4800 : return dest_addr;
4801 :
4802 6458 : do_libcall:
4803 6458 : fndecl = get_callee_fndecl (orig_exp);
4804 6458 : fcode = DECL_FUNCTION_CODE (fndecl);
4805 6458 : if (fcode == BUILT_IN_MEMSET)
4806 6458 : fn = build_call_nofold_loc (EXPR_LOCATION (orig_exp), fndecl, 3,
4807 : dest, val, len);
4808 0 : else if (fcode == BUILT_IN_BZERO)
4809 0 : fn = build_call_nofold_loc (EXPR_LOCATION (orig_exp), fndecl, 2,
4810 : dest, len);
4811 : else
4812 0 : gcc_unreachable ();
4813 6458 : gcc_assert (TREE_CODE (fn) == CALL_EXPR);
4814 6458 : CALL_EXPR_TAILCALL (fn) = CALL_EXPR_TAILCALL (orig_exp);
4815 6458 : return expand_call (fn, target, target == const0_rtx);
4816 : }
4817 :
4818 : /* Expand expression EXP, which is a call to the bzero builtin. Return
4819 : NULL_RTX if we failed the caller should emit a normal call. */
4820 :
4821 : static rtx
4822 0 : expand_builtin_bzero (tree exp)
4823 : {
4824 0 : if (!validate_arglist (exp, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
4825 : return NULL_RTX;
4826 :
4827 0 : tree dest = CALL_EXPR_ARG (exp, 0);
4828 0 : tree size = CALL_EXPR_ARG (exp, 1);
4829 :
4830 : /* New argument list transforming bzero(ptr x, int y) to
4831 : memset(ptr x, int 0, size_t y). This is done this way
4832 : so that if it isn't expanded inline, we fallback to
4833 : calling bzero instead of memset. */
4834 :
4835 0 : location_t loc = EXPR_LOCATION (exp);
4836 :
4837 0 : return expand_builtin_memset_args (dest, integer_zero_node,
4838 : fold_convert_loc (loc,
4839 : size_type_node, size),
4840 0 : const0_rtx, VOIDmode, exp);
4841 : }
4842 :
4843 : /* Try to expand cmpstr operation ICODE with the given operands.
4844 : Return the result rtx on success, otherwise return null. */
4845 :
4846 : static rtx
4847 0 : expand_cmpstr (insn_code icode, rtx target, rtx arg1_rtx, rtx arg2_rtx,
4848 : HOST_WIDE_INT align)
4849 : {
4850 0 : machine_mode insn_mode = insn_data[icode].operand[0].mode;
4851 :
4852 0 : if (target && (!REG_P (target) || HARD_REGISTER_P (target)))
4853 : target = NULL_RTX;
4854 :
4855 0 : class expand_operand ops[4];
4856 0 : create_output_operand (&ops[0], target, insn_mode);
4857 0 : create_fixed_operand (&ops[1], arg1_rtx);
4858 0 : create_fixed_operand (&ops[2], arg2_rtx);
4859 0 : create_integer_operand (&ops[3], align);
4860 0 : if (maybe_expand_insn (icode, 4, ops))
4861 0 : return ops[0].value;
4862 : return NULL_RTX;
4863 : }
4864 :
4865 : /* Expand expression EXP, which is a call to the memcmp built-in function.
4866 : Return NULL_RTX if we failed and the caller should emit a normal call,
4867 : otherwise try to get the result in TARGET, if convenient.
4868 : RESULT_EQ is true if we can relax the returned value to be either zero
4869 : or nonzero, without caring about the sign. */
4870 :
4871 : static rtx
4872 107259 : expand_builtin_memcmp (tree exp, rtx target, bool result_eq)
4873 : {
4874 107259 : if (!validate_arglist (exp,
4875 : POINTER_TYPE, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
4876 : return NULL_RTX;
4877 :
4878 107255 : tree arg1 = CALL_EXPR_ARG (exp, 0);
4879 107255 : tree arg2 = CALL_EXPR_ARG (exp, 1);
4880 107255 : tree len = CALL_EXPR_ARG (exp, 2);
4881 :
4882 : /* Due to the performance benefit, always inline the calls first
4883 : when result_eq is false. */
4884 107255 : rtx result = NULL_RTX;
4885 107255 : enum built_in_function fcode = DECL_FUNCTION_CODE (get_callee_fndecl (exp));
4886 107255 : if (!result_eq && fcode != BUILT_IN_BCMP)
4887 : {
4888 15315 : result = inline_expand_builtin_bytecmp (exp, target);
4889 15315 : if (result)
4890 : return result;
4891 : }
4892 :
4893 107237 : machine_mode mode = TYPE_MODE (TREE_TYPE (exp));
4894 107237 : location_t loc = EXPR_LOCATION (exp);
4895 :
4896 107237 : unsigned int arg1_align = get_pointer_alignment (arg1) / BITS_PER_UNIT;
4897 107237 : unsigned int arg2_align = get_pointer_alignment (arg2) / BITS_PER_UNIT;
4898 :
4899 : /* If we don't have POINTER_TYPE, call the function. */
4900 107237 : if (arg1_align == 0 || arg2_align == 0)
4901 : return NULL_RTX;
4902 :
4903 107237 : rtx arg1_rtx = get_memory_rtx (arg1, len, false);
4904 107237 : rtx arg2_rtx = get_memory_rtx (arg2, len, false);
4905 107237 : rtx len_rtx = expand_normal (fold_convert_loc (loc, sizetype, len));
4906 :
4907 : /* Set MEM_SIZE as appropriate. */
4908 107237 : if (CONST_INT_P (len_rtx))
4909 : {
4910 81477 : set_mem_size (arg1_rtx, INTVAL (len_rtx));
4911 81477 : set_mem_size (arg2_rtx, INTVAL (len_rtx));
4912 : }
4913 :
4914 107237 : by_pieces_constfn constfn = NULL;
4915 :
4916 : /* Try to get the byte representation of the constant ARG2 (or, only
4917 : when the function's result is used for equality to zero, ARG1)
4918 : points to, with its byte size in NBYTES. */
4919 107237 : unsigned HOST_WIDE_INT nbytes;
4920 107237 : const char *rep = getbyterep (arg2, &nbytes);
4921 107237 : if (result_eq && rep == NULL)
4922 : {
4923 : /* For equality to zero the arguments are interchangeable. */
4924 63851 : rep = getbyterep (arg1, &nbytes);
4925 63851 : if (rep != NULL)
4926 : std::swap (arg1_rtx, arg2_rtx);
4927 : }
4928 :
4929 : /* If the function's constant bound LEN_RTX is less than or equal
4930 : to the byte size of the representation of the constant argument,
4931 : and if block move would be done by pieces, we can avoid loading
4932 : the bytes from memory and only store the computed constant result. */
4933 43386 : if (rep
4934 30227 : && CONST_INT_P (len_rtx)
4935 30072 : && (unsigned HOST_WIDE_INT) INTVAL (len_rtx) <= nbytes)
4936 107237 : constfn = builtin_memcpy_read_str;
4937 :
4938 214474 : result = emit_block_cmp_hints (arg1_rtx, arg2_rtx, len_rtx,
4939 107237 : TREE_TYPE (len), target,
4940 : result_eq, constfn,
4941 : const_cast<char *> (rep),
4942 : tree_ctz (len));
4943 :
4944 107237 : if (result)
4945 : {
4946 : /* Return the value in the proper mode for this function. */
4947 69002 : if (GET_MODE (result) == mode)
4948 : return result;
4949 :
4950 0 : if (target != 0)
4951 : {
4952 0 : convert_move (target, result, 0);
4953 0 : return target;
4954 : }
4955 :
4956 0 : return convert_to_mode (mode, result, 0);
4957 : }
4958 :
4959 : return NULL_RTX;
4960 : }
4961 :
4962 : /* Expand expression EXP, which is a call to the strcmp builtin. Return NULL_RTX
4963 : if we failed the caller should emit a normal call, otherwise try to get
4964 : the result in TARGET, if convenient. */
4965 :
4966 : static rtx
4967 127960 : expand_builtin_strcmp (tree exp, ATTRIBUTE_UNUSED rtx target)
4968 : {
4969 127960 : if (!validate_arglist (exp, POINTER_TYPE, POINTER_TYPE, VOID_TYPE))
4970 : return NULL_RTX;
4971 :
4972 127945 : tree arg1 = CALL_EXPR_ARG (exp, 0);
4973 127945 : tree arg2 = CALL_EXPR_ARG (exp, 1);
4974 :
4975 : /* Due to the performance benefit, always inline the calls first. */
4976 127945 : rtx result = NULL_RTX;
4977 127945 : result = inline_expand_builtin_bytecmp (exp, target);
4978 127945 : if (result)
4979 : return result;
4980 :
4981 127546 : insn_code cmpstr_icode = direct_optab_handler (cmpstr_optab, SImode);
4982 127546 : insn_code cmpstrn_icode = direct_optab_handler (cmpstrn_optab, SImode);
4983 127546 : if (cmpstr_icode == CODE_FOR_nothing && cmpstrn_icode == CODE_FOR_nothing)
4984 : return NULL_RTX;
4985 :
4986 127546 : unsigned int arg1_align = get_pointer_alignment (arg1) / BITS_PER_UNIT;
4987 127546 : unsigned int arg2_align = get_pointer_alignment (arg2) / BITS_PER_UNIT;
4988 :
4989 : /* If we don't have POINTER_TYPE, call the function. */
4990 127546 : if (arg1_align == 0 || arg2_align == 0)
4991 : return NULL_RTX;
4992 :
4993 : /* Stabilize the arguments in case gen_cmpstr(n)si fail. */
4994 127546 : arg1 = builtin_save_expr (arg1);
4995 127546 : arg2 = builtin_save_expr (arg2);
4996 :
4997 127546 : rtx arg1_rtx = get_memory_rtx (arg1, NULL, false);
4998 127546 : rtx arg2_rtx = get_memory_rtx (arg2, NULL, false);
4999 :
5000 : /* Try to call cmpstrsi. */
5001 127546 : if (cmpstr_icode != CODE_FOR_nothing)
5002 0 : result = expand_cmpstr (cmpstr_icode, target, arg1_rtx, arg2_rtx,
5003 0 : MIN (arg1_align, arg2_align));
5004 :
5005 : /* Try to determine at least one length and call cmpstrnsi. */
5006 127546 : if (!result && cmpstrn_icode != CODE_FOR_nothing)
5007 : {
5008 127546 : tree len;
5009 127546 : rtx arg3_rtx;
5010 :
5011 127546 : tree len1 = c_strlen (arg1, 1);
5012 127546 : tree len2 = c_strlen (arg2, 1);
5013 :
5014 127546 : if (len1)
5015 224 : len1 = size_binop (PLUS_EXPR, ssize_int (1), len1);
5016 127546 : if (len2)
5017 125918 : len2 = size_binop (PLUS_EXPR, ssize_int (1), len2);
5018 :
5019 : /* If we don't have a constant length for the first, use the length
5020 : of the second, if we know it. We don't require a constant for
5021 : this case; some cost analysis could be done if both are available
5022 : but neither is constant. For now, assume they're equally cheap,
5023 : unless one has side effects. If both strings have constant lengths,
5024 : use the smaller. */
5025 :
5026 127546 : if (!len1)
5027 : len = len2;
5028 224 : else if (!len2)
5029 : len = len1;
5030 17 : else if (TREE_SIDE_EFFECTS (len1))
5031 : len = len2;
5032 17 : else if (TREE_SIDE_EFFECTS (len2))
5033 : len = len1;
5034 17 : else if (TREE_CODE (len1) != INTEGER_CST)
5035 : len = len2;
5036 17 : else if (TREE_CODE (len2) != INTEGER_CST)
5037 : len = len1;
5038 10 : else if (tree_int_cst_lt (len1, len2))
5039 : len = len1;
5040 : else
5041 127546 : len = len2;
5042 :
5043 : /* If both arguments have side effects, we cannot optimize. */
5044 127546 : if (len && !TREE_SIDE_EFFECTS (len))
5045 : {
5046 126125 : arg3_rtx = expand_normal (len);
5047 126125 : result = expand_cmpstrn_or_cmpmem
5048 126125 : (cmpstrn_icode, target, arg1_rtx, arg2_rtx, TREE_TYPE (len),
5049 126125 : arg3_rtx, MIN (arg1_align, arg2_align));
5050 : }
5051 : }
5052 :
5053 127546 : tree fndecl = get_callee_fndecl (exp);
5054 127546 : if (result)
5055 : {
5056 : /* Return the value in the proper mode for this function. */
5057 52 : machine_mode mode = TYPE_MODE (TREE_TYPE (exp));
5058 52 : if (GET_MODE (result) == mode)
5059 : return result;
5060 0 : if (target == 0)
5061 0 : return convert_to_mode (mode, result, 0);
5062 0 : convert_move (target, result, 0);
5063 0 : return target;
5064 : }
5065 :
5066 : /* Expand the library call ourselves using a stabilized argument
5067 : list to avoid re-evaluating the function's arguments twice. */
5068 127494 : tree fn = build_call_nofold_loc (EXPR_LOCATION (exp), fndecl, 2, arg1, arg2);
5069 127494 : copy_warning (fn, exp);
5070 127494 : gcc_assert (TREE_CODE (fn) == CALL_EXPR);
5071 127494 : CALL_EXPR_TAILCALL (fn) = CALL_EXPR_TAILCALL (exp);
5072 127494 : return expand_call (fn, target, target == const0_rtx);
5073 : }
5074 :
5075 : /* Expand expression EXP, which is a call to the strncmp builtin. Return
5076 : NULL_RTX if we failed the caller should emit a normal call, otherwise
5077 : try to get the result in TARGET, if convenient. */
5078 :
5079 : static rtx
5080 2027 : expand_builtin_strncmp (tree exp, ATTRIBUTE_UNUSED rtx target,
5081 : ATTRIBUTE_UNUSED machine_mode mode)
5082 : {
5083 2027 : if (!validate_arglist (exp,
5084 : POINTER_TYPE, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
5085 : return NULL_RTX;
5086 :
5087 2021 : tree arg1 = CALL_EXPR_ARG (exp, 0);
5088 2021 : tree arg2 = CALL_EXPR_ARG (exp, 1);
5089 2021 : tree arg3 = CALL_EXPR_ARG (exp, 2);
5090 :
5091 2021 : location_t loc = EXPR_LOCATION (exp);
5092 2021 : tree len1 = c_strlen (arg1, 1);
5093 2021 : tree len2 = c_strlen (arg2, 1);
5094 :
5095 : /* Due to the performance benefit, always inline the calls first. */
5096 2021 : rtx result = NULL_RTX;
5097 2021 : result = inline_expand_builtin_bytecmp (exp, target);
5098 2021 : if (result)
5099 : return result;
5100 :
5101 : /* If c_strlen can determine an expression for one of the string
5102 : lengths, and it doesn't have side effects, then emit cmpstrnsi
5103 : using length MIN(strlen(string)+1, arg3). */
5104 1803 : insn_code cmpstrn_icode = direct_optab_handler (cmpstrn_optab, SImode);
5105 1803 : if (cmpstrn_icode == CODE_FOR_nothing)
5106 : return NULL_RTX;
5107 :
5108 1803 : tree len;
5109 :
5110 1803 : unsigned int arg1_align = get_pointer_alignment (arg1) / BITS_PER_UNIT;
5111 1803 : unsigned int arg2_align = get_pointer_alignment (arg2) / BITS_PER_UNIT;
5112 :
5113 1803 : if (len1)
5114 160 : len1 = size_binop_loc (loc, PLUS_EXPR, ssize_int (1), len1);
5115 1803 : if (len2)
5116 674 : len2 = size_binop_loc (loc, PLUS_EXPR, ssize_int (1), len2);
5117 :
5118 1803 : tree len3 = fold_convert_loc (loc, sizetype, arg3);
5119 :
5120 : /* If we don't have a constant length for the first, use the length
5121 : of the second, if we know it. If neither string is constant length,
5122 : use the given length argument. We don't require a constant for
5123 : this case; some cost analysis could be done if both are available
5124 : but neither is constant. For now, assume they're equally cheap,
5125 : unless one has side effects. If both strings have constant lengths,
5126 : use the smaller. */
5127 :
5128 1803 : if (!len1 && !len2)
5129 : len = len3;
5130 717 : else if (!len1)
5131 : len = len2;
5132 160 : else if (!len2)
5133 : len = len1;
5134 117 : else if (TREE_SIDE_EFFECTS (len1))
5135 : len = len2;
5136 117 : else if (TREE_SIDE_EFFECTS (len2))
5137 : len = len1;
5138 117 : else if (TREE_CODE (len1) != INTEGER_CST)
5139 : len = len2;
5140 117 : else if (TREE_CODE (len2) != INTEGER_CST)
5141 : len = len1;
5142 117 : else if (tree_int_cst_lt (len1, len2))
5143 : len = len1;
5144 : else
5145 1803 : len = len2;
5146 :
5147 : /* If we are not using the given length, we must incorporate it here.
5148 : The actual new length parameter will be MIN(len,arg3) in this case. */
5149 1803 : if (len != len3)
5150 : {
5151 717 : len = fold_convert_loc (loc, sizetype, len);
5152 717 : len = fold_build2_loc (loc, MIN_EXPR, TREE_TYPE (len), len, len3);
5153 : }
5154 1803 : rtx arg1_rtx = get_memory_rtx (arg1, len, false);
5155 1803 : rtx arg2_rtx = get_memory_rtx (arg2, len, false);
5156 1803 : rtx arg3_rtx = expand_normal (len);
5157 1803 : result = expand_cmpstrn_or_cmpmem (cmpstrn_icode, target, arg1_rtx,
5158 1803 : arg2_rtx, TREE_TYPE (len), arg3_rtx,
5159 1803 : MIN (arg1_align, arg2_align));
5160 :
5161 1803 : tree fndecl = get_callee_fndecl (exp);
5162 1803 : if (result)
5163 : {
5164 : /* Return the value in the proper mode for this function. */
5165 17 : mode = TYPE_MODE (TREE_TYPE (exp));
5166 17 : if (GET_MODE (result) == mode)
5167 : return result;
5168 0 : if (target == 0)
5169 0 : return convert_to_mode (mode, result, 0);
5170 0 : convert_move (target, result, 0);
5171 0 : return target;
5172 : }
5173 :
5174 : /* Expand the library call ourselves using a stabilized argument
5175 : list to avoid re-evaluating the function's arguments twice. */
5176 1786 : tree call = build_call_nofold_loc (loc, fndecl, 3, arg1, arg2, len);
5177 1786 : copy_warning (call, exp);
5178 1786 : gcc_assert (TREE_CODE (call) == CALL_EXPR);
5179 1786 : CALL_EXPR_TAILCALL (call) = CALL_EXPR_TAILCALL (exp);
5180 1786 : return expand_call (call, target, target == const0_rtx);
5181 : }
5182 :
5183 : /* Expand a call to __builtin_saveregs, generating the result in TARGET,
5184 : if that's convenient. */
5185 :
5186 : rtx
5187 0 : expand_builtin_saveregs (void)
5188 : {
5189 0 : rtx val;
5190 0 : rtx_insn *seq;
5191 :
5192 : /* Don't do __builtin_saveregs more than once in a function.
5193 : Save the result of the first call and reuse it. */
5194 0 : if (saveregs_value != 0)
5195 : return saveregs_value;
5196 :
5197 : /* When this function is called, it means that registers must be
5198 : saved on entry to this function. So we migrate the call to the
5199 : first insn of this function. */
5200 :
5201 0 : start_sequence ();
5202 :
5203 : /* Do whatever the machine needs done in this case. */
5204 0 : val = targetm.calls.expand_builtin_saveregs ();
5205 :
5206 0 : seq = end_sequence ();
5207 :
5208 0 : saveregs_value = val;
5209 :
5210 : /* Put the insns after the NOTE that starts the function. If this
5211 : is inside a start_sequence, make the outer-level insn chain current, so
5212 : the code is placed at the start of the function. */
5213 0 : push_topmost_sequence ();
5214 0 : emit_insn_after (seq, entry_of_function ());
5215 0 : pop_topmost_sequence ();
5216 :
5217 0 : return val;
5218 : }
5219 :
5220 : /* Expand a call to __builtin_next_arg. */
5221 :
5222 : static rtx
5223 21245 : expand_builtin_next_arg (void)
5224 : {
5225 : /* Checking arguments is already done in fold_builtin_next_arg
5226 : that must be called before this function. */
5227 21245 : return expand_binop (ptr_mode, add_optab,
5228 : crtl->args.internal_arg_pointer,
5229 : crtl->args.arg_offset_rtx,
5230 21245 : NULL_RTX, 0, OPTAB_LIB_WIDEN);
5231 : }
5232 :
5233 : /* Make it easier for the backends by protecting the valist argument
5234 : from multiple evaluations. */
5235 :
5236 : static tree
5237 21567 : stabilize_va_list_loc (location_t loc, tree valist, int needs_lvalue)
5238 : {
5239 21567 : tree vatype = targetm.canonical_va_list_type (TREE_TYPE (valist));
5240 :
5241 : /* The current way of determining the type of valist is completely
5242 : bogus. We should have the information on the va builtin instead. */
5243 21567 : if (!vatype)
5244 21443 : vatype = targetm.fn_abi_va_list (cfun->decl);
5245 :
5246 21567 : if (TREE_CODE (vatype) == ARRAY_TYPE)
5247 : {
5248 15899 : if (TREE_SIDE_EFFECTS (valist))
5249 0 : valist = save_expr (valist);
5250 :
5251 : /* For this case, the backends will be expecting a pointer to
5252 : vatype, but it's possible we've actually been given an array
5253 : (an actual TARGET_CANONICAL_VA_LIST_TYPE (valist)).
5254 : So fix it. */
5255 15899 : if (TREE_CODE (TREE_TYPE (valist)) == ARRAY_TYPE)
5256 : {
5257 0 : tree p1 = build_pointer_type (TREE_TYPE (vatype));
5258 0 : valist = build_fold_addr_expr_with_type_loc (loc, valist, p1);
5259 : }
5260 : }
5261 : else
5262 : {
5263 5668 : tree pt = build_pointer_type (vatype);
5264 :
5265 5668 : if (! needs_lvalue)
5266 : {
5267 6 : if (! TREE_SIDE_EFFECTS (valist))
5268 : return valist;
5269 :
5270 0 : valist = fold_build1_loc (loc, ADDR_EXPR, pt, valist);
5271 0 : TREE_SIDE_EFFECTS (valist) = 1;
5272 : }
5273 :
5274 5662 : if (TREE_SIDE_EFFECTS (valist))
5275 0 : valist = save_expr (valist);
5276 5662 : valist = fold_build2_loc (loc, MEM_REF,
5277 : vatype, valist, build_int_cst (pt, 0));
5278 : }
5279 :
5280 : return valist;
5281 : }
5282 :
5283 : /* The "standard" definition of va_list is void*. */
5284 :
5285 : tree
5286 0 : std_build_builtin_va_list (void)
5287 : {
5288 0 : return ptr_type_node;
5289 : }
5290 :
5291 : /* The "standard" abi va_list is va_list_type_node. */
5292 :
5293 : tree
5294 0 : std_fn_abi_va_list (tree fndecl ATTRIBUTE_UNUSED)
5295 : {
5296 0 : return va_list_type_node;
5297 : }
5298 :
5299 : /* The "standard" type of va_list is va_list_type_node. */
5300 :
5301 : tree
5302 502 : std_canonical_va_list_type (tree type)
5303 : {
5304 502 : tree wtype, htype;
5305 :
5306 502 : wtype = va_list_type_node;
5307 502 : htype = type;
5308 :
5309 502 : if (TREE_CODE (wtype) == ARRAY_TYPE)
5310 : {
5311 : /* If va_list is an array type, the argument may have decayed
5312 : to a pointer type, e.g. by being passed to another function.
5313 : In that case, unwrap both types so that we can compare the
5314 : underlying records. */
5315 0 : if (TREE_CODE (htype) == ARRAY_TYPE
5316 0 : || POINTER_TYPE_P (htype))
5317 : {
5318 0 : wtype = TREE_TYPE (wtype);
5319 0 : htype = TREE_TYPE (htype);
5320 : }
5321 : }
5322 502 : if (TYPE_MAIN_VARIANT (wtype) == TYPE_MAIN_VARIANT (htype))
5323 332 : return va_list_type_node;
5324 :
5325 : return NULL_TREE;
5326 : }
5327 :
5328 : /* The "standard" implementation of va_start: just assign `nextarg' to
5329 : the variable. */
5330 :
5331 : void
5332 5658 : std_expand_builtin_va_start (tree valist, rtx nextarg)
5333 : {
5334 5658 : rtx va_r = expand_expr (valist, NULL_RTX, VOIDmode, EXPAND_WRITE);
5335 5658 : convert_move (va_r, nextarg, 0);
5336 5658 : }
5337 :
5338 : /* Expand EXP, a call to __builtin_va_start. */
5339 :
5340 : static rtx
5341 21087 : expand_builtin_va_start (tree exp)
5342 : {
5343 21087 : rtx nextarg;
5344 21087 : tree valist;
5345 21087 : location_t loc = EXPR_LOCATION (exp);
5346 :
5347 21087 : if (call_expr_nargs (exp) < 2)
5348 : {
5349 0 : error_at (loc, "too few arguments to function %<va_start%>");
5350 0 : return const0_rtx;
5351 : }
5352 :
5353 21087 : if (fold_builtin_next_arg (exp, true))
5354 0 : return const0_rtx;
5355 :
5356 21087 : nextarg = expand_builtin_next_arg ();
5357 21087 : valist = stabilize_va_list_loc (loc, CALL_EXPR_ARG (exp, 0), 1);
5358 :
5359 21087 : if (targetm.expand_builtin_va_start)
5360 21087 : targetm.expand_builtin_va_start (valist, nextarg);
5361 : else
5362 0 : std_expand_builtin_va_start (valist, nextarg);
5363 :
5364 21087 : return const0_rtx;
5365 : }
5366 :
5367 : /* Expand EXP, a call to __builtin_va_end. */
5368 :
5369 : static rtx
5370 12162 : expand_builtin_va_end (tree exp)
5371 : {
5372 12162 : tree valist = CALL_EXPR_ARG (exp, 0);
5373 :
5374 : /* Evaluate for side effects, if needed. I hate macros that don't
5375 : do that. */
5376 12162 : if (TREE_SIDE_EFFECTS (valist))
5377 0 : expand_expr (valist, const0_rtx, VOIDmode, EXPAND_NORMAL);
5378 :
5379 12162 : return const0_rtx;
5380 : }
5381 :
5382 : /* Expand EXP, a call to __builtin_va_copy. We do this as a
5383 : builtin rather than just as an assignment in stdarg.h because of the
5384 : nastiness of array-type va_list types. */
5385 :
5386 : static rtx
5387 240 : expand_builtin_va_copy (tree exp)
5388 : {
5389 240 : tree dst, src, t;
5390 240 : location_t loc = EXPR_LOCATION (exp);
5391 :
5392 240 : dst = CALL_EXPR_ARG (exp, 0);
5393 240 : src = CALL_EXPR_ARG (exp, 1);
5394 :
5395 240 : dst = stabilize_va_list_loc (loc, dst, 1);
5396 240 : src = stabilize_va_list_loc (loc, src, 0);
5397 :
5398 240 : gcc_assert (cfun != NULL && cfun->decl != NULL_TREE);
5399 :
5400 240 : if (TREE_CODE (targetm.fn_abi_va_list (cfun->decl)) != ARRAY_TYPE)
5401 : {
5402 0 : t = build2 (MODIFY_EXPR, targetm.fn_abi_va_list (cfun->decl), dst, src);
5403 0 : TREE_SIDE_EFFECTS (t) = 1;
5404 0 : expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL);
5405 : }
5406 : else
5407 : {
5408 240 : rtx dstb, srcb, size;
5409 :
5410 : /* Evaluate to pointers. */
5411 240 : dstb = expand_expr (dst, NULL_RTX, Pmode, EXPAND_NORMAL);
5412 240 : srcb = expand_expr (src, NULL_RTX, Pmode, EXPAND_NORMAL);
5413 240 : size = expand_expr (TYPE_SIZE_UNIT (targetm.fn_abi_va_list (cfun->decl)),
5414 : NULL_RTX, VOIDmode, EXPAND_NORMAL);
5415 :
5416 240 : dstb = convert_memory_address (Pmode, dstb);
5417 240 : srcb = convert_memory_address (Pmode, srcb);
5418 :
5419 : /* "Dereference" to BLKmode memories. */
5420 240 : dstb = gen_rtx_MEM (BLKmode, dstb);
5421 240 : set_mem_alias_set (dstb, get_alias_set (TREE_TYPE (TREE_TYPE (dst))));
5422 240 : set_mem_align (dstb, TYPE_ALIGN (targetm.fn_abi_va_list (cfun->decl)));
5423 240 : srcb = gen_rtx_MEM (BLKmode, srcb);
5424 240 : set_mem_alias_set (srcb, get_alias_set (TREE_TYPE (TREE_TYPE (src))));
5425 240 : set_mem_align (srcb, TYPE_ALIGN (targetm.fn_abi_va_list (cfun->decl)));
5426 :
5427 : /* Copy. */
5428 240 : emit_block_move (dstb, srcb, size, BLOCK_OP_NORMAL);
5429 : }
5430 :
5431 240 : return const0_rtx;
5432 : }
5433 :
5434 : /* Expand a call to one of the builtin functions __builtin_frame_address or
5435 : __builtin_return_address. */
5436 :
5437 : static rtx
5438 15936 : expand_builtin_frame_address (tree fndecl, tree exp)
5439 : {
5440 : /* The argument must be a nonnegative integer constant.
5441 : It counts the number of frames to scan up the stack.
5442 : The value is either the frame pointer value or the return
5443 : address saved in that frame. */
5444 15936 : if (call_expr_nargs (exp) == 0)
5445 : /* Warning about missing arg was already issued. */
5446 0 : return const0_rtx;
5447 15936 : else if (! tree_fits_uhwi_p (CALL_EXPR_ARG (exp, 0)))
5448 : {
5449 0 : error ("invalid argument to %qD", fndecl);
5450 0 : return const0_rtx;
5451 : }
5452 : else
5453 : {
5454 : /* Number of frames to scan up the stack. */
5455 15936 : unsigned HOST_WIDE_INT count = tree_to_uhwi (CALL_EXPR_ARG (exp, 0));
5456 :
5457 15936 : rtx tem = expand_builtin_return_addr (DECL_FUNCTION_CODE (fndecl), count);
5458 :
5459 : /* Some ports cannot access arbitrary stack frames. */
5460 15936 : if (tem == NULL)
5461 : {
5462 0 : warning (0, "unsupported argument to %qD", fndecl);
5463 0 : return const0_rtx;
5464 : }
5465 :
5466 15936 : if (count)
5467 : {
5468 : /* Warn since no effort is made to ensure that any frame
5469 : beyond the current one exists or can be safely reached. */
5470 938 : warning (OPT_Wframe_address, "calling %qD with "
5471 : "a nonzero argument is unsafe", fndecl);
5472 : }
5473 :
5474 : /* For __builtin_frame_address, return what we've got. */
5475 15936 : if (DECL_FUNCTION_CODE (fndecl) == BUILT_IN_FRAME_ADDRESS)
5476 : return tem;
5477 :
5478 5173 : if (!REG_P (tem)
5479 5173 : && ! CONSTANT_P (tem))
5480 5173 : tem = copy_addr_to_reg (tem);
5481 : return tem;
5482 : }
5483 : }
5484 :
5485 : #if ! STACK_GROWS_DOWNWARD
5486 : # define STACK_TOPS GT
5487 : #else
5488 : # define STACK_TOPS LT
5489 : #endif
5490 :
5491 : #ifdef POINTERS_EXTEND_UNSIGNED
5492 : # define STACK_UNSIGNED POINTERS_EXTEND_UNSIGNED
5493 : #else
5494 : # define STACK_UNSIGNED true
5495 : #endif
5496 :
5497 : /* Expand a call to builtin function __builtin_stack_address. */
5498 :
5499 : static rtx
5500 3455 : expand_builtin_stack_address ()
5501 : {
5502 3455 : rtx ret = convert_to_mode (ptr_mode, copy_to_reg (stack_pointer_rtx),
5503 : STACK_UNSIGNED);
5504 :
5505 : #ifdef STACK_ADDRESS_OFFSET
5506 : /* Unbias the stack pointer, bringing it to the boundary between the
5507 : stack area claimed by the active function calling this builtin,
5508 : and stack ranges that could get clobbered if it called another
5509 : function. It should NOT encompass any stack red zone, that is
5510 : used in leaf functions.
5511 :
5512 : On SPARC, the register save area is *not* considered active or
5513 : used by the active function, but rather as akin to the area in
5514 : which call-preserved registers are saved by callees. This
5515 : enables __strub_leave to clear what would otherwise overlap with
5516 : its own register save area.
5517 :
5518 : If the address is computed too high or too low, parts of a stack
5519 : range that should be scrubbed may be left unscrubbed, scrubbing
5520 : may corrupt active portions of the stack frame, and stack ranges
5521 : may be doubly-scrubbed by caller and callee.
5522 :
5523 : In order for it to be just right, the area delimited by
5524 : @code{__builtin_stack_address} and @code{__builtin_frame_address
5525 : (0)} should encompass caller's registers saved by the function,
5526 : local on-stack variables and @code{alloca} stack areas.
5527 : Accumulated outgoing on-stack arguments, preallocated as part of
5528 : a function's own prologue, are to be regarded as part of the
5529 : (caller) function's active area as well, whereas those pushed or
5530 : allocated temporarily for a call are regarded as part of the
5531 : callee's stack range, rather than the caller's. */
5532 : ret = plus_constant (ptr_mode, ret, STACK_ADDRESS_OFFSET);
5533 : #endif
5534 :
5535 3455 : return force_reg (ptr_mode, ret);
5536 : }
5537 :
5538 : /* Expand a call to builtin function __builtin_strub_enter. */
5539 :
5540 : static rtx
5541 2170 : expand_builtin_strub_enter (tree exp)
5542 : {
5543 2170 : if (!validate_arglist (exp, POINTER_TYPE, VOID_TYPE))
5544 : return NULL_RTX;
5545 :
5546 2170 : if (optimize < 1 || flag_no_inline)
5547 : return NULL_RTX;
5548 :
5549 1526 : rtx stktop = expand_builtin_stack_address ();
5550 :
5551 1526 : tree wmptr = CALL_EXPR_ARG (exp, 0);
5552 1526 : tree wmtype = TREE_TYPE (TREE_TYPE (wmptr));
5553 1526 : tree wmtree = fold_build2 (MEM_REF, wmtype, wmptr,
5554 : build_int_cst (TREE_TYPE (wmptr), 0));
5555 1526 : rtx wmark = expand_expr (wmtree, NULL_RTX, ptr_mode, EXPAND_MEMORY);
5556 :
5557 1526 : emit_move_insn (wmark, stktop);
5558 :
5559 1526 : return const0_rtx;
5560 : }
5561 :
5562 : /* Expand a call to builtin function __builtin_strub_update. */
5563 :
5564 : static rtx
5565 1084 : expand_builtin_strub_update (tree exp)
5566 : {
5567 1084 : if (!validate_arglist (exp, POINTER_TYPE, VOID_TYPE))
5568 : return NULL_RTX;
5569 :
5570 1084 : if (optimize < 2 || flag_no_inline)
5571 : return NULL_RTX;
5572 :
5573 663 : rtx stktop = expand_builtin_stack_address ();
5574 :
5575 : #ifdef RED_ZONE_SIZE
5576 : /* Here's how the strub enter, update and leave functions deal with red zones.
5577 :
5578 : If it weren't for red zones, update, called from within a strub context,
5579 : would bump the watermark to the top of the stack. Enter and leave, running
5580 : in the caller, would use the caller's top of stack address both to
5581 : initialize the watermark passed to the callee, and to start strubbing the
5582 : stack afterwards.
5583 :
5584 : Ideally, we'd update the watermark so as to cover the used amount of red
5585 : zone, and strub starting at the caller's other end of the (presumably
5586 : unused) red zone. Normally, only leaf functions use the red zone, but at
5587 : this point we can't tell whether a function is a leaf, nor can we tell how
5588 : much of the red zone it uses. Furthermore, some strub contexts may have
5589 : been inlined so that update and leave are called from the same stack frame,
5590 : and the strub builtins may all have been inlined, turning a strub function
5591 : into a leaf.
5592 :
5593 : So cleaning the range from the caller's stack pointer (one end of the red
5594 : zone) to the (potentially inlined) callee's (other end of the) red zone
5595 : could scribble over the caller's own red zone.
5596 :
5597 : We avoid this possibility by arranging for callers that are strub contexts
5598 : to use their own watermark as the strub starting point. So, if A calls B,
5599 : and B calls C, B will tell A to strub up to the end of B's red zone, and
5600 : will strub itself only the part of C's stack frame and red zone that
5601 : doesn't overlap with B's. With that, we don't need to know who's leaf and
5602 : who isn't: inlined calls will shrink their strub window to zero, each
5603 : remaining call will strub some portion of the stack, and eventually the
5604 : strub context will return to a caller that isn't a strub context itself,
5605 : that will therefore use its own stack pointer as the strub starting point.
5606 : It's not a leaf, because strub contexts can't be inlined into non-strub
5607 : contexts, so it doesn't use the red zone, and it will therefore correctly
5608 : strub up the callee's stack frame up to the end of the callee's red zone.
5609 : Neat! */
5610 663 : if (true /* (flags_from_decl_or_type (current_function_decl) & ECF_LEAF) */)
5611 : {
5612 663 : poly_int64 red_zone_size = RED_ZONE_SIZE;
5613 : #if STACK_GROWS_DOWNWARD
5614 663 : red_zone_size = -red_zone_size;
5615 : #endif
5616 663 : stktop = plus_constant (ptr_mode, stktop, red_zone_size);
5617 663 : stktop = force_reg (ptr_mode, stktop);
5618 : }
5619 : #endif
5620 :
5621 663 : tree wmptr = CALL_EXPR_ARG (exp, 0);
5622 663 : tree wmtype = TREE_TYPE (TREE_TYPE (wmptr));
5623 663 : tree wmtree = fold_build2 (MEM_REF, wmtype, wmptr,
5624 : build_int_cst (TREE_TYPE (wmptr), 0));
5625 663 : rtx wmark = expand_expr (wmtree, NULL_RTX, ptr_mode, EXPAND_MEMORY);
5626 :
5627 663 : rtx wmark_load = shallow_copy_rtx (wmark);
5628 663 : MEM_NOTRAP_P (wmark_load) = !tree_could_trap_p (wmtree);
5629 663 : rtx wmarkr = force_reg (ptr_mode, wmark_load);
5630 :
5631 663 : rtx_code_label *lab = gen_label_rtx ();
5632 663 : do_compare_rtx_and_jump (stktop, wmarkr, STACK_TOPS, STACK_UNSIGNED,
5633 : ptr_mode, NULL_RTX, lab, NULL,
5634 : profile_probability::very_likely ());
5635 663 : emit_move_insn (wmark, stktop);
5636 :
5637 : /* If this is an inlined strub function, also bump the watermark for the
5638 : enclosing function. This avoids a problem with the following scenario: A
5639 : calls B and B calls C, and both B and C get inlined into A. B allocates
5640 : temporary stack space before calling C. If we don't update A's watermark,
5641 : we may use an outdated baseline for the post-C strub_leave, erasing B's
5642 : temporary stack allocation. We only need this if we're fully expanding
5643 : strub_leave inline. */
5644 663 : tree xwmptr = (optimize > 2
5645 663 : ? strub_watermark_parm (current_function_decl)
5646 : : wmptr);
5647 663 : if (wmptr != xwmptr)
5648 : {
5649 156 : wmptr = xwmptr;
5650 156 : wmtype = TREE_TYPE (TREE_TYPE (wmptr));
5651 156 : wmtree = fold_build2 (MEM_REF, wmtype, wmptr,
5652 : build_int_cst (TREE_TYPE (wmptr), 0));
5653 156 : wmark = expand_expr (wmtree, NULL_RTX, ptr_mode, EXPAND_MEMORY);
5654 156 : wmark_load = shallow_copy_rtx (wmark);
5655 156 : MEM_NOTRAP_P (wmark_load) = !tree_could_trap_p (wmtree);
5656 156 : wmarkr = force_reg (ptr_mode, wmark_load);
5657 :
5658 156 : do_compare_rtx_and_jump (stktop, wmarkr, STACK_TOPS, STACK_UNSIGNED,
5659 : ptr_mode, NULL_RTX, lab, NULL,
5660 : profile_probability::very_likely ());
5661 156 : emit_move_insn (wmark, stktop);
5662 : }
5663 :
5664 663 : emit_label (lab);
5665 :
5666 663 : return const0_rtx;
5667 : }
5668 :
5669 :
5670 : /* Expand a call to builtin function __builtin_strub_leave. */
5671 :
5672 : static rtx
5673 2740 : expand_builtin_strub_leave (tree exp)
5674 : {
5675 2740 : if (!validate_arglist (exp, POINTER_TYPE, VOID_TYPE))
5676 : return NULL_RTX;
5677 :
5678 2740 : if (optimize < 2 || optimize_size || flag_no_inline)
5679 : return NULL_RTX;
5680 :
5681 1239 : rtx stktop = NULL_RTX;
5682 :
5683 1239 : if (tree wmptr = (optimize
5684 1239 : ? strub_watermark_parm (current_function_decl)
5685 : : NULL_TREE))
5686 : {
5687 513 : tree wmtype = TREE_TYPE (TREE_TYPE (wmptr));
5688 513 : tree wmtree = fold_build2 (MEM_REF, wmtype, wmptr,
5689 : build_int_cst (TREE_TYPE (wmptr), 0));
5690 513 : rtx wmark = expand_expr (wmtree, NULL_RTX, ptr_mode, EXPAND_MEMORY);
5691 513 : MEM_NOTRAP_P (wmark) = !tree_could_trap_p (wmtree);
5692 513 : stktop = force_reg (ptr_mode, wmark);
5693 : }
5694 :
5695 513 : if (!stktop)
5696 726 : stktop = expand_builtin_stack_address ();
5697 :
5698 1239 : tree wmptr = CALL_EXPR_ARG (exp, 0);
5699 1239 : tree wmtype = TREE_TYPE (TREE_TYPE (wmptr));
5700 1239 : tree wmtree = fold_build2 (MEM_REF, wmtype, wmptr,
5701 : build_int_cst (TREE_TYPE (wmptr), 0));
5702 1239 : rtx wmark = expand_expr (wmtree, NULL_RTX, ptr_mode, EXPAND_MEMORY);
5703 1239 : MEM_NOTRAP_P (wmark) = !tree_could_trap_p (wmtree);
5704 :
5705 1239 : rtx wmarkr = force_reg (ptr_mode, wmark);
5706 :
5707 : #if ! STACK_GROWS_DOWNWARD
5708 : rtx base = stktop;
5709 : rtx end = wmarkr;
5710 : #else
5711 1239 : rtx base = wmarkr;
5712 1239 : rtx end = stktop;
5713 : #endif
5714 :
5715 : /* We're going to modify it, so make sure it's not e.g. the stack pointer. */
5716 1239 : base = copy_to_reg (base);
5717 :
5718 1239 : rtx_code_label *done = gen_label_rtx ();
5719 1239 : do_compare_rtx_and_jump (base, end, LT, STACK_UNSIGNED,
5720 : ptr_mode, NULL_RTX, done, NULL,
5721 : profile_probability::very_likely ());
5722 :
5723 1239 : if (optimize < 3)
5724 919 : expand_call (exp, NULL_RTX, true);
5725 : else
5726 : {
5727 : /* Ok, now we've determined we want to copy the block, so convert the
5728 : addresses to Pmode, as needed to dereference them to access ptr_mode
5729 : memory locations, so that we don't have to convert anything within the
5730 : loop. */
5731 320 : base = memory_address (ptr_mode, base);
5732 320 : end = memory_address (ptr_mode, end);
5733 :
5734 320 : rtx zero = force_operand (const0_rtx, NULL_RTX);
5735 320 : int ulen = GET_MODE_SIZE (ptr_mode);
5736 :
5737 : /* ??? It would be nice to use setmem or similar patterns here,
5738 : but they do not necessarily obey the stack growth direction,
5739 : which has security implications. We also have to avoid calls
5740 : (memset, bzero or any machine-specific ones), which are
5741 : likely unsafe here (see TARGET_STRUB_MAY_USE_MEMSET). */
5742 : #if ! STACK_GROWS_DOWNWARD
5743 : rtx incr = plus_constant (Pmode, base, ulen);
5744 : rtx dstm = gen_rtx_MEM (ptr_mode, base);
5745 :
5746 : rtx_code_label *loop = gen_label_rtx ();
5747 : emit_label (loop);
5748 : emit_move_insn (dstm, zero);
5749 : emit_move_insn (base, force_operand (incr, NULL_RTX));
5750 : #else
5751 320 : rtx decr = plus_constant (Pmode, end, -ulen);
5752 320 : rtx dstm = gen_rtx_MEM (ptr_mode, end);
5753 :
5754 320 : rtx_code_label *loop = gen_label_rtx ();
5755 320 : emit_label (loop);
5756 320 : emit_move_insn (end, force_operand (decr, NULL_RTX));
5757 320 : emit_move_insn (dstm, zero);
5758 : #endif
5759 640 : do_compare_rtx_and_jump (base, end, LT, STACK_UNSIGNED,
5760 320 : Pmode, NULL_RTX, NULL, loop,
5761 : profile_probability::very_likely ());
5762 : }
5763 :
5764 1239 : emit_label (done);
5765 :
5766 1239 : return const0_rtx;
5767 : }
5768 :
5769 : /* Expand EXP, a call to the alloca builtin. Return NULL_RTX if we
5770 : failed and the caller should emit a normal call. */
5771 :
5772 : static rtx
5773 27543 : expand_builtin_alloca (tree exp)
5774 : {
5775 27543 : rtx op0;
5776 27543 : rtx result;
5777 27543 : unsigned int align;
5778 27543 : tree fndecl = get_callee_fndecl (exp);
5779 27543 : HOST_WIDE_INT max_size;
5780 27543 : enum built_in_function fcode = DECL_FUNCTION_CODE (fndecl);
5781 27543 : bool alloca_for_var = CALL_ALLOCA_FOR_VAR_P (exp);
5782 27543 : bool valid_arglist
5783 : = (fcode == BUILT_IN_ALLOCA_WITH_ALIGN_AND_MAX
5784 27543 : ? validate_arglist (exp, INTEGER_TYPE, INTEGER_TYPE, INTEGER_TYPE,
5785 : VOID_TYPE)
5786 : : fcode == BUILT_IN_ALLOCA_WITH_ALIGN
5787 27541 : ? validate_arglist (exp, INTEGER_TYPE, INTEGER_TYPE, VOID_TYPE)
5788 27543 : : validate_arglist (exp, INTEGER_TYPE, VOID_TYPE));
5789 :
5790 27543 : if (!valid_arglist)
5791 : return NULL_RTX;
5792 :
5793 : /* Compute the argument. */
5794 27538 : op0 = expand_normal (CALL_EXPR_ARG (exp, 0));
5795 :
5796 : /* Compute the alignment. */
5797 51085 : align = (fcode == BUILT_IN_ALLOCA
5798 23548 : ? BIGGEST_ALIGNMENT
5799 3990 : : TREE_INT_CST_LOW (CALL_EXPR_ARG (exp, 1)));
5800 :
5801 : /* Compute the maximum size. */
5802 2 : max_size = (fcode == BUILT_IN_ALLOCA_WITH_ALIGN_AND_MAX
5803 27540 : ? TREE_INT_CST_LOW (CALL_EXPR_ARG (exp, 2))
5804 : : -1);
5805 :
5806 : /* Allocate the desired space. If the allocation stems from the declaration
5807 : of a variable-sized object, it cannot accumulate. */
5808 27538 : result
5809 27538 : = allocate_dynamic_stack_space (op0, 0, align, max_size, alloca_for_var);
5810 27538 : result = convert_memory_address (ptr_mode, result);
5811 :
5812 : /* Dynamic allocations for variables are recorded during gimplification. */
5813 27538 : if (!alloca_for_var && (flag_callgraph_info & CALLGRAPH_INFO_DYNAMIC_ALLOC))
5814 0 : record_dynamic_alloc (exp);
5815 :
5816 : return result;
5817 : }
5818 :
5819 : /* Emit a call to __asan_allocas_unpoison call in EXP. Add to second argument
5820 : of the call virtual_stack_dynamic_rtx - stack_pointer_rtx, which is the
5821 : STACK_DYNAMIC_OFFSET value. See motivation for this in comment to
5822 : handle_builtin_stack_restore function. */
5823 :
5824 : static rtx
5825 204 : expand_asan_emit_allocas_unpoison (tree exp)
5826 : {
5827 204 : tree arg0 = CALL_EXPR_ARG (exp, 0);
5828 204 : tree arg1 = CALL_EXPR_ARG (exp, 1);
5829 204 : rtx top = expand_expr (arg0, NULL_RTX, ptr_mode, EXPAND_NORMAL);
5830 204 : rtx bot = expand_expr (arg1, NULL_RTX, ptr_mode, EXPAND_NORMAL);
5831 204 : rtx off = expand_simple_binop (Pmode, MINUS, virtual_stack_dynamic_rtx,
5832 : stack_pointer_rtx, NULL_RTX, 0,
5833 : OPTAB_LIB_WIDEN);
5834 204 : off = convert_modes (ptr_mode, Pmode, off, 0);
5835 204 : bot = expand_simple_binop (ptr_mode, PLUS, bot, off, NULL_RTX, 0,
5836 : OPTAB_LIB_WIDEN);
5837 204 : rtx ret = init_one_libfunc ("__asan_allocas_unpoison");
5838 204 : ret = emit_library_call_value (ret, NULL_RTX, LCT_NORMAL, ptr_mode,
5839 : top, ptr_mode, bot, ptr_mode);
5840 204 : return ret;
5841 : }
5842 :
5843 : /* Expand a call to bswap builtin in EXP.
5844 : Return NULL_RTX if a normal call should be emitted rather than expanding the
5845 : function in-line. If convenient, the result should be placed in TARGET.
5846 : SUBTARGET may be used as the target for computing one of EXP's operands. */
5847 :
5848 : static rtx
5849 1276 : expand_builtin_bswap (machine_mode target_mode, tree exp, rtx target,
5850 : rtx subtarget)
5851 : {
5852 1276 : tree arg;
5853 1276 : rtx op0;
5854 :
5855 1276 : if (!validate_arglist (exp, INTEGER_TYPE, VOID_TYPE))
5856 : return NULL_RTX;
5857 :
5858 1276 : arg = CALL_EXPR_ARG (exp, 0);
5859 1276 : op0 = expand_expr (arg,
5860 56 : subtarget && GET_MODE (subtarget) == target_mode
5861 : ? subtarget : NULL_RTX,
5862 : target_mode, EXPAND_NORMAL);
5863 1276 : if (GET_MODE (op0) != target_mode)
5864 0 : op0 = convert_to_mode (target_mode, op0, 1);
5865 :
5866 1276 : target = expand_unop (target_mode, bswap_optab, op0, target, 1);
5867 :
5868 1276 : gcc_assert (target);
5869 :
5870 1276 : return convert_to_mode (target_mode, target, 1);
5871 : }
5872 :
5873 : /* Expand a call to a unary builtin in EXP.
5874 : Return NULL_RTX if a normal call should be emitted rather than expanding the
5875 : function in-line. If convenient, the result should be placed in TARGET.
5876 : SUBTARGET may be used as the target for computing one of EXP's operands. */
5877 :
5878 : static rtx
5879 862 : expand_builtin_unop (machine_mode target_mode, tree exp, rtx target,
5880 : rtx subtarget, optab op_optab)
5881 : {
5882 862 : rtx op0;
5883 :
5884 862 : if (!validate_arglist (exp, INTEGER_TYPE, VOID_TYPE))
5885 : return NULL_RTX;
5886 :
5887 : /* Compute the argument. */
5888 1724 : op0 = expand_expr (CALL_EXPR_ARG (exp, 0),
5889 : (subtarget
5890 106 : && (TYPE_MODE (TREE_TYPE (CALL_EXPR_ARG (exp, 0)))
5891 106 : == GET_MODE (subtarget))) ? subtarget : NULL_RTX,
5892 : VOIDmode, EXPAND_NORMAL);
5893 : /* Compute op, into TARGET if possible.
5894 : Set TARGET to wherever the result comes back. */
5895 862 : target = expand_unop (TYPE_MODE (TREE_TYPE (CALL_EXPR_ARG (exp, 0))),
5896 : op_optab, op0, target, op_optab != clrsb_optab);
5897 862 : gcc_assert (target);
5898 :
5899 862 : return convert_to_mode (target_mode, target, 0);
5900 : }
5901 :
5902 : /* Expand a call to __builtin_expect. We just return our argument
5903 : as the builtin_expect semantic should've been already executed by
5904 : tree branch prediction pass. */
5905 :
5906 : static rtx
5907 1407 : expand_builtin_expect (tree exp, rtx target)
5908 : {
5909 1407 : tree arg;
5910 :
5911 1407 : if (call_expr_nargs (exp) < 2)
5912 0 : return const0_rtx;
5913 1407 : arg = CALL_EXPR_ARG (exp, 0);
5914 :
5915 1407 : target = expand_expr (arg, target, VOIDmode, EXPAND_NORMAL);
5916 : /* When guessing was done, the hints should be already stripped away. */
5917 1407 : gcc_assert (!flag_guess_branch_prob
5918 : || optimize == 0 || seen_error ());
5919 : return target;
5920 : }
5921 :
5922 : /* Expand a call to __builtin_expect_with_probability. We just return our
5923 : argument as the builtin_expect semantic should've been already executed by
5924 : tree branch prediction pass. */
5925 :
5926 : static rtx
5927 5 : expand_builtin_expect_with_probability (tree exp, rtx target)
5928 : {
5929 5 : tree arg;
5930 :
5931 5 : if (call_expr_nargs (exp) < 3)
5932 0 : return const0_rtx;
5933 5 : arg = CALL_EXPR_ARG (exp, 0);
5934 :
5935 5 : target = expand_expr (arg, target, VOIDmode, EXPAND_NORMAL);
5936 : /* When guessing was done, the hints should be already stripped away. */
5937 5 : gcc_assert (!flag_guess_branch_prob
5938 : || optimize == 0 || seen_error ());
5939 : return target;
5940 : }
5941 :
5942 :
5943 : /* Expand a call to __builtin_assume_aligned. We just return our first
5944 : argument as the builtin_assume_aligned semantic should've been already
5945 : executed by CCP. */
5946 :
5947 : static rtx
5948 662 : expand_builtin_assume_aligned (tree exp, rtx target)
5949 : {
5950 662 : if (call_expr_nargs (exp) < 2)
5951 0 : return const0_rtx;
5952 662 : target = expand_expr (CALL_EXPR_ARG (exp, 0), target, VOIDmode,
5953 : EXPAND_NORMAL);
5954 662 : gcc_assert (!TREE_SIDE_EFFECTS (CALL_EXPR_ARG (exp, 1))
5955 : && (call_expr_nargs (exp) < 3
5956 : || !TREE_SIDE_EFFECTS (CALL_EXPR_ARG (exp, 2))));
5957 : return target;
5958 : }
5959 :
5960 : void
5961 38761 : expand_builtin_trap (void)
5962 : {
5963 38761 : if (targetm.have_trap ())
5964 : {
5965 38761 : rtx_insn *insn = emit_insn (targetm.gen_trap ());
5966 : /* For trap insns when not accumulating outgoing args force
5967 : REG_ARGS_SIZE note to prevent crossjumping of calls with
5968 : different args sizes. */
5969 38761 : if (!ACCUMULATE_OUTGOING_ARGS)
5970 38759 : add_args_size_note (insn, stack_pointer_delta);
5971 : }
5972 : else
5973 : {
5974 0 : tree fn = builtin_decl_implicit (BUILT_IN_ABORT);
5975 0 : tree call_expr = build_call_expr (fn, 0);
5976 0 : expand_call (call_expr, NULL_RTX, false);
5977 : }
5978 :
5979 38761 : emit_barrier ();
5980 38761 : }
5981 :
5982 : /* Expand a call to __builtin_unreachable. We do nothing except emit
5983 : a barrier saying that control flow will not pass here.
5984 :
5985 : It is the responsibility of the program being compiled to ensure
5986 : that control flow does never reach __builtin_unreachable. */
5987 : static void
5988 2641 : expand_builtin_unreachable (void)
5989 : {
5990 : /* Use gimple_build_builtin_unreachable or builtin_decl_unreachable
5991 : to avoid this. */
5992 2641 : gcc_checking_assert (!sanitize_flags_p (SANITIZE_UNREACHABLE));
5993 2641 : emit_barrier ();
5994 2641 : }
5995 :
5996 : /* Expand EXP, a call to fabs, fabsf or fabsl.
5997 : Return NULL_RTX if a normal call should be emitted rather than expanding
5998 : the function inline. If convenient, the result should be placed
5999 : in TARGET. SUBTARGET may be used as the target for computing
6000 : the operand. */
6001 :
6002 : static rtx
6003 4 : expand_builtin_fabs (tree exp, rtx target, rtx subtarget)
6004 : {
6005 4 : machine_mode mode;
6006 4 : tree arg;
6007 4 : rtx op0;
6008 :
6009 4 : if (!validate_arglist (exp, REAL_TYPE, VOID_TYPE))
6010 : return NULL_RTX;
6011 :
6012 0 : arg = CALL_EXPR_ARG (exp, 0);
6013 0 : CALL_EXPR_ARG (exp, 0) = arg = builtin_save_expr (arg);
6014 0 : mode = TYPE_MODE (TREE_TYPE (arg));
6015 0 : op0 = expand_expr (arg, subtarget, VOIDmode, EXPAND_NORMAL);
6016 0 : return expand_abs (mode, op0, target, 0, safe_from_p (target, arg, 1));
6017 : }
6018 :
6019 : /* Expand EXP, a call to copysign, copysignf, or copysignl.
6020 : Return NULL is a normal call should be emitted rather than expanding the
6021 : function inline. If convenient, the result should be placed in TARGET.
6022 : SUBTARGET may be used as the target for computing the operand. */
6023 :
6024 : static rtx
6025 11677 : expand_builtin_copysign (tree exp, rtx target, rtx subtarget)
6026 : {
6027 11677 : rtx op0, op1;
6028 11677 : tree arg;
6029 :
6030 11677 : if (!validate_arglist (exp, REAL_TYPE, REAL_TYPE, VOID_TYPE))
6031 : return NULL_RTX;
6032 :
6033 11676 : arg = CALL_EXPR_ARG (exp, 0);
6034 11676 : op0 = expand_expr (arg, subtarget, VOIDmode, EXPAND_NORMAL);
6035 :
6036 11676 : arg = CALL_EXPR_ARG (exp, 1);
6037 11676 : op1 = expand_normal (arg);
6038 :
6039 11676 : return expand_copysign (op0, op1, target);
6040 : }
6041 :
6042 : /* Emit a call to __builtin___clear_cache. */
6043 :
6044 : void
6045 0 : default_emit_call_builtin___clear_cache (rtx begin, rtx end)
6046 : {
6047 0 : rtx callee = gen_rtx_SYMBOL_REF (Pmode,
6048 : BUILTIN_ASM_NAME_PTR
6049 : (BUILT_IN_CLEAR_CACHE));
6050 :
6051 0 : emit_library_call (callee,
6052 : LCT_NORMAL, VOIDmode,
6053 : convert_memory_address (ptr_mode, begin), ptr_mode,
6054 : convert_memory_address (ptr_mode, end), ptr_mode);
6055 0 : }
6056 :
6057 : /* Emit a call to __builtin___clear_cache, unless the target specifies
6058 : it as do-nothing. This function can be used by trampoline
6059 : finalizers to duplicate the effects of expanding a call to the
6060 : clear_cache builtin. */
6061 :
6062 : void
6063 28 : maybe_emit_call_builtin___clear_cache (rtx begin, rtx end)
6064 : {
6065 28 : gcc_assert ((GET_MODE (begin) == ptr_mode || GET_MODE (begin) == Pmode
6066 : || CONST_INT_P (begin))
6067 : && (GET_MODE (end) == ptr_mode || GET_MODE (end) == Pmode
6068 : || CONST_INT_P (end)));
6069 :
6070 28 : if (targetm.have_clear_cache ())
6071 : {
6072 : /* We have a "clear_cache" insn, and it will handle everything. */
6073 0 : class expand_operand ops[2];
6074 :
6075 0 : create_address_operand (&ops[0], begin);
6076 0 : create_address_operand (&ops[1], end);
6077 :
6078 0 : if (maybe_expand_insn (targetm.code_for_clear_cache, 2, ops))
6079 0 : return;
6080 : }
6081 : else
6082 : {
6083 : #ifndef CLEAR_INSN_CACHE
6084 : /* There is no "clear_cache" insn, and __clear_cache() in libgcc
6085 : does nothing. There is no need to call it. Do nothing. */
6086 : return;
6087 : #endif /* CLEAR_INSN_CACHE */
6088 : }
6089 :
6090 0 : targetm.calls.emit_call_builtin___clear_cache (begin, end);
6091 : }
6092 :
6093 : /* Expand a call to __builtin___clear_cache. */
6094 :
6095 : static void
6096 28 : expand_builtin___clear_cache (tree exp)
6097 : {
6098 28 : tree begin, end;
6099 28 : rtx begin_rtx, end_rtx;
6100 :
6101 : /* We must not expand to a library call. If we did, any
6102 : fallback library function in libgcc that might contain a call to
6103 : __builtin___clear_cache() would recurse infinitely. */
6104 28 : if (!validate_arglist (exp, POINTER_TYPE, POINTER_TYPE, VOID_TYPE))
6105 : {
6106 0 : error ("both arguments to %<__builtin___clear_cache%> must be pointers");
6107 0 : return;
6108 : }
6109 :
6110 28 : begin = CALL_EXPR_ARG (exp, 0);
6111 30 : begin_rtx = expand_expr (begin, NULL_RTX, Pmode, EXPAND_NORMAL);
6112 :
6113 28 : end = CALL_EXPR_ARG (exp, 1);
6114 30 : end_rtx = expand_expr (end, NULL_RTX, Pmode, EXPAND_NORMAL);
6115 :
6116 28 : maybe_emit_call_builtin___clear_cache (begin_rtx, end_rtx);
6117 : }
6118 :
6119 : /* Given a trampoline address, make sure it satisfies TRAMPOLINE_ALIGNMENT. */
6120 :
6121 : static rtx
6122 659 : round_trampoline_addr (rtx tramp)
6123 : {
6124 659 : rtx temp, addend, mask;
6125 :
6126 : /* If we don't need too much alignment, we'll have been guaranteed
6127 : proper alignment by get_trampoline_type. */
6128 659 : if (TRAMPOLINE_ALIGNMENT <= STACK_BOUNDARY)
6129 : return tramp;
6130 :
6131 : /* Round address up to desired boundary. */
6132 0 : temp = gen_reg_rtx (Pmode);
6133 0 : addend = gen_int_mode (TRAMPOLINE_ALIGNMENT / BITS_PER_UNIT - 1, Pmode);
6134 0 : mask = gen_int_mode (-TRAMPOLINE_ALIGNMENT / BITS_PER_UNIT, Pmode);
6135 :
6136 0 : temp = expand_simple_binop (Pmode, PLUS, tramp, addend,
6137 : temp, 0, OPTAB_LIB_WIDEN);
6138 0 : tramp = expand_simple_binop (Pmode, AND, temp, mask,
6139 : temp, 0, OPTAB_LIB_WIDEN);
6140 :
6141 0 : return tramp;
6142 : }
6143 :
6144 : static rtx
6145 306 : expand_builtin_init_trampoline (tree exp, bool onstack)
6146 : {
6147 306 : tree t_tramp, t_func, t_chain;
6148 306 : rtx m_tramp, r_tramp, r_chain, tmp;
6149 :
6150 306 : if (!validate_arglist (exp, POINTER_TYPE, POINTER_TYPE,
6151 : POINTER_TYPE, VOID_TYPE))
6152 : return NULL_RTX;
6153 :
6154 306 : t_tramp = CALL_EXPR_ARG (exp, 0);
6155 306 : t_func = CALL_EXPR_ARG (exp, 1);
6156 306 : t_chain = CALL_EXPR_ARG (exp, 2);
6157 :
6158 306 : r_tramp = expand_normal (t_tramp);
6159 306 : m_tramp = gen_rtx_MEM (BLKmode, r_tramp);
6160 306 : MEM_NOTRAP_P (m_tramp) = 1;
6161 :
6162 : /* If ONSTACK, the TRAMP argument should be the address of a field
6163 : within the local function's FRAME decl. Either way, let's see if
6164 : we can fill in the MEM_ATTRs for this memory. */
6165 306 : if (TREE_CODE (t_tramp) == ADDR_EXPR)
6166 306 : set_mem_attributes (m_tramp, TREE_OPERAND (t_tramp, 0), true);
6167 :
6168 : /* Creator of a heap trampoline is responsible for making sure the
6169 : address is aligned to at least STACK_BOUNDARY. Normally malloc
6170 : will ensure this anyhow. */
6171 306 : tmp = round_trampoline_addr (r_tramp);
6172 306 : if (tmp != r_tramp)
6173 : {
6174 0 : m_tramp = change_address (m_tramp, BLKmode, tmp);
6175 0 : set_mem_align (m_tramp, TRAMPOLINE_ALIGNMENT);
6176 0 : set_mem_size (m_tramp, TRAMPOLINE_SIZE);
6177 : }
6178 :
6179 : /* The FUNC argument should be the address of the nested function.
6180 : Extract the actual function decl to pass to the hook. */
6181 306 : gcc_assert (TREE_CODE (t_func) == ADDR_EXPR);
6182 306 : t_func = TREE_OPERAND (t_func, 0);
6183 306 : gcc_assert (TREE_CODE (t_func) == FUNCTION_DECL);
6184 :
6185 306 : r_chain = expand_normal (t_chain);
6186 :
6187 : /* Generate insns to initialize the trampoline. */
6188 306 : targetm.calls.trampoline_init (m_tramp, t_func, r_chain);
6189 :
6190 306 : if (onstack)
6191 : {
6192 306 : trampolines_created = 1;
6193 :
6194 306 : if (targetm.calls.custom_function_descriptors != 0)
6195 306 : warning_at (DECL_SOURCE_LOCATION (t_func), OPT_Wtrampolines,
6196 : "trampoline generated for nested function %qD", t_func);
6197 : }
6198 :
6199 306 : return const0_rtx;
6200 : }
6201 :
6202 : static rtx
6203 353 : expand_builtin_adjust_trampoline (tree exp)
6204 : {
6205 353 : rtx tramp;
6206 :
6207 353 : if (!validate_arglist (exp, POINTER_TYPE, VOID_TYPE))
6208 : return NULL_RTX;
6209 :
6210 353 : tramp = expand_normal (CALL_EXPR_ARG (exp, 0));
6211 353 : tramp = round_trampoline_addr (tramp);
6212 353 : if (targetm.calls.trampoline_adjust_address)
6213 0 : tramp = targetm.calls.trampoline_adjust_address (tramp);
6214 :
6215 : return tramp;
6216 : }
6217 :
6218 : /* Expand a call to the builtin descriptor initialization routine.
6219 : A descriptor is made up of a couple of pointers to the static
6220 : chain and the code entry in this order. */
6221 :
6222 : static rtx
6223 0 : expand_builtin_init_descriptor (tree exp)
6224 : {
6225 0 : tree t_descr, t_func, t_chain;
6226 0 : rtx m_descr, r_descr, r_func, r_chain;
6227 :
6228 0 : if (!validate_arglist (exp, POINTER_TYPE, POINTER_TYPE, POINTER_TYPE,
6229 : VOID_TYPE))
6230 : return NULL_RTX;
6231 :
6232 0 : t_descr = CALL_EXPR_ARG (exp, 0);
6233 0 : t_func = CALL_EXPR_ARG (exp, 1);
6234 0 : t_chain = CALL_EXPR_ARG (exp, 2);
6235 :
6236 0 : r_descr = expand_normal (t_descr);
6237 0 : m_descr = gen_rtx_MEM (BLKmode, r_descr);
6238 0 : MEM_NOTRAP_P (m_descr) = 1;
6239 0 : set_mem_align (m_descr, GET_MODE_ALIGNMENT (ptr_mode));
6240 :
6241 0 : r_func = expand_normal (t_func);
6242 0 : r_chain = expand_normal (t_chain);
6243 :
6244 : /* Generate insns to initialize the descriptor. */
6245 0 : emit_move_insn (adjust_address_nv (m_descr, ptr_mode, 0), r_chain);
6246 0 : emit_move_insn (adjust_address_nv (m_descr, ptr_mode,
6247 : POINTER_SIZE / BITS_PER_UNIT), r_func);
6248 :
6249 0 : return const0_rtx;
6250 : }
6251 :
6252 : /* Expand a call to the builtin descriptor adjustment routine. */
6253 :
6254 : static rtx
6255 0 : expand_builtin_adjust_descriptor (tree exp)
6256 : {
6257 0 : rtx tramp;
6258 :
6259 0 : if (!validate_arglist (exp, POINTER_TYPE, VOID_TYPE))
6260 : return NULL_RTX;
6261 :
6262 0 : tramp = expand_normal (CALL_EXPR_ARG (exp, 0));
6263 :
6264 : /* Unalign the descriptor to allow runtime identification. */
6265 0 : tramp = plus_constant (ptr_mode, tramp,
6266 0 : targetm.calls.custom_function_descriptors);
6267 :
6268 0 : return force_operand (tramp, NULL_RTX);
6269 : }
6270 :
6271 : /* Expand the call EXP to the built-in signbit, signbitf or signbitl
6272 : function. The function first checks whether the back end provides
6273 : an insn to implement signbit for the respective mode. If not, it
6274 : checks whether the floating point format of the value is such that
6275 : the sign bit can be extracted. If that is not the case, error out.
6276 : EXP is the expression that is a call to the builtin function; if
6277 : convenient, the result should be placed in TARGET. */
6278 : static rtx
6279 1380 : expand_builtin_signbit (tree exp, rtx target)
6280 : {
6281 1380 : const struct real_format *fmt;
6282 1380 : scalar_float_mode fmode;
6283 1380 : scalar_int_mode rmode, imode;
6284 1380 : tree arg;
6285 1380 : int word, bitpos;
6286 1380 : enum insn_code icode;
6287 1380 : rtx temp;
6288 1380 : location_t loc = EXPR_LOCATION (exp);
6289 :
6290 1380 : if (!validate_arglist (exp, REAL_TYPE, VOID_TYPE))
6291 : return NULL_RTX;
6292 :
6293 1380 : arg = CALL_EXPR_ARG (exp, 0);
6294 1380 : fmode = SCALAR_FLOAT_TYPE_MODE (TREE_TYPE (arg));
6295 1380 : rmode = SCALAR_INT_TYPE_MODE (TREE_TYPE (exp));
6296 1380 : fmt = REAL_MODE_FORMAT (fmode);
6297 :
6298 1380 : arg = builtin_save_expr (arg);
6299 :
6300 : /* Expand the argument yielding a RTX expression. */
6301 1380 : temp = expand_normal (arg);
6302 :
6303 : /* Check if the back end provides an insn that handles signbit for the
6304 : argument's mode. */
6305 1380 : icode = optab_handler (signbit_optab, fmode);
6306 1380 : if (icode != CODE_FOR_nothing)
6307 : {
6308 10 : rtx_insn *last = get_last_insn ();
6309 10 : rtx this_target = gen_reg_rtx (TYPE_MODE (TREE_TYPE (exp)));
6310 10 : if (maybe_emit_unop_insn (icode, this_target, temp, UNKNOWN))
6311 : return this_target;
6312 0 : delete_insns_since (last);
6313 : }
6314 :
6315 : /* For floating point formats without a sign bit, implement signbit
6316 : as "ARG < 0.0". */
6317 1370 : bitpos = fmt->signbit_ro;
6318 1370 : if (bitpos < 0)
6319 : {
6320 : /* But we can't do this if the format supports signed zero. */
6321 0 : gcc_assert (!fmt->has_signed_zero || !HONOR_SIGNED_ZEROS (fmode));
6322 :
6323 0 : arg = fold_build2_loc (loc, LT_EXPR, TREE_TYPE (exp), arg,
6324 0 : build_real (TREE_TYPE (arg), dconst0));
6325 0 : return expand_expr (arg, target, VOIDmode, EXPAND_NORMAL);
6326 : }
6327 :
6328 2744 : if (GET_MODE_SIZE (fmode) <= UNITS_PER_WORD)
6329 : {
6330 1266 : imode = int_mode_for_mode (fmode).require ();
6331 1266 : temp = gen_lowpart (imode, temp);
6332 : }
6333 : else
6334 : {
6335 104 : imode = word_mode;
6336 : /* Handle targets with different FP word orders. */
6337 104 : if (FLOAT_WORDS_BIG_ENDIAN)
6338 : word = (GET_MODE_BITSIZE (fmode) - bitpos) / BITS_PER_WORD;
6339 : else
6340 104 : word = bitpos / BITS_PER_WORD;
6341 104 : temp = operand_subword_force (temp, word, fmode);
6342 104 : bitpos = bitpos % BITS_PER_WORD;
6343 : }
6344 :
6345 : /* Force the intermediate word_mode (or narrower) result into a
6346 : register. This avoids attempting to create paradoxical SUBREGs
6347 : of floating point modes below. */
6348 1370 : temp = force_reg (imode, temp);
6349 :
6350 : /* If the bitpos is within the "result mode" lowpart, the operation
6351 : can be implement with a single bitwise AND. Otherwise, we need
6352 : a right shift and an AND. */
6353 :
6354 2740 : if (bitpos < GET_MODE_BITSIZE (rmode))
6355 : {
6356 1162 : wide_int mask = wi::set_bit_in_zero (bitpos, GET_MODE_PRECISION (rmode));
6357 :
6358 3486 : if (GET_MODE_SIZE (imode) > GET_MODE_SIZE (rmode))
6359 0 : temp = gen_lowpart (rmode, temp);
6360 2324 : temp = expand_binop (rmode, and_optab, temp,
6361 2324 : immed_wide_int_const (mask, rmode),
6362 : NULL_RTX, 1, OPTAB_LIB_WIDEN);
6363 1162 : }
6364 : else
6365 : {
6366 : /* Perform a logical right shift to place the signbit in the least
6367 : significant bit, then truncate the result to the desired mode
6368 : and mask just this bit. */
6369 208 : temp = expand_shift (RSHIFT_EXPR, imode, temp, bitpos, NULL_RTX, 1);
6370 208 : temp = gen_lowpart (rmode, temp);
6371 208 : temp = expand_binop (rmode, and_optab, temp, const1_rtx,
6372 : NULL_RTX, 1, OPTAB_LIB_WIDEN);
6373 : }
6374 :
6375 : return temp;
6376 : }
6377 :
6378 : /* Expand fork or exec calls. TARGET is the desired target of the
6379 : call. EXP is the call. FN is the
6380 : identificator of the actual function. IGNORE is nonzero if the
6381 : value is to be ignored. */
6382 :
6383 : static rtx
6384 109 : expand_builtin_fork_or_exec (tree fn, tree exp, rtx target, int ignore)
6385 : {
6386 109 : tree id, decl;
6387 109 : tree call;
6388 :
6389 : /* If we are not profiling, just call the function. */
6390 109 : if (!coverage_instrumentation_p ())
6391 : return NULL_RTX;
6392 :
6393 : /* Otherwise call the wrapper. This should be equivalent for the rest of
6394 : compiler, so the code does not diverge, and the wrapper may run the
6395 : code necessary for keeping the profiling sane. */
6396 :
6397 4 : switch (DECL_FUNCTION_CODE (fn))
6398 : {
6399 4 : case BUILT_IN_FORK:
6400 4 : id = get_identifier ("__gcov_fork");
6401 4 : break;
6402 :
6403 0 : case BUILT_IN_EXECL:
6404 0 : id = get_identifier ("__gcov_execl");
6405 0 : break;
6406 :
6407 0 : case BUILT_IN_EXECV:
6408 0 : id = get_identifier ("__gcov_execv");
6409 0 : break;
6410 :
6411 0 : case BUILT_IN_EXECLP:
6412 0 : id = get_identifier ("__gcov_execlp");
6413 0 : break;
6414 :
6415 0 : case BUILT_IN_EXECLE:
6416 0 : id = get_identifier ("__gcov_execle");
6417 0 : break;
6418 :
6419 0 : case BUILT_IN_EXECVP:
6420 0 : id = get_identifier ("__gcov_execvp");
6421 0 : break;
6422 :
6423 0 : case BUILT_IN_EXECVE:
6424 0 : id = get_identifier ("__gcov_execve");
6425 0 : break;
6426 :
6427 0 : default:
6428 0 : gcc_unreachable ();
6429 : }
6430 :
6431 4 : decl = build_decl (DECL_SOURCE_LOCATION (fn),
6432 4 : FUNCTION_DECL, id, TREE_TYPE (fn));
6433 4 : DECL_EXTERNAL (decl) = 1;
6434 4 : TREE_PUBLIC (decl) = 1;
6435 4 : DECL_ARTIFICIAL (decl) = 1;
6436 4 : TREE_NOTHROW (decl) = 1;
6437 4 : DECL_VISIBILITY (decl) = VISIBILITY_DEFAULT;
6438 4 : DECL_VISIBILITY_SPECIFIED (decl) = 1;
6439 4 : call = rewrite_call_expr (EXPR_LOCATION (exp), exp, 0, decl, 0);
6440 4 : return expand_call (call, target, ignore);
6441 : }
6442 :
6443 :
6444 :
6445 : /* Reconstitute a mode for a __sync intrinsic operation. Since the type of
6446 : the pointer in these functions is void*, the tree optimizers may remove
6447 : casts. The mode computed in expand_builtin isn't reliable either, due
6448 : to __sync_bool_compare_and_swap.
6449 :
6450 : FCODE_DIFF should be fcode - base, where base is the FOO_1 code for the
6451 : group of builtins. This gives us log2 of the mode size. */
6452 :
6453 : static inline machine_mode
6454 134548 : get_builtin_sync_mode (int fcode_diff)
6455 : {
6456 : /* The size is not negotiable, so ask not to get BLKmode in return
6457 : if the target indicates that a smaller size would be better. */
6458 134548 : return int_mode_for_size (BITS_PER_UNIT << fcode_diff, 0).require ();
6459 : }
6460 :
6461 : /* Expand the memory expression LOC and return the appropriate memory operand
6462 : for the builtin_sync operations. */
6463 :
6464 : static rtx
6465 151188 : get_builtin_sync_mem (tree loc, machine_mode mode)
6466 : {
6467 151188 : rtx addr, mem;
6468 151188 : int addr_space = TYPE_ADDR_SPACE (POINTER_TYPE_P (TREE_TYPE (loc))
6469 : ? TREE_TYPE (TREE_TYPE (loc))
6470 : : TREE_TYPE (loc));
6471 151188 : scalar_int_mode addr_mode = targetm.addr_space.address_mode (addr_space);
6472 :
6473 151188 : addr = expand_expr (loc, NULL_RTX, addr_mode, EXPAND_SUM);
6474 151188 : addr = convert_memory_address (addr_mode, addr);
6475 :
6476 : /* Note that we explicitly do not want any alias information for this
6477 : memory, so that we kill all other live memories. Otherwise we don't
6478 : satisfy the full barrier semantics of the intrinsic. */
6479 151188 : mem = gen_rtx_MEM (mode, addr);
6480 :
6481 151188 : set_mem_addr_space (mem, addr_space);
6482 :
6483 151188 : mem = validize_mem (mem);
6484 :
6485 : /* The alignment needs to be at least according to that of the mode. */
6486 151188 : set_mem_align (mem, MAX (GET_MODE_ALIGNMENT (mode),
6487 : get_pointer_alignment (loc)));
6488 151188 : set_mem_alias_set (mem, ALIAS_SET_MEMORY_BARRIER);
6489 151188 : MEM_VOLATILE_P (mem) = 1;
6490 :
6491 151188 : return mem;
6492 : }
6493 :
6494 : /* Make sure an argument is in the right mode.
6495 : EXP is the tree argument.
6496 : MODE is the mode it should be in. */
6497 :
6498 : static rtx
6499 94213 : expand_expr_force_mode (tree exp, machine_mode mode)
6500 : {
6501 94213 : rtx val;
6502 94213 : machine_mode old_mode;
6503 :
6504 94213 : if (TREE_CODE (exp) == SSA_NAME
6505 94213 : && TYPE_MODE (TREE_TYPE (exp)) != mode)
6506 : {
6507 : /* Undo argument promotion if possible, as combine might not
6508 : be able to do it later due to MEM_VOLATILE_P uses in the
6509 : patterns. */
6510 25 : gimple *g = get_gimple_for_ssa_name (exp);
6511 25 : if (g && gimple_assign_cast_p (g))
6512 : {
6513 0 : tree rhs = gimple_assign_rhs1 (g);
6514 0 : tree_code code = gimple_assign_rhs_code (g);
6515 0 : if (CONVERT_EXPR_CODE_P (code)
6516 0 : && TYPE_MODE (TREE_TYPE (rhs)) == mode
6517 0 : && INTEGRAL_TYPE_P (TREE_TYPE (exp))
6518 0 : && INTEGRAL_TYPE_P (TREE_TYPE (rhs))
6519 0 : && (TYPE_PRECISION (TREE_TYPE (exp))
6520 0 : > TYPE_PRECISION (TREE_TYPE (rhs))))
6521 : exp = rhs;
6522 : }
6523 : }
6524 :
6525 94213 : val = expand_expr (exp, NULL_RTX, mode, EXPAND_NORMAL);
6526 : /* If VAL is promoted to a wider mode, convert it back to MODE. Take care
6527 : of CONST_INTs, where we know the old_mode only from the call argument. */
6528 :
6529 94213 : old_mode = GET_MODE (val);
6530 94213 : if (old_mode == VOIDmode)
6531 44280 : old_mode = TYPE_MODE (TREE_TYPE (exp));
6532 94213 : val = convert_modes (mode, old_mode, val, 1);
6533 94213 : return val;
6534 : }
6535 :
6536 :
6537 : /* Expand the __sync_xxx_and_fetch and __sync_fetch_and_xxx intrinsics.
6538 : EXP is the CALL_EXPR. CODE is the rtx code
6539 : that corresponds to the arithmetic or logical operation from the name;
6540 : an exception here is that NOT actually means NAND. TARGET is an optional
6541 : place for us to store the results; AFTER is true if this is the
6542 : fetch_and_xxx form. */
6543 :
6544 : static rtx
6545 4028 : expand_builtin_sync_operation (machine_mode mode, tree exp,
6546 : enum rtx_code code, bool after,
6547 : rtx target)
6548 : {
6549 4028 : rtx val, mem;
6550 4028 : location_t loc = EXPR_LOCATION (exp);
6551 :
6552 4028 : if (code == NOT && warn_sync_nand)
6553 : {
6554 523 : tree fndecl = get_callee_fndecl (exp);
6555 523 : enum built_in_function fcode = DECL_FUNCTION_CODE (fndecl);
6556 :
6557 523 : static bool warned_f_a_n, warned_n_a_f;
6558 :
6559 523 : switch (fcode)
6560 : {
6561 434 : case BUILT_IN_SYNC_FETCH_AND_NAND_1:
6562 434 : case BUILT_IN_SYNC_FETCH_AND_NAND_2:
6563 434 : case BUILT_IN_SYNC_FETCH_AND_NAND_4:
6564 434 : case BUILT_IN_SYNC_FETCH_AND_NAND_8:
6565 434 : case BUILT_IN_SYNC_FETCH_AND_NAND_16:
6566 434 : if (warned_f_a_n)
6567 : break;
6568 :
6569 30 : fndecl = builtin_decl_implicit (BUILT_IN_SYNC_FETCH_AND_NAND_N);
6570 30 : inform (loc, "%qD changed semantics in GCC 4.4", fndecl);
6571 30 : warned_f_a_n = true;
6572 30 : break;
6573 :
6574 89 : case BUILT_IN_SYNC_NAND_AND_FETCH_1:
6575 89 : case BUILT_IN_SYNC_NAND_AND_FETCH_2:
6576 89 : case BUILT_IN_SYNC_NAND_AND_FETCH_4:
6577 89 : case BUILT_IN_SYNC_NAND_AND_FETCH_8:
6578 89 : case BUILT_IN_SYNC_NAND_AND_FETCH_16:
6579 89 : if (warned_n_a_f)
6580 : break;
6581 :
6582 22 : fndecl = builtin_decl_implicit (BUILT_IN_SYNC_NAND_AND_FETCH_N);
6583 22 : inform (loc, "%qD changed semantics in GCC 4.4", fndecl);
6584 22 : warned_n_a_f = true;
6585 22 : break;
6586 :
6587 0 : default:
6588 0 : gcc_unreachable ();
6589 : }
6590 : }
6591 :
6592 : /* Expand the operands. */
6593 4028 : mem = get_builtin_sync_mem (CALL_EXPR_ARG (exp, 0), mode);
6594 4028 : val = expand_expr_force_mode (CALL_EXPR_ARG (exp, 1), mode);
6595 :
6596 4028 : return expand_atomic_fetch_op (target, mem, val, code, MEMMODEL_SYNC_SEQ_CST,
6597 4028 : after);
6598 : }
6599 :
6600 : /* Expand the __sync_val_compare_and_swap and __sync_bool_compare_and_swap
6601 : intrinsics. EXP is the CALL_EXPR. IS_BOOL is
6602 : true if this is the boolean form. TARGET is a place for us to store the
6603 : results; this is NOT optional if IS_BOOL is true. */
6604 :
6605 : static rtx
6606 460 : expand_builtin_compare_and_swap (machine_mode mode, tree exp,
6607 : bool is_bool, rtx target)
6608 : {
6609 460 : rtx old_val, new_val, mem;
6610 460 : rtx *pbool, *poval;
6611 :
6612 : /* Expand the operands. */
6613 460 : mem = get_builtin_sync_mem (CALL_EXPR_ARG (exp, 0), mode);
6614 460 : old_val = expand_expr_force_mode (CALL_EXPR_ARG (exp, 1), mode);
6615 460 : new_val = expand_expr_force_mode (CALL_EXPR_ARG (exp, 2), mode);
6616 :
6617 460 : pbool = poval = NULL;
6618 460 : if (target != const0_rtx)
6619 : {
6620 434 : if (is_bool)
6621 : pbool = ⌖
6622 : else
6623 230 : poval = ⌖
6624 : }
6625 460 : if (!expand_atomic_compare_and_swap (pbool, poval, mem, old_val, new_val,
6626 : false, MEMMODEL_SYNC_SEQ_CST,
6627 : MEMMODEL_SYNC_SEQ_CST))
6628 : return NULL_RTX;
6629 :
6630 458 : return target;
6631 : }
6632 :
6633 : /* Expand the __sync_lock_test_and_set intrinsic. Note that the most
6634 : general form is actually an atomic exchange, and some targets only
6635 : support a reduced form with the second argument being a constant 1.
6636 : EXP is the CALL_EXPR; TARGET is an optional place for us to store
6637 : the results. */
6638 :
6639 : static rtx
6640 326 : expand_builtin_sync_lock_test_and_set (machine_mode mode, tree exp,
6641 : rtx target)
6642 : {
6643 326 : rtx val, mem;
6644 :
6645 : /* Expand the operands. */
6646 326 : mem = get_builtin_sync_mem (CALL_EXPR_ARG (exp, 0), mode);
6647 326 : val = expand_expr_force_mode (CALL_EXPR_ARG (exp, 1), mode);
6648 :
6649 326 : return expand_sync_lock_test_and_set (target, mem, val);
6650 : }
6651 :
6652 : /* Expand the __sync_lock_release intrinsic. EXP is the CALL_EXPR. */
6653 :
6654 : static rtx
6655 146 : expand_builtin_sync_lock_release (machine_mode mode, tree exp)
6656 : {
6657 146 : rtx mem;
6658 :
6659 : /* Expand the operands. */
6660 146 : mem = get_builtin_sync_mem (CALL_EXPR_ARG (exp, 0), mode);
6661 :
6662 146 : return expand_atomic_store (mem, const0_rtx, MEMMODEL_SYNC_RELEASE, true);
6663 : }
6664 :
6665 : /* Given an integer representing an ``enum memmodel'', verify its
6666 : correctness and return the memory model enum. */
6667 :
6668 : static enum memmodel
6669 169708 : get_memmodel (tree exp)
6670 : {
6671 : /* If the parameter is not a constant, it's a run time value so we'll just
6672 : convert it to MEMMODEL_SEQ_CST to avoid annoying runtime checking. */
6673 169708 : if (TREE_CODE (exp) != INTEGER_CST)
6674 : return MEMMODEL_SEQ_CST;
6675 :
6676 168881 : rtx op = expand_normal (exp);
6677 :
6678 168881 : unsigned HOST_WIDE_INT val = INTVAL (op);
6679 168881 : if (targetm.memmodel_check)
6680 168881 : val = targetm.memmodel_check (val);
6681 0 : else if (val & ~MEMMODEL_MASK)
6682 : return MEMMODEL_SEQ_CST;
6683 :
6684 : /* Should never see a user explicit SYNC memodel model, so >= LAST works. */
6685 168881 : if (memmodel_base (val) >= MEMMODEL_LAST)
6686 : return MEMMODEL_SEQ_CST;
6687 :
6688 : /* Workaround for Bugzilla 59448. GCC doesn't track consume properly, so
6689 : be conservative and promote consume to acquire. */
6690 168878 : if (val == MEMMODEL_CONSUME)
6691 755 : val = MEMMODEL_ACQUIRE;
6692 :
6693 168878 : return (enum memmodel) val;
6694 : }
6695 :
6696 : /* Expand the __atomic_exchange intrinsic:
6697 : TYPE __atomic_exchange (TYPE *object, TYPE desired, enum memmodel)
6698 : EXP is the CALL_EXPR.
6699 : TARGET is an optional place for us to store the results. */
6700 :
6701 : static rtx
6702 2937 : expand_builtin_atomic_exchange (machine_mode mode, tree exp, rtx target)
6703 : {
6704 2937 : rtx val, mem;
6705 2937 : enum memmodel model;
6706 :
6707 2937 : model = get_memmodel (CALL_EXPR_ARG (exp, 2));
6708 :
6709 2937 : if (!flag_inline_atomics)
6710 : return NULL_RTX;
6711 :
6712 : /* Expand the operands. */
6713 2886 : mem = get_builtin_sync_mem (CALL_EXPR_ARG (exp, 0), mode);
6714 2886 : val = expand_expr_force_mode (CALL_EXPR_ARG (exp, 1), mode);
6715 :
6716 2886 : return expand_atomic_exchange (target, mem, val, model);
6717 : }
6718 :
6719 : /* Expand the __atomic_compare_exchange intrinsic:
6720 : bool __atomic_compare_exchange (TYPE *object, TYPE *expect,
6721 : TYPE desired, BOOL weak,
6722 : enum memmodel success,
6723 : enum memmodel failure)
6724 : EXP is the CALL_EXPR.
6725 : TARGET is an optional place for us to store the results. */
6726 :
6727 : static rtx
6728 9131 : expand_builtin_atomic_compare_exchange (machine_mode mode, tree exp,
6729 : rtx target)
6730 : {
6731 9131 : rtx expect, desired, mem, oldval;
6732 9131 : rtx_code_label *label;
6733 9131 : tree weak;
6734 9131 : bool is_weak;
6735 :
6736 9131 : memmodel success = get_memmodel (CALL_EXPR_ARG (exp, 4));
6737 9131 : memmodel failure = get_memmodel (CALL_EXPR_ARG (exp, 5));
6738 :
6739 9131 : if (failure > success)
6740 22 : success = MEMMODEL_SEQ_CST;
6741 :
6742 9131 : if (is_mm_release (failure) || is_mm_acq_rel (failure))
6743 : {
6744 : failure = MEMMODEL_SEQ_CST;
6745 : success = MEMMODEL_SEQ_CST;
6746 : }
6747 :
6748 :
6749 9131 : if (!flag_inline_atomics)
6750 : return NULL_RTX;
6751 :
6752 : /* Expand the operands. */
6753 9080 : mem = get_builtin_sync_mem (CALL_EXPR_ARG (exp, 0), mode);
6754 :
6755 9080 : expect = expand_normal (CALL_EXPR_ARG (exp, 1));
6756 9116 : expect = convert_memory_address (Pmode, expect);
6757 9080 : expect = gen_rtx_MEM (mode, expect);
6758 9080 : desired = expand_expr_force_mode (CALL_EXPR_ARG (exp, 2), mode);
6759 :
6760 9080 : weak = CALL_EXPR_ARG (exp, 3);
6761 9080 : is_weak = false;
6762 9080 : if (tree_fits_shwi_p (weak) && tree_to_shwi (weak) != 0)
6763 9080 : is_weak = true;
6764 :
6765 9080 : if (target == const0_rtx)
6766 289 : target = NULL;
6767 :
6768 : /* Lest the rtl backend create a race condition with an imporoper store
6769 : to memory, always create a new pseudo for OLDVAL. */
6770 9080 : oldval = NULL;
6771 :
6772 9080 : if (!expand_atomic_compare_and_swap (&target, &oldval, mem, expect, desired,
6773 : is_weak, success, failure))
6774 : return NULL_RTX;
6775 :
6776 : /* Conditionally store back to EXPECT, lest we create a race condition
6777 : with an improper store to memory. */
6778 : /* ??? With a rearrangement of atomics at the gimple level, we can handle
6779 : the normal case where EXPECT is totally private, i.e. a register. At
6780 : which point the store can be unconditional. */
6781 7331 : label = gen_label_rtx ();
6782 7331 : emit_cmp_and_jump_insns (target, const0_rtx, NE, NULL,
6783 7331 : GET_MODE (target), 1, label);
6784 7331 : emit_move_insn (expect, oldval);
6785 7331 : emit_label (label);
6786 :
6787 7331 : return target;
6788 : }
6789 :
6790 : /* Helper function for expand_ifn_atomic_compare_exchange - expand
6791 : internal ATOMIC_COMPARE_EXCHANGE call into __atomic_compare_exchange_N
6792 : call. The weak parameter must be dropped to match the expected parameter
6793 : list and the expected argument changed from value to pointer to memory
6794 : slot. */
6795 :
6796 : static void
6797 0 : expand_ifn_atomic_compare_exchange_into_call (gcall *call, machine_mode mode)
6798 : {
6799 0 : unsigned int z;
6800 0 : vec<tree, va_gc> *vec;
6801 :
6802 0 : vec_alloc (vec, 5);
6803 0 : vec->quick_push (gimple_call_arg (call, 0));
6804 0 : tree expected = gimple_call_arg (call, 1);
6805 0 : rtx x = assign_stack_temp_for_type (mode, GET_MODE_SIZE (mode),
6806 0 : TREE_TYPE (expected));
6807 0 : rtx expd = expand_expr (expected, x, mode, EXPAND_NORMAL);
6808 0 : if (expd != x)
6809 0 : emit_move_insn (x, expd);
6810 0 : tree v = make_tree (TREE_TYPE (expected), x);
6811 0 : vec->quick_push (build1 (ADDR_EXPR,
6812 0 : build_pointer_type (TREE_TYPE (expected)), v));
6813 0 : vec->quick_push (gimple_call_arg (call, 2));
6814 : /* Skip the boolean weak parameter. */
6815 0 : for (z = 4; z < 6; z++)
6816 0 : vec->quick_push (gimple_call_arg (call, z));
6817 : /* At present we only have BUILT_IN_ATOMIC_COMPARE_EXCHANGE_{1,2,4,8,16}. */
6818 0 : unsigned int bytes_log2 = exact_log2 (GET_MODE_SIZE (mode).to_constant ());
6819 0 : gcc_assert (bytes_log2 < 5);
6820 0 : built_in_function fncode
6821 : = (built_in_function) ((int) BUILT_IN_ATOMIC_COMPARE_EXCHANGE_1
6822 : + bytes_log2);
6823 0 : tree fndecl = builtin_decl_explicit (fncode);
6824 0 : tree fn = build1 (ADDR_EXPR, build_pointer_type (TREE_TYPE (fndecl)),
6825 : fndecl);
6826 0 : tree exp = build_call_vec (boolean_type_node, fn, vec);
6827 0 : tree lhs = gimple_call_lhs (call);
6828 0 : rtx boolret = expand_call (exp, NULL_RTX, lhs == NULL_TREE);
6829 0 : if (lhs)
6830 : {
6831 0 : rtx target = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
6832 0 : if (GET_MODE (boolret) != mode)
6833 0 : boolret = convert_modes (mode, GET_MODE (boolret), boolret, 1);
6834 0 : x = force_reg (mode, x);
6835 0 : write_complex_part (target, boolret, true, true);
6836 0 : write_complex_part (target, x, false, false);
6837 : }
6838 0 : }
6839 :
6840 : /* Expand IFN_ATOMIC_COMPARE_EXCHANGE internal function. */
6841 :
6842 : void
6843 13951 : expand_ifn_atomic_compare_exchange (gcall *call)
6844 : {
6845 13951 : int size = tree_to_shwi (gimple_call_arg (call, 3)) & 255;
6846 13951 : gcc_assert (size == 1 || size == 2 || size == 4 || size == 8 || size == 16);
6847 13951 : machine_mode mode = int_mode_for_size (BITS_PER_UNIT * size, 0).require ();
6848 :
6849 13951 : memmodel success = get_memmodel (gimple_call_arg (call, 4));
6850 13951 : memmodel failure = get_memmodel (gimple_call_arg (call, 5));
6851 :
6852 13951 : if (failure > success)
6853 0 : success = MEMMODEL_SEQ_CST;
6854 :
6855 13951 : if (is_mm_release (failure) || is_mm_acq_rel (failure))
6856 : {
6857 : failure = MEMMODEL_SEQ_CST;
6858 : success = MEMMODEL_SEQ_CST;
6859 : }
6860 :
6861 13951 : if (!flag_inline_atomics)
6862 : {
6863 0 : expand_ifn_atomic_compare_exchange_into_call (call, mode);
6864 0 : return;
6865 : }
6866 :
6867 : /* Expand the operands. */
6868 13951 : rtx mem = get_builtin_sync_mem (gimple_call_arg (call, 0), mode);
6869 :
6870 13951 : rtx expect = expand_expr_force_mode (gimple_call_arg (call, 1), mode);
6871 13951 : rtx desired = expand_expr_force_mode (gimple_call_arg (call, 2), mode);
6872 :
6873 13951 : bool is_weak = (tree_to_shwi (gimple_call_arg (call, 3)) & 256) != 0;
6874 :
6875 13951 : rtx boolret = NULL;
6876 13951 : rtx oldval = NULL;
6877 :
6878 13951 : if (!expand_atomic_compare_and_swap (&boolret, &oldval, mem, expect, desired,
6879 : is_weak, success, failure))
6880 : {
6881 0 : expand_ifn_atomic_compare_exchange_into_call (call, mode);
6882 0 : return;
6883 : }
6884 :
6885 13951 : tree lhs = gimple_call_lhs (call);
6886 13951 : if (lhs)
6887 : {
6888 13742 : rtx target = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
6889 13742 : if (GET_MODE (boolret) != mode)
6890 12294 : boolret = convert_modes (mode, GET_MODE (boolret), boolret, 1);
6891 13742 : write_complex_part (target, boolret, true, true);
6892 13742 : write_complex_part (target, oldval, false, false);
6893 : }
6894 : }
6895 :
6896 : /* Expand the __atomic_load intrinsic:
6897 : TYPE __atomic_load (TYPE *object, enum memmodel)
6898 : EXP is the CALL_EXPR.
6899 : TARGET is an optional place for us to store the results. */
6900 :
6901 : static rtx
6902 70962 : expand_builtin_atomic_load (machine_mode mode, tree exp, rtx target)
6903 : {
6904 70962 : memmodel model = get_memmodel (CALL_EXPR_ARG (exp, 1));
6905 70962 : if (is_mm_release (model) || is_mm_acq_rel (model))
6906 : model = MEMMODEL_SEQ_CST;
6907 :
6908 70962 : if (!flag_inline_atomics)
6909 : return NULL_RTX;
6910 :
6911 : /* Expand the operand. */
6912 70921 : rtx mem = get_builtin_sync_mem (CALL_EXPR_ARG (exp, 0), mode);
6913 :
6914 70921 : return expand_atomic_load (target, mem, model);
6915 : }
6916 :
6917 :
6918 : /* Expand the __atomic_store intrinsic:
6919 : void __atomic_store (TYPE *object, TYPE desired, enum memmodel)
6920 : EXP is the CALL_EXPR.
6921 : TARGET is an optional place for us to store the results. */
6922 :
6923 : static rtx
6924 17481 : expand_builtin_atomic_store (machine_mode mode, tree exp)
6925 : {
6926 17481 : memmodel model = get_memmodel (CALL_EXPR_ARG (exp, 2));
6927 17481 : if (!(is_mm_relaxed (model) || is_mm_seq_cst (model)
6928 1599 : || is_mm_release (model)))
6929 : model = MEMMODEL_SEQ_CST;
6930 :
6931 17481 : if (!flag_inline_atomics)
6932 : return NULL_RTX;
6933 :
6934 : /* Expand the operands. */
6935 17450 : rtx mem = get_builtin_sync_mem (CALL_EXPR_ARG (exp, 0), mode);
6936 17450 : rtx val = expand_expr_force_mode (CALL_EXPR_ARG (exp, 1), mode);
6937 :
6938 17450 : return expand_atomic_store (mem, val, model, false);
6939 : }
6940 :
6941 : /* Expand the __atomic_fetch_XXX intrinsic:
6942 : TYPE __atomic_fetch_XXX (TYPE *object, TYPE val, enum memmodel)
6943 : EXP is the CALL_EXPR.
6944 : TARGET is an optional place for us to store the results.
6945 : CODE is the operation, PLUS, MINUS, ADD, XOR, or IOR.
6946 : FETCH_AFTER is true if returning the result of the operation.
6947 : FETCH_AFTER is false if returning the value before the operation.
6948 : IGNORE is true if the result is not used.
6949 : EXT_CALL is the correct builtin for an external call if this cannot be
6950 : resolved to an instruction sequence. */
6951 :
6952 : static rtx
6953 29046 : expand_builtin_atomic_fetch_op (machine_mode mode, tree exp, rtx target,
6954 : enum rtx_code code, bool fetch_after,
6955 : bool ignore, enum built_in_function ext_call)
6956 : {
6957 29046 : rtx val, mem, ret;
6958 29046 : enum memmodel model;
6959 29046 : tree fndecl, addr, oldval;
6960 :
6961 29046 : model = get_memmodel (CALL_EXPR_ARG (exp, 2));
6962 :
6963 : /* Expand the operands. */
6964 29046 : mem = get_builtin_sync_mem (CALL_EXPR_ARG (exp, 0), mode);
6965 29046 : val = expand_expr_force_mode (CALL_EXPR_ARG (exp, 1), mode);
6966 :
6967 : /* Only try generating instructions if inlining is turned on. */
6968 29046 : if (flag_inline_atomics)
6969 : {
6970 28503 : ret = expand_atomic_fetch_op (target, mem, val, code, model, fetch_after);
6971 28503 : if (ret)
6972 : return ret;
6973 : }
6974 :
6975 : /* Return if a different routine isn't needed for the library call. */
6976 1159 : if (ext_call == BUILT_IN_NONE)
6977 : return NULL_RTX;
6978 :
6979 : /* Change the call to the specified function. */
6980 288 : fndecl = get_callee_fndecl (exp);
6981 288 : addr = CALL_EXPR_FN (exp);
6982 288 : STRIP_NOPS (addr);
6983 :
6984 288 : gcc_assert (TREE_OPERAND (addr, 0) == fndecl);
6985 288 : TREE_OPERAND (addr, 0) = builtin_decl_explicit (ext_call);
6986 288 : oldval = CALL_EXPR_ARG (exp, 1);
6987 :
6988 288 : if (!ignore && reg_overlap_mentioned_p (mem, val))
6989 : {
6990 1 : val = force_reg (mode, val);
6991 1 : CALL_EXPR_ARG (exp, 1) = make_tree (TREE_TYPE (oldval), val);
6992 : }
6993 :
6994 : /* If we will emit code after the call, the call cannot be a tail call.
6995 : If it is emitted as a tail call, a barrier is emitted after it, and
6996 : then all trailing code is removed. */
6997 288 : if (!ignore)
6998 191 : CALL_EXPR_TAILCALL (exp) = 0;
6999 :
7000 : /* Expand the call here so we can emit trailing code. */
7001 288 : ret = expand_call (exp, target, ignore);
7002 :
7003 : /* Replace the original function just in case it matters. */
7004 288 : TREE_OPERAND (addr, 0) = fndecl;
7005 :
7006 : /* Then issue the arithmetic correction to return the right result. */
7007 288 : if (!ignore)
7008 : {
7009 191 : CALL_EXPR_ARG (exp, 1) = oldval;
7010 191 : if (code == NOT)
7011 : {
7012 33 : ret = expand_simple_binop (mode, AND, ret, val, NULL_RTX, true,
7013 : OPTAB_LIB_WIDEN);
7014 33 : ret = expand_simple_unop (mode, NOT, ret, target, true);
7015 : }
7016 : else
7017 158 : ret = expand_simple_binop (mode, code, ret, val, target, true,
7018 : OPTAB_LIB_WIDEN);
7019 : }
7020 : return ret;
7021 : }
7022 :
7023 : /* Expand IFN_ATOMIC_BIT_TEST_AND_* internal function. */
7024 :
7025 : void
7026 427 : expand_ifn_atomic_bit_test_and (gcall *call)
7027 : {
7028 427 : tree ptr = gimple_call_arg (call, 0);
7029 427 : tree bit = gimple_call_arg (call, 1);
7030 427 : tree flag = gimple_call_arg (call, 2);
7031 427 : tree lhs = gimple_call_lhs (call);
7032 427 : enum memmodel model = MEMMODEL_SYNC_SEQ_CST;
7033 427 : machine_mode mode = TYPE_MODE (TREE_TYPE (flag));
7034 427 : enum rtx_code code;
7035 427 : optab optab;
7036 427 : class expand_operand ops[5];
7037 :
7038 427 : gcc_assert (flag_inline_atomics);
7039 :
7040 427 : if (gimple_call_num_args (call) == 5)
7041 296 : model = get_memmodel (gimple_call_arg (call, 3));
7042 :
7043 427 : rtx mem = get_builtin_sync_mem (ptr, mode);
7044 427 : rtx val = expand_expr_force_mode (bit, mode);
7045 :
7046 427 : switch (gimple_call_internal_fn (call))
7047 : {
7048 : case IFN_ATOMIC_BIT_TEST_AND_SET:
7049 : code = IOR;
7050 : optab = atomic_bit_test_and_set_optab;
7051 : break;
7052 : case IFN_ATOMIC_BIT_TEST_AND_COMPLEMENT:
7053 : code = XOR;
7054 : optab = atomic_bit_test_and_complement_optab;
7055 : break;
7056 : case IFN_ATOMIC_BIT_TEST_AND_RESET:
7057 : code = AND;
7058 : optab = atomic_bit_test_and_reset_optab;
7059 : break;
7060 0 : default:
7061 0 : gcc_unreachable ();
7062 : }
7063 :
7064 427 : if (lhs == NULL_TREE)
7065 : {
7066 0 : rtx val2 = expand_simple_binop (mode, ASHIFT, const1_rtx,
7067 : val, NULL_RTX, true, OPTAB_DIRECT);
7068 0 : if (code == AND)
7069 0 : val2 = expand_simple_unop (mode, NOT, val2, NULL_RTX, true);
7070 0 : if (expand_atomic_fetch_op (const0_rtx, mem, val2, code, model, false))
7071 427 : return;
7072 : }
7073 :
7074 0 : rtx target;
7075 0 : if (lhs)
7076 427 : target = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
7077 : else
7078 0 : target = gen_reg_rtx (mode);
7079 427 : enum insn_code icode = direct_optab_handler (optab, mode);
7080 427 : gcc_assert (icode != CODE_FOR_nothing);
7081 427 : create_output_operand (&ops[0], target, mode);
7082 427 : create_fixed_operand (&ops[1], mem);
7083 427 : create_convert_operand_to (&ops[2], val, mode, true);
7084 427 : create_integer_operand (&ops[3], model);
7085 427 : create_integer_operand (&ops[4], integer_onep (flag));
7086 427 : if (maybe_expand_insn (icode, 5, ops))
7087 : return;
7088 :
7089 0 : if (reg_overlap_mentioned_p (mem, val))
7090 0 : val = force_reg (mode, val);
7091 :
7092 0 : rtx bitval = val;
7093 0 : val = expand_simple_binop (mode, ASHIFT, const1_rtx,
7094 : val, NULL_RTX, true, OPTAB_DIRECT);
7095 0 : rtx maskval = val;
7096 0 : if (code == AND)
7097 0 : val = expand_simple_unop (mode, NOT, val, NULL_RTX, true);
7098 0 : rtx result = expand_atomic_fetch_op (gen_reg_rtx (mode), mem, val,
7099 : code, model, false);
7100 0 : if (!result)
7101 : {
7102 0 : bool is_atomic = gimple_call_num_args (call) == 5;
7103 0 : tree tcall = gimple_call_arg (call, 3 + is_atomic);
7104 0 : tree fndecl = gimple_call_addr_fndecl (tcall);
7105 0 : tree type = TREE_TYPE (TREE_TYPE (fndecl));
7106 0 : tree exp;
7107 0 : if (is_atomic)
7108 0 : exp = build_call_nary (type, tcall, 3,
7109 : ptr, make_tree (type, val),
7110 : gimple_call_arg (call, 3));
7111 : else
7112 0 : exp = build_call_nary (type, tcall, 2, ptr, make_tree (type, val));
7113 0 : result = expand_builtin (exp, gen_reg_rtx (mode), NULL_RTX,
7114 : mode, !lhs);
7115 : }
7116 0 : if (!lhs)
7117 : return;
7118 0 : if (integer_onep (flag))
7119 : {
7120 0 : result = expand_simple_binop (mode, ASHIFTRT, result, bitval,
7121 : NULL_RTX, true, OPTAB_DIRECT);
7122 0 : result = expand_simple_binop (mode, AND, result, const1_rtx, target,
7123 : true, OPTAB_DIRECT);
7124 : }
7125 : else
7126 0 : result = expand_simple_binop (mode, AND, result, maskval, target, true,
7127 : OPTAB_DIRECT);
7128 0 : if (result != target)
7129 0 : emit_move_insn (target, result);
7130 : }
7131 :
7132 : /* Expand IFN_ATOMIC_*_FETCH_CMP_0 internal function. */
7133 :
7134 : void
7135 2148 : expand_ifn_atomic_op_fetch_cmp_0 (gcall *call)
7136 : {
7137 2148 : tree cmp = gimple_call_arg (call, 0);
7138 2148 : tree ptr = gimple_call_arg (call, 1);
7139 2148 : tree arg = gimple_call_arg (call, 2);
7140 2148 : tree lhs = gimple_call_lhs (call);
7141 2148 : enum memmodel model = MEMMODEL_SYNC_SEQ_CST;
7142 2148 : machine_mode mode = TYPE_MODE (TREE_TYPE (cmp));
7143 2148 : optab optab;
7144 2148 : rtx_code code;
7145 2148 : class expand_operand ops[5];
7146 :
7147 2148 : gcc_assert (flag_inline_atomics);
7148 :
7149 2148 : if (gimple_call_num_args (call) == 5)
7150 1740 : model = get_memmodel (gimple_call_arg (call, 3));
7151 :
7152 2148 : rtx mem = get_builtin_sync_mem (ptr, mode);
7153 2148 : rtx op = expand_expr_force_mode (arg, mode);
7154 :
7155 2148 : switch (gimple_call_internal_fn (call))
7156 : {
7157 : case IFN_ATOMIC_ADD_FETCH_CMP_0:
7158 : code = PLUS;
7159 : optab = atomic_add_fetch_cmp_0_optab;
7160 : break;
7161 : case IFN_ATOMIC_SUB_FETCH_CMP_0:
7162 : code = MINUS;
7163 : optab = atomic_sub_fetch_cmp_0_optab;
7164 : break;
7165 : case IFN_ATOMIC_AND_FETCH_CMP_0:
7166 : code = AND;
7167 : optab = atomic_and_fetch_cmp_0_optab;
7168 : break;
7169 : case IFN_ATOMIC_OR_FETCH_CMP_0:
7170 : code = IOR;
7171 : optab = atomic_or_fetch_cmp_0_optab;
7172 : break;
7173 : case IFN_ATOMIC_XOR_FETCH_CMP_0:
7174 : code = XOR;
7175 : optab = atomic_xor_fetch_cmp_0_optab;
7176 : break;
7177 0 : default:
7178 0 : gcc_unreachable ();
7179 : }
7180 :
7181 2148 : enum rtx_code comp = UNKNOWN;
7182 2148 : switch (tree_to_uhwi (cmp))
7183 : {
7184 : case ATOMIC_OP_FETCH_CMP_0_EQ: comp = EQ; break;
7185 : case ATOMIC_OP_FETCH_CMP_0_NE: comp = NE; break;
7186 : case ATOMIC_OP_FETCH_CMP_0_GT: comp = GT; break;
7187 : case ATOMIC_OP_FETCH_CMP_0_GE: comp = GE; break;
7188 : case ATOMIC_OP_FETCH_CMP_0_LT: comp = LT; break;
7189 : case ATOMIC_OP_FETCH_CMP_0_LE: comp = LE; break;
7190 0 : default: gcc_unreachable ();
7191 : }
7192 :
7193 2148 : rtx target;
7194 2148 : if (lhs == NULL_TREE)
7195 0 : target = gen_reg_rtx (TYPE_MODE (boolean_type_node));
7196 : else
7197 2148 : target = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
7198 2148 : enum insn_code icode = direct_optab_handler (optab, mode);
7199 2148 : gcc_assert (icode != CODE_FOR_nothing);
7200 2148 : create_output_operand (&ops[0], target, TYPE_MODE (boolean_type_node));
7201 2148 : create_fixed_operand (&ops[1], mem);
7202 2148 : create_convert_operand_to (&ops[2], op, mode, true);
7203 2148 : create_integer_operand (&ops[3], model);
7204 2148 : create_integer_operand (&ops[4], comp);
7205 2148 : if (maybe_expand_insn (icode, 5, ops))
7206 2116 : return;
7207 :
7208 32 : rtx result = expand_atomic_fetch_op (gen_reg_rtx (mode), mem, op,
7209 : code, model, true);
7210 32 : if (!result)
7211 : {
7212 0 : bool is_atomic = gimple_call_num_args (call) == 5;
7213 0 : tree tcall = gimple_call_arg (call, 3 + is_atomic);
7214 0 : tree fndecl = gimple_call_addr_fndecl (tcall);
7215 0 : tree type = TREE_TYPE (TREE_TYPE (fndecl));
7216 0 : tree exp;
7217 0 : if (is_atomic)
7218 0 : exp = build_call_nary (type, tcall, 3,
7219 : ptr, arg,
7220 : gimple_call_arg (call, 3));
7221 : else
7222 0 : exp = build_call_nary (type, tcall, 2, ptr, arg);
7223 0 : result = expand_builtin (exp, gen_reg_rtx (mode), NULL_RTX,
7224 : mode, !lhs);
7225 : }
7226 :
7227 32 : if (lhs)
7228 : {
7229 32 : result = emit_store_flag_force (target, comp, result, const0_rtx, mode,
7230 : 0, 1);
7231 32 : if (result != target)
7232 32 : emit_move_insn (target, result);
7233 : }
7234 : }
7235 :
7236 : /* Expand an atomic clear operation.
7237 : void _atomic_clear (BOOL *obj, enum memmodel)
7238 : EXP is the call expression. */
7239 :
7240 : static rtx
7241 53 : expand_builtin_atomic_clear (tree exp)
7242 : {
7243 53 : machine_mode mode = int_mode_for_size (BOOL_TYPE_SIZE, 0).require ();
7244 53 : rtx mem = get_builtin_sync_mem (CALL_EXPR_ARG (exp, 0), mode);
7245 53 : memmodel model = get_memmodel (CALL_EXPR_ARG (exp, 1));
7246 :
7247 53 : if (is_mm_consume (model) || is_mm_acquire (model) || is_mm_acq_rel (model))
7248 : model = MEMMODEL_SEQ_CST;
7249 :
7250 : /* Try issuing an __atomic_store, and allow fallback to __sync_lock_release.
7251 : Failing that, a store is issued by __atomic_store. The only way this can
7252 : fail is if the bool type is larger than a word size. Unlikely, but
7253 : handle it anyway for completeness. Assume a single threaded model since
7254 : there is no atomic support in this case, and no barriers are required. */
7255 53 : rtx ret = expand_atomic_store (mem, const0_rtx, model, true);
7256 53 : if (!ret)
7257 0 : emit_move_insn (mem, const0_rtx);
7258 53 : return const0_rtx;
7259 : }
7260 :
7261 : /* Expand an atomic test_and_set operation.
7262 : bool _atomic_test_and_set (BOOL *obj, enum memmodel)
7263 : EXP is the call expression. */
7264 :
7265 : static rtx
7266 266 : expand_builtin_atomic_test_and_set (tree exp, rtx target)
7267 : {
7268 266 : rtx mem;
7269 266 : enum memmodel model;
7270 266 : machine_mode mode;
7271 :
7272 266 : mode = int_mode_for_size (BOOL_TYPE_SIZE, 0).require ();
7273 266 : mem = get_builtin_sync_mem (CALL_EXPR_ARG (exp, 0), mode);
7274 266 : model = get_memmodel (CALL_EXPR_ARG (exp, 1));
7275 :
7276 266 : return expand_atomic_test_and_set (target, mem, model);
7277 : }
7278 :
7279 :
7280 : /* Return true if (optional) argument ARG1 of size ARG0 is always lock free on
7281 : this architecture. If ARG1 is NULL, use typical alignment for size ARG0. */
7282 :
7283 : static tree
7284 144806 : fold_builtin_atomic_always_lock_free (tree arg0, tree arg1)
7285 : {
7286 144806 : HOST_WIDE_INT size;
7287 144806 : machine_mode mode;
7288 144806 : unsigned int mode_align, type_align;
7289 :
7290 144806 : if (!tree_fits_shwi_p (arg0))
7291 : return NULL_TREE;
7292 :
7293 : /* We need a corresponding integer mode for the access to be lock-free. */
7294 144653 : size = tree_to_shwi (arg0) * BITS_PER_UNIT;
7295 144653 : if (!int_mode_for_size (size, 0).exists (&mode))
7296 9 : return boolean_false_node;
7297 :
7298 144644 : mode_align = GET_MODE_ALIGNMENT (mode);
7299 :
7300 144644 : if (tree_fits_uhwi_p (arg1))
7301 : {
7302 124838 : unsigned HOST_WIDE_INT val = tree_to_uhwi (arg1);
7303 :
7304 : /* Either this argument is null, or it's a fake pointer encoding
7305 : the alignment of the object. */
7306 124838 : val = least_bit_hwi (val);
7307 124838 : val *= BITS_PER_UNIT;
7308 :
7309 124838 : if (val == 0 || mode_align < val)
7310 : type_align = mode_align;
7311 : else
7312 19049 : type_align = val;
7313 : }
7314 : else
7315 : {
7316 19806 : tree ttype = TREE_TYPE (arg1);
7317 :
7318 : /* This function is usually invoked and folded immediately by the front
7319 : end before anything else has a chance to look at it. The pointer
7320 : parameter at this point is usually cast to a void *, so check for that
7321 : and look past the cast. */
7322 195 : if (CONVERT_EXPR_P (arg1)
7323 19642 : && POINTER_TYPE_P (ttype)
7324 19642 : && VOID_TYPE_P (TREE_TYPE (ttype))
7325 39448 : && POINTER_TYPE_P (TREE_TYPE (TREE_OPERAND (arg1, 0))))
7326 19611 : arg1 = TREE_OPERAND (arg1, 0);
7327 :
7328 19806 : ttype = TREE_TYPE (arg1);
7329 19806 : gcc_assert (POINTER_TYPE_P (ttype));
7330 :
7331 : /* Get the underlying type of the object. */
7332 19806 : ttype = TREE_TYPE (ttype);
7333 19806 : type_align = TYPE_ALIGN (ttype);
7334 : }
7335 :
7336 : /* If the object has smaller alignment, the lock free routines cannot
7337 : be used. */
7338 144644 : if (type_align < mode_align)
7339 247 : return boolean_false_node;
7340 :
7341 : /* Check if a compare_and_swap pattern exists for the mode which represents
7342 : the required size. The pattern is not allowed to fail, so the existence
7343 : of the pattern indicates support is present. Also require that an
7344 : atomic load exists for the required size. */
7345 144397 : if (can_compare_and_swap_p (mode, true) && can_atomic_load_p (mode))
7346 144355 : return boolean_true_node;
7347 : else
7348 42 : return boolean_false_node;
7349 : }
7350 :
7351 : /* Return true if the parameters to call EXP represent an object which will
7352 : always generate lock free instructions. The first argument represents the
7353 : size of the object, and the second parameter is a pointer to the object
7354 : itself. If NULL is passed for the object, then the result is based on
7355 : typical alignment for an object of the specified size. Otherwise return
7356 : false. */
7357 :
7358 : static rtx
7359 1 : expand_builtin_atomic_always_lock_free (tree exp)
7360 : {
7361 1 : tree size;
7362 1 : tree arg0 = CALL_EXPR_ARG (exp, 0);
7363 1 : tree arg1 = CALL_EXPR_ARG (exp, 1);
7364 :
7365 1 : if (TREE_CODE (arg0) != INTEGER_CST)
7366 : {
7367 1 : error ("non-constant argument 1 to %qs", "__atomic_always_lock_free");
7368 1 : return const0_rtx;
7369 : }
7370 :
7371 0 : size = fold_builtin_atomic_always_lock_free (arg0, arg1);
7372 0 : if (size == boolean_true_node)
7373 0 : return const1_rtx;
7374 0 : return const0_rtx;
7375 : }
7376 :
7377 : /* Return a one or zero if it can be determined that object ARG1 of size ARG
7378 : is lock free on this architecture. */
7379 :
7380 : static tree
7381 38954 : fold_builtin_atomic_is_lock_free (tree arg0, tree arg1)
7382 : {
7383 38954 : if (!flag_inline_atomics)
7384 : return NULL_TREE;
7385 :
7386 : /* If it isn't always lock free, don't generate a result. */
7387 38945 : if (fold_builtin_atomic_always_lock_free (arg0, arg1) == boolean_true_node)
7388 38586 : return boolean_true_node;
7389 :
7390 : return NULL_TREE;
7391 : }
7392 :
7393 : /* Return true if the parameters to call EXP represent an object which will
7394 : always generate lock free instructions. The first argument represents the
7395 : size of the object, and the second parameter is a pointer to the object
7396 : itself. If NULL is passed for the object, then the result is based on
7397 : typical alignment for an object of the specified size. Otherwise return
7398 : NULL*/
7399 :
7400 : static rtx
7401 10 : expand_builtin_atomic_is_lock_free (tree exp)
7402 : {
7403 10 : tree size;
7404 10 : tree arg0 = CALL_EXPR_ARG (exp, 0);
7405 10 : tree arg1 = CALL_EXPR_ARG (exp, 1);
7406 :
7407 10 : if (!INTEGRAL_TYPE_P (TREE_TYPE (arg0)))
7408 : {
7409 0 : error ("non-integer argument 1 to %qs", "__atomic_is_lock_free");
7410 0 : return NULL_RTX;
7411 : }
7412 :
7413 10 : if (!flag_inline_atomics)
7414 : return NULL_RTX;
7415 :
7416 : /* If the value is known at compile time, return the RTX for it. */
7417 9 : size = fold_builtin_atomic_is_lock_free (arg0, arg1);
7418 9 : if (size == boolean_true_node)
7419 0 : return const1_rtx;
7420 :
7421 : return NULL_RTX;
7422 : }
7423 :
7424 : /* Expand the __atomic_thread_fence intrinsic:
7425 : void __atomic_thread_fence (enum memmodel)
7426 : EXP is the CALL_EXPR. */
7427 :
7428 : static void
7429 703 : expand_builtin_atomic_thread_fence (tree exp)
7430 : {
7431 703 : enum memmodel model = get_memmodel (CALL_EXPR_ARG (exp, 0));
7432 703 : expand_mem_thread_fence (model);
7433 703 : }
7434 :
7435 : /* Expand the __atomic_signal_fence intrinsic:
7436 : void __atomic_signal_fence (enum memmodel)
7437 : EXP is the CALL_EXPR. */
7438 :
7439 : static void
7440 60 : expand_builtin_atomic_signal_fence (tree exp)
7441 : {
7442 60 : enum memmodel model = get_memmodel (CALL_EXPR_ARG (exp, 0));
7443 60 : expand_mem_signal_fence (model);
7444 60 : }
7445 :
7446 : /* Expand the __sync_synchronize intrinsic. */
7447 :
7448 : static void
7449 275 : expand_builtin_sync_synchronize (void)
7450 : {
7451 0 : expand_mem_thread_fence (MEMMODEL_SYNC_SEQ_CST);
7452 0 : }
7453 :
7454 : static rtx
7455 3 : expand_builtin_thread_pointer (tree exp, rtx target)
7456 : {
7457 3 : enum insn_code icode;
7458 3 : if (!validate_arglist (exp, VOID_TYPE))
7459 0 : return const0_rtx;
7460 3 : icode = direct_optab_handler (get_thread_pointer_optab, Pmode);
7461 3 : if (icode != CODE_FOR_nothing)
7462 : {
7463 3 : class expand_operand op;
7464 : /* If the target is not sutitable then create a new target. */
7465 3 : if (target == NULL_RTX
7466 3 : || !REG_P (target)
7467 6 : || GET_MODE (target) != Pmode)
7468 0 : target = gen_reg_rtx (Pmode);
7469 3 : create_output_operand (&op, target, Pmode);
7470 3 : expand_insn (icode, 1, &op);
7471 3 : return target;
7472 : }
7473 0 : error ("%<__builtin_thread_pointer%> is not supported on this target");
7474 0 : return const0_rtx;
7475 : }
7476 :
7477 : static void
7478 0 : expand_builtin_set_thread_pointer (tree exp)
7479 : {
7480 0 : enum insn_code icode;
7481 0 : if (!validate_arglist (exp, POINTER_TYPE, VOID_TYPE))
7482 : return;
7483 0 : icode = direct_optab_handler (set_thread_pointer_optab, Pmode);
7484 0 : if (icode != CODE_FOR_nothing)
7485 : {
7486 0 : class expand_operand op;
7487 0 : rtx val = expand_expr (CALL_EXPR_ARG (exp, 0), NULL_RTX,
7488 0 : Pmode, EXPAND_NORMAL);
7489 0 : create_input_operand (&op, val, Pmode);
7490 0 : expand_insn (icode, 1, &op);
7491 0 : return;
7492 : }
7493 0 : error ("%<__builtin_set_thread_pointer%> is not supported on this target");
7494 : }
7495 :
7496 :
7497 : /* Emit code to restore the current value of stack. */
7498 :
7499 : static void
7500 1755 : expand_stack_restore (tree var)
7501 : {
7502 1755 : rtx_insn *prev;
7503 1755 : rtx sa = expand_normal (var);
7504 :
7505 1811 : sa = convert_memory_address (Pmode, sa);
7506 :
7507 1755 : prev = get_last_insn ();
7508 1755 : emit_stack_restore (SAVE_BLOCK, sa);
7509 :
7510 1755 : record_new_stack_level ();
7511 :
7512 1755 : fixup_args_size_notes (prev, get_last_insn (), 0);
7513 1755 : }
7514 :
7515 : /* Emit code to save the current value of stack. */
7516 :
7517 : static rtx
7518 1856 : expand_stack_save (void)
7519 : {
7520 1856 : rtx ret = NULL_RTX;
7521 :
7522 0 : emit_stack_save (SAVE_BLOCK, &ret);
7523 1856 : return ret;
7524 : }
7525 :
7526 : /* Emit code to get the openacc gang, worker or vector id or size. */
7527 :
7528 : static rtx
7529 356 : expand_builtin_goacc_parlevel_id_size (tree exp, rtx target, int ignore)
7530 : {
7531 356 : const char *name;
7532 356 : rtx fallback_retval;
7533 356 : rtx_insn *(*gen_fn) (rtx, rtx);
7534 356 : switch (DECL_FUNCTION_CODE (get_callee_fndecl (exp)))
7535 : {
7536 244 : case BUILT_IN_GOACC_PARLEVEL_ID:
7537 244 : name = "__builtin_goacc_parlevel_id";
7538 244 : fallback_retval = const0_rtx;
7539 244 : gen_fn = targetm.gen_oacc_dim_pos;
7540 244 : break;
7541 112 : case BUILT_IN_GOACC_PARLEVEL_SIZE:
7542 112 : name = "__builtin_goacc_parlevel_size";
7543 112 : fallback_retval = const1_rtx;
7544 112 : gen_fn = targetm.gen_oacc_dim_size;
7545 112 : break;
7546 0 : default:
7547 0 : gcc_unreachable ();
7548 : }
7549 :
7550 356 : if (oacc_get_fn_attrib (current_function_decl) == NULL_TREE)
7551 : {
7552 8 : error ("%qs only supported in OpenACC code", name);
7553 8 : return const0_rtx;
7554 : }
7555 :
7556 348 : tree arg = CALL_EXPR_ARG (exp, 0);
7557 348 : if (TREE_CODE (arg) != INTEGER_CST)
7558 : {
7559 8 : error ("non-constant argument 0 to %qs", name);
7560 8 : return const0_rtx;
7561 : }
7562 :
7563 340 : int dim = TREE_INT_CST_LOW (arg);
7564 340 : switch (dim)
7565 : {
7566 324 : case GOMP_DIM_GANG:
7567 324 : case GOMP_DIM_WORKER:
7568 324 : case GOMP_DIM_VECTOR:
7569 324 : break;
7570 16 : default:
7571 16 : error ("illegal argument 0 to %qs", name);
7572 16 : return const0_rtx;
7573 : }
7574 :
7575 324 : if (ignore)
7576 : return target;
7577 :
7578 180 : if (target == NULL_RTX)
7579 0 : target = gen_reg_rtx (TYPE_MODE (TREE_TYPE (exp)));
7580 :
7581 180 : if (!targetm.have_oacc_dim_size ())
7582 : {
7583 180 : emit_move_insn (target, fallback_retval);
7584 180 : return target;
7585 : }
7586 :
7587 0 : rtx reg = MEM_P (target) ? gen_reg_rtx (GET_MODE (target)) : target;
7588 0 : emit_insn (gen_fn (reg, GEN_INT (dim)));
7589 0 : if (reg != target)
7590 0 : emit_move_insn (target, reg);
7591 :
7592 : return target;
7593 : }
7594 :
7595 : /* Expand a string compare operation using a sequence of char comparison
7596 : to get rid of the calling overhead, with result going to TARGET if
7597 : that's convenient.
7598 :
7599 : VAR_STR is the variable string source;
7600 : CONST_STR is the constant string source;
7601 : LENGTH is the number of chars to compare;
7602 : CONST_STR_N indicates which source string is the constant string;
7603 : IS_MEMCMP indicates whether it's a memcmp or strcmp.
7604 :
7605 : to: (assume const_str_n is 2, i.e., arg2 is a constant string)
7606 :
7607 : target = (int) (unsigned char) var_str[0]
7608 : - (int) (unsigned char) const_str[0];
7609 : if (target != 0)
7610 : goto ne_label;
7611 : ...
7612 : target = (int) (unsigned char) var_str[length - 2]
7613 : - (int) (unsigned char) const_str[length - 2];
7614 : if (target != 0)
7615 : goto ne_label;
7616 : target = (int) (unsigned char) var_str[length - 1]
7617 : - (int) (unsigned char) const_str[length - 1];
7618 : ne_label:
7619 : */
7620 :
7621 : static rtx
7622 635 : inline_string_cmp (rtx target, tree var_str, const char *const_str,
7623 : unsigned HOST_WIDE_INT length,
7624 : int const_str_n, machine_mode mode)
7625 : {
7626 635 : HOST_WIDE_INT offset = 0;
7627 635 : rtx var_rtx_array
7628 635 : = get_memory_rtx (var_str, build_int_cst (unsigned_type_node, length),
7629 : false);
7630 635 : rtx var_rtx = NULL_RTX;
7631 635 : rtx const_rtx = NULL_RTX;
7632 635 : rtx result = target ? target : gen_reg_rtx (mode);
7633 635 : rtx_code_label *ne_label = gen_label_rtx ();
7634 635 : tree unit_type_node = unsigned_char_type_node;
7635 635 : scalar_int_mode unit_mode
7636 635 : = as_a <scalar_int_mode> TYPE_MODE (unit_type_node);
7637 :
7638 635 : start_sequence ();
7639 :
7640 2964 : for (unsigned HOST_WIDE_INT i = 0; i < length; i++)
7641 : {
7642 1694 : var_rtx
7643 1694 : = adjust_address (var_rtx_array, TYPE_MODE (unit_type_node), offset);
7644 1694 : const_rtx = c_readstr (const_str + offset, unit_mode);
7645 1694 : rtx op0 = (const_str_n == 1) ? const_rtx : var_rtx;
7646 1544 : rtx op1 = (const_str_n == 1) ? var_rtx : const_rtx;
7647 :
7648 1694 : op0 = convert_modes (mode, unit_mode, op0, 1);
7649 1694 : op1 = convert_modes (mode, unit_mode, op1, 1);
7650 1694 : rtx diff = expand_simple_binop (mode, MINUS, op0, op1,
7651 : result, 1, OPTAB_WIDEN);
7652 :
7653 : /* Force the difference into result register. We cannot reassign
7654 : result here ("result = diff") or we may end up returning
7655 : uninitialized result when expand_simple_binop allocates a new
7656 : pseudo-register for returning. */
7657 1694 : if (diff != result)
7658 0 : emit_move_insn (result, diff);
7659 :
7660 1694 : if (i < length - 1)
7661 1059 : emit_cmp_and_jump_insns (result, CONST0_RTX (mode), NE, NULL_RTX,
7662 : mode, true, ne_label);
7663 3388 : offset += GET_MODE_SIZE (unit_mode);
7664 : }
7665 :
7666 635 : emit_label (ne_label);
7667 635 : rtx_insn *insns = end_sequence ();
7668 635 : emit_insn (insns);
7669 :
7670 635 : return result;
7671 : }
7672 :
7673 : /* Inline expansion of a call to str(n)cmp and memcmp, with result going
7674 : to TARGET if that's convenient.
7675 : If the call is not been inlined, return NULL_RTX. */
7676 :
7677 : static rtx
7678 145281 : inline_expand_builtin_bytecmp (tree exp, rtx target)
7679 : {
7680 145281 : tree fndecl = get_callee_fndecl (exp);
7681 145281 : enum built_in_function fcode = DECL_FUNCTION_CODE (fndecl);
7682 145281 : bool is_ncmp = (fcode == BUILT_IN_STRNCMP || fcode == BUILT_IN_MEMCMP);
7683 :
7684 : /* Do NOT apply this inlining expansion when optimizing for size or
7685 : optimization level below 2 or if unused *cmp hasn't been DCEd. */
7686 145281 : if (optimize < 2 || optimize_insn_for_size_p () || target == const0_rtx)
7687 : return NULL_RTX;
7688 :
7689 23144 : gcc_checking_assert (fcode == BUILT_IN_STRCMP
7690 : || fcode == BUILT_IN_STRNCMP
7691 : || fcode == BUILT_IN_MEMCMP);
7692 :
7693 : /* On a target where the type of the call (int) has same or narrower precision
7694 : than unsigned char, give up the inlining expansion. */
7695 23144 : if (TYPE_PRECISION (unsigned_char_type_node)
7696 23144 : >= TYPE_PRECISION (TREE_TYPE (exp)))
7697 : return NULL_RTX;
7698 :
7699 23144 : tree arg1 = CALL_EXPR_ARG (exp, 0);
7700 23144 : tree arg2 = CALL_EXPR_ARG (exp, 1);
7701 23144 : tree len3_tree = is_ncmp ? CALL_EXPR_ARG (exp, 2) : NULL_TREE;
7702 :
7703 23144 : unsigned HOST_WIDE_INT len1 = 0;
7704 23144 : unsigned HOST_WIDE_INT len2 = 0;
7705 23144 : unsigned HOST_WIDE_INT len3 = 0;
7706 :
7707 : /* Get the object representation of the initializers of ARG1 and ARG2
7708 : as strings, provided they refer to constant objects, with their byte
7709 : sizes in LEN1 and LEN2, respectively. */
7710 23144 : const char *bytes1 = getbyterep (arg1, &len1);
7711 23144 : const char *bytes2 = getbyterep (arg2, &len2);
7712 :
7713 : /* Fail if neither argument refers to an initialized constant. */
7714 23144 : if (!bytes1 && !bytes2)
7715 : return NULL_RTX;
7716 :
7717 18501 : if (is_ncmp)
7718 : {
7719 : /* Fail if the memcmp/strncmp bound is not a constant. */
7720 1384 : if (!tree_fits_uhwi_p (len3_tree))
7721 : return NULL_RTX;
7722 :
7723 962 : len3 = tree_to_uhwi (len3_tree);
7724 :
7725 962 : if (fcode == BUILT_IN_MEMCMP)
7726 : {
7727 : /* Fail if the memcmp bound is greater than the size of either
7728 : of the two constant objects. */
7729 462 : if ((bytes1 && len1 < len3)
7730 462 : || (bytes2 && len2 < len3))
7731 : return NULL_RTX;
7732 : }
7733 : }
7734 :
7735 : if (fcode != BUILT_IN_MEMCMP)
7736 : {
7737 : /* For string functions (i.e., strcmp and strncmp) reduce LEN1
7738 : and LEN2 to the length of the nul-terminated string stored
7739 : in each. */
7740 17617 : if (bytes1 != NULL)
7741 236 : len1 = strnlen (bytes1, len1) + 1;
7742 17617 : if (bytes2 != NULL)
7743 17384 : len2 = strnlen (bytes2, len2) + 1;
7744 : }
7745 :
7746 : /* See inline_string_cmp. */
7747 18075 : int const_str_n;
7748 18075 : if (!len1)
7749 : const_str_n = 2;
7750 241 : else if (!len2)
7751 : const_str_n = 1;
7752 3 : else if (len2 > len1)
7753 : const_str_n = 1;
7754 : else
7755 : const_str_n = 2;
7756 :
7757 : /* For strncmp only, compute the new bound as the smallest of
7758 : the lengths of the two strings (plus 1) and the bound provided
7759 : to the function. */
7760 17836 : unsigned HOST_WIDE_INT bound = (const_str_n == 1) ? len1 : len2;
7761 18075 : if (is_ncmp && len3 < bound)
7762 534 : bound = len3;
7763 :
7764 : /* If the bound of the comparison is larger than the threshold,
7765 : do nothing. */
7766 18075 : if (bound > (unsigned HOST_WIDE_INT) param_builtin_string_cmp_inline_length)
7767 : return NULL_RTX;
7768 :
7769 635 : machine_mode mode = TYPE_MODE (TREE_TYPE (exp));
7770 :
7771 : /* Now, start inline expansion the call. */
7772 1213 : return inline_string_cmp (target, (const_str_n == 1) ? arg2 : arg1,
7773 : (const_str_n == 1) ? bytes1 : bytes2, bound,
7774 635 : const_str_n, mode);
7775 : }
7776 :
7777 : /* Expand a call to __builtin_speculation_safe_value_<N>. MODE
7778 : represents the size of the first argument to that call, or VOIDmode
7779 : if the argument is a pointer. IGNORE will be true if the result
7780 : isn't used. */
7781 : static rtx
7782 35 : expand_speculation_safe_value (machine_mode mode, tree exp, rtx target,
7783 : bool ignore)
7784 : {
7785 35 : rtx val, failsafe;
7786 35 : unsigned nargs = call_expr_nargs (exp);
7787 :
7788 35 : tree arg0 = CALL_EXPR_ARG (exp, 0);
7789 :
7790 35 : if (mode == VOIDmode)
7791 : {
7792 4 : mode = TYPE_MODE (TREE_TYPE (arg0));
7793 4 : gcc_assert (GET_MODE_CLASS (mode) == MODE_INT);
7794 : }
7795 :
7796 35 : val = expand_expr (arg0, NULL_RTX, mode, EXPAND_NORMAL);
7797 :
7798 : /* An optional second argument can be used as a failsafe value on
7799 : some machines. If it isn't present, then the failsafe value is
7800 : assumed to be 0. */
7801 35 : if (nargs > 1)
7802 : {
7803 4 : tree arg1 = CALL_EXPR_ARG (exp, 1);
7804 4 : failsafe = expand_expr (arg1, NULL_RTX, mode, EXPAND_NORMAL);
7805 : }
7806 : else
7807 31 : failsafe = const0_rtx;
7808 :
7809 : /* If the result isn't used, the behavior is undefined. It would be
7810 : nice to emit a warning here, but path splitting means this might
7811 : happen with legitimate code. So simply drop the builtin
7812 : expansion in that case; we've handled any side-effects above. */
7813 35 : if (ignore)
7814 0 : return const0_rtx;
7815 :
7816 : /* If we don't have a suitable target, create one to hold the result. */
7817 35 : if (target == NULL || GET_MODE (target) != mode)
7818 0 : target = gen_reg_rtx (mode);
7819 :
7820 35 : if (GET_MODE (val) != mode && GET_MODE (val) != VOIDmode)
7821 0 : val = convert_modes (mode, VOIDmode, val, false);
7822 :
7823 35 : return targetm.speculation_safe_value (mode, target, val, failsafe);
7824 : }
7825 :
7826 : /* Expand CRC* or REV_CRC* built-ins. */
7827 :
7828 : rtx
7829 45 : expand_builtin_crc_table_based (internal_fn fn, scalar_mode crc_mode,
7830 : scalar_mode data_mode, machine_mode mode,
7831 : tree exp, rtx target)
7832 : {
7833 45 : tree rhs1 = CALL_EXPR_ARG (exp, 0); // crc
7834 45 : tree rhs2 = CALL_EXPR_ARG (exp, 1); // data
7835 45 : tree rhs3 = CALL_EXPR_ARG (exp, 2); // polynomial
7836 :
7837 45 : if (!target || mode == VOIDmode)
7838 0 : target = gen_reg_rtx (crc_mode);
7839 :
7840 45 : rtx op1 = expand_normal (rhs1);
7841 45 : rtx op2 = expand_normal (rhs2);
7842 45 : rtx op3;
7843 45 : if (TREE_CODE (rhs3) != INTEGER_CST)
7844 : {
7845 1 : error ("third argument to %<crc%> builtins must be a constant");
7846 1 : op3 = const0_rtx;
7847 : }
7848 : else
7849 44 : op3 = convert_to_mode (crc_mode, expand_normal (rhs3), 0);
7850 :
7851 45 : if (CONST_INT_P (op2))
7852 32 : op2 = convert_to_mode (crc_mode, op2, 0);
7853 :
7854 45 : if (fn == IFN_CRC)
7855 28 : expand_crc_table_based (target, op1, op2, op3, data_mode);
7856 : else
7857 : /* If it's IFN_CRC_REV generate bit-reversed CRC. */
7858 17 : expand_reversed_crc_table_based (target, op1, op2, op3,
7859 : data_mode);
7860 45 : return target;
7861 : }
7862 :
7863 : /* Expand an expression EXP that calls a built-in function,
7864 : with result going to TARGET if that's convenient
7865 : (and in mode MODE if that's convenient).
7866 : SUBTARGET may be used as the target for computing one of EXP's operands.
7867 : IGNORE is nonzero if the value is to be ignored. */
7868 :
7869 : rtx
7870 2036546 : expand_builtin (tree exp, rtx target, rtx subtarget, machine_mode mode,
7871 : int ignore)
7872 : {
7873 2036546 : tree fndecl = get_callee_fndecl (exp);
7874 2036546 : machine_mode target_mode = TYPE_MODE (TREE_TYPE (exp));
7875 2036546 : int flags;
7876 :
7877 2036546 : if (DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_MD)
7878 177332 : return targetm.expand_builtin (exp, target, subtarget, mode, ignore);
7879 :
7880 : /* When ASan is enabled, we don't want to expand some memory/string
7881 : builtins and rely on libsanitizer's hooks. This allows us to avoid
7882 : redundant checks and be sure, that possible overflow will be detected
7883 : by ASan. */
7884 :
7885 1859214 : enum built_in_function fcode = DECL_FUNCTION_CODE (fndecl);
7886 1859214 : if (param_asan_kernel_mem_intrinsic_prefix
7887 1859214 : && sanitize_flags_p (SANITIZE_KERNEL_ADDRESS
7888 : | SANITIZE_KERNEL_HWADDRESS))
7889 42 : switch (fcode)
7890 : {
7891 42 : rtx save_decl_rtl, ret;
7892 42 : case BUILT_IN_MEMCPY:
7893 42 : case BUILT_IN_MEMMOVE:
7894 42 : case BUILT_IN_MEMSET:
7895 42 : save_decl_rtl = DECL_RTL (fndecl);
7896 42 : DECL_RTL (fndecl) = asan_memfn_rtl (fndecl);
7897 42 : ret = expand_call (exp, target, ignore);
7898 42 : DECL_RTL (fndecl) = save_decl_rtl;
7899 42 : return ret;
7900 : default:
7901 : break;
7902 : }
7903 1859172 : if (sanitize_flags_p (SANITIZE_ADDRESS | SANITIZE_HWADDRESS)
7904 1859172 : && asan_intercepted_p (fcode))
7905 938 : return expand_call (exp, target, ignore);
7906 :
7907 : /* When not optimizing, generate calls to library functions for a certain
7908 : set of builtins. */
7909 1858234 : if (!optimize
7910 430486 : && !called_as_built_in (fndecl)
7911 145806 : && fcode != BUILT_IN_FORK
7912 145806 : && fcode != BUILT_IN_EXECL
7913 145793 : && fcode != BUILT_IN_EXECV
7914 145793 : && fcode != BUILT_IN_EXECLP
7915 145791 : && fcode != BUILT_IN_EXECLE
7916 145791 : && fcode != BUILT_IN_EXECVP
7917 145790 : && fcode != BUILT_IN_EXECVE
7918 145790 : && fcode != BUILT_IN_CLEAR_CACHE
7919 145787 : && !ALLOCA_FUNCTION_CODE_P (fcode)
7920 145733 : && fcode != BUILT_IN_FREE
7921 143590 : && (fcode != BUILT_IN_MEMSET
7922 55891 : || !(flag_inline_stringops & ILSOP_MEMSET))
7923 143587 : && (fcode != BUILT_IN_MEMCPY
7924 918 : || !(flag_inline_stringops & ILSOP_MEMCPY))
7925 143451 : && (fcode != BUILT_IN_MEMMOVE
7926 348 : || !(flag_inline_stringops & ILSOP_MEMMOVE))
7927 2001685 : && (fcode != BUILT_IN_MEMCMP
7928 2529 : || !(flag_inline_stringops & ILSOP_MEMCMP)))
7929 143403 : return expand_call (exp, target, ignore);
7930 :
7931 : /* The built-in function expanders test for target == const0_rtx
7932 : to determine whether the function's result will be ignored. */
7933 1714831 : if (ignore)
7934 1016882 : target = const0_rtx;
7935 :
7936 : /* If the result of a pure or const built-in function is ignored, and
7937 : none of its arguments are volatile, we can avoid expanding the
7938 : built-in call and just evaluate the arguments for side-effects. */
7939 1714831 : if (target == const0_rtx
7940 1016882 : && ((flags = flags_from_decl_or_type (fndecl)) & (ECF_CONST | ECF_PURE))
7941 1718578 : && !(flags & ECF_LOOPING_CONST_OR_PURE))
7942 : {
7943 6 : bool volatilep = false;
7944 6 : tree arg;
7945 6 : call_expr_arg_iterator iter;
7946 :
7947 20 : FOR_EACH_CALL_EXPR_ARG (arg, iter, exp)
7948 8 : if (TREE_THIS_VOLATILE (arg))
7949 : {
7950 : volatilep = true;
7951 : break;
7952 : }
7953 :
7954 6 : if (! volatilep)
7955 : {
7956 20 : FOR_EACH_CALL_EXPR_ARG (arg, iter, exp)
7957 8 : expand_expr (arg, const0_rtx, VOIDmode, EXPAND_NORMAL);
7958 6 : return const0_rtx;
7959 : }
7960 : }
7961 :
7962 1714825 : switch (fcode)
7963 : {
7964 4 : CASE_FLT_FN (BUILT_IN_FABS):
7965 4 : CASE_FLT_FN_FLOATN_NX (BUILT_IN_FABS):
7966 4 : case BUILT_IN_FABSD32:
7967 4 : case BUILT_IN_FABSD64:
7968 4 : case BUILT_IN_FABSD128:
7969 4 : case BUILT_IN_FABSD64X:
7970 4 : target = expand_builtin_fabs (exp, target, subtarget);
7971 4 : if (target)
7972 856841 : return target;
7973 857984 : break;
7974 :
7975 11677 : CASE_FLT_FN (BUILT_IN_COPYSIGN):
7976 11677 : CASE_FLT_FN_FLOATN_NX (BUILT_IN_COPYSIGN):
7977 11677 : target = expand_builtin_copysign (exp, target, subtarget);
7978 11677 : if (target)
7979 : return target;
7980 : break;
7981 :
7982 : /* Just do a normal library call if we were unable to fold
7983 : the values. */
7984 : CASE_FLT_FN (BUILT_IN_CABS):
7985 : CASE_FLT_FN_FLOATN_NX (BUILT_IN_CABS):
7986 : break;
7987 :
7988 368 : CASE_FLT_FN (BUILT_IN_FMA):
7989 368 : CASE_FLT_FN_FLOATN_NX (BUILT_IN_FMA):
7990 368 : target = expand_builtin_mathfn_ternary (exp, target, subtarget);
7991 368 : if (target)
7992 : return target;
7993 : break;
7994 :
7995 232 : CASE_FLT_FN (BUILT_IN_ILOGB):
7996 232 : if (! flag_unsafe_math_optimizations)
7997 : break;
7998 4 : gcc_fallthrough ();
7999 4 : CASE_FLT_FN (BUILT_IN_ISINF):
8000 4 : CASE_FLT_FN (BUILT_IN_FINITE):
8001 4 : CASE_FLT_FN (BUILT_IN_ISNAN):
8002 4 : case BUILT_IN_ISFINITE:
8003 4 : case BUILT_IN_ISNORMAL:
8004 4 : target = expand_builtin_interclass_mathfn (exp, target);
8005 4 : if (target)
8006 : return target;
8007 : break;
8008 :
8009 784 : case BUILT_IN_ISSIGNALING:
8010 784 : target = expand_builtin_issignaling (exp, target);
8011 784 : if (target)
8012 : return target;
8013 : break;
8014 :
8015 223 : CASE_FLT_FN (BUILT_IN_ICEIL):
8016 223 : CASE_FLT_FN (BUILT_IN_LCEIL):
8017 223 : CASE_FLT_FN (BUILT_IN_LLCEIL):
8018 223 : CASE_FLT_FN (BUILT_IN_LFLOOR):
8019 223 : CASE_FLT_FN (BUILT_IN_IFLOOR):
8020 223 : CASE_FLT_FN (BUILT_IN_LLFLOOR):
8021 223 : target = expand_builtin_int_roundingfn (exp, target);
8022 223 : if (target)
8023 : return target;
8024 : break;
8025 :
8026 588 : CASE_FLT_FN (BUILT_IN_IRINT):
8027 588 : CASE_FLT_FN (BUILT_IN_LRINT):
8028 588 : CASE_FLT_FN (BUILT_IN_LLRINT):
8029 588 : CASE_FLT_FN (BUILT_IN_IROUND):
8030 588 : CASE_FLT_FN (BUILT_IN_LROUND):
8031 588 : CASE_FLT_FN (BUILT_IN_LLROUND):
8032 588 : target = expand_builtin_int_roundingfn_2 (exp, target);
8033 588 : if (target)
8034 : return target;
8035 : break;
8036 :
8037 292 : CASE_FLT_FN (BUILT_IN_POWI):
8038 292 : target = expand_builtin_powi (exp, target);
8039 292 : if (target)
8040 : return target;
8041 : break;
8042 :
8043 170 : CASE_FLT_FN (BUILT_IN_CEXPI):
8044 170 : target = expand_builtin_cexpi (exp, target);
8045 170 : gcc_assert (target);
8046 : return target;
8047 :
8048 1017 : CASE_FLT_FN (BUILT_IN_SIN):
8049 1017 : CASE_FLT_FN (BUILT_IN_COS):
8050 1017 : if (! flag_unsafe_math_optimizations)
8051 : break;
8052 47 : target = expand_builtin_mathfn_3 (exp, target, subtarget);
8053 47 : if (target)
8054 : return target;
8055 : break;
8056 :
8057 164 : CASE_FLT_FN (BUILT_IN_SINCOS):
8058 164 : if (! flag_unsafe_math_optimizations)
8059 : break;
8060 3 : target = expand_builtin_sincos (exp);
8061 3 : if (target)
8062 : return target;
8063 : break;
8064 :
8065 60 : case BUILT_IN_FEGETROUND:
8066 60 : target = expand_builtin_fegetround (exp, target, target_mode);
8067 60 : if (target)
8068 : return target;
8069 : break;
8070 :
8071 1065 : case BUILT_IN_FECLEAREXCEPT:
8072 1065 : target = expand_builtin_feclear_feraise_except (exp, target, target_mode,
8073 : feclearexcept_optab);
8074 1065 : if (target)
8075 : return target;
8076 : break;
8077 :
8078 831 : case BUILT_IN_FERAISEEXCEPT:
8079 831 : target = expand_builtin_feclear_feraise_except (exp, target, target_mode,
8080 : feraiseexcept_optab);
8081 831 : if (target)
8082 : return target;
8083 : break;
8084 :
8085 464 : case BUILT_IN_APPLY_ARGS:
8086 464 : return expand_builtin_apply_args ();
8087 :
8088 : /* __builtin_apply (FUNCTION, ARGUMENTS, ARGSIZE) invokes
8089 : FUNCTION with a copy of the parameters described by
8090 : ARGUMENTS, and ARGSIZE. It returns a block of memory
8091 : allocated on the stack into which is stored all the registers
8092 : that might possibly be used for returning the result of a
8093 : function. ARGUMENTS is the value returned by
8094 : __builtin_apply_args. ARGSIZE is the number of bytes of
8095 : arguments that must be copied. ??? How should this value be
8096 : computed? We'll also need a safe worst case value for varargs
8097 : functions. */
8098 483 : case BUILT_IN_APPLY:
8099 483 : if (!validate_arglist (exp, POINTER_TYPE,
8100 : POINTER_TYPE, INTEGER_TYPE, VOID_TYPE)
8101 483 : && !validate_arglist (exp, REFERENCE_TYPE,
8102 : POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
8103 0 : return const0_rtx;
8104 : else
8105 : {
8106 483 : rtx ops[3];
8107 :
8108 483 : ops[0] = expand_normal (CALL_EXPR_ARG (exp, 0));
8109 483 : ops[1] = expand_normal (CALL_EXPR_ARG (exp, 1));
8110 483 : ops[2] = expand_normal (CALL_EXPR_ARG (exp, 2));
8111 :
8112 483 : return expand_builtin_apply (ops[0], ops[1], ops[2]);
8113 : }
8114 :
8115 : /* __builtin_return (RESULT) causes the function to return the
8116 : value described by RESULT. RESULT is address of the block of
8117 : memory returned by __builtin_apply. */
8118 379 : case BUILT_IN_RETURN:
8119 379 : if (validate_arglist (exp, POINTER_TYPE, VOID_TYPE))
8120 379 : expand_builtin_return (expand_normal (CALL_EXPR_ARG (exp, 0)));
8121 379 : return const0_rtx;
8122 :
8123 0 : case BUILT_IN_CALL_CODE_ADDRESS:
8124 : /* All valid uses of __builtin_call_code_address () are removed in
8125 : in tree-nested.cc or gimple-fold.cc. */
8126 0 : error ("argument to %<__builtin_call_code_address%> must be a function");
8127 0 : return const0_rtx;
8128 :
8129 0 : case BUILT_IN_CALL_STATIC_CHAIN:
8130 : /* All valid uses of __builtin_call_static_chain () are removed in
8131 : in tree-nested.cc or gimple-fold.cc. */
8132 0 : error ("argument to %<__builtin_call_static_chain%> must be a function");
8133 0 : return const0_rtx;
8134 :
8135 0 : case BUILT_IN_SAVEREGS:
8136 0 : return expand_builtin_saveregs ();
8137 :
8138 16 : case BUILT_IN_VA_ARG_PACK:
8139 : /* All valid uses of __builtin_va_arg_pack () are removed during
8140 : inlining. */
8141 16 : error ("invalid use of %<__builtin_va_arg_pack ()%>");
8142 16 : return const0_rtx;
8143 :
8144 0 : case BUILT_IN_VA_ARG_PACK_LEN:
8145 : /* All valid uses of __builtin_va_arg_pack_len () are removed during
8146 : inlining. */
8147 0 : error ("invalid use of %<__builtin_va_arg_pack_len ()%>");
8148 0 : return const0_rtx;
8149 :
8150 : /* Return the address of the first anonymous stack arg. */
8151 158 : case BUILT_IN_NEXT_ARG:
8152 158 : if (fold_builtin_next_arg (exp, false))
8153 0 : return const0_rtx;
8154 158 : return expand_builtin_next_arg ();
8155 :
8156 28 : case BUILT_IN_CLEAR_CACHE:
8157 28 : expand_builtin___clear_cache (exp);
8158 28 : return const0_rtx;
8159 :
8160 0 : case BUILT_IN_CLASSIFY_TYPE:
8161 0 : return expand_builtin_classify_type (exp);
8162 :
8163 0 : case BUILT_IN_CONSTANT_P:
8164 0 : return const0_rtx;
8165 :
8166 15936 : case BUILT_IN_FRAME_ADDRESS:
8167 15936 : case BUILT_IN_RETURN_ADDRESS:
8168 15936 : return expand_builtin_frame_address (fndecl, exp);
8169 :
8170 540 : case BUILT_IN_STACK_ADDRESS:
8171 540 : return expand_builtin_stack_address ();
8172 :
8173 2170 : case BUILT_IN___STRUB_ENTER:
8174 2170 : target = expand_builtin_strub_enter (exp);
8175 2170 : if (target)
8176 : return target;
8177 : break;
8178 :
8179 1084 : case BUILT_IN___STRUB_UPDATE:
8180 1084 : target = expand_builtin_strub_update (exp);
8181 1084 : if (target)
8182 : return target;
8183 : break;
8184 :
8185 2740 : case BUILT_IN___STRUB_LEAVE:
8186 2740 : target = expand_builtin_strub_leave (exp);
8187 2740 : if (target)
8188 : return target;
8189 : break;
8190 :
8191 : /* Returns the address of the area where the structure is returned.
8192 : 0 otherwise. */
8193 0 : case BUILT_IN_AGGREGATE_INCOMING_ADDRESS:
8194 0 : if (call_expr_nargs (exp) != 0
8195 0 : || ! AGGREGATE_TYPE_P (TREE_TYPE (TREE_TYPE (current_function_decl)))
8196 0 : || !MEM_P (DECL_RTL (DECL_RESULT (current_function_decl))))
8197 0 : return const0_rtx;
8198 : else
8199 0 : return XEXP (DECL_RTL (DECL_RESULT (current_function_decl)), 0);
8200 :
8201 27543 : CASE_BUILT_IN_ALLOCA:
8202 27543 : target = expand_builtin_alloca (exp);
8203 27543 : if (target)
8204 : return target;
8205 : break;
8206 :
8207 204 : case BUILT_IN_ASAN_ALLOCAS_UNPOISON:
8208 204 : return expand_asan_emit_allocas_unpoison (exp);
8209 :
8210 1856 : case BUILT_IN_STACK_SAVE:
8211 1856 : return expand_stack_save ();
8212 :
8213 1755 : case BUILT_IN_STACK_RESTORE:
8214 1755 : expand_stack_restore (CALL_EXPR_ARG (exp, 0));
8215 1755 : return const0_rtx;
8216 :
8217 1276 : case BUILT_IN_BSWAP16:
8218 1276 : case BUILT_IN_BSWAP32:
8219 1276 : case BUILT_IN_BSWAP64:
8220 1276 : case BUILT_IN_BSWAP128:
8221 1276 : target = expand_builtin_bswap (target_mode, exp, target, subtarget);
8222 1276 : if (target)
8223 : return target;
8224 : break;
8225 :
8226 54 : case BUILT_IN_BITREVERSE8:
8227 54 : case BUILT_IN_BITREVERSE16:
8228 54 : case BUILT_IN_BITREVERSE32:
8229 54 : case BUILT_IN_BITREVERSE64:
8230 54 : case BUILT_IN_BITREVERSE128:
8231 54 : target = expand_builtin_unop (target_mode, exp, target, subtarget,
8232 : bitreverse_optab);
8233 54 : if (target)
8234 : return target;
8235 : break;
8236 :
8237 0 : CASE_INT_FN (BUILT_IN_FFS):
8238 0 : target = expand_builtin_unop (target_mode, exp, target,
8239 : subtarget, ffs_optab);
8240 0 : if (target)
8241 : return target;
8242 : break;
8243 :
8244 205 : CASE_INT_FN (BUILT_IN_CLZ):
8245 205 : target = expand_builtin_unop (target_mode, exp, target,
8246 : subtarget, clz_optab);
8247 205 : if (target)
8248 : return target;
8249 : break;
8250 :
8251 48 : CASE_INT_FN (BUILT_IN_CTZ):
8252 48 : target = expand_builtin_unop (target_mode, exp, target,
8253 : subtarget, ctz_optab);
8254 48 : if (target)
8255 : return target;
8256 : break;
8257 :
8258 91 : CASE_INT_FN (BUILT_IN_CLRSB):
8259 91 : target = expand_builtin_unop (target_mode, exp, target,
8260 : subtarget, clrsb_optab);
8261 91 : if (target)
8262 : return target;
8263 : break;
8264 :
8265 453 : CASE_INT_FN (BUILT_IN_POPCOUNT):
8266 453 : target = expand_builtin_unop (target_mode, exp, target,
8267 : subtarget, popcount_optab);
8268 453 : if (target)
8269 : return target;
8270 : break;
8271 :
8272 11 : CASE_INT_FN (BUILT_IN_PARITY):
8273 11 : target = expand_builtin_unop (target_mode, exp, target,
8274 : subtarget, parity_optab);
8275 11 : if (target)
8276 : return target;
8277 : break;
8278 :
8279 14752 : case BUILT_IN_STRLEN:
8280 14752 : target = expand_builtin_strlen (exp, target, target_mode);
8281 14752 : if (target)
8282 : return target;
8283 : break;
8284 :
8285 580 : case BUILT_IN_STRNLEN:
8286 580 : target = expand_builtin_strnlen (exp, target, target_mode);
8287 580 : if (target)
8288 : return target;
8289 : break;
8290 :
8291 1860 : case BUILT_IN_STRCPY:
8292 1860 : target = expand_builtin_strcpy (exp, target);
8293 1860 : if (target)
8294 : return target;
8295 : break;
8296 :
8297 2177 : case BUILT_IN_STRNCPY:
8298 2177 : target = expand_builtin_strncpy (exp, target);
8299 2177 : if (target)
8300 : return target;
8301 : break;
8302 :
8303 454 : case BUILT_IN_STPCPY:
8304 454 : target = expand_builtin_stpcpy (exp, target, mode);
8305 454 : if (target)
8306 : return target;
8307 : break;
8308 :
8309 110102 : case BUILT_IN_MEMCPY:
8310 110102 : target = expand_builtin_memcpy (exp, target);
8311 110102 : if (target)
8312 : return target;
8313 : break;
8314 :
8315 17646 : case BUILT_IN_MEMMOVE:
8316 17646 : target = expand_builtin_memmove (exp, target);
8317 17646 : if (target)
8318 : return target;
8319 : break;
8320 :
8321 1395 : case BUILT_IN_MEMPCPY:
8322 1395 : target = expand_builtin_mempcpy (exp, target);
8323 1395 : if (target)
8324 : return target;
8325 : break;
8326 :
8327 36908 : case BUILT_IN_MEMSET:
8328 36908 : target = expand_builtin_memset (exp, target, mode);
8329 36908 : if (target)
8330 : return target;
8331 : break;
8332 :
8333 0 : case BUILT_IN_BZERO:
8334 0 : target = expand_builtin_bzero (exp);
8335 0 : if (target)
8336 : return target;
8337 : break;
8338 :
8339 : /* Expand it as BUILT_IN_MEMCMP_EQ first. If not successful, change it
8340 : back to a BUILT_IN_STRCMP. Remember to delete the 3rd parameter
8341 : when changing it to a strcmp call. */
8342 371 : case BUILT_IN_STRCMP_EQ:
8343 371 : target = expand_builtin_memcmp (exp, target, true);
8344 371 : if (target)
8345 : return target;
8346 :
8347 : /* Change this call back to a BUILT_IN_STRCMP. */
8348 25 : TREE_OPERAND (exp, 1)
8349 25 : = build_fold_addr_expr (builtin_decl_explicit (BUILT_IN_STRCMP));
8350 :
8351 : /* Delete the last parameter. */
8352 25 : unsigned int i;
8353 25 : vec<tree, va_gc> *arg_vec;
8354 25 : vec_alloc (arg_vec, 2);
8355 100 : for (i = 0; i < 2; i++)
8356 50 : arg_vec->quick_push (CALL_EXPR_ARG (exp, i));
8357 25 : exp = build_call_vec (TREE_TYPE (exp), CALL_EXPR_FN (exp), arg_vec);
8358 : /* FALLTHROUGH */
8359 :
8360 127960 : case BUILT_IN_STRCMP:
8361 127960 : target = expand_builtin_strcmp (exp, target);
8362 127960 : if (target)
8363 : return target;
8364 : break;
8365 :
8366 : /* Expand it as BUILT_IN_MEMCMP_EQ first. If not successful, change it
8367 : back to a BUILT_IN_STRNCMP. */
8368 38 : case BUILT_IN_STRNCMP_EQ:
8369 38 : target = expand_builtin_memcmp (exp, target, true);
8370 38 : if (target)
8371 : return target;
8372 :
8373 : /* Change it back to a BUILT_IN_STRNCMP. */
8374 0 : TREE_OPERAND (exp, 1)
8375 0 : = build_fold_addr_expr (builtin_decl_explicit (BUILT_IN_STRNCMP));
8376 : /* FALLTHROUGH */
8377 :
8378 2027 : case BUILT_IN_STRNCMP:
8379 2027 : target = expand_builtin_strncmp (exp, target, mode);
8380 2027 : if (target)
8381 : return target;
8382 : break;
8383 :
8384 106850 : case BUILT_IN_BCMP:
8385 106850 : case BUILT_IN_MEMCMP:
8386 106850 : case BUILT_IN_MEMCMP_EQ:
8387 106850 : target = expand_builtin_memcmp (exp, target, fcode == BUILT_IN_MEMCMP_EQ);
8388 106850 : if (target)
8389 : return target;
8390 38214 : if (fcode == BUILT_IN_MEMCMP_EQ)
8391 : {
8392 23286 : tree newdecl = builtin_decl_explicit (BUILT_IN_MEMCMP);
8393 23286 : TREE_OPERAND (exp, 1) = build_fold_addr_expr (newdecl);
8394 : }
8395 : break;
8396 :
8397 0 : case BUILT_IN_SETJMP:
8398 : /* This should have been lowered to the builtins below. */
8399 0 : gcc_unreachable ();
8400 :
8401 842 : case BUILT_IN_SETJMP_SETUP:
8402 : /* __builtin_setjmp_setup is passed a pointer to an array of five words
8403 : and the receiver label. */
8404 842 : if (validate_arglist (exp, POINTER_TYPE, POINTER_TYPE, VOID_TYPE))
8405 : {
8406 842 : rtx buf_addr = expand_expr (CALL_EXPR_ARG (exp, 0), subtarget,
8407 : VOIDmode, EXPAND_NORMAL);
8408 842 : tree label = TREE_OPERAND (CALL_EXPR_ARG (exp, 1), 0);
8409 842 : rtx_insn *label_r = label_rtx (label);
8410 :
8411 842 : expand_builtin_setjmp_setup (buf_addr, label_r);
8412 842 : return const0_rtx;
8413 : }
8414 : break;
8415 :
8416 842 : case BUILT_IN_SETJMP_RECEIVER:
8417 : /* __builtin_setjmp_receiver is passed the receiver label. */
8418 842 : if (validate_arglist (exp, POINTER_TYPE, VOID_TYPE))
8419 : {
8420 842 : tree label = TREE_OPERAND (CALL_EXPR_ARG (exp, 0), 0);
8421 842 : rtx_insn *label_r = label_rtx (label);
8422 :
8423 842 : expand_builtin_setjmp_receiver (label_r);
8424 842 : nonlocal_goto_handler_labels
8425 1684 : = gen_rtx_INSN_LIST (VOIDmode, label_r,
8426 842 : nonlocal_goto_handler_labels);
8427 : /* ??? Do not let expand_label treat us as such since we would
8428 : not want to be both on the list of non-local labels and on
8429 : the list of forced labels. */
8430 842 : FORCED_LABEL (label) = 0;
8431 842 : return const0_rtx;
8432 : }
8433 : break;
8434 :
8435 : /* __builtin_longjmp is passed a pointer to an array of five words.
8436 : It's similar to the C library longjmp function but works with
8437 : __builtin_setjmp above. */
8438 392 : case BUILT_IN_LONGJMP:
8439 392 : if (validate_arglist (exp, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
8440 : {
8441 392 : rtx buf_addr = expand_expr (CALL_EXPR_ARG (exp, 0), subtarget,
8442 : VOIDmode, EXPAND_NORMAL);
8443 392 : rtx value = expand_normal (CALL_EXPR_ARG (exp, 1));
8444 :
8445 392 : if (value != const1_rtx)
8446 : {
8447 0 : error ("%<__builtin_longjmp%> second argument must be 1");
8448 0 : return const0_rtx;
8449 : }
8450 :
8451 392 : expand_builtin_longjmp (buf_addr, value);
8452 392 : return const0_rtx;
8453 : }
8454 : break;
8455 :
8456 512 : case BUILT_IN_NONLOCAL_GOTO:
8457 512 : target = expand_builtin_nonlocal_goto (exp);
8458 512 : if (target)
8459 : return target;
8460 : break;
8461 :
8462 : /* This updates the setjmp buffer that is its argument with the value
8463 : of the current stack pointer. */
8464 0 : case BUILT_IN_UPDATE_SETJMP_BUF:
8465 0 : if (validate_arglist (exp, POINTER_TYPE, VOID_TYPE))
8466 : {
8467 0 : rtx buf_addr
8468 0 : = expand_normal (CALL_EXPR_ARG (exp, 0));
8469 :
8470 0 : expand_builtin_update_setjmp_buf (buf_addr);
8471 0 : return const0_rtx;
8472 : }
8473 : break;
8474 :
8475 38759 : case BUILT_IN_TRAP:
8476 38759 : case BUILT_IN_UNREACHABLE_TRAP:
8477 38759 : expand_builtin_trap ();
8478 38759 : return const0_rtx;
8479 :
8480 2641 : case BUILT_IN_UNREACHABLE:
8481 2641 : expand_builtin_unreachable ();
8482 2641 : return const0_rtx;
8483 :
8484 408 : case BUILT_IN_OBSERVABLE_CHKPT:
8485 : /* Generate no code. */
8486 408 : return const0_rtx;
8487 :
8488 1380 : CASE_FLT_FN (BUILT_IN_SIGNBIT):
8489 1380 : case BUILT_IN_SIGNBITD32:
8490 1380 : case BUILT_IN_SIGNBITD64:
8491 1380 : case BUILT_IN_SIGNBITD128:
8492 1380 : target = expand_builtin_signbit (exp, target);
8493 1380 : if (target)
8494 : return target;
8495 : break;
8496 :
8497 : /* Various hooks for the DWARF 2 __throw routine. */
8498 34 : case BUILT_IN_UNWIND_INIT:
8499 34 : expand_builtin_unwind_init ();
8500 34 : return const0_rtx;
8501 1224 : case BUILT_IN_DWARF_CFA:
8502 1224 : return virtual_cfa_rtx;
8503 : #ifdef DWARF2_UNWIND_INFO
8504 48 : case BUILT_IN_DWARF_SP_COLUMN:
8505 48 : return expand_builtin_dwarf_sp_column ();
8506 8 : case BUILT_IN_INIT_DWARF_REG_SIZES:
8507 8 : expand_builtin_init_dwarf_reg_sizes (CALL_EXPR_ARG (exp, 0));
8508 8 : return const0_rtx;
8509 : #endif
8510 19 : case BUILT_IN_FROB_RETURN_ADDR:
8511 19 : return expand_builtin_frob_return_addr (CALL_EXPR_ARG (exp, 0));
8512 2352 : case BUILT_IN_EXTRACT_RETURN_ADDR:
8513 2352 : return expand_builtin_extract_return_addr (CALL_EXPR_ARG (exp, 0));
8514 29 : case BUILT_IN_EH_RETURN:
8515 58 : expand_builtin_eh_return (CALL_EXPR_ARG (exp, 0),
8516 29 : CALL_EXPR_ARG (exp, 1));
8517 29 : return const0_rtx;
8518 21 : case BUILT_IN_EH_RETURN_DATA_REGNO:
8519 21 : return expand_builtin_eh_return_data_regno (exp);
8520 2 : case BUILT_IN_EXTEND_POINTER:
8521 2 : return expand_builtin_extend_pointer (CALL_EXPR_ARG (exp, 0));
8522 106012 : case BUILT_IN_EH_POINTER:
8523 106012 : return expand_builtin_eh_pointer (exp);
8524 6187 : case BUILT_IN_EH_FILTER:
8525 6187 : return expand_builtin_eh_filter (exp);
8526 107596 : case BUILT_IN_EH_COPY_VALUES:
8527 107596 : return expand_builtin_eh_copy_values (exp);
8528 :
8529 21087 : case BUILT_IN_VA_START:
8530 21087 : return expand_builtin_va_start (exp);
8531 12162 : case BUILT_IN_VA_END:
8532 12162 : return expand_builtin_va_end (exp);
8533 240 : case BUILT_IN_VA_COPY:
8534 240 : return expand_builtin_va_copy (exp);
8535 1407 : case BUILT_IN_EXPECT:
8536 1407 : return expand_builtin_expect (exp, target);
8537 5 : case BUILT_IN_EXPECT_WITH_PROBABILITY:
8538 5 : return expand_builtin_expect_with_probability (exp, target);
8539 662 : case BUILT_IN_ASSUME_ALIGNED:
8540 662 : return expand_builtin_assume_aligned (exp, target);
8541 2058 : case BUILT_IN_PREFETCH:
8542 2058 : expand_builtin_prefetch (exp);
8543 2058 : return const0_rtx;
8544 :
8545 306 : case BUILT_IN_INIT_TRAMPOLINE:
8546 306 : return expand_builtin_init_trampoline (exp, true);
8547 0 : case BUILT_IN_INIT_HEAP_TRAMPOLINE:
8548 0 : return expand_builtin_init_trampoline (exp, false);
8549 353 : case BUILT_IN_ADJUST_TRAMPOLINE:
8550 353 : return expand_builtin_adjust_trampoline (exp);
8551 :
8552 0 : case BUILT_IN_INIT_DESCRIPTOR:
8553 0 : return expand_builtin_init_descriptor (exp);
8554 0 : case BUILT_IN_ADJUST_DESCRIPTOR:
8555 0 : return expand_builtin_adjust_descriptor (exp);
8556 :
8557 : case BUILT_IN_GCC_NESTED_PTR_CREATED:
8558 : case BUILT_IN_GCC_NESTED_PTR_DELETED:
8559 : break; /* At present, no expansion, just call the function. */
8560 :
8561 109 : case BUILT_IN_FORK:
8562 109 : case BUILT_IN_EXECL:
8563 109 : case BUILT_IN_EXECV:
8564 109 : case BUILT_IN_EXECLP:
8565 109 : case BUILT_IN_EXECLE:
8566 109 : case BUILT_IN_EXECVP:
8567 109 : case BUILT_IN_EXECVE:
8568 109 : target = expand_builtin_fork_or_exec (fndecl, exp, target, ignore);
8569 109 : if (target)
8570 : return target;
8571 : break;
8572 :
8573 712 : case BUILT_IN_SYNC_FETCH_AND_ADD_1:
8574 712 : case BUILT_IN_SYNC_FETCH_AND_ADD_2:
8575 712 : case BUILT_IN_SYNC_FETCH_AND_ADD_4:
8576 712 : case BUILT_IN_SYNC_FETCH_AND_ADD_8:
8577 712 : case BUILT_IN_SYNC_FETCH_AND_ADD_16:
8578 712 : mode = get_builtin_sync_mode (fcode - BUILT_IN_SYNC_FETCH_AND_ADD_1);
8579 712 : target = expand_builtin_sync_operation (mode, exp, PLUS, false, target);
8580 712 : if (target)
8581 : return target;
8582 : break;
8583 :
8584 585 : case BUILT_IN_SYNC_FETCH_AND_SUB_1:
8585 585 : case BUILT_IN_SYNC_FETCH_AND_SUB_2:
8586 585 : case BUILT_IN_SYNC_FETCH_AND_SUB_4:
8587 585 : case BUILT_IN_SYNC_FETCH_AND_SUB_8:
8588 585 : case BUILT_IN_SYNC_FETCH_AND_SUB_16:
8589 585 : mode = get_builtin_sync_mode (fcode - BUILT_IN_SYNC_FETCH_AND_SUB_1);
8590 585 : target = expand_builtin_sync_operation (mode, exp, MINUS, false, target);
8591 585 : if (target)
8592 : return target;
8593 : break;
8594 :
8595 512 : case BUILT_IN_SYNC_FETCH_AND_OR_1:
8596 512 : case BUILT_IN_SYNC_FETCH_AND_OR_2:
8597 512 : case BUILT_IN_SYNC_FETCH_AND_OR_4:
8598 512 : case BUILT_IN_SYNC_FETCH_AND_OR_8:
8599 512 : case BUILT_IN_SYNC_FETCH_AND_OR_16:
8600 512 : mode = get_builtin_sync_mode (fcode - BUILT_IN_SYNC_FETCH_AND_OR_1);
8601 512 : target = expand_builtin_sync_operation (mode, exp, IOR, false, target);
8602 512 : if (target)
8603 : return target;
8604 : break;
8605 :
8606 488 : case BUILT_IN_SYNC_FETCH_AND_AND_1:
8607 488 : case BUILT_IN_SYNC_FETCH_AND_AND_2:
8608 488 : case BUILT_IN_SYNC_FETCH_AND_AND_4:
8609 488 : case BUILT_IN_SYNC_FETCH_AND_AND_8:
8610 488 : case BUILT_IN_SYNC_FETCH_AND_AND_16:
8611 488 : mode = get_builtin_sync_mode (fcode - BUILT_IN_SYNC_FETCH_AND_AND_1);
8612 488 : target = expand_builtin_sync_operation (mode, exp, AND, false, target);
8613 488 : if (target)
8614 : return target;
8615 : break;
8616 :
8617 581 : case BUILT_IN_SYNC_FETCH_AND_XOR_1:
8618 581 : case BUILT_IN_SYNC_FETCH_AND_XOR_2:
8619 581 : case BUILT_IN_SYNC_FETCH_AND_XOR_4:
8620 581 : case BUILT_IN_SYNC_FETCH_AND_XOR_8:
8621 581 : case BUILT_IN_SYNC_FETCH_AND_XOR_16:
8622 581 : mode = get_builtin_sync_mode (fcode - BUILT_IN_SYNC_FETCH_AND_XOR_1);
8623 581 : target = expand_builtin_sync_operation (mode, exp, XOR, false, target);
8624 581 : if (target)
8625 : return target;
8626 : break;
8627 :
8628 434 : case BUILT_IN_SYNC_FETCH_AND_NAND_1:
8629 434 : case BUILT_IN_SYNC_FETCH_AND_NAND_2:
8630 434 : case BUILT_IN_SYNC_FETCH_AND_NAND_4:
8631 434 : case BUILT_IN_SYNC_FETCH_AND_NAND_8:
8632 434 : case BUILT_IN_SYNC_FETCH_AND_NAND_16:
8633 434 : mode = get_builtin_sync_mode (fcode - BUILT_IN_SYNC_FETCH_AND_NAND_1);
8634 434 : target = expand_builtin_sync_operation (mode, exp, NOT, false, target);
8635 434 : if (target)
8636 : return target;
8637 : break;
8638 :
8639 161 : case BUILT_IN_SYNC_ADD_AND_FETCH_1:
8640 161 : case BUILT_IN_SYNC_ADD_AND_FETCH_2:
8641 161 : case BUILT_IN_SYNC_ADD_AND_FETCH_4:
8642 161 : case BUILT_IN_SYNC_ADD_AND_FETCH_8:
8643 161 : case BUILT_IN_SYNC_ADD_AND_FETCH_16:
8644 161 : mode = get_builtin_sync_mode (fcode - BUILT_IN_SYNC_ADD_AND_FETCH_1);
8645 161 : target = expand_builtin_sync_operation (mode, exp, PLUS, true, target);
8646 161 : if (target)
8647 : return target;
8648 : break;
8649 :
8650 121 : case BUILT_IN_SYNC_SUB_AND_FETCH_1:
8651 121 : case BUILT_IN_SYNC_SUB_AND_FETCH_2:
8652 121 : case BUILT_IN_SYNC_SUB_AND_FETCH_4:
8653 121 : case BUILT_IN_SYNC_SUB_AND_FETCH_8:
8654 121 : case BUILT_IN_SYNC_SUB_AND_FETCH_16:
8655 121 : mode = get_builtin_sync_mode (fcode - BUILT_IN_SYNC_SUB_AND_FETCH_1);
8656 121 : target = expand_builtin_sync_operation (mode, exp, MINUS, true, target);
8657 121 : if (target)
8658 : return target;
8659 : break;
8660 :
8661 115 : case BUILT_IN_SYNC_OR_AND_FETCH_1:
8662 115 : case BUILT_IN_SYNC_OR_AND_FETCH_2:
8663 115 : case BUILT_IN_SYNC_OR_AND_FETCH_4:
8664 115 : case BUILT_IN_SYNC_OR_AND_FETCH_8:
8665 115 : case BUILT_IN_SYNC_OR_AND_FETCH_16:
8666 115 : mode = get_builtin_sync_mode (fcode - BUILT_IN_SYNC_OR_AND_FETCH_1);
8667 115 : target = expand_builtin_sync_operation (mode, exp, IOR, true, target);
8668 115 : if (target)
8669 : return target;
8670 : break;
8671 :
8672 116 : case BUILT_IN_SYNC_AND_AND_FETCH_1:
8673 116 : case BUILT_IN_SYNC_AND_AND_FETCH_2:
8674 116 : case BUILT_IN_SYNC_AND_AND_FETCH_4:
8675 116 : case BUILT_IN_SYNC_AND_AND_FETCH_8:
8676 116 : case BUILT_IN_SYNC_AND_AND_FETCH_16:
8677 116 : mode = get_builtin_sync_mode (fcode - BUILT_IN_SYNC_AND_AND_FETCH_1);
8678 116 : target = expand_builtin_sync_operation (mode, exp, AND, true, target);
8679 116 : if (target)
8680 : return target;
8681 : break;
8682 :
8683 114 : case BUILT_IN_SYNC_XOR_AND_FETCH_1:
8684 114 : case BUILT_IN_SYNC_XOR_AND_FETCH_2:
8685 114 : case BUILT_IN_SYNC_XOR_AND_FETCH_4:
8686 114 : case BUILT_IN_SYNC_XOR_AND_FETCH_8:
8687 114 : case BUILT_IN_SYNC_XOR_AND_FETCH_16:
8688 114 : mode = get_builtin_sync_mode (fcode - BUILT_IN_SYNC_XOR_AND_FETCH_1);
8689 114 : target = expand_builtin_sync_operation (mode, exp, XOR, true, target);
8690 114 : if (target)
8691 : return target;
8692 : break;
8693 :
8694 89 : case BUILT_IN_SYNC_NAND_AND_FETCH_1:
8695 89 : case BUILT_IN_SYNC_NAND_AND_FETCH_2:
8696 89 : case BUILT_IN_SYNC_NAND_AND_FETCH_4:
8697 89 : case BUILT_IN_SYNC_NAND_AND_FETCH_8:
8698 89 : case BUILT_IN_SYNC_NAND_AND_FETCH_16:
8699 89 : mode = get_builtin_sync_mode (fcode - BUILT_IN_SYNC_NAND_AND_FETCH_1);
8700 89 : target = expand_builtin_sync_operation (mode, exp, NOT, true, target);
8701 89 : if (target)
8702 : return target;
8703 : break;
8704 :
8705 204 : case BUILT_IN_SYNC_BOOL_COMPARE_AND_SWAP_1:
8706 204 : case BUILT_IN_SYNC_BOOL_COMPARE_AND_SWAP_2:
8707 204 : case BUILT_IN_SYNC_BOOL_COMPARE_AND_SWAP_4:
8708 204 : case BUILT_IN_SYNC_BOOL_COMPARE_AND_SWAP_8:
8709 204 : case BUILT_IN_SYNC_BOOL_COMPARE_AND_SWAP_16:
8710 204 : if (mode == VOIDmode)
8711 40 : mode = TYPE_MODE (boolean_type_node);
8712 204 : if (!target || !register_operand (target, mode))
8713 40 : target = gen_reg_rtx (mode);
8714 :
8715 204 : mode = get_builtin_sync_mode
8716 204 : (fcode - BUILT_IN_SYNC_BOOL_COMPARE_AND_SWAP_1);
8717 204 : target = expand_builtin_compare_and_swap (mode, exp, true, target);
8718 204 : if (target)
8719 : return target;
8720 : break;
8721 :
8722 256 : case BUILT_IN_SYNC_VAL_COMPARE_AND_SWAP_1:
8723 256 : case BUILT_IN_SYNC_VAL_COMPARE_AND_SWAP_2:
8724 256 : case BUILT_IN_SYNC_VAL_COMPARE_AND_SWAP_4:
8725 256 : case BUILT_IN_SYNC_VAL_COMPARE_AND_SWAP_8:
8726 256 : case BUILT_IN_SYNC_VAL_COMPARE_AND_SWAP_16:
8727 256 : mode = get_builtin_sync_mode
8728 256 : (fcode - BUILT_IN_SYNC_VAL_COMPARE_AND_SWAP_1);
8729 256 : target = expand_builtin_compare_and_swap (mode, exp, false, target);
8730 256 : if (target)
8731 : return target;
8732 : break;
8733 :
8734 326 : case BUILT_IN_SYNC_LOCK_TEST_AND_SET_1:
8735 326 : case BUILT_IN_SYNC_LOCK_TEST_AND_SET_2:
8736 326 : case BUILT_IN_SYNC_LOCK_TEST_AND_SET_4:
8737 326 : case BUILT_IN_SYNC_LOCK_TEST_AND_SET_8:
8738 326 : case BUILT_IN_SYNC_LOCK_TEST_AND_SET_16:
8739 326 : mode = get_builtin_sync_mode (fcode - BUILT_IN_SYNC_LOCK_TEST_AND_SET_1);
8740 326 : target = expand_builtin_sync_lock_test_and_set (mode, exp, target);
8741 326 : if (target)
8742 : return target;
8743 : break;
8744 :
8745 146 : case BUILT_IN_SYNC_LOCK_RELEASE_1:
8746 146 : case BUILT_IN_SYNC_LOCK_RELEASE_2:
8747 146 : case BUILT_IN_SYNC_LOCK_RELEASE_4:
8748 146 : case BUILT_IN_SYNC_LOCK_RELEASE_8:
8749 146 : case BUILT_IN_SYNC_LOCK_RELEASE_16:
8750 146 : mode = get_builtin_sync_mode (fcode - BUILT_IN_SYNC_LOCK_RELEASE_1);
8751 146 : if (expand_builtin_sync_lock_release (mode, exp))
8752 144 : return const0_rtx;
8753 : break;
8754 :
8755 275 : case BUILT_IN_SYNC_SYNCHRONIZE:
8756 275 : expand_builtin_sync_synchronize ();
8757 275 : return const0_rtx;
8758 :
8759 2937 : case BUILT_IN_ATOMIC_EXCHANGE_1:
8760 2937 : case BUILT_IN_ATOMIC_EXCHANGE_2:
8761 2937 : case BUILT_IN_ATOMIC_EXCHANGE_4:
8762 2937 : case BUILT_IN_ATOMIC_EXCHANGE_8:
8763 2937 : case BUILT_IN_ATOMIC_EXCHANGE_16:
8764 2937 : mode = get_builtin_sync_mode (fcode - BUILT_IN_ATOMIC_EXCHANGE_1);
8765 2937 : target = expand_builtin_atomic_exchange (mode, exp, target);
8766 2937 : if (target)
8767 : return target;
8768 : break;
8769 :
8770 9131 : case BUILT_IN_ATOMIC_COMPARE_EXCHANGE_1:
8771 9131 : case BUILT_IN_ATOMIC_COMPARE_EXCHANGE_2:
8772 9131 : case BUILT_IN_ATOMIC_COMPARE_EXCHANGE_4:
8773 9131 : case BUILT_IN_ATOMIC_COMPARE_EXCHANGE_8:
8774 9131 : case BUILT_IN_ATOMIC_COMPARE_EXCHANGE_16:
8775 9131 : {
8776 9131 : unsigned int nargs, z;
8777 9131 : vec<tree, va_gc> *vec;
8778 :
8779 9131 : mode =
8780 9131 : get_builtin_sync_mode (fcode - BUILT_IN_ATOMIC_COMPARE_EXCHANGE_1);
8781 9131 : target = expand_builtin_atomic_compare_exchange (mode, exp, target);
8782 9131 : if (target)
8783 7331 : return target;
8784 :
8785 : /* If this is turned into an external library call, the weak parameter
8786 : must be dropped to match the expected parameter list. */
8787 1800 : nargs = call_expr_nargs (exp);
8788 1800 : vec_alloc (vec, nargs - 1);
8789 9000 : for (z = 0; z < 3; z++)
8790 5400 : vec->quick_push (CALL_EXPR_ARG (exp, z));
8791 : /* Skip the boolean weak parameter. */
8792 5400 : for (z = 4; z < 6; z++)
8793 3600 : vec->quick_push (CALL_EXPR_ARG (exp, z));
8794 1800 : exp = build_call_vec (TREE_TYPE (exp), CALL_EXPR_FN (exp), vec);
8795 1800 : break;
8796 : }
8797 :
8798 70962 : case BUILT_IN_ATOMIC_LOAD_1:
8799 70962 : case BUILT_IN_ATOMIC_LOAD_2:
8800 70962 : case BUILT_IN_ATOMIC_LOAD_4:
8801 70962 : case BUILT_IN_ATOMIC_LOAD_8:
8802 70962 : case BUILT_IN_ATOMIC_LOAD_16:
8803 70962 : mode = get_builtin_sync_mode (fcode - BUILT_IN_ATOMIC_LOAD_1);
8804 70962 : target = expand_builtin_atomic_load (mode, exp, target);
8805 70962 : if (target)
8806 : return target;
8807 : break;
8808 :
8809 17481 : case BUILT_IN_ATOMIC_STORE_1:
8810 17481 : case BUILT_IN_ATOMIC_STORE_2:
8811 17481 : case BUILT_IN_ATOMIC_STORE_4:
8812 17481 : case BUILT_IN_ATOMIC_STORE_8:
8813 17481 : case BUILT_IN_ATOMIC_STORE_16:
8814 17481 : mode = get_builtin_sync_mode (fcode - BUILT_IN_ATOMIC_STORE_1);
8815 17481 : target = expand_builtin_atomic_store (mode, exp);
8816 17481 : if (target)
8817 15849 : return const0_rtx;
8818 : break;
8819 :
8820 4394 : case BUILT_IN_ATOMIC_ADD_FETCH_1:
8821 4394 : case BUILT_IN_ATOMIC_ADD_FETCH_2:
8822 4394 : case BUILT_IN_ATOMIC_ADD_FETCH_4:
8823 4394 : case BUILT_IN_ATOMIC_ADD_FETCH_8:
8824 4394 : case BUILT_IN_ATOMIC_ADD_FETCH_16:
8825 4394 : {
8826 4394 : enum built_in_function lib;
8827 4394 : mode = get_builtin_sync_mode (fcode - BUILT_IN_ATOMIC_ADD_FETCH_1);
8828 4394 : lib = (enum built_in_function)((int)BUILT_IN_ATOMIC_FETCH_ADD_1 +
8829 : (fcode - BUILT_IN_ATOMIC_ADD_FETCH_1));
8830 4394 : target = expand_builtin_atomic_fetch_op (mode, exp, target, PLUS, true,
8831 : ignore, lib);
8832 4394 : if (target)
8833 : return target;
8834 : break;
8835 : }
8836 2172 : case BUILT_IN_ATOMIC_SUB_FETCH_1:
8837 2172 : case BUILT_IN_ATOMIC_SUB_FETCH_2:
8838 2172 : case BUILT_IN_ATOMIC_SUB_FETCH_4:
8839 2172 : case BUILT_IN_ATOMIC_SUB_FETCH_8:
8840 2172 : case BUILT_IN_ATOMIC_SUB_FETCH_16:
8841 2172 : {
8842 2172 : enum built_in_function lib;
8843 2172 : mode = get_builtin_sync_mode (fcode - BUILT_IN_ATOMIC_SUB_FETCH_1);
8844 2172 : lib = (enum built_in_function)((int)BUILT_IN_ATOMIC_FETCH_SUB_1 +
8845 : (fcode - BUILT_IN_ATOMIC_SUB_FETCH_1));
8846 2172 : target = expand_builtin_atomic_fetch_op (mode, exp, target, MINUS, true,
8847 : ignore, lib);
8848 2172 : if (target)
8849 : return target;
8850 : break;
8851 : }
8852 902 : case BUILT_IN_ATOMIC_AND_FETCH_1:
8853 902 : case BUILT_IN_ATOMIC_AND_FETCH_2:
8854 902 : case BUILT_IN_ATOMIC_AND_FETCH_4:
8855 902 : case BUILT_IN_ATOMIC_AND_FETCH_8:
8856 902 : case BUILT_IN_ATOMIC_AND_FETCH_16:
8857 902 : {
8858 902 : enum built_in_function lib;
8859 902 : mode = get_builtin_sync_mode (fcode - BUILT_IN_ATOMIC_AND_FETCH_1);
8860 902 : lib = (enum built_in_function)((int)BUILT_IN_ATOMIC_FETCH_AND_1 +
8861 : (fcode - BUILT_IN_ATOMIC_AND_FETCH_1));
8862 902 : target = expand_builtin_atomic_fetch_op (mode, exp, target, AND, true,
8863 : ignore, lib);
8864 902 : if (target)
8865 : return target;
8866 : break;
8867 : }
8868 162 : case BUILT_IN_ATOMIC_NAND_FETCH_1:
8869 162 : case BUILT_IN_ATOMIC_NAND_FETCH_2:
8870 162 : case BUILT_IN_ATOMIC_NAND_FETCH_4:
8871 162 : case BUILT_IN_ATOMIC_NAND_FETCH_8:
8872 162 : case BUILT_IN_ATOMIC_NAND_FETCH_16:
8873 162 : {
8874 162 : enum built_in_function lib;
8875 162 : mode = get_builtin_sync_mode (fcode - BUILT_IN_ATOMIC_NAND_FETCH_1);
8876 162 : lib = (enum built_in_function)((int)BUILT_IN_ATOMIC_FETCH_NAND_1 +
8877 : (fcode - BUILT_IN_ATOMIC_NAND_FETCH_1));
8878 162 : target = expand_builtin_atomic_fetch_op (mode, exp, target, NOT, true,
8879 : ignore, lib);
8880 162 : if (target)
8881 : return target;
8882 : break;
8883 : }
8884 847 : case BUILT_IN_ATOMIC_XOR_FETCH_1:
8885 847 : case BUILT_IN_ATOMIC_XOR_FETCH_2:
8886 847 : case BUILT_IN_ATOMIC_XOR_FETCH_4:
8887 847 : case BUILT_IN_ATOMIC_XOR_FETCH_8:
8888 847 : case BUILT_IN_ATOMIC_XOR_FETCH_16:
8889 847 : {
8890 847 : enum built_in_function lib;
8891 847 : mode = get_builtin_sync_mode (fcode - BUILT_IN_ATOMIC_XOR_FETCH_1);
8892 847 : lib = (enum built_in_function)((int)BUILT_IN_ATOMIC_FETCH_XOR_1 +
8893 : (fcode - BUILT_IN_ATOMIC_XOR_FETCH_1));
8894 847 : target = expand_builtin_atomic_fetch_op (mode, exp, target, XOR, true,
8895 : ignore, lib);
8896 847 : if (target)
8897 : return target;
8898 : break;
8899 : }
8900 965 : case BUILT_IN_ATOMIC_OR_FETCH_1:
8901 965 : case BUILT_IN_ATOMIC_OR_FETCH_2:
8902 965 : case BUILT_IN_ATOMIC_OR_FETCH_4:
8903 965 : case BUILT_IN_ATOMIC_OR_FETCH_8:
8904 965 : case BUILT_IN_ATOMIC_OR_FETCH_16:
8905 965 : {
8906 965 : enum built_in_function lib;
8907 965 : mode = get_builtin_sync_mode (fcode - BUILT_IN_ATOMIC_OR_FETCH_1);
8908 965 : lib = (enum built_in_function)((int)BUILT_IN_ATOMIC_FETCH_OR_1 +
8909 : (fcode - BUILT_IN_ATOMIC_OR_FETCH_1));
8910 965 : target = expand_builtin_atomic_fetch_op (mode, exp, target, IOR, true,
8911 : ignore, lib);
8912 965 : if (target)
8913 : return target;
8914 : break;
8915 : }
8916 14572 : case BUILT_IN_ATOMIC_FETCH_ADD_1:
8917 14572 : case BUILT_IN_ATOMIC_FETCH_ADD_2:
8918 14572 : case BUILT_IN_ATOMIC_FETCH_ADD_4:
8919 14572 : case BUILT_IN_ATOMIC_FETCH_ADD_8:
8920 14572 : case BUILT_IN_ATOMIC_FETCH_ADD_16:
8921 14572 : mode = get_builtin_sync_mode (fcode - BUILT_IN_ATOMIC_FETCH_ADD_1);
8922 14572 : target = expand_builtin_atomic_fetch_op (mode, exp, target, PLUS, false,
8923 : ignore, BUILT_IN_NONE);
8924 14572 : if (target)
8925 : return target;
8926 : break;
8927 :
8928 2107 : case BUILT_IN_ATOMIC_FETCH_SUB_1:
8929 2107 : case BUILT_IN_ATOMIC_FETCH_SUB_2:
8930 2107 : case BUILT_IN_ATOMIC_FETCH_SUB_4:
8931 2107 : case BUILT_IN_ATOMIC_FETCH_SUB_8:
8932 2107 : case BUILT_IN_ATOMIC_FETCH_SUB_16:
8933 2107 : mode = get_builtin_sync_mode (fcode - BUILT_IN_ATOMIC_FETCH_SUB_1);
8934 2107 : target = expand_builtin_atomic_fetch_op (mode, exp, target, MINUS, false,
8935 : ignore, BUILT_IN_NONE);
8936 2107 : if (target)
8937 : return target;
8938 : break;
8939 :
8940 785 : case BUILT_IN_ATOMIC_FETCH_AND_1:
8941 785 : case BUILT_IN_ATOMIC_FETCH_AND_2:
8942 785 : case BUILT_IN_ATOMIC_FETCH_AND_4:
8943 785 : case BUILT_IN_ATOMIC_FETCH_AND_8:
8944 785 : case BUILT_IN_ATOMIC_FETCH_AND_16:
8945 785 : mode = get_builtin_sync_mode (fcode - BUILT_IN_ATOMIC_FETCH_AND_1);
8946 785 : target = expand_builtin_atomic_fetch_op (mode, exp, target, AND, false,
8947 : ignore, BUILT_IN_NONE);
8948 785 : if (target)
8949 : return target;
8950 : break;
8951 :
8952 125 : case BUILT_IN_ATOMIC_FETCH_NAND_1:
8953 125 : case BUILT_IN_ATOMIC_FETCH_NAND_2:
8954 125 : case BUILT_IN_ATOMIC_FETCH_NAND_4:
8955 125 : case BUILT_IN_ATOMIC_FETCH_NAND_8:
8956 125 : case BUILT_IN_ATOMIC_FETCH_NAND_16:
8957 125 : mode = get_builtin_sync_mode (fcode - BUILT_IN_ATOMIC_FETCH_NAND_1);
8958 125 : target = expand_builtin_atomic_fetch_op (mode, exp, target, NOT, false,
8959 : ignore, BUILT_IN_NONE);
8960 125 : if (target)
8961 : return target;
8962 : break;
8963 :
8964 875 : case BUILT_IN_ATOMIC_FETCH_XOR_1:
8965 875 : case BUILT_IN_ATOMIC_FETCH_XOR_2:
8966 875 : case BUILT_IN_ATOMIC_FETCH_XOR_4:
8967 875 : case BUILT_IN_ATOMIC_FETCH_XOR_8:
8968 875 : case BUILT_IN_ATOMIC_FETCH_XOR_16:
8969 875 : mode = get_builtin_sync_mode (fcode - BUILT_IN_ATOMIC_FETCH_XOR_1);
8970 875 : target = expand_builtin_atomic_fetch_op (mode, exp, target, XOR, false,
8971 : ignore, BUILT_IN_NONE);
8972 875 : if (target)
8973 : return target;
8974 : break;
8975 :
8976 1140 : case BUILT_IN_ATOMIC_FETCH_OR_1:
8977 1140 : case BUILT_IN_ATOMIC_FETCH_OR_2:
8978 1140 : case BUILT_IN_ATOMIC_FETCH_OR_4:
8979 1140 : case BUILT_IN_ATOMIC_FETCH_OR_8:
8980 1140 : case BUILT_IN_ATOMIC_FETCH_OR_16:
8981 1140 : mode = get_builtin_sync_mode (fcode - BUILT_IN_ATOMIC_FETCH_OR_1);
8982 1140 : target = expand_builtin_atomic_fetch_op (mode, exp, target, IOR, false,
8983 : ignore, BUILT_IN_NONE);
8984 1140 : if (target)
8985 : return target;
8986 : break;
8987 :
8988 266 : case BUILT_IN_ATOMIC_TEST_AND_SET:
8989 266 : target = expand_builtin_atomic_test_and_set (exp, target);
8990 266 : if (target)
8991 : return target;
8992 : break;
8993 :
8994 53 : case BUILT_IN_ATOMIC_CLEAR:
8995 53 : return expand_builtin_atomic_clear (exp);
8996 :
8997 1 : case BUILT_IN_ATOMIC_ALWAYS_LOCK_FREE:
8998 1 : return expand_builtin_atomic_always_lock_free (exp);
8999 :
9000 10 : case BUILT_IN_ATOMIC_IS_LOCK_FREE:
9001 10 : target = expand_builtin_atomic_is_lock_free (exp);
9002 10 : if (target)
9003 : return target;
9004 : break;
9005 :
9006 703 : case BUILT_IN_ATOMIC_THREAD_FENCE:
9007 703 : expand_builtin_atomic_thread_fence (exp);
9008 703 : return const0_rtx;
9009 :
9010 60 : case BUILT_IN_ATOMIC_SIGNAL_FENCE:
9011 60 : expand_builtin_atomic_signal_fence (exp);
9012 60 : return const0_rtx;
9013 :
9014 620 : case BUILT_IN_OBJECT_SIZE:
9015 620 : case BUILT_IN_DYNAMIC_OBJECT_SIZE:
9016 620 : return expand_builtin_object_size (exp);
9017 :
9018 837 : case BUILT_IN_MEMCPY_CHK:
9019 837 : case BUILT_IN_MEMPCPY_CHK:
9020 837 : case BUILT_IN_MEMMOVE_CHK:
9021 837 : case BUILT_IN_MEMSET_CHK:
9022 837 : target = expand_builtin_memory_chk (exp, target, mode, fcode);
9023 837 : if (target)
9024 : return target;
9025 : break;
9026 :
9027 1086 : case BUILT_IN_STRCPY_CHK:
9028 1086 : case BUILT_IN_STPCPY_CHK:
9029 1086 : case BUILT_IN_STRNCPY_CHK:
9030 1086 : case BUILT_IN_STPNCPY_CHK:
9031 1086 : case BUILT_IN_STRCAT_CHK:
9032 1086 : case BUILT_IN_STRNCAT_CHK:
9033 1086 : case BUILT_IN_SNPRINTF_CHK:
9034 1086 : case BUILT_IN_VSNPRINTF_CHK:
9035 1086 : maybe_emit_chk_warning (exp, fcode);
9036 1086 : break;
9037 :
9038 1328 : case BUILT_IN_SPRINTF_CHK:
9039 1328 : case BUILT_IN_VSPRINTF_CHK:
9040 1328 : maybe_emit_sprintf_chk_warning (exp, fcode);
9041 1328 : break;
9042 :
9043 3 : case BUILT_IN_THREAD_POINTER:
9044 3 : return expand_builtin_thread_pointer (exp, target);
9045 :
9046 0 : case BUILT_IN_SET_THREAD_POINTER:
9047 0 : expand_builtin_set_thread_pointer (exp);
9048 0 : return const0_rtx;
9049 :
9050 : case BUILT_IN_ACC_ON_DEVICE:
9051 : /* Do library call, if we failed to expand the builtin when
9052 : folding. */
9053 : break;
9054 :
9055 356 : case BUILT_IN_GOACC_PARLEVEL_ID:
9056 356 : case BUILT_IN_GOACC_PARLEVEL_SIZE:
9057 356 : return expand_builtin_goacc_parlevel_id_size (exp, target, ignore);
9058 :
9059 4 : case BUILT_IN_SPECULATION_SAFE_VALUE_PTR:
9060 4 : return expand_speculation_safe_value (VOIDmode, exp, target, ignore);
9061 :
9062 31 : case BUILT_IN_SPECULATION_SAFE_VALUE_1:
9063 31 : case BUILT_IN_SPECULATION_SAFE_VALUE_2:
9064 31 : case BUILT_IN_SPECULATION_SAFE_VALUE_4:
9065 31 : case BUILT_IN_SPECULATION_SAFE_VALUE_8:
9066 31 : case BUILT_IN_SPECULATION_SAFE_VALUE_16:
9067 31 : mode = get_builtin_sync_mode (fcode - BUILT_IN_SPECULATION_SAFE_VALUE_1);
9068 31 : return expand_speculation_safe_value (mode, exp, target, ignore);
9069 :
9070 2 : case BUILT_IN_CRC8_DATA8:
9071 2 : return expand_builtin_crc_table_based (IFN_CRC, QImode, QImode, mode,
9072 : exp, target);
9073 2 : case BUILT_IN_CRC16_DATA8:
9074 2 : return expand_builtin_crc_table_based (IFN_CRC, HImode, QImode, mode,
9075 : exp, target);
9076 2 : case BUILT_IN_CRC16_DATA16:
9077 2 : return expand_builtin_crc_table_based (IFN_CRC, HImode, HImode, mode,
9078 : exp, target);
9079 2 : case BUILT_IN_CRC32_DATA8:
9080 2 : return expand_builtin_crc_table_based (IFN_CRC, SImode, QImode, mode,
9081 : exp, target);
9082 2 : case BUILT_IN_CRC32_DATA16:
9083 2 : return expand_builtin_crc_table_based (IFN_CRC, SImode, HImode, mode,
9084 : exp, target);
9085 14 : case BUILT_IN_CRC32_DATA32:
9086 14 : return expand_builtin_crc_table_based (IFN_CRC, SImode, SImode, mode,
9087 : exp, target);
9088 1 : case BUILT_IN_CRC64_DATA8:
9089 1 : return expand_builtin_crc_table_based (IFN_CRC, DImode, QImode, mode,
9090 : exp, target);
9091 1 : case BUILT_IN_CRC64_DATA16:
9092 1 : return expand_builtin_crc_table_based (IFN_CRC, DImode, HImode, mode,
9093 : exp, target);
9094 1 : case BUILT_IN_CRC64_DATA32:
9095 1 : return expand_builtin_crc_table_based (IFN_CRC, DImode, SImode, mode,
9096 : exp, target);
9097 1 : case BUILT_IN_CRC64_DATA64:
9098 1 : return expand_builtin_crc_table_based (IFN_CRC, DImode, DImode, mode,
9099 : exp, target);
9100 2 : case BUILT_IN_REV_CRC8_DATA8:
9101 2 : return expand_builtin_crc_table_based (IFN_CRC_REV, QImode, QImode,
9102 : mode, exp, target);
9103 2 : case BUILT_IN_REV_CRC16_DATA8:
9104 2 : return expand_builtin_crc_table_based (IFN_CRC_REV, HImode, QImode,
9105 : mode, exp, target);
9106 2 : case BUILT_IN_REV_CRC16_DATA16:
9107 2 : return expand_builtin_crc_table_based (IFN_CRC_REV, HImode, HImode,
9108 : mode, exp, target);
9109 3 : case BUILT_IN_REV_CRC32_DATA8:
9110 3 : return expand_builtin_crc_table_based (IFN_CRC_REV, SImode, QImode,
9111 : mode, exp, target);
9112 2 : case BUILT_IN_REV_CRC32_DATA16:
9113 2 : return expand_builtin_crc_table_based (IFN_CRC_REV, SImode, HImode,
9114 : mode, exp, target);
9115 2 : case BUILT_IN_REV_CRC32_DATA32:
9116 2 : return expand_builtin_crc_table_based (IFN_CRC_REV, SImode, SImode,
9117 : mode, exp, target);
9118 1 : case BUILT_IN_REV_CRC64_DATA8:
9119 1 : return expand_builtin_crc_table_based (IFN_CRC_REV, DImode, QImode,
9120 : mode, exp, target);
9121 1 : case BUILT_IN_REV_CRC64_DATA16:
9122 1 : return expand_builtin_crc_table_based (IFN_CRC_REV, DImode, HImode,
9123 : mode, exp, target);
9124 1 : case BUILT_IN_REV_CRC64_DATA32:
9125 1 : return expand_builtin_crc_table_based (IFN_CRC_REV, DImode, SImode,
9126 : mode, exp, target);
9127 1 : case BUILT_IN_REV_CRC64_DATA64:
9128 1 : return expand_builtin_crc_table_based (IFN_CRC_REV, DImode, DImode,
9129 : mode, exp, target);
9130 : default: /* just do library call, if unknown builtin */
9131 : break;
9132 : }
9133 :
9134 : /* The switch statement above can drop through to cause the function
9135 : to be called normally. */
9136 857984 : return expand_call (exp, target, ignore);
9137 : }
9138 :
9139 : /* Determine whether a tree node represents a call to a built-in
9140 : function. If the tree T is a call to a built-in function with
9141 : the right number of arguments of the appropriate types, return
9142 : the DECL_FUNCTION_CODE of the call, e.g. BUILT_IN_SQRT.
9143 : Otherwise the return value is END_BUILTINS. */
9144 :
9145 : enum built_in_function
9146 109709140 : builtin_mathfn_code (const_tree t)
9147 : {
9148 109709140 : const_tree fndecl, arg, parmlist;
9149 109709140 : const_tree argtype, parmtype;
9150 109709140 : const_call_expr_arg_iterator iter;
9151 :
9152 109709140 : if (TREE_CODE (t) != CALL_EXPR)
9153 : return END_BUILTINS;
9154 :
9155 1467308 : fndecl = get_callee_fndecl (t);
9156 1467308 : if (fndecl == NULL_TREE || !fndecl_built_in_p (fndecl, BUILT_IN_NORMAL))
9157 : return END_BUILTINS;
9158 :
9159 661068 : parmlist = TYPE_ARG_TYPES (TREE_TYPE (fndecl));
9160 661068 : init_const_call_expr_arg_iterator (t, &iter);
9161 2133358 : for (; parmlist; parmlist = TREE_CHAIN (parmlist))
9162 : {
9163 : /* If a function doesn't take a variable number of arguments,
9164 : the last element in the list will have type `void'. */
9165 1452629 : parmtype = TREE_VALUE (parmlist);
9166 1452629 : if (VOID_TYPE_P (parmtype))
9167 : {
9168 641393 : if (more_const_call_expr_args_p (&iter))
9169 : return END_BUILTINS;
9170 641393 : return DECL_FUNCTION_CODE (fndecl);
9171 : }
9172 :
9173 811236 : if (! more_const_call_expr_args_p (&iter))
9174 : return END_BUILTINS;
9175 :
9176 811236 : arg = next_const_call_expr_arg (&iter);
9177 811236 : argtype = TREE_TYPE (arg);
9178 :
9179 811236 : if (SCALAR_FLOAT_TYPE_P (parmtype))
9180 : {
9181 549379 : if (! SCALAR_FLOAT_TYPE_P (argtype))
9182 : return END_BUILTINS;
9183 : }
9184 261857 : else if (COMPLEX_FLOAT_TYPE_P (parmtype))
9185 : {
9186 7777 : if (! COMPLEX_FLOAT_TYPE_P (argtype))
9187 : return END_BUILTINS;
9188 : }
9189 254080 : else if (POINTER_TYPE_P (parmtype))
9190 : {
9191 75931 : if (! POINTER_TYPE_P (argtype))
9192 : return END_BUILTINS;
9193 : }
9194 178149 : else if (INTEGRAL_TYPE_P (parmtype))
9195 : {
9196 178149 : if (! INTEGRAL_TYPE_P (argtype))
9197 : return END_BUILTINS;
9198 : }
9199 : else
9200 : return END_BUILTINS;
9201 : }
9202 :
9203 : /* Variable-length argument list. */
9204 19661 : return DECL_FUNCTION_CODE (fndecl);
9205 : }
9206 :
9207 : /* Fold a call to __builtin_constant_p, if we know its argument ARG will
9208 : evaluate to a constant. */
9209 :
9210 : tree
9211 3291894 : fold_builtin_constant_p (tree arg)
9212 : {
9213 : /* We return 1 for a numeric type that's known to be a constant
9214 : value at compile-time or for an aggregate type that's a
9215 : literal constant. */
9216 3291894 : STRIP_NOPS (arg);
9217 :
9218 : /* If we know this is a constant, emit the constant of one. */
9219 3291894 : if (CONSTANT_CLASS_P (arg)
9220 3291894 : || (TREE_CODE (arg) == CONSTRUCTOR
9221 6 : && TREE_CONSTANT (arg)))
9222 1835733 : return integer_one_node;
9223 1456161 : if (TREE_CODE (arg) == ADDR_EXPR)
9224 : {
9225 110 : tree op = TREE_OPERAND (arg, 0);
9226 110 : if (TREE_CODE (op) == STRING_CST
9227 110 : || (TREE_CODE (op) == ARRAY_REF
9228 57 : && integer_zerop (TREE_OPERAND (op, 1))
9229 57 : && TREE_CODE (TREE_OPERAND (op, 0)) == STRING_CST))
9230 87 : return integer_one_node;
9231 : }
9232 :
9233 : /* If this expression has side effects, show we don't know it to be a
9234 : constant. Likewise if it's a pointer or aggregate type since in
9235 : those case we only want literals, since those are only optimized
9236 : when generating RTL, not later.
9237 : And finally, if we are compiling an initializer, not code, we
9238 : need to return a definite result now; there's not going to be any
9239 : more optimization done. */
9240 1456074 : if (TREE_SIDE_EFFECTS (arg)
9241 1455949 : || AGGREGATE_TYPE_P (TREE_TYPE (arg))
9242 1455943 : || POINTER_TYPE_P (TREE_TYPE (arg))
9243 1455772 : || cfun == 0
9244 1455679 : || folding_initializer
9245 2911746 : || force_folding_builtin_constant_p)
9246 497 : return integer_zero_node;
9247 :
9248 : return NULL_TREE;
9249 : }
9250 :
9251 : /* Create builtin_expect or builtin_expect_with_probability
9252 : with PRED and EXPECTED as its arguments and return it as a truthvalue.
9253 : Fortran FE can also produce builtin_expect with PREDICTOR as third argument.
9254 : builtin_expect_with_probability instead uses third argument as PROBABILITY
9255 : value. */
9256 :
9257 : static tree
9258 226100 : build_builtin_expect_predicate (location_t loc, tree pred, tree expected,
9259 : tree predictor, tree probability)
9260 : {
9261 226100 : tree fn, arg_types, pred_type, expected_type, call_expr, ret_type;
9262 :
9263 226100 : fn = builtin_decl_explicit (probability == NULL_TREE ? BUILT_IN_EXPECT
9264 : : BUILT_IN_EXPECT_WITH_PROBABILITY);
9265 226100 : arg_types = TYPE_ARG_TYPES (TREE_TYPE (fn));
9266 226100 : ret_type = TREE_TYPE (TREE_TYPE (fn));
9267 226100 : pred_type = TREE_VALUE (arg_types);
9268 226100 : expected_type = TREE_VALUE (TREE_CHAIN (arg_types));
9269 :
9270 226100 : pred = fold_convert_loc (loc, pred_type, pred);
9271 226100 : expected = fold_convert_loc (loc, expected_type, expected);
9272 :
9273 226100 : if (probability)
9274 0 : call_expr = build_call_expr_loc (loc, fn, 3, pred, expected, probability);
9275 : else
9276 452200 : call_expr = build_call_expr_loc (loc, fn, predictor ? 3 : 2, pred, expected,
9277 : predictor);
9278 :
9279 226100 : return build2 (NE_EXPR, TREE_TYPE (pred), call_expr,
9280 226100 : build_int_cst (ret_type, 0));
9281 : }
9282 :
9283 : /* Fold a call to builtin_expect with arguments ARG0, ARG1, ARG2, ARG3. Return
9284 : NULL_TREE if no simplification is possible. */
9285 :
9286 : tree
9287 7461664 : fold_builtin_expect (location_t loc, tree arg0, tree arg1, tree arg2,
9288 : tree arg3)
9289 : {
9290 7461664 : tree inner, fndecl, inner_arg0;
9291 7461664 : enum tree_code code;
9292 :
9293 : /* Distribute the expected value over short-circuiting operators.
9294 : See through the cast from truthvalue_type_node to long. */
9295 7461664 : inner_arg0 = arg0;
9296 15237794 : while (CONVERT_EXPR_P (inner_arg0)
9297 1071701 : && INTEGRAL_TYPE_P (TREE_TYPE (inner_arg0))
9298 9605065 : && INTEGRAL_TYPE_P (TREE_TYPE (TREE_OPERAND (inner_arg0, 0))))
9299 1071700 : inner_arg0 = TREE_OPERAND (inner_arg0, 0);
9300 :
9301 : /* If this is a builtin_expect within a builtin_expect keep the
9302 : inner one. See through a comparison against a constant. It
9303 : might have been added to create a thruthvalue. */
9304 7461664 : inner = inner_arg0;
9305 :
9306 7461664 : if (COMPARISON_CLASS_P (inner)
9307 7461664 : && TREE_CODE (TREE_OPERAND (inner, 1)) == INTEGER_CST)
9308 1433512 : inner = TREE_OPERAND (inner, 0);
9309 :
9310 7461664 : if (TREE_CODE (inner) == CALL_EXPR
9311 177099 : && (fndecl = get_callee_fndecl (inner))
9312 7638763 : && fndecl_built_in_p (fndecl, BUILT_IN_EXPECT,
9313 : BUILT_IN_EXPECT_WITH_PROBABILITY))
9314 : return arg0;
9315 :
9316 7461656 : inner = inner_arg0;
9317 7461656 : code = TREE_CODE (inner);
9318 7461656 : if (code == TRUTH_ANDIF_EXPR || code == TRUTH_ORIF_EXPR)
9319 : {
9320 113050 : tree op0 = TREE_OPERAND (inner, 0);
9321 113050 : tree op1 = TREE_OPERAND (inner, 1);
9322 113050 : arg1 = save_expr (arg1);
9323 :
9324 113050 : op0 = build_builtin_expect_predicate (loc, op0, arg1, arg2, arg3);
9325 113050 : op1 = build_builtin_expect_predicate (loc, op1, arg1, arg2, arg3);
9326 113050 : inner = build2 (code, TREE_TYPE (inner), op0, op1);
9327 :
9328 113050 : return fold_convert_loc (loc, TREE_TYPE (arg0), inner);
9329 : }
9330 :
9331 : /* If the argument isn't invariant then there's nothing else we can do. */
9332 7348606 : if (!TREE_CONSTANT (inner_arg0))
9333 : return NULL_TREE;
9334 :
9335 : /* If we expect that a comparison against the argument will fold to
9336 : a constant return the constant. In practice, this means a true
9337 : constant or the address of a non-weak symbol. */
9338 253917 : inner = inner_arg0;
9339 253917 : STRIP_NOPS (inner);
9340 253917 : if (TREE_CODE (inner) == ADDR_EXPR)
9341 : {
9342 1 : do
9343 : {
9344 1 : inner = TREE_OPERAND (inner, 0);
9345 : }
9346 1 : while (TREE_CODE (inner) == COMPONENT_REF
9347 1 : || TREE_CODE (inner) == ARRAY_REF);
9348 1 : if (VAR_OR_FUNCTION_DECL_P (inner) && DECL_WEAK (inner))
9349 0 : return NULL_TREE;
9350 : }
9351 :
9352 : /* Otherwise, ARG0 already has the proper type for the return value. */
9353 : return arg0;
9354 : }
9355 :
9356 : /* Fold a call to __builtin_classify_type with argument ARG. */
9357 :
9358 : static tree
9359 2068 : fold_builtin_classify_type (tree arg)
9360 : {
9361 2068 : if (arg == 0)
9362 0 : return build_int_cst (integer_type_node, no_type_class);
9363 :
9364 2068 : return build_int_cst (integer_type_node, type_to_class (TREE_TYPE (arg)));
9365 : }
9366 :
9367 : /* Fold a call EXPR (which may be null) to __builtin_strlen with argument
9368 : ARG. */
9369 :
9370 : static tree
9371 478331 : fold_builtin_strlen (location_t loc, tree expr, tree type, tree arg)
9372 : {
9373 478331 : if (!validate_arg (arg, POINTER_TYPE))
9374 : return NULL_TREE;
9375 : else
9376 : {
9377 478328 : c_strlen_data lendata = { };
9378 478328 : tree len = c_strlen (arg, 0, &lendata);
9379 :
9380 478328 : if (len)
9381 2223 : return fold_convert_loc (loc, type, len);
9382 :
9383 : /* TODO: Move this to gimple-ssa-warn-access once the pass runs
9384 : also early enough to detect invalid reads in multimensional
9385 : arrays and struct members. */
9386 476105 : if (!lendata.decl)
9387 468927 : c_strlen (arg, 1, &lendata);
9388 :
9389 476105 : if (lendata.decl)
9390 : {
9391 7192 : if (EXPR_HAS_LOCATION (arg))
9392 2800 : loc = EXPR_LOCATION (arg);
9393 4392 : else if (loc == UNKNOWN_LOCATION)
9394 0 : loc = input_location;
9395 7192 : warn_string_no_nul (loc, expr, "strlen", arg, lendata.decl);
9396 : }
9397 :
9398 : return NULL_TREE;
9399 : }
9400 : }
9401 :
9402 : /* Fold a call to __builtin_inf or __builtin_huge_val. */
9403 :
9404 : static tree
9405 264547 : fold_builtin_inf (location_t loc, tree type, int warn)
9406 : {
9407 : /* __builtin_inff is intended to be usable to define INFINITY on all
9408 : targets. If an infinity is not available, INFINITY expands "to a
9409 : positive constant of type float that overflows at translation
9410 : time", footnote "In this case, using INFINITY will violate the
9411 : constraint in 6.4.4 and thus require a diagnostic." (C99 7.12#4).
9412 : Thus we pedwarn to ensure this constraint violation is
9413 : diagnosed. */
9414 1057379 : if (!MODE_HAS_INFINITIES (TYPE_MODE (type)) && warn)
9415 0 : pedwarn (loc, 0, "target format does not support infinity");
9416 :
9417 264547 : return build_real (type, dconstinf);
9418 : }
9419 :
9420 : /* Fold function call to builtin sincos, sincosf, or sincosl. Return
9421 : NULL_TREE if no simplification can be made. */
9422 :
9423 : static tree
9424 145 : fold_builtin_sincos (location_t loc,
9425 : tree arg0, tree arg1, tree arg2)
9426 : {
9427 145 : tree type;
9428 145 : tree fndecl, call = NULL_TREE;
9429 :
9430 145 : if (!validate_arg (arg0, REAL_TYPE)
9431 145 : || !validate_arg (arg1, POINTER_TYPE)
9432 290 : || !validate_arg (arg2, POINTER_TYPE))
9433 : return NULL_TREE;
9434 :
9435 145 : type = TREE_TYPE (arg0);
9436 :
9437 : /* Calculate the result when the argument is a constant. */
9438 145 : built_in_function fn = mathfn_built_in_2 (type, CFN_BUILT_IN_CEXPI);
9439 145 : if (fn == END_BUILTINS)
9440 : return NULL_TREE;
9441 :
9442 : /* Canonicalize sincos to cexpi. */
9443 145 : if (TREE_CODE (arg0) == REAL_CST)
9444 : {
9445 86 : tree complex_type = build_complex_type (type);
9446 86 : call = fold_const_call (as_combined_fn (fn), complex_type, arg0);
9447 : }
9448 86 : if (!call)
9449 : {
9450 59 : if (!targetm.libc_has_function (function_c99_math_complex, type)
9451 59 : || !builtin_decl_implicit_p (fn))
9452 : return NULL_TREE;
9453 59 : fndecl = builtin_decl_explicit (fn);
9454 59 : call = build_call_expr_loc (loc, fndecl, 1, arg0);
9455 59 : call = builtin_save_expr (call);
9456 : }
9457 :
9458 145 : tree ptype = build_pointer_type (type);
9459 145 : arg1 = fold_convert (ptype, arg1);
9460 145 : arg2 = fold_convert (ptype, arg2);
9461 145 : return build2 (COMPOUND_EXPR, void_type_node,
9462 : build2 (MODIFY_EXPR, void_type_node,
9463 : build_fold_indirect_ref_loc (loc, arg1),
9464 : fold_build1_loc (loc, IMAGPART_EXPR, type, call)),
9465 : build2 (MODIFY_EXPR, void_type_node,
9466 : build_fold_indirect_ref_loc (loc, arg2),
9467 145 : fold_build1_loc (loc, REALPART_EXPR, type, call)));
9468 : }
9469 :
9470 : /* Fold function call to builtin memcmp with arguments ARG1 and ARG2.
9471 : Return NULL_TREE if no simplification can be made. */
9472 :
9473 : static tree
9474 2580962 : fold_builtin_memcmp (location_t loc, tree arg1, tree arg2, tree len)
9475 : {
9476 2580962 : if (!validate_arg (arg1, POINTER_TYPE)
9477 2580962 : || !validate_arg (arg2, POINTER_TYPE)
9478 5161924 : || !validate_arg (len, INTEGER_TYPE))
9479 : return NULL_TREE;
9480 :
9481 : /* If the LEN parameter is zero, return zero. */
9482 2580962 : if (integer_zerop (len))
9483 0 : return omit_two_operands_loc (loc, integer_type_node, integer_zero_node,
9484 0 : arg1, arg2);
9485 :
9486 : /* If ARG1 and ARG2 are the same (and not volatile), return zero. */
9487 2580962 : if (operand_equal_p (arg1, arg2, 0))
9488 705 : return omit_one_operand_loc (loc, integer_type_node, integer_zero_node, len);
9489 :
9490 : /* If len parameter is one, return an expression corresponding to
9491 : (*(const unsigned char*)arg1 - (const unsigned char*)arg2). */
9492 2580257 : if (tree_fits_uhwi_p (len) && tree_to_uhwi (len) == 1)
9493 : {
9494 55287 : tree cst_uchar_node = build_type_variant (unsigned_char_type_node, 1, 0);
9495 55287 : tree cst_uchar_ptr_node
9496 55287 : = build_pointer_type_for_mode (cst_uchar_node, ptr_mode, true);
9497 :
9498 55287 : tree ind1
9499 55287 : = fold_convert_loc (loc, integer_type_node,
9500 : build1 (INDIRECT_REF, cst_uchar_node,
9501 : fold_convert_loc (loc,
9502 : cst_uchar_ptr_node,
9503 : arg1)));
9504 55287 : tree ind2
9505 55287 : = fold_convert_loc (loc, integer_type_node,
9506 : build1 (INDIRECT_REF, cst_uchar_node,
9507 : fold_convert_loc (loc,
9508 : cst_uchar_ptr_node,
9509 : arg2)));
9510 55287 : return fold_build2_loc (loc, MINUS_EXPR, integer_type_node, ind1, ind2);
9511 : }
9512 :
9513 : return NULL_TREE;
9514 : }
9515 :
9516 : /* Fold a call to builtin isascii with argument ARG. */
9517 :
9518 : static tree
9519 211 : fold_builtin_isascii (location_t loc, tree arg)
9520 : {
9521 211 : if (!validate_arg (arg, INTEGER_TYPE))
9522 : return NULL_TREE;
9523 : else
9524 : {
9525 : /* Transform isascii(c) -> ((c & ~0x7f) == 0). */
9526 211 : arg = fold_build2 (BIT_AND_EXPR, integer_type_node, arg,
9527 : build_int_cst (integer_type_node,
9528 : ~ HOST_WIDE_INT_UC (0x7f)));
9529 211 : return fold_build2_loc (loc, EQ_EXPR, integer_type_node,
9530 211 : arg, integer_zero_node);
9531 : }
9532 : }
9533 :
9534 : /* Fold a call to builtin toascii with argument ARG. */
9535 :
9536 : static tree
9537 168 : fold_builtin_toascii (location_t loc, tree arg)
9538 : {
9539 168 : if (!validate_arg (arg, INTEGER_TYPE))
9540 : return NULL_TREE;
9541 :
9542 : /* Transform toascii(c) -> (c & 0x7f). */
9543 168 : return fold_build2_loc (loc, BIT_AND_EXPR, integer_type_node, arg,
9544 : build_int_cst (integer_type_node, 0x7f));
9545 : }
9546 :
9547 : /* Fold a call to builtin isdigit with argument ARG. */
9548 :
9549 : static tree
9550 325 : fold_builtin_isdigit (location_t loc, tree arg)
9551 : {
9552 325 : if (!validate_arg (arg, INTEGER_TYPE))
9553 : return NULL_TREE;
9554 : else
9555 : {
9556 : /* Transform isdigit(c) -> (unsigned)(c) - '0' <= 9. */
9557 : /* According to the C standard, isdigit is unaffected by locale.
9558 : However, it definitely is affected by the target character set. */
9559 313 : unsigned HOST_WIDE_INT target_digit0
9560 313 : = lang_hooks.to_target_charset ('0');
9561 :
9562 313 : if (target_digit0 == 0)
9563 : return NULL_TREE;
9564 :
9565 313 : arg = fold_convert_loc (loc, unsigned_type_node, arg);
9566 313 : arg = fold_build2 (MINUS_EXPR, unsigned_type_node, arg,
9567 : build_int_cst (unsigned_type_node, target_digit0));
9568 313 : return fold_build2_loc (loc, LE_EXPR, integer_type_node, arg,
9569 : build_int_cst (unsigned_type_node, 9));
9570 : }
9571 : }
9572 :
9573 : /* Fold a call to fabs, fabsf or fabsl with argument ARG. */
9574 :
9575 : static tree
9576 379580 : fold_builtin_fabs (location_t loc, tree arg, tree type)
9577 : {
9578 379580 : if (!validate_arg (arg, REAL_TYPE))
9579 : return NULL_TREE;
9580 :
9581 379495 : arg = fold_convert_loc (loc, type, arg);
9582 379495 : return fold_build1_loc (loc, ABS_EXPR, type, arg);
9583 : }
9584 :
9585 : /* Fold a call to abs, labs, llabs, imaxabs, uabs, ulabs, ullabs or uimaxabs
9586 : with argument ARG. */
9587 :
9588 : static tree
9589 101470 : fold_builtin_abs (location_t loc, tree arg, tree type)
9590 : {
9591 101470 : if (!validate_arg (arg, INTEGER_TYPE) || !INTEGRAL_TYPE_P (type))
9592 : return NULL_TREE;
9593 :
9594 101422 : if (TYPE_UNSIGNED (type))
9595 : {
9596 1168 : if (TYPE_PRECISION (TREE_TYPE (arg))
9597 1168 : != TYPE_PRECISION (type)
9598 1168 : || TYPE_UNSIGNED (TREE_TYPE (arg)))
9599 : return NULL_TREE;
9600 1168 : return fold_build1_loc (loc, ABSU_EXPR, type, arg);
9601 : }
9602 100254 : arg = fold_convert_loc (loc, type, arg);
9603 100254 : return fold_build1_loc (loc, ABS_EXPR, type, arg);
9604 : }
9605 :
9606 : /* Fold a call to builtin carg(a+bi) -> atan2(b,a). */
9607 :
9608 : static tree
9609 104839 : fold_builtin_carg (location_t loc, tree arg, tree type)
9610 : {
9611 104839 : if (validate_arg (arg, COMPLEX_TYPE)
9612 104839 : && SCALAR_FLOAT_TYPE_P (TREE_TYPE (TREE_TYPE (arg))))
9613 : {
9614 104839 : tree atan2_fn = mathfn_built_in (type, BUILT_IN_ATAN2);
9615 :
9616 104839 : if (atan2_fn)
9617 : {
9618 100935 : tree new_arg = builtin_save_expr (arg);
9619 100935 : tree r_arg = fold_build1_loc (loc, REALPART_EXPR, type, new_arg);
9620 100935 : tree i_arg = fold_build1_loc (loc, IMAGPART_EXPR, type, new_arg);
9621 100935 : return build_call_expr_loc (loc, atan2_fn, 2, i_arg, r_arg);
9622 : }
9623 : }
9624 :
9625 : return NULL_TREE;
9626 : }
9627 :
9628 : /* Fold a call to builtin frexp, we can assume the base is 2. */
9629 :
9630 : static tree
9631 116489 : fold_builtin_frexp (location_t loc, tree arg0, tree arg1, tree rettype)
9632 : {
9633 116489 : if (! validate_arg (arg0, REAL_TYPE) || ! validate_arg (arg1, POINTER_TYPE))
9634 : return NULL_TREE;
9635 :
9636 116489 : STRIP_NOPS (arg0);
9637 :
9638 116489 : if (!(TREE_CODE (arg0) == REAL_CST && ! TREE_OVERFLOW (arg0)))
9639 : return NULL_TREE;
9640 :
9641 2210 : arg1 = build_fold_indirect_ref_loc (loc, arg1);
9642 :
9643 : /* Proceed if a valid pointer type was passed in. */
9644 2210 : if (TYPE_MAIN_VARIANT (TREE_TYPE (arg1)) == integer_type_node)
9645 : {
9646 2210 : const REAL_VALUE_TYPE *const value = TREE_REAL_CST_PTR (arg0);
9647 2210 : tree frac, exp, res;
9648 :
9649 2210 : switch (value->cl)
9650 : {
9651 276 : case rvc_zero:
9652 276 : case rvc_nan:
9653 276 : case rvc_inf:
9654 : /* For +-0, return (*exp = 0, +-0). */
9655 : /* For +-NaN or +-Inf, *exp is unspecified, but something should
9656 : be stored there so that it isn't read from uninitialized object.
9657 : As glibc and newlib store *exp = 0 for +-Inf/NaN, storing
9658 : 0 here as well is easiest. */
9659 276 : exp = integer_zero_node;
9660 276 : frac = arg0;
9661 276 : break;
9662 1934 : case rvc_normal:
9663 1934 : {
9664 : /* Since the frexp function always expects base 2, and in
9665 : GCC normalized significands are already in the range
9666 : [0.5, 1.0), we have exactly what frexp wants. */
9667 1934 : REAL_VALUE_TYPE frac_rvt = *value;
9668 1934 : SET_REAL_EXP (&frac_rvt, 0);
9669 1934 : frac = build_real (rettype, frac_rvt);
9670 1934 : exp = build_int_cst (integer_type_node, REAL_EXP (value));
9671 : }
9672 1934 : break;
9673 0 : default:
9674 0 : gcc_unreachable ();
9675 : }
9676 :
9677 : /* Create the COMPOUND_EXPR (*arg1 = trunc, frac). */
9678 2210 : arg1 = fold_build2_loc (loc, MODIFY_EXPR, rettype, arg1, exp);
9679 2210 : TREE_SIDE_EFFECTS (arg1) = 1;
9680 2210 : res = fold_build2_loc (loc, COMPOUND_EXPR, rettype, arg1, frac);
9681 2210 : suppress_warning (res, OPT_Wunused_value);
9682 2210 : return res;
9683 : }
9684 :
9685 : return NULL_TREE;
9686 : }
9687 :
9688 : /* Fold a call to builtin modf. */
9689 :
9690 : static tree
9691 93230 : fold_builtin_modf (location_t loc, tree arg0, tree arg1, tree rettype)
9692 : {
9693 93230 : if (! validate_arg (arg0, REAL_TYPE) || ! validate_arg (arg1, POINTER_TYPE))
9694 : return NULL_TREE;
9695 :
9696 93230 : STRIP_NOPS (arg0);
9697 :
9698 93230 : if (!(TREE_CODE (arg0) == REAL_CST && ! TREE_OVERFLOW (arg0)))
9699 : return NULL_TREE;
9700 :
9701 2474 : arg1 = build_fold_indirect_ref_loc (loc, arg1);
9702 :
9703 : /* Proceed if a valid pointer type was passed in. */
9704 2474 : if (TYPE_MAIN_VARIANT (TREE_TYPE (arg1)) == TYPE_MAIN_VARIANT (rettype))
9705 : {
9706 2474 : const REAL_VALUE_TYPE *const value = TREE_REAL_CST_PTR (arg0);
9707 2474 : REAL_VALUE_TYPE trunc, frac;
9708 2474 : tree res;
9709 :
9710 2474 : switch (value->cl)
9711 : {
9712 228 : case rvc_nan:
9713 228 : case rvc_zero:
9714 : /* For +-NaN or +-0, return (*arg1 = arg0, arg0). */
9715 228 : trunc = frac = *value;
9716 228 : break;
9717 96 : case rvc_inf:
9718 : /* For +-Inf, return (*arg1 = arg0, +-0). */
9719 96 : frac = dconst0;
9720 96 : frac.sign = value->sign;
9721 96 : trunc = *value;
9722 96 : break;
9723 2150 : case rvc_normal:
9724 : /* Return (*arg1 = trunc(arg0), arg0-trunc(arg0)). */
9725 2150 : real_trunc (&trunc, VOIDmode, value);
9726 2150 : real_arithmetic (&frac, MINUS_EXPR, value, &trunc);
9727 : /* If the original number was negative and already
9728 : integral, then the fractional part is -0.0. */
9729 2150 : if (value->sign && frac.cl == rvc_zero)
9730 69 : frac.sign = value->sign;
9731 : break;
9732 : }
9733 :
9734 : /* Create the COMPOUND_EXPR (*arg1 = trunc, frac). */
9735 2474 : arg1 = fold_build2_loc (loc, MODIFY_EXPR, rettype, arg1,
9736 : build_real (rettype, trunc));
9737 2474 : TREE_SIDE_EFFECTS (arg1) = 1;
9738 2474 : res = fold_build2_loc (loc, COMPOUND_EXPR, rettype, arg1,
9739 : build_real (rettype, frac));
9740 2474 : suppress_warning (res, OPT_Wunused_value);
9741 2474 : return res;
9742 : }
9743 :
9744 : return NULL_TREE;
9745 : }
9746 :
9747 : /* Given a location LOC, an interclass builtin function decl FNDECL
9748 : and its single argument ARG, return an folded expression computing
9749 : the same, or NULL_TREE if we either couldn't or didn't want to fold
9750 : (the latter happen if there's an RTL instruction available). */
9751 :
9752 : static tree
9753 1826615 : fold_builtin_interclass_mathfn (location_t loc, tree fndecl, tree arg)
9754 : {
9755 1826615 : machine_mode mode;
9756 :
9757 1826615 : if (!validate_arg (arg, REAL_TYPE))
9758 : return NULL_TREE;
9759 :
9760 1826615 : if (interclass_mathfn_icode (arg, fndecl) != CODE_FOR_nothing)
9761 : return NULL_TREE;
9762 :
9763 1826615 : mode = TYPE_MODE (TREE_TYPE (arg));
9764 :
9765 12782463 : bool is_ibm_extended = MODE_COMPOSITE_P (mode);
9766 :
9767 : /* If there is no optab, try generic code. */
9768 1826615 : switch (DECL_FUNCTION_CODE (fndecl))
9769 : {
9770 711704 : tree result;
9771 :
9772 711704 : CASE_FLT_FN (BUILT_IN_ISINF):
9773 711704 : {
9774 : /* isinf(x) -> isgreater(fabs(x),DBL_MAX). */
9775 711704 : tree const isgr_fn = builtin_decl_explicit (BUILT_IN_ISGREATER);
9776 711704 : tree type = TREE_TYPE (arg);
9777 711704 : REAL_VALUE_TYPE r;
9778 711704 : char buf[128];
9779 :
9780 711704 : if (is_ibm_extended)
9781 : {
9782 : /* NaN and Inf are encoded in the high-order double value
9783 : only. The low-order value is not significant. */
9784 0 : type = double_type_node;
9785 0 : mode = DFmode;
9786 0 : arg = fold_build1_loc (loc, NOP_EXPR, type, arg);
9787 : }
9788 711704 : get_max_float (REAL_MODE_FORMAT (mode), buf, sizeof (buf), false);
9789 711704 : real_from_string3 (&r, buf, mode);
9790 711704 : result = build_call_expr (isgr_fn, 2,
9791 : fold_build1_loc (loc, ABS_EXPR, type, arg),
9792 : build_real (type, r));
9793 711704 : return result;
9794 : }
9795 628395 : CASE_FLT_FN (BUILT_IN_FINITE):
9796 628395 : case BUILT_IN_ISFINITE:
9797 628395 : {
9798 : /* isfinite(x) -> islessequal(fabs(x),DBL_MAX). */
9799 628395 : tree const isle_fn = builtin_decl_explicit (BUILT_IN_ISLESSEQUAL);
9800 628395 : tree type = TREE_TYPE (arg);
9801 628395 : REAL_VALUE_TYPE r;
9802 628395 : char buf[128];
9803 :
9804 628395 : if (is_ibm_extended)
9805 : {
9806 : /* NaN and Inf are encoded in the high-order double value
9807 : only. The low-order value is not significant. */
9808 0 : type = double_type_node;
9809 0 : mode = DFmode;
9810 0 : arg = fold_build1_loc (loc, NOP_EXPR, type, arg);
9811 : }
9812 628395 : get_max_float (REAL_MODE_FORMAT (mode), buf, sizeof (buf), false);
9813 628395 : real_from_string3 (&r, buf, mode);
9814 628395 : result = build_call_expr (isle_fn, 2,
9815 : fold_build1_loc (loc, ABS_EXPR, type, arg),
9816 : build_real (type, r));
9817 : /*result = fold_build2_loc (loc, UNGT_EXPR,
9818 : TREE_TYPE (TREE_TYPE (fndecl)),
9819 : fold_build1_loc (loc, ABS_EXPR, type, arg),
9820 : build_real (type, r));
9821 : result = fold_build1_loc (loc, TRUTH_NOT_EXPR,
9822 : TREE_TYPE (TREE_TYPE (fndecl)),
9823 : result);*/
9824 628395 : return result;
9825 : }
9826 240988 : case BUILT_IN_ISNORMAL:
9827 240988 : {
9828 : /* isnormal(x) -> isgreaterequal(fabs(x),DBL_MIN) &
9829 : islessequal(fabs(x),DBL_MAX). */
9830 240988 : tree const isle_fn = builtin_decl_explicit (BUILT_IN_ISLESSEQUAL);
9831 240988 : tree type = TREE_TYPE (arg);
9832 240988 : tree orig_arg, max_exp, min_exp;
9833 240988 : machine_mode orig_mode = mode;
9834 240988 : REAL_VALUE_TYPE rmax, rmin;
9835 240988 : char buf[128];
9836 :
9837 240988 : orig_arg = arg = builtin_save_expr (arg);
9838 240988 : if (is_ibm_extended)
9839 : {
9840 : /* Use double to test the normal range of IBM extended
9841 : precision. Emin for IBM extended precision is
9842 : different to emin for IEEE double, being 53 higher
9843 : since the low double exponent is at least 53 lower
9844 : than the high double exponent. */
9845 0 : type = double_type_node;
9846 0 : mode = DFmode;
9847 0 : arg = fold_build1_loc (loc, NOP_EXPR, type, arg);
9848 : }
9849 240988 : arg = fold_build1_loc (loc, ABS_EXPR, type, arg);
9850 :
9851 240988 : get_max_float (REAL_MODE_FORMAT (mode), buf, sizeof (buf), false);
9852 240988 : real_from_string3 (&rmax, buf, mode);
9853 240988 : if (DECIMAL_FLOAT_MODE_P (mode))
9854 1 : sprintf (buf, "1E%d", REAL_MODE_FORMAT (orig_mode)->emin - 1);
9855 : else
9856 240987 : sprintf (buf, "0x1p%d", REAL_MODE_FORMAT (orig_mode)->emin - 1);
9857 240988 : real_from_string3 (&rmin, buf, orig_mode);
9858 240988 : max_exp = build_real (type, rmax);
9859 240988 : min_exp = build_real (type, rmin);
9860 :
9861 240988 : max_exp = build_call_expr (isle_fn, 2, arg, max_exp);
9862 240988 : if (is_ibm_extended)
9863 : {
9864 : /* Testing the high end of the range is done just using
9865 : the high double, using the same test as isfinite().
9866 : For the subnormal end of the range we first test the
9867 : high double, then if its magnitude is equal to the
9868 : limit of 0x1p-969, we test whether the low double is
9869 : non-zero and opposite sign to the high double. */
9870 0 : tree const islt_fn = builtin_decl_explicit (BUILT_IN_ISLESS);
9871 0 : tree const isgt_fn = builtin_decl_explicit (BUILT_IN_ISGREATER);
9872 0 : tree gt_min = build_call_expr (isgt_fn, 2, arg, min_exp);
9873 0 : tree eq_min = fold_build2 (EQ_EXPR, integer_type_node,
9874 : arg, min_exp);
9875 0 : tree as_complex = build1 (VIEW_CONVERT_EXPR,
9876 : complex_double_type_node, orig_arg);
9877 0 : tree hi_dbl = build1 (REALPART_EXPR, type, as_complex);
9878 0 : tree lo_dbl = build1 (IMAGPART_EXPR, type, as_complex);
9879 0 : tree zero = build_real (type, dconst0);
9880 0 : tree hilt = build_call_expr (islt_fn, 2, hi_dbl, zero);
9881 0 : tree lolt = build_call_expr (islt_fn, 2, lo_dbl, zero);
9882 0 : tree logt = build_call_expr (isgt_fn, 2, lo_dbl, zero);
9883 0 : tree ok_lo = fold_build1 (TRUTH_NOT_EXPR, integer_type_node,
9884 : fold_build3 (COND_EXPR,
9885 : integer_type_node,
9886 : hilt, logt, lolt));
9887 0 : eq_min = fold_build2 (TRUTH_ANDIF_EXPR, integer_type_node,
9888 : eq_min, ok_lo);
9889 0 : min_exp = fold_build2 (TRUTH_ORIF_EXPR, integer_type_node,
9890 : gt_min, eq_min);
9891 : }
9892 : else
9893 : {
9894 240988 : tree const isge_fn
9895 240988 : = builtin_decl_explicit (BUILT_IN_ISGREATEREQUAL);
9896 240988 : min_exp = build_call_expr (isge_fn, 2, arg, min_exp);
9897 : }
9898 240988 : result = fold_build2 (BIT_AND_EXPR, integer_type_node,
9899 : max_exp, min_exp);
9900 240988 : return result;
9901 : }
9902 243994 : CASE_FLT_FN (BUILT_IN_ISNAN):
9903 243994 : case BUILT_IN_ISNAND32:
9904 243994 : case BUILT_IN_ISNAND64:
9905 243994 : case BUILT_IN_ISNAND128:
9906 243994 : {
9907 : /* In IBM extended NaN and Inf are encoded in the high-order double
9908 : value only. The low-order value is not significant. */
9909 243994 : if (is_ibm_extended)
9910 0 : arg = fold_build1_loc (loc, NOP_EXPR, double_type_node, arg);
9911 243994 : arg = builtin_save_expr (arg);
9912 243994 : tree type = TREE_TYPE (TREE_TYPE (fndecl));
9913 243994 : return fold_build2_loc (loc, UNORDERED_EXPR, type, arg, arg);
9914 : }
9915 : default:
9916 : break;
9917 : }
9918 :
9919 : return NULL_TREE;
9920 : }
9921 :
9922 : /* Fold a call to __builtin_isnan(), __builtin_isinf, __builtin_finite.
9923 : ARG is the argument for the call. */
9924 :
9925 : static tree
9926 1614857 : fold_builtin_classify (location_t loc, tree fndecl, tree arg, int builtin_index)
9927 : {
9928 1614857 : tree type = TREE_TYPE (TREE_TYPE (fndecl));
9929 :
9930 1614857 : if (!validate_arg (arg, REAL_TYPE))
9931 : return NULL_TREE;
9932 :
9933 1614857 : switch (builtin_index)
9934 : {
9935 713489 : case BUILT_IN_ISINF:
9936 713489 : if (tree_expr_infinite_p (arg))
9937 0 : return omit_one_operand_loc (loc, type, integer_one_node, arg);
9938 713489 : if (!tree_expr_maybe_infinite_p (arg))
9939 251 : return omit_one_operand_loc (loc, type, integer_zero_node, arg);
9940 : return NULL_TREE;
9941 :
9942 708 : case BUILT_IN_ISINF_SIGN:
9943 708 : {
9944 : /* isinf_sign(x) -> isinf(x) ? (signbit(x) ? -1 : 1) : 0 */
9945 : /* In a boolean context, GCC will fold the inner COND_EXPR to
9946 : 1. So e.g. "if (isinf_sign(x))" would be folded to just
9947 : "if (isinf(x) ? 1 : 0)" which becomes "if (isinf(x))". */
9948 708 : tree signbit_fn = builtin_decl_explicit (BUILT_IN_SIGNBIT);
9949 708 : tree isinf_fn = builtin_decl_explicit (BUILT_IN_ISINF);
9950 708 : tree tmp = NULL_TREE;
9951 :
9952 708 : arg = builtin_save_expr (arg);
9953 :
9954 708 : if (signbit_fn && isinf_fn)
9955 : {
9956 708 : tree signbit_call = build_call_expr_loc (loc, signbit_fn, 1, arg);
9957 708 : tree isinf_call = build_call_expr_loc (loc, isinf_fn, 1, arg);
9958 :
9959 708 : signbit_call = fold_build2_loc (loc, NE_EXPR, integer_type_node,
9960 : signbit_call, integer_zero_node);
9961 708 : isinf_call = fold_build2_loc (loc, NE_EXPR, integer_type_node,
9962 : isinf_call, integer_zero_node);
9963 :
9964 708 : tmp = fold_build3_loc (loc, COND_EXPR, integer_type_node, signbit_call,
9965 : integer_minus_one_node, integer_one_node);
9966 708 : tmp = fold_build3_loc (loc, COND_EXPR, integer_type_node,
9967 : isinf_call, tmp,
9968 : integer_zero_node);
9969 : }
9970 :
9971 : return tmp;
9972 : }
9973 :
9974 628727 : case BUILT_IN_ISFINITE:
9975 628727 : if (tree_expr_finite_p (arg))
9976 332 : return omit_one_operand_loc (loc, type, integer_one_node, arg);
9977 628395 : if (tree_expr_nan_p (arg) || tree_expr_infinite_p (arg))
9978 0 : return omit_one_operand_loc (loc, type, integer_zero_node, arg);
9979 : return NULL_TREE;
9980 :
9981 244118 : case BUILT_IN_ISNAN:
9982 244118 : if (tree_expr_nan_p (arg))
9983 0 : return omit_one_operand_loc (loc, type, integer_one_node, arg);
9984 244118 : if (!tree_expr_maybe_nan_p (arg))
9985 124 : return omit_one_operand_loc (loc, type, integer_zero_node, arg);
9986 : return NULL_TREE;
9987 :
9988 27815 : case BUILT_IN_ISSIGNALING:
9989 : /* Folding to true for REAL_CST is done in fold_const_call_ss.
9990 : Don't use tree_expr_signaling_nan_p (arg) -> integer_one_node
9991 : and !tree_expr_maybe_signaling_nan_p (arg) -> integer_zero_node
9992 : here, so there is some possibility of __builtin_issignaling working
9993 : without -fsignaling-nans. Especially when -fno-signaling-nans is
9994 : the default. */
9995 27815 : if (!tree_expr_maybe_nan_p (arg))
9996 0 : return omit_one_operand_loc (loc, type, integer_zero_node, arg);
9997 : return NULL_TREE;
9998 :
9999 0 : default:
10000 0 : gcc_unreachable ();
10001 : }
10002 : }
10003 :
10004 : /* Fold a call to __builtin_fpclassify(int, int, int, int, int, ...).
10005 : This builtin will generate code to return the appropriate floating
10006 : point classification depending on the value of the floating point
10007 : number passed in. The possible return values must be supplied as
10008 : int arguments to the call in the following order: FP_NAN, FP_INFINITE,
10009 : FP_NORMAL, FP_SUBNORMAL and FP_ZERO. The ellipses is for exactly
10010 : one floating point argument which is "type generic". */
10011 :
10012 : static tree
10013 104982 : fold_builtin_fpclassify (location_t loc, tree *args, int nargs)
10014 : {
10015 104982 : tree fp_nan, fp_infinite, fp_normal, fp_subnormal, fp_zero,
10016 : arg, type, res, tmp;
10017 104982 : machine_mode mode;
10018 104982 : REAL_VALUE_TYPE r;
10019 104982 : char buf[128];
10020 :
10021 : /* Verify the required arguments in the original call. */
10022 104982 : if (nargs != 6
10023 104982 : || !validate_arg (args[0], INTEGER_TYPE)
10024 104982 : || !validate_arg (args[1], INTEGER_TYPE)
10025 104982 : || !validate_arg (args[2], INTEGER_TYPE)
10026 104982 : || !validate_arg (args[3], INTEGER_TYPE)
10027 104982 : || !validate_arg (args[4], INTEGER_TYPE)
10028 209964 : || !validate_arg (args[5], REAL_TYPE))
10029 : return NULL_TREE;
10030 :
10031 104982 : fp_nan = args[0];
10032 104982 : fp_infinite = args[1];
10033 104982 : fp_normal = args[2];
10034 104982 : fp_subnormal = args[3];
10035 104982 : fp_zero = args[4];
10036 104982 : arg = args[5];
10037 104982 : type = TREE_TYPE (arg);
10038 104982 : mode = TYPE_MODE (type);
10039 :
10040 : /* A target defines the classification optabs when FP comparisons are
10041 : unsuitable for classification, for instance because they raise
10042 : FE_INVALID for a signaling NaN (PR middle-end/66462). Build on the
10043 : built-ins in that case rather than on comparisons. */
10044 104982 : if (optab_handler (isnan_optab, mode) != CODE_FOR_nothing
10045 0 : && optab_handler (isinf_optab, mode) != CODE_FOR_nothing
10046 104982 : && optab_handler (isnormal_optab, mode) != CODE_FOR_nothing)
10047 : {
10048 0 : tree isnan_fn = builtin_decl_explicit (BUILT_IN_ISNAN);
10049 0 : tree isinf_fn = builtin_decl_explicit (BUILT_IN_ISINF);
10050 0 : tree isnormal_fn = builtin_decl_explicit (BUILT_IN_ISNORMAL);
10051 0 : const struct real_format *fmt = REAL_MODE_FORMAT (mode);
10052 0 : tree itype = NULL_TREE;
10053 0 : scalar_int_mode imode;
10054 :
10055 : /* The remaining zero versus subnormal test must not use a comparison
10056 : either. Testing the magnitude of the encoding for zero works
10057 : whenever the format is binary, has a matching integer mode and
10058 : stores its sign in the high bit of it; that excludes e.g. XFmode,
10059 : whose encoding is narrower than its integer mode, and the composite
10060 : formats, whose sign is not a single bit that can be shifted out. */
10061 0 : if (fmt->b == 2
10062 0 : && int_mode_for_mode (mode).exists (&imode)
10063 0 : && fmt->signbit_rw == fmt->signbit_ro
10064 0 : && fmt->signbit_rw == (int) GET_MODE_PRECISION (imode) - 1)
10065 : {
10066 0 : itype = lang_hooks.types.type_for_mode (imode, 1);
10067 0 : if (itype && TYPE_PRECISION (itype) != GET_MODE_PRECISION (imode))
10068 : itype = NULL_TREE;
10069 : }
10070 :
10071 0 : if (isnan_fn && isinf_fn && isnormal_fn && itype)
10072 : {
10073 0 : arg = builtin_save_expr (arg);
10074 :
10075 : /* Shifting the sign bit out leaves zero iff ARG is +-0. */
10076 0 : tmp = fold_build1_loc (loc, VIEW_CONVERT_EXPR, itype, arg);
10077 0 : tmp = fold_build2_loc (loc, LSHIFT_EXPR, itype, tmp,
10078 : build_int_cst (integer_type_node, 1));
10079 0 : tmp = fold_build2_loc (loc, EQ_EXPR, integer_type_node, tmp,
10080 : build_int_cst (itype, 0));
10081 0 : res = fold_build3_loc (loc, COND_EXPR, integer_type_node,
10082 : tmp, fp_zero, fp_subnormal);
10083 :
10084 0 : tmp = build_call_expr_loc (loc, isnormal_fn, 1, arg);
10085 0 : tmp = fold_build2_loc (loc, NE_EXPR, integer_type_node, tmp,
10086 : integer_zero_node);
10087 0 : res = fold_build3_loc (loc, COND_EXPR, integer_type_node, tmp,
10088 : fp_normal, res);
10089 :
10090 0 : if (tree_expr_maybe_infinite_p (arg))
10091 : {
10092 0 : tmp = build_call_expr_loc (loc, isinf_fn, 1, arg);
10093 0 : tmp = fold_build2_loc (loc, NE_EXPR, integer_type_node, tmp,
10094 : integer_zero_node);
10095 0 : res = fold_build3_loc (loc, COND_EXPR, integer_type_node, tmp,
10096 : fp_infinite, res);
10097 : }
10098 :
10099 0 : if (tree_expr_maybe_nan_p (arg))
10100 : {
10101 0 : tmp = build_call_expr_loc (loc, isnan_fn, 1, arg);
10102 0 : tmp = fold_build2_loc (loc, NE_EXPR, integer_type_node, tmp,
10103 : integer_zero_node);
10104 0 : res = fold_build3_loc (loc, COND_EXPR, integer_type_node, tmp,
10105 : fp_nan, res);
10106 : }
10107 :
10108 104982 : return res;
10109 : }
10110 : }
10111 :
10112 104982 : arg = builtin_save_expr (fold_build1_loc (loc, ABS_EXPR, type, arg));
10113 :
10114 : /* fpclassify(x) ->
10115 : isnan(x) ? FP_NAN :
10116 : (fabs(x) == Inf ? FP_INFINITE :
10117 : (fabs(x) >= DBL_MIN ? FP_NORMAL :
10118 : (x == 0 ? FP_ZERO : FP_SUBNORMAL))). */
10119 :
10120 104982 : tmp = fold_build2_loc (loc, EQ_EXPR, integer_type_node, arg,
10121 : build_real (type, dconst0));
10122 104982 : res = fold_build3_loc (loc, COND_EXPR, integer_type_node,
10123 : tmp, fp_zero, fp_subnormal);
10124 :
10125 104982 : if (DECIMAL_FLOAT_MODE_P (mode))
10126 3 : sprintf (buf, "1E%d", REAL_MODE_FORMAT (mode)->emin - 1);
10127 : else
10128 104979 : sprintf (buf, "0x1p%d", REAL_MODE_FORMAT (mode)->emin - 1);
10129 104982 : real_from_string3 (&r, buf, mode);
10130 104982 : tmp = fold_build2_loc (loc, GE_EXPR, integer_type_node,
10131 : arg, build_real (type, r));
10132 104982 : res = fold_build3_loc (loc, COND_EXPR, integer_type_node, tmp,
10133 : fp_normal, res);
10134 :
10135 104982 : if (tree_expr_maybe_infinite_p (arg))
10136 : {
10137 104894 : tmp = fold_build2_loc (loc, EQ_EXPR, integer_type_node, arg,
10138 : build_real (type, dconstinf));
10139 104894 : res = fold_build3_loc (loc, COND_EXPR, integer_type_node, tmp,
10140 : fp_infinite, res);
10141 : }
10142 :
10143 104982 : if (tree_expr_maybe_nan_p (arg))
10144 : {
10145 104892 : tmp = fold_build2_loc (loc, ORDERED_EXPR, integer_type_node, arg, arg);
10146 104892 : res = fold_build3_loc (loc, COND_EXPR, integer_type_node, tmp,
10147 : res, fp_nan);
10148 : }
10149 :
10150 : return res;
10151 : }
10152 :
10153 : /* Fold a call to an unordered comparison function such as
10154 : __builtin_isgreater(). FNDECL is the FUNCTION_DECL for the function
10155 : being called and ARG0 and ARG1 are the arguments for the call.
10156 : UNORDERED_CODE and ORDERED_CODE are comparison codes that give
10157 : the opposite of the desired result. UNORDERED_CODE is used
10158 : for modes that can hold NaNs and ORDERED_CODE is used for
10159 : the rest. */
10160 :
10161 : static tree
10162 3272361 : fold_builtin_unordered_cmp (location_t loc, tree fndecl, tree arg0, tree arg1,
10163 : enum tree_code unordered_code,
10164 : enum tree_code ordered_code)
10165 : {
10166 3272361 : tree type = TREE_TYPE (TREE_TYPE (fndecl));
10167 3272361 : enum tree_code code;
10168 3272361 : tree type0, type1;
10169 3272361 : enum tree_code code0, code1;
10170 3272361 : tree cmp_type = NULL_TREE;
10171 :
10172 3272361 : type0 = TREE_TYPE (arg0);
10173 3272361 : type1 = TREE_TYPE (arg1);
10174 :
10175 3272361 : code0 = TREE_CODE (type0);
10176 3272361 : code1 = TREE_CODE (type1);
10177 :
10178 3272361 : if (code0 == REAL_TYPE && code1 == REAL_TYPE)
10179 : /* Choose the wider of two real types. */
10180 3272181 : cmp_type = TYPE_PRECISION (type0) >= TYPE_PRECISION (type1)
10181 3272181 : ? type0 : type1;
10182 180 : else if (code0 == REAL_TYPE
10183 91 : && (code1 == INTEGER_TYPE || code1 == BITINT_TYPE))
10184 : cmp_type = type0;
10185 89 : else if ((code0 == INTEGER_TYPE || code0 == BITINT_TYPE)
10186 89 : && code1 == REAL_TYPE)
10187 135 : cmp_type = type1;
10188 :
10189 3272361 : arg0 = fold_convert_loc (loc, cmp_type, arg0);
10190 3272361 : arg1 = fold_convert_loc (loc, cmp_type, arg1);
10191 :
10192 3272361 : if (unordered_code == UNORDERED_EXPR)
10193 : {
10194 241975 : if (tree_expr_nan_p (arg0) || tree_expr_nan_p (arg1))
10195 16 : return omit_two_operands_loc (loc, type, integer_one_node, arg0, arg1);
10196 241959 : if (!tree_expr_maybe_nan_p (arg0) && !tree_expr_maybe_nan_p (arg1))
10197 141 : return omit_two_operands_loc (loc, type, integer_zero_node, arg0, arg1);
10198 241818 : return fold_build2_loc (loc, UNORDERED_EXPR, type, arg0, arg1);
10199 : }
10200 :
10201 3033237 : code = (tree_expr_maybe_nan_p (arg0) || tree_expr_maybe_nan_p (arg1))
10202 3030386 : ? unordered_code : ordered_code;
10203 3030386 : return fold_build1_loc (loc, TRUTH_NOT_EXPR, type,
10204 3030386 : fold_build2_loc (loc, code, type, arg0, arg1));
10205 : }
10206 :
10207 : /* Fold a call to __builtin_iseqsig(). ARG0 and ARG1 are the arguments.
10208 : After choosing the wider floating-point type for the comparison,
10209 : the code is folded to:
10210 : SAVE_EXPR<ARG0> >= SAVE_EXPR<ARG1> && SAVE_EXPR<ARG0> <= SAVE_EXPR<ARG1> */
10211 :
10212 : static tree
10213 709 : fold_builtin_iseqsig (location_t loc, tree arg0, tree arg1)
10214 : {
10215 709 : tree type0, type1;
10216 709 : enum tree_code code0, code1;
10217 709 : tree cmp1, cmp2, cmp_type = NULL_TREE;
10218 :
10219 709 : type0 = TREE_TYPE (arg0);
10220 709 : type1 = TREE_TYPE (arg1);
10221 :
10222 709 : code0 = TREE_CODE (type0);
10223 709 : code1 = TREE_CODE (type1);
10224 :
10225 709 : if (code0 == REAL_TYPE && code1 == REAL_TYPE)
10226 : /* Choose the wider of two real types. */
10227 690 : cmp_type = TYPE_PRECISION (type0) >= TYPE_PRECISION (type1)
10228 690 : ? type0 : type1;
10229 19 : else if (code0 == REAL_TYPE
10230 6 : && (code1 == INTEGER_TYPE || code1 == BITINT_TYPE))
10231 : cmp_type = type0;
10232 13 : else if ((code0 == INTEGER_TYPE || code0 == BITINT_TYPE)
10233 13 : && code1 == REAL_TYPE)
10234 13 : cmp_type = type1;
10235 :
10236 709 : arg0 = builtin_save_expr (fold_convert_loc (loc, cmp_type, arg0));
10237 709 : arg1 = builtin_save_expr (fold_convert_loc (loc, cmp_type, arg1));
10238 :
10239 709 : cmp1 = fold_build2_loc (loc, GE_EXPR, integer_type_node, arg0, arg1);
10240 709 : cmp2 = fold_build2_loc (loc, LE_EXPR, integer_type_node, arg0, arg1);
10241 :
10242 709 : return fold_build2_loc (loc, TRUTH_AND_EXPR, integer_type_node, cmp1, cmp2);
10243 : }
10244 :
10245 : /* Fold __builtin_{,s,u}{add,sub,mul}{,l,ll}_overflow, either into normal
10246 : arithmetics if it can never overflow, or into internal functions that
10247 : return both result of arithmetics and overflowed boolean flag in
10248 : a complex integer result, or some other check for overflow.
10249 : Similarly fold __builtin_{add,sub,mul}_overflow_p to just the overflow
10250 : checking part of that. */
10251 :
10252 : static tree
10253 511299 : fold_builtin_arith_overflow (location_t loc, enum built_in_function fcode,
10254 : tree arg0, tree arg1, tree arg2)
10255 : {
10256 511299 : enum internal_fn ifn = IFN_LAST;
10257 : /* The code of the expression corresponding to the built-in. */
10258 511299 : enum tree_code opcode = ERROR_MARK;
10259 511299 : bool ovf_only = false;
10260 :
10261 511299 : switch (fcode)
10262 : {
10263 : case BUILT_IN_ADD_OVERFLOW_P:
10264 : ovf_only = true;
10265 : /* FALLTHRU */
10266 : case BUILT_IN_ADD_OVERFLOW:
10267 : case BUILT_IN_SADD_OVERFLOW:
10268 : case BUILT_IN_SADDL_OVERFLOW:
10269 : case BUILT_IN_SADDLL_OVERFLOW:
10270 : case BUILT_IN_UADD_OVERFLOW:
10271 : case BUILT_IN_UADDL_OVERFLOW:
10272 : case BUILT_IN_UADDLL_OVERFLOW:
10273 : opcode = PLUS_EXPR;
10274 : ifn = IFN_ADD_OVERFLOW;
10275 : break;
10276 15577 : case BUILT_IN_SUB_OVERFLOW_P:
10277 15577 : ovf_only = true;
10278 : /* FALLTHRU */
10279 37597 : case BUILT_IN_SUB_OVERFLOW:
10280 37597 : case BUILT_IN_SSUB_OVERFLOW:
10281 37597 : case BUILT_IN_SSUBL_OVERFLOW:
10282 37597 : case BUILT_IN_SSUBLL_OVERFLOW:
10283 37597 : case BUILT_IN_USUB_OVERFLOW:
10284 37597 : case BUILT_IN_USUBL_OVERFLOW:
10285 37597 : case BUILT_IN_USUBLL_OVERFLOW:
10286 37597 : opcode = MINUS_EXPR;
10287 37597 : ifn = IFN_SUB_OVERFLOW;
10288 37597 : break;
10289 15878 : case BUILT_IN_MUL_OVERFLOW_P:
10290 15878 : ovf_only = true;
10291 : /* FALLTHRU */
10292 434159 : case BUILT_IN_MUL_OVERFLOW:
10293 434159 : case BUILT_IN_SMUL_OVERFLOW:
10294 434159 : case BUILT_IN_SMULL_OVERFLOW:
10295 434159 : case BUILT_IN_SMULLL_OVERFLOW:
10296 434159 : case BUILT_IN_UMUL_OVERFLOW:
10297 434159 : case BUILT_IN_UMULL_OVERFLOW:
10298 434159 : case BUILT_IN_UMULLL_OVERFLOW:
10299 434159 : opcode = MULT_EXPR;
10300 434159 : ifn = IFN_MUL_OVERFLOW;
10301 434159 : break;
10302 0 : default:
10303 0 : gcc_unreachable ();
10304 : }
10305 :
10306 : /* For the "generic" overloads, the first two arguments can have different
10307 : types and the last argument determines the target type to use to check
10308 : for overflow. The arguments of the other overloads all have the same
10309 : type. */
10310 511299 : tree type = ovf_only ? TREE_TYPE (arg2) : TREE_TYPE (TREE_TYPE (arg2));
10311 :
10312 : /* For the __builtin_{add,sub,mul}_overflow_p builtins, when the first two
10313 : arguments are constant, attempt to fold the built-in call into a constant
10314 : expression indicating whether or not it detected an overflow. */
10315 511299 : if (ovf_only
10316 43265 : && TREE_CODE (arg0) == INTEGER_CST
10317 13131 : && TREE_CODE (arg1) == INTEGER_CST)
10318 : /* Perform the computation in the target type and check for overflow. */
10319 7347 : return omit_one_operand_loc (loc, boolean_type_node,
10320 7347 : arith_overflowed_p (opcode, type, arg0, arg1)
10321 : ? boolean_true_node : boolean_false_node,
10322 7347 : arg2);
10323 :
10324 503952 : tree intres, ovfres;
10325 503952 : if (TREE_CODE (arg0) == INTEGER_CST && TREE_CODE (arg1) == INTEGER_CST)
10326 : {
10327 88954 : intres = fold_binary_loc (loc, opcode, type,
10328 : fold_convert_loc (loc, type, arg0),
10329 : fold_convert_loc (loc, type, arg1));
10330 88954 : if (TREE_OVERFLOW (intres))
10331 1629 : intres = drop_tree_overflow (intres);
10332 177908 : ovfres = (arith_overflowed_p (opcode, type, arg0, arg1)
10333 88954 : ? boolean_true_node : boolean_false_node);
10334 : }
10335 : else
10336 : {
10337 414998 : tree ctype = build_complex_type (type);
10338 414998 : tree call = build_call_expr_internal_loc (loc, ifn, ctype, 2,
10339 : arg0, arg1);
10340 414998 : tree tgt;
10341 414998 : if (ovf_only)
10342 : {
10343 : tgt = call;
10344 414998 : intres = NULL_TREE;
10345 : }
10346 : else
10347 : {
10348 : /* Force SAVE_EXPR even for calls which satisfy tree_invariant_p_1,
10349 : as while the call itself is const, the REALPART_EXPR store is
10350 : certainly not. And in any case, we want just one call,
10351 : not multiple and trying to CSE them later. */
10352 379080 : TREE_SIDE_EFFECTS (call) = 1;
10353 379080 : tgt = save_expr (call);
10354 : }
10355 414998 : intres = build1_loc (loc, REALPART_EXPR, type, tgt);
10356 414998 : ovfres = build1_loc (loc, IMAGPART_EXPR, type, tgt);
10357 414998 : ovfres = fold_convert_loc (loc, boolean_type_node, ovfres);
10358 : }
10359 :
10360 503952 : if (ovf_only)
10361 35918 : return omit_one_operand_loc (loc, boolean_type_node, ovfres, arg2);
10362 :
10363 468034 : tree mem_arg2 = build_fold_indirect_ref_loc (loc, arg2);
10364 468034 : tree store
10365 468034 : = fold_build2_loc (loc, MODIFY_EXPR, void_type_node, mem_arg2, intres);
10366 468034 : return build2_loc (loc, COMPOUND_EXPR, boolean_type_node, store, ovfres);
10367 : }
10368 :
10369 : /* Fold __builtin_{clz,ctz,clrsb,ffs,parity,popcount}g into corresponding
10370 : internal function. */
10371 :
10372 : static tree
10373 267151 : fold_builtin_bit_query (location_t loc, enum built_in_function fcode,
10374 : tree arg0, tree arg1)
10375 : {
10376 267151 : enum internal_fn ifn;
10377 267151 : enum built_in_function fcodei, fcodel, fcodell;
10378 267151 : tree arg0_type = TREE_TYPE (arg0);
10379 267151 : tree cast_type = NULL_TREE;
10380 267151 : int addend = 0;
10381 :
10382 267151 : switch (fcode)
10383 : {
10384 188435 : case BUILT_IN_CLZG:
10385 188435 : if (arg1 && TREE_CODE (arg1) != INTEGER_CST)
10386 : return NULL_TREE;
10387 : ifn = IFN_CLZ;
10388 : fcodei = BUILT_IN_CLZ;
10389 : fcodel = BUILT_IN_CLZL;
10390 : fcodell = BUILT_IN_CLZLL;
10391 : break;
10392 67237 : case BUILT_IN_CTZG:
10393 67237 : if (arg1 && TREE_CODE (arg1) != INTEGER_CST)
10394 : return NULL_TREE;
10395 : ifn = IFN_CTZ;
10396 : fcodei = BUILT_IN_CTZ;
10397 : fcodel = BUILT_IN_CTZL;
10398 : fcodell = BUILT_IN_CTZLL;
10399 : break;
10400 : case BUILT_IN_CLRSBG:
10401 : ifn = IFN_CLRSB;
10402 : fcodei = BUILT_IN_CLRSB;
10403 : fcodel = BUILT_IN_CLRSBL;
10404 : fcodell = BUILT_IN_CLRSBLL;
10405 : break;
10406 84 : case BUILT_IN_FFSG:
10407 84 : ifn = IFN_FFS;
10408 84 : fcodei = BUILT_IN_FFS;
10409 84 : fcodel = BUILT_IN_FFSL;
10410 84 : fcodell = BUILT_IN_FFSLL;
10411 84 : break;
10412 82 : case BUILT_IN_PARITYG:
10413 82 : ifn = IFN_PARITY;
10414 82 : fcodei = BUILT_IN_PARITY;
10415 82 : fcodel = BUILT_IN_PARITYL;
10416 82 : fcodell = BUILT_IN_PARITYLL;
10417 82 : break;
10418 11231 : case BUILT_IN_POPCOUNTG:
10419 11231 : ifn = IFN_POPCOUNT;
10420 11231 : fcodei = BUILT_IN_POPCOUNT;
10421 11231 : fcodel = BUILT_IN_POPCOUNTL;
10422 11231 : fcodell = BUILT_IN_POPCOUNTLL;
10423 11231 : break;
10424 0 : default:
10425 0 : gcc_unreachable ();
10426 : }
10427 :
10428 266948 : if (TYPE_PRECISION (arg0_type)
10429 266948 : <= TYPE_PRECISION (long_long_unsigned_type_node))
10430 : {
10431 227681 : if (TYPE_PRECISION (arg0_type) <= TYPE_PRECISION (unsigned_type_node))
10432 :
10433 79774 : cast_type = (TYPE_UNSIGNED (arg0_type)
10434 79720 : ? unsigned_type_node : integer_type_node);
10435 147961 : else if (TYPE_PRECISION (arg0_type)
10436 147961 : <= TYPE_PRECISION (long_unsigned_type_node))
10437 : {
10438 147910 : cast_type = (TYPE_UNSIGNED (arg0_type)
10439 147838 : ? long_unsigned_type_node : long_integer_type_node);
10440 : fcodei = fcodel;
10441 : }
10442 : else
10443 : {
10444 123 : cast_type = (TYPE_UNSIGNED (arg0_type)
10445 123 : ? long_long_unsigned_type_node
10446 : : long_long_integer_type_node);
10447 : fcodei = fcodell;
10448 : }
10449 : }
10450 78534 : else if (TYPE_PRECISION (arg0_type) <= MAX_FIXED_MODE_SIZE)
10451 : {
10452 39157 : cast_type
10453 39157 : = build_nonstandard_integer_type (MAX_FIXED_MODE_SIZE,
10454 39157 : TYPE_UNSIGNED (arg0_type));
10455 39157 : gcc_assert (TYPE_PRECISION (cast_type)
10456 : == 2 * TYPE_PRECISION (long_long_unsigned_type_node));
10457 : fcodei = END_BUILTINS;
10458 : }
10459 : else
10460 : fcodei = END_BUILTINS;
10461 266838 : if (cast_type)
10462 : {
10463 266838 : switch (fcode)
10464 : {
10465 188384 : case BUILT_IN_CLZG:
10466 188384 : case BUILT_IN_CLRSBG:
10467 188384 : addend = TYPE_PRECISION (arg0_type) - TYPE_PRECISION (cast_type);
10468 188384 : break;
10469 : default:
10470 : break;
10471 : }
10472 266838 : arg0 = fold_convert (cast_type, arg0);
10473 266838 : arg0_type = cast_type;
10474 : }
10475 :
10476 266948 : if (arg1)
10477 177049 : arg1 = fold_convert (integer_type_node, arg1);
10478 :
10479 266948 : tree arg2 = arg1;
10480 266948 : if (fcode == BUILT_IN_CLZG && addend)
10481 : {
10482 4389 : if (arg1)
10483 4356 : arg0 = save_expr (arg0);
10484 : arg2 = NULL_TREE;
10485 : }
10486 266948 : tree call = NULL_TREE, tem;
10487 266948 : if (TYPE_PRECISION (arg0_type) == MAX_FIXED_MODE_SIZE
10488 39280 : && (TYPE_PRECISION (arg0_type)
10489 39280 : == 2 * TYPE_PRECISION (long_long_unsigned_type_node))
10490 : /* If the target supports the optab, then don't do the expansion. */
10491 306105 : && !direct_internal_fn_supported_p (ifn, arg0_type, OPTIMIZE_FOR_BOTH))
10492 : {
10493 : /* __int128 expansions using up to 2 long long builtins. */
10494 39157 : arg0 = save_expr (arg0);
10495 39157 : tree type = (TYPE_UNSIGNED (arg0_type)
10496 39157 : ? long_long_unsigned_type_node
10497 39157 : : long_long_integer_type_node);
10498 78314 : tree hi = fold_build2 (RSHIFT_EXPR, arg0_type, arg0,
10499 : build_int_cst (integer_type_node,
10500 : MAX_FIXED_MODE_SIZE / 2));
10501 39157 : hi = fold_convert (type, hi);
10502 39157 : tree lo = fold_convert (type, arg0);
10503 39157 : switch (fcode)
10504 : {
10505 39068 : case BUILT_IN_CLZG:
10506 39068 : call = fold_builtin_bit_query (loc, fcode, lo, NULL_TREE);
10507 78136 : call = fold_build2 (PLUS_EXPR, integer_type_node, call,
10508 : build_int_cst (integer_type_node,
10509 : MAX_FIXED_MODE_SIZE / 2));
10510 39068 : if (arg2)
10511 39048 : call = fold_build3 (COND_EXPR, integer_type_node,
10512 : fold_build2 (NE_EXPR, boolean_type_node,
10513 : lo, build_zero_cst (type)),
10514 : call, arg2);
10515 39068 : call = fold_build3 (COND_EXPR, integer_type_node,
10516 : fold_build2 (NE_EXPR, boolean_type_node,
10517 : hi, build_zero_cst (type)),
10518 : fold_builtin_bit_query (loc, fcode, hi,
10519 : NULL_TREE),
10520 : call);
10521 39068 : break;
10522 27 : case BUILT_IN_CTZG:
10523 27 : call = fold_builtin_bit_query (loc, fcode, hi, NULL_TREE);
10524 54 : call = fold_build2 (PLUS_EXPR, integer_type_node, call,
10525 : build_int_cst (integer_type_node,
10526 : MAX_FIXED_MODE_SIZE / 2));
10527 27 : if (arg2)
10528 18 : call = fold_build3 (COND_EXPR, integer_type_node,
10529 : fold_build2 (NE_EXPR, boolean_type_node,
10530 : hi, build_zero_cst (type)),
10531 : call, arg2);
10532 27 : call = fold_build3 (COND_EXPR, integer_type_node,
10533 : fold_build2 (NE_EXPR, boolean_type_node,
10534 : lo, build_zero_cst (type)),
10535 : fold_builtin_bit_query (loc, fcode, lo,
10536 : NULL_TREE),
10537 : call);
10538 27 : break;
10539 9 : case BUILT_IN_CLRSBG:
10540 9 : tem = fold_builtin_bit_query (loc, fcode, lo, NULL_TREE);
10541 18 : tem = fold_build2 (PLUS_EXPR, integer_type_node, tem,
10542 : build_int_cst (integer_type_node,
10543 : MAX_FIXED_MODE_SIZE / 2));
10544 18 : tem = fold_build3 (COND_EXPR, integer_type_node,
10545 : fold_build2 (LT_EXPR, boolean_type_node,
10546 : fold_build2 (BIT_XOR_EXPR, type,
10547 : lo, hi),
10548 : build_zero_cst (type)),
10549 : build_int_cst (integer_type_node,
10550 : MAX_FIXED_MODE_SIZE / 2 - 1),
10551 : tem);
10552 9 : call = fold_builtin_bit_query (loc, fcode, hi, NULL_TREE);
10553 9 : call = save_expr (call);
10554 18 : call = fold_build3 (COND_EXPR, integer_type_node,
10555 : fold_build2 (NE_EXPR, boolean_type_node,
10556 : call,
10557 : build_int_cst (integer_type_node,
10558 : MAX_FIXED_MODE_SIZE
10559 : / 2 - 1)),
10560 : call, tem);
10561 9 : break;
10562 9 : case BUILT_IN_FFSG:
10563 9 : call = fold_builtin_bit_query (loc, fcode, hi, NULL_TREE);
10564 18 : call = fold_build2 (PLUS_EXPR, integer_type_node, call,
10565 : build_int_cst (integer_type_node,
10566 : MAX_FIXED_MODE_SIZE / 2));
10567 9 : call = fold_build3 (COND_EXPR, integer_type_node,
10568 : fold_build2 (NE_EXPR, boolean_type_node,
10569 : hi, build_zero_cst (type)),
10570 : call, integer_zero_node);
10571 9 : call = fold_build3 (COND_EXPR, integer_type_node,
10572 : fold_build2 (NE_EXPR, boolean_type_node,
10573 : lo, build_zero_cst (type)),
10574 : fold_builtin_bit_query (loc, fcode, lo,
10575 : NULL_TREE),
10576 : call);
10577 9 : break;
10578 9 : case BUILT_IN_PARITYG:
10579 9 : call = fold_builtin_bit_query (loc, fcode,
10580 : fold_build2 (BIT_XOR_EXPR, type,
10581 : lo, hi), NULL_TREE);
10582 9 : break;
10583 35 : case BUILT_IN_POPCOUNTG:
10584 35 : call = fold_build2 (PLUS_EXPR, integer_type_node,
10585 : fold_builtin_bit_query (loc, fcode, hi,
10586 : NULL_TREE),
10587 : fold_builtin_bit_query (loc, fcode, lo,
10588 : NULL_TREE));
10589 35 : break;
10590 : default:
10591 : gcc_unreachable ();
10592 : }
10593 : }
10594 : else
10595 : {
10596 : /* Only keep second argument to IFN_CLZ/IFN_CTZ if it is the
10597 : value defined at zero during GIMPLE, or for large/huge _BitInt
10598 : (which are then lowered during bitint lowering). */
10599 227791 : if (arg2 && !BITINT_TYPE_P (TREE_TYPE (arg0)))
10600 : {
10601 133607 : int val;
10602 133607 : if (fcode == BUILT_IN_CLZG)
10603 : {
10604 66664 : if (CLZ_DEFINED_VALUE_AT_ZERO (SCALAR_TYPE_MODE (arg0_type),
10605 : val) != 2
10606 66664 : || wi::to_widest (arg2) != val)
10607 : arg2 = NULL_TREE;
10608 : }
10609 66943 : else if (CTZ_DEFINED_VALUE_AT_ZERO (SCALAR_TYPE_MODE (arg0_type),
10610 : val) != 2
10611 66943 : || wi::to_widest (arg2) != val)
10612 : arg2 = NULL_TREE;
10613 133607 : if (!direct_internal_fn_supported_p (ifn, arg0_type,
10614 : OPTIMIZE_FOR_BOTH))
10615 : arg2 = NULL_TREE;
10616 133496 : if (arg2 == NULL_TREE)
10617 133560 : arg0 = save_expr (arg0);
10618 : }
10619 227791 : if (fcodei == END_BUILTINS || arg2)
10620 247 : call = build_call_expr_internal_loc (loc, ifn, integer_type_node,
10621 : arg2 ? 2 : 1, arg0, arg2);
10622 : else
10623 227634 : call = build_call_expr_loc (loc, builtin_decl_explicit (fcodei), 1,
10624 : arg0);
10625 : }
10626 266948 : if (addend)
10627 4407 : call = fold_build2 (PLUS_EXPR, integer_type_node, call,
10628 : build_int_cst (integer_type_node, addend));
10629 266948 : if (arg1 && arg2 == NULL_TREE)
10630 137916 : call = fold_build3 (COND_EXPR, integer_type_node,
10631 : fold_build2 (NE_EXPR, boolean_type_node,
10632 : arg0, build_zero_cst (arg0_type)),
10633 : call, arg1);
10634 :
10635 : return call;
10636 : }
10637 :
10638 : /* Fold or build a __builtin_bswapg (ARG) (if IFN is IFN_BSWAP) or
10639 : __builtin_bitreverseg (ARG (otherwise) call. The FE should have
10640 : verified earlier that the argument type is unsigned INTEGER_TYPE
10641 : or BITINT_TYPE, for __builtin_bswapg with precision divisible by 8. */
10642 :
10643 : tree
10644 218 : fold_build_builtin_bswapg_bitreverseg (location_t loc, enum internal_fn ifn,
10645 : tree arg)
10646 : {
10647 218 : tree type = TYPE_MAIN_VARIANT (TREE_TYPE (arg));
10648 218 : if (ifn == IFN_BSWAP && TYPE_PRECISION (type) == 8)
10649 11 : return fold_convert_loc (loc, type, arg);
10650 207 : struct { tree type; built_in_function bswap, bitreverse; } fns[]
10651 207 : = { { unsigned_char_type_node, END_BUILTINS, BUILT_IN_BITREVERSE8 },
10652 207 : { uint16_type_node, BUILT_IN_BSWAP16, BUILT_IN_BITREVERSE16 },
10653 207 : { uint32_type_node, BUILT_IN_BSWAP32, BUILT_IN_BITREVERSE32 },
10654 207 : { uint64_type_node, BUILT_IN_BSWAP64, BUILT_IN_BITREVERSE64 },
10655 207 : { uint128_type_node, BUILT_IN_BSWAP128, BUILT_IN_BITREVERSE128 } };
10656 207 : if (TREE_CODE (arg) == INTEGER_CST)
10657 : {
10658 127 : wide_int res;
10659 127 : if (ifn == IFN_BSWAP)
10660 37 : res = wi::bswap (wi::to_wide (arg));
10661 : else
10662 96 : res = wi::bitreverse (wi::to_wide (arg));
10663 127 : return wide_int_to_tree (type, res);
10664 127 : }
10665 346 : for (unsigned i = 0; i < ARRAY_SIZE (fns); ++i)
10666 314 : if (fns[i].type
10667 314 : && TYPE_PRECISION (fns[i].type) >= TYPE_PRECISION (type))
10668 : {
10669 48 : arg = fold_convert_loc (loc, fns[i].type, arg);
10670 48 : tree fndecl
10671 48 : = builtin_decl_explicit (ifn == IFN_BSWAP
10672 : ? fns[i].bswap : fns[i].bitreverse);
10673 48 : tree ret = build_call_expr_loc (loc, fndecl, 1, arg);
10674 48 : if (TYPE_PRECISION (type) != TYPE_PRECISION (fns[i].type))
10675 4 : ret = fold_build2_loc (loc, RSHIFT_EXPR, fns[i].type, ret,
10676 : build_int_cst (unsigned_type_node,
10677 4 : TYPE_PRECISION (fns[i].type)
10678 4 : - TYPE_PRECISION (type)));
10679 48 : return fold_convert_loc (loc, type, ret);
10680 : }
10681 32 : gcc_assert (TREE_CODE (type) == BITINT_TYPE);
10682 32 : return build_call_expr_internal_loc (loc, ifn, type, 1, arg);
10683 : }
10684 :
10685 : /* Fold __builtin_{add,sub}c{,l,ll} into pair of internal functions
10686 : that return both result of arithmetics and overflowed boolean
10687 : flag in a complex integer result. */
10688 :
10689 : static tree
10690 55 : fold_builtin_addc_subc (location_t loc, enum built_in_function fcode,
10691 : tree *args)
10692 : {
10693 55 : enum internal_fn ifn;
10694 :
10695 55 : switch (fcode)
10696 : {
10697 : case BUILT_IN_ADDC:
10698 : case BUILT_IN_ADDCL:
10699 : case BUILT_IN_ADDCLL:
10700 : ifn = IFN_ADD_OVERFLOW;
10701 : break;
10702 29 : case BUILT_IN_SUBC:
10703 29 : case BUILT_IN_SUBCL:
10704 29 : case BUILT_IN_SUBCLL:
10705 29 : ifn = IFN_SUB_OVERFLOW;
10706 29 : break;
10707 0 : default:
10708 0 : gcc_unreachable ();
10709 : }
10710 :
10711 55 : tree type = TREE_TYPE (args[0]);
10712 55 : tree ctype = build_complex_type (type);
10713 55 : tree call = build_call_expr_internal_loc (loc, ifn, ctype, 2,
10714 : args[0], args[1]);
10715 : /* Force SAVE_EXPR even for calls which satisfy tree_invariant_p_1,
10716 : as while the call itself is const, the REALPART_EXPR store is
10717 : certainly not. And in any case, we want just one call,
10718 : not multiple and trying to CSE them later. */
10719 55 : TREE_SIDE_EFFECTS (call) = 1;
10720 55 : tree tgt = save_expr (call);
10721 55 : tree intres = build1_loc (loc, REALPART_EXPR, type, tgt);
10722 55 : tree ovfres = build1_loc (loc, IMAGPART_EXPR, type, tgt);
10723 55 : call = build_call_expr_internal_loc (loc, ifn, ctype, 2,
10724 : intres, args[2]);
10725 55 : TREE_SIDE_EFFECTS (call) = 1;
10726 55 : tgt = save_expr (call);
10727 55 : intres = build1_loc (loc, REALPART_EXPR, type, tgt);
10728 55 : tree ovfres2 = build1_loc (loc, IMAGPART_EXPR, type, tgt);
10729 55 : ovfres = build2_loc (loc, BIT_IOR_EXPR, type, ovfres, ovfres2);
10730 55 : tree mem_arg3 = build_fold_indirect_ref_loc (loc, args[3]);
10731 55 : tree store
10732 55 : = fold_build2_loc (loc, MODIFY_EXPR, void_type_node, mem_arg3, ovfres);
10733 55 : return build2_loc (loc, COMPOUND_EXPR, type, store, intres);
10734 : }
10735 :
10736 : /* Fold a call to __builtin_FILE to a constant string. */
10737 :
10738 : static inline tree
10739 5939 : fold_builtin_FILE (location_t loc)
10740 : {
10741 5939 : if (const char *fname = LOCATION_FILE (loc))
10742 : {
10743 : /* The documentation says this builtin is equivalent to the preprocessor
10744 : __FILE__ macro so it appears appropriate to use the same file prefix
10745 : mappings. */
10746 5939 : fname = remap_macro_filename (fname);
10747 5939 : return build_string_literal (fname);
10748 : }
10749 :
10750 0 : return build_string_literal ("");
10751 : }
10752 :
10753 : /* Fold a call to __builtin_FUNCTION to a constant string. */
10754 :
10755 : static inline tree
10756 68 : fold_builtin_FUNCTION ()
10757 : {
10758 68 : const char *name = "";
10759 :
10760 68 : if (current_function_decl)
10761 43 : name = lang_hooks.decl_printable_name (current_function_decl, 0);
10762 :
10763 68 : return build_string_literal (name);
10764 : }
10765 :
10766 : /* Fold a call to __builtin_LINE to an integer constant. */
10767 :
10768 : static inline tree
10769 11845 : fold_builtin_LINE (location_t loc, tree type)
10770 : {
10771 11845 : return build_int_cst (type, LOCATION_LINE (loc));
10772 : }
10773 :
10774 : /* Fold a call to built-in function FNDECL with 0 arguments.
10775 : This function returns NULL_TREE if no simplification was possible. */
10776 :
10777 : static tree
10778 24135509 : fold_builtin_0 (location_t loc, tree fndecl)
10779 : {
10780 24135509 : tree type = TREE_TYPE (TREE_TYPE (fndecl));
10781 24135509 : enum built_in_function fcode = DECL_FUNCTION_CODE (fndecl);
10782 24135509 : switch (fcode)
10783 : {
10784 5939 : case BUILT_IN_FILE:
10785 5939 : return fold_builtin_FILE (loc);
10786 :
10787 68 : case BUILT_IN_FUNCTION:
10788 68 : return fold_builtin_FUNCTION ();
10789 :
10790 11845 : case BUILT_IN_LINE:
10791 11845 : return fold_builtin_LINE (loc, type);
10792 :
10793 33954 : CASE_FLT_FN (BUILT_IN_INF):
10794 33954 : CASE_FLT_FN_FLOATN_NX (BUILT_IN_INF):
10795 33954 : case BUILT_IN_INFD32:
10796 33954 : case BUILT_IN_INFD64:
10797 33954 : case BUILT_IN_INFD128:
10798 33954 : case BUILT_IN_INFD64X:
10799 33954 : return fold_builtin_inf (loc, type, true);
10800 :
10801 230593 : CASE_FLT_FN (BUILT_IN_HUGE_VAL):
10802 230593 : CASE_FLT_FN_FLOATN_NX (BUILT_IN_HUGE_VAL):
10803 230593 : return fold_builtin_inf (loc, type, false);
10804 :
10805 0 : case BUILT_IN_CLASSIFY_TYPE:
10806 0 : return fold_builtin_classify_type (NULL_TREE);
10807 :
10808 20661913 : case BUILT_IN_UNREACHABLE:
10809 : /* Rewrite any explicit calls to __builtin_unreachable. */
10810 20661913 : if (sanitize_flags_p (SANITIZE_UNREACHABLE))
10811 91 : return build_builtin_unreachable (loc);
10812 : break;
10813 :
10814 : default:
10815 : break;
10816 : }
10817 : return NULL_TREE;
10818 : }
10819 :
10820 : /* Fold a call to built-in function FNDECL with 1 argument, ARG0.
10821 : This function returns NULL_TREE if no simplification was possible. */
10822 :
10823 : static tree
10824 20330621 : fold_builtin_1 (location_t loc, tree expr, tree fndecl, tree arg0)
10825 : {
10826 20330621 : tree type = TREE_TYPE (TREE_TYPE (fndecl));
10827 20330621 : enum built_in_function fcode = DECL_FUNCTION_CODE (fndecl);
10828 :
10829 20330621 : if (error_operand_p (arg0))
10830 : return NULL_TREE;
10831 :
10832 20330621 : if (tree ret = fold_const_call (as_combined_fn (fcode), type, arg0))
10833 : return ret;
10834 :
10835 19700707 : switch (fcode)
10836 : {
10837 3120931 : case BUILT_IN_CONSTANT_P:
10838 3120931 : {
10839 3120931 : tree val = fold_builtin_constant_p (arg0);
10840 :
10841 : /* Gimplification will pull the CALL_EXPR for the builtin out of
10842 : an if condition. When not optimizing, we'll not CSE it back.
10843 : To avoid link error types of regressions, return false now. */
10844 3120931 : if (!val && !optimize)
10845 1558 : val = integer_zero_node;
10846 :
10847 : return val;
10848 : }
10849 :
10850 2068 : case BUILT_IN_CLASSIFY_TYPE:
10851 2068 : return fold_builtin_classify_type (arg0);
10852 :
10853 478331 : case BUILT_IN_STRLEN:
10854 478331 : return fold_builtin_strlen (loc, expr, type, arg0);
10855 :
10856 379580 : CASE_FLT_FN (BUILT_IN_FABS):
10857 379580 : CASE_FLT_FN_FLOATN_NX (BUILT_IN_FABS):
10858 379580 : case BUILT_IN_FABSD32:
10859 379580 : case BUILT_IN_FABSD64:
10860 379580 : case BUILT_IN_FABSD128:
10861 379580 : case BUILT_IN_FABSD64X:
10862 379580 : return fold_builtin_fabs (loc, arg0, type);
10863 :
10864 101470 : case BUILT_IN_ABS:
10865 101470 : case BUILT_IN_LABS:
10866 101470 : case BUILT_IN_LLABS:
10867 101470 : case BUILT_IN_IMAXABS:
10868 101470 : case BUILT_IN_UABS:
10869 101470 : case BUILT_IN_ULABS:
10870 101470 : case BUILT_IN_ULLABS:
10871 101470 : case BUILT_IN_UMAXABS:
10872 101470 : return fold_builtin_abs (loc, arg0, type);
10873 :
10874 25461 : CASE_FLT_FN (BUILT_IN_CONJ):
10875 25461 : if (validate_arg (arg0, COMPLEX_TYPE)
10876 25461 : && TREE_CODE (TREE_TYPE (TREE_TYPE (arg0))) == REAL_TYPE)
10877 25461 : return fold_build1_loc (loc, CONJ_EXPR, type, arg0);
10878 : break;
10879 :
10880 764 : CASE_FLT_FN (BUILT_IN_CREAL):
10881 764 : if (validate_arg (arg0, COMPLEX_TYPE)
10882 764 : && TREE_CODE (TREE_TYPE (TREE_TYPE (arg0))) == REAL_TYPE)
10883 764 : return non_lvalue_loc (loc, fold_build1_loc (loc, REALPART_EXPR, type, arg0));
10884 : break;
10885 :
10886 1884 : CASE_FLT_FN (BUILT_IN_CIMAG):
10887 1884 : if (validate_arg (arg0, COMPLEX_TYPE)
10888 1884 : && TREE_CODE (TREE_TYPE (TREE_TYPE (arg0))) == REAL_TYPE)
10889 1884 : return non_lvalue_loc (loc, fold_build1_loc (loc, IMAGPART_EXPR, type, arg0));
10890 : break;
10891 :
10892 104839 : CASE_FLT_FN (BUILT_IN_CARG):
10893 104839 : CASE_FLT_FN_FLOATN_NX (BUILT_IN_CARG):
10894 104839 : return fold_builtin_carg (loc, arg0, type);
10895 :
10896 211 : case BUILT_IN_ISASCII:
10897 211 : return fold_builtin_isascii (loc, arg0);
10898 :
10899 168 : case BUILT_IN_TOASCII:
10900 168 : return fold_builtin_toascii (loc, arg0);
10901 :
10902 325 : case BUILT_IN_ISDIGIT:
10903 325 : return fold_builtin_isdigit (loc, arg0);
10904 :
10905 628727 : CASE_FLT_FN (BUILT_IN_FINITE):
10906 628727 : case BUILT_IN_FINITED32:
10907 628727 : case BUILT_IN_FINITED64:
10908 628727 : case BUILT_IN_FINITED128:
10909 628727 : case BUILT_IN_ISFINITE:
10910 628727 : {
10911 628727 : tree ret = fold_builtin_classify (loc, fndecl, arg0, BUILT_IN_ISFINITE);
10912 628727 : if (ret)
10913 : return ret;
10914 628395 : return fold_builtin_interclass_mathfn (loc, fndecl, arg0);
10915 : }
10916 :
10917 713489 : CASE_FLT_FN (BUILT_IN_ISINF):
10918 713489 : case BUILT_IN_ISINFD32:
10919 713489 : case BUILT_IN_ISINFD64:
10920 713489 : case BUILT_IN_ISINFD128:
10921 713489 : {
10922 713489 : tree ret = fold_builtin_classify (loc, fndecl, arg0, BUILT_IN_ISINF);
10923 713489 : if (ret)
10924 : return ret;
10925 713238 : return fold_builtin_interclass_mathfn (loc, fndecl, arg0);
10926 : }
10927 :
10928 240988 : case BUILT_IN_ISNORMAL:
10929 240988 : return fold_builtin_interclass_mathfn (loc, fndecl, arg0);
10930 :
10931 708 : case BUILT_IN_ISINF_SIGN:
10932 708 : return fold_builtin_classify (loc, fndecl, arg0, BUILT_IN_ISINF_SIGN);
10933 :
10934 244118 : CASE_FLT_FN (BUILT_IN_ISNAN):
10935 244118 : case BUILT_IN_ISNAND32:
10936 244118 : case BUILT_IN_ISNAND64:
10937 244118 : case BUILT_IN_ISNAND128:
10938 244118 : {
10939 244118 : tree ret = fold_builtin_classify (loc, fndecl, arg0, BUILT_IN_ISNAN);
10940 244118 : if (ret)
10941 : return ret;
10942 243994 : return fold_builtin_interclass_mathfn (loc, fndecl, arg0);
10943 : }
10944 :
10945 27815 : case BUILT_IN_ISSIGNALING:
10946 27815 : return fold_builtin_classify (loc, fndecl, arg0, BUILT_IN_ISSIGNALING);
10947 :
10948 638871 : case BUILT_IN_FREE:
10949 638871 : if (integer_zerop (arg0))
10950 1082 : return build_empty_stmt (loc);
10951 : break;
10952 :
10953 11594 : case BUILT_IN_CLZG:
10954 11594 : case BUILT_IN_CTZG:
10955 11594 : case BUILT_IN_CLRSBG:
10956 11594 : case BUILT_IN_FFSG:
10957 11594 : case BUILT_IN_PARITYG:
10958 11594 : case BUILT_IN_POPCOUNTG:
10959 11594 : return fold_builtin_bit_query (loc, fcode, arg0, NULL_TREE);
10960 :
10961 : default:
10962 : break;
10963 : }
10964 :
10965 : return NULL_TREE;
10966 :
10967 : }
10968 :
10969 : /* Folds a call EXPR (which may be null) to built-in function FNDECL
10970 : with 2 arguments, ARG0 and ARG1. This function returns NULL_TREE
10971 : if no simplification was possible. */
10972 :
10973 : static tree
10974 19543824 : fold_builtin_2 (location_t loc, tree expr, tree fndecl, tree arg0, tree arg1)
10975 : {
10976 19543824 : tree type = TREE_TYPE (TREE_TYPE (fndecl));
10977 19543824 : enum built_in_function fcode = DECL_FUNCTION_CODE (fndecl);
10978 :
10979 19543824 : if (error_operand_p (arg0)
10980 19543824 : || error_operand_p (arg1))
10981 : return NULL_TREE;
10982 :
10983 19543820 : if (tree ret = fold_const_call (as_combined_fn (fcode), type, arg0, arg1))
10984 : return ret;
10985 :
10986 19326967 : switch (fcode)
10987 : {
10988 6504 : CASE_FLT_FN_REENT (BUILT_IN_GAMMA): /* GAMMA_R */
10989 6504 : CASE_FLT_FN_REENT (BUILT_IN_LGAMMA): /* LGAMMA_R */
10990 6504 : if (validate_arg (arg0, REAL_TYPE)
10991 6504 : && validate_arg (arg1, POINTER_TYPE))
10992 6504 : return do_mpfr_lgamma_r (arg0, arg1, type);
10993 : break;
10994 :
10995 116489 : CASE_FLT_FN (BUILT_IN_FREXP):
10996 116489 : return fold_builtin_frexp (loc, arg0, arg1, type);
10997 :
10998 93230 : CASE_FLT_FN (BUILT_IN_MODF):
10999 93230 : return fold_builtin_modf (loc, arg0, arg1, type);
11000 :
11001 2560 : case BUILT_IN_STRSPN:
11002 2560 : return fold_builtin_strspn (loc, expr, arg0, arg1, type);
11003 :
11004 2465 : case BUILT_IN_STRCSPN:
11005 2465 : return fold_builtin_strcspn (loc, expr, arg0, arg1, type);
11006 :
11007 100567 : case BUILT_IN_STRPBRK:
11008 100567 : return fold_builtin_strpbrk (loc, expr, arg0, arg1, type);
11009 :
11010 6774165 : case BUILT_IN_EXPECT:
11011 6774165 : return fold_builtin_expect (loc, arg0, arg1, NULL_TREE, NULL_TREE);
11012 :
11013 954385 : case BUILT_IN_ISGREATER:
11014 954385 : return fold_builtin_unordered_cmp (loc, fndecl,
11015 954385 : arg0, arg1, UNLE_EXPR, LE_EXPR);
11016 482070 : case BUILT_IN_ISGREATEREQUAL:
11017 482070 : return fold_builtin_unordered_cmp (loc, fndecl,
11018 482070 : arg0, arg1, UNLT_EXPR, LT_EXPR);
11019 242651 : case BUILT_IN_ISLESS:
11020 242651 : return fold_builtin_unordered_cmp (loc, fndecl,
11021 242651 : arg0, arg1, UNGE_EXPR, GE_EXPR);
11022 1110495 : case BUILT_IN_ISLESSEQUAL:
11023 1110495 : return fold_builtin_unordered_cmp (loc, fndecl,
11024 1110495 : arg0, arg1, UNGT_EXPR, GT_EXPR);
11025 240785 : case BUILT_IN_ISLESSGREATER:
11026 240785 : return fold_builtin_unordered_cmp (loc, fndecl,
11027 240785 : arg0, arg1, UNEQ_EXPR, EQ_EXPR);
11028 241975 : case BUILT_IN_ISUNORDERED:
11029 241975 : return fold_builtin_unordered_cmp (loc, fndecl,
11030 : arg0, arg1, UNORDERED_EXPR,
11031 241975 : NOP_EXPR);
11032 :
11033 709 : case BUILT_IN_ISEQSIG:
11034 709 : return fold_builtin_iseqsig (loc, arg0, arg1);
11035 :
11036 : /* We do the folding for va_start in the expander. */
11037 : case BUILT_IN_VA_START:
11038 : break;
11039 :
11040 201103 : case BUILT_IN_OBJECT_SIZE:
11041 201103 : case BUILT_IN_DYNAMIC_OBJECT_SIZE:
11042 201103 : return fold_builtin_object_size (arg0, arg1, fcode);
11043 :
11044 105861 : case BUILT_IN_ATOMIC_ALWAYS_LOCK_FREE:
11045 105861 : return fold_builtin_atomic_always_lock_free (arg0, arg1);
11046 :
11047 38945 : case BUILT_IN_ATOMIC_IS_LOCK_FREE:
11048 38945 : return fold_builtin_atomic_is_lock_free (arg0, arg1);
11049 :
11050 177252 : case BUILT_IN_CLZG:
11051 177252 : case BUILT_IN_CTZG:
11052 177252 : return fold_builtin_bit_query (loc, fcode, arg0, arg1);
11053 :
11054 : default:
11055 : break;
11056 : }
11057 : return NULL_TREE;
11058 : }
11059 :
11060 : /* Fold a call to built-in function FNDECL with 3 arguments, ARG0, ARG1,
11061 : and ARG2.
11062 : This function returns NULL_TREE if no simplification was possible. */
11063 :
11064 : static tree
11065 7447587 : fold_builtin_3 (location_t loc, tree fndecl,
11066 : tree arg0, tree arg1, tree arg2)
11067 : {
11068 7447587 : tree type = TREE_TYPE (TREE_TYPE (fndecl));
11069 7447587 : enum built_in_function fcode = DECL_FUNCTION_CODE (fndecl);
11070 :
11071 7447587 : if (error_operand_p (arg0)
11072 7447587 : || error_operand_p (arg1)
11073 14895174 : || error_operand_p (arg2))
11074 : return NULL_TREE;
11075 :
11076 7447585 : if (tree ret = fold_const_call (as_combined_fn (fcode), type,
11077 : arg0, arg1, arg2))
11078 : return ret;
11079 :
11080 7430462 : switch (fcode)
11081 : {
11082 :
11083 145 : CASE_FLT_FN (BUILT_IN_SINCOS):
11084 145 : return fold_builtin_sincos (loc, arg0, arg1, arg2);
11085 :
11086 100416 : CASE_FLT_FN (BUILT_IN_REMQUO):
11087 100416 : if (validate_arg (arg0, REAL_TYPE)
11088 100416 : && validate_arg (arg1, REAL_TYPE)
11089 200832 : && validate_arg (arg2, POINTER_TYPE))
11090 100416 : return do_mpfr_remquo (arg0, arg1, arg2);
11091 : break;
11092 :
11093 2580962 : case BUILT_IN_MEMCMP:
11094 2580962 : return fold_builtin_memcmp (loc, arg0, arg1, arg2);
11095 :
11096 520371 : case BUILT_IN_EXPECT:
11097 520371 : return fold_builtin_expect (loc, arg0, arg1, arg2, NULL_TREE);
11098 :
11099 395 : case BUILT_IN_EXPECT_WITH_PROBABILITY:
11100 395 : return fold_builtin_expect (loc, arg0, arg1, NULL_TREE, arg2);
11101 :
11102 511299 : case BUILT_IN_ADD_OVERFLOW:
11103 511299 : case BUILT_IN_SUB_OVERFLOW:
11104 511299 : case BUILT_IN_MUL_OVERFLOW:
11105 511299 : case BUILT_IN_ADD_OVERFLOW_P:
11106 511299 : case BUILT_IN_SUB_OVERFLOW_P:
11107 511299 : case BUILT_IN_MUL_OVERFLOW_P:
11108 511299 : case BUILT_IN_SADD_OVERFLOW:
11109 511299 : case BUILT_IN_SADDL_OVERFLOW:
11110 511299 : case BUILT_IN_SADDLL_OVERFLOW:
11111 511299 : case BUILT_IN_SSUB_OVERFLOW:
11112 511299 : case BUILT_IN_SSUBL_OVERFLOW:
11113 511299 : case BUILT_IN_SSUBLL_OVERFLOW:
11114 511299 : case BUILT_IN_SMUL_OVERFLOW:
11115 511299 : case BUILT_IN_SMULL_OVERFLOW:
11116 511299 : case BUILT_IN_SMULLL_OVERFLOW:
11117 511299 : case BUILT_IN_UADD_OVERFLOW:
11118 511299 : case BUILT_IN_UADDL_OVERFLOW:
11119 511299 : case BUILT_IN_UADDLL_OVERFLOW:
11120 511299 : case BUILT_IN_USUB_OVERFLOW:
11121 511299 : case BUILT_IN_USUBL_OVERFLOW:
11122 511299 : case BUILT_IN_USUBLL_OVERFLOW:
11123 511299 : case BUILT_IN_UMUL_OVERFLOW:
11124 511299 : case BUILT_IN_UMULL_OVERFLOW:
11125 511299 : case BUILT_IN_UMULLL_OVERFLOW:
11126 511299 : return fold_builtin_arith_overflow (loc, fcode, arg0, arg1, arg2);
11127 :
11128 : default:
11129 : break;
11130 : }
11131 : return NULL_TREE;
11132 : }
11133 :
11134 : /* Folds a call EXPR (which may be null) to built-in function FNDECL.
11135 : ARGS is an array of NARGS arguments. IGNORE is true if the result
11136 : of the function call is ignored. This function returns NULL_TREE
11137 : if no simplification was possible. */
11138 :
11139 : static tree
11140 74079571 : fold_builtin_n (location_t loc, tree expr, tree fndecl, tree *args,
11141 : int nargs, bool)
11142 : {
11143 74079571 : tree ret = NULL_TREE;
11144 :
11145 74079571 : switch (nargs)
11146 : {
11147 24135509 : case 0:
11148 24135509 : ret = fold_builtin_0 (loc, fndecl);
11149 24135509 : break;
11150 20330621 : case 1:
11151 20330621 : ret = fold_builtin_1 (loc, expr, fndecl, args[0]);
11152 20330621 : break;
11153 19543824 : case 2:
11154 19543824 : ret = fold_builtin_2 (loc, expr, fndecl, args[0], args[1]);
11155 19543824 : break;
11156 7447587 : case 3:
11157 7447587 : ret = fold_builtin_3 (loc, fndecl, args[0], args[1], args[2]);
11158 7447587 : break;
11159 2622030 : default:
11160 2622030 : ret = fold_builtin_varargs (loc, fndecl, args, nargs);
11161 2622030 : break;
11162 : }
11163 74079571 : if (ret)
11164 : {
11165 10092864 : ret = build1 (NOP_EXPR, TREE_TYPE (ret), ret);
11166 10092864 : SET_EXPR_LOCATION (ret, loc);
11167 10092864 : return ret;
11168 : }
11169 : return NULL_TREE;
11170 : }
11171 :
11172 : /* Construct a new CALL_EXPR to FNDECL using the tail of the argument
11173 : list ARGS along with N new arguments in NEWARGS. SKIP is the number
11174 : of arguments in ARGS to be omitted. OLDNARGS is the number of
11175 : elements in ARGS. */
11176 :
11177 : static tree
11178 4 : rewrite_call_expr_valist (location_t loc, int oldnargs, tree *args,
11179 : int skip, tree fndecl, int n, va_list newargs)
11180 : {
11181 4 : int nargs = oldnargs - skip + n;
11182 4 : tree *buffer;
11183 :
11184 4 : if (n > 0)
11185 : {
11186 0 : int i, j;
11187 :
11188 0 : buffer = XALLOCAVEC (tree, nargs);
11189 0 : for (i = 0; i < n; i++)
11190 0 : buffer[i] = va_arg (newargs, tree);
11191 0 : for (j = skip; j < oldnargs; j++, i++)
11192 0 : buffer[i] = args[j];
11193 : }
11194 : else
11195 4 : buffer = args + skip;
11196 :
11197 4 : return build_call_expr_loc_array (loc, fndecl, nargs, buffer);
11198 : }
11199 :
11200 : /* Return true if FNDECL shouldn't be folded right now.
11201 : If a built-in function has an inline attribute always_inline
11202 : wrapper, defer folding it after always_inline functions have
11203 : been inlined, otherwise e.g. -D_FORTIFY_SOURCE checking
11204 : might not be performed. */
11205 :
11206 : bool
11207 154920669 : avoid_folding_inline_builtin (tree fndecl)
11208 : {
11209 154920669 : return (DECL_DECLARED_INLINE_P (fndecl)
11210 13300 : && DECL_DISREGARD_INLINE_LIMITS (fndecl)
11211 13258 : && cfun
11212 13258 : && !cfun->always_inline_functions_inlined
11213 154933927 : && lookup_attribute ("always_inline", DECL_ATTRIBUTES (fndecl)));
11214 : }
11215 :
11216 : /* A wrapper function for builtin folding that prevents warnings for
11217 : "statement without effect" and the like, caused by removing the
11218 : call node earlier than the warning is generated. */
11219 :
11220 : tree
11221 204420939 : fold_call_expr (location_t loc, tree exp, bool ignore)
11222 : {
11223 204420939 : tree ret = NULL_TREE;
11224 204420939 : tree fndecl = get_callee_fndecl (exp);
11225 202637364 : if (fndecl && fndecl_built_in_p (fndecl)
11226 : /* If CALL_EXPR_VA_ARG_PACK is set, the arguments aren't finalized
11227 : yet. Defer folding until we see all the arguments
11228 : (after inlining). */
11229 264493647 : && !CALL_EXPR_VA_ARG_PACK (exp))
11230 : {
11231 60072677 : int nargs = call_expr_nargs (exp);
11232 :
11233 : /* Before gimplification CALL_EXPR_VA_ARG_PACK is not set, but
11234 : instead last argument is __builtin_va_arg_pack (). Defer folding
11235 : even in that case, until arguments are finalized. */
11236 60072677 : if (nargs && TREE_CODE (CALL_EXPR_ARG (exp, nargs - 1)) == CALL_EXPR)
11237 : {
11238 223586 : tree fndecl2 = get_callee_fndecl (CALL_EXPR_ARG (exp, nargs - 1));
11239 223586 : if (fndecl2 && fndecl_built_in_p (fndecl2, BUILT_IN_VA_ARG_PACK))
11240 : return NULL_TREE;
11241 : }
11242 :
11243 60072608 : if (avoid_folding_inline_builtin (fndecl))
11244 : return NULL_TREE;
11245 :
11246 60069070 : if (DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_MD)
11247 71916262 : return targetm.fold_builtin (fndecl, call_expr_nargs (exp),
11248 71916262 : CALL_EXPR_ARGP (exp), ignore);
11249 : else
11250 : {
11251 24110939 : tree *args = CALL_EXPR_ARGP (exp);
11252 24110939 : ret = fold_builtin_n (loc, exp, fndecl, args, nargs, ignore);
11253 24110939 : if (ret)
11254 : return ret;
11255 : }
11256 : }
11257 : return NULL_TREE;
11258 : }
11259 :
11260 : /* Fold a CALL_EXPR with type TYPE with FN as the function expression.
11261 : N arguments are passed in the array ARGARRAY. Return a folded
11262 : expression or NULL_TREE if no simplification was possible. */
11263 :
11264 : tree
11265 79604911 : fold_builtin_call_array (location_t loc, tree,
11266 : tree fn,
11267 : int n,
11268 : tree *argarray)
11269 : {
11270 79604911 : if (TREE_CODE (fn) != ADDR_EXPR)
11271 : return NULL_TREE;
11272 :
11273 79604911 : tree fndecl = TREE_OPERAND (fn, 0);
11274 79604911 : if (TREE_CODE (fndecl) == FUNCTION_DECL
11275 79604911 : && fndecl_built_in_p (fndecl))
11276 : {
11277 : /* If last argument is __builtin_va_arg_pack (), arguments to this
11278 : function are not finalized yet. Defer folding until they are. */
11279 78992279 : if (n && TREE_CODE (argarray[n - 1]) == CALL_EXPR)
11280 : {
11281 137702 : tree fndecl2 = get_callee_fndecl (argarray[n - 1]);
11282 137702 : if (fndecl2 && fndecl_built_in_p (fndecl2, BUILT_IN_VA_ARG_PACK))
11283 : return NULL_TREE;
11284 : }
11285 78992240 : if (avoid_folding_inline_builtin (fndecl))
11286 : return NULL_TREE;
11287 78992240 : if (DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_MD)
11288 35191971 : return targetm.fold_builtin (fndecl, n, argarray, false);
11289 : else
11290 43800269 : return fold_builtin_n (loc, NULL_TREE, fndecl, argarray, n, false);
11291 : }
11292 :
11293 : return NULL_TREE;
11294 : }
11295 :
11296 : /* Construct a new CALL_EXPR using the tail of the argument list of EXP
11297 : along with N new arguments specified as the "..." parameters. SKIP
11298 : is the number of arguments in EXP to be omitted. This function is used
11299 : to do varargs-to-varargs transformations. */
11300 :
11301 : static tree
11302 4 : rewrite_call_expr (location_t loc, tree exp, int skip, tree fndecl, int n, ...)
11303 : {
11304 4 : va_list ap;
11305 4 : tree t;
11306 :
11307 4 : va_start (ap, n);
11308 8 : t = rewrite_call_expr_valist (loc, call_expr_nargs (exp),
11309 4 : CALL_EXPR_ARGP (exp), skip, fndecl, n, ap);
11310 4 : va_end (ap);
11311 :
11312 4 : return t;
11313 : }
11314 :
11315 : /* Validate a single argument ARG against a tree code CODE representing
11316 : a type. Return true when argument is valid. */
11317 :
11318 : static bool
11319 15525520 : validate_arg (const_tree arg, enum tree_code code)
11320 : {
11321 15525520 : if (!arg)
11322 : return false;
11323 15525497 : else if (code == POINTER_TYPE)
11324 7206153 : return POINTER_TYPE_P (TREE_TYPE (arg));
11325 8319344 : else if (code == INTEGER_TYPE)
11326 3815211 : return INTEGRAL_TYPE_P (TREE_TYPE (arg));
11327 4504133 : return code == TREE_CODE (TREE_TYPE (arg));
11328 : }
11329 :
11330 : /* This function validates the types of a function call argument list
11331 : against a specified list of tree_codes. If the last specifier is a 0,
11332 : that represents an ellipses, otherwise the last specifier must be a
11333 : VOID_TYPE.
11334 :
11335 : This is the GIMPLE version of validate_arglist. Eventually we want to
11336 : completely convert builtins.cc to work from GIMPLEs and the tree based
11337 : validate_arglist will then be removed. */
11338 :
11339 : bool
11340 136 : validate_gimple_arglist (const gcall *call, ...)
11341 : {
11342 136 : enum tree_code code;
11343 136 : bool res = 0;
11344 136 : va_list ap;
11345 136 : const_tree arg;
11346 136 : size_t i;
11347 :
11348 136 : va_start (ap, call);
11349 136 : i = 0;
11350 :
11351 544 : do
11352 : {
11353 544 : code = (enum tree_code) va_arg (ap, int);
11354 544 : switch (code)
11355 : {
11356 0 : case 0:
11357 : /* This signifies an ellipses, any further arguments are all ok. */
11358 0 : res = true;
11359 0 : goto end;
11360 136 : case VOID_TYPE:
11361 : /* This signifies an endlink, if no arguments remain, return
11362 : true, otherwise return false. */
11363 136 : res = (i == gimple_call_num_args (call));
11364 136 : goto end;
11365 408 : default:
11366 : /* If no parameters remain or the parameter's code does not
11367 : match the specified code, return false. Otherwise continue
11368 : checking any remaining arguments. */
11369 408 : arg = gimple_call_arg (call, i++);
11370 408 : if (!validate_arg (arg, code))
11371 0 : goto end;
11372 : break;
11373 : }
11374 : }
11375 : while (1);
11376 :
11377 : /* We need gotos here since we can only have one VA_CLOSE in a
11378 : function. */
11379 136 : end: ;
11380 136 : va_end (ap);
11381 :
11382 136 : return res;
11383 : }
11384 :
11385 : /* Default target-specific builtin expander that does nothing. */
11386 :
11387 : rtx
11388 0 : default_expand_builtin (tree exp ATTRIBUTE_UNUSED,
11389 : rtx target ATTRIBUTE_UNUSED,
11390 : rtx subtarget ATTRIBUTE_UNUSED,
11391 : machine_mode mode ATTRIBUTE_UNUSED,
11392 : int ignore ATTRIBUTE_UNUSED)
11393 : {
11394 0 : return NULL_RTX;
11395 : }
11396 :
11397 : /* Returns true is EXP represents data that would potentially reside
11398 : in a readonly section. */
11399 :
11400 : bool
11401 211730 : readonly_data_expr (tree exp)
11402 : {
11403 211730 : STRIP_NOPS (exp);
11404 :
11405 211730 : if (TREE_CODE (exp) != ADDR_EXPR)
11406 : return false;
11407 :
11408 26811 : exp = get_base_address (TREE_OPERAND (exp, 0));
11409 26811 : if (!exp)
11410 : return false;
11411 :
11412 : /* Make sure we call decl_readonly_section only for trees it
11413 : can handle (since it returns true for everything it doesn't
11414 : understand). */
11415 26811 : if (TREE_CODE (exp) == STRING_CST
11416 5775 : || TREE_CODE (exp) == CONSTRUCTOR
11417 5775 : || (VAR_P (exp) && TREE_STATIC (exp)))
11418 23655 : return decl_readonly_section (exp, 0);
11419 : else
11420 : return false;
11421 : }
11422 :
11423 : /* Simplify a call to the strpbrk builtin. S1 and S2 are the arguments
11424 : to the call, and TYPE is its return type.
11425 :
11426 : Return NULL_TREE if no simplification was possible, otherwise return the
11427 : simplified form of the call as a tree.
11428 :
11429 : The simplified form may be a constant or other expression which
11430 : computes the same value, but in a more efficient manner (including
11431 : calls to other builtin functions).
11432 :
11433 : The call may contain arguments which need to be evaluated, but
11434 : which are not useful to determine the result of the call. In
11435 : this case we return a chain of COMPOUND_EXPRs. The LHS of each
11436 : COMPOUND_EXPR will be an argument which must be evaluated.
11437 : COMPOUND_EXPRs are chained through their RHS. The RHS of the last
11438 : COMPOUND_EXPR in the chain will contain the tree for the simplified
11439 : form of the builtin function call. */
11440 :
11441 : static tree
11442 100567 : fold_builtin_strpbrk (location_t loc, tree, tree s1, tree s2, tree type)
11443 : {
11444 100567 : if (!validate_arg (s1, POINTER_TYPE)
11445 100567 : || !validate_arg (s2, POINTER_TYPE))
11446 : return NULL_TREE;
11447 :
11448 100567 : tree fn;
11449 100567 : const char *p1, *p2;
11450 :
11451 100567 : p2 = c_getstr (s2);
11452 100567 : if (p2 == NULL)
11453 : return NULL_TREE;
11454 :
11455 92 : p1 = c_getstr (s1);
11456 92 : if (p1 != NULL)
11457 : {
11458 22 : const char *r = strpbrk (p1, p2);
11459 22 : tree tem;
11460 :
11461 22 : if (r == NULL)
11462 0 : return build_int_cst (TREE_TYPE (s1), 0);
11463 :
11464 : /* Return an offset into the constant string argument. */
11465 22 : tem = fold_build_pointer_plus_hwi_loc (loc, s1, r - p1);
11466 22 : return fold_convert_loc (loc, type, tem);
11467 : }
11468 :
11469 70 : if (p2[0] == '\0')
11470 : /* strpbrk(x, "") == NULL.
11471 : Evaluate and ignore s1 in case it had side-effects. */
11472 26 : return omit_one_operand_loc (loc, type, integer_zero_node, s1);
11473 :
11474 44 : if (p2[1] != '\0')
11475 : return NULL_TREE; /* Really call strpbrk. */
11476 :
11477 41 : fn = builtin_decl_implicit (BUILT_IN_STRCHR);
11478 41 : if (!fn)
11479 : return NULL_TREE;
11480 :
11481 : /* New argument list transforming strpbrk(s1, s2) to
11482 : strchr(s1, s2[0]). */
11483 41 : return build_call_expr_loc (loc, fn, 2, s1,
11484 41 : build_int_cst (integer_type_node, p2[0]));
11485 : }
11486 :
11487 : /* Simplify a call to the strspn builtin. S1 and S2 are the arguments
11488 : to the call.
11489 :
11490 : Return NULL_TREE if no simplification was possible, otherwise return the
11491 : simplified form of the call as a tree.
11492 :
11493 : The simplified form may be a constant or other expression which
11494 : computes the same value, but in a more efficient manner (including
11495 : calls to other builtin functions).
11496 :
11497 : The call may contain arguments which need to be evaluated, but
11498 : which are not useful to determine the result of the call. In
11499 : this case we return a chain of COMPOUND_EXPRs. The LHS of each
11500 : COMPOUND_EXPR will be an argument which must be evaluated.
11501 : COMPOUND_EXPRs are chained through their RHS. The RHS of the last
11502 : COMPOUND_EXPR in the chain will contain the tree for the simplified
11503 : form of the builtin function call. */
11504 :
11505 : static tree
11506 2560 : fold_builtin_strspn (location_t loc, tree expr, tree s1, tree s2, tree type)
11507 : {
11508 2560 : if (!validate_arg (s1, POINTER_TYPE)
11509 2560 : || !validate_arg (s2, POINTER_TYPE))
11510 : return NULL_TREE;
11511 :
11512 2560 : if (!check_nul_terminated_array (expr, s1)
11513 2560 : || !check_nul_terminated_array (expr, s2))
11514 : return NULL_TREE;
11515 :
11516 2502 : const char *p1 = c_getstr (s1), *p2 = c_getstr (s2);
11517 :
11518 : /* If either argument is "", return NULL_TREE. */
11519 2502 : if ((p1 && *p1 == '\0') || (p2 && *p2 == '\0'))
11520 : /* Evaluate and ignore both arguments in case either one has
11521 : side-effects. */
11522 147 : return omit_two_operands_loc (loc, type, size_zero_node, s1, s2);
11523 : return NULL_TREE;
11524 : }
11525 :
11526 : /* Simplify a call to the strcspn builtin. S1 and S2 are the arguments
11527 : to the call.
11528 :
11529 : Return NULL_TREE if no simplification was possible, otherwise return the
11530 : simplified form of the call as a tree.
11531 :
11532 : The simplified form may be a constant or other expression which
11533 : computes the same value, but in a more efficient manner (including
11534 : calls to other builtin functions).
11535 :
11536 : The call may contain arguments which need to be evaluated, but
11537 : which are not useful to determine the result of the call. In
11538 : this case we return a chain of COMPOUND_EXPRs. The LHS of each
11539 : COMPOUND_EXPR will be an argument which must be evaluated.
11540 : COMPOUND_EXPRs are chained through their RHS. The RHS of the last
11541 : COMPOUND_EXPR in the chain will contain the tree for the simplified
11542 : form of the builtin function call. */
11543 :
11544 : static tree
11545 2465 : fold_builtin_strcspn (location_t loc, tree expr, tree s1, tree s2, tree type)
11546 : {
11547 2465 : if (!validate_arg (s1, POINTER_TYPE)
11548 2465 : || !validate_arg (s2, POINTER_TYPE))
11549 : return NULL_TREE;
11550 :
11551 2465 : if (!check_nul_terminated_array (expr, s1)
11552 2465 : || !check_nul_terminated_array (expr, s2))
11553 : return NULL_TREE;
11554 :
11555 : /* If the first argument is "", return NULL_TREE. */
11556 2407 : const char *p1 = c_getstr (s1);
11557 2407 : if (p1 && *p1 == '\0')
11558 : {
11559 : /* Evaluate and ignore argument s2 in case it has
11560 : side-effects. */
11561 65 : return omit_one_operand_loc (loc, type, size_zero_node, s2);
11562 : }
11563 :
11564 : /* If the second argument is "", return __builtin_strlen(s1). */
11565 2342 : const char *p2 = c_getstr (s2);
11566 2342 : if (p2 && *p2 == '\0')
11567 : {
11568 81 : tree fn = builtin_decl_implicit (BUILT_IN_STRLEN);
11569 :
11570 : /* If the replacement _DECL isn't initialized, don't do the
11571 : transformation. */
11572 81 : if (!fn)
11573 : return NULL_TREE;
11574 :
11575 81 : return fold_convert_loc (loc, type,
11576 81 : build_call_expr_loc (loc, fn, 1, s1));
11577 : }
11578 : return NULL_TREE;
11579 : }
11580 :
11581 : /* Fold the next_arg or va_start call EXP. Returns true if there was an error
11582 : produced. False otherwise. This is done so that we don't output the error
11583 : or warning twice or three times. */
11584 :
11585 : bool
11586 42141 : fold_builtin_next_arg (tree exp, bool va_start_p)
11587 : {
11588 42141 : tree fntype = TREE_TYPE (current_function_decl);
11589 42141 : int nargs = call_expr_nargs (exp);
11590 42141 : tree arg;
11591 : /* There is good chance the current input_location points inside the
11592 : definition of the va_start macro (perhaps on the token for
11593 : builtin) in a system header, so warnings will not be emitted.
11594 : Use the location in real source code. */
11595 42141 : location_t current_location =
11596 42141 : linemap_unwind_to_first_non_reserved_loc (line_table, input_location,
11597 : NULL);
11598 :
11599 42141 : if (!stdarg_p (fntype))
11600 : {
11601 8 : error ("%<va_start%> used in function with fixed arguments");
11602 8 : return true;
11603 : }
11604 :
11605 42133 : if (va_start_p)
11606 : {
11607 41975 : if (va_start_p && (nargs != 2))
11608 : {
11609 0 : error ("wrong number of arguments to function %<va_start%>");
11610 0 : return true;
11611 : }
11612 41975 : arg = CALL_EXPR_ARG (exp, 1);
11613 : }
11614 : /* We use __builtin_va_start (ap, 0, 0) or __builtin_next_arg (0, 0)
11615 : when we checked the arguments and if needed issued a warning. */
11616 : else
11617 : {
11618 158 : if (nargs == 0)
11619 : {
11620 : /* Evidently an out of date version of <stdarg.h>; can't validate
11621 : va_start's second argument, but can still work as intended. */
11622 0 : warning_at (current_location,
11623 0 : OPT_Wvarargs,
11624 : "%<__builtin_next_arg%> called without an argument");
11625 0 : return true;
11626 : }
11627 158 : else if (nargs > 1)
11628 : {
11629 0 : error ("wrong number of arguments to function %<__builtin_next_arg%>");
11630 0 : return true;
11631 : }
11632 158 : arg = CALL_EXPR_ARG (exp, 0);
11633 : }
11634 :
11635 42133 : if (TREE_CODE (arg) == SSA_NAME
11636 42133 : && SSA_NAME_VAR (arg))
11637 : arg = SSA_NAME_VAR (arg);
11638 :
11639 : /* We destructively modify the call to be __builtin_va_start (ap, 0)
11640 : or __builtin_next_arg (0) the first time we see it, after checking
11641 : the arguments and if needed issuing a warning. */
11642 42133 : if (!integer_zerop (arg))
11643 : {
11644 7031 : tree last_parm = tree_last (DECL_ARGUMENTS (current_function_decl));
11645 :
11646 : /* Strip off all nops for the sake of the comparison. This
11647 : is not quite the same as STRIP_NOPS. It does more.
11648 : We must also strip off INDIRECT_EXPR for C++ reference
11649 : parameters. */
11650 14064 : while (CONVERT_EXPR_P (arg)
11651 14075 : || INDIRECT_REF_P (arg))
11652 11 : arg = TREE_OPERAND (arg, 0);
11653 7031 : if (arg != last_parm)
11654 : {
11655 : /* FIXME: Sometimes with the tree optimizers we can get the
11656 : not the last argument even though the user used the last
11657 : argument. We just warn and set the arg to be the last
11658 : argument so that we will get wrong-code because of
11659 : it. */
11660 12 : warning_at (current_location,
11661 12 : OPT_Wvarargs,
11662 : "second parameter of %<va_start%> not last named argument");
11663 : }
11664 :
11665 : /* Undefined by C99 7.15.1.4p4 (va_start):
11666 : "If the parameter parmN is declared with the register storage
11667 : class, with a function or array type, or with a type that is
11668 : not compatible with the type that results after application of
11669 : the default argument promotions, the behavior is undefined."
11670 : */
11671 7019 : else if (DECL_REGISTER (arg))
11672 : {
11673 12 : warning_at (current_location,
11674 12 : OPT_Wvarargs,
11675 : "undefined behavior when second parameter of "
11676 : "%<va_start%> is declared with %<register%> storage");
11677 : }
11678 :
11679 : /* We want to verify the second parameter just once before the tree
11680 : optimizers are run and then avoid keeping it in the tree,
11681 : as otherwise we could warn even for correct code like:
11682 : void foo (int i, ...)
11683 : { va_list ap; i++; va_start (ap, i); va_end (ap); } */
11684 7031 : if (va_start_p)
11685 7029 : CALL_EXPR_ARG (exp, 1) = integer_zero_node;
11686 : else
11687 2 : CALL_EXPR_ARG (exp, 0) = integer_zero_node;
11688 : }
11689 : return false;
11690 : }
11691 :
11692 :
11693 : /* Expand a call EXP to __builtin_object_size. */
11694 :
11695 : static rtx
11696 620 : expand_builtin_object_size (tree exp)
11697 : {
11698 620 : tree ost;
11699 620 : int object_size_type;
11700 620 : tree fndecl = get_callee_fndecl (exp);
11701 :
11702 620 : if (!validate_arglist (exp, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
11703 : {
11704 0 : error ("first argument of %qD must be a pointer, second integer constant",
11705 : fndecl);
11706 0 : expand_builtin_trap ();
11707 0 : return const0_rtx;
11708 : }
11709 :
11710 620 : ost = CALL_EXPR_ARG (exp, 1);
11711 620 : STRIP_NOPS (ost);
11712 :
11713 620 : if (TREE_CODE (ost) != INTEGER_CST
11714 620 : || tree_int_cst_sgn (ost) < 0
11715 1240 : || compare_tree_int (ost, 3) > 0)
11716 : {
11717 0 : error ("last argument of %qD is not integer constant between 0 and 3",
11718 : fndecl);
11719 0 : expand_builtin_trap ();
11720 0 : return const0_rtx;
11721 : }
11722 :
11723 620 : object_size_type = tree_to_shwi (ost);
11724 :
11725 620 : return object_size_type < 2 ? constm1_rtx : const0_rtx;
11726 : }
11727 :
11728 : /* Expand EXP, a call to the __mem{cpy,pcpy,move,set}_chk builtin.
11729 : FCODE is the BUILT_IN_* to use.
11730 : Return NULL_RTX if we failed; the caller should emit a normal call,
11731 : otherwise try to get the result in TARGET, if convenient (and in
11732 : mode MODE if that's convenient). */
11733 :
11734 : static rtx
11735 837 : expand_builtin_memory_chk (tree exp, rtx target, machine_mode mode,
11736 : enum built_in_function fcode)
11737 : {
11738 1410 : if (!validate_arglist (exp,
11739 : POINTER_TYPE,
11740 : fcode == BUILT_IN_MEMSET_CHK
11741 : ? INTEGER_TYPE : POINTER_TYPE,
11742 : INTEGER_TYPE, INTEGER_TYPE, VOID_TYPE))
11743 : return NULL_RTX;
11744 :
11745 837 : tree dest = CALL_EXPR_ARG (exp, 0);
11746 837 : tree src = CALL_EXPR_ARG (exp, 1);
11747 837 : tree len = CALL_EXPR_ARG (exp, 2);
11748 837 : tree size = CALL_EXPR_ARG (exp, 3);
11749 :
11750 : /* FIXME: Set access mode to write only for memset et al. */
11751 837 : bool sizes_ok = check_access (exp, len, /*maxread=*/NULL_TREE,
11752 : /*srcstr=*/NULL_TREE, size, access_read_write);
11753 :
11754 837 : if (!tree_fits_uhwi_p (size))
11755 : return NULL_RTX;
11756 :
11757 627 : if (tree_fits_uhwi_p (len) || integer_all_onesp (size))
11758 : {
11759 : /* Avoid transforming the checking call to an ordinary one when
11760 : an overflow has been detected or when the call couldn't be
11761 : validated because the size is not constant. */
11762 186 : if (!sizes_ok && !integer_all_onesp (size) && tree_int_cst_lt (size, len))
11763 : return NULL_RTX;
11764 :
11765 0 : tree fn = NULL_TREE;
11766 : /* If __builtin_mem{cpy,pcpy,move,set}_chk is used, assume
11767 : mem{cpy,pcpy,move,set} is available. */
11768 0 : switch (fcode)
11769 : {
11770 0 : case BUILT_IN_MEMCPY_CHK:
11771 0 : fn = builtin_decl_explicit (BUILT_IN_MEMCPY);
11772 0 : break;
11773 0 : case BUILT_IN_MEMPCPY_CHK:
11774 0 : fn = builtin_decl_explicit (BUILT_IN_MEMPCPY);
11775 0 : break;
11776 0 : case BUILT_IN_MEMMOVE_CHK:
11777 0 : fn = builtin_decl_explicit (BUILT_IN_MEMMOVE);
11778 0 : break;
11779 0 : case BUILT_IN_MEMSET_CHK:
11780 0 : fn = builtin_decl_explicit (BUILT_IN_MEMSET);
11781 0 : break;
11782 : default:
11783 : break;
11784 : }
11785 :
11786 0 : if (! fn)
11787 : return NULL_RTX;
11788 :
11789 0 : fn = build_call_nofold_loc (EXPR_LOCATION (exp), fn, 3, dest, src, len);
11790 0 : gcc_assert (TREE_CODE (fn) == CALL_EXPR);
11791 0 : CALL_EXPR_TAILCALL (fn) = CALL_EXPR_TAILCALL (exp);
11792 0 : return expand_expr (fn, target, mode, EXPAND_NORMAL);
11793 : }
11794 441 : else if (fcode == BUILT_IN_MEMSET_CHK)
11795 : return NULL_RTX;
11796 : else
11797 : {
11798 293 : unsigned int dest_align = get_pointer_alignment (dest);
11799 :
11800 : /* If DEST is not a pointer type, call the normal function. */
11801 293 : if (dest_align == 0)
11802 : return NULL_RTX;
11803 :
11804 : /* If SRC and DEST are the same (and not volatile), do nothing. */
11805 293 : if (operand_equal_p (src, dest, 0))
11806 : {
11807 0 : tree expr;
11808 :
11809 0 : if (fcode != BUILT_IN_MEMPCPY_CHK)
11810 : {
11811 : /* Evaluate and ignore LEN in case it has side-effects. */
11812 0 : expand_expr (len, const0_rtx, VOIDmode, EXPAND_NORMAL);
11813 0 : return expand_expr (dest, target, mode, EXPAND_NORMAL);
11814 : }
11815 :
11816 0 : expr = fold_build_pointer_plus (dest, len);
11817 0 : return expand_expr (expr, target, mode, EXPAND_NORMAL);
11818 : }
11819 :
11820 : /* __memmove_chk special case. */
11821 293 : if (fcode == BUILT_IN_MEMMOVE_CHK)
11822 : {
11823 79 : unsigned int src_align = get_pointer_alignment (src);
11824 :
11825 79 : if (src_align == 0)
11826 : return NULL_RTX;
11827 :
11828 : /* If src is categorized for a readonly section we can use
11829 : normal __memcpy_chk. */
11830 79 : if (readonly_data_expr (src))
11831 : {
11832 15 : tree fn = builtin_decl_explicit (BUILT_IN_MEMCPY_CHK);
11833 15 : if (!fn)
11834 : return NULL_RTX;
11835 15 : fn = build_call_nofold_loc (EXPR_LOCATION (exp), fn, 4,
11836 : dest, src, len, size);
11837 15 : gcc_assert (TREE_CODE (fn) == CALL_EXPR);
11838 15 : CALL_EXPR_TAILCALL (fn) = CALL_EXPR_TAILCALL (exp);
11839 15 : return expand_expr (fn, target, mode, EXPAND_NORMAL);
11840 : }
11841 : }
11842 : return NULL_RTX;
11843 : }
11844 : }
11845 :
11846 : /* Emit warning if a buffer overflow is detected at compile time. */
11847 :
11848 : static void
11849 1086 : maybe_emit_chk_warning (tree exp, enum built_in_function fcode)
11850 : {
11851 : /* The source string. */
11852 1086 : tree srcstr = NULL_TREE;
11853 : /* The size of the destination object returned by __builtin_object_size. */
11854 1086 : tree objsize = NULL_TREE;
11855 : /* The string that is being concatenated with (as in __strcat_chk)
11856 : or null if it isn't. */
11857 1086 : tree catstr = NULL_TREE;
11858 : /* The maximum length of the source sequence in a bounded operation
11859 : (such as __strncat_chk) or null if the operation isn't bounded
11860 : (such as __strcat_chk). */
11861 1086 : tree maxread = NULL_TREE;
11862 : /* The exact size of the access (such as in __strncpy_chk). */
11863 1086 : tree size = NULL_TREE;
11864 : /* The access by the function that's checked. Except for snprintf
11865 : both writing and reading is checked. */
11866 1086 : access_mode mode = access_read_write;
11867 :
11868 1086 : switch (fcode)
11869 : {
11870 275 : case BUILT_IN_STRCPY_CHK:
11871 275 : case BUILT_IN_STPCPY_CHK:
11872 275 : srcstr = CALL_EXPR_ARG (exp, 1);
11873 275 : objsize = CALL_EXPR_ARG (exp, 2);
11874 275 : break;
11875 :
11876 151 : case BUILT_IN_STRCAT_CHK:
11877 : /* For __strcat_chk the warning will be emitted only if overflowing
11878 : by at least strlen (dest) + 1 bytes. */
11879 151 : catstr = CALL_EXPR_ARG (exp, 0);
11880 151 : srcstr = CALL_EXPR_ARG (exp, 1);
11881 151 : objsize = CALL_EXPR_ARG (exp, 2);
11882 151 : break;
11883 :
11884 108 : case BUILT_IN_STRNCAT_CHK:
11885 108 : catstr = CALL_EXPR_ARG (exp, 0);
11886 108 : srcstr = CALL_EXPR_ARG (exp, 1);
11887 108 : maxread = CALL_EXPR_ARG (exp, 2);
11888 108 : objsize = CALL_EXPR_ARG (exp, 3);
11889 108 : break;
11890 :
11891 243 : case BUILT_IN_STRNCPY_CHK:
11892 243 : case BUILT_IN_STPNCPY_CHK:
11893 243 : srcstr = CALL_EXPR_ARG (exp, 1);
11894 243 : size = CALL_EXPR_ARG (exp, 2);
11895 243 : objsize = CALL_EXPR_ARG (exp, 3);
11896 243 : break;
11897 :
11898 309 : case BUILT_IN_SNPRINTF_CHK:
11899 309 : case BUILT_IN_VSNPRINTF_CHK:
11900 309 : maxread = CALL_EXPR_ARG (exp, 1);
11901 309 : objsize = CALL_EXPR_ARG (exp, 3);
11902 : /* The only checked access the write to the destination. */
11903 309 : mode = access_write_only;
11904 309 : break;
11905 0 : default:
11906 0 : gcc_unreachable ();
11907 : }
11908 :
11909 1086 : if (catstr && maxread)
11910 : {
11911 : /* Check __strncat_chk. There is no way to determine the length
11912 : of the string to which the source string is being appended so
11913 : just warn when the length of the source string is not known. */
11914 108 : check_strncat_sizes (exp, objsize);
11915 108 : return;
11916 : }
11917 :
11918 978 : check_access (exp, size, maxread, srcstr, objsize, mode);
11919 : }
11920 :
11921 : /* Emit warning if a buffer overflow is detected at compile time
11922 : in __sprintf_chk/__vsprintf_chk calls. */
11923 :
11924 : static void
11925 1328 : maybe_emit_sprintf_chk_warning (tree exp, enum built_in_function fcode)
11926 : {
11927 1328 : tree size, len, fmt;
11928 1328 : const char *fmt_str;
11929 1328 : int nargs = call_expr_nargs (exp);
11930 :
11931 : /* Verify the required arguments in the original call. */
11932 :
11933 1328 : if (nargs < 4)
11934 : return;
11935 1328 : size = CALL_EXPR_ARG (exp, 2);
11936 1328 : fmt = CALL_EXPR_ARG (exp, 3);
11937 :
11938 1328 : if (! tree_fits_uhwi_p (size) || integer_all_onesp (size))
11939 : return;
11940 :
11941 : /* Check whether the format is a literal string constant. */
11942 1307 : fmt_str = c_getstr (fmt);
11943 1307 : if (fmt_str == NULL)
11944 : return;
11945 :
11946 1271 : if (!init_target_chars ())
11947 : return;
11948 :
11949 : /* If the format doesn't contain % args or %%, we know its size. */
11950 1271 : if (strchr (fmt_str, target_percent) == 0)
11951 22 : len = build_int_cstu (size_type_node, strlen (fmt_str));
11952 : /* If the format is "%s" and first ... argument is a string literal,
11953 : we know it too. */
11954 1249 : else if (fcode == BUILT_IN_SPRINTF_CHK
11955 1095 : && strcmp (fmt_str, target_percent_s) == 0)
11956 : {
11957 49 : tree arg;
11958 :
11959 49 : if (nargs < 5)
11960 : return;
11961 49 : arg = CALL_EXPR_ARG (exp, 4);
11962 49 : if (! POINTER_TYPE_P (TREE_TYPE (arg)))
11963 : return;
11964 :
11965 45 : len = c_strlen (arg, 1);
11966 45 : if (!len || ! tree_fits_uhwi_p (len))
11967 : return;
11968 : }
11969 : else
11970 : return;
11971 :
11972 : /* Add one for the terminating nul. */
11973 34 : len = fold_build2 (PLUS_EXPR, TREE_TYPE (len), len, size_one_node);
11974 :
11975 34 : check_access (exp, /*size=*/NULL_TREE, /*maxread=*/NULL_TREE, len, size,
11976 : access_write_only);
11977 : }
11978 :
11979 : /* Fold a call to __builtin_object_size with arguments PTR and OST,
11980 : if possible. */
11981 :
11982 : static tree
11983 201103 : fold_builtin_object_size (tree ptr, tree ost, enum built_in_function fcode)
11984 : {
11985 201103 : tree bytes;
11986 201103 : int object_size_type;
11987 :
11988 201103 : if (!validate_arg (ptr, POINTER_TYPE)
11989 201103 : || !validate_arg (ost, INTEGER_TYPE))
11990 : return NULL_TREE;
11991 :
11992 201103 : STRIP_NOPS (ost);
11993 :
11994 201103 : if (TREE_CODE (ost) != INTEGER_CST
11995 201103 : || tree_int_cst_sgn (ost) < 0
11996 402206 : || compare_tree_int (ost, 3) > 0)
11997 : return NULL_TREE;
11998 :
11999 201103 : object_size_type = tree_to_shwi (ost);
12000 :
12001 : /* __builtin_object_size doesn't evaluate side-effects in its arguments;
12002 : if there are any side-effects, it returns (size_t) -1 for types 0 and 1
12003 : and (size_t) 0 for types 2 and 3. */
12004 201103 : if (TREE_SIDE_EFFECTS (ptr))
12005 603 : return build_int_cst_type (size_type_node, object_size_type < 2 ? -1 : 0);
12006 :
12007 200500 : if (fcode == BUILT_IN_DYNAMIC_OBJECT_SIZE)
12008 67467 : object_size_type |= OST_DYNAMIC;
12009 :
12010 200500 : if (TREE_CODE (ptr) == ADDR_EXPR)
12011 : {
12012 12232 : compute_builtin_object_size (ptr, object_size_type, &bytes);
12013 12232 : if ((object_size_type & OST_DYNAMIC)
12014 10886 : || int_fits_type_p (bytes, size_type_node))
12015 12232 : return fold_convert (size_type_node, bytes);
12016 : }
12017 188268 : else if (TREE_CODE (ptr) == SSA_NAME)
12018 : {
12019 : /* If object size is not known yet, delay folding until
12020 : later. Maybe subsequent passes will help determining
12021 : it. */
12022 102230 : if (compute_builtin_object_size (ptr, object_size_type, &bytes)
12023 102230 : && ((object_size_type & OST_DYNAMIC)
12024 2538 : || int_fits_type_p (bytes, size_type_node)))
12025 4808 : return fold_convert (size_type_node, bytes);
12026 : }
12027 :
12028 : return NULL_TREE;
12029 : }
12030 :
12031 : /* Builtins with folding operations that operate on "..." arguments
12032 : need special handling; we need to store the arguments in a convenient
12033 : data structure before attempting any folding. Fortunately there are
12034 : only a few builtins that fall into this category. FNDECL is the
12035 : function, EXP is the CALL_EXPR for the call. */
12036 :
12037 : static tree
12038 2622030 : fold_builtin_varargs (location_t loc, tree fndecl, tree *args, int nargs)
12039 : {
12040 2622030 : enum built_in_function fcode = DECL_FUNCTION_CODE (fndecl);
12041 2622030 : tree ret = NULL_TREE;
12042 :
12043 2622030 : switch (fcode)
12044 : {
12045 104982 : case BUILT_IN_FPCLASSIFY:
12046 104982 : ret = fold_builtin_fpclassify (loc, args, nargs);
12047 104982 : break;
12048 :
12049 55 : case BUILT_IN_ADDC:
12050 55 : case BUILT_IN_ADDCL:
12051 55 : case BUILT_IN_ADDCLL:
12052 55 : case BUILT_IN_SUBC:
12053 55 : case BUILT_IN_SUBCL:
12054 55 : case BUILT_IN_SUBCLL:
12055 55 : return fold_builtin_addc_subc (loc, fcode, args);
12056 :
12057 : default:
12058 : break;
12059 : }
12060 104982 : if (ret)
12061 : {
12062 104982 : ret = build1 (NOP_EXPR, TREE_TYPE (ret), ret);
12063 104982 : SET_EXPR_LOCATION (ret, loc);
12064 104982 : suppress_warning (ret);
12065 104982 : return ret;
12066 : }
12067 : return NULL_TREE;
12068 : }
12069 :
12070 : /* Initialize format string characters in the target charset. */
12071 :
12072 : bool
12073 290956 : init_target_chars (void)
12074 : {
12075 290956 : static bool init;
12076 290956 : if (!init)
12077 : {
12078 115891 : target_newline = lang_hooks.to_target_charset ('\n');
12079 115891 : target_percent = lang_hooks.to_target_charset ('%');
12080 115891 : target_c = lang_hooks.to_target_charset ('c');
12081 115891 : target_s = lang_hooks.to_target_charset ('s');
12082 115891 : if (target_newline == 0 || target_percent == 0 || target_c == 0
12083 115891 : || target_s == 0)
12084 : return false;
12085 :
12086 115891 : target_percent_c[0] = target_percent;
12087 115891 : target_percent_c[1] = target_c;
12088 115891 : target_percent_c[2] = '\0';
12089 :
12090 115891 : target_percent_s[0] = target_percent;
12091 115891 : target_percent_s[1] = target_s;
12092 115891 : target_percent_s[2] = '\0';
12093 :
12094 115891 : target_percent_s_newline[0] = target_percent;
12095 115891 : target_percent_s_newline[1] = target_s;
12096 115891 : target_percent_s_newline[2] = target_newline;
12097 115891 : target_percent_s_newline[3] = '\0';
12098 :
12099 115891 : init = true;
12100 : }
12101 : return true;
12102 : }
12103 :
12104 : /* Helper function for do_mpfr_arg*(). Ensure M is a normal number
12105 : and no overflow/underflow occurred. INEXACT is true if M was not
12106 : exactly calculated. TYPE is the tree type for the result. This
12107 : function assumes that you cleared the MPFR flags and then
12108 : calculated M to see if anything subsequently set a flag prior to
12109 : entering this function. Return NULL_TREE if any checks fail. */
12110 :
12111 : static tree
12112 2979 : do_mpfr_ckconv (mpfr_srcptr m, tree type, int inexact)
12113 : {
12114 : /* Proceed iff we get a normal number, i.e. not NaN or Inf and no
12115 : overflow/underflow occurred. If -frounding-math, proceed iff the
12116 : result of calling FUNC was exact. */
12117 4832 : if (mpfr_number_p (m) && !mpfr_overflow_p () && !mpfr_underflow_p ()
12118 4832 : && (!flag_rounding_math || !inexact))
12119 : {
12120 1853 : REAL_VALUE_TYPE rr;
12121 :
12122 1853 : real_from_mpfr (&rr, m, type, MPFR_RNDN);
12123 : /* Proceed iff GCC's REAL_VALUE_TYPE can hold the MPFR value,
12124 : check for overflow/underflow. If the REAL_VALUE_TYPE is zero
12125 : but the mpfr_t is not, then we underflowed in the
12126 : conversion. */
12127 1853 : if (real_isfinite (&rr)
12128 1853 : && (rr.cl == rvc_zero) == (mpfr_zero_p (m) != 0))
12129 : {
12130 1853 : REAL_VALUE_TYPE rmode;
12131 :
12132 1853 : real_convert (&rmode, TYPE_MODE (type), &rr);
12133 : /* Proceed iff the specified mode can hold the value. */
12134 1853 : if (real_identical (&rmode, &rr))
12135 1853 : return build_real (type, rmode);
12136 : }
12137 : }
12138 : return NULL_TREE;
12139 : }
12140 :
12141 : /* Helper function for do_mpc_arg*(). Ensure M is a normal complex
12142 : number and no overflow/underflow occurred. INEXACT is true if M
12143 : was not exactly calculated. TYPE is the tree type for the result.
12144 : This function assumes that you cleared the MPFR flags and then
12145 : calculated M to see if anything subsequently set a flag prior to
12146 : entering this function. Return NULL_TREE if any checks fail, if
12147 : FORCE_CONVERT is true, then bypass the checks. */
12148 :
12149 : static tree
12150 4171 : do_mpc_ckconv (mpc_srcptr m, tree type, int inexact, int force_convert)
12151 : {
12152 : /* Proceed iff we get a normal number, i.e. not NaN or Inf and no
12153 : overflow/underflow occurred. If -frounding-math, proceed iff the
12154 : result of calling FUNC was exact. */
12155 4171 : if (force_convert
12156 4171 : || (mpfr_number_p (mpc_realref (m)) && mpfr_number_p (mpc_imagref (m))
12157 3852 : && !mpfr_overflow_p () && !mpfr_underflow_p ()
12158 3852 : && (!flag_rounding_math || !inexact)))
12159 : {
12160 3992 : REAL_VALUE_TYPE re, im;
12161 :
12162 3992 : real_from_mpfr (&re, mpc_realref (m), TREE_TYPE (type), MPFR_RNDN);
12163 3992 : real_from_mpfr (&im, mpc_imagref (m), TREE_TYPE (type), MPFR_RNDN);
12164 : /* Proceed iff GCC's REAL_VALUE_TYPE can hold the MPFR values,
12165 : check for overflow/underflow. If the REAL_VALUE_TYPE is zero
12166 : but the mpfr_t is not, then we underflowed in the
12167 : conversion. */
12168 3992 : if (force_convert
12169 3992 : || (real_isfinite (&re) && real_isfinite (&im)
12170 3852 : && (re.cl == rvc_zero) == (mpfr_zero_p (mpc_realref (m)) != 0)
12171 3852 : && (im.cl == rvc_zero) == (mpfr_zero_p (mpc_imagref (m)) != 0)))
12172 : {
12173 3992 : REAL_VALUE_TYPE re_mode, im_mode;
12174 :
12175 3992 : real_convert (&re_mode, TYPE_MODE (TREE_TYPE (type)), &re);
12176 3992 : real_convert (&im_mode, TYPE_MODE (TREE_TYPE (type)), &im);
12177 : /* Proceed iff the specified mode can hold the value. */
12178 3992 : if (force_convert
12179 3992 : || (real_identical (&re_mode, &re)
12180 3852 : && real_identical (&im_mode, &im)))
12181 3992 : return build_complex (type, build_real (TREE_TYPE (type), re_mode),
12182 7984 : build_real (TREE_TYPE (type), im_mode));
12183 : }
12184 : }
12185 : return NULL_TREE;
12186 : }
12187 :
12188 : /* If arguments ARG0 and ARG1 are REAL_CSTs, call mpfr_remquo() to set
12189 : the pointer *(ARG_QUO) and return the result. The type is taken
12190 : from the type of ARG0 and is used for setting the precision of the
12191 : calculation and results. */
12192 :
12193 : static tree
12194 100416 : do_mpfr_remquo (tree arg0, tree arg1, tree arg_quo)
12195 : {
12196 100416 : tree const type = TREE_TYPE (arg0);
12197 100416 : tree result = NULL_TREE;
12198 :
12199 100416 : STRIP_NOPS (arg0);
12200 100416 : STRIP_NOPS (arg1);
12201 :
12202 : /* To proceed, MPFR must exactly represent the target floating point
12203 : format, which only happens when the target base equals two. */
12204 100416 : if (REAL_MODE_FORMAT (TYPE_MODE (type))->b == 2
12205 100416 : && TREE_CODE (arg0) == REAL_CST && !TREE_OVERFLOW (arg0)
12206 102721 : && TREE_CODE (arg1) == REAL_CST && !TREE_OVERFLOW (arg1))
12207 : {
12208 2305 : const REAL_VALUE_TYPE *const ra0 = TREE_REAL_CST_PTR (arg0);
12209 2305 : const REAL_VALUE_TYPE *const ra1 = TREE_REAL_CST_PTR (arg1);
12210 :
12211 2305 : if (real_isfinite (ra0) && real_isfinite (ra1))
12212 : {
12213 2305 : const struct real_format *fmt = REAL_MODE_FORMAT (TYPE_MODE (type));
12214 2305 : const int prec = fmt->p;
12215 2305 : const mpfr_rnd_t rnd = fmt->round_towards_zero? MPFR_RNDZ : MPFR_RNDN;
12216 2305 : tree result_rem;
12217 2305 : long integer_quo;
12218 2305 : mpfr_t m0, m1;
12219 :
12220 2305 : mpfr_inits2 (prec, m0, m1, NULL);
12221 2305 : mpfr_from_real (m0, ra0, MPFR_RNDN);
12222 2305 : mpfr_from_real (m1, ra1, MPFR_RNDN);
12223 2305 : mpfr_clear_flags ();
12224 2305 : mpfr_remquo (m0, &integer_quo, m0, m1, rnd);
12225 : /* Remquo is independent of the rounding mode, so pass
12226 : inexact=0 to do_mpfr_ckconv(). */
12227 2305 : result_rem = do_mpfr_ckconv (m0, type, /*inexact=*/ 0);
12228 2305 : mpfr_clears (m0, m1, NULL);
12229 2305 : if (result_rem)
12230 : {
12231 : /* MPFR calculates quo in the host's long so it may
12232 : return more bits in quo than the target int can hold
12233 : if sizeof(host long) > sizeof(target int). This can
12234 : happen even for native compilers in LP64 mode. In
12235 : these cases, modulo the quo value with the largest
12236 : number that the target int can hold while leaving one
12237 : bit for the sign. */
12238 1179 : if (sizeof (integer_quo) * CHAR_BIT > INT_TYPE_SIZE)
12239 1179 : integer_quo %= (long)(1UL << (INT_TYPE_SIZE - 1));
12240 :
12241 : /* Dereference the quo pointer argument. */
12242 1179 : arg_quo = build_fold_indirect_ref (arg_quo);
12243 : /* Proceed iff a valid pointer type was passed in. */
12244 1179 : if (TYPE_MAIN_VARIANT (TREE_TYPE (arg_quo)) == integer_type_node)
12245 : {
12246 : /* Set the value. */
12247 1179 : tree result_quo
12248 1179 : = fold_build2 (MODIFY_EXPR, TREE_TYPE (arg_quo), arg_quo,
12249 : build_int_cst (TREE_TYPE (arg_quo),
12250 : integer_quo));
12251 1179 : TREE_SIDE_EFFECTS (result_quo) = 1;
12252 : /* Combine the quo assignment with the rem. */
12253 1179 : result = fold_build2 (COMPOUND_EXPR, type,
12254 : result_quo, result_rem);
12255 1179 : suppress_warning (result, OPT_Wunused_value);
12256 1179 : result = non_lvalue (result);
12257 : }
12258 : }
12259 : }
12260 : }
12261 100416 : return result;
12262 : }
12263 :
12264 : /* If ARG is a REAL_CST, call mpfr_lgamma() on it and return the
12265 : resulting value as a tree with type TYPE. The mpfr precision is
12266 : set to the precision of TYPE. We assume that this mpfr function
12267 : returns zero if the result could be calculated exactly within the
12268 : requested precision. In addition, the integer pointer represented
12269 : by ARG_SG will be dereferenced and set to the appropriate signgam
12270 : (-1,1) value. */
12271 :
12272 : static tree
12273 6504 : do_mpfr_lgamma_r (tree arg, tree arg_sg, tree type)
12274 : {
12275 6504 : tree result = NULL_TREE;
12276 :
12277 6504 : STRIP_NOPS (arg);
12278 :
12279 : /* To proceed, MPFR must exactly represent the target floating point
12280 : format, which only happens when the target base equals two. Also
12281 : verify ARG is a constant and that ARG_SG is an int pointer. */
12282 6504 : if (REAL_MODE_FORMAT (TYPE_MODE (type))->b == 2
12283 6504 : && TREE_CODE (arg) == REAL_CST && !TREE_OVERFLOW (arg)
12284 6470 : && TREE_CODE (TREE_TYPE (arg_sg)) == POINTER_TYPE
12285 12974 : && TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (arg_sg))) == integer_type_node)
12286 : {
12287 6470 : const REAL_VALUE_TYPE *const ra = TREE_REAL_CST_PTR (arg);
12288 :
12289 : /* In addition to NaN and Inf, the argument cannot be zero or a
12290 : negative integer. */
12291 6470 : if (real_isfinite (ra)
12292 6470 : && ra->cl != rvc_zero
12293 12940 : && !(real_isneg (ra) && real_isinteger (ra, TYPE_MODE (type))))
12294 : {
12295 674 : const struct real_format *fmt = REAL_MODE_FORMAT (TYPE_MODE (type));
12296 674 : const int prec = fmt->p;
12297 674 : const mpfr_rnd_t rnd = fmt->round_towards_zero? MPFR_RNDZ : MPFR_RNDN;
12298 674 : int inexact, sg;
12299 674 : tree result_lg;
12300 :
12301 674 : auto_mpfr m (prec);
12302 674 : mpfr_from_real (m, ra, MPFR_RNDN);
12303 674 : mpfr_clear_flags ();
12304 674 : inexact = mpfr_lgamma (m, &sg, m, rnd);
12305 674 : result_lg = do_mpfr_ckconv (m, type, inexact);
12306 674 : if (result_lg)
12307 : {
12308 674 : tree result_sg;
12309 :
12310 : /* Dereference the arg_sg pointer argument. */
12311 674 : arg_sg = build_fold_indirect_ref (arg_sg);
12312 : /* Assign the signgam value into *arg_sg. */
12313 674 : result_sg = fold_build2 (MODIFY_EXPR,
12314 : TREE_TYPE (arg_sg), arg_sg,
12315 : build_int_cst (TREE_TYPE (arg_sg), sg));
12316 674 : TREE_SIDE_EFFECTS (result_sg) = 1;
12317 : /* Combine the signgam assignment with the lgamma result. */
12318 674 : result = non_lvalue (fold_build2 (COMPOUND_EXPR, type,
12319 : result_sg, result_lg));
12320 : }
12321 674 : }
12322 : }
12323 :
12324 6504 : return result;
12325 : }
12326 :
12327 : /* If arguments ARG0 and ARG1 are a COMPLEX_CST, call the two-argument
12328 : mpc function FUNC on it and return the resulting value as a tree
12329 : with type TYPE. The mpfr precision is set to the precision of
12330 : TYPE. We assume that function FUNC returns zero if the result
12331 : could be calculated exactly within the requested precision. If
12332 : DO_NONFINITE is true, then fold expressions containing Inf or NaN
12333 : in the arguments and/or results. */
12334 :
12335 : tree
12336 4523 : do_mpc_arg2 (tree arg0, tree arg1, tree type, int do_nonfinite,
12337 : int (*func)(mpc_ptr, mpc_srcptr, mpc_srcptr, mpc_rnd_t))
12338 : {
12339 4523 : tree result = NULL_TREE;
12340 :
12341 4523 : STRIP_NOPS (arg0);
12342 4523 : STRIP_NOPS (arg1);
12343 :
12344 : /* To proceed, MPFR must exactly represent the target floating point
12345 : format, which only happens when the target base equals two. */
12346 4523 : if (TREE_CODE (arg0) == COMPLEX_CST && !TREE_OVERFLOW (arg0)
12347 4523 : && SCALAR_FLOAT_TYPE_P (TREE_TYPE (TREE_TYPE (arg0)))
12348 4523 : && TREE_CODE (arg1) == COMPLEX_CST && !TREE_OVERFLOW (arg1)
12349 4523 : && SCALAR_FLOAT_TYPE_P (TREE_TYPE (TREE_TYPE (arg1)))
12350 9046 : && REAL_MODE_FORMAT (TYPE_MODE (TREE_TYPE (TREE_TYPE (arg0))))->b == 2)
12351 : {
12352 4523 : const REAL_VALUE_TYPE *const re0 = TREE_REAL_CST_PTR (TREE_REALPART (arg0));
12353 4523 : const REAL_VALUE_TYPE *const im0 = TREE_REAL_CST_PTR (TREE_IMAGPART (arg0));
12354 4523 : const REAL_VALUE_TYPE *const re1 = TREE_REAL_CST_PTR (TREE_REALPART (arg1));
12355 4523 : const REAL_VALUE_TYPE *const im1 = TREE_REAL_CST_PTR (TREE_IMAGPART (arg1));
12356 :
12357 4523 : if (do_nonfinite
12358 4523 : || (real_isfinite (re0) && real_isfinite (im0)
12359 4059 : && real_isfinite (re1) && real_isfinite (im1)))
12360 : {
12361 4171 : const struct real_format *const fmt =
12362 4171 : REAL_MODE_FORMAT (TYPE_MODE (TREE_TYPE (type)));
12363 4171 : const int prec = fmt->p;
12364 4171 : const mpfr_rnd_t rnd = fmt->round_towards_zero
12365 4171 : ? MPFR_RNDZ : MPFR_RNDN;
12366 4171 : const mpc_rnd_t crnd = fmt->round_towards_zero ? MPC_RNDZZ : MPC_RNDNN;
12367 4171 : int inexact;
12368 4171 : mpc_t m0, m1;
12369 :
12370 4171 : mpc_init2 (m0, prec);
12371 4171 : mpc_init2 (m1, prec);
12372 4171 : mpfr_from_real (mpc_realref (m0), re0, rnd);
12373 4171 : mpfr_from_real (mpc_imagref (m0), im0, rnd);
12374 4171 : mpfr_from_real (mpc_realref (m1), re1, rnd);
12375 4171 : mpfr_from_real (mpc_imagref (m1), im1, rnd);
12376 4171 : mpfr_clear_flags ();
12377 4171 : inexact = func (m0, m0, m1, crnd);
12378 4171 : result = do_mpc_ckconv (m0, type, inexact, do_nonfinite);
12379 4171 : mpc_clear (m0);
12380 4171 : mpc_clear (m1);
12381 : }
12382 : }
12383 :
12384 4523 : return result;
12385 : }
12386 :
12387 : /* A wrapper function for builtin folding that prevents warnings for
12388 : "statement without effect" and the like, caused by removing the
12389 : call node earlier than the warning is generated. */
12390 :
12391 : tree
12392 6168429 : fold_call_stmt (gcall *stmt, bool ignore)
12393 : {
12394 6168429 : tree ret = NULL_TREE;
12395 6168429 : tree fndecl = gimple_call_fndecl (stmt);
12396 6168429 : location_t loc = gimple_location (stmt);
12397 6168429 : if (fndecl && fndecl_built_in_p (fndecl)
12398 12336858 : && !gimple_call_va_arg_pack_p (stmt))
12399 : {
12400 6168363 : int nargs = gimple_call_num_args (stmt);
12401 6168363 : tree *args = (nargs > 0
12402 6168363 : ? gimple_call_arg_ptr (stmt, 0)
12403 : : &error_mark_node);
12404 :
12405 6168363 : if (avoid_folding_inline_builtin (fndecl))
12406 : return NULL_TREE;
12407 6168363 : if (DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_MD)
12408 : {
12409 0 : return targetm.fold_builtin (fndecl, nargs, args, ignore);
12410 : }
12411 : else
12412 : {
12413 6168363 : ret = fold_builtin_n (loc, NULL_TREE, fndecl, args, nargs, ignore);
12414 6168363 : if (ret)
12415 : {
12416 : /* Propagate location information from original call to
12417 : expansion of builtin. Otherwise things like
12418 : maybe_emit_chk_warning, that operate on the expansion
12419 : of a builtin, will use the wrong location information. */
12420 5119 : if (gimple_has_location (stmt))
12421 : {
12422 5118 : tree realret = ret;
12423 5118 : if (TREE_CODE (ret) == NOP_EXPR)
12424 5118 : realret = TREE_OPERAND (ret, 0);
12425 5118 : if (CAN_HAVE_LOCATION_P (realret)
12426 9366 : && !EXPR_HAS_LOCATION (realret))
12427 6 : SET_EXPR_LOCATION (realret, loc);
12428 : return realret;
12429 : }
12430 : return ret;
12431 : }
12432 : }
12433 : }
12434 : return NULL_TREE;
12435 : }
12436 :
12437 : /* Look up the function in builtin_decl that corresponds to DECL
12438 : and set ASMSPEC as its user assembler name. DECL must be a
12439 : function decl that declares a builtin. */
12440 :
12441 : void
12442 156382 : set_builtin_user_assembler_name (tree decl, const char *asmspec)
12443 : {
12444 156382 : gcc_assert (fndecl_built_in_p (decl, BUILT_IN_NORMAL)
12445 : && asmspec != 0);
12446 :
12447 156382 : tree builtin = builtin_decl_explicit (DECL_FUNCTION_CODE (decl));
12448 156382 : set_user_assembler_name (builtin, asmspec);
12449 :
12450 156382 : if (DECL_FUNCTION_CODE (decl) == BUILT_IN_FFS
12451 156382 : && INT_TYPE_SIZE < BITS_PER_WORD)
12452 : {
12453 1 : scalar_int_mode mode = int_mode_for_size (INT_TYPE_SIZE, 0).require ();
12454 1 : set_user_assembler_libfunc ("ffs", asmspec);
12455 1 : set_optab_libfunc (ffs_optab, mode, "ffs");
12456 : }
12457 156382 : }
12458 :
12459 : /* Return true if DECL is a builtin that expands to a constant or similarly
12460 : simple code. */
12461 : bool
12462 32691432 : is_simple_builtin (tree decl)
12463 : {
12464 32691432 : if (decl && fndecl_built_in_p (decl, BUILT_IN_NORMAL))
12465 31372316 : switch (DECL_FUNCTION_CODE (decl))
12466 : {
12467 : /* Builtins that expand to constants. */
12468 : case BUILT_IN_CONSTANT_P:
12469 : case BUILT_IN_EXPECT:
12470 : case BUILT_IN_OBJECT_SIZE:
12471 : case BUILT_IN_UNREACHABLE:
12472 : /* Simple register moves or loads from stack. */
12473 : case BUILT_IN_ASSUME_ALIGNED:
12474 : case BUILT_IN_RETURN_ADDRESS:
12475 : case BUILT_IN_EXTRACT_RETURN_ADDR:
12476 : case BUILT_IN_FROB_RETURN_ADDR:
12477 : case BUILT_IN_RETURN:
12478 : case BUILT_IN_AGGREGATE_INCOMING_ADDRESS:
12479 : case BUILT_IN_FRAME_ADDRESS:
12480 : case BUILT_IN_VA_END:
12481 : case BUILT_IN_STACK_SAVE:
12482 : case BUILT_IN_STACK_RESTORE:
12483 : case BUILT_IN_DWARF_CFA:
12484 : case BUILT_IN_CALL_CODE_ADDRESS:
12485 : case BUILT_IN_CALL_STATIC_CHAIN:
12486 : /* Exception state returns or moves registers around. */
12487 : case BUILT_IN_EH_FILTER:
12488 : case BUILT_IN_EH_POINTER:
12489 : case BUILT_IN_EH_COPY_VALUES:
12490 : return true;
12491 :
12492 28123304 : default:
12493 28123304 : return false;
12494 : }
12495 :
12496 : return false;
12497 : }
12498 :
12499 : /* Return true if DECL is a builtin that is not expensive, i.e., they are
12500 : most probably expanded inline into reasonably simple code. This is a
12501 : superset of is_simple_builtin. */
12502 : bool
12503 19669435 : is_inexpensive_builtin (tree decl)
12504 : {
12505 19669435 : if (!decl)
12506 : return false;
12507 19654844 : else if (DECL_BUILT_IN_CLASS (decl) == BUILT_IN_MD)
12508 : return true;
12509 18309335 : else if (DECL_BUILT_IN_CLASS (decl) == BUILT_IN_NORMAL)
12510 15242131 : switch (DECL_FUNCTION_CODE (decl))
12511 : {
12512 : case BUILT_IN_ABS:
12513 : CASE_BUILT_IN_ALLOCA:
12514 : case BUILT_IN_BSWAP16:
12515 : case BUILT_IN_BSWAP32:
12516 : case BUILT_IN_BSWAP64:
12517 : case BUILT_IN_BSWAP128:
12518 : case BUILT_IN_BITREVERSE8:
12519 : case BUILT_IN_BITREVERSE16:
12520 : case BUILT_IN_BITREVERSE32:
12521 : case BUILT_IN_BITREVERSE64:
12522 : case BUILT_IN_BITREVERSE128:
12523 : case BUILT_IN_CLZ:
12524 : case BUILT_IN_CLZIMAX:
12525 : case BUILT_IN_CLZL:
12526 : case BUILT_IN_CLZLL:
12527 : case BUILT_IN_CTZ:
12528 : case BUILT_IN_CTZIMAX:
12529 : case BUILT_IN_CTZL:
12530 : case BUILT_IN_CTZLL:
12531 : case BUILT_IN_FFS:
12532 : case BUILT_IN_FFSIMAX:
12533 : case BUILT_IN_FFSL:
12534 : case BUILT_IN_FFSLL:
12535 : case BUILT_IN_IMAXABS:
12536 : case BUILT_IN_FINITE:
12537 : case BUILT_IN_FINITEF:
12538 : case BUILT_IN_FINITEL:
12539 : case BUILT_IN_FINITED32:
12540 : case BUILT_IN_FINITED64:
12541 : case BUILT_IN_FINITED128:
12542 : case BUILT_IN_FPCLASSIFY:
12543 : case BUILT_IN_ISFINITE:
12544 : case BUILT_IN_ISINF_SIGN:
12545 : case BUILT_IN_ISINF:
12546 : case BUILT_IN_ISINFF:
12547 : case BUILT_IN_ISINFL:
12548 : case BUILT_IN_ISINFD32:
12549 : case BUILT_IN_ISINFD64:
12550 : case BUILT_IN_ISINFD128:
12551 : case BUILT_IN_ISNAN:
12552 : case BUILT_IN_ISNANF:
12553 : case BUILT_IN_ISNANL:
12554 : case BUILT_IN_ISNAND32:
12555 : case BUILT_IN_ISNAND64:
12556 : case BUILT_IN_ISNAND128:
12557 : case BUILT_IN_ISNORMAL:
12558 : case BUILT_IN_ISGREATER:
12559 : case BUILT_IN_ISGREATEREQUAL:
12560 : case BUILT_IN_ISLESS:
12561 : case BUILT_IN_ISLESSEQUAL:
12562 : case BUILT_IN_ISLESSGREATER:
12563 : case BUILT_IN_ISUNORDERED:
12564 : case BUILT_IN_ISEQSIG:
12565 : case BUILT_IN_VA_ARG_PACK:
12566 : case BUILT_IN_VA_ARG_PACK_LEN:
12567 : case BUILT_IN_VA_COPY:
12568 : case BUILT_IN_TRAP:
12569 : case BUILT_IN_UNREACHABLE_TRAP:
12570 : case BUILT_IN_SAVEREGS:
12571 : case BUILT_IN_POPCOUNTL:
12572 : case BUILT_IN_POPCOUNTLL:
12573 : case BUILT_IN_POPCOUNTIMAX:
12574 : case BUILT_IN_POPCOUNT:
12575 : case BUILT_IN_PARITYL:
12576 : case BUILT_IN_PARITYLL:
12577 : case BUILT_IN_PARITYIMAX:
12578 : case BUILT_IN_PARITY:
12579 : case BUILT_IN_LABS:
12580 : case BUILT_IN_LLABS:
12581 : case BUILT_IN_PREFETCH:
12582 : case BUILT_IN_ACC_ON_DEVICE:
12583 : return true;
12584 :
12585 14581859 : default:
12586 14581859 : return is_simple_builtin (decl);
12587 : }
12588 :
12589 : return false;
12590 : }
12591 :
12592 : /* Return true if T is a constant and the value cast to a target char
12593 : can be represented by a host char.
12594 : Store the casted char constant in *P if so. */
12595 :
12596 : bool
12597 3791 : target_char_cst_p (tree t, char *p)
12598 : {
12599 3791 : if (!tree_fits_uhwi_p (t) || CHAR_TYPE_SIZE != HOST_BITS_PER_CHAR)
12600 : return false;
12601 :
12602 2065 : *p = (char)tree_to_uhwi (t);
12603 2065 : return true;
12604 : }
12605 :
12606 : /* Return true if the builtin DECL is implemented in a standard library.
12607 : Otherwise return false which doesn't guarantee it is not (thus the list
12608 : of handled builtins below may be incomplete). */
12609 :
12610 : bool
12611 42460 : builtin_with_linkage_p (tree decl)
12612 : {
12613 42460 : if (DECL_BUILT_IN_CLASS (decl) == BUILT_IN_NORMAL)
12614 42176 : switch (DECL_FUNCTION_CODE (decl))
12615 : {
12616 1322 : CASE_FLT_FN (BUILT_IN_ACOS):
12617 1322 : CASE_FLT_FN_FLOATN_NX (BUILT_IN_ACOS):
12618 1322 : CASE_FLT_FN (BUILT_IN_ACOSH):
12619 1322 : CASE_FLT_FN_FLOATN_NX (BUILT_IN_ACOSH):
12620 1322 : CASE_FLT_FN (BUILT_IN_ACOSPI):
12621 1322 : CASE_FLT_FN_FLOATN_NX (BUILT_IN_ACOSPI):
12622 1322 : CASE_FLT_FN (BUILT_IN_ASIN):
12623 1322 : CASE_FLT_FN_FLOATN_NX (BUILT_IN_ASIN):
12624 1322 : CASE_FLT_FN (BUILT_IN_ASINH):
12625 1322 : CASE_FLT_FN_FLOATN_NX (BUILT_IN_ASINH):
12626 1322 : CASE_FLT_FN (BUILT_IN_ASINPI):
12627 1322 : CASE_FLT_FN_FLOATN_NX (BUILT_IN_ASINPI):
12628 1322 : CASE_FLT_FN (BUILT_IN_ATAN):
12629 1322 : CASE_FLT_FN_FLOATN_NX (BUILT_IN_ATAN):
12630 1322 : CASE_FLT_FN (BUILT_IN_ATAN2):
12631 1322 : CASE_FLT_FN_FLOATN_NX (BUILT_IN_ATAN2):
12632 1322 : CASE_FLT_FN (BUILT_IN_ATAN2PI):
12633 1322 : CASE_FLT_FN_FLOATN_NX (BUILT_IN_ATAN2PI):
12634 1322 : CASE_FLT_FN (BUILT_IN_ATANH):
12635 1322 : CASE_FLT_FN_FLOATN_NX (BUILT_IN_ATANH):
12636 1322 : CASE_FLT_FN (BUILT_IN_ATANPI):
12637 1322 : CASE_FLT_FN_FLOATN_NX (BUILT_IN_ATANPI):
12638 1322 : CASE_FLT_FN (BUILT_IN_CBRT):
12639 1322 : CASE_FLT_FN_FLOATN_NX (BUILT_IN_CBRT):
12640 1322 : CASE_FLT_FN (BUILT_IN_CEIL):
12641 1322 : CASE_FLT_FN_FLOATN_NX (BUILT_IN_CEIL):
12642 1322 : CASE_FLT_FN (BUILT_IN_COPYSIGN):
12643 1322 : CASE_FLT_FN_FLOATN_NX (BUILT_IN_COPYSIGN):
12644 1322 : CASE_FLT_FN (BUILT_IN_COS):
12645 1322 : CASE_FLT_FN_FLOATN_NX (BUILT_IN_COS):
12646 1322 : CASE_FLT_FN (BUILT_IN_COSH):
12647 1322 : CASE_FLT_FN_FLOATN_NX (BUILT_IN_COSH):
12648 1322 : CASE_FLT_FN (BUILT_IN_COSPI):
12649 1322 : CASE_FLT_FN_FLOATN_NX (BUILT_IN_COSPI):
12650 1322 : CASE_FLT_FN (BUILT_IN_ERF):
12651 1322 : CASE_FLT_FN_FLOATN_NX (BUILT_IN_ERF):
12652 1322 : CASE_FLT_FN (BUILT_IN_ERFC):
12653 1322 : CASE_FLT_FN_FLOATN_NX (BUILT_IN_ERFC):
12654 1322 : CASE_FLT_FN (BUILT_IN_EXP):
12655 1322 : CASE_FLT_FN_FLOATN_NX (BUILT_IN_EXP):
12656 1322 : CASE_FLT_FN (BUILT_IN_EXP2):
12657 1322 : CASE_FLT_FN_FLOATN_NX (BUILT_IN_EXP2):
12658 1322 : CASE_FLT_FN (BUILT_IN_EXPM1):
12659 1322 : CASE_FLT_FN_FLOATN_NX (BUILT_IN_EXPM1):
12660 1322 : CASE_FLT_FN (BUILT_IN_FABS):
12661 1322 : CASE_FLT_FN_FLOATN_NX (BUILT_IN_FABS):
12662 1322 : CASE_FLT_FN (BUILT_IN_FDIM):
12663 1322 : CASE_FLT_FN_FLOATN_NX (BUILT_IN_FDIM):
12664 1322 : CASE_FLT_FN (BUILT_IN_FLOOR):
12665 1322 : CASE_FLT_FN_FLOATN_NX (BUILT_IN_FLOOR):
12666 1322 : CASE_FLT_FN (BUILT_IN_FMA):
12667 1322 : CASE_FLT_FN_FLOATN_NX (BUILT_IN_FMA):
12668 1322 : CASE_FLT_FN (BUILT_IN_FMAX):
12669 1322 : CASE_FLT_FN_FLOATN_NX (BUILT_IN_FMAX):
12670 1322 : CASE_FLT_FN (BUILT_IN_FMIN):
12671 1322 : CASE_FLT_FN_FLOATN_NX (BUILT_IN_FMIN):
12672 1322 : CASE_FLT_FN (BUILT_IN_FMOD):
12673 1322 : CASE_FLT_FN_FLOATN_NX (BUILT_IN_FMOD):
12674 1322 : CASE_FLT_FN (BUILT_IN_FREXP):
12675 1322 : CASE_FLT_FN_FLOATN_NX (BUILT_IN_FREXP):
12676 1322 : CASE_FLT_FN (BUILT_IN_HYPOT):
12677 1322 : CASE_FLT_FN_FLOATN_NX (BUILT_IN_HYPOT):
12678 1322 : CASE_FLT_FN (BUILT_IN_ILOGB):
12679 1322 : CASE_FLT_FN_FLOATN_NX (BUILT_IN_ILOGB):
12680 1322 : CASE_FLT_FN (BUILT_IN_LDEXP):
12681 1322 : CASE_FLT_FN_FLOATN_NX (BUILT_IN_LDEXP):
12682 1322 : CASE_FLT_FN (BUILT_IN_LGAMMA):
12683 1322 : CASE_FLT_FN_FLOATN_NX (BUILT_IN_LGAMMA):
12684 1322 : CASE_FLT_FN (BUILT_IN_LLRINT):
12685 1322 : CASE_FLT_FN_FLOATN_NX (BUILT_IN_LLRINT):
12686 1322 : CASE_FLT_FN (BUILT_IN_LLROUND):
12687 1322 : CASE_FLT_FN_FLOATN_NX (BUILT_IN_LLROUND):
12688 1322 : CASE_FLT_FN (BUILT_IN_LOG):
12689 1322 : CASE_FLT_FN_FLOATN_NX (BUILT_IN_LOG):
12690 1322 : CASE_FLT_FN (BUILT_IN_LOG10):
12691 1322 : CASE_FLT_FN_FLOATN_NX (BUILT_IN_LOG10):
12692 1322 : CASE_FLT_FN (BUILT_IN_LOG1P):
12693 1322 : CASE_FLT_FN_FLOATN_NX (BUILT_IN_LOG1P):
12694 1322 : CASE_FLT_FN (BUILT_IN_LOG2):
12695 1322 : CASE_FLT_FN_FLOATN_NX (BUILT_IN_LOG2):
12696 1322 : CASE_FLT_FN (BUILT_IN_LOGB):
12697 1322 : CASE_FLT_FN_FLOATN_NX (BUILT_IN_LOGB):
12698 1322 : CASE_FLT_FN (BUILT_IN_LRINT):
12699 1322 : CASE_FLT_FN_FLOATN_NX (BUILT_IN_LRINT):
12700 1322 : CASE_FLT_FN (BUILT_IN_LROUND):
12701 1322 : CASE_FLT_FN_FLOATN_NX (BUILT_IN_LROUND):
12702 1322 : CASE_FLT_FN (BUILT_IN_MODF):
12703 1322 : CASE_FLT_FN_FLOATN_NX (BUILT_IN_MODF):
12704 1322 : CASE_FLT_FN (BUILT_IN_NAN):
12705 1322 : CASE_FLT_FN_FLOATN_NX (BUILT_IN_NAN):
12706 1322 : CASE_FLT_FN (BUILT_IN_NEARBYINT):
12707 1322 : CASE_FLT_FN_FLOATN_NX (BUILT_IN_NEARBYINT):
12708 1322 : CASE_FLT_FN (BUILT_IN_NEXTAFTER):
12709 1322 : CASE_FLT_FN_FLOATN_NX (BUILT_IN_NEXTAFTER):
12710 1322 : CASE_FLT_FN (BUILT_IN_NEXTTOWARD):
12711 1322 : CASE_FLT_FN (BUILT_IN_POW):
12712 1322 : CASE_FLT_FN_FLOATN_NX (BUILT_IN_POW):
12713 1322 : CASE_FLT_FN (BUILT_IN_REMAINDER):
12714 1322 : CASE_FLT_FN_FLOATN_NX (BUILT_IN_REMAINDER):
12715 1322 : CASE_FLT_FN (BUILT_IN_REMQUO):
12716 1322 : CASE_FLT_FN_FLOATN_NX (BUILT_IN_REMQUO):
12717 1322 : CASE_FLT_FN (BUILT_IN_RINT):
12718 1322 : CASE_FLT_FN_FLOATN_NX (BUILT_IN_RINT):
12719 1322 : CASE_FLT_FN (BUILT_IN_ROUND):
12720 1322 : CASE_FLT_FN_FLOATN_NX (BUILT_IN_ROUND):
12721 1322 : CASE_FLT_FN (BUILT_IN_SCALBLN):
12722 1322 : CASE_FLT_FN_FLOATN_NX (BUILT_IN_SCALBLN):
12723 1322 : CASE_FLT_FN (BUILT_IN_SCALBN):
12724 1322 : CASE_FLT_FN_FLOATN_NX (BUILT_IN_SCALBN):
12725 1322 : CASE_FLT_FN (BUILT_IN_SIN):
12726 1322 : CASE_FLT_FN_FLOATN_NX (BUILT_IN_SIN):
12727 1322 : CASE_FLT_FN (BUILT_IN_SINCOS):
12728 1322 : CASE_FLT_FN (BUILT_IN_SINH):
12729 1322 : CASE_FLT_FN_FLOATN_NX (BUILT_IN_SINH):
12730 1322 : CASE_FLT_FN (BUILT_IN_SINPI):
12731 1322 : CASE_FLT_FN_FLOATN_NX (BUILT_IN_SINPI):
12732 1322 : CASE_FLT_FN (BUILT_IN_SQRT):
12733 1322 : CASE_FLT_FN_FLOATN_NX (BUILT_IN_SQRT):
12734 1322 : CASE_FLT_FN (BUILT_IN_TAN):
12735 1322 : CASE_FLT_FN_FLOATN_NX (BUILT_IN_TAN):
12736 1322 : CASE_FLT_FN (BUILT_IN_TANH):
12737 1322 : CASE_FLT_FN_FLOATN_NX (BUILT_IN_TANH):
12738 1322 : CASE_FLT_FN (BUILT_IN_TANPI):
12739 1322 : CASE_FLT_FN_FLOATN_NX (BUILT_IN_TANPI):
12740 1322 : CASE_FLT_FN (BUILT_IN_TGAMMA):
12741 1322 : CASE_FLT_FN_FLOATN_NX (BUILT_IN_TGAMMA):
12742 1322 : CASE_FLT_FN (BUILT_IN_TRUNC):
12743 1322 : CASE_FLT_FN_FLOATN_NX (BUILT_IN_TRUNC):
12744 1322 : return true;
12745 :
12746 16 : case BUILT_IN_STPCPY:
12747 16 : case BUILT_IN_STPNCPY:
12748 : /* stpcpy is both referenced in libiberty's pex-win32.c and provided
12749 : by libiberty's stpcpy.c for MinGW targets so we need to return true
12750 : in order to be able to build libiberty in LTO mode for them. */
12751 16 : return true;
12752 :
12753 : default:
12754 : break;
12755 : }
12756 : return false;
12757 : }
12758 :
12759 : /* Return true if OFFRNG is bounded to a subrange of offset values
12760 : valid for the largest possible object. */
12761 :
12762 : bool
12763 501 : access_ref::offset_bounded () const
12764 : {
12765 501 : tree min = TYPE_MIN_VALUE (ptrdiff_type_node);
12766 501 : tree max = TYPE_MAX_VALUE (ptrdiff_type_node);
12767 975 : return wi::to_offset (min) <= offrng[0] && offrng[1] <= wi::to_offset (max);
12768 : }
12769 :
12770 : /* If CALLEE has known side effects, fill in INFO and return true.
12771 : See tree-ssa-structalias.cc:find_func_aliases
12772 : for the list of builtins we might need to handle here. */
12773 :
12774 : attr_fnspec
12775 116196797 : builtin_fnspec (tree callee)
12776 : {
12777 116196797 : built_in_function code = DECL_FUNCTION_CODE (callee);
12778 :
12779 116196797 : switch (code)
12780 : {
12781 : /* All the following functions read memory pointed to by
12782 : their second argument and write memory pointed to by first
12783 : argument.
12784 : strcat/strncat additionally reads memory pointed to by the first
12785 : argument. */
12786 133457 : case BUILT_IN_STRCAT:
12787 133457 : case BUILT_IN_STRCAT_CHK:
12788 133457 : return "1cW 1 ";
12789 42125 : case BUILT_IN_STRNCAT:
12790 42125 : case BUILT_IN_STRNCAT_CHK:
12791 42125 : return "1cW 13";
12792 263477 : case BUILT_IN_STRCPY:
12793 263477 : case BUILT_IN_STRCPY_CHK:
12794 263477 : return "1cO 1 ";
12795 32528 : case BUILT_IN_STPCPY:
12796 32528 : case BUILT_IN_STPCPY_CHK:
12797 32528 : return ".cO 1 ";
12798 19313281 : case BUILT_IN_STRNCPY:
12799 19313281 : case BUILT_IN_MEMCPY:
12800 19313281 : case BUILT_IN_MEMMOVE:
12801 19313281 : case BUILT_IN_TM_MEMCPY:
12802 19313281 : case BUILT_IN_TM_MEMMOVE:
12803 19313281 : case BUILT_IN_STRNCPY_CHK:
12804 19313281 : case BUILT_IN_MEMCPY_CHK:
12805 19313281 : case BUILT_IN_MEMMOVE_CHK:
12806 19313281 : return "1cO313";
12807 143964 : case BUILT_IN_MEMPCPY:
12808 143964 : case BUILT_IN_MEMPCPY_CHK:
12809 143964 : return ".cO313";
12810 58403 : case BUILT_IN_STPNCPY:
12811 58403 : case BUILT_IN_STPNCPY_CHK:
12812 58403 : return ".cO313";
12813 0 : case BUILT_IN_BCOPY:
12814 0 : return ".c23O3";
12815 0 : case BUILT_IN_BZERO:
12816 0 : return ".cO2";
12817 10074025 : case BUILT_IN_MEMCMP:
12818 10074025 : case BUILT_IN_MEMCMP_EQ:
12819 10074025 : case BUILT_IN_BCMP:
12820 10074025 : case BUILT_IN_STRNCMP:
12821 10074025 : case BUILT_IN_STRNCMP_EQ:
12822 10074025 : case BUILT_IN_STRNCASECMP:
12823 10074025 : return ".cR3R3";
12824 :
12825 : /* The following functions read memory pointed to by their
12826 : first argument. */
12827 773 : CASE_BUILT_IN_TM_LOAD (1):
12828 773 : CASE_BUILT_IN_TM_LOAD (2):
12829 773 : CASE_BUILT_IN_TM_LOAD (4):
12830 773 : CASE_BUILT_IN_TM_LOAD (8):
12831 773 : CASE_BUILT_IN_TM_LOAD (FLOAT):
12832 773 : CASE_BUILT_IN_TM_LOAD (DOUBLE):
12833 773 : CASE_BUILT_IN_TM_LOAD (LDOUBLE):
12834 773 : CASE_BUILT_IN_TM_LOAD (M64):
12835 773 : CASE_BUILT_IN_TM_LOAD (M128):
12836 773 : CASE_BUILT_IN_TM_LOAD (M256):
12837 773 : case BUILT_IN_TM_LOG:
12838 773 : case BUILT_IN_TM_LOG_1:
12839 773 : case BUILT_IN_TM_LOG_2:
12840 773 : case BUILT_IN_TM_LOG_4:
12841 773 : case BUILT_IN_TM_LOG_8:
12842 773 : case BUILT_IN_TM_LOG_FLOAT:
12843 773 : case BUILT_IN_TM_LOG_DOUBLE:
12844 773 : case BUILT_IN_TM_LOG_LDOUBLE:
12845 773 : case BUILT_IN_TM_LOG_M64:
12846 773 : case BUILT_IN_TM_LOG_M128:
12847 773 : case BUILT_IN_TM_LOG_M256:
12848 773 : return ".cR ";
12849 :
12850 524045 : case BUILT_IN_INDEX:
12851 524045 : case BUILT_IN_RINDEX:
12852 524045 : case BUILT_IN_STRCHR:
12853 524045 : case BUILT_IN_STRLEN:
12854 524045 : case BUILT_IN_STRRCHR:
12855 524045 : return ".cR ";
12856 59118 : case BUILT_IN_STRNLEN:
12857 59118 : return ".cR2";
12858 :
12859 : /* These read memory pointed to by the first argument.
12860 : Allocating memory does not have any side-effects apart from
12861 : being the definition point for the pointer.
12862 : Unix98 specifies that errno is set on allocation failure. */
12863 18629 : case BUILT_IN_STRDUP:
12864 18629 : return "mCR ";
12865 13316 : case BUILT_IN_STRNDUP:
12866 13316 : return "mCR2";
12867 : /* Allocating memory does not have any side-effects apart from
12868 : being the definition point for the pointer. */
12869 11395171 : case BUILT_IN_MALLOC:
12870 11395171 : case BUILT_IN_ALIGNED_ALLOC:
12871 11395171 : case BUILT_IN_CALLOC:
12872 11395171 : case BUILT_IN_GOMP_ALLOC:
12873 11395171 : return "mC";
12874 852553 : CASE_BUILT_IN_ALLOCA:
12875 852553 : return "mc";
12876 : /* These read memory pointed to by the first argument with size
12877 : in the third argument. */
12878 746530 : case BUILT_IN_MEMCHR:
12879 746530 : return ".cR3";
12880 : /* These read memory pointed to by the first and second arguments. */
12881 12362599 : case BUILT_IN_STRSTR:
12882 12362599 : case BUILT_IN_STRPBRK:
12883 12362599 : case BUILT_IN_STRCASECMP:
12884 12362599 : case BUILT_IN_STRCSPN:
12885 12362599 : case BUILT_IN_STRSPN:
12886 12362599 : case BUILT_IN_STRCMP:
12887 12362599 : case BUILT_IN_STRCMP_EQ:
12888 12362599 : return ".cR R ";
12889 : /* Freeing memory kills the pointed-to memory. More importantly
12890 : the call has to serve as a barrier for moving loads and stores
12891 : across it. */
12892 6572268 : case BUILT_IN_STACK_RESTORE:
12893 6572268 : case BUILT_IN_FREE:
12894 6572268 : case BUILT_IN_GOMP_FREE:
12895 6572268 : return ".co ";
12896 108884 : case BUILT_IN_VA_END:
12897 108884 : return ".cO ";
12898 : /* Realloc serves both as allocation point and deallocation point. */
12899 1116905 : case BUILT_IN_REALLOC:
12900 1116905 : case BUILT_IN_GOMP_REALLOC:
12901 1116905 : return ".Cw ";
12902 15732 : case BUILT_IN_GAMMA_R:
12903 15732 : case BUILT_IN_GAMMAF_R:
12904 15732 : case BUILT_IN_GAMMAL_R:
12905 15732 : case BUILT_IN_LGAMMA_R:
12906 15732 : case BUILT_IN_LGAMMAF_R:
12907 15732 : case BUILT_IN_LGAMMAL_R:
12908 15732 : return ".C. Ot";
12909 44420 : case BUILT_IN_FREXP:
12910 44420 : case BUILT_IN_FREXPF:
12911 44420 : case BUILT_IN_FREXPL:
12912 44420 : case BUILT_IN_MODF:
12913 44420 : case BUILT_IN_MODFF:
12914 44420 : case BUILT_IN_MODFL:
12915 44420 : return ".c. Ot";
12916 7586 : case BUILT_IN_REMQUO:
12917 7586 : case BUILT_IN_REMQUOF:
12918 7586 : case BUILT_IN_REMQUOL:
12919 7586 : return ".c. . Ot";
12920 164 : case BUILT_IN_SINCOS:
12921 164 : case BUILT_IN_SINCOSF:
12922 164 : case BUILT_IN_SINCOSL:
12923 164 : return ".c. OtOt";
12924 4366861 : case BUILT_IN_MEMSET:
12925 4366861 : case BUILT_IN_MEMSET_CHK:
12926 4366861 : case BUILT_IN_TM_MEMSET:
12927 4366861 : return "1cO3";
12928 366 : CASE_BUILT_IN_TM_STORE (1):
12929 366 : CASE_BUILT_IN_TM_STORE (2):
12930 366 : CASE_BUILT_IN_TM_STORE (4):
12931 366 : CASE_BUILT_IN_TM_STORE (8):
12932 366 : CASE_BUILT_IN_TM_STORE (FLOAT):
12933 366 : CASE_BUILT_IN_TM_STORE (DOUBLE):
12934 366 : CASE_BUILT_IN_TM_STORE (LDOUBLE):
12935 366 : CASE_BUILT_IN_TM_STORE (M64):
12936 366 : CASE_BUILT_IN_TM_STORE (M128):
12937 366 : CASE_BUILT_IN_TM_STORE (M256):
12938 366 : return ".cO ";
12939 2557172 : case BUILT_IN_STACK_SAVE:
12940 2557172 : case BUILT_IN_RETURN:
12941 2557172 : case BUILT_IN_EH_POINTER:
12942 2557172 : case BUILT_IN_EH_FILTER:
12943 2557172 : case BUILT_IN_UNWIND_RESUME:
12944 2557172 : case BUILT_IN_CXA_END_CLEANUP:
12945 2557172 : case BUILT_IN_EH_COPY_VALUES:
12946 2557172 : case BUILT_IN_FRAME_ADDRESS:
12947 2557172 : case BUILT_IN_APPLY_ARGS:
12948 2557172 : case BUILT_IN_ASAN_BEFORE_DYNAMIC_INIT:
12949 2557172 : case BUILT_IN_ASAN_AFTER_DYNAMIC_INIT:
12950 2557172 : case BUILT_IN_PREFETCH:
12951 2557172 : case BUILT_IN_DWARF_CFA:
12952 2557172 : case BUILT_IN_RETURN_ADDRESS:
12953 2557172 : return ".c";
12954 2317424 : case BUILT_IN_ASSUME_ALIGNED:
12955 2317424 : case BUILT_IN_EXPECT:
12956 2317424 : case BUILT_IN_EXPECT_WITH_PROBABILITY:
12957 2317424 : return "1cX ";
12958 : /* But posix_memalign stores a pointer into the memory pointed to
12959 : by its first argument. */
12960 6162 : case BUILT_IN_POSIX_MEMALIGN:
12961 6162 : return ".cOt";
12962 4438 : case BUILT_IN_OMP_GET_MAPPED_PTR:
12963 4438 : return ". R ";
12964 :
12965 43044421 : default:
12966 43044421 : return "";
12967 : }
12968 : }
|