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