Line data Source code
1 : /* Expand builtin functions.
2 : Copyright (C) 1988-2026 Free Software Foundation, Inc.
3 :
4 : This file is part of GCC.
5 :
6 : GCC is free software; you can redistribute it and/or modify it under
7 : the terms of the GNU General Public License as published by the Free
8 : Software Foundation; either version 3, or (at your option) any later
9 : version.
10 :
11 : GCC is distributed in the hope that it will be useful, but WITHOUT ANY
12 : WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 : FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 : for more details.
15 :
16 : You should have received a copy of the GNU General Public License
17 : along with GCC; see the file COPYING3. If not see
18 : <http://www.gnu.org/licenses/>. */
19 :
20 : /* Legacy warning! Please add no further builtin simplifications here
21 : (apart from pure constant folding) - builtin simplifications should go
22 : to match.pd or gimple-fold.cc instead. */
23 :
24 : #include "config.h"
25 : #include "system.h"
26 : #include "coretypes.h"
27 : #include "backend.h"
28 : #include "target.h"
29 : #include "rtl.h"
30 : #include "tree.h"
31 : #include "memmodel.h"
32 : #include "gimple.h"
33 : #include "tree-eh.h"
34 : #include "predict.h"
35 : #include "tm_p.h"
36 : #include "stringpool.h"
37 : #include "tree-vrp.h"
38 : #include "tree-ssanames.h"
39 : #include "expmed.h"
40 : #include "optabs.h"
41 : #include "emit-rtl.h"
42 : #include "recog.h"
43 : #include "diagnostic-core.h"
44 : #include "alias.h"
45 : #include "fold-const.h"
46 : #include "fold-const-call.h"
47 : #include "gimple-ssa-warn-access.h"
48 : #include "stor-layout.h"
49 : #include "calls.h"
50 : #include "varasm.h"
51 : #include "tree-object-size.h"
52 : #include "tree-ssa-strlen.h"
53 : #include "realmpfr.h"
54 : #include "cfgrtl.h"
55 : #include "except.h"
56 : #include "dojump.h"
57 : #include "explow.h"
58 : #include "stmt.h"
59 : #include "expr.h"
60 : #include "libfuncs.h"
61 : #include "output.h"
62 : #include "typeclass.h"
63 : #include "langhooks.h"
64 : #include "value-prof.h"
65 : #include "builtins.h"
66 : #include "attribs.h"
67 : #include "asan.h"
68 : #include "internal-fn.h"
69 : #include "case-cfn-macros.h"
70 : #include "gimple-iterator.h"
71 : #include "gimple-fold.h"
72 : #include "intl.h"
73 : #include "file-prefix-map.h" /* remap_macro_filename() */
74 : #include "ipa-strub.h" /* strub_watermark_parm() */
75 : #include "gomp-constants.h"
76 : #include "omp-general.h"
77 : #include "tree-dfa.h"
78 : #include "gimple-ssa.h"
79 : #include "tree-ssa-live.h"
80 : #include "tree-outof-ssa.h"
81 : #include "attr-fnspec.h"
82 : #include "demangle.h"
83 : #include "gimple-range.h"
84 : #include "pointer-query.h"
85 :
86 : struct target_builtins default_target_builtins;
87 : #if SWITCHABLE_TARGET
88 : struct target_builtins *this_target_builtins = &default_target_builtins;
89 : #endif
90 :
91 : /* Define the names of the builtin function types and codes. */
92 : const char *const built_in_class_names[BUILT_IN_LAST]
93 : = {"NOT_BUILT_IN", "BUILT_IN_FRONTEND", "BUILT_IN_MD", "BUILT_IN_NORMAL"};
94 :
95 : #define DEF_BUILTIN(X, N, C, T, LT, B, F, NA, AT, IM, COND) #X,
96 : const char * built_in_names[(int) END_BUILTINS] =
97 : {
98 : #include "builtins.def"
99 : };
100 :
101 : /* Setup an array of builtin_info_type, make sure each element decl is
102 : initialized to NULL_TREE. */
103 : builtin_info_type builtin_info[(int)END_BUILTINS];
104 :
105 : /* Non-zero if __builtin_constant_p should be folded right away. */
106 : bool force_folding_builtin_constant_p;
107 :
108 : static int target_char_cast (tree, char *);
109 : static int apply_args_size (void);
110 : static int apply_result_size (void);
111 : static rtx result_vector (int, rtx);
112 : static void expand_builtin_prefetch (tree);
113 : static rtx expand_builtin_apply_args (void);
114 : static rtx expand_builtin_apply_args_1 (void);
115 : static rtx expand_builtin_apply (rtx, rtx, rtx);
116 : static void expand_builtin_return (rtx);
117 : static rtx expand_builtin_classify_type (tree);
118 : static rtx expand_builtin_mathfn_3 (tree, rtx, rtx);
119 : static rtx expand_builtin_mathfn_ternary (tree, rtx, rtx);
120 : static rtx expand_builtin_interclass_mathfn (tree, rtx);
121 : static rtx expand_builtin_sincos (tree);
122 : static rtx expand_builtin_fegetround (tree, rtx, machine_mode);
123 : static rtx expand_builtin_feclear_feraise_except (tree, rtx, machine_mode,
124 : optab);
125 : static rtx expand_builtin_cexpi (tree, rtx);
126 : static rtx expand_builtin_issignaling (tree, rtx);
127 : static rtx expand_builtin_int_roundingfn (tree, rtx);
128 : static rtx expand_builtin_int_roundingfn_2 (tree, rtx);
129 : static rtx expand_builtin_next_arg (void);
130 : static rtx expand_builtin_va_start (tree);
131 : static rtx expand_builtin_va_end (tree);
132 : static rtx expand_builtin_va_copy (tree);
133 : static rtx inline_expand_builtin_bytecmp (tree, rtx);
134 : static rtx expand_builtin_strcmp (tree, rtx);
135 : static rtx expand_builtin_strncmp (tree, rtx, machine_mode);
136 : static rtx expand_builtin_memcpy (tree, rtx);
137 : static rtx expand_builtin_memory_copy_args (tree dest, tree src, tree len,
138 : rtx target, tree exp,
139 : memop_ret retmode,
140 : bool might_overlap);
141 : static rtx expand_builtin_memmove (tree, rtx);
142 : static rtx expand_builtin_mempcpy (tree, rtx);
143 : static rtx expand_builtin_mempcpy_args (tree, tree, tree, rtx, tree, memop_ret);
144 : static rtx expand_builtin_strcpy (tree, rtx);
145 : static rtx expand_builtin_strcpy_args (tree, tree, tree, rtx);
146 : static rtx expand_builtin_stpcpy (tree, rtx, machine_mode);
147 : static rtx expand_builtin_strncpy (tree, rtx);
148 : static rtx expand_builtin_memset_args (tree, tree, tree, rtx, machine_mode, tree);
149 : static rtx expand_builtin_bzero (tree);
150 : static rtx expand_builtin_strlen (tree, rtx, machine_mode);
151 : static rtx expand_builtin_strnlen (tree, rtx, machine_mode);
152 : static rtx expand_builtin_alloca (tree);
153 : static rtx expand_builtin_unop (machine_mode, tree, rtx, rtx, optab);
154 : static rtx expand_builtin_frame_address (tree, tree);
155 : static rtx expand_builtin_stack_address ();
156 : static tree stabilize_va_list_loc (location_t, tree, int);
157 : static rtx expand_builtin_expect (tree, rtx);
158 : static rtx expand_builtin_expect_with_probability (tree, rtx);
159 : static tree fold_builtin_classify_type (tree);
160 : static tree fold_builtin_strlen (location_t, tree, tree, tree);
161 : static tree fold_builtin_inf (location_t, tree, int);
162 : static tree rewrite_call_expr (location_t, tree, int, tree, int, ...);
163 : static bool validate_arg (const_tree, enum tree_code code);
164 : static rtx expand_builtin_fabs (tree, rtx, rtx);
165 : static rtx expand_builtin_signbit (tree, rtx);
166 : static tree fold_builtin_memcmp (location_t, tree, tree, tree);
167 : static tree fold_builtin_isascii (location_t, tree);
168 : static tree fold_builtin_toascii (location_t, tree);
169 : static tree fold_builtin_isdigit (location_t, tree);
170 : static tree fold_builtin_fabs (location_t, tree, tree);
171 : static tree fold_builtin_abs (location_t, tree, tree);
172 : static tree fold_builtin_unordered_cmp (location_t, tree, tree, tree, enum tree_code,
173 : enum tree_code);
174 : static tree fold_builtin_iseqsig (location_t, tree, tree);
175 : static tree fold_builtin_varargs (location_t, tree, tree*, int);
176 :
177 : static tree fold_builtin_strpbrk (location_t, tree, tree, tree, tree);
178 : static tree fold_builtin_strspn (location_t, tree, tree, tree, tree);
179 : static tree fold_builtin_strcspn (location_t, tree, tree, tree, tree);
180 :
181 : static rtx expand_builtin_object_size (tree);
182 : static rtx expand_builtin_memory_chk (tree, rtx, machine_mode,
183 : enum built_in_function);
184 : static void maybe_emit_chk_warning (tree, enum built_in_function);
185 : static void maybe_emit_sprintf_chk_warning (tree, enum built_in_function);
186 : static tree fold_builtin_object_size (tree, tree, enum built_in_function);
187 :
188 : unsigned HOST_WIDE_INT target_newline;
189 : unsigned HOST_WIDE_INT target_percent;
190 : static unsigned HOST_WIDE_INT target_c;
191 : static unsigned HOST_WIDE_INT target_s;
192 : char target_percent_c[3];
193 : char target_percent_s[3];
194 : char target_percent_s_newline[4];
195 : static tree do_mpfr_remquo (tree, tree, tree);
196 : static tree do_mpfr_lgamma_r (tree, tree, tree);
197 : static void expand_builtin_sync_synchronize (void);
198 :
199 : /* Return true if NAME starts with __builtin_ or __sync_. */
200 :
201 : static bool
202 536032 : is_builtin_name (const char *name)
203 : {
204 536032 : return (startswith (name, "__builtin_")
205 194864 : || startswith (name, "__sync_")
206 730031 : || 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 536032 : 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 536032 : const char *name = IDENTIFIER_POINTER (DECL_NAME (node));
220 536032 : 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 112292746 : get_object_alignment_2 (tree exp, unsigned int *alignp,
240 : unsigned HOST_WIDE_INT *bitposp, bool addr_p)
241 : {
242 112292746 : poly_int64 bitsize, bitpos;
243 112292746 : tree offset;
244 112292746 : machine_mode mode;
245 112292746 : int unsignedp, reversep, volatilep;
246 112292746 : unsigned int align = BITS_PER_UNIT;
247 112292746 : bool known_alignment = false;
248 :
249 : /* Get the innermost object and the constant (bitpos) and possibly
250 : variable (offset) offset of the access. */
251 112292746 : 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 112292746 : 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 111831097 : else if (TREE_CODE (exp) == LABEL_DECL)
266 : ;
267 111794180 : else if (TREE_CODE (exp) == CONST_DECL)
268 : {
269 : /* The alignment of a CONST_DECL is determined by its initializer. */
270 59675 : exp = DECL_INITIAL (exp);
271 59675 : align = TYPE_ALIGN (TREE_TYPE (exp));
272 59675 : if (CONSTANT_CLASS_P (exp))
273 59674 : align = targetm.constant_alignment (exp, align);
274 :
275 : known_alignment = true;
276 : }
277 111734505 : else if (DECL_P (exp))
278 : {
279 67034072 : align = DECL_ALIGN (exp);
280 : known_alignment = true;
281 : }
282 44700433 : else if (TREE_CODE (exp) == INDIRECT_REF
283 44699377 : || TREE_CODE (exp) == MEM_REF
284 5384895 : || TREE_CODE (exp) == TARGET_MEM_REF)
285 : {
286 42997610 : tree addr = TREE_OPERAND (exp, 0);
287 42997610 : unsigned ptr_align;
288 42997610 : unsigned HOST_WIDE_INT ptr_bitpos;
289 42997610 : unsigned HOST_WIDE_INT ptr_bitmask = ~0;
290 :
291 : /* If the address is explicitly aligned, handle that. */
292 42997610 : if (TREE_CODE (addr) == BIT_AND_EXPR
293 42997610 : && 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 42997610 : known_alignment
302 42997610 : = get_pointer_alignment_1 (addr, &ptr_align, &ptr_bitpos);
303 42997610 : align = MAX (ptr_align, align);
304 :
305 : /* Re-apply explicit alignment to the bitpos. */
306 42997610 : 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 42997610 : if (TREE_CODE (exp) == TARGET_MEM_REF)
311 : {
312 3682072 : if (TMR_INDEX (exp))
313 : {
314 1602275 : unsigned HOST_WIDE_INT step = 1;
315 1602275 : if (TMR_STEP (exp))
316 1468356 : step = TREE_INT_CST_LOW (TMR_STEP (exp));
317 1602275 : align = MIN (align, least_bit_hwi (step) * BITS_PER_UNIT);
318 : }
319 3682072 : if (TMR_INDEX2 (exp))
320 42926 : 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 42997610 : unsigned int talign;
330 42997610 : if (!addr_p && !known_alignment
331 40560944 : && (talign = min_align_of_type (TREE_TYPE (exp)) * BITS_PER_UNIT)
332 83558548 : && talign > align)
333 : align = talign;
334 : else
335 : {
336 : /* Else adjust bitpos accordingly. */
337 11701037 : bitpos += ptr_bitpos;
338 11701037 : if (TREE_CODE (exp) == MEM_REF
339 11701037 : || TREE_CODE (exp) == TARGET_MEM_REF)
340 11699981 : bitpos += mem_ref_offset (exp).force_shwi () * BITS_PER_UNIT;
341 : }
342 42997610 : }
343 1702823 : 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 1702203 : align = TYPE_ALIGN (TREE_TYPE (exp));
348 1702203 : if (CONSTANT_CLASS_P (exp))
349 1702203 : 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 112292746 : if (offset)
357 : {
358 10028092 : unsigned int trailing_zeros = tree_ctz (offset);
359 10028092 : if (trailing_zeros < HOST_BITS_PER_INT)
360 : {
361 10028014 : unsigned int inner = (1U << trailing_zeros) * BITS_PER_UNIT;
362 10028014 : if (inner)
363 10028014 : 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 112292746 : unsigned int alt_align = ::known_alignment (bitpos - bitpos.coeffs[0]);
370 112292746 : if (alt_align != 0 && alt_align < align)
371 : {
372 : align = alt_align;
373 : known_alignment = false;
374 : }
375 :
376 112292746 : *alignp = align;
377 112292746 : *bitposp = bitpos.coeffs[0] & (align - 1);
378 112292746 : 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 89086199 : 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 89086199 : if (TREE_CODE (exp) == WITH_SIZE_EXPR)
393 0 : exp = TREE_OPERAND (exp, 0);
394 89086199 : 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 36922046 : get_object_alignment (tree exp)
401 : {
402 36922046 : unsigned HOST_WIDE_INT bitpos = 0;
403 36922046 : unsigned int align;
404 :
405 36922046 : 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 36922046 : if (bitpos != 0)
411 2771791 : align = least_bit_hwi (bitpos);
412 36922046 : 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 85048619 : get_pointer_alignment_1 (tree exp, unsigned int *alignp,
424 : unsigned HOST_WIDE_INT *bitposp)
425 : {
426 85048619 : STRIP_NOPS (exp);
427 :
428 85048619 : if (TREE_CODE (exp) == ADDR_EXPR)
429 23204916 : return get_object_alignment_2 (TREE_OPERAND (exp, 0),
430 23204916 : alignp, bitposp, true);
431 61843703 : else if (TREE_CODE (exp) == POINTER_PLUS_EXPR)
432 : {
433 1016499 : unsigned int align;
434 1016499 : unsigned HOST_WIDE_INT bitpos;
435 1016499 : bool res = get_pointer_alignment_1 (TREE_OPERAND (exp, 0),
436 : &align, &bitpos);
437 1016499 : if (TREE_CODE (TREE_OPERAND (exp, 1)) == INTEGER_CST)
438 3758 : bitpos += TREE_INT_CST_LOW (TREE_OPERAND (exp, 1)) * BITS_PER_UNIT;
439 : else
440 : {
441 1012741 : unsigned int trailing_zeros = tree_ctz (TREE_OPERAND (exp, 1));
442 1012741 : if (trailing_zeros < HOST_BITS_PER_INT)
443 : {
444 1012733 : unsigned int inner = (1U << trailing_zeros) * BITS_PER_UNIT;
445 1012733 : if (inner)
446 1012733 : align = MIN (align, inner);
447 : }
448 : }
449 1016499 : *alignp = align;
450 1016499 : *bitposp = bitpos & (align - 1);
451 1016499 : return res;
452 : }
453 60827204 : else if (TREE_CODE (exp) == SSA_NAME
454 60827204 : && POINTER_TYPE_P (TREE_TYPE (exp)))
455 : {
456 58511827 : unsigned int ptr_align, ptr_misalign;
457 58511827 : struct ptr_info_def *pi = SSA_NAME_PTR_INFO (exp);
458 :
459 58511827 : if (pi && get_ptr_info_alignment (pi, &ptr_align, &ptr_misalign))
460 : {
461 6480668 : *bitposp = ptr_misalign * BITS_PER_UNIT;
462 6480668 : *alignp = ptr_align * BITS_PER_UNIT;
463 : /* Make sure to return a sensible alignment when the multiplication
464 : by BITS_PER_UNIT overflowed. */
465 6480668 : if (*alignp == 0)
466 30 : *alignp = 1u << (HOST_BITS_PER_INT - 1);
467 : /* We cannot really tell whether this result is an approximation. */
468 : return false;
469 : }
470 : else
471 : {
472 52031159 : *bitposp = 0;
473 52031159 : *alignp = BITS_PER_UNIT;
474 52031159 : return false;
475 : }
476 : }
477 2315377 : else if (TREE_CODE (exp) == INTEGER_CST)
478 : {
479 17485 : *alignp = BIGGEST_ALIGNMENT;
480 17485 : *bitposp = ((TREE_INT_CST_LOW (exp) * BITS_PER_UNIT)
481 17485 : & (BIGGEST_ALIGNMENT - 1));
482 17485 : return true;
483 : }
484 :
485 2297892 : *bitposp = 0;
486 2297892 : *alignp = BITS_PER_UNIT;
487 2297892 : 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 11598398 : get_pointer_alignment (tree exp)
499 : {
500 11598398 : unsigned HOST_WIDE_INT bitpos = 0;
501 11598398 : unsigned int align;
502 :
503 11598398 : 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 11598398 : if (bitpos != 0)
509 79554 : align = least_bit_hwi (bitpos);
510 :
511 11598398 : 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 774464 : string_length (const void *ptr, unsigned eltsize, unsigned maxelts)
520 : {
521 774464 : gcc_checking_assert (eltsize == 1 || eltsize == 2 || eltsize == 4);
522 :
523 774464 : unsigned n;
524 :
525 774464 : if (eltsize == 1)
526 : {
527 : /* Optimize the common case of plain char. */
528 244947658 : for (n = 0; n < maxelts; n++)
529 : {
530 244857660 : const char *elt = (const char*) ptr + n;
531 244857660 : 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 774464 : 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 2631627 : 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 2631627 : c_strlen_data local_strlen_data = { };
583 2631627 : if (!data)
584 604953 : data = &local_strlen_data;
585 :
586 2631627 : gcc_checking_assert (eltsize == 1 || eltsize == 2 || eltsize == 4);
587 :
588 2631627 : tree src = STRIP_NOPS (arg);
589 2631627 : if (TREE_CODE (src) == COND_EXPR
590 2631627 : && (only_value || !TREE_SIDE_EFFECTS (TREE_OPERAND (src, 0))))
591 : {
592 690 : tree len1, len2;
593 :
594 690 : len1 = c_strlen (TREE_OPERAND (src, 1), only_value, data, eltsize);
595 690 : len2 = c_strlen (TREE_OPERAND (src, 2), only_value, data, eltsize);
596 690 : if (tree_int_cst_equal (len1, len2))
597 : return len1;
598 : }
599 :
600 2631461 : if (TREE_CODE (src) == COMPOUND_EXPR
601 2631461 : && (only_value || !TREE_SIDE_EFFECTS (TREE_OPERAND (src, 0))))
602 45 : return c_strlen (TREE_OPERAND (src, 1), only_value, data, eltsize);
603 :
604 2631416 : location_t loc = EXPR_LOC_OR_LOC (src, input_location);
605 :
606 : /* Offset from the beginning of the string in bytes. */
607 2631416 : tree byteoff;
608 2631416 : tree memsize;
609 2631416 : tree decl;
610 2631416 : src = string_constant (src, &byteoff, &memsize, &decl);
611 2631416 : if (src == 0)
612 : return NULL_TREE;
613 :
614 : /* Determine the size of the string element. */
615 790710 : 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 778292 : HOST_WIDE_INT strelts = TREE_STRING_LENGTH (src);
625 778292 : strelts = strelts / eltsize;
626 :
627 778292 : if (!tree_fits_uhwi_p (memsize))
628 : return NULL_TREE;
629 :
630 778292 : 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 778292 : const char *ptr = TREE_STRING_POINTER (src);
635 :
636 778292 : if (byteoff && TREE_CODE (byteoff) != INTEGER_CST)
637 : {
638 : /* The code below works only for single byte character types. */
639 5058 : 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 5058 : 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 5058 : if (len + 1 < strelts)
652 : return NULL_TREE;
653 4488 : 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 3386 : 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 3347 : tree offsave = TREE_SIDE_EFFECTS (byteoff) ? save_expr (byteoff)
671 : : byteoff;
672 3347 : offsave = fold_convert_loc (loc, sizetype, offsave);
673 3347 : tree condexp = fold_build2_loc (loc, LE_EXPR, boolean_type_node, offsave,
674 3347 : size_int (len));
675 3347 : tree lenexp = fold_build2_loc (loc, MINUS_EXPR, sizetype, size_int (len),
676 : offsave);
677 3347 : lenexp = fold_convert_loc (loc, ssizetype, lenexp);
678 3347 : return fold_build3_loc (loc, COND_EXPR, ssizetype, condexp, lenexp,
679 3347 : build_zero_cst (ssizetype));
680 : }
681 :
682 : /* Offset from the beginning of the string in elements. */
683 773234 : 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 773234 : if (byteoff == 0)
688 : eltoff = 0;
689 773234 : else if (! tree_fits_uhwi_p (byteoff) || tree_to_uhwi (byteoff) % eltsize)
690 : eltoff = -1;
691 : else
692 772046 : 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 773234 : if (eltoff < 0 || eltoff >= maxelts)
697 : {
698 : /* Suppress multiple warnings for propagated constant strings. */
699 3828 : if (only_value != 2
700 3828 : && !warning_suppressed_p (arg, OPT_Warray_bounds_)
701 7656 : && warning_at (loc, OPT_Warray_bounds_,
702 : "offset %qwi outside bounds of constant string",
703 : eltoff))
704 : {
705 679 : if (decl)
706 678 : inform (DECL_SOURCE_LOCATION (decl), "%qE declared here", decl);
707 679 : suppress_warning (arg, OPT_Warray_bounds_);
708 : }
709 : return NULL_TREE;
710 : }
711 :
712 : /* If eltoff is larger than strelts but less than maxelts the
713 : string length is zero, since the excess memory will be zero. */
714 769406 : 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 769406 : unsigned len = string_length (ptr + eltoff * eltsize, eltsize,
724 769406 : 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 769406 : if (len >= maxelts - eltoff)
730 : {
731 84400 : data->decl = decl;
732 84400 : data->off = byteoff;
733 84400 : data->minlen = ssize_int (len);
734 84400 : return NULL_TREE;
735 : }
736 :
737 685006 : 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 291876 : c_readstr (const char *str, fixed_size_mode mode,
748 : bool null_terminated_p/*=true*/)
749 : {
750 291876 : auto_vec<target_unit, MAX_BITSIZE_MODE_ANY_INT / BITS_PER_UNIT> bytes;
751 :
752 583752 : bytes.reserve (GET_MODE_SIZE (mode));
753 :
754 291876 : target_unit ch = 1;
755 4753310 : for (unsigned int i = 0; i < GET_MODE_SIZE (mode); ++i)
756 : {
757 2084779 : if (ch || !null_terminated_p)
758 1996644 : ch = (unsigned char) str[i];
759 2084779 : bytes.quick_push (ch);
760 : }
761 :
762 291876 : return native_decode_rtx (mode, bytes, 0);
763 291876 : }
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 60832 : target_char_cast (tree cst, char *p)
771 : {
772 60832 : unsigned HOST_WIDE_INT val, hostval;
773 :
774 60832 : 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 60832 : val = TREE_INT_CST_LOW (cst);
780 :
781 60832 : if (CHAR_TYPE_SIZE < HOST_BITS_PER_WIDE_INT)
782 60832 : val &= (HOST_WIDE_INT_1U << CHAR_TYPE_SIZE) - 1;
783 :
784 60832 : hostval = val;
785 60832 : if (HOST_BITS_PER_CHAR < HOST_BITS_PER_WIDE_INT)
786 60832 : hostval &= (HOST_WIDE_INT_1U << HOST_BITS_PER_CHAR) - 1;
787 :
788 60832 : if (val != hostval)
789 : return 1;
790 :
791 60832 : *p = hostval;
792 60832 : 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 1134609 : builtin_save_expr (tree exp)
801 : {
802 1134609 : if (TREE_CODE (exp) == SSA_NAME
803 970506 : || (TREE_ADDRESSABLE (exp) == 0
804 970314 : && (TREE_CODE (exp) == PARM_DECL
805 434259 : || (VAR_P (exp) && !TREE_STATIC (exp)))))
806 : return exp;
807 :
808 432450 : return save_expr (exp);
809 : }
810 :
811 : /* Given TEM, a pointer to a stack frame, follow the dynamic chain COUNT
812 : times to get the address of either a higher stack frame, or a return
813 : address located within it (depending on FNDECL_CODE). */
814 :
815 : static rtx
816 15936 : expand_builtin_return_addr (enum built_in_function fndecl_code, int count)
817 : {
818 15936 : int i;
819 15936 : rtx tem = INITIAL_FRAME_ADDRESS_RTX;
820 15936 : if (tem == NULL_RTX)
821 : {
822 : /* For a zero count with __builtin_return_address, we don't care what
823 : frame address we return, because target-specific definitions will
824 : override us. Therefore frame pointer elimination is OK, and using
825 : the soft frame pointer is OK.
826 :
827 : For a nonzero count, or a zero count with __builtin_frame_address,
828 : we require a stable offset from the current frame pointer to the
829 : previous one, so we must use the hard frame pointer, and
830 : we must disable frame pointer elimination. */
831 15936 : if (count == 0 && fndecl_code == BUILT_IN_RETURN_ADDRESS)
832 4333 : tem = frame_pointer_rtx;
833 : else
834 : {
835 11603 : tem = hard_frame_pointer_rtx;
836 :
837 : /* Tell reload not to eliminate the frame pointer. */
838 11603 : crtl->accesses_prior_frames = 1;
839 : }
840 : }
841 :
842 15936 : if (count > 0)
843 938 : SETUP_FRAME_ADDRESSES ();
844 :
845 : /* On the SPARC, the return address is not in the frame, it is in a
846 : register. There is no way to access it off of the current frame
847 : pointer, but it can be accessed off the previous frame pointer by
848 : reading the value from the register window save area. */
849 15936 : if (RETURN_ADDR_IN_PREVIOUS_FRAME && fndecl_code == BUILT_IN_RETURN_ADDRESS)
850 : count--;
851 :
852 : /* Scan back COUNT frames to the specified frame. */
853 51818 : for (i = 0; i < count; i++)
854 : {
855 : /* Assume the dynamic chain pointer is in the word that the
856 : frame address points to, unless otherwise specified. */
857 35882 : tem = DYNAMIC_CHAIN_ADDRESS (tem);
858 35882 : tem = memory_address (Pmode, tem);
859 35882 : tem = gen_frame_mem (Pmode, tem);
860 35882 : tem = copy_to_reg (tem);
861 : }
862 :
863 : /* For __builtin_frame_address, return what we've got. But, on
864 : the SPARC for example, we may have to add a bias. */
865 15936 : if (fndecl_code == BUILT_IN_FRAME_ADDRESS)
866 : return FRAME_ADDR_RTX (count, tem);
867 :
868 : /* For __builtin_return_address, get the return address from that frame. */
869 : #ifdef RETURN_ADDR_RTX
870 7402 : tem = RETURN_ADDR_RTX (count, tem);
871 : #else
872 : tem = memory_address (Pmode,
873 : plus_constant (Pmode, tem, GET_MODE_SIZE (Pmode)));
874 : tem = gen_frame_mem (Pmode, tem);
875 : #endif
876 5173 : return tem;
877 : }
878 :
879 : /* Alias set used for setjmp buffer. */
880 : static alias_set_type setjmp_alias_set = -1;
881 :
882 : /* Construct the leading half of a __builtin_setjmp call. Control will
883 : return to RECEIVER_LABEL. This is also called directly by the SJLJ
884 : exception handling code. */
885 :
886 : void
887 842 : expand_builtin_setjmp_setup (rtx buf_addr, rtx receiver_label)
888 : {
889 842 : machine_mode sa_mode = STACK_SAVEAREA_MODE (SAVE_NONLOCAL);
890 842 : rtx stack_save;
891 842 : rtx mem;
892 :
893 842 : if (setjmp_alias_set == -1)
894 241 : setjmp_alias_set = new_alias_set ();
895 :
896 843 : buf_addr = convert_memory_address (Pmode, buf_addr);
897 :
898 843 : buf_addr = force_reg (Pmode, force_operand (buf_addr, NULL_RTX));
899 :
900 : /* We store the frame pointer and the address of receiver_label in
901 : the buffer and use the rest of it for the stack save area, which
902 : is machine-dependent. */
903 :
904 843 : mem = gen_rtx_MEM (Pmode, buf_addr);
905 842 : set_mem_alias_set (mem, setjmp_alias_set);
906 842 : emit_move_insn (mem, hard_frame_pointer_rtx);
907 :
908 843 : mem = gen_rtx_MEM (Pmode, plus_constant (Pmode, buf_addr,
909 1684 : GET_MODE_SIZE (Pmode))),
910 842 : set_mem_alias_set (mem, setjmp_alias_set);
911 :
912 1684 : emit_move_insn (validize_mem (mem),
913 1684 : force_reg (Pmode, gen_rtx_LABEL_REF (Pmode, receiver_label)));
914 :
915 842 : stack_save = gen_rtx_MEM (sa_mode,
916 : plus_constant (Pmode, buf_addr,
917 1684 : 2 * GET_MODE_SIZE (Pmode)));
918 842 : set_mem_alias_set (stack_save, setjmp_alias_set);
919 842 : emit_stack_save (SAVE_NONLOCAL, &stack_save);
920 :
921 : /* If there is further processing to do, do it. */
922 842 : if (targetm.have_builtin_setjmp_setup ())
923 0 : emit_insn (targetm.gen_builtin_setjmp_setup (buf_addr));
924 :
925 : /* We have a nonlocal label. */
926 842 : cfun->has_nonlocal_label = 1;
927 842 : }
928 :
929 : /* Construct the trailing part of a __builtin_setjmp call. This is
930 : also called directly by the SJLJ exception handling code.
931 : If RECEIVER_LABEL is NULL, instead construct a nonlocal goto handler. */
932 :
933 : void
934 1346 : expand_builtin_setjmp_receiver (rtx receiver_label)
935 : {
936 1346 : rtx chain;
937 :
938 : /* Mark the FP as used when we get here, so we have to make sure it's
939 : marked as used by this function. */
940 1346 : emit_use (hard_frame_pointer_rtx);
941 :
942 : /* Mark the static chain as clobbered here so life information
943 : doesn't get messed up for it. */
944 1346 : chain = rtx_for_static_chain (current_function_decl, true);
945 1346 : if (chain && REG_P (chain))
946 1 : emit_clobber (chain);
947 :
948 1346 : if (!HARD_FRAME_POINTER_IS_ARG_POINTER && fixed_regs[ARG_POINTER_REGNUM])
949 : {
950 : /* If the argument pointer can be eliminated in favor of the
951 : frame pointer, we don't need to restore it. We assume here
952 : that if such an elimination is present, it can always be used.
953 : This is the case on all known machines; if we don't make this
954 : assumption, we do unnecessary saving on many machines. */
955 : size_t i;
956 : static const struct elims {const int from, to;} elim_regs[] = ELIMINABLE_REGS;
957 :
958 2692 : for (i = 0; i < ARRAY_SIZE (elim_regs); i++)
959 2692 : if (elim_regs[i].from == ARG_POINTER_REGNUM
960 2692 : && elim_regs[i].to == HARD_FRAME_POINTER_REGNUM)
961 : break;
962 :
963 1346 : if (i == ARRAY_SIZE (elim_regs))
964 : {
965 : /* Now restore our arg pointer from the address at which it
966 : was saved in our stack frame. */
967 0 : emit_move_insn (crtl->args.internal_arg_pointer,
968 : copy_to_reg (get_arg_pointer_save_area ()));
969 : }
970 : }
971 :
972 1346 : if (receiver_label != NULL && targetm.have_builtin_setjmp_receiver ())
973 0 : emit_insn (targetm.gen_builtin_setjmp_receiver (receiver_label));
974 1346 : else if (targetm.have_nonlocal_goto_receiver ())
975 0 : emit_insn (targetm.gen_nonlocal_goto_receiver ());
976 : else
977 : { /* Nothing */ }
978 :
979 : /* We must not allow the code we just generated to be reordered by
980 : scheduling. Specifically, the update of the frame pointer must
981 : happen immediately, not later. */
982 1346 : emit_insn (gen_blockage ());
983 1346 : }
984 :
985 : /* __builtin_longjmp is passed a pointer to an array of five words (not
986 : all will be used on all machines). It operates similarly to the C
987 : library function of the same name, but is more efficient. Much of
988 : the code below is copied from the handling of non-local gotos. */
989 :
990 : static void
991 392 : expand_builtin_longjmp (rtx buf_addr, rtx value)
992 : {
993 392 : rtx fp, lab, stack;
994 392 : rtx_insn *insn, *last;
995 392 : machine_mode sa_mode = STACK_SAVEAREA_MODE (SAVE_NONLOCAL);
996 :
997 : /* DRAP is needed for stack realign if longjmp is expanded to current
998 : function */
999 392 : if (SUPPORTS_STACK_ALIGNMENT)
1000 392 : crtl->need_drap = true;
1001 :
1002 392 : if (setjmp_alias_set == -1)
1003 331 : setjmp_alias_set = new_alias_set ();
1004 :
1005 393 : buf_addr = convert_memory_address (Pmode, buf_addr);
1006 :
1007 393 : buf_addr = force_reg (Pmode, buf_addr);
1008 :
1009 : /* We require that the user must pass a second argument of 1, because
1010 : that is what builtin_setjmp will return. */
1011 392 : gcc_assert (value == const1_rtx);
1012 :
1013 392 : last = get_last_insn ();
1014 392 : if (targetm.have_builtin_longjmp ())
1015 0 : emit_insn (targetm.gen_builtin_longjmp (buf_addr));
1016 : else
1017 : {
1018 393 : fp = gen_rtx_MEM (Pmode, buf_addr);
1019 393 : lab = gen_rtx_MEM (Pmode, plus_constant (Pmode, buf_addr,
1020 784 : GET_MODE_SIZE (Pmode)));
1021 :
1022 392 : stack = gen_rtx_MEM (sa_mode, plus_constant (Pmode, buf_addr,
1023 784 : 2 * GET_MODE_SIZE (Pmode)));
1024 392 : set_mem_alias_set (fp, setjmp_alias_set);
1025 392 : set_mem_alias_set (lab, setjmp_alias_set);
1026 392 : set_mem_alias_set (stack, setjmp_alias_set);
1027 :
1028 : /* Pick up FP, label, and SP from the block and jump. This code is
1029 : from expand_goto in stmt.cc; see there for detailed comments. */
1030 392 : if (targetm.have_nonlocal_goto ())
1031 : /* We have to pass a value to the nonlocal_goto pattern that will
1032 : get copied into the static_chain pointer, but it does not matter
1033 : what that value is, because builtin_setjmp does not use it. */
1034 0 : emit_insn (targetm.gen_nonlocal_goto (value, lab, stack, fp));
1035 : else
1036 : {
1037 392 : emit_clobber (gen_rtx_MEM (BLKmode, gen_rtx_SCRATCH (VOIDmode)));
1038 392 : emit_clobber (gen_rtx_MEM (BLKmode, hard_frame_pointer_rtx));
1039 :
1040 392 : lab = copy_to_reg (lab);
1041 :
1042 : /* Restore the frame pointer and stack pointer. We must use a
1043 : temporary since the setjmp buffer may be a local. */
1044 392 : fp = copy_to_reg (fp);
1045 392 : emit_stack_restore (SAVE_NONLOCAL, stack);
1046 :
1047 : /* Ensure the frame pointer move is not optimized. */
1048 392 : emit_insn (gen_blockage ());
1049 392 : emit_clobber (hard_frame_pointer_rtx);
1050 392 : emit_clobber (frame_pointer_rtx);
1051 392 : emit_move_insn (hard_frame_pointer_rtx, fp);
1052 :
1053 392 : emit_use (hard_frame_pointer_rtx);
1054 392 : emit_use (stack_pointer_rtx);
1055 392 : emit_indirect_jump (lab);
1056 : }
1057 : }
1058 :
1059 : /* Search backwards and mark the jump insn as a non-local goto.
1060 : Note that this precludes the use of __builtin_longjmp to a
1061 : __builtin_setjmp target in the same function. However, we've
1062 : already cautioned the user that these functions are for
1063 : internal exception handling use only. */
1064 784 : for (insn = get_last_insn (); insn; insn = PREV_INSN (insn))
1065 : {
1066 784 : gcc_assert (insn != last);
1067 :
1068 784 : if (JUMP_P (insn))
1069 : {
1070 392 : add_reg_note (insn, REG_NON_LOCAL_GOTO, const0_rtx);
1071 392 : break;
1072 : }
1073 392 : else if (CALL_P (insn))
1074 : break;
1075 : }
1076 392 : }
1077 :
1078 : static inline bool
1079 1949651 : more_const_call_expr_args_p (const const_call_expr_arg_iterator *iter)
1080 : {
1081 1949651 : 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 507441 : validate_arglist (const_tree callexpr, ...)
1091 : {
1092 507441 : enum tree_code code;
1093 507441 : bool res = 0;
1094 507441 : va_list ap;
1095 507441 : const_call_expr_arg_iterator iter;
1096 507441 : const_tree arg;
1097 :
1098 507441 : va_start (ap, callexpr);
1099 507441 : init_const_call_expr_arg_iterator (callexpr, &iter);
1100 :
1101 : /* Get a bitmap of pointer argument numbers declared attribute nonnull. */
1102 507441 : tree fn = CALL_EXPR_FN (callexpr);
1103 507441 : bitmap argmap = get_nonnull_args (TREE_TYPE (TREE_TYPE (fn)));
1104 :
1105 1770690 : for (unsigned argno = 1; ; ++argno)
1106 : {
1107 1770690 : code = (enum tree_code) va_arg (ap, int);
1108 :
1109 1770690 : switch (code)
1110 : {
1111 2058 : case 0:
1112 : /* This signifies an ellipses, any further arguments are all ok. */
1113 2058 : res = true;
1114 2058 : goto end;
1115 505151 : case VOID_TYPE:
1116 : /* This signifies an endlink, if no arguments remain, return
1117 : true, otherwise return false. */
1118 505151 : res = !more_const_call_expr_args_p (&iter);
1119 505151 : goto end;
1120 832014 : 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 832014 : if (argmap
1125 832014 : && (bitmap_empty_p (argmap) || bitmap_bit_p (argmap, argno)))
1126 : {
1127 281820 : arg = next_const_call_expr_arg (&iter);
1128 281820 : if (!validate_arg (arg, code) || integer_zerop (arg))
1129 58 : goto end;
1130 : break;
1131 : }
1132 : /* FALLTHRU */
1133 981661 : 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 981661 : arg = next_const_call_expr_arg (&iter);
1138 981661 : 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 507441 : end: ;
1147 507441 : va_end (ap);
1148 :
1149 507441 : BITMAP_FREE (argmap);
1150 :
1151 507441 : if (res)
1152 507209 : for (tree attrs = TYPE_ATTRIBUTES (TREE_TYPE (TREE_TYPE (fn)));
1153 737489 : (attrs = lookup_attribute ("nonnull_if_nonzero", attrs));
1154 230280 : attrs = TREE_CHAIN (attrs))
1155 : {
1156 230302 : tree args = TREE_VALUE (attrs);
1157 230302 : unsigned int idx = TREE_INT_CST_LOW (TREE_VALUE (args)) - 1;
1158 230302 : unsigned int idx2
1159 230302 : = TREE_INT_CST_LOW (TREE_VALUE (TREE_CHAIN (args))) - 1;
1160 230302 : unsigned int idx3 = idx2;
1161 230302 : if (tree chain2 = TREE_CHAIN (TREE_CHAIN (args)))
1162 0 : idx3 = TREE_INT_CST_LOW (TREE_VALUE (chain2)) - 1;
1163 230302 : if (idx < (unsigned) call_expr_nargs (callexpr)
1164 230302 : && idx2 < (unsigned) call_expr_nargs (callexpr)
1165 230302 : && idx3 < (unsigned) call_expr_nargs (callexpr)
1166 230302 : && POINTER_TYPE_P (TREE_TYPE (CALL_EXPR_ARG (callexpr, idx)))
1167 230302 : && integer_zerop (CALL_EXPR_ARG (callexpr, idx))
1168 89 : && INTEGRAL_TYPE_P (TREE_TYPE (CALL_EXPR_ARG (callexpr, idx2)))
1169 89 : && integer_nonzerop (CALL_EXPR_ARG (callexpr, idx2))
1170 22 : && INTEGRAL_TYPE_P (TREE_TYPE (CALL_EXPR_ARG (callexpr, idx3)))
1171 230324 : && integer_nonzerop (CALL_EXPR_ARG (callexpr, idx3)))
1172 : return false;
1173 : }
1174 :
1175 : return res;
1176 : }
1177 :
1178 : /* Expand a call to __builtin_nonlocal_goto. We're passed the target label
1179 : and the address of the save area. */
1180 :
1181 : static rtx
1182 512 : expand_builtin_nonlocal_goto (tree exp)
1183 : {
1184 512 : tree t_label, t_save_area;
1185 512 : rtx r_label, r_save_area, r_fp, r_sp;
1186 512 : rtx_insn *insn;
1187 :
1188 512 : if (!validate_arglist (exp, POINTER_TYPE, POINTER_TYPE, VOID_TYPE))
1189 : return NULL_RTX;
1190 :
1191 512 : t_label = CALL_EXPR_ARG (exp, 0);
1192 512 : t_save_area = CALL_EXPR_ARG (exp, 1);
1193 :
1194 512 : r_label = expand_normal (t_label);
1195 512 : r_label = convert_memory_address (Pmode, r_label);
1196 512 : r_save_area = expand_normal (t_save_area);
1197 512 : r_save_area = convert_memory_address (Pmode, r_save_area);
1198 : /* Copy the address of the save location to a register just in case it was
1199 : based on the frame pointer. */
1200 512 : r_save_area = copy_to_reg (r_save_area);
1201 512 : r_fp = gen_rtx_MEM (Pmode, r_save_area);
1202 512 : r_sp = gen_rtx_MEM (STACK_SAVEAREA_MODE (SAVE_NONLOCAL),
1203 : plus_constant (Pmode, r_save_area,
1204 1024 : GET_MODE_SIZE (Pmode)));
1205 :
1206 512 : crtl->has_nonlocal_goto = 1;
1207 :
1208 : /* ??? We no longer need to pass the static chain value, afaik. */
1209 512 : if (targetm.have_nonlocal_goto ())
1210 0 : emit_insn (targetm.gen_nonlocal_goto (const0_rtx, r_label, r_sp, r_fp));
1211 : else
1212 : {
1213 512 : emit_clobber (gen_rtx_MEM (BLKmode, gen_rtx_SCRATCH (VOIDmode)));
1214 512 : emit_clobber (gen_rtx_MEM (BLKmode, hard_frame_pointer_rtx));
1215 :
1216 512 : r_label = copy_to_reg (r_label);
1217 :
1218 : /* Restore the frame pointer and stack pointer. We must use a
1219 : temporary since the setjmp buffer may be a local. */
1220 512 : r_fp = copy_to_reg (r_fp);
1221 512 : emit_stack_restore (SAVE_NONLOCAL, r_sp);
1222 :
1223 : /* Ensure the frame pointer move is not optimized. */
1224 512 : emit_insn (gen_blockage ());
1225 512 : emit_clobber (hard_frame_pointer_rtx);
1226 512 : emit_clobber (frame_pointer_rtx);
1227 512 : emit_move_insn (hard_frame_pointer_rtx, r_fp);
1228 :
1229 : /* USE of hard_frame_pointer_rtx added for consistency;
1230 : not clear if really needed. */
1231 512 : emit_use (hard_frame_pointer_rtx);
1232 512 : emit_use (stack_pointer_rtx);
1233 :
1234 : /* If the architecture is using a GP register, we must
1235 : conservatively assume that the target function makes use of it.
1236 : The prologue of functions with nonlocal gotos must therefore
1237 : initialize the GP register to the appropriate value, and we
1238 : must then make sure that this value is live at the point
1239 : of the jump. (Note that this doesn't necessarily apply
1240 : to targets with a nonlocal_goto pattern; they are free
1241 : to implement it in their own way. Note also that this is
1242 : a no-op if the GP register is a global invariant.) */
1243 512 : unsigned regnum = PIC_OFFSET_TABLE_REGNUM;
1244 0 : if (regnum != INVALID_REGNUM && fixed_regs[regnum])
1245 0 : emit_use (pic_offset_table_rtx);
1246 :
1247 512 : emit_indirect_jump (r_label);
1248 : }
1249 :
1250 : /* Search backwards to the jump insn and mark it as a
1251 : non-local goto. */
1252 1024 : for (insn = get_last_insn (); insn; insn = PREV_INSN (insn))
1253 : {
1254 1024 : if (JUMP_P (insn))
1255 : {
1256 512 : add_reg_note (insn, REG_NON_LOCAL_GOTO, const0_rtx);
1257 512 : break;
1258 : }
1259 512 : else if (CALL_P (insn))
1260 : break;
1261 : }
1262 :
1263 512 : return const0_rtx;
1264 : }
1265 :
1266 : /* __builtin_update_setjmp_buf is passed a pointer to an array of five words
1267 : (not all will be used on all machines) that was passed to __builtin_setjmp.
1268 : It updates the stack pointer in that block to the current value. This is
1269 : also called directly by the SJLJ exception handling code. */
1270 :
1271 : void
1272 0 : expand_builtin_update_setjmp_buf (rtx buf_addr)
1273 : {
1274 0 : machine_mode sa_mode = STACK_SAVEAREA_MODE (SAVE_NONLOCAL);
1275 0 : buf_addr = convert_memory_address (Pmode, buf_addr);
1276 0 : rtx stack_save
1277 0 : = gen_rtx_MEM (sa_mode,
1278 0 : memory_address
1279 : (sa_mode,
1280 : plus_constant (Pmode, buf_addr,
1281 0 : 2 * GET_MODE_SIZE (Pmode))));
1282 :
1283 0 : emit_stack_save (SAVE_NONLOCAL, &stack_save);
1284 0 : }
1285 :
1286 : /* Expand a call to __builtin_prefetch. For a target that does not support
1287 : data prefetch, evaluate the memory address argument in case it has side
1288 : effects. */
1289 :
1290 : static void
1291 2058 : expand_builtin_prefetch (tree exp)
1292 : {
1293 2058 : tree arg0, arg1, arg2;
1294 2058 : int nargs;
1295 2058 : rtx op0, op1, op2;
1296 :
1297 2058 : if (!validate_arglist (exp, POINTER_TYPE, 0))
1298 : return;
1299 :
1300 2058 : arg0 = CALL_EXPR_ARG (exp, 0);
1301 :
1302 : /* Arguments 1 and 2 are optional; argument 1 (read/write) defaults to
1303 : zero (read) and argument 2 (locality) defaults to 3 (high degree of
1304 : locality). */
1305 2058 : nargs = call_expr_nargs (exp);
1306 2058 : arg1 = nargs > 1 ? CALL_EXPR_ARG (exp, 1) : NULL_TREE;
1307 2018 : arg2 = nargs > 2 ? CALL_EXPR_ARG (exp, 2) : NULL_TREE;
1308 :
1309 : /* Argument 0 is an address. */
1310 2154 : op0 = expand_expr (arg0, NULL_RTX, Pmode, EXPAND_NORMAL);
1311 :
1312 : /* Argument 1 (read/write flag) must be a compile-time constant int. */
1313 2058 : if (arg1 == NULL_TREE)
1314 40 : op1 = const0_rtx;
1315 2018 : else if (TREE_CODE (arg1) != INTEGER_CST)
1316 : {
1317 0 : error ("second argument to %<__builtin_prefetch%> must be a constant");
1318 0 : op1 = const0_rtx;
1319 : }
1320 : else
1321 2018 : op1 = expand_normal (arg1);
1322 : /* Argument 1 must be 0, 1 or 2. */
1323 2058 : if (!IN_RANGE (INTVAL (op1), 0, 2))
1324 : {
1325 3 : warning (0, "invalid second argument to %<__builtin_prefetch%>;"
1326 : " using zero");
1327 3 : op1 = const0_rtx;
1328 : }
1329 :
1330 : /* Argument 2 (locality) must be a compile-time constant int. */
1331 2058 : if (arg2 == NULL_TREE)
1332 77 : op2 = GEN_INT (3);
1333 1981 : else if (TREE_CODE (arg2) != INTEGER_CST)
1334 : {
1335 0 : error ("third argument to %<__builtin_prefetch%> must be a constant");
1336 0 : op2 = const0_rtx;
1337 : }
1338 : else
1339 1981 : op2 = expand_normal (arg2);
1340 : /* Argument 2 must be 0, 1, 2, or 3. */
1341 2058 : if (!IN_RANGE (INTVAL (op2), 0, 3))
1342 : {
1343 3 : warning (0, "invalid third argument to %<__builtin_prefetch%>; using zero");
1344 3 : op2 = const0_rtx;
1345 : }
1346 :
1347 2058 : if (targetm.have_prefetch ())
1348 : {
1349 2058 : class expand_operand ops[3];
1350 :
1351 2058 : create_address_operand (&ops[0], op0);
1352 2058 : create_integer_operand (&ops[1], INTVAL (op1));
1353 2058 : create_integer_operand (&ops[2], INTVAL (op2));
1354 2058 : if (maybe_expand_insn (targetm.code_for_prefetch, 3, ops))
1355 2058 : return;
1356 : }
1357 :
1358 : /* Don't do anything with direct references to volatile memory, but
1359 : generate code to handle other side effects. */
1360 0 : if (!MEM_P (op0) && side_effects_p (op0))
1361 0 : emit_insn (op0);
1362 : }
1363 :
1364 : /* Get a MEM rtx for expression EXP which is the address of an operand
1365 : to be used in a string instruction (cmpstrsi, cpymemsi, ..). LEN is
1366 : the maximum length of the block of memory that might be accessed or
1367 : NULL if unknown. STORE_P is true when EXP is the destination. */
1368 :
1369 : rtx
1370 761729 : get_memory_rtx (tree exp, tree len, bool store_p)
1371 : {
1372 761729 : tree orig_exp = exp, base;
1373 761729 : rtx addr, mem;
1374 :
1375 761729 : 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 761729 : if (TREE_CODE (exp) == SAVE_EXPR && !SAVE_EXPR_RESOLVED_P (exp))
1381 1611 : exp = TREE_OPERAND (exp, 0);
1382 :
1383 761729 : addr = expand_expr (orig_exp, NULL_RTX, ptr_mode, EXPAND_NORMAL);
1384 761729 : 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 1523458 : while (CONVERT_EXPR_P (exp)
1389 761732 : && 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 761729 : 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 761729 : if (is_gimple_mem_ref_addr (TREE_OPERAND (exp, 0)))
1404 761717 : set_mem_attributes (mem, exp, 0, store_p);
1405 12 : else if (TREE_CODE (TREE_OPERAND (exp, 0)) == ADDR_EXPR
1406 12 : && (base = get_base_address (TREE_OPERAND (TREE_OPERAND (exp, 0),
1407 : 0))))
1408 : {
1409 12 : unsigned int align = get_pointer_alignment (TREE_OPERAND (exp, 0));
1410 12 : exp = build_fold_addr_expr (base);
1411 12 : exp = fold_build2 (MEM_REF,
1412 : build_array_type (char_type_node,
1413 : build_range_type (sizetype,
1414 : size_zero_node,
1415 : NULL)),
1416 : exp, build_int_cst (ptr_type_node, 0));
1417 12 : set_mem_attributes (mem, exp, 0, store_p);
1418 : /* Since we stripped parts make sure the offset is unknown and the
1419 : alignment is computed from the original address. */
1420 12 : clear_mem_offset (mem);
1421 12 : set_mem_align (mem, align);
1422 : }
1423 761729 : set_mem_alias_set (mem, 0);
1424 761729 : return mem;
1425 : }
1426 :
1427 : /* Built-in functions to perform an untyped call and return. */
1428 :
1429 : /* Wrapper that implicitly applies a delta when getting or setting the
1430 : enclosed value. */
1431 : template <typename T>
1432 : class delta_type
1433 : {
1434 : T &value; T const delta;
1435 : public:
1436 2524 : delta_type (T &val, T dlt) : value (val), delta (dlt) {}
1437 1809 : operator T () const { return value + delta; }
1438 715 : T operator = (T val) const { value = val - delta; return val; }
1439 : };
1440 :
1441 : #define saved_apply_args_size \
1442 : (delta_type<int> (this_target_builtins->x_apply_args_size_plus_one, -1))
1443 : #define apply_args_mode \
1444 : (this_target_builtins->x_apply_args_mode)
1445 : #define saved_apply_result_size \
1446 : (delta_type<int> (this_target_builtins->x_apply_result_size_plus_one, -1))
1447 : #define apply_result_mode \
1448 : (this_target_builtins->x_apply_result_mode)
1449 :
1450 : /* Return the size required for the block returned by __builtin_apply_args,
1451 : and initialize apply_args_mode. */
1452 :
1453 : static int
1454 947 : apply_args_size (void)
1455 : {
1456 947 : int size = saved_apply_args_size;
1457 947 : int align;
1458 947 : unsigned int regno;
1459 :
1460 : /* The values computed by this function never change. */
1461 947 : if (size < 0)
1462 : {
1463 : /* The first value is the incoming arg-pointer. */
1464 360 : size = GET_MODE_SIZE (Pmode);
1465 :
1466 : /* The second value is the structure value address unless this is
1467 : passed as an "invisible" first argument. */
1468 360 : if (targetm.calls.struct_value_rtx (cfun ? TREE_TYPE (cfun->decl) : 0, 0))
1469 0 : size += GET_MODE_SIZE (Pmode);
1470 :
1471 34200 : for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
1472 33840 : if (FUNCTION_ARG_REGNO_P (regno))
1473 : {
1474 5400 : fixed_size_mode mode = targetm.calls.get_raw_arg_mode (regno);
1475 :
1476 5400 : if (mode != VOIDmode)
1477 : {
1478 5400 : align = GET_MODE_ALIGNMENT (mode) / BITS_PER_UNIT;
1479 5400 : if (size % align != 0)
1480 1 : size = CEIL (size, align) * align;
1481 5400 : size += GET_MODE_SIZE (mode);
1482 5400 : apply_args_mode[regno] = mode;
1483 : }
1484 : else
1485 0 : apply_args_mode[regno] = as_a <fixed_size_mode> (VOIDmode);
1486 : }
1487 : else
1488 28440 : apply_args_mode[regno] = as_a <fixed_size_mode> (VOIDmode);
1489 :
1490 360 : saved_apply_args_size = size;
1491 : }
1492 947 : return size;
1493 : }
1494 :
1495 : /* Return the size required for the block returned by __builtin_apply,
1496 : and initialize apply_result_mode. */
1497 :
1498 : static int
1499 862 : apply_result_size (void)
1500 : {
1501 862 : int size = saved_apply_result_size;
1502 862 : int align, regno;
1503 :
1504 : /* The values computed by this function never change. */
1505 862 : if (size < 0)
1506 : {
1507 : size = 0;
1508 :
1509 33725 : for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
1510 33370 : if (targetm.calls.function_value_regno_p (regno))
1511 : {
1512 2130 : fixed_size_mode mode = targetm.calls.get_raw_result_mode (regno);
1513 :
1514 2130 : if (mode != VOIDmode)
1515 : {
1516 2130 : align = GET_MODE_ALIGNMENT (mode) / BITS_PER_UNIT;
1517 2130 : if (size % align != 0)
1518 : size = CEIL (size, align) * align;
1519 2130 : size += GET_MODE_SIZE (mode);
1520 2130 : apply_result_mode[regno] = mode;
1521 : }
1522 : else
1523 0 : apply_result_mode[regno] = as_a <fixed_size_mode> (VOIDmode);
1524 : }
1525 : else
1526 31240 : apply_result_mode[regno] = as_a <fixed_size_mode> (VOIDmode);
1527 :
1528 : /* Allow targets that use untyped_call and untyped_return to override
1529 : the size so that machine-specific information can be stored here. */
1530 : #ifdef APPLY_RESULT_SIZE
1531 355 : size = APPLY_RESULT_SIZE;
1532 : #endif
1533 :
1534 355 : saved_apply_result_size = size;
1535 : }
1536 862 : return size;
1537 : }
1538 :
1539 : /* Create a vector describing the result block RESULT. If SAVEP is true,
1540 : the result block is used to save the values; otherwise it is used to
1541 : restore the values. */
1542 :
1543 : static rtx
1544 483 : result_vector (int savep, rtx result)
1545 : {
1546 483 : int regno, size, align, nelts;
1547 483 : fixed_size_mode mode;
1548 483 : rtx reg, mem;
1549 483 : rtx *savevec = XALLOCAVEC (rtx, FIRST_PSEUDO_REGISTER);
1550 :
1551 483 : size = nelts = 0;
1552 45885 : for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
1553 45402 : if ((mode = apply_result_mode[regno]) != VOIDmode)
1554 : {
1555 2898 : align = GET_MODE_ALIGNMENT (mode) / BITS_PER_UNIT;
1556 2898 : if (size % align != 0)
1557 0 : size = CEIL (size, align) * align;
1558 2898 : reg = gen_rtx_REG (mode, savep ? regno : INCOMING_REGNO (regno));
1559 2898 : mem = adjust_address (result, mode, size);
1560 5796 : savevec[nelts++] = (savep
1561 5796 : ? gen_rtx_SET (mem, reg)
1562 0 : : gen_rtx_SET (reg, mem));
1563 5796 : size += GET_MODE_SIZE (mode);
1564 : }
1565 483 : return gen_rtx_PARALLEL (VOIDmode, gen_rtvec_v (nelts, savevec));
1566 : }
1567 :
1568 : /* Save the state required to perform an untyped call with the same
1569 : arguments as were passed to the current function. */
1570 :
1571 : static rtx
1572 464 : expand_builtin_apply_args_1 (void)
1573 : {
1574 464 : rtx registers, tem;
1575 464 : int size, align, regno;
1576 464 : fixed_size_mode mode;
1577 464 : rtx struct_incoming_value = targetm.calls.struct_value_rtx (cfun ? TREE_TYPE (cfun->decl) : 0, 1);
1578 :
1579 : /* Create a block where the arg-pointer, structure value address,
1580 : and argument registers can be saved. */
1581 464 : registers = assign_stack_local (BLKmode, apply_args_size (), -1);
1582 :
1583 : /* Walk past the arg-pointer and structure value address. */
1584 464 : size = GET_MODE_SIZE (Pmode);
1585 464 : if (targetm.calls.struct_value_rtx (cfun ? TREE_TYPE (cfun->decl) : 0, 0))
1586 0 : size += GET_MODE_SIZE (Pmode);
1587 :
1588 : /* Save each register used in calling a function to the block. */
1589 44080 : for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
1590 43616 : if ((mode = apply_args_mode[regno]) != VOIDmode)
1591 : {
1592 6960 : align = GET_MODE_ALIGNMENT (mode) / BITS_PER_UNIT;
1593 6960 : if (size % align != 0)
1594 1 : size = CEIL (size, align) * align;
1595 :
1596 6960 : tem = gen_rtx_REG (mode, INCOMING_REGNO (regno));
1597 :
1598 6960 : emit_move_insn (adjust_address (registers, mode, size), tem);
1599 13920 : size += GET_MODE_SIZE (mode);
1600 : }
1601 :
1602 : /* Save the arg pointer to the block. */
1603 464 : tem = copy_to_reg (crtl->args.internal_arg_pointer);
1604 : /* We need the pointer as the caller actually passed them to us, not
1605 : as we might have pretended they were passed. Make sure it's a valid
1606 : operand, as emit_move_insn isn't expected to handle a PLUS. */
1607 464 : if (STACK_GROWS_DOWNWARD)
1608 464 : tem
1609 464 : = force_operand (plus_constant (Pmode, tem,
1610 464 : crtl->args.pretend_args_size),
1611 : NULL_RTX);
1612 464 : emit_move_insn (adjust_address (registers, Pmode, 0), tem);
1613 :
1614 464 : size = GET_MODE_SIZE (Pmode);
1615 :
1616 : /* Save the structure value address unless this is passed as an
1617 : "invisible" first argument. */
1618 464 : if (struct_incoming_value)
1619 0 : emit_move_insn (adjust_address (registers, Pmode, size),
1620 : copy_to_reg (struct_incoming_value));
1621 :
1622 : /* Return the address of the block. */
1623 464 : return copy_addr_to_reg (XEXP (registers, 0));
1624 : }
1625 :
1626 : /* __builtin_apply_args returns block of memory allocated on
1627 : the stack into which is stored the arg pointer, structure
1628 : value address, static chain, and all the registers that might
1629 : possibly be used in performing a function call. The code is
1630 : moved to the start of the function so the incoming values are
1631 : saved. */
1632 :
1633 : static rtx
1634 464 : expand_builtin_apply_args (void)
1635 : {
1636 : /* Don't do __builtin_apply_args more than once in a function.
1637 : Save the result of the first call and reuse it. */
1638 464 : if (apply_args_value != 0)
1639 : return apply_args_value;
1640 464 : {
1641 : /* When this function is called, it means that registers must be
1642 : saved on entry to this function. So we migrate the
1643 : call to the first insn of this function. */
1644 464 : rtx temp;
1645 :
1646 464 : start_sequence ();
1647 464 : temp = expand_builtin_apply_args_1 ();
1648 464 : rtx_insn *seq = end_sequence ();
1649 :
1650 464 : apply_args_value = temp;
1651 :
1652 : /* Put the insns after the NOTE that starts the function.
1653 : If this is inside a start_sequence, make the outer-level insn
1654 : chain current, so the code is placed at the start of the
1655 : function. If internal_arg_pointer is a non-virtual pseudo,
1656 : it needs to be placed after the function that initializes
1657 : that pseudo. */
1658 464 : push_topmost_sequence ();
1659 464 : if (REG_P (crtl->args.internal_arg_pointer)
1660 464 : && REGNO (crtl->args.internal_arg_pointer) > LAST_VIRTUAL_REGISTER)
1661 0 : emit_insn_before (seq, parm_birth_insn);
1662 : else
1663 464 : emit_insn_before (seq, NEXT_INSN (entry_of_function ()));
1664 464 : pop_topmost_sequence ();
1665 464 : return temp;
1666 : }
1667 : }
1668 :
1669 : /* Perform an untyped call and save the state required to perform an
1670 : untyped return of whatever value was returned by the given function. */
1671 :
1672 : static rtx
1673 483 : expand_builtin_apply (rtx function, rtx arguments, rtx argsize)
1674 : {
1675 483 : int size, align, regno;
1676 483 : fixed_size_mode mode;
1677 483 : rtx incoming_args, result, reg, dest, src;
1678 483 : rtx_call_insn *call_insn;
1679 483 : rtx old_stack_level = 0;
1680 483 : rtx call_fusage = 0;
1681 483 : rtx struct_value = targetm.calls.struct_value_rtx (cfun ? TREE_TYPE (cfun->decl) : 0, 0);
1682 :
1683 483 : arguments = convert_memory_address (Pmode, arguments);
1684 :
1685 : /* Create a block where the return registers can be saved. */
1686 483 : result = assign_stack_local (BLKmode, apply_result_size (), -1);
1687 :
1688 : /* Fetch the arg pointer from the ARGUMENTS block. */
1689 483 : incoming_args = gen_reg_rtx (Pmode);
1690 483 : emit_move_insn (incoming_args, gen_rtx_MEM (Pmode, arguments));
1691 483 : if (!STACK_GROWS_DOWNWARD)
1692 : incoming_args = expand_simple_binop (Pmode, MINUS, incoming_args, argsize,
1693 : incoming_args, 0, OPTAB_LIB_WIDEN);
1694 :
1695 : /* Push a new argument block and copy the arguments. Do not allow
1696 : the (potential) memcpy call below to interfere with our stack
1697 : manipulations. */
1698 483 : do_pending_stack_adjust ();
1699 483 : NO_DEFER_POP;
1700 :
1701 : /* Save the stack with nonlocal if available. */
1702 483 : if (targetm.have_save_stack_nonlocal ())
1703 483 : emit_stack_save (SAVE_NONLOCAL, &old_stack_level);
1704 : else
1705 0 : emit_stack_save (SAVE_BLOCK, &old_stack_level);
1706 :
1707 : /* Allocate a block of memory onto the stack and copy the memory
1708 : arguments to the outgoing arguments address. We can pass TRUE
1709 : as the 4th argument because we just saved the stack pointer
1710 : and will restore it right after the call. */
1711 966 : allocate_dynamic_stack_space (argsize, 0, BIGGEST_ALIGNMENT, -1, true);
1712 :
1713 : /* Set DRAP flag to true, even though allocate_dynamic_stack_space
1714 : may have already set current_function_calls_alloca to true.
1715 : current_function_calls_alloca won't be set if argsize is zero,
1716 : so we have to guarantee need_drap is true here. */
1717 483 : if (SUPPORTS_STACK_ALIGNMENT)
1718 483 : crtl->need_drap = true;
1719 :
1720 483 : dest = virtual_outgoing_args_rtx;
1721 483 : if (!STACK_GROWS_DOWNWARD)
1722 : {
1723 : if (CONST_INT_P (argsize))
1724 : dest = plus_constant (Pmode, dest, -INTVAL (argsize));
1725 : else
1726 : dest = gen_rtx_PLUS (Pmode, dest, negate_rtx (Pmode, argsize));
1727 : }
1728 483 : dest = gen_rtx_MEM (BLKmode, dest);
1729 483 : set_mem_align (dest, PARM_BOUNDARY);
1730 483 : src = gen_rtx_MEM (BLKmode, incoming_args);
1731 483 : set_mem_align (src, PARM_BOUNDARY);
1732 483 : emit_block_move (dest, src, argsize, BLOCK_OP_NORMAL);
1733 :
1734 : /* Refer to the argument block. */
1735 483 : apply_args_size ();
1736 483 : arguments = gen_rtx_MEM (BLKmode, arguments);
1737 483 : set_mem_align (arguments, PARM_BOUNDARY);
1738 :
1739 : /* Walk past the arg-pointer and structure value address. */
1740 483 : size = GET_MODE_SIZE (Pmode);
1741 483 : if (struct_value)
1742 0 : size += GET_MODE_SIZE (Pmode);
1743 :
1744 : /* Restore each of the registers previously saved. Make USE insns
1745 : for each of these registers for use in making the call. */
1746 45885 : for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
1747 45402 : if ((mode = apply_args_mode[regno]) != VOIDmode)
1748 : {
1749 7245 : align = GET_MODE_ALIGNMENT (mode) / BITS_PER_UNIT;
1750 7245 : if (size % align != 0)
1751 0 : size = CEIL (size, align) * align;
1752 7245 : reg = gen_rtx_REG (mode, regno);
1753 7245 : emit_move_insn (reg, adjust_address (arguments, mode, size));
1754 7245 : use_reg (&call_fusage, reg);
1755 14490 : size += GET_MODE_SIZE (mode);
1756 : }
1757 :
1758 : /* Restore the structure value address unless this is passed as an
1759 : "invisible" first argument. */
1760 483 : size = GET_MODE_SIZE (Pmode);
1761 483 : if (struct_value)
1762 : {
1763 0 : rtx value = gen_reg_rtx (Pmode);
1764 0 : emit_move_insn (value, adjust_address (arguments, Pmode, size));
1765 0 : emit_move_insn (struct_value, value);
1766 0 : if (REG_P (struct_value))
1767 0 : use_reg (&call_fusage, struct_value);
1768 : }
1769 :
1770 : /* All arguments and registers used for the call are set up by now! */
1771 483 : function = prepare_call_address (NULL, function, NULL, &call_fusage, 0, 0);
1772 :
1773 : /* Ensure address is valid. SYMBOL_REF is already valid, so no need,
1774 : and we don't want to load it into a register as an optimization,
1775 : because prepare_call_address already did it if it should be done. */
1776 483 : if (GET_CODE (function) != SYMBOL_REF)
1777 29 : function = memory_address (FUNCTION_MODE, function);
1778 :
1779 : /* Generate the actual call instruction and save the return value. */
1780 483 : if (targetm.have_untyped_call ())
1781 : {
1782 483 : rtx mem = gen_rtx_MEM (FUNCTION_MODE, function);
1783 483 : rtx_insn *seq = targetm.gen_untyped_call (mem, result,
1784 : result_vector (1, result));
1785 5317 : for (rtx_insn *insn = seq; insn; insn = NEXT_INSN (insn))
1786 4351 : if (CALL_P (insn))
1787 483 : add_reg_note (insn, REG_UNTYPED_CALL, NULL_RTX);
1788 483 : emit_insn (seq);
1789 : }
1790 0 : else if (targetm.have_call_value ())
1791 : {
1792 : rtx valreg = 0;
1793 :
1794 : /* Locate the unique return register. It is not possible to
1795 : express a call that sets more than one return register using
1796 : call_value; use untyped_call for that. In fact, untyped_call
1797 : only needs to save the return registers in the given block. */
1798 0 : for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
1799 0 : if ((mode = apply_result_mode[regno]) != VOIDmode)
1800 : {
1801 0 : gcc_assert (!valreg); /* have_untyped_call required. */
1802 :
1803 0 : valreg = gen_rtx_REG (mode, regno);
1804 : }
1805 :
1806 0 : emit_insn (targetm.gen_call_value (valreg,
1807 : gen_rtx_MEM (FUNCTION_MODE, function),
1808 : const0_rtx, NULL_RTX, const0_rtx));
1809 :
1810 0 : emit_move_insn (adjust_address (result, GET_MODE (valreg), 0), valreg);
1811 : }
1812 : else
1813 0 : gcc_unreachable ();
1814 :
1815 : /* Find the CALL insn we just emitted, and attach the register usage
1816 : information. */
1817 483 : call_insn = last_call_insn ();
1818 483 : add_function_usage_to (call_insn, call_fusage);
1819 :
1820 : /* Restore the stack. */
1821 483 : if (targetm.have_save_stack_nonlocal ())
1822 483 : emit_stack_restore (SAVE_NONLOCAL, old_stack_level);
1823 : else
1824 0 : emit_stack_restore (SAVE_BLOCK, old_stack_level);
1825 483 : fixup_args_size_notes (call_insn, get_last_insn (), 0);
1826 :
1827 483 : OK_DEFER_POP;
1828 :
1829 : /* Return the address of the result block. */
1830 483 : result = copy_addr_to_reg (XEXP (result, 0));
1831 483 : return convert_memory_address (ptr_mode, result);
1832 : }
1833 :
1834 : /* Perform an untyped return. */
1835 :
1836 : static void
1837 379 : expand_builtin_return (rtx result)
1838 : {
1839 379 : int size, align, regno;
1840 379 : fixed_size_mode mode;
1841 379 : rtx reg;
1842 379 : rtx_insn *call_fusage = 0;
1843 :
1844 379 : result = convert_memory_address (Pmode, result);
1845 :
1846 379 : apply_result_size ();
1847 379 : result = gen_rtx_MEM (BLKmode, result);
1848 :
1849 379 : if (targetm.have_untyped_return ())
1850 : {
1851 0 : rtx vector = result_vector (0, result);
1852 0 : emit_jump_insn (targetm.gen_untyped_return (result, vector));
1853 0 : emit_barrier ();
1854 0 : return;
1855 : }
1856 :
1857 : /* Restore the return value and note that each value is used. */
1858 : size = 0;
1859 36005 : for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
1860 35626 : if ((mode = apply_result_mode[regno]) != VOIDmode)
1861 : {
1862 2274 : align = GET_MODE_ALIGNMENT (mode) / BITS_PER_UNIT;
1863 2274 : if (size % align != 0)
1864 7 : size = CEIL (size, align) * align;
1865 2274 : reg = gen_rtx_REG (mode, INCOMING_REGNO (regno));
1866 2274 : emit_move_insn (reg, adjust_address (result, mode, size));
1867 :
1868 2274 : push_to_sequence (call_fusage);
1869 2274 : emit_use (reg);
1870 2274 : call_fusage = end_sequence ();
1871 4548 : size += GET_MODE_SIZE (mode);
1872 : }
1873 :
1874 : /* Put the USE insns before the return. */
1875 379 : emit_insn (call_fusage);
1876 :
1877 : /* Return whatever values was restored by jumping directly to the end
1878 : of the function. */
1879 379 : expand_naked_return ();
1880 : }
1881 :
1882 : /* Used by expand_builtin_classify_type and fold_builtin_classify_type. */
1883 :
1884 : int
1885 2365 : type_to_class (tree type)
1886 : {
1887 2365 : switch (TREE_CODE (type))
1888 : {
1889 : case VOID_TYPE: return void_type_class;
1890 896 : 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 982 : 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 607244 : mathfn_built_in_2 (tree type, combined_fn fn)
1958 : {
1959 607244 : tree mtype;
1960 607244 : built_in_function fcode, fcodef, fcodel;
1961 607244 : built_in_function fcodef16 = END_BUILTINS;
1962 607244 : built_in_function fcodef32 = END_BUILTINS;
1963 607244 : built_in_function fcodef64 = END_BUILTINS;
1964 607244 : built_in_function fcodef128 = END_BUILTINS;
1965 607244 : built_in_function fcodef32x = END_BUILTINS;
1966 607244 : built_in_function fcodef64x = END_BUILTINS;
1967 607244 : 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 607244 : 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 607180 : SEQ_OF_CASE_MATHFN
2067 :
2068 : default:
2069 : return END_BUILTINS;
2070 : }
2071 :
2072 607244 : mtype = TYPE_MAIN_VARIANT (type);
2073 607244 : if (mtype == double_type_node)
2074 : return fcode;
2075 567692 : else if (mtype == float_type_node)
2076 : return fcodef;
2077 522193 : else if (mtype == long_double_type_node)
2078 : return fcodel;
2079 489664 : else if (mtype == float16_type_node)
2080 : return fcodef16;
2081 489616 : else if (mtype == float32_type_node)
2082 : return fcodef32;
2083 489616 : else if (mtype == float64_type_node)
2084 : return fcodef64;
2085 489616 : else if (mtype == float128_type_node)
2086 : return fcodef128;
2087 482148 : else if (mtype == float32x_type_node)
2088 : return fcodef32x;
2089 482148 : else if (mtype == float64x_type_node)
2090 : return fcodef64x;
2091 482148 : else if (mtype == float128x_type_node)
2092 : return fcodef128x;
2093 : else
2094 482148 : 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 607099 : mathfn_built_in_1 (tree type, combined_fn fn, bool implicit_p)
2108 : {
2109 607099 : built_in_function fcode2 = mathfn_built_in_2 (type, fn);
2110 607099 : if (fcode2 == END_BUILTINS)
2111 : return NULL_TREE;
2112 :
2113 121303 : if (implicit_p && !builtin_decl_implicit_p (fcode2))
2114 : return NULL_TREE;
2115 :
2116 117386 : 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 606600 : mathfn_built_in (tree type, enum built_in_function fn)
2140 : {
2141 606600 : 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 14089687 : associated_internal_fn (built_in_function fn, tree return_type)
2208 : {
2209 14089687 : 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 19587 : CASE_FLT_FN (BUILT_IN_SCALBN):
2227 19587 : CASE_FLT_FN (BUILT_IN_SCALBLN):
2228 19587 : if (REAL_MODE_FORMAT (TYPE_MODE (return_type))->b == 2)
2229 : return IFN_LDEXP;
2230 : return IFN_LAST;
2231 715 : case BUILT_IN_CRC8_DATA8:
2232 715 : case BUILT_IN_CRC16_DATA8:
2233 715 : case BUILT_IN_CRC16_DATA16:
2234 715 : case BUILT_IN_CRC32_DATA8:
2235 715 : case BUILT_IN_CRC32_DATA16:
2236 715 : case BUILT_IN_CRC32_DATA32:
2237 715 : case BUILT_IN_CRC64_DATA8:
2238 715 : case BUILT_IN_CRC64_DATA16:
2239 715 : case BUILT_IN_CRC64_DATA32:
2240 715 : case BUILT_IN_CRC64_DATA64:
2241 715 : return IFN_CRC;
2242 369 : case BUILT_IN_REV_CRC8_DATA8:
2243 369 : case BUILT_IN_REV_CRC16_DATA8:
2244 369 : case BUILT_IN_REV_CRC16_DATA16:
2245 369 : case BUILT_IN_REV_CRC32_DATA8:
2246 369 : case BUILT_IN_REV_CRC32_DATA16:
2247 369 : case BUILT_IN_REV_CRC32_DATA32:
2248 369 : case BUILT_IN_REV_CRC64_DATA8:
2249 369 : case BUILT_IN_REV_CRC64_DATA16:
2250 369 : case BUILT_IN_REV_CRC64_DATA32:
2251 369 : case BUILT_IN_REV_CRC64_DATA64:
2252 369 : 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 636165 : associated_internal_fn (tree fndecl)
2265 : {
2266 636165 : gcc_checking_assert (DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_NORMAL);
2267 636165 : return associated_internal_fn (DECL_FUNCTION_CODE (fndecl),
2268 636165 : 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 34368183 : associated_internal_fn (combined_fn cfn, tree return_type)
2280 : {
2281 34368183 : if (internal_fn_p (cfn))
2282 20914661 : return as_internal_fn (cfn);
2283 13453522 : 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 870514 : replacement_internal_fn (gcall *call)
2296 : {
2297 870514 : if (gimple_call_builtin_p (call, BUILT_IN_NORMAL))
2298 : {
2299 633303 : internal_fn ifn = associated_internal_fn (gimple_call_fndecl (call));
2300 633303 : if (ifn != IFN_LAST)
2301 : {
2302 59152 : tree_pair types = direct_internal_fn_types (ifn, call);
2303 59152 : optimization_type opt_type = bb_optimization_type (gimple_bb (call));
2304 59152 : if (direct_internal_fn_supported_p (ifn, types, opt_type))
2305 37213 : 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 1818519 : interclass_mathfn_icode (tree arg, tree fndecl)
2491 : {
2492 1818519 : bool errno_set = false;
2493 1818519 : optab builtin_optab = unknown_optab;
2494 1818519 : machine_mode mode;
2495 :
2496 1818519 : 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 708836 : CASE_FLT_FN (BUILT_IN_ISINF):
2503 708836 : builtin_optab = isinf_optab;
2504 708836 : break;
2505 625191 : case BUILT_IN_ISFINITE:
2506 625191 : builtin_optab = isfinite_optab;
2507 625191 : break;
2508 239896 : case BUILT_IN_ISNORMAL:
2509 239896 : builtin_optab = isnormal_optab;
2510 239896 : break;
2511 242515 : CASE_FLT_FN (BUILT_IN_ISNAN):
2512 242515 : builtin_optab = isnan_optab;
2513 242515 : 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 1818519 : if (flag_errno_math && errno_set)
2532 : return CODE_FOR_nothing;
2533 :
2534 : /* Optab mode depends on the mode of the input argument. */
2535 1818519 : mode = TYPE_MODE (TREE_TYPE (arg));
2536 :
2537 1818519 : if (builtin_optab)
2538 1816442 : 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 1895 : expand_builtin_feclear_feraise_except (tree exp, rtx target,
2677 : machine_mode target_mode, optab op_optab)
2678 : {
2679 1895 : if (!validate_arglist (exp, INTEGER_TYPE, VOID_TYPE))
2680 : return NULL_RTX;
2681 1895 : rtx op0 = expand_normal (CALL_EXPR_ARG (exp, 0));
2682 :
2683 1895 : insn_code icode = direct_optab_handler (op_optab, SImode);
2684 1895 : 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 136103 : build_call_nofold_loc (location_t loc, tree fndecl, int n, ...)
2819 : {
2820 136103 : va_list ap;
2821 136103 : tree fntype = TREE_TYPE (fndecl);
2822 136103 : tree fn = build1 (ADDR_EXPR, build_pointer_type (fntype), fndecl);
2823 :
2824 136103 : va_start (ap, n);
2825 136103 : fn = build_call_valist (TREE_TYPE (fntype), fn, n, ap);
2826 136103 : va_end (ap);
2827 136103 : SET_EXPR_LOCATION (fn, loc);
2828 136103 : 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 292 : expand_builtin_powi (tree exp, rtx target)
3372 : {
3373 292 : tree arg0, arg1;
3374 292 : rtx op0, op1;
3375 292 : machine_mode mode;
3376 292 : machine_mode mode2;
3377 :
3378 292 : if (! validate_arglist (exp, REAL_TYPE, INTEGER_TYPE, VOID_TYPE))
3379 : return NULL_RTX;
3380 :
3381 292 : arg0 = CALL_EXPR_ARG (exp, 0);
3382 292 : arg1 = CALL_EXPR_ARG (exp, 1);
3383 292 : 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 292 : mode2 = int_mode_for_size (INT_TYPE_SIZE, 0).require ();
3389 :
3390 292 : if (target == NULL_RTX)
3391 0 : target = gen_reg_rtx (mode);
3392 :
3393 292 : op0 = expand_expr (arg0, NULL_RTX, mode, EXPAND_NORMAL);
3394 292 : if (GET_MODE (op0) != mode)
3395 0 : op0 = convert_to_mode (mode, op0, 0);
3396 292 : op1 = expand_expr (arg1, NULL_RTX, mode2, EXPAND_NORMAL);
3397 292 : if (GET_MODE (op1) != mode2)
3398 52 : op1 = convert_to_mode (mode2, op1, 0);
3399 :
3400 292 : target = emit_library_call_value (optab_libfunc (powi_optab, mode),
3401 : target, LCT_CONST, mode,
3402 : op0, mode, op1, mode2);
3403 :
3404 292 : 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 14617 : expand_builtin_strlen (tree exp, rtx target,
3413 : machine_mode target_mode)
3414 : {
3415 14617 : if (!validate_arglist (exp, POINTER_TYPE, VOID_TYPE))
3416 : return NULL_RTX;
3417 :
3418 14598 : tree src = CALL_EXPR_ARG (exp, 0);
3419 :
3420 : /* If the length can be computed at compile-time, return it. */
3421 14598 : if (tree len = c_strlen (src, 0))
3422 141 : 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 14457 : tree len = c_strlen (src, 1);
3430 14457 : 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 14457 : 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 14457 : 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 14457 : FOR_EACH_MODE_FROM (insn_mode, target_mode)
3446 : {
3447 14457 : icode = optab_handler (strlen_optab, insn_mode);
3448 14457 : if (icode != CODE_FOR_nothing)
3449 : break;
3450 : }
3451 14457 : 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 15074 : 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 14457 : rtx_insn *before_strlen = get_last_insn ();
3462 :
3463 14457 : class expand_operand ops[4];
3464 14457 : create_output_operand (&ops[0], target, insn_mode);
3465 14457 : create_fixed_operand (&ops[1], gen_rtx_MEM (BLKmode, src_reg));
3466 14457 : create_integer_operand (&ops[2], 0);
3467 14457 : create_integer_operand (&ops[3], align);
3468 14457 : 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 580 : expand_builtin_strnlen (tree exp, rtx target, machine_mode target_mode)
3511 : {
3512 580 : if (!validate_arglist (exp, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
3513 : return NULL_RTX;
3514 :
3515 571 : tree src = CALL_EXPR_ARG (exp, 0);
3516 571 : tree bound = CALL_EXPR_ARG (exp, 1);
3517 :
3518 571 : if (!bound)
3519 : return NULL_RTX;
3520 :
3521 571 : location_t loc = UNKNOWN_LOCATION;
3522 571 : if (EXPR_HAS_LOCATION (exp))
3523 571 : loc = EXPR_LOCATION (exp);
3524 :
3525 : /* FIXME: Change c_strlen() to return sizetype instead of ssizetype
3526 : so these conversions aren't necessary. */
3527 571 : c_strlen_data lendata = { };
3528 571 : tree len = c_strlen (src, 0, &lendata, 1);
3529 571 : if (len)
3530 63 : len = fold_convert_loc (loc, TREE_TYPE (bound), len);
3531 :
3532 571 : if (TREE_CODE (bound) == INTEGER_CST)
3533 : {
3534 304 : if (!len)
3535 : return NULL_RTX;
3536 :
3537 23 : len = fold_build2_loc (loc, MIN_EXPR, size_type_node, len, bound);
3538 23 : 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 171903 : 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 171903 : const char *rep = (const char *) data;
3582 :
3583 171903 : 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 190323 : 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 190323 : if (CONST_INT_P (len_rtx))
3598 : {
3599 96062 : *min_size = *max_size = *probable_max_size = UINTVAL (len_rtx);
3600 96062 : return;
3601 : }
3602 : else
3603 : {
3604 94261 : wide_int min, max;
3605 94261 : enum value_range_kind range_type = VR_UNDEFINED;
3606 :
3607 : /* Determine bounds from the type. */
3608 94261 : if (tree_fits_uhwi_p (TYPE_MIN_VALUE (TREE_TYPE (len))))
3609 94260 : *min_size = tree_to_uhwi (TYPE_MIN_VALUE (TREE_TYPE (len)));
3610 : else
3611 : *min_size = 0;
3612 94261 : if (tree_fits_uhwi_p (TYPE_MAX_VALUE (TREE_TYPE (len))))
3613 94261 : *probable_max_size = *max_size
3614 94261 : = 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 94261 : if (TREE_CODE (len) == SSA_NAME)
3619 : {
3620 94261 : int_range_max r;
3621 94261 : tree tmin, tmax;
3622 94261 : gimple *cg = currently_expanding_gimple_stmt;
3623 188522 : get_range_query (cfun)->range_of_expr (r, len, cg);
3624 94261 : range_type = get_legacy_range (r, tmin, tmax);
3625 94261 : if (range_type != VR_UNDEFINED)
3626 : {
3627 94259 : min = wi::to_wide (tmin);
3628 94259 : max = wi::to_wide (tmax);
3629 : }
3630 94261 : }
3631 94261 : if (range_type == VR_RANGE)
3632 : {
3633 67961 : if (wi::fits_uhwi_p (min) && *min_size < min.to_uhwi ())
3634 55329 : *min_size = min.to_uhwi ();
3635 67961 : if (wi::fits_uhwi_p (max) && *max_size > max.to_uhwi ())
3636 61369 : *probable_max_size = *max_size = max.to_uhwi ();
3637 : }
3638 26300 : 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 3066 : if (!wi::leu_p (max, 1 << 30) && wi::fits_uhwi_p (min))
3650 2928 : *probable_max_size = min.to_uhwi () - 1;
3651 : }
3652 94261 : }
3653 :
3654 94261 : if (*min_size == *max_size)
3655 11 : len_rtx = GEN_INT (*min_size);
3656 : else
3657 94250 : 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 108828 : expand_builtin_memcpy (tree exp, rtx target)
3669 : {
3670 108828 : if (!validate_arglist (exp,
3671 : POINTER_TYPE, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
3672 : return NULL_RTX;
3673 :
3674 108810 : tree dest = CALL_EXPR_ARG (exp, 0);
3675 108810 : tree src = CALL_EXPR_ARG (exp, 1);
3676 108810 : tree len = CALL_EXPR_ARG (exp, 2);
3677 :
3678 108810 : return expand_builtin_memory_copy_args (dest, src, len, target, exp,
3679 108810 : /*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 17563 : expand_builtin_memmove (tree exp, rtx target)
3687 : {
3688 17563 : if (!validate_arglist (exp,
3689 : POINTER_TYPE, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
3690 : return NULL_RTX;
3691 :
3692 17548 : tree dest = CALL_EXPR_ARG (exp, 0);
3693 17548 : tree src = CALL_EXPR_ARG (exp, 1);
3694 17548 : tree len = CALL_EXPR_ARG (exp, 2);
3695 :
3696 17548 : return expand_builtin_memory_copy_args (dest, src, len, target, exp,
3697 17548 : /*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 127770 : 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 127770 : unsigned int src_align = get_pointer_alignment (src);
3748 127770 : unsigned int dest_align = get_pointer_alignment (dest);
3749 127770 : rtx dest_mem, src_mem, dest_addr, len_rtx;
3750 127770 : HOST_WIDE_INT expected_size = -1;
3751 127770 : unsigned int expected_align = 0;
3752 127770 : unsigned HOST_WIDE_INT min_size;
3753 127770 : unsigned HOST_WIDE_INT max_size;
3754 127770 : unsigned HOST_WIDE_INT probable_max_size;
3755 :
3756 127770 : bool is_move_done;
3757 :
3758 : /* If DEST is not a pointer type, call the normal function. */
3759 127770 : 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 127770 : if (src_align == 0)
3765 : return NULL_RTX;
3766 :
3767 127770 : if (currently_expanding_gimple_stmt)
3768 127770 : stringop_block_profile (currently_expanding_gimple_stmt,
3769 : &expected_align, &expected_size);
3770 :
3771 127770 : if (expected_align < dest_align)
3772 127748 : expected_align = dest_align;
3773 127770 : dest_mem = get_memory_rtx (dest, len, true);
3774 127770 : set_mem_align (dest_mem, dest_align);
3775 127770 : len_rtx = expand_normal (len);
3776 127770 : 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 127770 : unsigned HOST_WIDE_INT nbytes;
3782 127770 : 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 127770 : if (rep
3792 31264 : && CONST_INT_P (len_rtx)
3793 29610 : && (unsigned HOST_WIDE_INT) INTVAL (len_rtx) <= nbytes
3794 157114 : && can_store_by_pieces (INTVAL (len_rtx), builtin_memcpy_read_str,
3795 : const_cast<char *> (rep),
3796 : dest_align, false))
3797 : {
3798 28865 : 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 28865 : dest_mem = force_operand (XEXP (dest_mem, 0), target);
3803 28865 : dest_mem = convert_memory_address (ptr_mode, dest_mem);
3804 28865 : return dest_mem;
3805 : }
3806 :
3807 98905 : src_mem = get_memory_rtx (src, len, false);
3808 98905 : set_mem_align (src_mem, src_align);
3809 :
3810 : /* Copy word part most expediently. */
3811 98905 : enum block_op_methods method = BLOCK_OP_NORMAL;
3812 98905 : if (CALL_EXPR_TAILCALL (exp)
3813 98905 : && (retmode == RETURN_BEGIN || target == const0_rtx))
3814 : method = BLOCK_OP_TAILCALL;
3815 98905 : bool use_mempcpy_call = (targetm.libc_has_fast_function (BUILT_IN_MEMPCPY)
3816 98905 : && retmode == RETURN_END
3817 98905 : && !might_overlap
3818 99979 : && target != const0_rtx);
3819 : if (use_mempcpy_call)
3820 98905 : method = BLOCK_OP_NO_LIBCALL_RET;
3821 98905 : 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 98905 : if (!is_move_done)
3831 : return NULL_RTX;
3832 :
3833 85831 : if (dest_addr == pc_rtx)
3834 : return NULL_RTX;
3835 :
3836 85831 : if (dest_addr == 0)
3837 : {
3838 33008 : dest_addr = force_operand (XEXP (dest_mem, 0), target);
3839 33008 : dest_addr = convert_memory_address (ptr_mode, dest_addr);
3840 : }
3841 :
3842 85831 : 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, true);
3877 0 : src_mem = get_memory_rtx (src, NULL, false);
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 9867 : builtin_strncpy_read_str (void *data, void *, HOST_WIDE_INT offset,
4042 : fixed_size_mode mode)
4043 : {
4044 9867 : const char *str = (const char *) data;
4045 :
4046 9867 : if ((unsigned HOST_WIDE_INT) offset > strlen (str))
4047 260 : return const0_rtx;
4048 :
4049 9607 : 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 : return NULL_RTX;
4152 :
4153 128 : dest_mem = get_memory_rtx (dest, len, true);
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 251353 : gen_memset_value_from_prev (by_pieces_prev *prev, fixed_size_mode mode)
4171 : {
4172 251353 : rtx target = nullptr;
4173 251353 : if (prev != nullptr && prev->data != nullptr)
4174 : {
4175 : /* Use the previous data in the same mode. */
4176 139172 : if (prev->mode == mode)
4177 251353 : return prev->data;
4178 :
4179 32442 : 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 32442 : if (VECTOR_MODE_P (prev_mode) && mode == QImode)
4184 : return target;
4185 :
4186 32043 : rtx prev_rtx = prev->data;
4187 :
4188 32043 : if (REG_P (prev_rtx)
4189 23662 : && HARD_REGISTER_P (prev_rtx)
4190 32043 : && 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 32043 : 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 250089 : builtin_memset_read_str (void *data, void *prev,
4249 : HOST_WIDE_INT offset ATTRIBUTE_UNUSED,
4250 : fixed_size_mode mode)
4251 : {
4252 250089 : const char *c = (const char *) data;
4253 250089 : unsigned int size = GET_MODE_SIZE (mode);
4254 :
4255 250089 : rtx target = gen_memset_value_from_prev ((by_pieces_prev *) prev,
4256 : mode);
4257 250089 : if (target != nullptr)
4258 : return target;
4259 111859 : rtx src = gen_int_mode (*c, QImode);
4260 :
4261 111859 : if (VECTOR_MODE_P (mode))
4262 : {
4263 161842 : gcc_assert (GET_MODE_INNER (mode) == QImode);
4264 :
4265 80921 : rtx const_vec = gen_const_vec_duplicate (mode, src);
4266 80921 : 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 60102 : target = gen_reg_rtx (mode);
4272 60102 : emit_move_insn (target, const_vec);
4273 60102 : return target;
4274 : }
4275 :
4276 30938 : char *p = XALLOCAVEC (char, size);
4277 :
4278 30938 : memset (p, *c, size);
4279 :
4280 30938 : 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 1403 : builtin_memset_gen_str (void *data, void *prev,
4291 : HOST_WIDE_INT offset ATTRIBUTE_UNUSED,
4292 : fixed_size_mode mode)
4293 : {
4294 1403 : rtx target, coeff;
4295 1403 : size_t size;
4296 1403 : char *p;
4297 :
4298 1403 : size = GET_MODE_SIZE (mode);
4299 1403 : if (size == 1)
4300 : return (rtx) data;
4301 :
4302 1264 : target = gen_memset_value_from_prev ((by_pieces_prev *) prev, mode);
4303 1264 : if (target != nullptr)
4304 : return target;
4305 :
4306 721 : 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 540 : p = XALLOCAVEC (char, size);
4326 540 : memset (p, 1, size);
4327 540 : coeff = c_readstr (p, mode);
4328 :
4329 540 : target = convert_to_mode (mode, (rtx) data, 1);
4330 540 : target = expand_mult (mode, target, coeff, NULL_RTX, 1);
4331 540 : 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 62562 : expand_builtin_memset (tree exp, rtx target, machine_mode mode)
4341 : {
4342 62562 : if (!validate_arglist (exp,
4343 : POINTER_TYPE, INTEGER_TYPE, INTEGER_TYPE, VOID_TYPE))
4344 : return NULL_RTX;
4345 :
4346 62553 : tree dest = CALL_EXPR_ARG (exp, 0);
4347 62553 : tree val = CALL_EXPR_ARG (exp, 1);
4348 62553 : tree len = CALL_EXPR_ARG (exp, 2);
4349 :
4350 62553 : 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 24683 : 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 24683 : if (bits
4365 24683 : && !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 22542 : 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 22542 : int max_bits = floor_log2 (max_len);
4407 22542 : int min_bits = floor_log2 (min_len);
4408 22542 : int sctz_len = ctz_len;
4409 :
4410 22542 : gcc_checking_assert (sctz_len >= 0);
4411 :
4412 22542 : if (val)
4413 638 : 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 22542 : int tst_bits = (max_bits != min_bits ? max_bits
4419 10029 : : floor_log2 (max_len ^ min_len));
4420 :
4421 : /* Save the pre-blksize values. */
4422 22542 : int orig_max_bits = max_bits;
4423 22542 : 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 22542 : unsigned HOST_WIDE_INT blksize;
4432 22542 : if (max_len > min_len)
4433 : {
4434 12526 : unsigned HOST_WIDE_INT alrng = MAX (HOST_WIDE_INT_1U << ctz_len,
4435 : align / BITS_PER_UNIT);
4436 12526 : blksize = max_len - (HOST_WIDE_INT_1U << tst_bits) + alrng;
4437 12526 : blksize &= ~(alrng - 1);
4438 : }
4439 10016 : 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 22541 : if (min_len >= blksize
4445 : /* ??? Maybe try smaller fixed-prefix blksizes before
4446 : punting? */
4447 22541 : && can_store_by_pieces (blksize, builtin_memset_read_str,
4448 : &valc, align, true))
4449 : {
4450 281 : min_len -= blksize;
4451 281 : min_bits = floor_log2 (min_len);
4452 281 : max_len -= blksize;
4453 281 : max_bits = floor_log2 (max_len);
4454 :
4455 281 : 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 22541 : unsigned HOST_WIDE_INT xlenest = blksize;
4465 22541 : if (max_bits >= 0)
4466 22366 : xlenest += ((HOST_WIDE_INT_1U << max_bits) * 2
4467 22366 : - (HOST_WIDE_INT_1U << ctz_len));
4468 22541 : bool max_loop = false;
4469 22541 : 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 22541 : if (blksize > xlenest
4474 22541 : || !can_store_by_multiple_pieces (xlenest - blksize,
4475 : builtin_memset_read_str,
4476 : &valc, align, true, blksize))
4477 : {
4478 22366 : 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 62553 : expand_builtin_memset_args (tree dest, tree val, tree len,
4669 : rtx target, machine_mode mode, tree orig_exp)
4670 : {
4671 62553 : tree fndecl, fn;
4672 62553 : enum built_in_function fcode;
4673 62553 : machine_mode val_mode;
4674 62553 : char c;
4675 62553 : unsigned int dest_align;
4676 62553 : rtx dest_mem, dest_addr, len_rtx;
4677 62553 : HOST_WIDE_INT expected_size = -1;
4678 62553 : unsigned int expected_align = 0;
4679 62553 : unsigned HOST_WIDE_INT min_size;
4680 62553 : unsigned HOST_WIDE_INT max_size;
4681 62553 : unsigned HOST_WIDE_INT probable_max_size;
4682 :
4683 62553 : dest_align = get_pointer_alignment (dest);
4684 :
4685 : /* If DEST is not a pointer type, don't do this operation in-line. */
4686 62553 : if (dest_align == 0)
4687 : return NULL_RTX;
4688 :
4689 62553 : if (currently_expanding_gimple_stmt)
4690 62553 : stringop_block_profile (currently_expanding_gimple_stmt,
4691 : &expected_align, &expected_size);
4692 :
4693 62553 : if (expected_align < dest_align)
4694 62545 : expected_align = dest_align;
4695 :
4696 : /* If the LEN parameter is zero, return DEST. */
4697 62553 : 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 62553 : dest = builtin_save_expr (dest);
4706 62553 : val = builtin_save_expr (val);
4707 62553 : len = builtin_save_expr (len);
4708 :
4709 62553 : len_rtx = expand_normal (len);
4710 62553 : determine_block_size (len, len_rtx, &min_size, &max_size,
4711 : &probable_max_size);
4712 62553 : dest_mem = get_memory_rtx (dest, len, true);
4713 62553 : val_mode = TYPE_MODE (unsigned_char_type_node);
4714 :
4715 62553 : if (TREE_CODE (val) != INTEGER_CST
4716 62553 : || target_char_cast (val, &c))
4717 : {
4718 1721 : rtx val_rtx;
4719 :
4720 1721 : val_rtx = expand_normal (val);
4721 1721 : 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 1721 : c = 1;
4727 1721 : if (tree_fits_uhwi_p (len)
4728 1721 : && can_store_by_pieces (tree_to_uhwi (len),
4729 : builtin_memset_read_str, &c, dest_align,
4730 : true))
4731 : {
4732 724 : val_rtx = force_reg (val_mode, val_rtx);
4733 724 : store_by_pieces (dest_mem, tree_to_uhwi (len),
4734 : builtin_memset_gen_str, val_rtx, dest_align,
4735 : true, RETURN_BEGIN);
4736 : }
4737 997 : 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 997 : && !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 637 : goto do_libcall;
4747 :
4748 1084 : dest_mem = force_operand (XEXP (dest_mem, 0), NULL_RTX);
4749 1084 : dest_mem = convert_memory_address (ptr_mode, dest_mem);
4750 1084 : return dest_mem;
4751 : }
4752 :
4753 60832 : if (c)
4754 : {
4755 13406 : if (tree_fits_uhwi_p (len)
4756 13406 : && can_store_by_pieces (tree_to_uhwi (len),
4757 : builtin_memset_read_str, &c, dest_align,
4758 : true))
4759 5741 : store_by_pieces (dest_mem, tree_to_uhwi (len),
4760 : builtin_memset_read_str, &c, dest_align, true,
4761 : RETURN_BEGIN);
4762 9583 : else if (!set_storage_via_setmem (dest_mem, len_rtx,
4763 7665 : gen_int_mode (c, val_mode),
4764 : dest_align, expected_align,
4765 : expected_size, min_size, max_size,
4766 : probable_max_size)
4767 7665 : && !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 5747 : goto do_libcall;
4773 :
4774 7659 : dest_mem = force_operand (XEXP (dest_mem, 0), NULL_RTX);
4775 7659 : dest_mem = convert_memory_address (ptr_mode, dest_mem);
4776 7659 : return dest_mem;
4777 : }
4778 :
4779 47426 : set_mem_align (dest_mem, dest_align);
4780 94852 : dest_addr = clear_storage_hints (dest_mem, len_rtx,
4781 47426 : 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 47426 : if (dest_addr == 0)
4788 : {
4789 37422 : dest_addr = force_operand (XEXP (dest_mem, 0), NULL_RTX);
4790 37422 : dest_addr = convert_memory_address (ptr_mode, dest_addr);
4791 : }
4792 :
4793 : return dest_addr;
4794 :
4795 6384 : do_libcall:
4796 6384 : fndecl = get_callee_fndecl (orig_exp);
4797 6384 : fcode = DECL_FUNCTION_CODE (fndecl);
4798 6384 : if (fcode == BUILT_IN_MEMSET)
4799 6384 : 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 6384 : gcc_assert (TREE_CODE (fn) == CALL_EXPR);
4807 6384 : CALL_EXPR_TAILCALL (fn) = CALL_EXPR_TAILCALL (orig_exp);
4808 6384 : 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 106532 : expand_builtin_memcmp (tree exp, rtx target, bool result_eq)
4866 : {
4867 106532 : if (!validate_arglist (exp,
4868 : POINTER_TYPE, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
4869 : return NULL_RTX;
4870 :
4871 106528 : tree arg1 = CALL_EXPR_ARG (exp, 0);
4872 106528 : tree arg2 = CALL_EXPR_ARG (exp, 1);
4873 106528 : 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 106528 : rtx result = NULL_RTX;
4878 106528 : enum built_in_function fcode = DECL_FUNCTION_CODE (get_callee_fndecl (exp));
4879 106528 : if (!result_eq && fcode != BUILT_IN_BCMP)
4880 : {
4881 14903 : result = inline_expand_builtin_bytecmp (exp, target);
4882 14903 : if (result)
4883 : return result;
4884 : }
4885 :
4886 106510 : machine_mode mode = TYPE_MODE (TREE_TYPE (exp));
4887 106510 : location_t loc = EXPR_LOCATION (exp);
4888 :
4889 106510 : unsigned int arg1_align = get_pointer_alignment (arg1) / BITS_PER_UNIT;
4890 106510 : unsigned int arg2_align = get_pointer_alignment (arg2) / BITS_PER_UNIT;
4891 :
4892 : /* If we don't have POINTER_TYPE, call the function. */
4893 106510 : if (arg1_align == 0 || arg2_align == 0)
4894 : return NULL_RTX;
4895 :
4896 106510 : rtx arg1_rtx = get_memory_rtx (arg1, len, false);
4897 106510 : rtx arg2_rtx = get_memory_rtx (arg2, len, false);
4898 106510 : rtx len_rtx = expand_normal (fold_convert_loc (loc, sizetype, len));
4899 :
4900 : /* Set MEM_SIZE as appropriate. */
4901 106510 : if (CONST_INT_P (len_rtx))
4902 : {
4903 81406 : set_mem_size (arg1_rtx, INTVAL (len_rtx));
4904 81406 : set_mem_size (arg2_rtx, INTVAL (len_rtx));
4905 : }
4906 :
4907 106510 : 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 106510 : unsigned HOST_WIDE_INT nbytes;
4913 106510 : const char *rep = getbyterep (arg2, &nbytes);
4914 106510 : if (result_eq && rep == NULL)
4915 : {
4916 : /* For equality to zero the arguments are interchangeable. */
4917 63602 : rep = getbyterep (arg1, &nbytes);
4918 63602 : 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 42908 : if (rep
4927 30154 : && CONST_INT_P (len_rtx)
4928 30001 : && (unsigned HOST_WIDE_INT) INTVAL (len_rtx) <= nbytes)
4929 106510 : constfn = builtin_memcpy_read_str;
4930 :
4931 213020 : result = emit_block_cmp_hints (arg1_rtx, arg2_rtx, len_rtx,
4932 106510 : TREE_TYPE (len), target,
4933 : result_eq, constfn,
4934 : const_cast<char *> (rep),
4935 : tree_ctz (len));
4936 :
4937 106510 : if (result)
4938 : {
4939 : /* Return the value in the proper mode for this function. */
4940 68942 : 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 127970 : expand_builtin_strcmp (tree exp, ATTRIBUTE_UNUSED rtx target)
4961 : {
4962 127970 : if (!validate_arglist (exp, POINTER_TYPE, POINTER_TYPE, VOID_TYPE))
4963 : return NULL_RTX;
4964 :
4965 127955 : tree arg1 = CALL_EXPR_ARG (exp, 0);
4966 127955 : tree arg2 = CALL_EXPR_ARG (exp, 1);
4967 :
4968 : /* Due to the performance benefit, always inline the calls first. */
4969 127955 : rtx result = NULL_RTX;
4970 127955 : result = inline_expand_builtin_bytecmp (exp, target);
4971 127955 : if (result)
4972 : return result;
4973 :
4974 127556 : insn_code cmpstr_icode = direct_optab_handler (cmpstr_optab, SImode);
4975 127556 : insn_code cmpstrn_icode = direct_optab_handler (cmpstrn_optab, SImode);
4976 127556 : if (cmpstr_icode == CODE_FOR_nothing && cmpstrn_icode == CODE_FOR_nothing)
4977 : return NULL_RTX;
4978 :
4979 127556 : unsigned int arg1_align = get_pointer_alignment (arg1) / BITS_PER_UNIT;
4980 127556 : unsigned int arg2_align = get_pointer_alignment (arg2) / BITS_PER_UNIT;
4981 :
4982 : /* If we don't have POINTER_TYPE, call the function. */
4983 127556 : if (arg1_align == 0 || arg2_align == 0)
4984 : return NULL_RTX;
4985 :
4986 : /* Stabilize the arguments in case gen_cmpstr(n)si fail. */
4987 127556 : arg1 = builtin_save_expr (arg1);
4988 127556 : arg2 = builtin_save_expr (arg2);
4989 :
4990 127556 : rtx arg1_rtx = get_memory_rtx (arg1, NULL, false);
4991 127556 : rtx arg2_rtx = get_memory_rtx (arg2, NULL, false);
4992 :
4993 : /* Try to call cmpstrsi. */
4994 127556 : 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 127556 : if (!result && cmpstrn_icode != CODE_FOR_nothing)
5000 : {
5001 127556 : tree len;
5002 127556 : rtx arg3_rtx;
5003 :
5004 127556 : tree len1 = c_strlen (arg1, 1);
5005 127556 : tree len2 = c_strlen (arg2, 1);
5006 :
5007 127556 : if (len1)
5008 224 : len1 = size_binop (PLUS_EXPR, ssize_int (1), len1);
5009 127556 : if (len2)
5010 125928 : 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 127556 : 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 127556 : len = len2;
5035 :
5036 : /* If both arguments have side effects, we cannot optimize. */
5037 127556 : if (len && !TREE_SIDE_EFFECTS (len))
5038 : {
5039 126135 : arg3_rtx = expand_normal (len);
5040 126135 : result = expand_cmpstrn_or_cmpmem
5041 126135 : (cmpstrn_icode, target, arg1_rtx, arg2_rtx, TREE_TYPE (len),
5042 126135 : arg3_rtx, MIN (arg1_align, arg2_align));
5043 : }
5044 : }
5045 :
5046 127556 : tree fndecl = get_callee_fndecl (exp);
5047 127556 : 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 127504 : tree fn = build_call_nofold_loc (EXPR_LOCATION (exp), fndecl, 2, arg1, arg2);
5062 127504 : copy_warning (fn, exp);
5063 127504 : gcc_assert (TREE_CODE (fn) == CALL_EXPR);
5064 127504 : CALL_EXPR_TAILCALL (fn) = CALL_EXPR_TAILCALL (exp);
5065 127504 : 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 2027 : expand_builtin_strncmp (tree exp, ATTRIBUTE_UNUSED rtx target,
5074 : ATTRIBUTE_UNUSED machine_mode mode)
5075 : {
5076 2027 : if (!validate_arglist (exp,
5077 : POINTER_TYPE, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
5078 : return NULL_RTX;
5079 :
5080 2021 : tree arg1 = CALL_EXPR_ARG (exp, 0);
5081 2021 : tree arg2 = CALL_EXPR_ARG (exp, 1);
5082 2021 : tree arg3 = CALL_EXPR_ARG (exp, 2);
5083 :
5084 2021 : location_t loc = EXPR_LOCATION (exp);
5085 2021 : tree len1 = c_strlen (arg1, 1);
5086 2021 : tree len2 = c_strlen (arg2, 1);
5087 :
5088 : /* Due to the performance benefit, always inline the calls first. */
5089 2021 : rtx result = NULL_RTX;
5090 2021 : result = inline_expand_builtin_bytecmp (exp, target);
5091 2021 : 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 1803 : insn_code cmpstrn_icode = direct_optab_handler (cmpstrn_optab, SImode);
5098 1803 : if (cmpstrn_icode == CODE_FOR_nothing)
5099 : return NULL_RTX;
5100 :
5101 1803 : tree len;
5102 :
5103 1803 : unsigned int arg1_align = get_pointer_alignment (arg1) / BITS_PER_UNIT;
5104 1803 : unsigned int arg2_align = get_pointer_alignment (arg2) / BITS_PER_UNIT;
5105 :
5106 1803 : if (len1)
5107 160 : len1 = size_binop_loc (loc, PLUS_EXPR, ssize_int (1), len1);
5108 1803 : if (len2)
5109 674 : len2 = size_binop_loc (loc, PLUS_EXPR, ssize_int (1), len2);
5110 :
5111 1803 : 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 1803 : if (!len1 && !len2)
5122 : len = len3;
5123 717 : else if (!len1)
5124 : len = len2;
5125 160 : 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 1803 : 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 1803 : if (len != len3)
5143 : {
5144 717 : len = fold_convert_loc (loc, sizetype, len);
5145 717 : len = fold_build2_loc (loc, MIN_EXPR, TREE_TYPE (len), len, len3);
5146 : }
5147 1803 : rtx arg1_rtx = get_memory_rtx (arg1, len, false);
5148 1803 : rtx arg2_rtx = get_memory_rtx (arg2, len, false);
5149 1803 : rtx arg3_rtx = expand_normal (len);
5150 1803 : result = expand_cmpstrn_or_cmpmem (cmpstrn_icode, target, arg1_rtx,
5151 1803 : arg2_rtx, TREE_TYPE (len), arg3_rtx,
5152 1803 : MIN (arg1_align, arg2_align));
5153 :
5154 1803 : tree fndecl = get_callee_fndecl (exp);
5155 1803 : 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 1786 : tree call = build_call_nofold_loc (loc, fndecl, 3, arg1, arg2, len);
5170 1786 : copy_warning (call, exp);
5171 1786 : gcc_assert (TREE_CODE (call) == CALL_EXPR);
5172 1786 : CALL_EXPR_TAILCALL (call) = CALL_EXPR_TAILCALL (exp);
5173 1786 : 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 21240 : 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 21240 : return expand_binop (ptr_mode, add_optab,
5221 : crtl->args.internal_arg_pointer,
5222 : crtl->args.arg_offset_rtx,
5223 21240 : 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 21562 : stabilize_va_list_loc (location_t loc, tree valist, int needs_lvalue)
5231 : {
5232 21562 : 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 21562 : if (!vatype)
5237 21438 : vatype = targetm.fn_abi_va_list (cfun->decl);
5238 :
5239 21562 : if (TREE_CODE (vatype) == ARRAY_TYPE)
5240 : {
5241 15896 : 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 15896 : 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 5666 : tree pt = build_pointer_type (vatype);
5257 :
5258 5666 : 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 5660 : if (TREE_SIDE_EFFECTS (valist))
5268 0 : valist = save_expr (valist);
5269 5660 : 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 5656 : std_expand_builtin_va_start (tree valist, rtx nextarg)
5326 : {
5327 5656 : rtx va_r = expand_expr (valist, NULL_RTX, VOIDmode, EXPAND_WRITE);
5328 5656 : convert_move (va_r, nextarg, 0);
5329 5656 : }
5330 :
5331 : /* Expand EXP, a call to __builtin_va_start. */
5332 :
5333 : static rtx
5334 21082 : expand_builtin_va_start (tree exp)
5335 : {
5336 21082 : rtx nextarg;
5337 21082 : tree valist;
5338 21082 : location_t loc = EXPR_LOCATION (exp);
5339 :
5340 21082 : 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 21082 : if (fold_builtin_next_arg (exp, true))
5347 0 : return const0_rtx;
5348 :
5349 21082 : nextarg = expand_builtin_next_arg ();
5350 21082 : valist = stabilize_va_list_loc (loc, CALL_EXPR_ARG (exp, 0), 1);
5351 :
5352 21082 : if (targetm.expand_builtin_va_start)
5353 21082 : targetm.expand_builtin_va_start (valist, nextarg);
5354 : else
5355 0 : std_expand_builtin_va_start (valist, nextarg);
5356 :
5357 21082 : return const0_rtx;
5358 : }
5359 :
5360 : /* Expand EXP, a call to __builtin_va_end. */
5361 :
5362 : static rtx
5363 12161 : expand_builtin_va_end (tree exp)
5364 : {
5365 12161 : 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 12161 : if (TREE_SIDE_EFFECTS (valist))
5370 0 : expand_expr (valist, const0_rtx, VOIDmode, EXPAND_NORMAL);
5371 :
5372 12161 : 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 15936 : 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 15936 : if (call_expr_nargs (exp) == 0)
5438 : /* Warning about missing arg was already issued. */
5439 0 : return const0_rtx;
5440 15936 : 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 15936 : unsigned HOST_WIDE_INT count = tree_to_uhwi (CALL_EXPR_ARG (exp, 0));
5449 :
5450 15936 : rtx tem = expand_builtin_return_addr (DECL_FUNCTION_CODE (fndecl), count);
5451 :
5452 : /* Some ports cannot access arbitrary stack frames. */
5453 15936 : if (tem == NULL)
5454 : {
5455 0 : warning (0, "unsupported argument to %qD", fndecl);
5456 0 : return const0_rtx;
5457 : }
5458 :
5459 15936 : 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 938 : 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 15936 : if (DECL_FUNCTION_CODE (fndecl) == BUILT_IN_FRAME_ADDRESS)
5469 : return tem;
5470 :
5471 5173 : if (!REG_P (tem)
5472 5173 : && ! CONSTANT_P (tem))
5473 5173 : tem = copy_addr_to_reg (tem);
5474 : 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 3455 : expand_builtin_stack_address ()
5494 : {
5495 3455 : 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 3455 : return force_reg (ptr_mode, ret);
5529 : }
5530 :
5531 : /* Expand a call to builtin function __builtin_strub_enter. */
5532 :
5533 : static rtx
5534 2170 : expand_builtin_strub_enter (tree exp)
5535 : {
5536 2170 : if (!validate_arglist (exp, POINTER_TYPE, VOID_TYPE))
5537 : return NULL_RTX;
5538 :
5539 2170 : if (optimize < 1 || flag_no_inline)
5540 : return NULL_RTX;
5541 :
5542 1526 : rtx stktop = expand_builtin_stack_address ();
5543 :
5544 1526 : tree wmptr = CALL_EXPR_ARG (exp, 0);
5545 1526 : tree wmtype = TREE_TYPE (TREE_TYPE (wmptr));
5546 1526 : tree wmtree = fold_build2 (MEM_REF, wmtype, wmptr,
5547 : build_int_cst (TREE_TYPE (wmptr), 0));
5548 1526 : rtx wmark = expand_expr (wmtree, NULL_RTX, ptr_mode, EXPAND_MEMORY);
5549 :
5550 1526 : emit_move_insn (wmark, stktop);
5551 :
5552 1526 : return const0_rtx;
5553 : }
5554 :
5555 : /* Expand a call to builtin function __builtin_strub_update. */
5556 :
5557 : static rtx
5558 1085 : expand_builtin_strub_update (tree exp)
5559 : {
5560 1085 : if (!validate_arglist (exp, POINTER_TYPE, VOID_TYPE))
5561 : return NULL_RTX;
5562 :
5563 1085 : if (optimize < 2 || flag_no_inline)
5564 : return NULL_RTX;
5565 :
5566 663 : 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 663 : if (true /* (flags_from_decl_or_type (current_function_decl) & ECF_LEAF) */)
5604 : {
5605 663 : poly_int64 red_zone_size = RED_ZONE_SIZE;
5606 : #if STACK_GROWS_DOWNWARD
5607 663 : red_zone_size = -red_zone_size;
5608 : #endif
5609 663 : stktop = plus_constant (ptr_mode, stktop, red_zone_size);
5610 663 : stktop = force_reg (ptr_mode, stktop);
5611 : }
5612 : #endif
5613 :
5614 663 : tree wmptr = CALL_EXPR_ARG (exp, 0);
5615 663 : tree wmtype = TREE_TYPE (TREE_TYPE (wmptr));
5616 663 : tree wmtree = fold_build2 (MEM_REF, wmtype, wmptr,
5617 : build_int_cst (TREE_TYPE (wmptr), 0));
5618 663 : rtx wmark = expand_expr (wmtree, NULL_RTX, ptr_mode, EXPAND_MEMORY);
5619 :
5620 663 : rtx wmark_load = shallow_copy_rtx (wmark);
5621 663 : MEM_NOTRAP_P (wmark_load) = !tree_could_trap_p (wmtree);
5622 663 : rtx wmarkr = force_reg (ptr_mode, wmark_load);
5623 :
5624 663 : rtx_code_label *lab = gen_label_rtx ();
5625 663 : do_compare_rtx_and_jump (stktop, wmarkr, STACK_TOPS, STACK_UNSIGNED,
5626 : ptr_mode, NULL_RTX, lab, NULL,
5627 : profile_probability::very_likely ());
5628 663 : emit_move_insn (wmark, stktop);
5629 :
5630 : /* If this is an inlined strub function, also bump the watermark for the
5631 : enclosing function. This avoids a problem with the following scenario: A
5632 : calls B and B calls C, and both B and C get inlined into A. B allocates
5633 : temporary stack space before calling C. If we don't update A's watermark,
5634 : we may use an outdated baseline for the post-C strub_leave, erasing B's
5635 : temporary stack allocation. We only need this if we're fully expanding
5636 : strub_leave inline. */
5637 663 : tree xwmptr = (optimize > 2
5638 663 : ? strub_watermark_parm (current_function_decl)
5639 : : wmptr);
5640 663 : if (wmptr != xwmptr)
5641 : {
5642 156 : wmptr = xwmptr;
5643 156 : wmtype = TREE_TYPE (TREE_TYPE (wmptr));
5644 156 : wmtree = fold_build2 (MEM_REF, wmtype, wmptr,
5645 : build_int_cst (TREE_TYPE (wmptr), 0));
5646 156 : wmark = expand_expr (wmtree, NULL_RTX, ptr_mode, EXPAND_MEMORY);
5647 156 : wmark_load = shallow_copy_rtx (wmark);
5648 156 : MEM_NOTRAP_P (wmark_load) = !tree_could_trap_p (wmtree);
5649 156 : wmarkr = force_reg (ptr_mode, wmark_load);
5650 :
5651 156 : do_compare_rtx_and_jump (stktop, wmarkr, STACK_TOPS, STACK_UNSIGNED,
5652 : ptr_mode, NULL_RTX, lab, NULL,
5653 : profile_probability::very_likely ());
5654 156 : emit_move_insn (wmark, stktop);
5655 : }
5656 :
5657 663 : emit_label (lab);
5658 :
5659 663 : return const0_rtx;
5660 : }
5661 :
5662 :
5663 : /* Expand a call to builtin function __builtin_strub_leave. */
5664 :
5665 : static rtx
5666 2740 : expand_builtin_strub_leave (tree exp)
5667 : {
5668 2740 : if (!validate_arglist (exp, POINTER_TYPE, VOID_TYPE))
5669 : return NULL_RTX;
5670 :
5671 2740 : if (optimize < 2 || optimize_size || flag_no_inline)
5672 : return NULL_RTX;
5673 :
5674 1239 : rtx stktop = NULL_RTX;
5675 :
5676 1239 : if (tree wmptr = (optimize
5677 1239 : ? strub_watermark_parm (current_function_decl)
5678 : : NULL_TREE))
5679 : {
5680 513 : tree wmtype = TREE_TYPE (TREE_TYPE (wmptr));
5681 513 : tree wmtree = fold_build2 (MEM_REF, wmtype, wmptr,
5682 : build_int_cst (TREE_TYPE (wmptr), 0));
5683 513 : rtx wmark = expand_expr (wmtree, NULL_RTX, ptr_mode, EXPAND_MEMORY);
5684 513 : MEM_NOTRAP_P (wmark) = !tree_could_trap_p (wmtree);
5685 513 : stktop = force_reg (ptr_mode, wmark);
5686 : }
5687 :
5688 513 : if (!stktop)
5689 726 : stktop = expand_builtin_stack_address ();
5690 :
5691 1239 : tree wmptr = CALL_EXPR_ARG (exp, 0);
5692 1239 : tree wmtype = TREE_TYPE (TREE_TYPE (wmptr));
5693 1239 : tree wmtree = fold_build2 (MEM_REF, wmtype, wmptr,
5694 : build_int_cst (TREE_TYPE (wmptr), 0));
5695 1239 : rtx wmark = expand_expr (wmtree, NULL_RTX, ptr_mode, EXPAND_MEMORY);
5696 1239 : MEM_NOTRAP_P (wmark) = !tree_could_trap_p (wmtree);
5697 :
5698 1239 : rtx wmarkr = force_reg (ptr_mode, wmark);
5699 :
5700 : #if ! STACK_GROWS_DOWNWARD
5701 : rtx base = stktop;
5702 : rtx end = wmarkr;
5703 : #else
5704 1239 : rtx base = wmarkr;
5705 1239 : rtx end = stktop;
5706 : #endif
5707 :
5708 : /* We're going to modify it, so make sure it's not e.g. the stack pointer. */
5709 1239 : base = copy_to_reg (base);
5710 :
5711 1239 : rtx_code_label *done = gen_label_rtx ();
5712 1239 : do_compare_rtx_and_jump (base, end, LT, STACK_UNSIGNED,
5713 : ptr_mode, NULL_RTX, done, NULL,
5714 : profile_probability::very_likely ());
5715 :
5716 1239 : if (optimize < 3)
5717 919 : expand_call (exp, NULL_RTX, true);
5718 : else
5719 : {
5720 : /* Ok, now we've determined we want to copy the block, so convert the
5721 : addresses to Pmode, as needed to dereference them to access ptr_mode
5722 : memory locations, so that we don't have to convert anything within the
5723 : loop. */
5724 320 : base = memory_address (ptr_mode, base);
5725 320 : end = memory_address (ptr_mode, end);
5726 :
5727 320 : rtx zero = force_operand (const0_rtx, NULL_RTX);
5728 320 : int ulen = GET_MODE_SIZE (ptr_mode);
5729 :
5730 : /* ??? It would be nice to use setmem or similar patterns here,
5731 : but they do not necessarily obey the stack growth direction,
5732 : which has security implications. We also have to avoid calls
5733 : (memset, bzero or any machine-specific ones), which are
5734 : likely unsafe here (see TARGET_STRUB_MAY_USE_MEMSET). */
5735 : #if ! STACK_GROWS_DOWNWARD
5736 : rtx incr = plus_constant (Pmode, base, ulen);
5737 : rtx dstm = gen_rtx_MEM (ptr_mode, base);
5738 :
5739 : rtx_code_label *loop = gen_label_rtx ();
5740 : emit_label (loop);
5741 : emit_move_insn (dstm, zero);
5742 : emit_move_insn (base, force_operand (incr, NULL_RTX));
5743 : #else
5744 320 : rtx decr = plus_constant (Pmode, end, -ulen);
5745 320 : rtx dstm = gen_rtx_MEM (ptr_mode, end);
5746 :
5747 320 : rtx_code_label *loop = gen_label_rtx ();
5748 320 : emit_label (loop);
5749 320 : emit_move_insn (end, force_operand (decr, NULL_RTX));
5750 320 : emit_move_insn (dstm, zero);
5751 : #endif
5752 640 : do_compare_rtx_and_jump (base, end, LT, STACK_UNSIGNED,
5753 320 : Pmode, NULL_RTX, NULL, loop,
5754 : profile_probability::very_likely ());
5755 : }
5756 :
5757 1239 : emit_label (done);
5758 :
5759 1239 : return const0_rtx;
5760 : }
5761 :
5762 : /* Expand EXP, a call to the alloca builtin. Return NULL_RTX if we
5763 : failed and the caller should emit a normal call. */
5764 :
5765 : static rtx
5766 27611 : expand_builtin_alloca (tree exp)
5767 : {
5768 27611 : rtx op0;
5769 27611 : rtx result;
5770 27611 : unsigned int align;
5771 27611 : tree fndecl = get_callee_fndecl (exp);
5772 27611 : HOST_WIDE_INT max_size;
5773 27611 : enum built_in_function fcode = DECL_FUNCTION_CODE (fndecl);
5774 27611 : bool alloca_for_var = CALL_ALLOCA_FOR_VAR_P (exp);
5775 27611 : bool valid_arglist
5776 : = (fcode == BUILT_IN_ALLOCA_WITH_ALIGN_AND_MAX
5777 27611 : ? validate_arglist (exp, INTEGER_TYPE, INTEGER_TYPE, INTEGER_TYPE,
5778 : VOID_TYPE)
5779 : : fcode == BUILT_IN_ALLOCA_WITH_ALIGN
5780 27609 : ? validate_arglist (exp, INTEGER_TYPE, INTEGER_TYPE, VOID_TYPE)
5781 27611 : : validate_arglist (exp, INTEGER_TYPE, VOID_TYPE));
5782 :
5783 27611 : if (!valid_arglist)
5784 : return NULL_RTX;
5785 :
5786 : /* Compute the argument. */
5787 27606 : op0 = expand_normal (CALL_EXPR_ARG (exp, 0));
5788 :
5789 : /* Compute the alignment. */
5790 51221 : align = (fcode == BUILT_IN_ALLOCA
5791 23616 : ? BIGGEST_ALIGNMENT
5792 3990 : : TREE_INT_CST_LOW (CALL_EXPR_ARG (exp, 1)));
5793 :
5794 : /* Compute the maximum size. */
5795 2 : max_size = (fcode == BUILT_IN_ALLOCA_WITH_ALIGN_AND_MAX
5796 27608 : ? TREE_INT_CST_LOW (CALL_EXPR_ARG (exp, 2))
5797 : : -1);
5798 :
5799 : /* Allocate the desired space. If the allocation stems from the declaration
5800 : of a variable-sized object, it cannot accumulate. */
5801 27606 : result
5802 27606 : = allocate_dynamic_stack_space (op0, 0, align, max_size, alloca_for_var);
5803 27606 : result = convert_memory_address (ptr_mode, result);
5804 :
5805 : /* Dynamic allocations for variables are recorded during gimplification. */
5806 27606 : if (!alloca_for_var && (flag_callgraph_info & CALLGRAPH_INFO_DYNAMIC_ALLOC))
5807 0 : record_dynamic_alloc (exp);
5808 :
5809 : return result;
5810 : }
5811 :
5812 : /* Emit a call to __asan_allocas_unpoison call in EXP. Add to second argument
5813 : of the call virtual_stack_dynamic_rtx - stack_pointer_rtx, which is the
5814 : STACK_DYNAMIC_OFFSET value. See motivation for this in comment to
5815 : handle_builtin_stack_restore function. */
5816 :
5817 : static rtx
5818 204 : expand_asan_emit_allocas_unpoison (tree exp)
5819 : {
5820 204 : tree arg0 = CALL_EXPR_ARG (exp, 0);
5821 204 : tree arg1 = CALL_EXPR_ARG (exp, 1);
5822 204 : rtx top = expand_expr (arg0, NULL_RTX, ptr_mode, EXPAND_NORMAL);
5823 204 : rtx bot = expand_expr (arg1, NULL_RTX, ptr_mode, EXPAND_NORMAL);
5824 204 : rtx off = expand_simple_binop (Pmode, MINUS, virtual_stack_dynamic_rtx,
5825 : stack_pointer_rtx, NULL_RTX, 0,
5826 : OPTAB_LIB_WIDEN);
5827 204 : off = convert_modes (ptr_mode, Pmode, off, 0);
5828 204 : bot = expand_simple_binop (ptr_mode, PLUS, bot, off, NULL_RTX, 0,
5829 : OPTAB_LIB_WIDEN);
5830 204 : rtx ret = init_one_libfunc ("__asan_allocas_unpoison");
5831 204 : ret = emit_library_call_value (ret, NULL_RTX, LCT_NORMAL, ptr_mode,
5832 : top, ptr_mode, bot, ptr_mode);
5833 204 : return ret;
5834 : }
5835 :
5836 : /* Expand a call to bswap builtin in EXP.
5837 : Return NULL_RTX if a normal call should be emitted rather than expanding the
5838 : function in-line. If convenient, the result should be placed in TARGET.
5839 : SUBTARGET may be used as the target for computing one of EXP's operands. */
5840 :
5841 : static rtx
5842 1279 : expand_builtin_bswap (machine_mode target_mode, tree exp, rtx target,
5843 : rtx subtarget)
5844 : {
5845 1279 : tree arg;
5846 1279 : rtx op0;
5847 :
5848 1279 : if (!validate_arglist (exp, INTEGER_TYPE, VOID_TYPE))
5849 : return NULL_RTX;
5850 :
5851 1279 : arg = CALL_EXPR_ARG (exp, 0);
5852 1279 : op0 = expand_expr (arg,
5853 56 : subtarget && GET_MODE (subtarget) == target_mode
5854 : ? subtarget : NULL_RTX,
5855 : target_mode, EXPAND_NORMAL);
5856 1279 : if (GET_MODE (op0) != target_mode)
5857 0 : op0 = convert_to_mode (target_mode, op0, 1);
5858 :
5859 1279 : target = expand_unop (target_mode, bswap_optab, op0, target, 1);
5860 :
5861 1279 : gcc_assert (target);
5862 :
5863 1279 : return convert_to_mode (target_mode, target, 1);
5864 : }
5865 :
5866 : /* Expand a call to a unary builtin in EXP.
5867 : Return NULL_RTX if a normal call should be emitted rather than expanding the
5868 : function in-line. If convenient, the result should be placed in TARGET.
5869 : SUBTARGET may be used as the target for computing one of EXP's operands. */
5870 :
5871 : static rtx
5872 854 : expand_builtin_unop (machine_mode target_mode, tree exp, rtx target,
5873 : rtx subtarget, optab op_optab)
5874 : {
5875 854 : rtx op0;
5876 :
5877 854 : if (!validate_arglist (exp, INTEGER_TYPE, VOID_TYPE))
5878 : return NULL_RTX;
5879 :
5880 : /* Compute the argument. */
5881 1708 : op0 = expand_expr (CALL_EXPR_ARG (exp, 0),
5882 : (subtarget
5883 102 : && (TYPE_MODE (TREE_TYPE (CALL_EXPR_ARG (exp, 0)))
5884 102 : == GET_MODE (subtarget))) ? subtarget : NULL_RTX,
5885 : VOIDmode, EXPAND_NORMAL);
5886 : /* Compute op, into TARGET if possible.
5887 : Set TARGET to wherever the result comes back. */
5888 854 : target = expand_unop (TYPE_MODE (TREE_TYPE (CALL_EXPR_ARG (exp, 0))),
5889 : op_optab, op0, target, op_optab != clrsb_optab);
5890 854 : gcc_assert (target);
5891 :
5892 854 : return convert_to_mode (target_mode, target, 0);
5893 : }
5894 :
5895 : /* Expand a call to __builtin_expect. We just return our argument
5896 : as the builtin_expect semantic should've been already executed by
5897 : tree branch prediction pass. */
5898 :
5899 : static rtx
5900 1407 : expand_builtin_expect (tree exp, rtx target)
5901 : {
5902 1407 : tree arg;
5903 :
5904 1407 : if (call_expr_nargs (exp) < 2)
5905 0 : return const0_rtx;
5906 1407 : arg = CALL_EXPR_ARG (exp, 0);
5907 :
5908 1407 : target = expand_expr (arg, target, VOIDmode, EXPAND_NORMAL);
5909 : /* When guessing was done, the hints should be already stripped away. */
5910 1407 : gcc_assert (!flag_guess_branch_prob
5911 : || optimize == 0 || seen_error ());
5912 : return target;
5913 : }
5914 :
5915 : /* Expand a call to __builtin_expect_with_probability. We just return our
5916 : argument as the builtin_expect semantic should've been already executed by
5917 : tree branch prediction pass. */
5918 :
5919 : static rtx
5920 5 : expand_builtin_expect_with_probability (tree exp, rtx target)
5921 : {
5922 5 : tree arg;
5923 :
5924 5 : if (call_expr_nargs (exp) < 3)
5925 0 : return const0_rtx;
5926 5 : arg = CALL_EXPR_ARG (exp, 0);
5927 :
5928 5 : target = expand_expr (arg, target, VOIDmode, EXPAND_NORMAL);
5929 : /* When guessing was done, the hints should be already stripped away. */
5930 5 : gcc_assert (!flag_guess_branch_prob
5931 : || optimize == 0 || seen_error ());
5932 : return target;
5933 : }
5934 :
5935 :
5936 : /* Expand a call to __builtin_assume_aligned. We just return our first
5937 : argument as the builtin_assume_aligned semantic should've been already
5938 : executed by CCP. */
5939 :
5940 : static rtx
5941 665 : expand_builtin_assume_aligned (tree exp, rtx target)
5942 : {
5943 665 : if (call_expr_nargs (exp) < 2)
5944 0 : return const0_rtx;
5945 665 : target = expand_expr (CALL_EXPR_ARG (exp, 0), target, VOIDmode,
5946 : EXPAND_NORMAL);
5947 665 : gcc_assert (!TREE_SIDE_EFFECTS (CALL_EXPR_ARG (exp, 1))
5948 : && (call_expr_nargs (exp) < 3
5949 : || !TREE_SIDE_EFFECTS (CALL_EXPR_ARG (exp, 2))));
5950 : return target;
5951 : }
5952 :
5953 : void
5954 38677 : expand_builtin_trap (void)
5955 : {
5956 38677 : if (targetm.have_trap ())
5957 : {
5958 38677 : rtx_insn *insn = emit_insn (targetm.gen_trap ());
5959 : /* For trap insns when not accumulating outgoing args force
5960 : REG_ARGS_SIZE note to prevent crossjumping of calls with
5961 : different args sizes. */
5962 38677 : if (!ACCUMULATE_OUTGOING_ARGS)
5963 38675 : add_args_size_note (insn, stack_pointer_delta);
5964 : }
5965 : else
5966 : {
5967 0 : tree fn = builtin_decl_implicit (BUILT_IN_ABORT);
5968 0 : tree call_expr = build_call_expr (fn, 0);
5969 0 : expand_call (call_expr, NULL_RTX, false);
5970 : }
5971 :
5972 38677 : emit_barrier ();
5973 38677 : }
5974 :
5975 : /* Expand a call to __builtin_unreachable. We do nothing except emit
5976 : a barrier saying that control flow will not pass here.
5977 :
5978 : It is the responsibility of the program being compiled to ensure
5979 : that control flow does never reach __builtin_unreachable. */
5980 : static void
5981 2563 : expand_builtin_unreachable (void)
5982 : {
5983 : /* Use gimple_build_builtin_unreachable or builtin_decl_unreachable
5984 : to avoid this. */
5985 2563 : gcc_checking_assert (!sanitize_flags_p (SANITIZE_UNREACHABLE));
5986 2563 : emit_barrier ();
5987 2563 : }
5988 :
5989 : /* Expand EXP, a call to fabs, fabsf or fabsl.
5990 : Return NULL_RTX if a normal call should be emitted rather than expanding
5991 : the function inline. If convenient, the result should be placed
5992 : in TARGET. SUBTARGET may be used as the target for computing
5993 : the operand. */
5994 :
5995 : static rtx
5996 4 : expand_builtin_fabs (tree exp, rtx target, rtx subtarget)
5997 : {
5998 4 : machine_mode mode;
5999 4 : tree arg;
6000 4 : rtx op0;
6001 :
6002 4 : if (!validate_arglist (exp, REAL_TYPE, VOID_TYPE))
6003 : return NULL_RTX;
6004 :
6005 0 : arg = CALL_EXPR_ARG (exp, 0);
6006 0 : CALL_EXPR_ARG (exp, 0) = arg = builtin_save_expr (arg);
6007 0 : mode = TYPE_MODE (TREE_TYPE (arg));
6008 0 : op0 = expand_expr (arg, subtarget, VOIDmode, EXPAND_NORMAL);
6009 0 : return expand_abs (mode, op0, target, 0, safe_from_p (target, arg, 1));
6010 : }
6011 :
6012 : /* Expand EXP, a call to copysign, copysignf, or copysignl.
6013 : Return NULL is a normal call should be emitted rather than expanding the
6014 : function inline. If convenient, the result should be placed in TARGET.
6015 : SUBTARGET may be used as the target for computing the operand. */
6016 :
6017 : static rtx
6018 11677 : expand_builtin_copysign (tree exp, rtx target, rtx subtarget)
6019 : {
6020 11677 : rtx op0, op1;
6021 11677 : tree arg;
6022 :
6023 11677 : if (!validate_arglist (exp, REAL_TYPE, REAL_TYPE, VOID_TYPE))
6024 : return NULL_RTX;
6025 :
6026 11676 : arg = CALL_EXPR_ARG (exp, 0);
6027 11676 : op0 = expand_expr (arg, subtarget, VOIDmode, EXPAND_NORMAL);
6028 :
6029 11676 : arg = CALL_EXPR_ARG (exp, 1);
6030 11676 : op1 = expand_normal (arg);
6031 :
6032 11676 : return expand_copysign (op0, op1, target);
6033 : }
6034 :
6035 : /* Emit a call to __builtin___clear_cache. */
6036 :
6037 : void
6038 0 : default_emit_call_builtin___clear_cache (rtx begin, rtx end)
6039 : {
6040 0 : rtx callee = gen_rtx_SYMBOL_REF (Pmode,
6041 : BUILTIN_ASM_NAME_PTR
6042 : (BUILT_IN_CLEAR_CACHE));
6043 :
6044 0 : emit_library_call (callee,
6045 : LCT_NORMAL, VOIDmode,
6046 : convert_memory_address (ptr_mode, begin), ptr_mode,
6047 : convert_memory_address (ptr_mode, end), ptr_mode);
6048 0 : }
6049 :
6050 : /* Emit a call to __builtin___clear_cache, unless the target specifies
6051 : it as do-nothing. This function can be used by trampoline
6052 : finalizers to duplicate the effects of expanding a call to the
6053 : clear_cache builtin. */
6054 :
6055 : void
6056 28 : maybe_emit_call_builtin___clear_cache (rtx begin, rtx end)
6057 : {
6058 28 : gcc_assert ((GET_MODE (begin) == ptr_mode || GET_MODE (begin) == Pmode
6059 : || CONST_INT_P (begin))
6060 : && (GET_MODE (end) == ptr_mode || GET_MODE (end) == Pmode
6061 : || CONST_INT_P (end)));
6062 :
6063 28 : if (targetm.have_clear_cache ())
6064 : {
6065 : /* We have a "clear_cache" insn, and it will handle everything. */
6066 0 : class expand_operand ops[2];
6067 :
6068 0 : create_address_operand (&ops[0], begin);
6069 0 : create_address_operand (&ops[1], end);
6070 :
6071 0 : if (maybe_expand_insn (targetm.code_for_clear_cache, 2, ops))
6072 0 : return;
6073 : }
6074 : else
6075 : {
6076 : #ifndef CLEAR_INSN_CACHE
6077 : /* There is no "clear_cache" insn, and __clear_cache() in libgcc
6078 : does nothing. There is no need to call it. Do nothing. */
6079 : return;
6080 : #endif /* CLEAR_INSN_CACHE */
6081 : }
6082 :
6083 0 : targetm.calls.emit_call_builtin___clear_cache (begin, end);
6084 : }
6085 :
6086 : /* Expand a call to __builtin___clear_cache. */
6087 :
6088 : static void
6089 28 : expand_builtin___clear_cache (tree exp)
6090 : {
6091 28 : tree begin, end;
6092 28 : rtx begin_rtx, end_rtx;
6093 :
6094 : /* We must not expand to a library call. If we did, any
6095 : fallback library function in libgcc that might contain a call to
6096 : __builtin___clear_cache() would recurse infinitely. */
6097 28 : if (!validate_arglist (exp, POINTER_TYPE, POINTER_TYPE, VOID_TYPE))
6098 : {
6099 0 : error ("both arguments to %<__builtin___clear_cache%> must be pointers");
6100 0 : return;
6101 : }
6102 :
6103 28 : begin = CALL_EXPR_ARG (exp, 0);
6104 30 : begin_rtx = expand_expr (begin, NULL_RTX, Pmode, EXPAND_NORMAL);
6105 :
6106 28 : end = CALL_EXPR_ARG (exp, 1);
6107 30 : end_rtx = expand_expr (end, NULL_RTX, Pmode, EXPAND_NORMAL);
6108 :
6109 28 : maybe_emit_call_builtin___clear_cache (begin_rtx, end_rtx);
6110 : }
6111 :
6112 : /* Given a trampoline address, make sure it satisfies TRAMPOLINE_ALIGNMENT. */
6113 :
6114 : static rtx
6115 659 : round_trampoline_addr (rtx tramp)
6116 : {
6117 659 : rtx temp, addend, mask;
6118 :
6119 : /* If we don't need too much alignment, we'll have been guaranteed
6120 : proper alignment by get_trampoline_type. */
6121 659 : if (TRAMPOLINE_ALIGNMENT <= STACK_BOUNDARY)
6122 : return tramp;
6123 :
6124 : /* Round address up to desired boundary. */
6125 0 : temp = gen_reg_rtx (Pmode);
6126 0 : addend = gen_int_mode (TRAMPOLINE_ALIGNMENT / BITS_PER_UNIT - 1, Pmode);
6127 0 : mask = gen_int_mode (-TRAMPOLINE_ALIGNMENT / BITS_PER_UNIT, Pmode);
6128 :
6129 0 : temp = expand_simple_binop (Pmode, PLUS, tramp, addend,
6130 : temp, 0, OPTAB_LIB_WIDEN);
6131 0 : tramp = expand_simple_binop (Pmode, AND, temp, mask,
6132 : temp, 0, OPTAB_LIB_WIDEN);
6133 :
6134 0 : return tramp;
6135 : }
6136 :
6137 : static rtx
6138 306 : expand_builtin_init_trampoline (tree exp, bool onstack)
6139 : {
6140 306 : tree t_tramp, t_func, t_chain;
6141 306 : rtx m_tramp, r_tramp, r_chain, tmp;
6142 :
6143 306 : if (!validate_arglist (exp, POINTER_TYPE, POINTER_TYPE,
6144 : POINTER_TYPE, VOID_TYPE))
6145 : return NULL_RTX;
6146 :
6147 306 : t_tramp = CALL_EXPR_ARG (exp, 0);
6148 306 : t_func = CALL_EXPR_ARG (exp, 1);
6149 306 : t_chain = CALL_EXPR_ARG (exp, 2);
6150 :
6151 306 : r_tramp = expand_normal (t_tramp);
6152 306 : m_tramp = gen_rtx_MEM (BLKmode, r_tramp);
6153 306 : MEM_NOTRAP_P (m_tramp) = 1;
6154 :
6155 : /* If ONSTACK, the TRAMP argument should be the address of a field
6156 : within the local function's FRAME decl. Either way, let's see if
6157 : we can fill in the MEM_ATTRs for this memory. */
6158 306 : if (TREE_CODE (t_tramp) == ADDR_EXPR)
6159 306 : set_mem_attributes (m_tramp, TREE_OPERAND (t_tramp, 0), true);
6160 :
6161 : /* Creator of a heap trampoline is responsible for making sure the
6162 : address is aligned to at least STACK_BOUNDARY. Normally malloc
6163 : will ensure this anyhow. */
6164 306 : tmp = round_trampoline_addr (r_tramp);
6165 306 : if (tmp != r_tramp)
6166 : {
6167 0 : m_tramp = change_address (m_tramp, BLKmode, tmp);
6168 0 : set_mem_align (m_tramp, TRAMPOLINE_ALIGNMENT);
6169 0 : set_mem_size (m_tramp, TRAMPOLINE_SIZE);
6170 : }
6171 :
6172 : /* The FUNC argument should be the address of the nested function.
6173 : Extract the actual function decl to pass to the hook. */
6174 306 : gcc_assert (TREE_CODE (t_func) == ADDR_EXPR);
6175 306 : t_func = TREE_OPERAND (t_func, 0);
6176 306 : gcc_assert (TREE_CODE (t_func) == FUNCTION_DECL);
6177 :
6178 306 : r_chain = expand_normal (t_chain);
6179 :
6180 : /* Generate insns to initialize the trampoline. */
6181 306 : targetm.calls.trampoline_init (m_tramp, t_func, r_chain);
6182 :
6183 306 : if (onstack)
6184 : {
6185 306 : trampolines_created = 1;
6186 :
6187 306 : if (targetm.calls.custom_function_descriptors != 0)
6188 306 : warning_at (DECL_SOURCE_LOCATION (t_func), OPT_Wtrampolines,
6189 : "trampoline generated for nested function %qD", t_func);
6190 : }
6191 :
6192 306 : return const0_rtx;
6193 : }
6194 :
6195 : static rtx
6196 353 : expand_builtin_adjust_trampoline (tree exp)
6197 : {
6198 353 : rtx tramp;
6199 :
6200 353 : if (!validate_arglist (exp, POINTER_TYPE, VOID_TYPE))
6201 : return NULL_RTX;
6202 :
6203 353 : tramp = expand_normal (CALL_EXPR_ARG (exp, 0));
6204 353 : tramp = round_trampoline_addr (tramp);
6205 353 : if (targetm.calls.trampoline_adjust_address)
6206 0 : tramp = targetm.calls.trampoline_adjust_address (tramp);
6207 :
6208 : return tramp;
6209 : }
6210 :
6211 : /* Expand a call to the builtin descriptor initialization routine.
6212 : A descriptor is made up of a couple of pointers to the static
6213 : chain and the code entry in this order. */
6214 :
6215 : static rtx
6216 0 : expand_builtin_init_descriptor (tree exp)
6217 : {
6218 0 : tree t_descr, t_func, t_chain;
6219 0 : rtx m_descr, r_descr, r_func, r_chain;
6220 :
6221 0 : if (!validate_arglist (exp, POINTER_TYPE, POINTER_TYPE, POINTER_TYPE,
6222 : VOID_TYPE))
6223 : return NULL_RTX;
6224 :
6225 0 : t_descr = CALL_EXPR_ARG (exp, 0);
6226 0 : t_func = CALL_EXPR_ARG (exp, 1);
6227 0 : t_chain = CALL_EXPR_ARG (exp, 2);
6228 :
6229 0 : r_descr = expand_normal (t_descr);
6230 0 : m_descr = gen_rtx_MEM (BLKmode, r_descr);
6231 0 : MEM_NOTRAP_P (m_descr) = 1;
6232 0 : set_mem_align (m_descr, GET_MODE_ALIGNMENT (ptr_mode));
6233 :
6234 0 : r_func = expand_normal (t_func);
6235 0 : r_chain = expand_normal (t_chain);
6236 :
6237 : /* Generate insns to initialize the descriptor. */
6238 0 : emit_move_insn (adjust_address_nv (m_descr, ptr_mode, 0), r_chain);
6239 0 : emit_move_insn (adjust_address_nv (m_descr, ptr_mode,
6240 : POINTER_SIZE / BITS_PER_UNIT), r_func);
6241 :
6242 0 : return const0_rtx;
6243 : }
6244 :
6245 : /* Expand a call to the builtin descriptor adjustment routine. */
6246 :
6247 : static rtx
6248 0 : expand_builtin_adjust_descriptor (tree exp)
6249 : {
6250 0 : rtx tramp;
6251 :
6252 0 : if (!validate_arglist (exp, POINTER_TYPE, VOID_TYPE))
6253 : return NULL_RTX;
6254 :
6255 0 : tramp = expand_normal (CALL_EXPR_ARG (exp, 0));
6256 :
6257 : /* Unalign the descriptor to allow runtime identification. */
6258 0 : tramp = plus_constant (ptr_mode, tramp,
6259 0 : targetm.calls.custom_function_descriptors);
6260 :
6261 0 : return force_operand (tramp, NULL_RTX);
6262 : }
6263 :
6264 : /* Expand the call EXP to the built-in signbit, signbitf or signbitl
6265 : function. The function first checks whether the back end provides
6266 : an insn to implement signbit for the respective mode. If not, it
6267 : checks whether the floating point format of the value is such that
6268 : the sign bit can be extracted. If that is not the case, error out.
6269 : EXP is the expression that is a call to the builtin function; if
6270 : convenient, the result should be placed in TARGET. */
6271 : static rtx
6272 1368 : expand_builtin_signbit (tree exp, rtx target)
6273 : {
6274 1368 : const struct real_format *fmt;
6275 1368 : scalar_float_mode fmode;
6276 1368 : scalar_int_mode rmode, imode;
6277 1368 : tree arg;
6278 1368 : int word, bitpos;
6279 1368 : enum insn_code icode;
6280 1368 : rtx temp;
6281 1368 : location_t loc = EXPR_LOCATION (exp);
6282 :
6283 1368 : if (!validate_arglist (exp, REAL_TYPE, VOID_TYPE))
6284 : return NULL_RTX;
6285 :
6286 1368 : arg = CALL_EXPR_ARG (exp, 0);
6287 1368 : fmode = SCALAR_FLOAT_TYPE_MODE (TREE_TYPE (arg));
6288 1368 : rmode = SCALAR_INT_TYPE_MODE (TREE_TYPE (exp));
6289 1368 : fmt = REAL_MODE_FORMAT (fmode);
6290 :
6291 1368 : arg = builtin_save_expr (arg);
6292 :
6293 : /* Expand the argument yielding a RTX expression. */
6294 1368 : temp = expand_normal (arg);
6295 :
6296 : /* Check if the back end provides an insn that handles signbit for the
6297 : argument's mode. */
6298 1368 : icode = optab_handler (signbit_optab, fmode);
6299 1368 : if (icode != CODE_FOR_nothing)
6300 : {
6301 10 : rtx_insn *last = get_last_insn ();
6302 10 : rtx this_target = gen_reg_rtx (TYPE_MODE (TREE_TYPE (exp)));
6303 10 : if (maybe_emit_unop_insn (icode, this_target, temp, UNKNOWN))
6304 : return this_target;
6305 0 : delete_insns_since (last);
6306 : }
6307 :
6308 : /* For floating point formats without a sign bit, implement signbit
6309 : as "ARG < 0.0". */
6310 1358 : bitpos = fmt->signbit_ro;
6311 1358 : if (bitpos < 0)
6312 : {
6313 : /* But we can't do this if the format supports signed zero. */
6314 0 : gcc_assert (!fmt->has_signed_zero || !HONOR_SIGNED_ZEROS (fmode));
6315 :
6316 0 : arg = fold_build2_loc (loc, LT_EXPR, TREE_TYPE (exp), arg,
6317 0 : build_real (TREE_TYPE (arg), dconst0));
6318 0 : return expand_expr (arg, target, VOIDmode, EXPAND_NORMAL);
6319 : }
6320 :
6321 2720 : if (GET_MODE_SIZE (fmode) <= UNITS_PER_WORD)
6322 : {
6323 1254 : imode = int_mode_for_mode (fmode).require ();
6324 1254 : temp = gen_lowpart (imode, temp);
6325 : }
6326 : else
6327 : {
6328 104 : imode = word_mode;
6329 : /* Handle targets with different FP word orders. */
6330 104 : if (FLOAT_WORDS_BIG_ENDIAN)
6331 : word = (GET_MODE_BITSIZE (fmode) - bitpos) / BITS_PER_WORD;
6332 : else
6333 104 : word = bitpos / BITS_PER_WORD;
6334 104 : temp = operand_subword_force (temp, word, fmode);
6335 104 : bitpos = bitpos % BITS_PER_WORD;
6336 : }
6337 :
6338 : /* Force the intermediate word_mode (or narrower) result into a
6339 : register. This avoids attempting to create paradoxical SUBREGs
6340 : of floating point modes below. */
6341 1358 : temp = force_reg (imode, temp);
6342 :
6343 : /* If the bitpos is within the "result mode" lowpart, the operation
6344 : can be implement with a single bitwise AND. Otherwise, we need
6345 : a right shift and an AND. */
6346 :
6347 2716 : if (bitpos < GET_MODE_BITSIZE (rmode))
6348 : {
6349 1150 : wide_int mask = wi::set_bit_in_zero (bitpos, GET_MODE_PRECISION (rmode));
6350 :
6351 3450 : if (GET_MODE_SIZE (imode) > GET_MODE_SIZE (rmode))
6352 0 : temp = gen_lowpart (rmode, temp);
6353 2300 : temp = expand_binop (rmode, and_optab, temp,
6354 2300 : immed_wide_int_const (mask, rmode),
6355 : NULL_RTX, 1, OPTAB_LIB_WIDEN);
6356 1150 : }
6357 : else
6358 : {
6359 : /* Perform a logical right shift to place the signbit in the least
6360 : significant bit, then truncate the result to the desired mode
6361 : and mask just this bit. */
6362 208 : temp = expand_shift (RSHIFT_EXPR, imode, temp, bitpos, NULL_RTX, 1);
6363 208 : temp = gen_lowpart (rmode, temp);
6364 208 : temp = expand_binop (rmode, and_optab, temp, const1_rtx,
6365 : NULL_RTX, 1, OPTAB_LIB_WIDEN);
6366 : }
6367 :
6368 : return temp;
6369 : }
6370 :
6371 : /* Expand fork or exec calls. TARGET is the desired target of the
6372 : call. EXP is the call. FN is the
6373 : identificator of the actual function. IGNORE is nonzero if the
6374 : value is to be ignored. */
6375 :
6376 : static rtx
6377 111 : expand_builtin_fork_or_exec (tree fn, tree exp, rtx target, int ignore)
6378 : {
6379 111 : tree id, decl;
6380 111 : tree call;
6381 :
6382 : /* If we are not profiling, just call the function. */
6383 111 : if (!coverage_instrumentation_p ())
6384 : return NULL_RTX;
6385 :
6386 : /* Otherwise call the wrapper. This should be equivalent for the rest of
6387 : compiler, so the code does not diverge, and the wrapper may run the
6388 : code necessary for keeping the profiling sane. */
6389 :
6390 4 : switch (DECL_FUNCTION_CODE (fn))
6391 : {
6392 4 : case BUILT_IN_FORK:
6393 4 : id = get_identifier ("__gcov_fork");
6394 4 : break;
6395 :
6396 0 : case BUILT_IN_EXECL:
6397 0 : id = get_identifier ("__gcov_execl");
6398 0 : break;
6399 :
6400 0 : case BUILT_IN_EXECV:
6401 0 : id = get_identifier ("__gcov_execv");
6402 0 : break;
6403 :
6404 0 : case BUILT_IN_EXECLP:
6405 0 : id = get_identifier ("__gcov_execlp");
6406 0 : break;
6407 :
6408 0 : case BUILT_IN_EXECLE:
6409 0 : id = get_identifier ("__gcov_execle");
6410 0 : break;
6411 :
6412 0 : case BUILT_IN_EXECVP:
6413 0 : id = get_identifier ("__gcov_execvp");
6414 0 : break;
6415 :
6416 0 : case BUILT_IN_EXECVE:
6417 0 : id = get_identifier ("__gcov_execve");
6418 0 : break;
6419 :
6420 0 : default:
6421 0 : gcc_unreachable ();
6422 : }
6423 :
6424 4 : decl = build_decl (DECL_SOURCE_LOCATION (fn),
6425 4 : FUNCTION_DECL, id, TREE_TYPE (fn));
6426 4 : DECL_EXTERNAL (decl) = 1;
6427 4 : TREE_PUBLIC (decl) = 1;
6428 4 : DECL_ARTIFICIAL (decl) = 1;
6429 4 : TREE_NOTHROW (decl) = 1;
6430 4 : DECL_VISIBILITY (decl) = VISIBILITY_DEFAULT;
6431 4 : DECL_VISIBILITY_SPECIFIED (decl) = 1;
6432 4 : call = rewrite_call_expr (EXPR_LOCATION (exp), exp, 0, decl, 0);
6433 4 : return expand_call (call, target, ignore);
6434 : }
6435 :
6436 :
6437 :
6438 : /* Reconstitute a mode for a __sync intrinsic operation. Since the type of
6439 : the pointer in these functions is void*, the tree optimizers may remove
6440 : casts. The mode computed in expand_builtin isn't reliable either, due
6441 : to __sync_bool_compare_and_swap.
6442 :
6443 : FCODE_DIFF should be fcode - base, where base is the FOO_1 code for the
6444 : group of builtins. This gives us log2 of the mode size. */
6445 :
6446 : static inline machine_mode
6447 134161 : get_builtin_sync_mode (int fcode_diff)
6448 : {
6449 : /* The size is not negotiable, so ask not to get BLKmode in return
6450 : if the target indicates that a smaller size would be better. */
6451 134161 : return int_mode_for_size (BITS_PER_UNIT << fcode_diff, 0).require ();
6452 : }
6453 :
6454 : /* Expand the memory expression LOC and return the appropriate memory operand
6455 : for the builtin_sync operations. */
6456 :
6457 : static rtx
6458 150797 : get_builtin_sync_mem (tree loc, machine_mode mode)
6459 : {
6460 150797 : rtx addr, mem;
6461 150797 : int addr_space = TYPE_ADDR_SPACE (POINTER_TYPE_P (TREE_TYPE (loc))
6462 : ? TREE_TYPE (TREE_TYPE (loc))
6463 : : TREE_TYPE (loc));
6464 150797 : scalar_int_mode addr_mode = targetm.addr_space.address_mode (addr_space);
6465 :
6466 150797 : addr = expand_expr (loc, NULL_RTX, addr_mode, EXPAND_SUM);
6467 150797 : addr = convert_memory_address (addr_mode, addr);
6468 :
6469 : /* Note that we explicitly do not want any alias information for this
6470 : memory, so that we kill all other live memories. Otherwise we don't
6471 : satisfy the full barrier semantics of the intrinsic. */
6472 150797 : mem = gen_rtx_MEM (mode, addr);
6473 :
6474 150797 : set_mem_addr_space (mem, addr_space);
6475 :
6476 150797 : mem = validize_mem (mem);
6477 :
6478 : /* The alignment needs to be at least according to that of the mode. */
6479 150797 : set_mem_align (mem, MAX (GET_MODE_ALIGNMENT (mode),
6480 : get_pointer_alignment (loc)));
6481 150797 : set_mem_alias_set (mem, ALIAS_SET_MEMORY_BARRIER);
6482 150797 : MEM_VOLATILE_P (mem) = 1;
6483 :
6484 150797 : return mem;
6485 : }
6486 :
6487 : /* Make sure an argument is in the right mode.
6488 : EXP is the tree argument.
6489 : MODE is the mode it should be in. */
6490 :
6491 : static rtx
6492 94182 : expand_expr_force_mode (tree exp, machine_mode mode)
6493 : {
6494 94182 : rtx val;
6495 94182 : machine_mode old_mode;
6496 :
6497 94182 : if (TREE_CODE (exp) == SSA_NAME
6498 94182 : && TYPE_MODE (TREE_TYPE (exp)) != mode)
6499 : {
6500 : /* Undo argument promotion if possible, as combine might not
6501 : be able to do it later due to MEM_VOLATILE_P uses in the
6502 : patterns. */
6503 25 : gimple *g = get_gimple_for_ssa_name (exp);
6504 25 : if (g && gimple_assign_cast_p (g))
6505 : {
6506 0 : tree rhs = gimple_assign_rhs1 (g);
6507 0 : tree_code code = gimple_assign_rhs_code (g);
6508 0 : if (CONVERT_EXPR_CODE_P (code)
6509 0 : && TYPE_MODE (TREE_TYPE (rhs)) == mode
6510 0 : && INTEGRAL_TYPE_P (TREE_TYPE (exp))
6511 0 : && INTEGRAL_TYPE_P (TREE_TYPE (rhs))
6512 0 : && (TYPE_PRECISION (TREE_TYPE (exp))
6513 0 : > TYPE_PRECISION (TREE_TYPE (rhs))))
6514 : exp = rhs;
6515 : }
6516 : }
6517 :
6518 94182 : val = expand_expr (exp, NULL_RTX, mode, EXPAND_NORMAL);
6519 : /* If VAL is promoted to a wider mode, convert it back to MODE. Take care
6520 : of CONST_INTs, where we know the old_mode only from the call argument. */
6521 :
6522 94182 : old_mode = GET_MODE (val);
6523 94182 : if (old_mode == VOIDmode)
6524 44268 : old_mode = TYPE_MODE (TREE_TYPE (exp));
6525 94182 : val = convert_modes (mode, old_mode, val, 1);
6526 94182 : return val;
6527 : }
6528 :
6529 :
6530 : /* Expand the __sync_xxx_and_fetch and __sync_fetch_and_xxx intrinsics.
6531 : EXP is the CALL_EXPR. CODE is the rtx code
6532 : that corresponds to the arithmetic or logical operation from the name;
6533 : an exception here is that NOT actually means NAND. TARGET is an optional
6534 : place for us to store the results; AFTER is true if this is the
6535 : fetch_and_xxx form. */
6536 :
6537 : static rtx
6538 4028 : expand_builtin_sync_operation (machine_mode mode, tree exp,
6539 : enum rtx_code code, bool after,
6540 : rtx target)
6541 : {
6542 4028 : rtx val, mem;
6543 4028 : location_t loc = EXPR_LOCATION (exp);
6544 :
6545 4028 : if (code == NOT && warn_sync_nand)
6546 : {
6547 523 : tree fndecl = get_callee_fndecl (exp);
6548 523 : enum built_in_function fcode = DECL_FUNCTION_CODE (fndecl);
6549 :
6550 523 : static bool warned_f_a_n, warned_n_a_f;
6551 :
6552 523 : switch (fcode)
6553 : {
6554 434 : case BUILT_IN_SYNC_FETCH_AND_NAND_1:
6555 434 : case BUILT_IN_SYNC_FETCH_AND_NAND_2:
6556 434 : case BUILT_IN_SYNC_FETCH_AND_NAND_4:
6557 434 : case BUILT_IN_SYNC_FETCH_AND_NAND_8:
6558 434 : case BUILT_IN_SYNC_FETCH_AND_NAND_16:
6559 434 : if (warned_f_a_n)
6560 : break;
6561 :
6562 30 : fndecl = builtin_decl_implicit (BUILT_IN_SYNC_FETCH_AND_NAND_N);
6563 30 : inform (loc, "%qD changed semantics in GCC 4.4", fndecl);
6564 30 : warned_f_a_n = true;
6565 30 : break;
6566 :
6567 89 : case BUILT_IN_SYNC_NAND_AND_FETCH_1:
6568 89 : case BUILT_IN_SYNC_NAND_AND_FETCH_2:
6569 89 : case BUILT_IN_SYNC_NAND_AND_FETCH_4:
6570 89 : case BUILT_IN_SYNC_NAND_AND_FETCH_8:
6571 89 : case BUILT_IN_SYNC_NAND_AND_FETCH_16:
6572 89 : if (warned_n_a_f)
6573 : break;
6574 :
6575 22 : fndecl = builtin_decl_implicit (BUILT_IN_SYNC_NAND_AND_FETCH_N);
6576 22 : inform (loc, "%qD changed semantics in GCC 4.4", fndecl);
6577 22 : warned_n_a_f = true;
6578 22 : break;
6579 :
6580 0 : default:
6581 0 : gcc_unreachable ();
6582 : }
6583 : }
6584 :
6585 : /* Expand the operands. */
6586 4028 : mem = get_builtin_sync_mem (CALL_EXPR_ARG (exp, 0), mode);
6587 4028 : val = expand_expr_force_mode (CALL_EXPR_ARG (exp, 1), mode);
6588 :
6589 4028 : return expand_atomic_fetch_op (target, mem, val, code, MEMMODEL_SYNC_SEQ_CST,
6590 4028 : after);
6591 : }
6592 :
6593 : /* Expand the __sync_val_compare_and_swap and __sync_bool_compare_and_swap
6594 : intrinsics. EXP is the CALL_EXPR. IS_BOOL is
6595 : true if this is the boolean form. TARGET is a place for us to store the
6596 : results; this is NOT optional if IS_BOOL is true. */
6597 :
6598 : static rtx
6599 460 : expand_builtin_compare_and_swap (machine_mode mode, tree exp,
6600 : bool is_bool, rtx target)
6601 : {
6602 460 : rtx old_val, new_val, mem;
6603 460 : rtx *pbool, *poval;
6604 :
6605 : /* Expand the operands. */
6606 460 : mem = get_builtin_sync_mem (CALL_EXPR_ARG (exp, 0), mode);
6607 460 : old_val = expand_expr_force_mode (CALL_EXPR_ARG (exp, 1), mode);
6608 460 : new_val = expand_expr_force_mode (CALL_EXPR_ARG (exp, 2), mode);
6609 :
6610 460 : pbool = poval = NULL;
6611 460 : if (target != const0_rtx)
6612 : {
6613 434 : if (is_bool)
6614 : pbool = ⌖
6615 : else
6616 230 : poval = ⌖
6617 : }
6618 460 : if (!expand_atomic_compare_and_swap (pbool, poval, mem, old_val, new_val,
6619 : false, MEMMODEL_SYNC_SEQ_CST,
6620 : MEMMODEL_SYNC_SEQ_CST))
6621 : return NULL_RTX;
6622 :
6623 458 : return target;
6624 : }
6625 :
6626 : /* Expand the __sync_lock_test_and_set intrinsic. Note that the most
6627 : general form is actually an atomic exchange, and some targets only
6628 : support a reduced form with the second argument being a constant 1.
6629 : EXP is the CALL_EXPR; TARGET is an optional place for us to store
6630 : the results. */
6631 :
6632 : static rtx
6633 326 : expand_builtin_sync_lock_test_and_set (machine_mode mode, tree exp,
6634 : rtx target)
6635 : {
6636 326 : rtx val, mem;
6637 :
6638 : /* Expand the operands. */
6639 326 : mem = get_builtin_sync_mem (CALL_EXPR_ARG (exp, 0), mode);
6640 326 : val = expand_expr_force_mode (CALL_EXPR_ARG (exp, 1), mode);
6641 :
6642 326 : return expand_sync_lock_test_and_set (target, mem, val);
6643 : }
6644 :
6645 : /* Expand the __sync_lock_release intrinsic. EXP is the CALL_EXPR. */
6646 :
6647 : static rtx
6648 146 : expand_builtin_sync_lock_release (machine_mode mode, tree exp)
6649 : {
6650 146 : rtx mem;
6651 :
6652 : /* Expand the operands. */
6653 146 : mem = get_builtin_sync_mem (CALL_EXPR_ARG (exp, 0), mode);
6654 :
6655 146 : return expand_atomic_store (mem, const0_rtx, MEMMODEL_SYNC_RELEASE, true);
6656 : }
6657 :
6658 : /* Given an integer representing an ``enum memmodel'', verify its
6659 : correctness and return the memory model enum. */
6660 :
6661 : static enum memmodel
6662 169300 : get_memmodel (tree exp)
6663 : {
6664 : /* If the parameter is not a constant, it's a run time value so we'll just
6665 : convert it to MEMMODEL_SEQ_CST to avoid annoying runtime checking. */
6666 169300 : if (TREE_CODE (exp) != INTEGER_CST)
6667 : return MEMMODEL_SEQ_CST;
6668 :
6669 168473 : rtx op = expand_normal (exp);
6670 :
6671 168473 : unsigned HOST_WIDE_INT val = INTVAL (op);
6672 168473 : if (targetm.memmodel_check)
6673 168473 : val = targetm.memmodel_check (val);
6674 0 : else if (val & ~MEMMODEL_MASK)
6675 : return MEMMODEL_SEQ_CST;
6676 :
6677 : /* Should never see a user explicit SYNC memodel model, so >= LAST works. */
6678 168473 : if (memmodel_base (val) >= MEMMODEL_LAST)
6679 : return MEMMODEL_SEQ_CST;
6680 :
6681 : /* Workaround for Bugzilla 59448. GCC doesn't track consume properly, so
6682 : be conservative and promote consume to acquire. */
6683 168470 : if (val == MEMMODEL_CONSUME)
6684 755 : val = MEMMODEL_ACQUIRE;
6685 :
6686 168470 : return (enum memmodel) val;
6687 : }
6688 :
6689 : /* Expand the __atomic_exchange intrinsic:
6690 : TYPE __atomic_exchange (TYPE *object, TYPE desired, enum memmodel)
6691 : EXP is the CALL_EXPR.
6692 : TARGET is an optional place for us to store the results. */
6693 :
6694 : static rtx
6695 2937 : expand_builtin_atomic_exchange (machine_mode mode, tree exp, rtx target)
6696 : {
6697 2937 : rtx val, mem;
6698 2937 : enum memmodel model;
6699 :
6700 2937 : model = get_memmodel (CALL_EXPR_ARG (exp, 2));
6701 :
6702 2937 : if (!flag_inline_atomics)
6703 : return NULL_RTX;
6704 :
6705 : /* Expand the operands. */
6706 2886 : mem = get_builtin_sync_mem (CALL_EXPR_ARG (exp, 0), mode);
6707 2886 : val = expand_expr_force_mode (CALL_EXPR_ARG (exp, 1), mode);
6708 :
6709 2886 : return expand_atomic_exchange (target, mem, val, model);
6710 : }
6711 :
6712 : /* Expand the __atomic_compare_exchange intrinsic:
6713 : bool __atomic_compare_exchange (TYPE *object, TYPE *expect,
6714 : TYPE desired, BOOL weak,
6715 : enum memmodel success,
6716 : enum memmodel failure)
6717 : EXP is the CALL_EXPR.
6718 : TARGET is an optional place for us to store the results. */
6719 :
6720 : static rtx
6721 9129 : expand_builtin_atomic_compare_exchange (machine_mode mode, tree exp,
6722 : rtx target)
6723 : {
6724 9129 : rtx expect, desired, mem, oldval;
6725 9129 : rtx_code_label *label;
6726 9129 : tree weak;
6727 9129 : bool is_weak;
6728 :
6729 9129 : memmodel success = get_memmodel (CALL_EXPR_ARG (exp, 4));
6730 9129 : memmodel failure = get_memmodel (CALL_EXPR_ARG (exp, 5));
6731 :
6732 9129 : if (failure > success)
6733 22 : success = MEMMODEL_SEQ_CST;
6734 :
6735 9129 : if (is_mm_release (failure) || is_mm_acq_rel (failure))
6736 : {
6737 : failure = MEMMODEL_SEQ_CST;
6738 : success = MEMMODEL_SEQ_CST;
6739 : }
6740 :
6741 :
6742 9129 : if (!flag_inline_atomics)
6743 : return NULL_RTX;
6744 :
6745 : /* Expand the operands. */
6746 9078 : mem = get_builtin_sync_mem (CALL_EXPR_ARG (exp, 0), mode);
6747 :
6748 9078 : expect = expand_normal (CALL_EXPR_ARG (exp, 1));
6749 9114 : expect = convert_memory_address (Pmode, expect);
6750 9078 : expect = gen_rtx_MEM (mode, expect);
6751 9078 : desired = expand_expr_force_mode (CALL_EXPR_ARG (exp, 2), mode);
6752 :
6753 9078 : weak = CALL_EXPR_ARG (exp, 3);
6754 9078 : is_weak = false;
6755 9078 : if (tree_fits_shwi_p (weak) && tree_to_shwi (weak) != 0)
6756 9078 : is_weak = true;
6757 :
6758 9078 : if (target == const0_rtx)
6759 287 : target = NULL;
6760 :
6761 : /* Lest the rtl backend create a race condition with an imporoper store
6762 : to memory, always create a new pseudo for OLDVAL. */
6763 9078 : oldval = NULL;
6764 :
6765 9078 : if (!expand_atomic_compare_and_swap (&target, &oldval, mem, expect, desired,
6766 : is_weak, success, failure))
6767 : return NULL_RTX;
6768 :
6769 : /* Conditionally store back to EXPECT, lest we create a race condition
6770 : with an improper store to memory. */
6771 : /* ??? With a rearrangement of atomics at the gimple level, we can handle
6772 : the normal case where EXPECT is totally private, i.e. a register. At
6773 : which point the store can be unconditional. */
6774 7329 : label = gen_label_rtx ();
6775 7329 : emit_cmp_and_jump_insns (target, const0_rtx, NE, NULL,
6776 7329 : GET_MODE (target), 1, label);
6777 7329 : emit_move_insn (expect, oldval);
6778 7329 : emit_label (label);
6779 :
6780 7329 : return target;
6781 : }
6782 :
6783 : /* Helper function for expand_ifn_atomic_compare_exchange - expand
6784 : internal ATOMIC_COMPARE_EXCHANGE call into __atomic_compare_exchange_N
6785 : call. The weak parameter must be dropped to match the expected parameter
6786 : list and the expected argument changed from value to pointer to memory
6787 : slot. */
6788 :
6789 : static void
6790 0 : expand_ifn_atomic_compare_exchange_into_call (gcall *call, machine_mode mode)
6791 : {
6792 0 : unsigned int z;
6793 0 : vec<tree, va_gc> *vec;
6794 :
6795 0 : vec_alloc (vec, 5);
6796 0 : vec->quick_push (gimple_call_arg (call, 0));
6797 0 : tree expected = gimple_call_arg (call, 1);
6798 0 : rtx x = assign_stack_temp_for_type (mode, GET_MODE_SIZE (mode),
6799 0 : TREE_TYPE (expected));
6800 0 : rtx expd = expand_expr (expected, x, mode, EXPAND_NORMAL);
6801 0 : if (expd != x)
6802 0 : emit_move_insn (x, expd);
6803 0 : tree v = make_tree (TREE_TYPE (expected), x);
6804 0 : vec->quick_push (build1 (ADDR_EXPR,
6805 0 : build_pointer_type (TREE_TYPE (expected)), v));
6806 0 : vec->quick_push (gimple_call_arg (call, 2));
6807 : /* Skip the boolean weak parameter. */
6808 0 : for (z = 4; z < 6; z++)
6809 0 : vec->quick_push (gimple_call_arg (call, z));
6810 : /* At present we only have BUILT_IN_ATOMIC_COMPARE_EXCHANGE_{1,2,4,8,16}. */
6811 0 : unsigned int bytes_log2 = exact_log2 (GET_MODE_SIZE (mode).to_constant ());
6812 0 : gcc_assert (bytes_log2 < 5);
6813 0 : built_in_function fncode
6814 : = (built_in_function) ((int) BUILT_IN_ATOMIC_COMPARE_EXCHANGE_1
6815 : + bytes_log2);
6816 0 : tree fndecl = builtin_decl_explicit (fncode);
6817 0 : tree fn = build1 (ADDR_EXPR, build_pointer_type (TREE_TYPE (fndecl)),
6818 : fndecl);
6819 0 : tree exp = build_call_vec (boolean_type_node, fn, vec);
6820 0 : tree lhs = gimple_call_lhs (call);
6821 0 : rtx boolret = expand_call (exp, NULL_RTX, lhs == NULL_TREE);
6822 0 : if (lhs)
6823 : {
6824 0 : rtx target = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
6825 0 : if (GET_MODE (boolret) != mode)
6826 0 : boolret = convert_modes (mode, GET_MODE (boolret), boolret, 1);
6827 0 : x = force_reg (mode, x);
6828 0 : write_complex_part (target, boolret, true, true);
6829 0 : write_complex_part (target, x, false, false);
6830 : }
6831 0 : }
6832 :
6833 : /* Expand IFN_ATOMIC_COMPARE_EXCHANGE internal function. */
6834 :
6835 : void
6836 13946 : expand_ifn_atomic_compare_exchange (gcall *call)
6837 : {
6838 13946 : int size = tree_to_shwi (gimple_call_arg (call, 3)) & 255;
6839 13946 : gcc_assert (size == 1 || size == 2 || size == 4 || size == 8 || size == 16);
6840 13946 : machine_mode mode = int_mode_for_size (BITS_PER_UNIT * size, 0).require ();
6841 :
6842 13946 : memmodel success = get_memmodel (gimple_call_arg (call, 4));
6843 13946 : memmodel failure = get_memmodel (gimple_call_arg (call, 5));
6844 :
6845 13946 : if (failure > success)
6846 0 : success = MEMMODEL_SEQ_CST;
6847 :
6848 13946 : if (is_mm_release (failure) || is_mm_acq_rel (failure))
6849 : {
6850 : failure = MEMMODEL_SEQ_CST;
6851 : success = MEMMODEL_SEQ_CST;
6852 : }
6853 :
6854 13946 : if (!flag_inline_atomics)
6855 : {
6856 0 : expand_ifn_atomic_compare_exchange_into_call (call, mode);
6857 0 : return;
6858 : }
6859 :
6860 : /* Expand the operands. */
6861 13946 : rtx mem = get_builtin_sync_mem (gimple_call_arg (call, 0), mode);
6862 :
6863 13946 : rtx expect = expand_expr_force_mode (gimple_call_arg (call, 1), mode);
6864 13946 : rtx desired = expand_expr_force_mode (gimple_call_arg (call, 2), mode);
6865 :
6866 13946 : bool is_weak = (tree_to_shwi (gimple_call_arg (call, 3)) & 256) != 0;
6867 :
6868 13946 : rtx boolret = NULL;
6869 13946 : rtx oldval = NULL;
6870 :
6871 13946 : if (!expand_atomic_compare_and_swap (&boolret, &oldval, mem, expect, desired,
6872 : is_weak, success, failure))
6873 : {
6874 0 : expand_ifn_atomic_compare_exchange_into_call (call, mode);
6875 0 : return;
6876 : }
6877 :
6878 13946 : tree lhs = gimple_call_lhs (call);
6879 13946 : if (lhs)
6880 : {
6881 13738 : rtx target = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
6882 13738 : if (GET_MODE (boolret) != mode)
6883 12290 : boolret = convert_modes (mode, GET_MODE (boolret), boolret, 1);
6884 13738 : write_complex_part (target, boolret, true, true);
6885 13738 : write_complex_part (target, oldval, false, false);
6886 : }
6887 : }
6888 :
6889 : /* Expand the __atomic_load intrinsic:
6890 : TYPE __atomic_load (TYPE *object, enum memmodel)
6891 : EXP is the CALL_EXPR.
6892 : TARGET is an optional place for us to store the results. */
6893 :
6894 : static rtx
6895 70597 : expand_builtin_atomic_load (machine_mode mode, tree exp, rtx target)
6896 : {
6897 70597 : memmodel model = get_memmodel (CALL_EXPR_ARG (exp, 1));
6898 70597 : if (is_mm_release (model) || is_mm_acq_rel (model))
6899 : model = MEMMODEL_SEQ_CST;
6900 :
6901 70597 : if (!flag_inline_atomics)
6902 : return NULL_RTX;
6903 :
6904 : /* Expand the operand. */
6905 70556 : rtx mem = get_builtin_sync_mem (CALL_EXPR_ARG (exp, 0), mode);
6906 :
6907 70556 : return expand_atomic_load (target, mem, model);
6908 : }
6909 :
6910 :
6911 : /* Expand the __atomic_store intrinsic:
6912 : void __atomic_store (TYPE *object, TYPE desired, enum memmodel)
6913 : EXP is the CALL_EXPR.
6914 : TARGET is an optional place for us to store the results. */
6915 :
6916 : static rtx
6917 17465 : expand_builtin_atomic_store (machine_mode mode, tree exp)
6918 : {
6919 17465 : memmodel model = get_memmodel (CALL_EXPR_ARG (exp, 2));
6920 17465 : if (!(is_mm_relaxed (model) || is_mm_seq_cst (model)
6921 1592 : || is_mm_release (model)))
6922 : model = MEMMODEL_SEQ_CST;
6923 :
6924 17465 : if (!flag_inline_atomics)
6925 : return NULL_RTX;
6926 :
6927 : /* Expand the operands. */
6928 17434 : rtx mem = get_builtin_sync_mem (CALL_EXPR_ARG (exp, 0), mode);
6929 17434 : rtx val = expand_expr_force_mode (CALL_EXPR_ARG (exp, 1), mode);
6930 :
6931 17434 : return expand_atomic_store (mem, val, model, false);
6932 : }
6933 :
6934 : /* Expand the __atomic_fetch_XXX intrinsic:
6935 : TYPE __atomic_fetch_XXX (TYPE *object, TYPE val, enum memmodel)
6936 : EXP is the CALL_EXPR.
6937 : TARGET is an optional place for us to store the results.
6938 : CODE is the operation, PLUS, MINUS, ADD, XOR, or IOR.
6939 : FETCH_AFTER is true if returning the result of the operation.
6940 : FETCH_AFTER is false if returning the value before the operation.
6941 : IGNORE is true if the result is not used.
6942 : EXT_CALL is the correct builtin for an external call if this cannot be
6943 : resolved to an instruction sequence. */
6944 :
6945 : static rtx
6946 29043 : expand_builtin_atomic_fetch_op (machine_mode mode, tree exp, rtx target,
6947 : enum rtx_code code, bool fetch_after,
6948 : bool ignore, enum built_in_function ext_call)
6949 : {
6950 29043 : rtx val, mem, ret;
6951 29043 : enum memmodel model;
6952 29043 : tree fndecl;
6953 29043 : tree addr;
6954 :
6955 29043 : model = get_memmodel (CALL_EXPR_ARG (exp, 2));
6956 :
6957 : /* Expand the operands. */
6958 29043 : mem = get_builtin_sync_mem (CALL_EXPR_ARG (exp, 0), mode);
6959 29043 : val = expand_expr_force_mode (CALL_EXPR_ARG (exp, 1), mode);
6960 :
6961 : /* Only try generating instructions if inlining is turned on. */
6962 29043 : if (flag_inline_atomics)
6963 : {
6964 28500 : ret = expand_atomic_fetch_op (target, mem, val, code, model, fetch_after);
6965 28500 : if (ret)
6966 : return ret;
6967 : }
6968 :
6969 : /* Return if a different routine isn't needed for the library call. */
6970 1158 : if (ext_call == BUILT_IN_NONE)
6971 : return NULL_RTX;
6972 :
6973 : /* Change the call to the specified function. */
6974 287 : fndecl = get_callee_fndecl (exp);
6975 287 : addr = CALL_EXPR_FN (exp);
6976 287 : STRIP_NOPS (addr);
6977 :
6978 287 : gcc_assert (TREE_OPERAND (addr, 0) == fndecl);
6979 287 : TREE_OPERAND (addr, 0) = builtin_decl_explicit (ext_call);
6980 :
6981 : /* If we will emit code after the call, the call cannot be a tail call.
6982 : If it is emitted as a tail call, a barrier is emitted after it, and
6983 : then all trailing code is removed. */
6984 287 : if (!ignore)
6985 190 : CALL_EXPR_TAILCALL (exp) = 0;
6986 :
6987 : /* Expand the call here so we can emit trailing code. */
6988 287 : ret = expand_call (exp, target, ignore);
6989 :
6990 : /* Replace the original function just in case it matters. */
6991 287 : TREE_OPERAND (addr, 0) = fndecl;
6992 :
6993 : /* Then issue the arithmetic correction to return the right result. */
6994 287 : if (!ignore)
6995 : {
6996 190 : if (code == NOT)
6997 : {
6998 33 : ret = expand_simple_binop (mode, AND, ret, val, NULL_RTX, true,
6999 : OPTAB_LIB_WIDEN);
7000 33 : ret = expand_simple_unop (mode, NOT, ret, target, true);
7001 : }
7002 : else
7003 157 : ret = expand_simple_binop (mode, code, ret, val, target, true,
7004 : OPTAB_LIB_WIDEN);
7005 : }
7006 : return ret;
7007 : }
7008 :
7009 : /* Expand IFN_ATOMIC_BIT_TEST_AND_* internal function. */
7010 :
7011 : void
7012 427 : expand_ifn_atomic_bit_test_and (gcall *call)
7013 : {
7014 427 : tree ptr = gimple_call_arg (call, 0);
7015 427 : tree bit = gimple_call_arg (call, 1);
7016 427 : tree flag = gimple_call_arg (call, 2);
7017 427 : tree lhs = gimple_call_lhs (call);
7018 427 : enum memmodel model = MEMMODEL_SYNC_SEQ_CST;
7019 427 : machine_mode mode = TYPE_MODE (TREE_TYPE (flag));
7020 427 : enum rtx_code code;
7021 427 : optab optab;
7022 427 : class expand_operand ops[5];
7023 :
7024 427 : gcc_assert (flag_inline_atomics);
7025 :
7026 427 : if (gimple_call_num_args (call) == 5)
7027 296 : model = get_memmodel (gimple_call_arg (call, 3));
7028 :
7029 427 : rtx mem = get_builtin_sync_mem (ptr, mode);
7030 427 : rtx val = expand_expr_force_mode (bit, mode);
7031 :
7032 427 : switch (gimple_call_internal_fn (call))
7033 : {
7034 : case IFN_ATOMIC_BIT_TEST_AND_SET:
7035 : code = IOR;
7036 : optab = atomic_bit_test_and_set_optab;
7037 : break;
7038 : case IFN_ATOMIC_BIT_TEST_AND_COMPLEMENT:
7039 : code = XOR;
7040 : optab = atomic_bit_test_and_complement_optab;
7041 : break;
7042 : case IFN_ATOMIC_BIT_TEST_AND_RESET:
7043 : code = AND;
7044 : optab = atomic_bit_test_and_reset_optab;
7045 : break;
7046 0 : default:
7047 0 : gcc_unreachable ();
7048 : }
7049 :
7050 427 : if (lhs == NULL_TREE)
7051 : {
7052 0 : rtx val2 = expand_simple_binop (mode, ASHIFT, const1_rtx,
7053 : val, NULL_RTX, true, OPTAB_DIRECT);
7054 0 : if (code == AND)
7055 0 : val2 = expand_simple_unop (mode, NOT, val2, NULL_RTX, true);
7056 0 : if (expand_atomic_fetch_op (const0_rtx, mem, val2, code, model, false))
7057 427 : return;
7058 : }
7059 :
7060 0 : rtx target;
7061 0 : if (lhs)
7062 427 : target = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
7063 : else
7064 0 : target = gen_reg_rtx (mode);
7065 427 : enum insn_code icode = direct_optab_handler (optab, mode);
7066 427 : gcc_assert (icode != CODE_FOR_nothing);
7067 427 : create_output_operand (&ops[0], target, mode);
7068 427 : create_fixed_operand (&ops[1], mem);
7069 427 : create_convert_operand_to (&ops[2], val, mode, true);
7070 427 : create_integer_operand (&ops[3], model);
7071 427 : create_integer_operand (&ops[4], integer_onep (flag));
7072 427 : if (maybe_expand_insn (icode, 5, ops))
7073 : return;
7074 :
7075 0 : rtx bitval = val;
7076 0 : val = expand_simple_binop (mode, ASHIFT, const1_rtx,
7077 : val, NULL_RTX, true, OPTAB_DIRECT);
7078 0 : rtx maskval = val;
7079 0 : if (code == AND)
7080 0 : val = expand_simple_unop (mode, NOT, val, NULL_RTX, true);
7081 0 : rtx result = expand_atomic_fetch_op (gen_reg_rtx (mode), mem, val,
7082 : code, model, false);
7083 0 : if (!result)
7084 : {
7085 0 : bool is_atomic = gimple_call_num_args (call) == 5;
7086 0 : tree tcall = gimple_call_arg (call, 3 + is_atomic);
7087 0 : tree fndecl = gimple_call_addr_fndecl (tcall);
7088 0 : tree type = TREE_TYPE (TREE_TYPE (fndecl));
7089 0 : tree exp;
7090 0 : if (is_atomic)
7091 0 : exp = build_call_nary (type, tcall, 3,
7092 : ptr, make_tree (type, val),
7093 : gimple_call_arg (call, 3));
7094 : else
7095 0 : exp = build_call_nary (type, tcall, 2, ptr, make_tree (type, val));
7096 0 : result = expand_builtin (exp, gen_reg_rtx (mode), NULL_RTX,
7097 : mode, !lhs);
7098 : }
7099 0 : if (!lhs)
7100 : return;
7101 0 : if (integer_onep (flag))
7102 : {
7103 0 : result = expand_simple_binop (mode, ASHIFTRT, result, bitval,
7104 : NULL_RTX, true, OPTAB_DIRECT);
7105 0 : result = expand_simple_binop (mode, AND, result, const1_rtx, target,
7106 : true, OPTAB_DIRECT);
7107 : }
7108 : else
7109 0 : result = expand_simple_binop (mode, AND, result, maskval, target, true,
7110 : OPTAB_DIRECT);
7111 0 : if (result != target)
7112 0 : emit_move_insn (target, result);
7113 : }
7114 :
7115 : /* Expand IFN_ATOMIC_*_FETCH_CMP_0 internal function. */
7116 :
7117 : void
7118 2148 : expand_ifn_atomic_op_fetch_cmp_0 (gcall *call)
7119 : {
7120 2148 : tree cmp = gimple_call_arg (call, 0);
7121 2148 : tree ptr = gimple_call_arg (call, 1);
7122 2148 : tree arg = gimple_call_arg (call, 2);
7123 2148 : tree lhs = gimple_call_lhs (call);
7124 2148 : enum memmodel model = MEMMODEL_SYNC_SEQ_CST;
7125 2148 : machine_mode mode = TYPE_MODE (TREE_TYPE (cmp));
7126 2148 : optab optab;
7127 2148 : rtx_code code;
7128 2148 : class expand_operand ops[5];
7129 :
7130 2148 : gcc_assert (flag_inline_atomics);
7131 :
7132 2148 : if (gimple_call_num_args (call) == 5)
7133 1740 : model = get_memmodel (gimple_call_arg (call, 3));
7134 :
7135 2148 : rtx mem = get_builtin_sync_mem (ptr, mode);
7136 2148 : rtx op = expand_expr_force_mode (arg, mode);
7137 :
7138 2148 : switch (gimple_call_internal_fn (call))
7139 : {
7140 : case IFN_ATOMIC_ADD_FETCH_CMP_0:
7141 : code = PLUS;
7142 : optab = atomic_add_fetch_cmp_0_optab;
7143 : break;
7144 : case IFN_ATOMIC_SUB_FETCH_CMP_0:
7145 : code = MINUS;
7146 : optab = atomic_sub_fetch_cmp_0_optab;
7147 : break;
7148 : case IFN_ATOMIC_AND_FETCH_CMP_0:
7149 : code = AND;
7150 : optab = atomic_and_fetch_cmp_0_optab;
7151 : break;
7152 : case IFN_ATOMIC_OR_FETCH_CMP_0:
7153 : code = IOR;
7154 : optab = atomic_or_fetch_cmp_0_optab;
7155 : break;
7156 : case IFN_ATOMIC_XOR_FETCH_CMP_0:
7157 : code = XOR;
7158 : optab = atomic_xor_fetch_cmp_0_optab;
7159 : break;
7160 0 : default:
7161 0 : gcc_unreachable ();
7162 : }
7163 :
7164 2148 : enum rtx_code comp = UNKNOWN;
7165 2148 : switch (tree_to_uhwi (cmp))
7166 : {
7167 : case ATOMIC_OP_FETCH_CMP_0_EQ: comp = EQ; break;
7168 : case ATOMIC_OP_FETCH_CMP_0_NE: comp = NE; break;
7169 : case ATOMIC_OP_FETCH_CMP_0_GT: comp = GT; break;
7170 : case ATOMIC_OP_FETCH_CMP_0_GE: comp = GE; break;
7171 : case ATOMIC_OP_FETCH_CMP_0_LT: comp = LT; break;
7172 : case ATOMIC_OP_FETCH_CMP_0_LE: comp = LE; break;
7173 0 : default: gcc_unreachable ();
7174 : }
7175 :
7176 2148 : rtx target;
7177 2148 : if (lhs == NULL_TREE)
7178 0 : target = gen_reg_rtx (TYPE_MODE (boolean_type_node));
7179 : else
7180 2148 : target = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
7181 2148 : enum insn_code icode = direct_optab_handler (optab, mode);
7182 2148 : gcc_assert (icode != CODE_FOR_nothing);
7183 2148 : create_output_operand (&ops[0], target, TYPE_MODE (boolean_type_node));
7184 2148 : create_fixed_operand (&ops[1], mem);
7185 2148 : create_convert_operand_to (&ops[2], op, mode, true);
7186 2148 : create_integer_operand (&ops[3], model);
7187 2148 : create_integer_operand (&ops[4], comp);
7188 2148 : if (maybe_expand_insn (icode, 5, ops))
7189 2116 : return;
7190 :
7191 32 : rtx result = expand_atomic_fetch_op (gen_reg_rtx (mode), mem, op,
7192 : code, model, true);
7193 32 : if (!result)
7194 : {
7195 0 : bool is_atomic = gimple_call_num_args (call) == 5;
7196 0 : tree tcall = gimple_call_arg (call, 3 + is_atomic);
7197 0 : tree fndecl = gimple_call_addr_fndecl (tcall);
7198 0 : tree type = TREE_TYPE (TREE_TYPE (fndecl));
7199 0 : tree exp;
7200 0 : if (is_atomic)
7201 0 : exp = build_call_nary (type, tcall, 3,
7202 : ptr, arg,
7203 : gimple_call_arg (call, 3));
7204 : else
7205 0 : exp = build_call_nary (type, tcall, 2, ptr, arg);
7206 0 : result = expand_builtin (exp, gen_reg_rtx (mode), NULL_RTX,
7207 : mode, !lhs);
7208 : }
7209 :
7210 32 : if (lhs)
7211 : {
7212 32 : result = emit_store_flag_force (target, comp, result, const0_rtx, mode,
7213 : 0, 1);
7214 32 : if (result != target)
7215 32 : emit_move_insn (target, result);
7216 : }
7217 : }
7218 :
7219 : /* Expand an atomic clear operation.
7220 : void _atomic_clear (BOOL *obj, enum memmodel)
7221 : EXP is the call expression. */
7222 :
7223 : static rtx
7224 53 : expand_builtin_atomic_clear (tree exp)
7225 : {
7226 53 : machine_mode mode = int_mode_for_size (BOOL_TYPE_SIZE, 0).require ();
7227 53 : rtx mem = get_builtin_sync_mem (CALL_EXPR_ARG (exp, 0), mode);
7228 53 : memmodel model = get_memmodel (CALL_EXPR_ARG (exp, 1));
7229 :
7230 53 : if (is_mm_consume (model) || is_mm_acquire (model) || is_mm_acq_rel (model))
7231 : model = MEMMODEL_SEQ_CST;
7232 :
7233 : /* Try issuing an __atomic_store, and allow fallback to __sync_lock_release.
7234 : Failing that, a store is issued by __atomic_store. The only way this can
7235 : fail is if the bool type is larger than a word size. Unlikely, but
7236 : handle it anyway for completeness. Assume a single threaded model since
7237 : there is no atomic support in this case, and no barriers are required. */
7238 53 : rtx ret = expand_atomic_store (mem, const0_rtx, model, true);
7239 53 : if (!ret)
7240 0 : emit_move_insn (mem, const0_rtx);
7241 53 : return const0_rtx;
7242 : }
7243 :
7244 : /* Expand an atomic test_and_set operation.
7245 : bool _atomic_test_and_set (BOOL *obj, enum memmodel)
7246 : EXP is the call expression. */
7247 :
7248 : static rtx
7249 266 : expand_builtin_atomic_test_and_set (tree exp, rtx target)
7250 : {
7251 266 : rtx mem;
7252 266 : enum memmodel model;
7253 266 : machine_mode mode;
7254 :
7255 266 : mode = int_mode_for_size (BOOL_TYPE_SIZE, 0).require ();
7256 266 : mem = get_builtin_sync_mem (CALL_EXPR_ARG (exp, 0), mode);
7257 266 : model = get_memmodel (CALL_EXPR_ARG (exp, 1));
7258 :
7259 266 : return expand_atomic_test_and_set (target, mem, model);
7260 : }
7261 :
7262 :
7263 : /* Return true if (optional) argument ARG1 of size ARG0 is always lock free on
7264 : this architecture. If ARG1 is NULL, use typical alignment for size ARG0. */
7265 :
7266 : static tree
7267 144319 : fold_builtin_atomic_always_lock_free (tree arg0, tree arg1)
7268 : {
7269 144319 : HOST_WIDE_INT size;
7270 144319 : machine_mode mode;
7271 144319 : unsigned int mode_align, type_align;
7272 :
7273 144319 : if (!tree_fits_shwi_p (arg0))
7274 : return NULL_TREE;
7275 :
7276 : /* We need a corresponding integer mode for the access to be lock-free. */
7277 144166 : size = tree_to_shwi (arg0) * BITS_PER_UNIT;
7278 144166 : if (!int_mode_for_size (size, 0).exists (&mode))
7279 9 : return boolean_false_node;
7280 :
7281 144157 : mode_align = GET_MODE_ALIGNMENT (mode);
7282 :
7283 144157 : if (tree_fits_uhwi_p (arg1))
7284 : {
7285 124415 : unsigned HOST_WIDE_INT val = tree_to_uhwi (arg1);
7286 :
7287 : /* Either this argument is null, or it's a fake pointer encoding
7288 : the alignment of the object. */
7289 124415 : val = least_bit_hwi (val);
7290 124415 : val *= BITS_PER_UNIT;
7291 :
7292 124415 : if (val == 0 || mode_align < val)
7293 : type_align = mode_align;
7294 : else
7295 18985 : type_align = val;
7296 : }
7297 : else
7298 : {
7299 19742 : tree ttype = TREE_TYPE (arg1);
7300 :
7301 : /* This function is usually invoked and folded immediately by the front
7302 : end before anything else has a chance to look at it. The pointer
7303 : parameter at this point is usually cast to a void *, so check for that
7304 : and look past the cast. */
7305 195 : if (CONVERT_EXPR_P (arg1)
7306 19578 : && POINTER_TYPE_P (ttype)
7307 19578 : && VOID_TYPE_P (TREE_TYPE (ttype))
7308 39320 : && POINTER_TYPE_P (TREE_TYPE (TREE_OPERAND (arg1, 0))))
7309 19547 : arg1 = TREE_OPERAND (arg1, 0);
7310 :
7311 19742 : ttype = TREE_TYPE (arg1);
7312 19742 : gcc_assert (POINTER_TYPE_P (ttype));
7313 :
7314 : /* Get the underlying type of the object. */
7315 19742 : ttype = TREE_TYPE (ttype);
7316 19742 : type_align = TYPE_ALIGN (ttype);
7317 : }
7318 :
7319 : /* If the object has smaller alignment, the lock free routines cannot
7320 : be used. */
7321 144157 : if (type_align < mode_align)
7322 247 : return boolean_false_node;
7323 :
7324 : /* Check if a compare_and_swap pattern exists for the mode which represents
7325 : the required size. The pattern is not allowed to fail, so the existence
7326 : of the pattern indicates support is present. Also require that an
7327 : atomic load exists for the required size. */
7328 143910 : if (can_compare_and_swap_p (mode, true) && can_atomic_load_p (mode))
7329 143868 : return boolean_true_node;
7330 : else
7331 42 : return boolean_false_node;
7332 : }
7333 :
7334 : /* Return true if the parameters to call EXP represent an object which will
7335 : always generate lock free instructions. The first argument represents the
7336 : size of the object, and the second parameter is a pointer to the object
7337 : itself. If NULL is passed for the object, then the result is based on
7338 : typical alignment for an object of the specified size. Otherwise return
7339 : false. */
7340 :
7341 : static rtx
7342 1 : expand_builtin_atomic_always_lock_free (tree exp)
7343 : {
7344 1 : tree size;
7345 1 : tree arg0 = CALL_EXPR_ARG (exp, 0);
7346 1 : tree arg1 = CALL_EXPR_ARG (exp, 1);
7347 :
7348 1 : if (TREE_CODE (arg0) != INTEGER_CST)
7349 : {
7350 1 : error ("non-constant argument 1 to %qs", "__atomic_always_lock_free");
7351 1 : return const0_rtx;
7352 : }
7353 :
7354 0 : size = fold_builtin_atomic_always_lock_free (arg0, arg1);
7355 0 : if (size == boolean_true_node)
7356 0 : return const1_rtx;
7357 0 : return const0_rtx;
7358 : }
7359 :
7360 : /* Return a one or zero if it can be determined that object ARG1 of size ARG
7361 : is lock free on this architecture. */
7362 :
7363 : static tree
7364 38826 : fold_builtin_atomic_is_lock_free (tree arg0, tree arg1)
7365 : {
7366 38826 : if (!flag_inline_atomics)
7367 : return NULL_TREE;
7368 :
7369 : /* If it isn't always lock free, don't generate a result. */
7370 38817 : if (fold_builtin_atomic_always_lock_free (arg0, arg1) == boolean_true_node)
7371 38458 : return boolean_true_node;
7372 :
7373 : return NULL_TREE;
7374 : }
7375 :
7376 : /* Return true if the parameters to call EXP represent an object which will
7377 : always generate lock free instructions. The first argument represents the
7378 : size of the object, and the second parameter is a pointer to the object
7379 : itself. If NULL is passed for the object, then the result is based on
7380 : typical alignment for an object of the specified size. Otherwise return
7381 : NULL*/
7382 :
7383 : static rtx
7384 10 : expand_builtin_atomic_is_lock_free (tree exp)
7385 : {
7386 10 : tree size;
7387 10 : tree arg0 = CALL_EXPR_ARG (exp, 0);
7388 10 : tree arg1 = CALL_EXPR_ARG (exp, 1);
7389 :
7390 10 : if (!INTEGRAL_TYPE_P (TREE_TYPE (arg0)))
7391 : {
7392 0 : error ("non-integer argument 1 to %qs", "__atomic_is_lock_free");
7393 0 : return NULL_RTX;
7394 : }
7395 :
7396 10 : if (!flag_inline_atomics)
7397 : return NULL_RTX;
7398 :
7399 : /* If the value is known at compile time, return the RTX for it. */
7400 9 : size = fold_builtin_atomic_is_lock_free (arg0, arg1);
7401 9 : if (size == boolean_true_node)
7402 0 : return const1_rtx;
7403 :
7404 : return NULL_RTX;
7405 : }
7406 :
7407 : /* Expand the __atomic_thread_fence intrinsic:
7408 : void __atomic_thread_fence (enum memmodel)
7409 : EXP is the CALL_EXPR. */
7410 :
7411 : static void
7412 693 : expand_builtin_atomic_thread_fence (tree exp)
7413 : {
7414 693 : enum memmodel model = get_memmodel (CALL_EXPR_ARG (exp, 0));
7415 693 : expand_mem_thread_fence (model);
7416 693 : }
7417 :
7418 : /* Expand the __atomic_signal_fence intrinsic:
7419 : void __atomic_signal_fence (enum memmodel)
7420 : EXP is the CALL_EXPR. */
7421 :
7422 : static void
7423 60 : expand_builtin_atomic_signal_fence (tree exp)
7424 : {
7425 60 : enum memmodel model = get_memmodel (CALL_EXPR_ARG (exp, 0));
7426 60 : expand_mem_signal_fence (model);
7427 60 : }
7428 :
7429 : /* Expand the __sync_synchronize intrinsic. */
7430 :
7431 : static void
7432 273 : expand_builtin_sync_synchronize (void)
7433 : {
7434 0 : expand_mem_thread_fence (MEMMODEL_SYNC_SEQ_CST);
7435 0 : }
7436 :
7437 : static rtx
7438 3 : expand_builtin_thread_pointer (tree exp, rtx target)
7439 : {
7440 3 : enum insn_code icode;
7441 3 : if (!validate_arglist (exp, VOID_TYPE))
7442 0 : return const0_rtx;
7443 3 : icode = direct_optab_handler (get_thread_pointer_optab, Pmode);
7444 3 : if (icode != CODE_FOR_nothing)
7445 : {
7446 3 : class expand_operand op;
7447 : /* If the target is not sutitable then create a new target. */
7448 3 : if (target == NULL_RTX
7449 3 : || !REG_P (target)
7450 6 : || GET_MODE (target) != Pmode)
7451 0 : target = gen_reg_rtx (Pmode);
7452 3 : create_output_operand (&op, target, Pmode);
7453 3 : expand_insn (icode, 1, &op);
7454 3 : return target;
7455 : }
7456 0 : error ("%<__builtin_thread_pointer%> is not supported on this target");
7457 0 : return const0_rtx;
7458 : }
7459 :
7460 : static void
7461 0 : expand_builtin_set_thread_pointer (tree exp)
7462 : {
7463 0 : enum insn_code icode;
7464 0 : if (!validate_arglist (exp, POINTER_TYPE, VOID_TYPE))
7465 : return;
7466 0 : icode = direct_optab_handler (set_thread_pointer_optab, Pmode);
7467 0 : if (icode != CODE_FOR_nothing)
7468 : {
7469 0 : class expand_operand op;
7470 0 : rtx val = expand_expr (CALL_EXPR_ARG (exp, 0), NULL_RTX,
7471 0 : Pmode, EXPAND_NORMAL);
7472 0 : create_input_operand (&op, val, Pmode);
7473 0 : expand_insn (icode, 1, &op);
7474 0 : return;
7475 : }
7476 0 : error ("%<__builtin_set_thread_pointer%> is not supported on this target");
7477 : }
7478 :
7479 :
7480 : /* Emit code to restore the current value of stack. */
7481 :
7482 : static void
7483 1755 : expand_stack_restore (tree var)
7484 : {
7485 1755 : rtx_insn *prev;
7486 1755 : rtx sa = expand_normal (var);
7487 :
7488 1811 : sa = convert_memory_address (Pmode, sa);
7489 :
7490 1755 : prev = get_last_insn ();
7491 1755 : emit_stack_restore (SAVE_BLOCK, sa);
7492 :
7493 1755 : record_new_stack_level ();
7494 :
7495 1755 : fixup_args_size_notes (prev, get_last_insn (), 0);
7496 1755 : }
7497 :
7498 : /* Emit code to save the current value of stack. */
7499 :
7500 : static rtx
7501 1856 : expand_stack_save (void)
7502 : {
7503 1856 : rtx ret = NULL_RTX;
7504 :
7505 0 : emit_stack_save (SAVE_BLOCK, &ret);
7506 1856 : return ret;
7507 : }
7508 :
7509 : /* Emit code to get the openacc gang, worker or vector id or size. */
7510 :
7511 : static rtx
7512 356 : expand_builtin_goacc_parlevel_id_size (tree exp, rtx target, int ignore)
7513 : {
7514 356 : const char *name;
7515 356 : rtx fallback_retval;
7516 356 : rtx_insn *(*gen_fn) (rtx, rtx);
7517 356 : switch (DECL_FUNCTION_CODE (get_callee_fndecl (exp)))
7518 : {
7519 244 : case BUILT_IN_GOACC_PARLEVEL_ID:
7520 244 : name = "__builtin_goacc_parlevel_id";
7521 244 : fallback_retval = const0_rtx;
7522 244 : gen_fn = targetm.gen_oacc_dim_pos;
7523 244 : break;
7524 112 : case BUILT_IN_GOACC_PARLEVEL_SIZE:
7525 112 : name = "__builtin_goacc_parlevel_size";
7526 112 : fallback_retval = const1_rtx;
7527 112 : gen_fn = targetm.gen_oacc_dim_size;
7528 112 : break;
7529 0 : default:
7530 0 : gcc_unreachable ();
7531 : }
7532 :
7533 356 : if (oacc_get_fn_attrib (current_function_decl) == NULL_TREE)
7534 : {
7535 8 : error ("%qs only supported in OpenACC code", name);
7536 8 : return const0_rtx;
7537 : }
7538 :
7539 348 : tree arg = CALL_EXPR_ARG (exp, 0);
7540 348 : if (TREE_CODE (arg) != INTEGER_CST)
7541 : {
7542 8 : error ("non-constant argument 0 to %qs", name);
7543 8 : return const0_rtx;
7544 : }
7545 :
7546 340 : int dim = TREE_INT_CST_LOW (arg);
7547 340 : switch (dim)
7548 : {
7549 324 : case GOMP_DIM_GANG:
7550 324 : case GOMP_DIM_WORKER:
7551 324 : case GOMP_DIM_VECTOR:
7552 324 : break;
7553 16 : default:
7554 16 : error ("illegal argument 0 to %qs", name);
7555 16 : return const0_rtx;
7556 : }
7557 :
7558 324 : if (ignore)
7559 : return target;
7560 :
7561 180 : if (target == NULL_RTX)
7562 0 : target = gen_reg_rtx (TYPE_MODE (TREE_TYPE (exp)));
7563 :
7564 180 : if (!targetm.have_oacc_dim_size ())
7565 : {
7566 180 : emit_move_insn (target, fallback_retval);
7567 180 : return target;
7568 : }
7569 :
7570 0 : rtx reg = MEM_P (target) ? gen_reg_rtx (GET_MODE (target)) : target;
7571 0 : emit_insn (gen_fn (reg, GEN_INT (dim)));
7572 0 : if (reg != target)
7573 0 : emit_move_insn (target, reg);
7574 :
7575 : return target;
7576 : }
7577 :
7578 : /* Expand a string compare operation using a sequence of char comparison
7579 : to get rid of the calling overhead, with result going to TARGET if
7580 : that's convenient.
7581 :
7582 : VAR_STR is the variable string source;
7583 : CONST_STR is the constant string source;
7584 : LENGTH is the number of chars to compare;
7585 : CONST_STR_N indicates which source string is the constant string;
7586 : IS_MEMCMP indicates whether it's a memcmp or strcmp.
7587 :
7588 : to: (assume const_str_n is 2, i.e., arg2 is a constant string)
7589 :
7590 : target = (int) (unsigned char) var_str[0]
7591 : - (int) (unsigned char) const_str[0];
7592 : if (target != 0)
7593 : goto ne_label;
7594 : ...
7595 : target = (int) (unsigned char) var_str[length - 2]
7596 : - (int) (unsigned char) const_str[length - 2];
7597 : if (target != 0)
7598 : goto ne_label;
7599 : target = (int) (unsigned char) var_str[length - 1]
7600 : - (int) (unsigned char) const_str[length - 1];
7601 : ne_label:
7602 : */
7603 :
7604 : static rtx
7605 635 : inline_string_cmp (rtx target, tree var_str, const char *const_str,
7606 : unsigned HOST_WIDE_INT length,
7607 : int const_str_n, machine_mode mode)
7608 : {
7609 635 : HOST_WIDE_INT offset = 0;
7610 635 : rtx var_rtx_array
7611 635 : = get_memory_rtx (var_str, build_int_cst (unsigned_type_node, length),
7612 : false);
7613 635 : rtx var_rtx = NULL_RTX;
7614 635 : rtx const_rtx = NULL_RTX;
7615 635 : rtx result = target ? target : gen_reg_rtx (mode);
7616 635 : rtx_code_label *ne_label = gen_label_rtx ();
7617 635 : tree unit_type_node = unsigned_char_type_node;
7618 635 : scalar_int_mode unit_mode
7619 635 : = as_a <scalar_int_mode> TYPE_MODE (unit_type_node);
7620 :
7621 635 : start_sequence ();
7622 :
7623 2964 : for (unsigned HOST_WIDE_INT i = 0; i < length; i++)
7624 : {
7625 1694 : var_rtx
7626 1694 : = adjust_address (var_rtx_array, TYPE_MODE (unit_type_node), offset);
7627 1694 : const_rtx = c_readstr (const_str + offset, unit_mode);
7628 1694 : rtx op0 = (const_str_n == 1) ? const_rtx : var_rtx;
7629 1544 : rtx op1 = (const_str_n == 1) ? var_rtx : const_rtx;
7630 :
7631 1694 : op0 = convert_modes (mode, unit_mode, op0, 1);
7632 1694 : op1 = convert_modes (mode, unit_mode, op1, 1);
7633 1694 : rtx diff = expand_simple_binop (mode, MINUS, op0, op1,
7634 : result, 1, OPTAB_WIDEN);
7635 :
7636 : /* Force the difference into result register. We cannot reassign
7637 : result here ("result = diff") or we may end up returning
7638 : uninitialized result when expand_simple_binop allocates a new
7639 : pseudo-register for returning. */
7640 1694 : if (diff != result)
7641 0 : emit_move_insn (result, diff);
7642 :
7643 1694 : if (i < length - 1)
7644 1059 : emit_cmp_and_jump_insns (result, CONST0_RTX (mode), NE, NULL_RTX,
7645 : mode, true, ne_label);
7646 3388 : offset += GET_MODE_SIZE (unit_mode);
7647 : }
7648 :
7649 635 : emit_label (ne_label);
7650 635 : rtx_insn *insns = end_sequence ();
7651 635 : emit_insn (insns);
7652 :
7653 635 : return result;
7654 : }
7655 :
7656 : /* Inline expansion of a call to str(n)cmp and memcmp, with result going
7657 : to TARGET if that's convenient.
7658 : If the call is not been inlined, return NULL_RTX. */
7659 :
7660 : static rtx
7661 144879 : inline_expand_builtin_bytecmp (tree exp, rtx target)
7662 : {
7663 144879 : tree fndecl = get_callee_fndecl (exp);
7664 144879 : enum built_in_function fcode = DECL_FUNCTION_CODE (fndecl);
7665 144879 : bool is_ncmp = (fcode == BUILT_IN_STRNCMP || fcode == BUILT_IN_MEMCMP);
7666 :
7667 : /* Do NOT apply this inlining expansion when optimizing for size or
7668 : optimization level below 2 or if unused *cmp hasn't been DCEd. */
7669 144879 : if (optimize < 2 || optimize_insn_for_size_p () || target == const0_rtx)
7670 : return NULL_RTX;
7671 :
7672 22736 : gcc_checking_assert (fcode == BUILT_IN_STRCMP
7673 : || fcode == BUILT_IN_STRNCMP
7674 : || fcode == BUILT_IN_MEMCMP);
7675 :
7676 : /* On a target where the type of the call (int) has same or narrower precision
7677 : than unsigned char, give up the inlining expansion. */
7678 22736 : if (TYPE_PRECISION (unsigned_char_type_node)
7679 22736 : >= TYPE_PRECISION (TREE_TYPE (exp)))
7680 : return NULL_RTX;
7681 :
7682 22736 : tree arg1 = CALL_EXPR_ARG (exp, 0);
7683 22736 : tree arg2 = CALL_EXPR_ARG (exp, 1);
7684 22736 : tree len3_tree = is_ncmp ? CALL_EXPR_ARG (exp, 2) : NULL_TREE;
7685 :
7686 22736 : unsigned HOST_WIDE_INT len1 = 0;
7687 22736 : unsigned HOST_WIDE_INT len2 = 0;
7688 22736 : unsigned HOST_WIDE_INT len3 = 0;
7689 :
7690 : /* Get the object representation of the initializers of ARG1 and ARG2
7691 : as strings, provided they refer to constant objects, with their byte
7692 : sizes in LEN1 and LEN2, respectively. */
7693 22736 : const char *bytes1 = getbyterep (arg1, &len1);
7694 22736 : const char *bytes2 = getbyterep (arg2, &len2);
7695 :
7696 : /* Fail if neither argument refers to an initialized constant. */
7697 22736 : if (!bytes1 && !bytes2)
7698 : return NULL_RTX;
7699 :
7700 18497 : if (is_ncmp)
7701 : {
7702 : /* Fail if the memcmp/strncmp bound is not a constant. */
7703 1382 : if (!tree_fits_uhwi_p (len3_tree))
7704 : return NULL_RTX;
7705 :
7706 962 : len3 = tree_to_uhwi (len3_tree);
7707 :
7708 962 : if (fcode == BUILT_IN_MEMCMP)
7709 : {
7710 : /* Fail if the memcmp bound is greater than the size of either
7711 : of the two constant objects. */
7712 462 : if ((bytes1 && len1 < len3)
7713 462 : || (bytes2 && len2 < len3))
7714 : return NULL_RTX;
7715 : }
7716 : }
7717 :
7718 : if (fcode != BUILT_IN_MEMCMP)
7719 : {
7720 : /* For string functions (i.e., strcmp and strncmp) reduce LEN1
7721 : and LEN2 to the length of the nul-terminated string stored
7722 : in each. */
7723 17615 : if (bytes1 != NULL)
7724 236 : len1 = strnlen (bytes1, len1) + 1;
7725 17615 : if (bytes2 != NULL)
7726 17382 : len2 = strnlen (bytes2, len2) + 1;
7727 : }
7728 :
7729 : /* See inline_string_cmp. */
7730 18073 : int const_str_n;
7731 18073 : if (!len1)
7732 : const_str_n = 2;
7733 241 : else if (!len2)
7734 : const_str_n = 1;
7735 3 : else if (len2 > len1)
7736 : const_str_n = 1;
7737 : else
7738 : const_str_n = 2;
7739 :
7740 : /* For strncmp only, compute the new bound as the smallest of
7741 : the lengths of the two strings (plus 1) and the bound provided
7742 : to the function. */
7743 17834 : unsigned HOST_WIDE_INT bound = (const_str_n == 1) ? len1 : len2;
7744 18073 : if (is_ncmp && len3 < bound)
7745 534 : bound = len3;
7746 :
7747 : /* If the bound of the comparison is larger than the threshold,
7748 : do nothing. */
7749 18073 : if (bound > (unsigned HOST_WIDE_INT) param_builtin_string_cmp_inline_length)
7750 : return NULL_RTX;
7751 :
7752 635 : machine_mode mode = TYPE_MODE (TREE_TYPE (exp));
7753 :
7754 : /* Now, start inline expansion the call. */
7755 1213 : return inline_string_cmp (target, (const_str_n == 1) ? arg2 : arg1,
7756 : (const_str_n == 1) ? bytes1 : bytes2, bound,
7757 635 : const_str_n, mode);
7758 : }
7759 :
7760 : /* Expand a call to __builtin_speculation_safe_value_<N>. MODE
7761 : represents the size of the first argument to that call, or VOIDmode
7762 : if the argument is a pointer. IGNORE will be true if the result
7763 : isn't used. */
7764 : static rtx
7765 34 : expand_speculation_safe_value (machine_mode mode, tree exp, rtx target,
7766 : bool ignore)
7767 : {
7768 34 : rtx val, failsafe;
7769 34 : unsigned nargs = call_expr_nargs (exp);
7770 :
7771 34 : tree arg0 = CALL_EXPR_ARG (exp, 0);
7772 :
7773 34 : if (mode == VOIDmode)
7774 : {
7775 4 : mode = TYPE_MODE (TREE_TYPE (arg0));
7776 4 : gcc_assert (GET_MODE_CLASS (mode) == MODE_INT);
7777 : }
7778 :
7779 34 : val = expand_expr (arg0, NULL_RTX, mode, EXPAND_NORMAL);
7780 :
7781 : /* An optional second argument can be used as a failsafe value on
7782 : some machines. If it isn't present, then the failsafe value is
7783 : assumed to be 0. */
7784 34 : if (nargs > 1)
7785 : {
7786 4 : tree arg1 = CALL_EXPR_ARG (exp, 1);
7787 4 : failsafe = expand_expr (arg1, NULL_RTX, mode, EXPAND_NORMAL);
7788 : }
7789 : else
7790 30 : failsafe = const0_rtx;
7791 :
7792 : /* If the result isn't used, the behavior is undefined. It would be
7793 : nice to emit a warning here, but path splitting means this might
7794 : happen with legitimate code. So simply drop the builtin
7795 : expansion in that case; we've handled any side-effects above. */
7796 34 : if (ignore)
7797 0 : return const0_rtx;
7798 :
7799 : /* If we don't have a suitable target, create one to hold the result. */
7800 34 : if (target == NULL || GET_MODE (target) != mode)
7801 0 : target = gen_reg_rtx (mode);
7802 :
7803 34 : if (GET_MODE (val) != mode && GET_MODE (val) != VOIDmode)
7804 0 : val = convert_modes (mode, VOIDmode, val, false);
7805 :
7806 34 : return targetm.speculation_safe_value (mode, target, val, failsafe);
7807 : }
7808 :
7809 : /* Expand CRC* or REV_CRC* built-ins. */
7810 :
7811 : rtx
7812 45 : expand_builtin_crc_table_based (internal_fn fn, scalar_mode crc_mode,
7813 : scalar_mode data_mode, machine_mode mode,
7814 : tree exp, rtx target)
7815 : {
7816 45 : tree rhs1 = CALL_EXPR_ARG (exp, 0); // crc
7817 45 : tree rhs2 = CALL_EXPR_ARG (exp, 1); // data
7818 45 : tree rhs3 = CALL_EXPR_ARG (exp, 2); // polynomial
7819 :
7820 45 : if (!target || mode == VOIDmode)
7821 0 : target = gen_reg_rtx (crc_mode);
7822 :
7823 45 : rtx op1 = expand_normal (rhs1);
7824 45 : rtx op2 = expand_normal (rhs2);
7825 45 : rtx op3;
7826 45 : if (TREE_CODE (rhs3) != INTEGER_CST)
7827 : {
7828 1 : error ("third argument to %<crc%> builtins must be a constant");
7829 1 : op3 = const0_rtx;
7830 : }
7831 : else
7832 44 : op3 = convert_to_mode (crc_mode, expand_normal (rhs3), 0);
7833 :
7834 45 : if (CONST_INT_P (op2))
7835 32 : op2 = convert_to_mode (crc_mode, op2, 0);
7836 :
7837 45 : if (fn == IFN_CRC)
7838 28 : expand_crc_table_based (target, op1, op2, op3, data_mode);
7839 : else
7840 : /* If it's IFN_CRC_REV generate bit-reversed CRC. */
7841 17 : expand_reversed_crc_table_based (target, op1, op2, op3,
7842 : data_mode);
7843 45 : return target;
7844 : }
7845 :
7846 : /* Expand an expression EXP that calls a built-in function,
7847 : with result going to TARGET if that's convenient
7848 : (and in mode MODE if that's convenient).
7849 : SUBTARGET may be used as the target for computing one of EXP's operands.
7850 : IGNORE is nonzero if the value is to be ignored. */
7851 :
7852 : rtx
7853 2018241 : expand_builtin (tree exp, rtx target, rtx subtarget, machine_mode mode,
7854 : int ignore)
7855 : {
7856 2018241 : tree fndecl = get_callee_fndecl (exp);
7857 2018241 : machine_mode target_mode = TYPE_MODE (TREE_TYPE (exp));
7858 2018241 : int flags;
7859 :
7860 2018241 : if (DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_MD)
7861 177486 : return targetm.expand_builtin (exp, target, subtarget, mode, ignore);
7862 :
7863 : /* When ASan is enabled, we don't want to expand some memory/string
7864 : builtins and rely on libsanitizer's hooks. This allows us to avoid
7865 : redundant checks and be sure, that possible overflow will be detected
7866 : by ASan. */
7867 :
7868 1840755 : enum built_in_function fcode = DECL_FUNCTION_CODE (fndecl);
7869 1840755 : if (param_asan_kernel_mem_intrinsic_prefix
7870 1840755 : && sanitize_flags_p (SANITIZE_KERNEL_ADDRESS
7871 : | SANITIZE_KERNEL_HWADDRESS))
7872 42 : switch (fcode)
7873 : {
7874 42 : rtx save_decl_rtl, ret;
7875 42 : case BUILT_IN_MEMCPY:
7876 42 : case BUILT_IN_MEMMOVE:
7877 42 : case BUILT_IN_MEMSET:
7878 42 : save_decl_rtl = DECL_RTL (fndecl);
7879 42 : DECL_RTL (fndecl) = asan_memfn_rtl (fndecl);
7880 42 : ret = expand_call (exp, target, ignore);
7881 42 : DECL_RTL (fndecl) = save_decl_rtl;
7882 42 : return ret;
7883 : default:
7884 : break;
7885 : }
7886 1840713 : if (sanitize_flags_p (SANITIZE_ADDRESS | SANITIZE_HWADDRESS)
7887 1840713 : && asan_intercepted_p (fcode))
7888 938 : return expand_call (exp, target, ignore);
7889 :
7890 : /* When not optimizing, generate calls to library functions for a certain
7891 : set of builtins. */
7892 1839775 : if (!optimize
7893 430051 : && !called_as_built_in (fndecl)
7894 145875 : && fcode != BUILT_IN_FORK
7895 145875 : && fcode != BUILT_IN_EXECL
7896 145862 : && fcode != BUILT_IN_EXECV
7897 145862 : && fcode != BUILT_IN_EXECLP
7898 145860 : && fcode != BUILT_IN_EXECLE
7899 145860 : && fcode != BUILT_IN_EXECVP
7900 145859 : && fcode != BUILT_IN_EXECVE
7901 145859 : && fcode != BUILT_IN_CLEAR_CACHE
7902 145856 : && !ALLOCA_FUNCTION_CODE_P (fcode)
7903 145802 : && fcode != BUILT_IN_FREE
7904 143658 : && (fcode != BUILT_IN_MEMSET
7905 55893 : || !(flag_inline_stringops & ILSOP_MEMSET))
7906 143655 : && (fcode != BUILT_IN_MEMCPY
7907 918 : || !(flag_inline_stringops & ILSOP_MEMCPY))
7908 143519 : && (fcode != BUILT_IN_MEMMOVE
7909 348 : || !(flag_inline_stringops & ILSOP_MEMMOVE))
7910 1983294 : && (fcode != BUILT_IN_MEMCMP
7911 2529 : || !(flag_inline_stringops & ILSOP_MEMCMP)))
7912 143471 : return expand_call (exp, target, ignore);
7913 :
7914 : /* The built-in function expanders test for target == const0_rtx
7915 : to determine whether the function's result will be ignored. */
7916 1696304 : if (ignore)
7917 1004387 : target = const0_rtx;
7918 :
7919 : /* If the result of a pure or const built-in function is ignored, and
7920 : none of its arguments are volatile, we can avoid expanding the
7921 : built-in call and just evaluate the arguments for side-effects. */
7922 1696304 : if (target == const0_rtx
7923 1004387 : && ((flags = flags_from_decl_or_type (fndecl)) & (ECF_CONST | ECF_PURE))
7924 1699973 : && !(flags & ECF_LOOPING_CONST_OR_PURE))
7925 : {
7926 6 : bool volatilep = false;
7927 6 : tree arg;
7928 6 : call_expr_arg_iterator iter;
7929 :
7930 20 : FOR_EACH_CALL_EXPR_ARG (arg, iter, exp)
7931 8 : if (TREE_THIS_VOLATILE (arg))
7932 : {
7933 : volatilep = true;
7934 : break;
7935 : }
7936 :
7937 6 : if (! volatilep)
7938 : {
7939 20 : FOR_EACH_CALL_EXPR_ARG (arg, iter, exp)
7940 8 : expand_expr (arg, const0_rtx, VOIDmode, EXPAND_NORMAL);
7941 6 : return const0_rtx;
7942 : }
7943 : }
7944 :
7945 1696298 : switch (fcode)
7946 : {
7947 4 : CASE_FLT_FN (BUILT_IN_FABS):
7948 4 : CASE_FLT_FN_FLOATN_NX (BUILT_IN_FABS):
7949 4 : case BUILT_IN_FABSD32:
7950 4 : case BUILT_IN_FABSD64:
7951 4 : case BUILT_IN_FABSD128:
7952 4 : case BUILT_IN_FABSD64X:
7953 4 : target = expand_builtin_fabs (exp, target, subtarget);
7954 4 : if (target)
7955 843087 : return target;
7956 853211 : break;
7957 :
7958 11677 : CASE_FLT_FN (BUILT_IN_COPYSIGN):
7959 11677 : CASE_FLT_FN_FLOATN_NX (BUILT_IN_COPYSIGN):
7960 11677 : target = expand_builtin_copysign (exp, target, subtarget);
7961 11677 : if (target)
7962 : return target;
7963 : break;
7964 :
7965 : /* Just do a normal library call if we were unable to fold
7966 : the values. */
7967 : CASE_FLT_FN (BUILT_IN_CABS):
7968 : CASE_FLT_FN_FLOATN_NX (BUILT_IN_CABS):
7969 : break;
7970 :
7971 368 : CASE_FLT_FN (BUILT_IN_FMA):
7972 368 : CASE_FLT_FN_FLOATN_NX (BUILT_IN_FMA):
7973 368 : target = expand_builtin_mathfn_ternary (exp, target, subtarget);
7974 368 : if (target)
7975 : return target;
7976 : break;
7977 :
7978 232 : CASE_FLT_FN (BUILT_IN_ILOGB):
7979 232 : if (! flag_unsafe_math_optimizations)
7980 : break;
7981 4 : gcc_fallthrough ();
7982 4 : CASE_FLT_FN (BUILT_IN_ISINF):
7983 4 : CASE_FLT_FN (BUILT_IN_FINITE):
7984 4 : CASE_FLT_FN (BUILT_IN_ISNAN):
7985 4 : case BUILT_IN_ISFINITE:
7986 4 : case BUILT_IN_ISNORMAL:
7987 4 : target = expand_builtin_interclass_mathfn (exp, target);
7988 4 : if (target)
7989 : return target;
7990 : break;
7991 :
7992 784 : case BUILT_IN_ISSIGNALING:
7993 784 : target = expand_builtin_issignaling (exp, target);
7994 784 : if (target)
7995 : return target;
7996 : break;
7997 :
7998 223 : CASE_FLT_FN (BUILT_IN_ICEIL):
7999 223 : CASE_FLT_FN (BUILT_IN_LCEIL):
8000 223 : CASE_FLT_FN (BUILT_IN_LLCEIL):
8001 223 : CASE_FLT_FN (BUILT_IN_LFLOOR):
8002 223 : CASE_FLT_FN (BUILT_IN_IFLOOR):
8003 223 : CASE_FLT_FN (BUILT_IN_LLFLOOR):
8004 223 : target = expand_builtin_int_roundingfn (exp, target);
8005 223 : if (target)
8006 : return target;
8007 : break;
8008 :
8009 588 : CASE_FLT_FN (BUILT_IN_IRINT):
8010 588 : CASE_FLT_FN (BUILT_IN_LRINT):
8011 588 : CASE_FLT_FN (BUILT_IN_LLRINT):
8012 588 : CASE_FLT_FN (BUILT_IN_IROUND):
8013 588 : CASE_FLT_FN (BUILT_IN_LROUND):
8014 588 : CASE_FLT_FN (BUILT_IN_LLROUND):
8015 588 : target = expand_builtin_int_roundingfn_2 (exp, target);
8016 588 : if (target)
8017 : return target;
8018 : break;
8019 :
8020 292 : CASE_FLT_FN (BUILT_IN_POWI):
8021 292 : target = expand_builtin_powi (exp, target);
8022 292 : if (target)
8023 : return target;
8024 : break;
8025 :
8026 170 : CASE_FLT_FN (BUILT_IN_CEXPI):
8027 170 : target = expand_builtin_cexpi (exp, target);
8028 170 : gcc_assert (target);
8029 : return target;
8030 :
8031 1018 : CASE_FLT_FN (BUILT_IN_SIN):
8032 1018 : CASE_FLT_FN (BUILT_IN_COS):
8033 1018 : if (! flag_unsafe_math_optimizations)
8034 : break;
8035 47 : target = expand_builtin_mathfn_3 (exp, target, subtarget);
8036 47 : if (target)
8037 : return target;
8038 : break;
8039 :
8040 164 : CASE_FLT_FN (BUILT_IN_SINCOS):
8041 164 : if (! flag_unsafe_math_optimizations)
8042 : break;
8043 3 : target = expand_builtin_sincos (exp);
8044 3 : if (target)
8045 : return target;
8046 : break;
8047 :
8048 60 : case BUILT_IN_FEGETROUND:
8049 60 : target = expand_builtin_fegetround (exp, target, target_mode);
8050 60 : if (target)
8051 : return target;
8052 : break;
8053 :
8054 1064 : case BUILT_IN_FECLEAREXCEPT:
8055 1064 : target = expand_builtin_feclear_feraise_except (exp, target, target_mode,
8056 : feclearexcept_optab);
8057 1064 : if (target)
8058 : return target;
8059 : break;
8060 :
8061 831 : case BUILT_IN_FERAISEEXCEPT:
8062 831 : target = expand_builtin_feclear_feraise_except (exp, target, target_mode,
8063 : feraiseexcept_optab);
8064 831 : if (target)
8065 : return target;
8066 : break;
8067 :
8068 464 : case BUILT_IN_APPLY_ARGS:
8069 464 : return expand_builtin_apply_args ();
8070 :
8071 : /* __builtin_apply (FUNCTION, ARGUMENTS, ARGSIZE) invokes
8072 : FUNCTION with a copy of the parameters described by
8073 : ARGUMENTS, and ARGSIZE. It returns a block of memory
8074 : allocated on the stack into which is stored all the registers
8075 : that might possibly be used for returning the result of a
8076 : function. ARGUMENTS is the value returned by
8077 : __builtin_apply_args. ARGSIZE is the number of bytes of
8078 : arguments that must be copied. ??? How should this value be
8079 : computed? We'll also need a safe worst case value for varargs
8080 : functions. */
8081 483 : case BUILT_IN_APPLY:
8082 483 : if (!validate_arglist (exp, POINTER_TYPE,
8083 : POINTER_TYPE, INTEGER_TYPE, VOID_TYPE)
8084 483 : && !validate_arglist (exp, REFERENCE_TYPE,
8085 : POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
8086 0 : return const0_rtx;
8087 : else
8088 : {
8089 483 : rtx ops[3];
8090 :
8091 483 : ops[0] = expand_normal (CALL_EXPR_ARG (exp, 0));
8092 483 : ops[1] = expand_normal (CALL_EXPR_ARG (exp, 1));
8093 483 : ops[2] = expand_normal (CALL_EXPR_ARG (exp, 2));
8094 :
8095 483 : return expand_builtin_apply (ops[0], ops[1], ops[2]);
8096 : }
8097 :
8098 : /* __builtin_return (RESULT) causes the function to return the
8099 : value described by RESULT. RESULT is address of the block of
8100 : memory returned by __builtin_apply. */
8101 379 : case BUILT_IN_RETURN:
8102 379 : if (validate_arglist (exp, POINTER_TYPE, VOID_TYPE))
8103 379 : expand_builtin_return (expand_normal (CALL_EXPR_ARG (exp, 0)));
8104 379 : return const0_rtx;
8105 :
8106 0 : case BUILT_IN_CALL_CODE_ADDRESS:
8107 : /* All valid uses of __builtin_call_code_address () are removed in
8108 : in tree-nested.cc or gimple-fold.cc. */
8109 0 : error ("argument to %<__builtin_call_code_address%> must be a function");
8110 0 : return const0_rtx;
8111 :
8112 0 : case BUILT_IN_CALL_STATIC_CHAIN:
8113 : /* All valid uses of __builtin_call_static_chain () are removed in
8114 : in tree-nested.cc or gimple-fold.cc. */
8115 0 : error ("argument to %<__builtin_call_static_chain%> must be a function");
8116 0 : return const0_rtx;
8117 :
8118 0 : case BUILT_IN_SAVEREGS:
8119 0 : return expand_builtin_saveregs ();
8120 :
8121 16 : case BUILT_IN_VA_ARG_PACK:
8122 : /* All valid uses of __builtin_va_arg_pack () are removed during
8123 : inlining. */
8124 16 : error ("invalid use of %<__builtin_va_arg_pack ()%>");
8125 16 : return const0_rtx;
8126 :
8127 0 : case BUILT_IN_VA_ARG_PACK_LEN:
8128 : /* All valid uses of __builtin_va_arg_pack_len () are removed during
8129 : inlining. */
8130 0 : error ("invalid use of %<__builtin_va_arg_pack_len ()%>");
8131 0 : return const0_rtx;
8132 :
8133 : /* Return the address of the first anonymous stack arg. */
8134 158 : case BUILT_IN_NEXT_ARG:
8135 158 : if (fold_builtin_next_arg (exp, false))
8136 0 : return const0_rtx;
8137 158 : return expand_builtin_next_arg ();
8138 :
8139 28 : case BUILT_IN_CLEAR_CACHE:
8140 28 : expand_builtin___clear_cache (exp);
8141 28 : return const0_rtx;
8142 :
8143 0 : case BUILT_IN_CLASSIFY_TYPE:
8144 0 : return expand_builtin_classify_type (exp);
8145 :
8146 0 : case BUILT_IN_CONSTANT_P:
8147 0 : return const0_rtx;
8148 :
8149 15936 : case BUILT_IN_FRAME_ADDRESS:
8150 15936 : case BUILT_IN_RETURN_ADDRESS:
8151 15936 : return expand_builtin_frame_address (fndecl, exp);
8152 :
8153 540 : case BUILT_IN_STACK_ADDRESS:
8154 540 : return expand_builtin_stack_address ();
8155 :
8156 2170 : case BUILT_IN___STRUB_ENTER:
8157 2170 : target = expand_builtin_strub_enter (exp);
8158 2170 : if (target)
8159 : return target;
8160 : break;
8161 :
8162 1085 : case BUILT_IN___STRUB_UPDATE:
8163 1085 : target = expand_builtin_strub_update (exp);
8164 1085 : if (target)
8165 : return target;
8166 : break;
8167 :
8168 2740 : case BUILT_IN___STRUB_LEAVE:
8169 2740 : target = expand_builtin_strub_leave (exp);
8170 2740 : if (target)
8171 : return target;
8172 : break;
8173 :
8174 : /* Returns the address of the area where the structure is returned.
8175 : 0 otherwise. */
8176 0 : case BUILT_IN_AGGREGATE_INCOMING_ADDRESS:
8177 0 : if (call_expr_nargs (exp) != 0
8178 0 : || ! AGGREGATE_TYPE_P (TREE_TYPE (TREE_TYPE (current_function_decl)))
8179 0 : || !MEM_P (DECL_RTL (DECL_RESULT (current_function_decl))))
8180 0 : return const0_rtx;
8181 : else
8182 0 : return XEXP (DECL_RTL (DECL_RESULT (current_function_decl)), 0);
8183 :
8184 27611 : CASE_BUILT_IN_ALLOCA:
8185 27611 : target = expand_builtin_alloca (exp);
8186 27611 : if (target)
8187 : return target;
8188 : break;
8189 :
8190 204 : case BUILT_IN_ASAN_ALLOCAS_UNPOISON:
8191 204 : return expand_asan_emit_allocas_unpoison (exp);
8192 :
8193 1856 : case BUILT_IN_STACK_SAVE:
8194 1856 : return expand_stack_save ();
8195 :
8196 1755 : case BUILT_IN_STACK_RESTORE:
8197 1755 : expand_stack_restore (CALL_EXPR_ARG (exp, 0));
8198 1755 : return const0_rtx;
8199 :
8200 1279 : case BUILT_IN_BSWAP16:
8201 1279 : case BUILT_IN_BSWAP32:
8202 1279 : case BUILT_IN_BSWAP64:
8203 1279 : case BUILT_IN_BSWAP128:
8204 1279 : target = expand_builtin_bswap (target_mode, exp, target, subtarget);
8205 1279 : if (target)
8206 : return target;
8207 : break;
8208 :
8209 52 : case BUILT_IN_BITREVERSE8:
8210 52 : case BUILT_IN_BITREVERSE16:
8211 52 : case BUILT_IN_BITREVERSE32:
8212 52 : case BUILT_IN_BITREVERSE64:
8213 52 : case BUILT_IN_BITREVERSE128:
8214 52 : target = expand_builtin_unop (target_mode, exp, target, subtarget,
8215 : bitreverse_optab);
8216 52 : if (target)
8217 : return target;
8218 : break;
8219 :
8220 0 : CASE_INT_FN (BUILT_IN_FFS):
8221 0 : target = expand_builtin_unop (target_mode, exp, target,
8222 : subtarget, ffs_optab);
8223 0 : if (target)
8224 : return target;
8225 : break;
8226 :
8227 205 : CASE_INT_FN (BUILT_IN_CLZ):
8228 205 : target = expand_builtin_unop (target_mode, exp, target,
8229 : subtarget, clz_optab);
8230 205 : if (target)
8231 : return target;
8232 : break;
8233 :
8234 48 : CASE_INT_FN (BUILT_IN_CTZ):
8235 48 : target = expand_builtin_unop (target_mode, exp, target,
8236 : subtarget, ctz_optab);
8237 48 : if (target)
8238 : return target;
8239 : break;
8240 :
8241 91 : CASE_INT_FN (BUILT_IN_CLRSB):
8242 91 : target = expand_builtin_unop (target_mode, exp, target,
8243 : subtarget, clrsb_optab);
8244 91 : if (target)
8245 : return target;
8246 : break;
8247 :
8248 447 : CASE_INT_FN (BUILT_IN_POPCOUNT):
8249 447 : target = expand_builtin_unop (target_mode, exp, target,
8250 : subtarget, popcount_optab);
8251 447 : if (target)
8252 : return target;
8253 : break;
8254 :
8255 11 : CASE_INT_FN (BUILT_IN_PARITY):
8256 11 : target = expand_builtin_unop (target_mode, exp, target,
8257 : subtarget, parity_optab);
8258 11 : if (target)
8259 : return target;
8260 : break;
8261 :
8262 14617 : case BUILT_IN_STRLEN:
8263 14617 : target = expand_builtin_strlen (exp, target, target_mode);
8264 14617 : if (target)
8265 : return target;
8266 : break;
8267 :
8268 580 : case BUILT_IN_STRNLEN:
8269 580 : target = expand_builtin_strnlen (exp, target, target_mode);
8270 580 : if (target)
8271 : return target;
8272 : break;
8273 :
8274 1860 : case BUILT_IN_STRCPY:
8275 1860 : target = expand_builtin_strcpy (exp, target);
8276 1860 : if (target)
8277 : return target;
8278 : break;
8279 :
8280 2177 : case BUILT_IN_STRNCPY:
8281 2177 : target = expand_builtin_strncpy (exp, target);
8282 2177 : if (target)
8283 : return target;
8284 : break;
8285 :
8286 454 : case BUILT_IN_STPCPY:
8287 454 : target = expand_builtin_stpcpy (exp, target, mode);
8288 454 : if (target)
8289 : return target;
8290 : break;
8291 :
8292 108828 : case BUILT_IN_MEMCPY:
8293 108828 : target = expand_builtin_memcpy (exp, target);
8294 108828 : if (target)
8295 : return target;
8296 : break;
8297 :
8298 17563 : case BUILT_IN_MEMMOVE:
8299 17563 : target = expand_builtin_memmove (exp, target);
8300 17563 : if (target)
8301 : return target;
8302 : break;
8303 :
8304 1394 : case BUILT_IN_MEMPCPY:
8305 1394 : target = expand_builtin_mempcpy (exp, target);
8306 1394 : if (target)
8307 : return target;
8308 : break;
8309 :
8310 36761 : case BUILT_IN_MEMSET:
8311 36761 : target = expand_builtin_memset (exp, target, mode);
8312 36761 : if (target)
8313 : return target;
8314 : break;
8315 :
8316 0 : case BUILT_IN_BZERO:
8317 0 : target = expand_builtin_bzero (exp);
8318 0 : if (target)
8319 : return target;
8320 : break;
8321 :
8322 : /* Expand it as BUILT_IN_MEMCMP_EQ first. If not successful, change it
8323 : back to a BUILT_IN_STRCMP. Remember to delete the 3rd parameter
8324 : when changing it to a strcmp call. */
8325 371 : case BUILT_IN_STRCMP_EQ:
8326 371 : target = expand_builtin_memcmp (exp, target, true);
8327 371 : if (target)
8328 : return target;
8329 :
8330 : /* Change this call back to a BUILT_IN_STRCMP. */
8331 25 : TREE_OPERAND (exp, 1)
8332 25 : = build_fold_addr_expr (builtin_decl_explicit (BUILT_IN_STRCMP));
8333 :
8334 : /* Delete the last parameter. */
8335 25 : unsigned int i;
8336 25 : vec<tree, va_gc> *arg_vec;
8337 25 : vec_alloc (arg_vec, 2);
8338 100 : for (i = 0; i < 2; i++)
8339 50 : arg_vec->quick_push (CALL_EXPR_ARG (exp, i));
8340 25 : exp = build_call_vec (TREE_TYPE (exp), CALL_EXPR_FN (exp), arg_vec);
8341 : /* FALLTHROUGH */
8342 :
8343 127970 : case BUILT_IN_STRCMP:
8344 127970 : target = expand_builtin_strcmp (exp, target);
8345 127970 : if (target)
8346 : return target;
8347 : break;
8348 :
8349 : /* Expand it as BUILT_IN_MEMCMP_EQ first. If not successful, change it
8350 : back to a BUILT_IN_STRNCMP. */
8351 38 : case BUILT_IN_STRNCMP_EQ:
8352 38 : target = expand_builtin_memcmp (exp, target, true);
8353 38 : if (target)
8354 : return target;
8355 :
8356 : /* Change it back to a BUILT_IN_STRNCMP. */
8357 0 : TREE_OPERAND (exp, 1)
8358 0 : = build_fold_addr_expr (builtin_decl_explicit (BUILT_IN_STRNCMP));
8359 : /* FALLTHROUGH */
8360 :
8361 2027 : case BUILT_IN_STRNCMP:
8362 2027 : target = expand_builtin_strncmp (exp, target, mode);
8363 2027 : if (target)
8364 : return target;
8365 : break;
8366 :
8367 106123 : case BUILT_IN_BCMP:
8368 106123 : case BUILT_IN_MEMCMP:
8369 106123 : case BUILT_IN_MEMCMP_EQ:
8370 106123 : target = expand_builtin_memcmp (exp, target, fcode == BUILT_IN_MEMCMP_EQ);
8371 106123 : if (target)
8372 : return target;
8373 37547 : if (fcode == BUILT_IN_MEMCMP_EQ)
8374 : {
8375 23031 : tree newdecl = builtin_decl_explicit (BUILT_IN_MEMCMP);
8376 23031 : TREE_OPERAND (exp, 1) = build_fold_addr_expr (newdecl);
8377 : }
8378 : break;
8379 :
8380 0 : case BUILT_IN_SETJMP:
8381 : /* This should have been lowered to the builtins below. */
8382 0 : gcc_unreachable ();
8383 :
8384 842 : case BUILT_IN_SETJMP_SETUP:
8385 : /* __builtin_setjmp_setup is passed a pointer to an array of five words
8386 : and the receiver label. */
8387 842 : if (validate_arglist (exp, POINTER_TYPE, POINTER_TYPE, VOID_TYPE))
8388 : {
8389 842 : rtx buf_addr = expand_expr (CALL_EXPR_ARG (exp, 0), subtarget,
8390 : VOIDmode, EXPAND_NORMAL);
8391 842 : tree label = TREE_OPERAND (CALL_EXPR_ARG (exp, 1), 0);
8392 842 : rtx_insn *label_r = label_rtx (label);
8393 :
8394 842 : expand_builtin_setjmp_setup (buf_addr, label_r);
8395 842 : return const0_rtx;
8396 : }
8397 : break;
8398 :
8399 842 : case BUILT_IN_SETJMP_RECEIVER:
8400 : /* __builtin_setjmp_receiver is passed the receiver label. */
8401 842 : if (validate_arglist (exp, POINTER_TYPE, VOID_TYPE))
8402 : {
8403 842 : tree label = TREE_OPERAND (CALL_EXPR_ARG (exp, 0), 0);
8404 842 : rtx_insn *label_r = label_rtx (label);
8405 :
8406 842 : expand_builtin_setjmp_receiver (label_r);
8407 842 : nonlocal_goto_handler_labels
8408 1684 : = gen_rtx_INSN_LIST (VOIDmode, label_r,
8409 842 : nonlocal_goto_handler_labels);
8410 : /* ??? Do not let expand_label treat us as such since we would
8411 : not want to be both on the list of non-local labels and on
8412 : the list of forced labels. */
8413 842 : FORCED_LABEL (label) = 0;
8414 842 : return const0_rtx;
8415 : }
8416 : break;
8417 :
8418 : /* __builtin_longjmp is passed a pointer to an array of five words.
8419 : It's similar to the C library longjmp function but works with
8420 : __builtin_setjmp above. */
8421 392 : case BUILT_IN_LONGJMP:
8422 392 : if (validate_arglist (exp, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
8423 : {
8424 392 : rtx buf_addr = expand_expr (CALL_EXPR_ARG (exp, 0), subtarget,
8425 : VOIDmode, EXPAND_NORMAL);
8426 392 : rtx value = expand_normal (CALL_EXPR_ARG (exp, 1));
8427 :
8428 392 : if (value != const1_rtx)
8429 : {
8430 0 : error ("%<__builtin_longjmp%> second argument must be 1");
8431 0 : return const0_rtx;
8432 : }
8433 :
8434 392 : expand_builtin_longjmp (buf_addr, value);
8435 392 : return const0_rtx;
8436 : }
8437 : break;
8438 :
8439 512 : case BUILT_IN_NONLOCAL_GOTO:
8440 512 : target = expand_builtin_nonlocal_goto (exp);
8441 512 : if (target)
8442 : return target;
8443 : break;
8444 :
8445 : /* This updates the setjmp buffer that is its argument with the value
8446 : of the current stack pointer. */
8447 0 : case BUILT_IN_UPDATE_SETJMP_BUF:
8448 0 : if (validate_arglist (exp, POINTER_TYPE, VOID_TYPE))
8449 : {
8450 0 : rtx buf_addr
8451 0 : = expand_normal (CALL_EXPR_ARG (exp, 0));
8452 :
8453 0 : expand_builtin_update_setjmp_buf (buf_addr);
8454 0 : return const0_rtx;
8455 : }
8456 : break;
8457 :
8458 38675 : case BUILT_IN_TRAP:
8459 38675 : case BUILT_IN_UNREACHABLE_TRAP:
8460 38675 : expand_builtin_trap ();
8461 38675 : return const0_rtx;
8462 :
8463 2563 : case BUILT_IN_UNREACHABLE:
8464 2563 : expand_builtin_unreachable ();
8465 2563 : return const0_rtx;
8466 :
8467 402 : case BUILT_IN_OBSERVABLE_CHKPT:
8468 : /* Generate no code. */
8469 402 : return const0_rtx;
8470 :
8471 1368 : CASE_FLT_FN (BUILT_IN_SIGNBIT):
8472 1368 : case BUILT_IN_SIGNBITD32:
8473 1368 : case BUILT_IN_SIGNBITD64:
8474 1368 : case BUILT_IN_SIGNBITD128:
8475 1368 : target = expand_builtin_signbit (exp, target);
8476 1368 : if (target)
8477 : return target;
8478 : break;
8479 :
8480 : /* Various hooks for the DWARF 2 __throw routine. */
8481 34 : case BUILT_IN_UNWIND_INIT:
8482 34 : expand_builtin_unwind_init ();
8483 34 : return const0_rtx;
8484 1224 : case BUILT_IN_DWARF_CFA:
8485 1224 : return virtual_cfa_rtx;
8486 : #ifdef DWARF2_UNWIND_INFO
8487 48 : case BUILT_IN_DWARF_SP_COLUMN:
8488 48 : return expand_builtin_dwarf_sp_column ();
8489 8 : case BUILT_IN_INIT_DWARF_REG_SIZES:
8490 8 : expand_builtin_init_dwarf_reg_sizes (CALL_EXPR_ARG (exp, 0));
8491 8 : return const0_rtx;
8492 : #endif
8493 19 : case BUILT_IN_FROB_RETURN_ADDR:
8494 19 : return expand_builtin_frob_return_addr (CALL_EXPR_ARG (exp, 0));
8495 2352 : case BUILT_IN_EXTRACT_RETURN_ADDR:
8496 2352 : return expand_builtin_extract_return_addr (CALL_EXPR_ARG (exp, 0));
8497 29 : case BUILT_IN_EH_RETURN:
8498 58 : expand_builtin_eh_return (CALL_EXPR_ARG (exp, 0),
8499 29 : CALL_EXPR_ARG (exp, 1));
8500 29 : return const0_rtx;
8501 21 : case BUILT_IN_EH_RETURN_DATA_REGNO:
8502 21 : return expand_builtin_eh_return_data_regno (exp);
8503 2 : case BUILT_IN_EXTEND_POINTER:
8504 2 : return expand_builtin_extend_pointer (CALL_EXPR_ARG (exp, 0));
8505 102017 : case BUILT_IN_EH_POINTER:
8506 102017 : return expand_builtin_eh_pointer (exp);
8507 5721 : case BUILT_IN_EH_FILTER:
8508 5721 : return expand_builtin_eh_filter (exp);
8509 100295 : case BUILT_IN_EH_COPY_VALUES:
8510 100295 : return expand_builtin_eh_copy_values (exp);
8511 :
8512 21082 : case BUILT_IN_VA_START:
8513 21082 : return expand_builtin_va_start (exp);
8514 12161 : case BUILT_IN_VA_END:
8515 12161 : return expand_builtin_va_end (exp);
8516 240 : case BUILT_IN_VA_COPY:
8517 240 : return expand_builtin_va_copy (exp);
8518 1407 : case BUILT_IN_EXPECT:
8519 1407 : return expand_builtin_expect (exp, target);
8520 5 : case BUILT_IN_EXPECT_WITH_PROBABILITY:
8521 5 : return expand_builtin_expect_with_probability (exp, target);
8522 665 : case BUILT_IN_ASSUME_ALIGNED:
8523 665 : return expand_builtin_assume_aligned (exp, target);
8524 2058 : case BUILT_IN_PREFETCH:
8525 2058 : expand_builtin_prefetch (exp);
8526 2058 : return const0_rtx;
8527 :
8528 306 : case BUILT_IN_INIT_TRAMPOLINE:
8529 306 : return expand_builtin_init_trampoline (exp, true);
8530 0 : case BUILT_IN_INIT_HEAP_TRAMPOLINE:
8531 0 : return expand_builtin_init_trampoline (exp, false);
8532 353 : case BUILT_IN_ADJUST_TRAMPOLINE:
8533 353 : return expand_builtin_adjust_trampoline (exp);
8534 :
8535 0 : case BUILT_IN_INIT_DESCRIPTOR:
8536 0 : return expand_builtin_init_descriptor (exp);
8537 0 : case BUILT_IN_ADJUST_DESCRIPTOR:
8538 0 : return expand_builtin_adjust_descriptor (exp);
8539 :
8540 : case BUILT_IN_GCC_NESTED_PTR_CREATED:
8541 : case BUILT_IN_GCC_NESTED_PTR_DELETED:
8542 : break; /* At present, no expansion, just call the function. */
8543 :
8544 111 : case BUILT_IN_FORK:
8545 111 : case BUILT_IN_EXECL:
8546 111 : case BUILT_IN_EXECV:
8547 111 : case BUILT_IN_EXECLP:
8548 111 : case BUILT_IN_EXECLE:
8549 111 : case BUILT_IN_EXECVP:
8550 111 : case BUILT_IN_EXECVE:
8551 111 : target = expand_builtin_fork_or_exec (fndecl, exp, target, ignore);
8552 111 : if (target)
8553 : return target;
8554 : break;
8555 :
8556 712 : case BUILT_IN_SYNC_FETCH_AND_ADD_1:
8557 712 : case BUILT_IN_SYNC_FETCH_AND_ADD_2:
8558 712 : case BUILT_IN_SYNC_FETCH_AND_ADD_4:
8559 712 : case BUILT_IN_SYNC_FETCH_AND_ADD_8:
8560 712 : case BUILT_IN_SYNC_FETCH_AND_ADD_16:
8561 712 : mode = get_builtin_sync_mode (fcode - BUILT_IN_SYNC_FETCH_AND_ADD_1);
8562 712 : target = expand_builtin_sync_operation (mode, exp, PLUS, false, target);
8563 712 : if (target)
8564 : return target;
8565 : break;
8566 :
8567 585 : case BUILT_IN_SYNC_FETCH_AND_SUB_1:
8568 585 : case BUILT_IN_SYNC_FETCH_AND_SUB_2:
8569 585 : case BUILT_IN_SYNC_FETCH_AND_SUB_4:
8570 585 : case BUILT_IN_SYNC_FETCH_AND_SUB_8:
8571 585 : case BUILT_IN_SYNC_FETCH_AND_SUB_16:
8572 585 : mode = get_builtin_sync_mode (fcode - BUILT_IN_SYNC_FETCH_AND_SUB_1);
8573 585 : target = expand_builtin_sync_operation (mode, exp, MINUS, false, target);
8574 585 : if (target)
8575 : return target;
8576 : break;
8577 :
8578 512 : case BUILT_IN_SYNC_FETCH_AND_OR_1:
8579 512 : case BUILT_IN_SYNC_FETCH_AND_OR_2:
8580 512 : case BUILT_IN_SYNC_FETCH_AND_OR_4:
8581 512 : case BUILT_IN_SYNC_FETCH_AND_OR_8:
8582 512 : case BUILT_IN_SYNC_FETCH_AND_OR_16:
8583 512 : mode = get_builtin_sync_mode (fcode - BUILT_IN_SYNC_FETCH_AND_OR_1);
8584 512 : target = expand_builtin_sync_operation (mode, exp, IOR, false, target);
8585 512 : if (target)
8586 : return target;
8587 : break;
8588 :
8589 488 : case BUILT_IN_SYNC_FETCH_AND_AND_1:
8590 488 : case BUILT_IN_SYNC_FETCH_AND_AND_2:
8591 488 : case BUILT_IN_SYNC_FETCH_AND_AND_4:
8592 488 : case BUILT_IN_SYNC_FETCH_AND_AND_8:
8593 488 : case BUILT_IN_SYNC_FETCH_AND_AND_16:
8594 488 : mode = get_builtin_sync_mode (fcode - BUILT_IN_SYNC_FETCH_AND_AND_1);
8595 488 : target = expand_builtin_sync_operation (mode, exp, AND, false, target);
8596 488 : if (target)
8597 : return target;
8598 : break;
8599 :
8600 581 : case BUILT_IN_SYNC_FETCH_AND_XOR_1:
8601 581 : case BUILT_IN_SYNC_FETCH_AND_XOR_2:
8602 581 : case BUILT_IN_SYNC_FETCH_AND_XOR_4:
8603 581 : case BUILT_IN_SYNC_FETCH_AND_XOR_8:
8604 581 : case BUILT_IN_SYNC_FETCH_AND_XOR_16:
8605 581 : mode = get_builtin_sync_mode (fcode - BUILT_IN_SYNC_FETCH_AND_XOR_1);
8606 581 : target = expand_builtin_sync_operation (mode, exp, XOR, false, target);
8607 581 : if (target)
8608 : return target;
8609 : break;
8610 :
8611 434 : case BUILT_IN_SYNC_FETCH_AND_NAND_1:
8612 434 : case BUILT_IN_SYNC_FETCH_AND_NAND_2:
8613 434 : case BUILT_IN_SYNC_FETCH_AND_NAND_4:
8614 434 : case BUILT_IN_SYNC_FETCH_AND_NAND_8:
8615 434 : case BUILT_IN_SYNC_FETCH_AND_NAND_16:
8616 434 : mode = get_builtin_sync_mode (fcode - BUILT_IN_SYNC_FETCH_AND_NAND_1);
8617 434 : target = expand_builtin_sync_operation (mode, exp, NOT, false, target);
8618 434 : if (target)
8619 : return target;
8620 : break;
8621 :
8622 161 : case BUILT_IN_SYNC_ADD_AND_FETCH_1:
8623 161 : case BUILT_IN_SYNC_ADD_AND_FETCH_2:
8624 161 : case BUILT_IN_SYNC_ADD_AND_FETCH_4:
8625 161 : case BUILT_IN_SYNC_ADD_AND_FETCH_8:
8626 161 : case BUILT_IN_SYNC_ADD_AND_FETCH_16:
8627 161 : mode = get_builtin_sync_mode (fcode - BUILT_IN_SYNC_ADD_AND_FETCH_1);
8628 161 : target = expand_builtin_sync_operation (mode, exp, PLUS, true, target);
8629 161 : if (target)
8630 : return target;
8631 : break;
8632 :
8633 121 : case BUILT_IN_SYNC_SUB_AND_FETCH_1:
8634 121 : case BUILT_IN_SYNC_SUB_AND_FETCH_2:
8635 121 : case BUILT_IN_SYNC_SUB_AND_FETCH_4:
8636 121 : case BUILT_IN_SYNC_SUB_AND_FETCH_8:
8637 121 : case BUILT_IN_SYNC_SUB_AND_FETCH_16:
8638 121 : mode = get_builtin_sync_mode (fcode - BUILT_IN_SYNC_SUB_AND_FETCH_1);
8639 121 : target = expand_builtin_sync_operation (mode, exp, MINUS, true, target);
8640 121 : if (target)
8641 : return target;
8642 : break;
8643 :
8644 115 : case BUILT_IN_SYNC_OR_AND_FETCH_1:
8645 115 : case BUILT_IN_SYNC_OR_AND_FETCH_2:
8646 115 : case BUILT_IN_SYNC_OR_AND_FETCH_4:
8647 115 : case BUILT_IN_SYNC_OR_AND_FETCH_8:
8648 115 : case BUILT_IN_SYNC_OR_AND_FETCH_16:
8649 115 : mode = get_builtin_sync_mode (fcode - BUILT_IN_SYNC_OR_AND_FETCH_1);
8650 115 : target = expand_builtin_sync_operation (mode, exp, IOR, true, target);
8651 115 : if (target)
8652 : return target;
8653 : break;
8654 :
8655 116 : case BUILT_IN_SYNC_AND_AND_FETCH_1:
8656 116 : case BUILT_IN_SYNC_AND_AND_FETCH_2:
8657 116 : case BUILT_IN_SYNC_AND_AND_FETCH_4:
8658 116 : case BUILT_IN_SYNC_AND_AND_FETCH_8:
8659 116 : case BUILT_IN_SYNC_AND_AND_FETCH_16:
8660 116 : mode = get_builtin_sync_mode (fcode - BUILT_IN_SYNC_AND_AND_FETCH_1);
8661 116 : target = expand_builtin_sync_operation (mode, exp, AND, true, target);
8662 116 : if (target)
8663 : return target;
8664 : break;
8665 :
8666 114 : case BUILT_IN_SYNC_XOR_AND_FETCH_1:
8667 114 : case BUILT_IN_SYNC_XOR_AND_FETCH_2:
8668 114 : case BUILT_IN_SYNC_XOR_AND_FETCH_4:
8669 114 : case BUILT_IN_SYNC_XOR_AND_FETCH_8:
8670 114 : case BUILT_IN_SYNC_XOR_AND_FETCH_16:
8671 114 : mode = get_builtin_sync_mode (fcode - BUILT_IN_SYNC_XOR_AND_FETCH_1);
8672 114 : target = expand_builtin_sync_operation (mode, exp, XOR, true, target);
8673 114 : if (target)
8674 : return target;
8675 : break;
8676 :
8677 89 : case BUILT_IN_SYNC_NAND_AND_FETCH_1:
8678 89 : case BUILT_IN_SYNC_NAND_AND_FETCH_2:
8679 89 : case BUILT_IN_SYNC_NAND_AND_FETCH_4:
8680 89 : case BUILT_IN_SYNC_NAND_AND_FETCH_8:
8681 89 : case BUILT_IN_SYNC_NAND_AND_FETCH_16:
8682 89 : mode = get_builtin_sync_mode (fcode - BUILT_IN_SYNC_NAND_AND_FETCH_1);
8683 89 : target = expand_builtin_sync_operation (mode, exp, NOT, true, target);
8684 89 : if (target)
8685 : return target;
8686 : break;
8687 :
8688 204 : case BUILT_IN_SYNC_BOOL_COMPARE_AND_SWAP_1:
8689 204 : case BUILT_IN_SYNC_BOOL_COMPARE_AND_SWAP_2:
8690 204 : case BUILT_IN_SYNC_BOOL_COMPARE_AND_SWAP_4:
8691 204 : case BUILT_IN_SYNC_BOOL_COMPARE_AND_SWAP_8:
8692 204 : case BUILT_IN_SYNC_BOOL_COMPARE_AND_SWAP_16:
8693 204 : if (mode == VOIDmode)
8694 40 : mode = TYPE_MODE (boolean_type_node);
8695 204 : if (!target || !register_operand (target, mode))
8696 40 : target = gen_reg_rtx (mode);
8697 :
8698 204 : mode = get_builtin_sync_mode
8699 204 : (fcode - BUILT_IN_SYNC_BOOL_COMPARE_AND_SWAP_1);
8700 204 : target = expand_builtin_compare_and_swap (mode, exp, true, target);
8701 204 : if (target)
8702 : return target;
8703 : break;
8704 :
8705 256 : case BUILT_IN_SYNC_VAL_COMPARE_AND_SWAP_1:
8706 256 : case BUILT_IN_SYNC_VAL_COMPARE_AND_SWAP_2:
8707 256 : case BUILT_IN_SYNC_VAL_COMPARE_AND_SWAP_4:
8708 256 : case BUILT_IN_SYNC_VAL_COMPARE_AND_SWAP_8:
8709 256 : case BUILT_IN_SYNC_VAL_COMPARE_AND_SWAP_16:
8710 256 : mode = get_builtin_sync_mode
8711 256 : (fcode - BUILT_IN_SYNC_VAL_COMPARE_AND_SWAP_1);
8712 256 : target = expand_builtin_compare_and_swap (mode, exp, false, target);
8713 256 : if (target)
8714 : return target;
8715 : break;
8716 :
8717 326 : case BUILT_IN_SYNC_LOCK_TEST_AND_SET_1:
8718 326 : case BUILT_IN_SYNC_LOCK_TEST_AND_SET_2:
8719 326 : case BUILT_IN_SYNC_LOCK_TEST_AND_SET_4:
8720 326 : case BUILT_IN_SYNC_LOCK_TEST_AND_SET_8:
8721 326 : case BUILT_IN_SYNC_LOCK_TEST_AND_SET_16:
8722 326 : mode = get_builtin_sync_mode (fcode - BUILT_IN_SYNC_LOCK_TEST_AND_SET_1);
8723 326 : target = expand_builtin_sync_lock_test_and_set (mode, exp, target);
8724 326 : if (target)
8725 : return target;
8726 : break;
8727 :
8728 146 : case BUILT_IN_SYNC_LOCK_RELEASE_1:
8729 146 : case BUILT_IN_SYNC_LOCK_RELEASE_2:
8730 146 : case BUILT_IN_SYNC_LOCK_RELEASE_4:
8731 146 : case BUILT_IN_SYNC_LOCK_RELEASE_8:
8732 146 : case BUILT_IN_SYNC_LOCK_RELEASE_16:
8733 146 : mode = get_builtin_sync_mode (fcode - BUILT_IN_SYNC_LOCK_RELEASE_1);
8734 146 : if (expand_builtin_sync_lock_release (mode, exp))
8735 144 : return const0_rtx;
8736 : break;
8737 :
8738 273 : case BUILT_IN_SYNC_SYNCHRONIZE:
8739 273 : expand_builtin_sync_synchronize ();
8740 273 : return const0_rtx;
8741 :
8742 2937 : case BUILT_IN_ATOMIC_EXCHANGE_1:
8743 2937 : case BUILT_IN_ATOMIC_EXCHANGE_2:
8744 2937 : case BUILT_IN_ATOMIC_EXCHANGE_4:
8745 2937 : case BUILT_IN_ATOMIC_EXCHANGE_8:
8746 2937 : case BUILT_IN_ATOMIC_EXCHANGE_16:
8747 2937 : mode = get_builtin_sync_mode (fcode - BUILT_IN_ATOMIC_EXCHANGE_1);
8748 2937 : target = expand_builtin_atomic_exchange (mode, exp, target);
8749 2937 : if (target)
8750 : return target;
8751 : break;
8752 :
8753 9129 : case BUILT_IN_ATOMIC_COMPARE_EXCHANGE_1:
8754 9129 : case BUILT_IN_ATOMIC_COMPARE_EXCHANGE_2:
8755 9129 : case BUILT_IN_ATOMIC_COMPARE_EXCHANGE_4:
8756 9129 : case BUILT_IN_ATOMIC_COMPARE_EXCHANGE_8:
8757 9129 : case BUILT_IN_ATOMIC_COMPARE_EXCHANGE_16:
8758 9129 : {
8759 9129 : unsigned int nargs, z;
8760 9129 : vec<tree, va_gc> *vec;
8761 :
8762 9129 : mode =
8763 9129 : get_builtin_sync_mode (fcode - BUILT_IN_ATOMIC_COMPARE_EXCHANGE_1);
8764 9129 : target = expand_builtin_atomic_compare_exchange (mode, exp, target);
8765 9129 : if (target)
8766 7329 : return target;
8767 :
8768 : /* If this is turned into an external library call, the weak parameter
8769 : must be dropped to match the expected parameter list. */
8770 1800 : nargs = call_expr_nargs (exp);
8771 1800 : vec_alloc (vec, nargs - 1);
8772 9000 : for (z = 0; z < 3; z++)
8773 5400 : vec->quick_push (CALL_EXPR_ARG (exp, z));
8774 : /* Skip the boolean weak parameter. */
8775 5400 : for (z = 4; z < 6; z++)
8776 3600 : vec->quick_push (CALL_EXPR_ARG (exp, z));
8777 1800 : exp = build_call_vec (TREE_TYPE (exp), CALL_EXPR_FN (exp), vec);
8778 1800 : break;
8779 : }
8780 :
8781 70597 : case BUILT_IN_ATOMIC_LOAD_1:
8782 70597 : case BUILT_IN_ATOMIC_LOAD_2:
8783 70597 : case BUILT_IN_ATOMIC_LOAD_4:
8784 70597 : case BUILT_IN_ATOMIC_LOAD_8:
8785 70597 : case BUILT_IN_ATOMIC_LOAD_16:
8786 70597 : mode = get_builtin_sync_mode (fcode - BUILT_IN_ATOMIC_LOAD_1);
8787 70597 : target = expand_builtin_atomic_load (mode, exp, target);
8788 70597 : if (target)
8789 : return target;
8790 : break;
8791 :
8792 17465 : case BUILT_IN_ATOMIC_STORE_1:
8793 17465 : case BUILT_IN_ATOMIC_STORE_2:
8794 17465 : case BUILT_IN_ATOMIC_STORE_4:
8795 17465 : case BUILT_IN_ATOMIC_STORE_8:
8796 17465 : case BUILT_IN_ATOMIC_STORE_16:
8797 17465 : mode = get_builtin_sync_mode (fcode - BUILT_IN_ATOMIC_STORE_1);
8798 17465 : target = expand_builtin_atomic_store (mode, exp);
8799 17465 : if (target)
8800 15833 : return const0_rtx;
8801 : break;
8802 :
8803 4394 : case BUILT_IN_ATOMIC_ADD_FETCH_1:
8804 4394 : case BUILT_IN_ATOMIC_ADD_FETCH_2:
8805 4394 : case BUILT_IN_ATOMIC_ADD_FETCH_4:
8806 4394 : case BUILT_IN_ATOMIC_ADD_FETCH_8:
8807 4394 : case BUILT_IN_ATOMIC_ADD_FETCH_16:
8808 4394 : {
8809 4394 : enum built_in_function lib;
8810 4394 : mode = get_builtin_sync_mode (fcode - BUILT_IN_ATOMIC_ADD_FETCH_1);
8811 4394 : lib = (enum built_in_function)((int)BUILT_IN_ATOMIC_FETCH_ADD_1 +
8812 : (fcode - BUILT_IN_ATOMIC_ADD_FETCH_1));
8813 4394 : target = expand_builtin_atomic_fetch_op (mode, exp, target, PLUS, true,
8814 : ignore, lib);
8815 4394 : if (target)
8816 : return target;
8817 : break;
8818 : }
8819 2172 : case BUILT_IN_ATOMIC_SUB_FETCH_1:
8820 2172 : case BUILT_IN_ATOMIC_SUB_FETCH_2:
8821 2172 : case BUILT_IN_ATOMIC_SUB_FETCH_4:
8822 2172 : case BUILT_IN_ATOMIC_SUB_FETCH_8:
8823 2172 : case BUILT_IN_ATOMIC_SUB_FETCH_16:
8824 2172 : {
8825 2172 : enum built_in_function lib;
8826 2172 : mode = get_builtin_sync_mode (fcode - BUILT_IN_ATOMIC_SUB_FETCH_1);
8827 2172 : lib = (enum built_in_function)((int)BUILT_IN_ATOMIC_FETCH_SUB_1 +
8828 : (fcode - BUILT_IN_ATOMIC_SUB_FETCH_1));
8829 2172 : target = expand_builtin_atomic_fetch_op (mode, exp, target, MINUS, true,
8830 : ignore, lib);
8831 2172 : if (target)
8832 : return target;
8833 : break;
8834 : }
8835 902 : case BUILT_IN_ATOMIC_AND_FETCH_1:
8836 902 : case BUILT_IN_ATOMIC_AND_FETCH_2:
8837 902 : case BUILT_IN_ATOMIC_AND_FETCH_4:
8838 902 : case BUILT_IN_ATOMIC_AND_FETCH_8:
8839 902 : case BUILT_IN_ATOMIC_AND_FETCH_16:
8840 902 : {
8841 902 : enum built_in_function lib;
8842 902 : mode = get_builtin_sync_mode (fcode - BUILT_IN_ATOMIC_AND_FETCH_1);
8843 902 : lib = (enum built_in_function)((int)BUILT_IN_ATOMIC_FETCH_AND_1 +
8844 : (fcode - BUILT_IN_ATOMIC_AND_FETCH_1));
8845 902 : target = expand_builtin_atomic_fetch_op (mode, exp, target, AND, true,
8846 : ignore, lib);
8847 902 : if (target)
8848 : return target;
8849 : break;
8850 : }
8851 162 : case BUILT_IN_ATOMIC_NAND_FETCH_1:
8852 162 : case BUILT_IN_ATOMIC_NAND_FETCH_2:
8853 162 : case BUILT_IN_ATOMIC_NAND_FETCH_4:
8854 162 : case BUILT_IN_ATOMIC_NAND_FETCH_8:
8855 162 : case BUILT_IN_ATOMIC_NAND_FETCH_16:
8856 162 : {
8857 162 : enum built_in_function lib;
8858 162 : mode = get_builtin_sync_mode (fcode - BUILT_IN_ATOMIC_NAND_FETCH_1);
8859 162 : lib = (enum built_in_function)((int)BUILT_IN_ATOMIC_FETCH_NAND_1 +
8860 : (fcode - BUILT_IN_ATOMIC_NAND_FETCH_1));
8861 162 : target = expand_builtin_atomic_fetch_op (mode, exp, target, NOT, true,
8862 : ignore, lib);
8863 162 : if (target)
8864 : return target;
8865 : break;
8866 : }
8867 847 : case BUILT_IN_ATOMIC_XOR_FETCH_1:
8868 847 : case BUILT_IN_ATOMIC_XOR_FETCH_2:
8869 847 : case BUILT_IN_ATOMIC_XOR_FETCH_4:
8870 847 : case BUILT_IN_ATOMIC_XOR_FETCH_8:
8871 847 : case BUILT_IN_ATOMIC_XOR_FETCH_16:
8872 847 : {
8873 847 : enum built_in_function lib;
8874 847 : mode = get_builtin_sync_mode (fcode - BUILT_IN_ATOMIC_XOR_FETCH_1);
8875 847 : lib = (enum built_in_function)((int)BUILT_IN_ATOMIC_FETCH_XOR_1 +
8876 : (fcode - BUILT_IN_ATOMIC_XOR_FETCH_1));
8877 847 : target = expand_builtin_atomic_fetch_op (mode, exp, target, XOR, true,
8878 : ignore, lib);
8879 847 : if (target)
8880 : return target;
8881 : break;
8882 : }
8883 965 : case BUILT_IN_ATOMIC_OR_FETCH_1:
8884 965 : case BUILT_IN_ATOMIC_OR_FETCH_2:
8885 965 : case BUILT_IN_ATOMIC_OR_FETCH_4:
8886 965 : case BUILT_IN_ATOMIC_OR_FETCH_8:
8887 965 : case BUILT_IN_ATOMIC_OR_FETCH_16:
8888 965 : {
8889 965 : enum built_in_function lib;
8890 965 : mode = get_builtin_sync_mode (fcode - BUILT_IN_ATOMIC_OR_FETCH_1);
8891 965 : lib = (enum built_in_function)((int)BUILT_IN_ATOMIC_FETCH_OR_1 +
8892 : (fcode - BUILT_IN_ATOMIC_OR_FETCH_1));
8893 965 : target = expand_builtin_atomic_fetch_op (mode, exp, target, IOR, true,
8894 : ignore, lib);
8895 965 : if (target)
8896 : return target;
8897 : break;
8898 : }
8899 14569 : case BUILT_IN_ATOMIC_FETCH_ADD_1:
8900 14569 : case BUILT_IN_ATOMIC_FETCH_ADD_2:
8901 14569 : case BUILT_IN_ATOMIC_FETCH_ADD_4:
8902 14569 : case BUILT_IN_ATOMIC_FETCH_ADD_8:
8903 14569 : case BUILT_IN_ATOMIC_FETCH_ADD_16:
8904 14569 : mode = get_builtin_sync_mode (fcode - BUILT_IN_ATOMIC_FETCH_ADD_1);
8905 14569 : target = expand_builtin_atomic_fetch_op (mode, exp, target, PLUS, false,
8906 : ignore, BUILT_IN_NONE);
8907 14569 : if (target)
8908 : return target;
8909 : break;
8910 :
8911 2107 : case BUILT_IN_ATOMIC_FETCH_SUB_1:
8912 2107 : case BUILT_IN_ATOMIC_FETCH_SUB_2:
8913 2107 : case BUILT_IN_ATOMIC_FETCH_SUB_4:
8914 2107 : case BUILT_IN_ATOMIC_FETCH_SUB_8:
8915 2107 : case BUILT_IN_ATOMIC_FETCH_SUB_16:
8916 2107 : mode = get_builtin_sync_mode (fcode - BUILT_IN_ATOMIC_FETCH_SUB_1);
8917 2107 : target = expand_builtin_atomic_fetch_op (mode, exp, target, MINUS, false,
8918 : ignore, BUILT_IN_NONE);
8919 2107 : if (target)
8920 : return target;
8921 : break;
8922 :
8923 785 : case BUILT_IN_ATOMIC_FETCH_AND_1:
8924 785 : case BUILT_IN_ATOMIC_FETCH_AND_2:
8925 785 : case BUILT_IN_ATOMIC_FETCH_AND_4:
8926 785 : case BUILT_IN_ATOMIC_FETCH_AND_8:
8927 785 : case BUILT_IN_ATOMIC_FETCH_AND_16:
8928 785 : mode = get_builtin_sync_mode (fcode - BUILT_IN_ATOMIC_FETCH_AND_1);
8929 785 : target = expand_builtin_atomic_fetch_op (mode, exp, target, AND, false,
8930 : ignore, BUILT_IN_NONE);
8931 785 : if (target)
8932 : return target;
8933 : break;
8934 :
8935 125 : case BUILT_IN_ATOMIC_FETCH_NAND_1:
8936 125 : case BUILT_IN_ATOMIC_FETCH_NAND_2:
8937 125 : case BUILT_IN_ATOMIC_FETCH_NAND_4:
8938 125 : case BUILT_IN_ATOMIC_FETCH_NAND_8:
8939 125 : case BUILT_IN_ATOMIC_FETCH_NAND_16:
8940 125 : mode = get_builtin_sync_mode (fcode - BUILT_IN_ATOMIC_FETCH_NAND_1);
8941 125 : target = expand_builtin_atomic_fetch_op (mode, exp, target, NOT, false,
8942 : ignore, BUILT_IN_NONE);
8943 125 : if (target)
8944 : return target;
8945 : break;
8946 :
8947 875 : case BUILT_IN_ATOMIC_FETCH_XOR_1:
8948 875 : case BUILT_IN_ATOMIC_FETCH_XOR_2:
8949 875 : case BUILT_IN_ATOMIC_FETCH_XOR_4:
8950 875 : case BUILT_IN_ATOMIC_FETCH_XOR_8:
8951 875 : case BUILT_IN_ATOMIC_FETCH_XOR_16:
8952 875 : mode = get_builtin_sync_mode (fcode - BUILT_IN_ATOMIC_FETCH_XOR_1);
8953 875 : target = expand_builtin_atomic_fetch_op (mode, exp, target, XOR, false,
8954 : ignore, BUILT_IN_NONE);
8955 875 : if (target)
8956 : return target;
8957 : break;
8958 :
8959 1140 : case BUILT_IN_ATOMIC_FETCH_OR_1:
8960 1140 : case BUILT_IN_ATOMIC_FETCH_OR_2:
8961 1140 : case BUILT_IN_ATOMIC_FETCH_OR_4:
8962 1140 : case BUILT_IN_ATOMIC_FETCH_OR_8:
8963 1140 : case BUILT_IN_ATOMIC_FETCH_OR_16:
8964 1140 : mode = get_builtin_sync_mode (fcode - BUILT_IN_ATOMIC_FETCH_OR_1);
8965 1140 : target = expand_builtin_atomic_fetch_op (mode, exp, target, IOR, false,
8966 : ignore, BUILT_IN_NONE);
8967 1140 : if (target)
8968 : return target;
8969 : break;
8970 :
8971 266 : case BUILT_IN_ATOMIC_TEST_AND_SET:
8972 266 : target = expand_builtin_atomic_test_and_set (exp, target);
8973 266 : if (target)
8974 : return target;
8975 : break;
8976 :
8977 53 : case BUILT_IN_ATOMIC_CLEAR:
8978 53 : return expand_builtin_atomic_clear (exp);
8979 :
8980 1 : case BUILT_IN_ATOMIC_ALWAYS_LOCK_FREE:
8981 1 : return expand_builtin_atomic_always_lock_free (exp);
8982 :
8983 10 : case BUILT_IN_ATOMIC_IS_LOCK_FREE:
8984 10 : target = expand_builtin_atomic_is_lock_free (exp);
8985 10 : if (target)
8986 : return target;
8987 : break;
8988 :
8989 693 : case BUILT_IN_ATOMIC_THREAD_FENCE:
8990 693 : expand_builtin_atomic_thread_fence (exp);
8991 693 : return const0_rtx;
8992 :
8993 60 : case BUILT_IN_ATOMIC_SIGNAL_FENCE:
8994 60 : expand_builtin_atomic_signal_fence (exp);
8995 60 : return const0_rtx;
8996 :
8997 620 : case BUILT_IN_OBJECT_SIZE:
8998 620 : case BUILT_IN_DYNAMIC_OBJECT_SIZE:
8999 620 : return expand_builtin_object_size (exp);
9000 :
9001 837 : case BUILT_IN_MEMCPY_CHK:
9002 837 : case BUILT_IN_MEMPCPY_CHK:
9003 837 : case BUILT_IN_MEMMOVE_CHK:
9004 837 : case BUILT_IN_MEMSET_CHK:
9005 837 : target = expand_builtin_memory_chk (exp, target, mode, fcode);
9006 837 : if (target)
9007 : return target;
9008 : break;
9009 :
9010 1086 : case BUILT_IN_STRCPY_CHK:
9011 1086 : case BUILT_IN_STPCPY_CHK:
9012 1086 : case BUILT_IN_STRNCPY_CHK:
9013 1086 : case BUILT_IN_STPNCPY_CHK:
9014 1086 : case BUILT_IN_STRCAT_CHK:
9015 1086 : case BUILT_IN_STRNCAT_CHK:
9016 1086 : case BUILT_IN_SNPRINTF_CHK:
9017 1086 : case BUILT_IN_VSNPRINTF_CHK:
9018 1086 : maybe_emit_chk_warning (exp, fcode);
9019 1086 : break;
9020 :
9021 1328 : case BUILT_IN_SPRINTF_CHK:
9022 1328 : case BUILT_IN_VSPRINTF_CHK:
9023 1328 : maybe_emit_sprintf_chk_warning (exp, fcode);
9024 1328 : break;
9025 :
9026 3 : case BUILT_IN_THREAD_POINTER:
9027 3 : return expand_builtin_thread_pointer (exp, target);
9028 :
9029 0 : case BUILT_IN_SET_THREAD_POINTER:
9030 0 : expand_builtin_set_thread_pointer (exp);
9031 0 : return const0_rtx;
9032 :
9033 : case BUILT_IN_ACC_ON_DEVICE:
9034 : /* Do library call, if we failed to expand the builtin when
9035 : folding. */
9036 : break;
9037 :
9038 356 : case BUILT_IN_GOACC_PARLEVEL_ID:
9039 356 : case BUILT_IN_GOACC_PARLEVEL_SIZE:
9040 356 : return expand_builtin_goacc_parlevel_id_size (exp, target, ignore);
9041 :
9042 4 : case BUILT_IN_SPECULATION_SAFE_VALUE_PTR:
9043 4 : return expand_speculation_safe_value (VOIDmode, exp, target, ignore);
9044 :
9045 30 : case BUILT_IN_SPECULATION_SAFE_VALUE_1:
9046 30 : case BUILT_IN_SPECULATION_SAFE_VALUE_2:
9047 30 : case BUILT_IN_SPECULATION_SAFE_VALUE_4:
9048 30 : case BUILT_IN_SPECULATION_SAFE_VALUE_8:
9049 30 : case BUILT_IN_SPECULATION_SAFE_VALUE_16:
9050 30 : mode = get_builtin_sync_mode (fcode - BUILT_IN_SPECULATION_SAFE_VALUE_1);
9051 30 : return expand_speculation_safe_value (mode, exp, target, ignore);
9052 :
9053 2 : case BUILT_IN_CRC8_DATA8:
9054 2 : return expand_builtin_crc_table_based (IFN_CRC, QImode, QImode, mode,
9055 : exp, target);
9056 2 : case BUILT_IN_CRC16_DATA8:
9057 2 : return expand_builtin_crc_table_based (IFN_CRC, HImode, QImode, mode,
9058 : exp, target);
9059 2 : case BUILT_IN_CRC16_DATA16:
9060 2 : return expand_builtin_crc_table_based (IFN_CRC, HImode, HImode, mode,
9061 : exp, target);
9062 2 : case BUILT_IN_CRC32_DATA8:
9063 2 : return expand_builtin_crc_table_based (IFN_CRC, SImode, QImode, mode,
9064 : exp, target);
9065 2 : case BUILT_IN_CRC32_DATA16:
9066 2 : return expand_builtin_crc_table_based (IFN_CRC, SImode, HImode, mode,
9067 : exp, target);
9068 14 : case BUILT_IN_CRC32_DATA32:
9069 14 : return expand_builtin_crc_table_based (IFN_CRC, SImode, SImode, mode,
9070 : exp, target);
9071 1 : case BUILT_IN_CRC64_DATA8:
9072 1 : return expand_builtin_crc_table_based (IFN_CRC, DImode, QImode, mode,
9073 : exp, target);
9074 1 : case BUILT_IN_CRC64_DATA16:
9075 1 : return expand_builtin_crc_table_based (IFN_CRC, DImode, HImode, mode,
9076 : exp, target);
9077 1 : case BUILT_IN_CRC64_DATA32:
9078 1 : return expand_builtin_crc_table_based (IFN_CRC, DImode, SImode, mode,
9079 : exp, target);
9080 1 : case BUILT_IN_CRC64_DATA64:
9081 1 : return expand_builtin_crc_table_based (IFN_CRC, DImode, DImode, mode,
9082 : exp, target);
9083 2 : case BUILT_IN_REV_CRC8_DATA8:
9084 2 : return expand_builtin_crc_table_based (IFN_CRC_REV, QImode, QImode,
9085 : mode, exp, target);
9086 2 : case BUILT_IN_REV_CRC16_DATA8:
9087 2 : return expand_builtin_crc_table_based (IFN_CRC_REV, HImode, QImode,
9088 : mode, exp, target);
9089 2 : case BUILT_IN_REV_CRC16_DATA16:
9090 2 : return expand_builtin_crc_table_based (IFN_CRC_REV, HImode, HImode,
9091 : mode, exp, target);
9092 3 : case BUILT_IN_REV_CRC32_DATA8:
9093 3 : return expand_builtin_crc_table_based (IFN_CRC_REV, SImode, QImode,
9094 : mode, exp, target);
9095 2 : case BUILT_IN_REV_CRC32_DATA16:
9096 2 : return expand_builtin_crc_table_based (IFN_CRC_REV, SImode, HImode,
9097 : mode, exp, target);
9098 2 : case BUILT_IN_REV_CRC32_DATA32:
9099 2 : return expand_builtin_crc_table_based (IFN_CRC_REV, SImode, SImode,
9100 : mode, exp, target);
9101 1 : case BUILT_IN_REV_CRC64_DATA8:
9102 1 : return expand_builtin_crc_table_based (IFN_CRC_REV, DImode, QImode,
9103 : mode, exp, target);
9104 1 : case BUILT_IN_REV_CRC64_DATA16:
9105 1 : return expand_builtin_crc_table_based (IFN_CRC_REV, DImode, HImode,
9106 : mode, exp, target);
9107 1 : case BUILT_IN_REV_CRC64_DATA32:
9108 1 : return expand_builtin_crc_table_based (IFN_CRC_REV, DImode, SImode,
9109 : mode, exp, target);
9110 1 : case BUILT_IN_REV_CRC64_DATA64:
9111 1 : return expand_builtin_crc_table_based (IFN_CRC_REV, DImode, DImode,
9112 : mode, exp, target);
9113 : default: /* just do library call, if unknown builtin */
9114 : break;
9115 : }
9116 :
9117 : /* The switch statement above can drop through to cause the function
9118 : to be called normally. */
9119 853211 : return expand_call (exp, target, ignore);
9120 : }
9121 :
9122 : /* Determine whether a tree node represents a call to a built-in
9123 : function. If the tree T is a call to a built-in function with
9124 : the right number of arguments of the appropriate types, return
9125 : the DECL_FUNCTION_CODE of the call, e.g. BUILT_IN_SQRT.
9126 : Otherwise the return value is END_BUILTINS. */
9127 :
9128 : enum built_in_function
9129 109284668 : builtin_mathfn_code (const_tree t)
9130 : {
9131 109284668 : const_tree fndecl, arg, parmlist;
9132 109284668 : const_tree argtype, parmtype;
9133 109284668 : const_call_expr_arg_iterator iter;
9134 :
9135 109284668 : if (TREE_CODE (t) != CALL_EXPR)
9136 : return END_BUILTINS;
9137 :
9138 1460942 : fndecl = get_callee_fndecl (t);
9139 1460942 : if (fndecl == NULL_TREE || !fndecl_built_in_p (fndecl, BUILT_IN_NORMAL))
9140 : return END_BUILTINS;
9141 :
9142 657437 : parmlist = TYPE_ARG_TYPES (TREE_TYPE (fndecl));
9143 657437 : init_const_call_expr_arg_iterator (t, &iter);
9144 2121524 : for (; parmlist; parmlist = TREE_CHAIN (parmlist))
9145 : {
9146 : /* If a function doesn't take a variable number of arguments,
9147 : the last element in the list will have type `void'. */
9148 1444500 : parmtype = TREE_VALUE (parmlist);
9149 1444500 : if (VOID_TYPE_P (parmtype))
9150 : {
9151 637836 : if (more_const_call_expr_args_p (&iter))
9152 : return END_BUILTINS;
9153 637836 : return DECL_FUNCTION_CODE (fndecl);
9154 : }
9155 :
9156 806664 : if (! more_const_call_expr_args_p (&iter))
9157 : return END_BUILTINS;
9158 :
9159 806664 : arg = next_const_call_expr_arg (&iter);
9160 806664 : argtype = TREE_TYPE (arg);
9161 :
9162 806664 : if (SCALAR_FLOAT_TYPE_P (parmtype))
9163 : {
9164 545611 : if (! SCALAR_FLOAT_TYPE_P (argtype))
9165 : return END_BUILTINS;
9166 : }
9167 261053 : else if (COMPLEX_FLOAT_TYPE_P (parmtype))
9168 : {
9169 7705 : if (! COMPLEX_FLOAT_TYPE_P (argtype))
9170 : return END_BUILTINS;
9171 : }
9172 253348 : else if (POINTER_TYPE_P (parmtype))
9173 : {
9174 75679 : if (! POINTER_TYPE_P (argtype))
9175 : return END_BUILTINS;
9176 : }
9177 177669 : else if (INTEGRAL_TYPE_P (parmtype))
9178 : {
9179 177669 : if (! INTEGRAL_TYPE_P (argtype))
9180 : return END_BUILTINS;
9181 : }
9182 : else
9183 : return END_BUILTINS;
9184 : }
9185 :
9186 : /* Variable-length argument list. */
9187 19587 : return DECL_FUNCTION_CODE (fndecl);
9188 : }
9189 :
9190 : /* Fold a call to __builtin_constant_p, if we know its argument ARG will
9191 : evaluate to a constant. */
9192 :
9193 : tree
9194 3285511 : fold_builtin_constant_p (tree arg)
9195 : {
9196 : /* We return 1 for a numeric type that's known to be a constant
9197 : value at compile-time or for an aggregate type that's a
9198 : literal constant. */
9199 3285511 : STRIP_NOPS (arg);
9200 :
9201 : /* If we know this is a constant, emit the constant of one. */
9202 3285511 : if (CONSTANT_CLASS_P (arg)
9203 3285511 : || (TREE_CODE (arg) == CONSTRUCTOR
9204 6 : && TREE_CONSTANT (arg)))
9205 1835085 : return integer_one_node;
9206 1450426 : if (TREE_CODE (arg) == ADDR_EXPR)
9207 : {
9208 110 : tree op = TREE_OPERAND (arg, 0);
9209 110 : if (TREE_CODE (op) == STRING_CST
9210 110 : || (TREE_CODE (op) == ARRAY_REF
9211 57 : && integer_zerop (TREE_OPERAND (op, 1))
9212 57 : && TREE_CODE (TREE_OPERAND (op, 0)) == STRING_CST))
9213 87 : return integer_one_node;
9214 : }
9215 :
9216 : /* If this expression has side effects, show we don't know it to be a
9217 : constant. Likewise if it's a pointer or aggregate type since in
9218 : those case we only want literals, since those are only optimized
9219 : when generating RTL, not later.
9220 : And finally, if we are compiling an initializer, not code, we
9221 : need to return a definite result now; there's not going to be any
9222 : more optimization done. */
9223 1450339 : if (TREE_SIDE_EFFECTS (arg)
9224 1450214 : || AGGREGATE_TYPE_P (TREE_TYPE (arg))
9225 1450208 : || POINTER_TYPE_P (TREE_TYPE (arg))
9226 1450037 : || cfun == 0
9227 1449944 : || folding_initializer
9228 2900276 : || force_folding_builtin_constant_p)
9229 497 : return integer_zero_node;
9230 :
9231 : return NULL_TREE;
9232 : }
9233 :
9234 : /* Create builtin_expect or builtin_expect_with_probability
9235 : with PRED and EXPECTED as its arguments and return it as a truthvalue.
9236 : Fortran FE can also produce builtin_expect with PREDICTOR as third argument.
9237 : builtin_expect_with_probability instead uses third argument as PROBABILITY
9238 : value. */
9239 :
9240 : static tree
9241 225516 : build_builtin_expect_predicate (location_t loc, tree pred, tree expected,
9242 : tree predictor, tree probability)
9243 : {
9244 225516 : tree fn, arg_types, pred_type, expected_type, call_expr, ret_type;
9245 :
9246 225516 : fn = builtin_decl_explicit (probability == NULL_TREE ? BUILT_IN_EXPECT
9247 : : BUILT_IN_EXPECT_WITH_PROBABILITY);
9248 225516 : arg_types = TYPE_ARG_TYPES (TREE_TYPE (fn));
9249 225516 : ret_type = TREE_TYPE (TREE_TYPE (fn));
9250 225516 : pred_type = TREE_VALUE (arg_types);
9251 225516 : expected_type = TREE_VALUE (TREE_CHAIN (arg_types));
9252 :
9253 225516 : pred = fold_convert_loc (loc, pred_type, pred);
9254 225516 : expected = fold_convert_loc (loc, expected_type, expected);
9255 :
9256 225516 : if (probability)
9257 0 : call_expr = build_call_expr_loc (loc, fn, 3, pred, expected, probability);
9258 : else
9259 451032 : call_expr = build_call_expr_loc (loc, fn, predictor ? 3 : 2, pred, expected,
9260 : predictor);
9261 :
9262 225516 : return build2 (NE_EXPR, TREE_TYPE (pred), call_expr,
9263 225516 : build_int_cst (ret_type, 0));
9264 : }
9265 :
9266 : /* Fold a call to builtin_expect with arguments ARG0, ARG1, ARG2, ARG3. Return
9267 : NULL_TREE if no simplification is possible. */
9268 :
9269 : tree
9270 7435730 : fold_builtin_expect (location_t loc, tree arg0, tree arg1, tree arg2,
9271 : tree arg3)
9272 : {
9273 7435730 : tree inner, fndecl, inner_arg0;
9274 7435730 : enum tree_code code;
9275 :
9276 : /* Distribute the expected value over short-circuiting operators.
9277 : See through the cast from truthvalue_type_node to long. */
9278 7435730 : inner_arg0 = arg0;
9279 15185252 : while (CONVERT_EXPR_P (inner_arg0)
9280 1068660 : && INTEGRAL_TYPE_P (TREE_TYPE (inner_arg0))
9281 9573049 : && INTEGRAL_TYPE_P (TREE_TYPE (TREE_OPERAND (inner_arg0, 0))))
9282 1068659 : inner_arg0 = TREE_OPERAND (inner_arg0, 0);
9283 :
9284 : /* If this is a builtin_expect within a builtin_expect keep the
9285 : inner one. See through a comparison against a constant. It
9286 : might have been added to create a thruthvalue. */
9287 7435730 : inner = inner_arg0;
9288 :
9289 7435730 : if (COMPARISON_CLASS_P (inner)
9290 7435730 : && TREE_CODE (TREE_OPERAND (inner, 1)) == INTEGER_CST)
9291 1428515 : inner = TREE_OPERAND (inner, 0);
9292 :
9293 7435730 : if (TREE_CODE (inner) == CALL_EXPR
9294 176546 : && (fndecl = get_callee_fndecl (inner))
9295 7612276 : && fndecl_built_in_p (fndecl, BUILT_IN_EXPECT,
9296 : BUILT_IN_EXPECT_WITH_PROBABILITY))
9297 : return arg0;
9298 :
9299 7435722 : inner = inner_arg0;
9300 7435722 : code = TREE_CODE (inner);
9301 7435722 : if (code == TRUTH_ANDIF_EXPR || code == TRUTH_ORIF_EXPR)
9302 : {
9303 112758 : tree op0 = TREE_OPERAND (inner, 0);
9304 112758 : tree op1 = TREE_OPERAND (inner, 1);
9305 112758 : arg1 = save_expr (arg1);
9306 :
9307 112758 : op0 = build_builtin_expect_predicate (loc, op0, arg1, arg2, arg3);
9308 112758 : op1 = build_builtin_expect_predicate (loc, op1, arg1, arg2, arg3);
9309 112758 : inner = build2 (code, TREE_TYPE (inner), op0, op1);
9310 :
9311 112758 : return fold_convert_loc (loc, TREE_TYPE (arg0), inner);
9312 : }
9313 :
9314 : /* If the argument isn't invariant then there's nothing else we can do. */
9315 7322964 : if (!TREE_CONSTANT (inner_arg0))
9316 : return NULL_TREE;
9317 :
9318 : /* If we expect that a comparison against the argument will fold to
9319 : a constant return the constant. In practice, this means a true
9320 : constant or the address of a non-weak symbol. */
9321 253254 : inner = inner_arg0;
9322 253254 : STRIP_NOPS (inner);
9323 253254 : if (TREE_CODE (inner) == ADDR_EXPR)
9324 : {
9325 1 : do
9326 : {
9327 1 : inner = TREE_OPERAND (inner, 0);
9328 : }
9329 1 : while (TREE_CODE (inner) == COMPONENT_REF
9330 1 : || TREE_CODE (inner) == ARRAY_REF);
9331 1 : if (VAR_OR_FUNCTION_DECL_P (inner) && DECL_WEAK (inner))
9332 0 : return NULL_TREE;
9333 : }
9334 :
9335 : /* Otherwise, ARG0 already has the proper type for the return value. */
9336 : return arg0;
9337 : }
9338 :
9339 : /* Fold a call to __builtin_classify_type with argument ARG. */
9340 :
9341 : static tree
9342 2078 : fold_builtin_classify_type (tree arg)
9343 : {
9344 2078 : if (arg == 0)
9345 0 : return build_int_cst (integer_type_node, no_type_class);
9346 :
9347 2078 : return build_int_cst (integer_type_node, type_to_class (TREE_TYPE (arg)));
9348 : }
9349 :
9350 : /* Fold a call EXPR (which may be null) to __builtin_strlen with argument
9351 : ARG. */
9352 :
9353 : static tree
9354 476464 : fold_builtin_strlen (location_t loc, tree expr, tree type, tree arg)
9355 : {
9356 476464 : if (!validate_arg (arg, POINTER_TYPE))
9357 : return NULL_TREE;
9358 : else
9359 : {
9360 476461 : c_strlen_data lendata = { };
9361 476461 : tree len = c_strlen (arg, 0, &lendata);
9362 :
9363 476461 : if (len)
9364 2231 : return fold_convert_loc (loc, type, len);
9365 :
9366 : /* TODO: Move this to gimple-ssa-warn-access once the pass runs
9367 : also early enough to detect invalid reads in multimensional
9368 : arrays and struct members. */
9369 474230 : if (!lendata.decl)
9370 467052 : c_strlen (arg, 1, &lendata);
9371 :
9372 474230 : if (lendata.decl)
9373 : {
9374 7192 : if (EXPR_HAS_LOCATION (arg))
9375 2800 : loc = EXPR_LOCATION (arg);
9376 4392 : else if (loc == UNKNOWN_LOCATION)
9377 0 : loc = input_location;
9378 7192 : warn_string_no_nul (loc, expr, "strlen", arg, lendata.decl);
9379 : }
9380 :
9381 : return NULL_TREE;
9382 : }
9383 : }
9384 :
9385 : /* Fold a call to __builtin_inf or __builtin_huge_val. */
9386 :
9387 : static tree
9388 263612 : fold_builtin_inf (location_t loc, tree type, int warn)
9389 : {
9390 : /* __builtin_inff is intended to be usable to define INFINITY on all
9391 : targets. If an infinity is not available, INFINITY expands "to a
9392 : positive constant of type float that overflows at translation
9393 : time", footnote "In this case, using INFINITY will violate the
9394 : constraint in 6.4.4 and thus require a diagnostic." (C99 7.12#4).
9395 : Thus we pedwarn to ensure this constraint violation is
9396 : diagnosed. */
9397 1053639 : if (!MODE_HAS_INFINITIES (TYPE_MODE (type)) && warn)
9398 0 : pedwarn (loc, 0, "target format does not support infinity");
9399 :
9400 263612 : return build_real (type, dconstinf);
9401 : }
9402 :
9403 : /* Fold function call to builtin sincos, sincosf, or sincosl. Return
9404 : NULL_TREE if no simplification can be made. */
9405 :
9406 : static tree
9407 145 : fold_builtin_sincos (location_t loc,
9408 : tree arg0, tree arg1, tree arg2)
9409 : {
9410 145 : tree type;
9411 145 : tree fndecl, call = NULL_TREE;
9412 :
9413 145 : if (!validate_arg (arg0, REAL_TYPE)
9414 145 : || !validate_arg (arg1, POINTER_TYPE)
9415 290 : || !validate_arg (arg2, POINTER_TYPE))
9416 : return NULL_TREE;
9417 :
9418 145 : type = TREE_TYPE (arg0);
9419 :
9420 : /* Calculate the result when the argument is a constant. */
9421 145 : built_in_function fn = mathfn_built_in_2 (type, CFN_BUILT_IN_CEXPI);
9422 145 : if (fn == END_BUILTINS)
9423 : return NULL_TREE;
9424 :
9425 : /* Canonicalize sincos to cexpi. */
9426 145 : if (TREE_CODE (arg0) == REAL_CST)
9427 : {
9428 86 : tree complex_type = build_complex_type (type);
9429 86 : call = fold_const_call (as_combined_fn (fn), complex_type, arg0);
9430 : }
9431 86 : if (!call)
9432 : {
9433 59 : if (!targetm.libc_has_function (function_c99_math_complex, type)
9434 59 : || !builtin_decl_implicit_p (fn))
9435 : return NULL_TREE;
9436 59 : fndecl = builtin_decl_explicit (fn);
9437 59 : call = build_call_expr_loc (loc, fndecl, 1, arg0);
9438 59 : call = builtin_save_expr (call);
9439 : }
9440 :
9441 145 : tree ptype = build_pointer_type (type);
9442 145 : arg1 = fold_convert (ptype, arg1);
9443 145 : arg2 = fold_convert (ptype, arg2);
9444 145 : return build2 (COMPOUND_EXPR, void_type_node,
9445 : build2 (MODIFY_EXPR, void_type_node,
9446 : build_fold_indirect_ref_loc (loc, arg1),
9447 : fold_build1_loc (loc, IMAGPART_EXPR, type, call)),
9448 : build2 (MODIFY_EXPR, void_type_node,
9449 : build_fold_indirect_ref_loc (loc, arg2),
9450 145 : fold_build1_loc (loc, REALPART_EXPR, type, call)));
9451 : }
9452 :
9453 : /* Fold function call to builtin memcmp with arguments ARG1 and ARG2.
9454 : Return NULL_TREE if no simplification can be made. */
9455 :
9456 : static tree
9457 2568558 : fold_builtin_memcmp (location_t loc, tree arg1, tree arg2, tree len)
9458 : {
9459 2568558 : if (!validate_arg (arg1, POINTER_TYPE)
9460 2568558 : || !validate_arg (arg2, POINTER_TYPE)
9461 5137116 : || !validate_arg (len, INTEGER_TYPE))
9462 : return NULL_TREE;
9463 :
9464 : /* If the LEN parameter is zero, return zero. */
9465 2568558 : if (integer_zerop (len))
9466 0 : return omit_two_operands_loc (loc, integer_type_node, integer_zero_node,
9467 0 : arg1, arg2);
9468 :
9469 : /* If ARG1 and ARG2 are the same (and not volatile), return zero. */
9470 2568558 : if (operand_equal_p (arg1, arg2, 0))
9471 697 : return omit_one_operand_loc (loc, integer_type_node, integer_zero_node, len);
9472 :
9473 : /* If len parameter is one, return an expression corresponding to
9474 : (*(const unsigned char*)arg1 - (const unsigned char*)arg2). */
9475 2567861 : if (tree_fits_uhwi_p (len) && tree_to_uhwi (len) == 1)
9476 : {
9477 55087 : tree cst_uchar_node = build_type_variant (unsigned_char_type_node, 1, 0);
9478 55087 : tree cst_uchar_ptr_node
9479 55087 : = build_pointer_type_for_mode (cst_uchar_node, ptr_mode, true);
9480 :
9481 55087 : tree ind1
9482 55087 : = fold_convert_loc (loc, integer_type_node,
9483 : build1 (INDIRECT_REF, cst_uchar_node,
9484 : fold_convert_loc (loc,
9485 : cst_uchar_ptr_node,
9486 : arg1)));
9487 55087 : tree ind2
9488 55087 : = fold_convert_loc (loc, integer_type_node,
9489 : build1 (INDIRECT_REF, cst_uchar_node,
9490 : fold_convert_loc (loc,
9491 : cst_uchar_ptr_node,
9492 : arg2)));
9493 55087 : return fold_build2_loc (loc, MINUS_EXPR, integer_type_node, ind1, ind2);
9494 : }
9495 :
9496 : return NULL_TREE;
9497 : }
9498 :
9499 : /* Fold a call to builtin isascii with argument ARG. */
9500 :
9501 : static tree
9502 211 : fold_builtin_isascii (location_t loc, tree arg)
9503 : {
9504 211 : if (!validate_arg (arg, INTEGER_TYPE))
9505 : return NULL_TREE;
9506 : else
9507 : {
9508 : /* Transform isascii(c) -> ((c & ~0x7f) == 0). */
9509 211 : arg = fold_build2 (BIT_AND_EXPR, integer_type_node, arg,
9510 : build_int_cst (integer_type_node,
9511 : ~ HOST_WIDE_INT_UC (0x7f)));
9512 211 : return fold_build2_loc (loc, EQ_EXPR, integer_type_node,
9513 211 : arg, integer_zero_node);
9514 : }
9515 : }
9516 :
9517 : /* Fold a call to builtin toascii with argument ARG. */
9518 :
9519 : static tree
9520 168 : fold_builtin_toascii (location_t loc, tree arg)
9521 : {
9522 168 : if (!validate_arg (arg, INTEGER_TYPE))
9523 : return NULL_TREE;
9524 :
9525 : /* Transform toascii(c) -> (c & 0x7f). */
9526 168 : return fold_build2_loc (loc, BIT_AND_EXPR, integer_type_node, arg,
9527 : build_int_cst (integer_type_node, 0x7f));
9528 : }
9529 :
9530 : /* Fold a call to builtin isdigit with argument ARG. */
9531 :
9532 : static tree
9533 325 : fold_builtin_isdigit (location_t loc, tree arg)
9534 : {
9535 325 : if (!validate_arg (arg, INTEGER_TYPE))
9536 : return NULL_TREE;
9537 : else
9538 : {
9539 : /* Transform isdigit(c) -> (unsigned)(c) - '0' <= 9. */
9540 : /* According to the C standard, isdigit is unaffected by locale.
9541 : However, it definitely is affected by the target character set. */
9542 313 : unsigned HOST_WIDE_INT target_digit0
9543 313 : = lang_hooks.to_target_charset ('0');
9544 :
9545 313 : if (target_digit0 == 0)
9546 : return NULL_TREE;
9547 :
9548 313 : arg = fold_convert_loc (loc, unsigned_type_node, arg);
9549 313 : arg = fold_build2 (MINUS_EXPR, unsigned_type_node, arg,
9550 : build_int_cst (unsigned_type_node, target_digit0));
9551 313 : return fold_build2_loc (loc, LE_EXPR, integer_type_node, arg,
9552 : build_int_cst (unsigned_type_node, 9));
9553 : }
9554 : }
9555 :
9556 : /* Fold a call to fabs, fabsf or fabsl with argument ARG. */
9557 :
9558 : static tree
9559 378195 : fold_builtin_fabs (location_t loc, tree arg, tree type)
9560 : {
9561 378195 : if (!validate_arg (arg, REAL_TYPE))
9562 : return NULL_TREE;
9563 :
9564 378110 : arg = fold_convert_loc (loc, type, arg);
9565 378110 : return fold_build1_loc (loc, ABS_EXPR, type, arg);
9566 : }
9567 :
9568 : /* Fold a call to abs, labs, llabs, imaxabs, uabs, ulabs, ullabs or uimaxabs
9569 : with argument ARG. */
9570 :
9571 : static tree
9572 101153 : fold_builtin_abs (location_t loc, tree arg, tree type)
9573 : {
9574 101153 : if (!validate_arg (arg, INTEGER_TYPE) || !INTEGRAL_TYPE_P (type))
9575 : return NULL_TREE;
9576 :
9577 101105 : if (TYPE_UNSIGNED (type))
9578 : {
9579 1168 : if (TYPE_PRECISION (TREE_TYPE (arg))
9580 1168 : != TYPE_PRECISION (type)
9581 1168 : || TYPE_UNSIGNED (TREE_TYPE (arg)))
9582 : return NULL_TREE;
9583 1168 : return fold_build1_loc (loc, ABSU_EXPR, type, arg);
9584 : }
9585 99937 : arg = fold_convert_loc (loc, type, arg);
9586 99937 : return fold_build1_loc (loc, ABS_EXPR, type, arg);
9587 : }
9588 :
9589 : /* Fold a call to builtin carg(a+bi) -> atan2(b,a). */
9590 :
9591 : static tree
9592 104371 : fold_builtin_carg (location_t loc, tree arg, tree type)
9593 : {
9594 104371 : if (validate_arg (arg, COMPLEX_TYPE)
9595 104371 : && SCALAR_FLOAT_TYPE_P (TREE_TYPE (TREE_TYPE (arg))))
9596 : {
9597 104371 : tree atan2_fn = mathfn_built_in (type, BUILT_IN_ATAN2);
9598 :
9599 104371 : if (atan2_fn)
9600 : {
9601 100503 : tree new_arg = builtin_save_expr (arg);
9602 100503 : tree r_arg = fold_build1_loc (loc, REALPART_EXPR, type, new_arg);
9603 100503 : tree i_arg = fold_build1_loc (loc, IMAGPART_EXPR, type, new_arg);
9604 100503 : return build_call_expr_loc (loc, atan2_fn, 2, i_arg, r_arg);
9605 : }
9606 : }
9607 :
9608 : return NULL_TREE;
9609 : }
9610 :
9611 : /* Fold a call to builtin frexp, we can assume the base is 2. */
9612 :
9613 : static tree
9614 115911 : fold_builtin_frexp (location_t loc, tree arg0, tree arg1, tree rettype)
9615 : {
9616 115911 : if (! validate_arg (arg0, REAL_TYPE) || ! validate_arg (arg1, POINTER_TYPE))
9617 : return NULL_TREE;
9618 :
9619 115911 : STRIP_NOPS (arg0);
9620 :
9621 115911 : if (!(TREE_CODE (arg0) == REAL_CST && ! TREE_OVERFLOW (arg0)))
9622 : return NULL_TREE;
9623 :
9624 2210 : arg1 = build_fold_indirect_ref_loc (loc, arg1);
9625 :
9626 : /* Proceed if a valid pointer type was passed in. */
9627 2210 : if (TYPE_MAIN_VARIANT (TREE_TYPE (arg1)) == integer_type_node)
9628 : {
9629 2210 : const REAL_VALUE_TYPE *const value = TREE_REAL_CST_PTR (arg0);
9630 2210 : tree frac, exp, res;
9631 :
9632 2210 : switch (value->cl)
9633 : {
9634 276 : case rvc_zero:
9635 276 : case rvc_nan:
9636 276 : case rvc_inf:
9637 : /* For +-0, return (*exp = 0, +-0). */
9638 : /* For +-NaN or +-Inf, *exp is unspecified, but something should
9639 : be stored there so that it isn't read from uninitialized object.
9640 : As glibc and newlib store *exp = 0 for +-Inf/NaN, storing
9641 : 0 here as well is easiest. */
9642 276 : exp = integer_zero_node;
9643 276 : frac = arg0;
9644 276 : break;
9645 1934 : case rvc_normal:
9646 1934 : {
9647 : /* Since the frexp function always expects base 2, and in
9648 : GCC normalized significands are already in the range
9649 : [0.5, 1.0), we have exactly what frexp wants. */
9650 1934 : REAL_VALUE_TYPE frac_rvt = *value;
9651 1934 : SET_REAL_EXP (&frac_rvt, 0);
9652 1934 : frac = build_real (rettype, frac_rvt);
9653 1934 : exp = build_int_cst (integer_type_node, REAL_EXP (value));
9654 : }
9655 1934 : break;
9656 0 : default:
9657 0 : gcc_unreachable ();
9658 : }
9659 :
9660 : /* Create the COMPOUND_EXPR (*arg1 = trunc, frac). */
9661 2210 : arg1 = fold_build2_loc (loc, MODIFY_EXPR, rettype, arg1, exp);
9662 2210 : TREE_SIDE_EFFECTS (arg1) = 1;
9663 2210 : res = fold_build2_loc (loc, COMPOUND_EXPR, rettype, arg1, frac);
9664 2210 : suppress_warning (res, OPT_Wunused_value);
9665 2210 : return res;
9666 : }
9667 :
9668 : return NULL_TREE;
9669 : }
9670 :
9671 : /* Fold a call to builtin modf. */
9672 :
9673 : static tree
9674 92826 : fold_builtin_modf (location_t loc, tree arg0, tree arg1, tree rettype)
9675 : {
9676 92826 : if (! validate_arg (arg0, REAL_TYPE) || ! validate_arg (arg1, POINTER_TYPE))
9677 : return NULL_TREE;
9678 :
9679 92826 : STRIP_NOPS (arg0);
9680 :
9681 92826 : if (!(TREE_CODE (arg0) == REAL_CST && ! TREE_OVERFLOW (arg0)))
9682 : return NULL_TREE;
9683 :
9684 2474 : arg1 = build_fold_indirect_ref_loc (loc, arg1);
9685 :
9686 : /* Proceed if a valid pointer type was passed in. */
9687 2474 : if (TYPE_MAIN_VARIANT (TREE_TYPE (arg1)) == TYPE_MAIN_VARIANT (rettype))
9688 : {
9689 2474 : const REAL_VALUE_TYPE *const value = TREE_REAL_CST_PTR (arg0);
9690 2474 : REAL_VALUE_TYPE trunc, frac;
9691 2474 : tree res;
9692 :
9693 2474 : switch (value->cl)
9694 : {
9695 228 : case rvc_nan:
9696 228 : case rvc_zero:
9697 : /* For +-NaN or +-0, return (*arg1 = arg0, arg0). */
9698 228 : trunc = frac = *value;
9699 228 : break;
9700 96 : case rvc_inf:
9701 : /* For +-Inf, return (*arg1 = arg0, +-0). */
9702 96 : frac = dconst0;
9703 96 : frac.sign = value->sign;
9704 96 : trunc = *value;
9705 96 : break;
9706 2150 : case rvc_normal:
9707 : /* Return (*arg1 = trunc(arg0), arg0-trunc(arg0)). */
9708 2150 : real_trunc (&trunc, VOIDmode, value);
9709 2150 : real_arithmetic (&frac, MINUS_EXPR, value, &trunc);
9710 : /* If the original number was negative and already
9711 : integral, then the fractional part is -0.0. */
9712 2150 : if (value->sign && frac.cl == rvc_zero)
9713 69 : frac.sign = value->sign;
9714 : break;
9715 : }
9716 :
9717 : /* Create the COMPOUND_EXPR (*arg1 = trunc, frac). */
9718 2474 : arg1 = fold_build2_loc (loc, MODIFY_EXPR, rettype, arg1,
9719 : build_real (rettype, trunc));
9720 2474 : TREE_SIDE_EFFECTS (arg1) = 1;
9721 2474 : res = fold_build2_loc (loc, COMPOUND_EXPR, rettype, arg1,
9722 : build_real (rettype, frac));
9723 2474 : suppress_warning (res, OPT_Wunused_value);
9724 2474 : return res;
9725 : }
9726 :
9727 : return NULL_TREE;
9728 : }
9729 :
9730 : /* Given a location LOC, an interclass builtin function decl FNDECL
9731 : and its single argument ARG, return an folded expression computing
9732 : the same, or NULL_TREE if we either couldn't or didn't want to fold
9733 : (the latter happen if there's an RTL instruction available). */
9734 :
9735 : static tree
9736 1818515 : fold_builtin_interclass_mathfn (location_t loc, tree fndecl, tree arg)
9737 : {
9738 1818515 : machine_mode mode;
9739 :
9740 1818515 : if (!validate_arg (arg, REAL_TYPE))
9741 : return NULL_TREE;
9742 :
9743 1818515 : if (interclass_mathfn_icode (arg, fndecl) != CODE_FOR_nothing)
9744 : return NULL_TREE;
9745 :
9746 1818515 : mode = TYPE_MODE (TREE_TYPE (arg));
9747 :
9748 12725763 : bool is_ibm_extended = MODE_COMPOSITE_P (mode);
9749 :
9750 : /* If there is no optab, try generic code. */
9751 1818515 : switch (DECL_FUNCTION_CODE (fndecl))
9752 : {
9753 708836 : tree result;
9754 :
9755 708836 : CASE_FLT_FN (BUILT_IN_ISINF):
9756 708836 : {
9757 : /* isinf(x) -> isgreater(fabs(x),DBL_MAX). */
9758 708836 : tree const isgr_fn = builtin_decl_explicit (BUILT_IN_ISGREATER);
9759 708836 : tree type = TREE_TYPE (arg);
9760 708836 : REAL_VALUE_TYPE r;
9761 708836 : char buf[128];
9762 :
9763 708836 : if (is_ibm_extended)
9764 : {
9765 : /* NaN and Inf are encoded in the high-order double value
9766 : only. The low-order value is not significant. */
9767 0 : type = double_type_node;
9768 0 : mode = DFmode;
9769 0 : arg = fold_build1_loc (loc, NOP_EXPR, type, arg);
9770 : }
9771 708836 : get_max_float (REAL_MODE_FORMAT (mode), buf, sizeof (buf), false);
9772 708836 : real_from_string3 (&r, buf, mode);
9773 708836 : result = build_call_expr (isgr_fn, 2,
9774 : fold_build1_loc (loc, ABS_EXPR, type, arg),
9775 : build_real (type, r));
9776 708836 : return result;
9777 : }
9778 625359 : CASE_FLT_FN (BUILT_IN_FINITE):
9779 625359 : case BUILT_IN_ISFINITE:
9780 625359 : {
9781 : /* isfinite(x) -> islessequal(fabs(x),DBL_MAX). */
9782 625359 : tree const isle_fn = builtin_decl_explicit (BUILT_IN_ISLESSEQUAL);
9783 625359 : tree type = TREE_TYPE (arg);
9784 625359 : REAL_VALUE_TYPE r;
9785 625359 : char buf[128];
9786 :
9787 625359 : if (is_ibm_extended)
9788 : {
9789 : /* NaN and Inf are encoded in the high-order double value
9790 : only. The low-order value is not significant. */
9791 0 : type = double_type_node;
9792 0 : mode = DFmode;
9793 0 : arg = fold_build1_loc (loc, NOP_EXPR, type, arg);
9794 : }
9795 625359 : get_max_float (REAL_MODE_FORMAT (mode), buf, sizeof (buf), false);
9796 625359 : real_from_string3 (&r, buf, mode);
9797 625359 : result = build_call_expr (isle_fn, 2,
9798 : fold_build1_loc (loc, ABS_EXPR, type, arg),
9799 : build_real (type, r));
9800 : /*result = fold_build2_loc (loc, UNGT_EXPR,
9801 : TREE_TYPE (TREE_TYPE (fndecl)),
9802 : fold_build1_loc (loc, ABS_EXPR, type, arg),
9803 : build_real (type, r));
9804 : result = fold_build1_loc (loc, TRUTH_NOT_EXPR,
9805 : TREE_TYPE (TREE_TYPE (fndecl)),
9806 : result);*/
9807 625359 : return result;
9808 : }
9809 239896 : case BUILT_IN_ISNORMAL:
9810 239896 : {
9811 : /* isnormal(x) -> isgreaterequal(fabs(x),DBL_MIN) &
9812 : islessequal(fabs(x),DBL_MAX). */
9813 239896 : tree const isle_fn = builtin_decl_explicit (BUILT_IN_ISLESSEQUAL);
9814 239896 : tree type = TREE_TYPE (arg);
9815 239896 : tree orig_arg, max_exp, min_exp;
9816 239896 : machine_mode orig_mode = mode;
9817 239896 : REAL_VALUE_TYPE rmax, rmin;
9818 239896 : char buf[128];
9819 :
9820 239896 : orig_arg = arg = builtin_save_expr (arg);
9821 239896 : if (is_ibm_extended)
9822 : {
9823 : /* Use double to test the normal range of IBM extended
9824 : precision. Emin for IBM extended precision is
9825 : different to emin for IEEE double, being 53 higher
9826 : since the low double exponent is at least 53 lower
9827 : than the high double exponent. */
9828 0 : type = double_type_node;
9829 0 : mode = DFmode;
9830 0 : arg = fold_build1_loc (loc, NOP_EXPR, type, arg);
9831 : }
9832 239896 : arg = fold_build1_loc (loc, ABS_EXPR, type, arg);
9833 :
9834 239896 : get_max_float (REAL_MODE_FORMAT (mode), buf, sizeof (buf), false);
9835 239896 : real_from_string3 (&rmax, buf, mode);
9836 239896 : if (DECIMAL_FLOAT_MODE_P (mode))
9837 1 : sprintf (buf, "1E%d", REAL_MODE_FORMAT (orig_mode)->emin - 1);
9838 : else
9839 239895 : sprintf (buf, "0x1p%d", REAL_MODE_FORMAT (orig_mode)->emin - 1);
9840 239896 : real_from_string3 (&rmin, buf, orig_mode);
9841 239896 : max_exp = build_real (type, rmax);
9842 239896 : min_exp = build_real (type, rmin);
9843 :
9844 239896 : max_exp = build_call_expr (isle_fn, 2, arg, max_exp);
9845 239896 : if (is_ibm_extended)
9846 : {
9847 : /* Testing the high end of the range is done just using
9848 : the high double, using the same test as isfinite().
9849 : For the subnormal end of the range we first test the
9850 : high double, then if its magnitude is equal to the
9851 : limit of 0x1p-969, we test whether the low double is
9852 : non-zero and opposite sign to the high double. */
9853 0 : tree const islt_fn = builtin_decl_explicit (BUILT_IN_ISLESS);
9854 0 : tree const isgt_fn = builtin_decl_explicit (BUILT_IN_ISGREATER);
9855 0 : tree gt_min = build_call_expr (isgt_fn, 2, arg, min_exp);
9856 0 : tree eq_min = fold_build2 (EQ_EXPR, integer_type_node,
9857 : arg, min_exp);
9858 0 : tree as_complex = build1 (VIEW_CONVERT_EXPR,
9859 : complex_double_type_node, orig_arg);
9860 0 : tree hi_dbl = build1 (REALPART_EXPR, type, as_complex);
9861 0 : tree lo_dbl = build1 (IMAGPART_EXPR, type, as_complex);
9862 0 : tree zero = build_real (type, dconst0);
9863 0 : tree hilt = build_call_expr (islt_fn, 2, hi_dbl, zero);
9864 0 : tree lolt = build_call_expr (islt_fn, 2, lo_dbl, zero);
9865 0 : tree logt = build_call_expr (isgt_fn, 2, lo_dbl, zero);
9866 0 : tree ok_lo = fold_build1 (TRUTH_NOT_EXPR, integer_type_node,
9867 : fold_build3 (COND_EXPR,
9868 : integer_type_node,
9869 : hilt, logt, lolt));
9870 0 : eq_min = fold_build2 (TRUTH_ANDIF_EXPR, integer_type_node,
9871 : eq_min, ok_lo);
9872 0 : min_exp = fold_build2 (TRUTH_ORIF_EXPR, integer_type_node,
9873 : gt_min, eq_min);
9874 : }
9875 : else
9876 : {
9877 239896 : tree const isge_fn
9878 239896 : = builtin_decl_explicit (BUILT_IN_ISGREATEREQUAL);
9879 239896 : min_exp = build_call_expr (isge_fn, 2, arg, min_exp);
9880 : }
9881 239896 : result = fold_build2 (BIT_AND_EXPR, integer_type_node,
9882 : max_exp, min_exp);
9883 239896 : return result;
9884 : }
9885 242890 : CASE_FLT_FN (BUILT_IN_ISNAN):
9886 242890 : case BUILT_IN_ISNAND32:
9887 242890 : case BUILT_IN_ISNAND64:
9888 242890 : case BUILT_IN_ISNAND128:
9889 242890 : {
9890 : /* In IBM extended NaN and Inf are encoded in the high-order double
9891 : value only. The low-order value is not significant. */
9892 242890 : if (is_ibm_extended)
9893 0 : arg = fold_build1_loc (loc, NOP_EXPR, double_type_node, arg);
9894 242890 : arg = builtin_save_expr (arg);
9895 242890 : tree type = TREE_TYPE (TREE_TYPE (fndecl));
9896 242890 : return fold_build2_loc (loc, UNORDERED_EXPR, type, arg, arg);
9897 : }
9898 : default:
9899 : break;
9900 : }
9901 :
9902 : return NULL_TREE;
9903 : }
9904 :
9905 : /* Fold a call to __builtin_isnan(), __builtin_isinf, __builtin_finite.
9906 : ARG is the argument for the call. */
9907 :
9908 : static tree
9909 1607849 : fold_builtin_classify (location_t loc, tree fndecl, tree arg, int builtin_index)
9910 : {
9911 1607849 : tree type = TREE_TYPE (TREE_TYPE (fndecl));
9912 :
9913 1607849 : if (!validate_arg (arg, REAL_TYPE))
9914 : return NULL_TREE;
9915 :
9916 1607849 : switch (builtin_index)
9917 : {
9918 710621 : case BUILT_IN_ISINF:
9919 710621 : if (tree_expr_infinite_p (arg))
9920 0 : return omit_one_operand_loc (loc, type, integer_one_node, arg);
9921 710621 : if (!tree_expr_maybe_infinite_p (arg))
9922 251 : return omit_one_operand_loc (loc, type, integer_zero_node, arg);
9923 : return NULL_TREE;
9924 :
9925 708 : case BUILT_IN_ISINF_SIGN:
9926 708 : {
9927 : /* isinf_sign(x) -> isinf(x) ? (signbit(x) ? -1 : 1) : 0 */
9928 : /* In a boolean context, GCC will fold the inner COND_EXPR to
9929 : 1. So e.g. "if (isinf_sign(x))" would be folded to just
9930 : "if (isinf(x) ? 1 : 0)" which becomes "if (isinf(x))". */
9931 708 : tree signbit_fn = builtin_decl_explicit (BUILT_IN_SIGNBIT);
9932 708 : tree isinf_fn = builtin_decl_explicit (BUILT_IN_ISINF);
9933 708 : tree tmp = NULL_TREE;
9934 :
9935 708 : arg = builtin_save_expr (arg);
9936 :
9937 708 : if (signbit_fn && isinf_fn)
9938 : {
9939 708 : tree signbit_call = build_call_expr_loc (loc, signbit_fn, 1, arg);
9940 708 : tree isinf_call = build_call_expr_loc (loc, isinf_fn, 1, arg);
9941 :
9942 708 : signbit_call = fold_build2_loc (loc, NE_EXPR, integer_type_node,
9943 : signbit_call, integer_zero_node);
9944 708 : isinf_call = fold_build2_loc (loc, NE_EXPR, integer_type_node,
9945 : isinf_call, integer_zero_node);
9946 :
9947 708 : tmp = fold_build3_loc (loc, COND_EXPR, integer_type_node, signbit_call,
9948 : integer_minus_one_node, integer_one_node);
9949 708 : tmp = fold_build3_loc (loc, COND_EXPR, integer_type_node,
9950 : isinf_call, tmp,
9951 : integer_zero_node);
9952 : }
9953 :
9954 : return tmp;
9955 : }
9956 :
9957 625691 : case BUILT_IN_ISFINITE:
9958 625691 : if (tree_expr_finite_p (arg))
9959 332 : return omit_one_operand_loc (loc, type, integer_one_node, arg);
9960 625359 : if (tree_expr_nan_p (arg) || tree_expr_infinite_p (arg))
9961 0 : return omit_one_operand_loc (loc, type, integer_zero_node, arg);
9962 : return NULL_TREE;
9963 :
9964 243014 : case BUILT_IN_ISNAN:
9965 243014 : if (tree_expr_nan_p (arg))
9966 0 : return omit_one_operand_loc (loc, type, integer_one_node, arg);
9967 243014 : if (!tree_expr_maybe_nan_p (arg))
9968 124 : return omit_one_operand_loc (loc, type, integer_zero_node, arg);
9969 : return NULL_TREE;
9970 :
9971 27815 : case BUILT_IN_ISSIGNALING:
9972 : /* Folding to true for REAL_CST is done in fold_const_call_ss.
9973 : Don't use tree_expr_signaling_nan_p (arg) -> integer_one_node
9974 : and !tree_expr_maybe_signaling_nan_p (arg) -> integer_zero_node
9975 : here, so there is some possibility of __builtin_issignaling working
9976 : without -fsignaling-nans. Especially when -fno-signaling-nans is
9977 : the default. */
9978 27815 : if (!tree_expr_maybe_nan_p (arg))
9979 0 : return omit_one_operand_loc (loc, type, integer_zero_node, arg);
9980 : return NULL_TREE;
9981 :
9982 0 : default:
9983 0 : gcc_unreachable ();
9984 : }
9985 : }
9986 :
9987 : /* Fold a call to __builtin_fpclassify(int, int, int, int, int, ...).
9988 : This builtin will generate code to return the appropriate floating
9989 : point classification depending on the value of the floating point
9990 : number passed in. The possible return values must be supplied as
9991 : int arguments to the call in the following order: FP_NAN, FP_INFINITE,
9992 : FP_NORMAL, FP_SUBNORMAL and FP_ZERO. The ellipses is for exactly
9993 : one floating point argument which is "type generic". */
9994 :
9995 : static tree
9996 104514 : fold_builtin_fpclassify (location_t loc, tree *args, int nargs)
9997 : {
9998 104514 : tree fp_nan, fp_infinite, fp_normal, fp_subnormal, fp_zero,
9999 : arg, type, res, tmp;
10000 104514 : machine_mode mode;
10001 104514 : REAL_VALUE_TYPE r;
10002 104514 : char buf[128];
10003 :
10004 : /* Verify the required arguments in the original call. */
10005 104514 : if (nargs != 6
10006 104514 : || !validate_arg (args[0], INTEGER_TYPE)
10007 104514 : || !validate_arg (args[1], INTEGER_TYPE)
10008 104514 : || !validate_arg (args[2], INTEGER_TYPE)
10009 104514 : || !validate_arg (args[3], INTEGER_TYPE)
10010 104514 : || !validate_arg (args[4], INTEGER_TYPE)
10011 209028 : || !validate_arg (args[5], REAL_TYPE))
10012 : return NULL_TREE;
10013 :
10014 104514 : fp_nan = args[0];
10015 104514 : fp_infinite = args[1];
10016 104514 : fp_normal = args[2];
10017 104514 : fp_subnormal = args[3];
10018 104514 : fp_zero = args[4];
10019 104514 : arg = args[5];
10020 104514 : type = TREE_TYPE (arg);
10021 104514 : mode = TYPE_MODE (type);
10022 104514 : arg = builtin_save_expr (fold_build1_loc (loc, ABS_EXPR, type, arg));
10023 :
10024 : /* fpclassify(x) ->
10025 : isnan(x) ? FP_NAN :
10026 : (fabs(x) == Inf ? FP_INFINITE :
10027 : (fabs(x) >= DBL_MIN ? FP_NORMAL :
10028 : (x == 0 ? FP_ZERO : FP_SUBNORMAL))). */
10029 :
10030 104514 : tmp = fold_build2_loc (loc, EQ_EXPR, integer_type_node, arg,
10031 : build_real (type, dconst0));
10032 104514 : res = fold_build3_loc (loc, COND_EXPR, integer_type_node,
10033 : tmp, fp_zero, fp_subnormal);
10034 :
10035 104514 : if (DECIMAL_FLOAT_MODE_P (mode))
10036 3 : sprintf (buf, "1E%d", REAL_MODE_FORMAT (mode)->emin - 1);
10037 : else
10038 104511 : sprintf (buf, "0x1p%d", REAL_MODE_FORMAT (mode)->emin - 1);
10039 104514 : real_from_string3 (&r, buf, mode);
10040 104514 : tmp = fold_build2_loc (loc, GE_EXPR, integer_type_node,
10041 : arg, build_real (type, r));
10042 104514 : res = fold_build3_loc (loc, COND_EXPR, integer_type_node, tmp,
10043 : fp_normal, res);
10044 :
10045 104514 : if (tree_expr_maybe_infinite_p (arg))
10046 : {
10047 104426 : tmp = fold_build2_loc (loc, EQ_EXPR, integer_type_node, arg,
10048 : build_real (type, dconstinf));
10049 104426 : res = fold_build3_loc (loc, COND_EXPR, integer_type_node, tmp,
10050 : fp_infinite, res);
10051 : }
10052 :
10053 104514 : if (tree_expr_maybe_nan_p (arg))
10054 : {
10055 104424 : tmp = fold_build2_loc (loc, ORDERED_EXPR, integer_type_node, arg, arg);
10056 104424 : res = fold_build3_loc (loc, COND_EXPR, integer_type_node, tmp,
10057 : res, fp_nan);
10058 : }
10059 :
10060 : return res;
10061 : }
10062 :
10063 : /* Fold a call to an unordered comparison function such as
10064 : __builtin_isgreater(). FNDECL is the FUNCTION_DECL for the function
10065 : being called and ARG0 and ARG1 are the arguments for the call.
10066 : UNORDERED_CODE and ORDERED_CODE are comparison codes that give
10067 : the opposite of the desired result. UNORDERED_CODE is used
10068 : for modes that can hold NaNs and ORDERED_CODE is used for
10069 : the rest. */
10070 :
10071 : static tree
10072 3257721 : fold_builtin_unordered_cmp (location_t loc, tree fndecl, tree arg0, tree arg1,
10073 : enum tree_code unordered_code,
10074 : enum tree_code ordered_code)
10075 : {
10076 3257721 : tree type = TREE_TYPE (TREE_TYPE (fndecl));
10077 3257721 : enum tree_code code;
10078 3257721 : tree type0, type1;
10079 3257721 : enum tree_code code0, code1;
10080 3257721 : tree cmp_type = NULL_TREE;
10081 :
10082 3257721 : type0 = TREE_TYPE (arg0);
10083 3257721 : type1 = TREE_TYPE (arg1);
10084 :
10085 3257721 : code0 = TREE_CODE (type0);
10086 3257721 : code1 = TREE_CODE (type1);
10087 :
10088 3257721 : if (code0 == REAL_TYPE && code1 == REAL_TYPE)
10089 : /* Choose the wider of two real types. */
10090 3257541 : cmp_type = TYPE_PRECISION (type0) >= TYPE_PRECISION (type1)
10091 3257541 : ? type0 : type1;
10092 180 : else if (code0 == REAL_TYPE
10093 91 : && (code1 == INTEGER_TYPE || code1 == BITINT_TYPE))
10094 : cmp_type = type0;
10095 89 : else if ((code0 == INTEGER_TYPE || code0 == BITINT_TYPE)
10096 89 : && code1 == REAL_TYPE)
10097 135 : cmp_type = type1;
10098 :
10099 3257721 : arg0 = fold_convert_loc (loc, cmp_type, arg0);
10100 3257721 : arg1 = fold_convert_loc (loc, cmp_type, arg1);
10101 :
10102 3257721 : if (unordered_code == UNORDERED_EXPR)
10103 : {
10104 240883 : if (tree_expr_nan_p (arg0) || tree_expr_nan_p (arg1))
10105 16 : return omit_two_operands_loc (loc, type, integer_one_node, arg0, arg1);
10106 240867 : if (!tree_expr_maybe_nan_p (arg0) && !tree_expr_maybe_nan_p (arg1))
10107 141 : return omit_two_operands_loc (loc, type, integer_zero_node, arg0, arg1);
10108 240726 : return fold_build2_loc (loc, UNORDERED_EXPR, type, arg0, arg1);
10109 : }
10110 :
10111 3019689 : code = (tree_expr_maybe_nan_p (arg0) || tree_expr_maybe_nan_p (arg1))
10112 3016838 : ? unordered_code : ordered_code;
10113 3016838 : return fold_build1_loc (loc, TRUTH_NOT_EXPR, type,
10114 3016838 : fold_build2_loc (loc, code, type, arg0, arg1));
10115 : }
10116 :
10117 : /* Fold a call to __builtin_iseqsig(). ARG0 and ARG1 are the arguments.
10118 : After choosing the wider floating-point type for the comparison,
10119 : the code is folded to:
10120 : SAVE_EXPR<ARG0> >= SAVE_EXPR<ARG1> && SAVE_EXPR<ARG0> <= SAVE_EXPR<ARG1> */
10121 :
10122 : static tree
10123 709 : fold_builtin_iseqsig (location_t loc, tree arg0, tree arg1)
10124 : {
10125 709 : tree type0, type1;
10126 709 : enum tree_code code0, code1;
10127 709 : tree cmp1, cmp2, cmp_type = NULL_TREE;
10128 :
10129 709 : type0 = TREE_TYPE (arg0);
10130 709 : type1 = TREE_TYPE (arg1);
10131 :
10132 709 : code0 = TREE_CODE (type0);
10133 709 : code1 = TREE_CODE (type1);
10134 :
10135 709 : if (code0 == REAL_TYPE && code1 == REAL_TYPE)
10136 : /* Choose the wider of two real types. */
10137 690 : cmp_type = TYPE_PRECISION (type0) >= TYPE_PRECISION (type1)
10138 690 : ? type0 : type1;
10139 19 : else if (code0 == REAL_TYPE
10140 6 : && (code1 == INTEGER_TYPE || code1 == BITINT_TYPE))
10141 : cmp_type = type0;
10142 13 : else if ((code0 == INTEGER_TYPE || code0 == BITINT_TYPE)
10143 13 : && code1 == REAL_TYPE)
10144 13 : cmp_type = type1;
10145 :
10146 709 : arg0 = builtin_save_expr (fold_convert_loc (loc, cmp_type, arg0));
10147 709 : arg1 = builtin_save_expr (fold_convert_loc (loc, cmp_type, arg1));
10148 :
10149 709 : cmp1 = fold_build2_loc (loc, GE_EXPR, integer_type_node, arg0, arg1);
10150 709 : cmp2 = fold_build2_loc (loc, LE_EXPR, integer_type_node, arg0, arg1);
10151 :
10152 709 : return fold_build2_loc (loc, TRUTH_AND_EXPR, integer_type_node, cmp1, cmp2);
10153 : }
10154 :
10155 : /* Fold __builtin_{,s,u}{add,sub,mul}{,l,ll}_overflow, either into normal
10156 : arithmetics if it can never overflow, or into internal functions that
10157 : return both result of arithmetics and overflowed boolean flag in
10158 : a complex integer result, or some other check for overflow.
10159 : Similarly fold __builtin_{add,sub,mul}_overflow_p to just the overflow
10160 : checking part of that. */
10161 :
10162 : static tree
10163 509878 : fold_builtin_arith_overflow (location_t loc, enum built_in_function fcode,
10164 : tree arg0, tree arg1, tree arg2)
10165 : {
10166 509878 : enum internal_fn ifn = IFN_LAST;
10167 : /* The code of the expression corresponding to the built-in. */
10168 509878 : enum tree_code opcode = ERROR_MARK;
10169 509878 : bool ovf_only = false;
10170 :
10171 509878 : switch (fcode)
10172 : {
10173 : case BUILT_IN_ADD_OVERFLOW_P:
10174 : ovf_only = true;
10175 : /* FALLTHRU */
10176 : case BUILT_IN_ADD_OVERFLOW:
10177 : case BUILT_IN_SADD_OVERFLOW:
10178 : case BUILT_IN_SADDL_OVERFLOW:
10179 : case BUILT_IN_SADDLL_OVERFLOW:
10180 : case BUILT_IN_UADD_OVERFLOW:
10181 : case BUILT_IN_UADDL_OVERFLOW:
10182 : case BUILT_IN_UADDLL_OVERFLOW:
10183 : opcode = PLUS_EXPR;
10184 : ifn = IFN_ADD_OVERFLOW;
10185 : break;
10186 15577 : case BUILT_IN_SUB_OVERFLOW_P:
10187 15577 : ovf_only = true;
10188 : /* FALLTHRU */
10189 37597 : case BUILT_IN_SUB_OVERFLOW:
10190 37597 : case BUILT_IN_SSUB_OVERFLOW:
10191 37597 : case BUILT_IN_SSUBL_OVERFLOW:
10192 37597 : case BUILT_IN_SSUBLL_OVERFLOW:
10193 37597 : case BUILT_IN_USUB_OVERFLOW:
10194 37597 : case BUILT_IN_USUBL_OVERFLOW:
10195 37597 : case BUILT_IN_USUBLL_OVERFLOW:
10196 37597 : opcode = MINUS_EXPR;
10197 37597 : ifn = IFN_SUB_OVERFLOW;
10198 37597 : break;
10199 15871 : case BUILT_IN_MUL_OVERFLOW_P:
10200 15871 : ovf_only = true;
10201 : /* FALLTHRU */
10202 432847 : case BUILT_IN_MUL_OVERFLOW:
10203 432847 : case BUILT_IN_SMUL_OVERFLOW:
10204 432847 : case BUILT_IN_SMULL_OVERFLOW:
10205 432847 : case BUILT_IN_SMULLL_OVERFLOW:
10206 432847 : case BUILT_IN_UMUL_OVERFLOW:
10207 432847 : case BUILT_IN_UMULL_OVERFLOW:
10208 432847 : case BUILT_IN_UMULLL_OVERFLOW:
10209 432847 : opcode = MULT_EXPR;
10210 432847 : ifn = IFN_MUL_OVERFLOW;
10211 432847 : break;
10212 0 : default:
10213 0 : gcc_unreachable ();
10214 : }
10215 :
10216 : /* For the "generic" overloads, the first two arguments can have different
10217 : types and the last argument determines the target type to use to check
10218 : for overflow. The arguments of the other overloads all have the same
10219 : type. */
10220 509878 : tree type = ovf_only ? TREE_TYPE (arg2) : TREE_TYPE (TREE_TYPE (arg2));
10221 :
10222 : /* For the __builtin_{add,sub,mul}_overflow_p builtins, when the first two
10223 : arguments are constant, attempt to fold the built-in call into a constant
10224 : expression indicating whether or not it detected an overflow. */
10225 509878 : if (ovf_only
10226 43258 : && TREE_CODE (arg0) == INTEGER_CST
10227 13131 : && TREE_CODE (arg1) == INTEGER_CST)
10228 : /* Perform the computation in the target type and check for overflow. */
10229 7347 : return omit_one_operand_loc (loc, boolean_type_node,
10230 7347 : arith_overflowed_p (opcode, type, arg0, arg1)
10231 : ? boolean_true_node : boolean_false_node,
10232 7347 : arg2);
10233 :
10234 502531 : tree intres, ovfres;
10235 502531 : if (TREE_CODE (arg0) == INTEGER_CST && TREE_CODE (arg1) == INTEGER_CST)
10236 : {
10237 88944 : intres = fold_binary_loc (loc, opcode, type,
10238 : fold_convert_loc (loc, type, arg0),
10239 : fold_convert_loc (loc, type, arg1));
10240 88944 : if (TREE_OVERFLOW (intres))
10241 1629 : intres = drop_tree_overflow (intres);
10242 177888 : ovfres = (arith_overflowed_p (opcode, type, arg0, arg1)
10243 88944 : ? boolean_true_node : boolean_false_node);
10244 : }
10245 : else
10246 : {
10247 413587 : tree ctype = build_complex_type (type);
10248 413587 : tree call = build_call_expr_internal_loc (loc, ifn, ctype, 2,
10249 : arg0, arg1);
10250 413587 : tree tgt;
10251 413587 : if (ovf_only)
10252 : {
10253 : tgt = call;
10254 413587 : intres = NULL_TREE;
10255 : }
10256 : else
10257 : {
10258 : /* Force SAVE_EXPR even for calls which satisfy tree_invariant_p_1,
10259 : as while the call itself is const, the REALPART_EXPR store is
10260 : certainly not. And in any case, we want just one call,
10261 : not multiple and trying to CSE them later. */
10262 377676 : TREE_SIDE_EFFECTS (call) = 1;
10263 377676 : tgt = save_expr (call);
10264 : }
10265 413587 : intres = build1_loc (loc, REALPART_EXPR, type, tgt);
10266 413587 : ovfres = build1_loc (loc, IMAGPART_EXPR, type, tgt);
10267 413587 : ovfres = fold_convert_loc (loc, boolean_type_node, ovfres);
10268 : }
10269 :
10270 502531 : if (ovf_only)
10271 35911 : return omit_one_operand_loc (loc, boolean_type_node, ovfres, arg2);
10272 :
10273 466620 : tree mem_arg2 = build_fold_indirect_ref_loc (loc, arg2);
10274 466620 : tree store
10275 466620 : = fold_build2_loc (loc, MODIFY_EXPR, void_type_node, mem_arg2, intres);
10276 466620 : return build2_loc (loc, COMPOUND_EXPR, boolean_type_node, store, ovfres);
10277 : }
10278 :
10279 : /* Fold __builtin_{clz,ctz,clrsb,ffs,parity,popcount}g into corresponding
10280 : internal function. */
10281 :
10282 : static tree
10283 265984 : fold_builtin_bit_query (location_t loc, enum built_in_function fcode,
10284 : tree arg0, tree arg1)
10285 : {
10286 265984 : enum internal_fn ifn;
10287 265984 : enum built_in_function fcodei, fcodel, fcodell;
10288 265984 : tree arg0_type = TREE_TYPE (arg0);
10289 265984 : tree cast_type = NULL_TREE;
10290 265984 : int addend = 0;
10291 :
10292 265984 : switch (fcode)
10293 : {
10294 187709 : case BUILT_IN_CLZG:
10295 187709 : if (arg1 && TREE_CODE (arg1) != INTEGER_CST)
10296 : return NULL_TREE;
10297 : ifn = IFN_CLZ;
10298 : fcodei = BUILT_IN_CLZ;
10299 : fcodel = BUILT_IN_CLZL;
10300 : fcodell = BUILT_IN_CLZLL;
10301 : break;
10302 66961 : case BUILT_IN_CTZG:
10303 66961 : if (arg1 && TREE_CODE (arg1) != INTEGER_CST)
10304 : return NULL_TREE;
10305 : ifn = IFN_CTZ;
10306 : fcodei = BUILT_IN_CTZ;
10307 : fcodel = BUILT_IN_CTZL;
10308 : fcodell = BUILT_IN_CTZLL;
10309 : break;
10310 : case BUILT_IN_CLRSBG:
10311 : ifn = IFN_CLRSB;
10312 : fcodei = BUILT_IN_CLRSB;
10313 : fcodel = BUILT_IN_CLRSBL;
10314 : fcodell = BUILT_IN_CLRSBLL;
10315 : break;
10316 84 : case BUILT_IN_FFSG:
10317 84 : ifn = IFN_FFS;
10318 84 : fcodei = BUILT_IN_FFS;
10319 84 : fcodel = BUILT_IN_FFSL;
10320 84 : fcodell = BUILT_IN_FFSLL;
10321 84 : break;
10322 82 : case BUILT_IN_PARITYG:
10323 82 : ifn = IFN_PARITY;
10324 82 : fcodei = BUILT_IN_PARITY;
10325 82 : fcodel = BUILT_IN_PARITYL;
10326 82 : fcodell = BUILT_IN_PARITYLL;
10327 82 : break;
10328 11066 : case BUILT_IN_POPCOUNTG:
10329 11066 : ifn = IFN_POPCOUNT;
10330 11066 : fcodei = BUILT_IN_POPCOUNT;
10331 11066 : fcodel = BUILT_IN_POPCOUNTL;
10332 11066 : fcodell = BUILT_IN_POPCOUNTLL;
10333 11066 : break;
10334 0 : default:
10335 0 : gcc_unreachable ();
10336 : }
10337 :
10338 265781 : if (TYPE_PRECISION (arg0_type)
10339 265781 : <= TYPE_PRECISION (long_long_unsigned_type_node))
10340 : {
10341 226667 : if (TYPE_PRECISION (arg0_type) <= TYPE_PRECISION (unsigned_type_node))
10342 :
10343 79393 : cast_type = (TYPE_UNSIGNED (arg0_type)
10344 79339 : ? unsigned_type_node : integer_type_node);
10345 147328 : else if (TYPE_PRECISION (arg0_type)
10346 147328 : <= TYPE_PRECISION (long_unsigned_type_node))
10347 : {
10348 147277 : cast_type = (TYPE_UNSIGNED (arg0_type)
10349 147205 : ? long_unsigned_type_node : long_integer_type_node);
10350 : fcodei = fcodel;
10351 : }
10352 : else
10353 : {
10354 123 : cast_type = (TYPE_UNSIGNED (arg0_type)
10355 123 : ? long_long_unsigned_type_node
10356 : : long_long_integer_type_node);
10357 : fcodei = fcodell;
10358 : }
10359 : }
10360 78228 : else if (TYPE_PRECISION (arg0_type) <= MAX_FIXED_MODE_SIZE)
10361 : {
10362 39004 : cast_type
10363 39004 : = build_nonstandard_integer_type (MAX_FIXED_MODE_SIZE,
10364 39004 : TYPE_UNSIGNED (arg0_type));
10365 39004 : gcc_assert (TYPE_PRECISION (cast_type)
10366 : == 2 * TYPE_PRECISION (long_long_unsigned_type_node));
10367 : fcodei = END_BUILTINS;
10368 : }
10369 : else
10370 : fcodei = END_BUILTINS;
10371 265671 : if (cast_type)
10372 : {
10373 265671 : switch (fcode)
10374 : {
10375 187658 : case BUILT_IN_CLZG:
10376 187658 : case BUILT_IN_CLRSBG:
10377 187658 : addend = TYPE_PRECISION (arg0_type) - TYPE_PRECISION (cast_type);
10378 187658 : break;
10379 : default:
10380 : break;
10381 : }
10382 265671 : arg0 = fold_convert (cast_type, arg0);
10383 265671 : arg0_type = cast_type;
10384 : }
10385 :
10386 265781 : if (arg1)
10387 176341 : arg1 = fold_convert (integer_type_node, arg1);
10388 :
10389 265781 : tree arg2 = arg1;
10390 265781 : if (fcode == BUILT_IN_CLZG && addend)
10391 : {
10392 4344 : if (arg1)
10393 4311 : arg0 = save_expr (arg0);
10394 : arg2 = NULL_TREE;
10395 : }
10396 265781 : tree call = NULL_TREE, tem;
10397 265781 : if (TYPE_PRECISION (arg0_type) == MAX_FIXED_MODE_SIZE
10398 39127 : && (TYPE_PRECISION (arg0_type)
10399 39127 : == 2 * TYPE_PRECISION (long_long_unsigned_type_node))
10400 : /* If the target supports the optab, then don't do the expansion. */
10401 304785 : && !direct_internal_fn_supported_p (ifn, arg0_type, OPTIMIZE_FOR_BOTH))
10402 : {
10403 : /* __int128 expansions using up to 2 long long builtins. */
10404 39004 : arg0 = save_expr (arg0);
10405 39004 : tree type = (TYPE_UNSIGNED (arg0_type)
10406 39004 : ? long_long_unsigned_type_node
10407 39004 : : long_long_integer_type_node);
10408 78008 : tree hi = fold_build2 (RSHIFT_EXPR, arg0_type, arg0,
10409 : build_int_cst (integer_type_node,
10410 : MAX_FIXED_MODE_SIZE / 2));
10411 39004 : hi = fold_convert (type, hi);
10412 39004 : tree lo = fold_convert (type, arg0);
10413 39004 : switch (fcode)
10414 : {
10415 38921 : case BUILT_IN_CLZG:
10416 38921 : call = fold_builtin_bit_query (loc, fcode, lo, NULL_TREE);
10417 77842 : call = fold_build2 (PLUS_EXPR, integer_type_node, call,
10418 : build_int_cst (integer_type_node,
10419 : MAX_FIXED_MODE_SIZE / 2));
10420 38921 : if (arg2)
10421 38901 : call = fold_build3 (COND_EXPR, integer_type_node,
10422 : fold_build2 (NE_EXPR, boolean_type_node,
10423 : lo, build_zero_cst (type)),
10424 : call, arg2);
10425 38921 : call = fold_build3 (COND_EXPR, integer_type_node,
10426 : fold_build2 (NE_EXPR, boolean_type_node,
10427 : hi, build_zero_cst (type)),
10428 : fold_builtin_bit_query (loc, fcode, hi,
10429 : NULL_TREE),
10430 : call);
10431 38921 : break;
10432 27 : case BUILT_IN_CTZG:
10433 27 : call = fold_builtin_bit_query (loc, fcode, hi, NULL_TREE);
10434 54 : call = fold_build2 (PLUS_EXPR, integer_type_node, call,
10435 : build_int_cst (integer_type_node,
10436 : MAX_FIXED_MODE_SIZE / 2));
10437 27 : if (arg2)
10438 18 : call = fold_build3 (COND_EXPR, integer_type_node,
10439 : fold_build2 (NE_EXPR, boolean_type_node,
10440 : hi, build_zero_cst (type)),
10441 : call, arg2);
10442 27 : call = fold_build3 (COND_EXPR, integer_type_node,
10443 : fold_build2 (NE_EXPR, boolean_type_node,
10444 : lo, build_zero_cst (type)),
10445 : fold_builtin_bit_query (loc, fcode, lo,
10446 : NULL_TREE),
10447 : call);
10448 27 : break;
10449 9 : case BUILT_IN_CLRSBG:
10450 9 : tem = fold_builtin_bit_query (loc, fcode, lo, NULL_TREE);
10451 18 : tem = fold_build2 (PLUS_EXPR, integer_type_node, tem,
10452 : build_int_cst (integer_type_node,
10453 : MAX_FIXED_MODE_SIZE / 2));
10454 18 : tem = fold_build3 (COND_EXPR, integer_type_node,
10455 : fold_build2 (LT_EXPR, boolean_type_node,
10456 : fold_build2 (BIT_XOR_EXPR, type,
10457 : lo, hi),
10458 : build_zero_cst (type)),
10459 : build_int_cst (integer_type_node,
10460 : MAX_FIXED_MODE_SIZE / 2 - 1),
10461 : tem);
10462 9 : call = fold_builtin_bit_query (loc, fcode, hi, NULL_TREE);
10463 9 : call = save_expr (call);
10464 18 : call = fold_build3 (COND_EXPR, integer_type_node,
10465 : fold_build2 (NE_EXPR, boolean_type_node,
10466 : call,
10467 : build_int_cst (integer_type_node,
10468 : MAX_FIXED_MODE_SIZE
10469 : / 2 - 1)),
10470 : call, tem);
10471 9 : break;
10472 9 : case BUILT_IN_FFSG:
10473 9 : call = fold_builtin_bit_query (loc, fcode, hi, NULL_TREE);
10474 18 : call = fold_build2 (PLUS_EXPR, integer_type_node, call,
10475 : build_int_cst (integer_type_node,
10476 : MAX_FIXED_MODE_SIZE / 2));
10477 9 : call = fold_build3 (COND_EXPR, integer_type_node,
10478 : fold_build2 (NE_EXPR, boolean_type_node,
10479 : hi, build_zero_cst (type)),
10480 : call, integer_zero_node);
10481 9 : call = fold_build3 (COND_EXPR, integer_type_node,
10482 : fold_build2 (NE_EXPR, boolean_type_node,
10483 : lo, build_zero_cst (type)),
10484 : fold_builtin_bit_query (loc, fcode, lo,
10485 : NULL_TREE),
10486 : call);
10487 9 : break;
10488 9 : case BUILT_IN_PARITYG:
10489 9 : call = fold_builtin_bit_query (loc, fcode,
10490 : fold_build2 (BIT_XOR_EXPR, type,
10491 : lo, hi), NULL_TREE);
10492 9 : break;
10493 29 : case BUILT_IN_POPCOUNTG:
10494 29 : call = fold_build2 (PLUS_EXPR, integer_type_node,
10495 : fold_builtin_bit_query (loc, fcode, hi,
10496 : NULL_TREE),
10497 : fold_builtin_bit_query (loc, fcode, lo,
10498 : NULL_TREE));
10499 29 : break;
10500 : default:
10501 : gcc_unreachable ();
10502 : }
10503 : }
10504 : else
10505 : {
10506 : /* Only keep second argument to IFN_CLZ/IFN_CTZ if it is the
10507 : value defined at zero during GIMPLE, or for large/huge _BitInt
10508 : (which are then lowered during bitint lowering). */
10509 226777 : if (arg2 && !BITINT_TYPE_P (TREE_TYPE (arg0)))
10510 : {
10511 133091 : int val;
10512 133091 : if (fcode == BUILT_IN_CLZG)
10513 : {
10514 66424 : if (CLZ_DEFINED_VALUE_AT_ZERO (SCALAR_TYPE_MODE (arg0_type),
10515 : val) != 2
10516 66424 : || wi::to_widest (arg2) != val)
10517 : arg2 = NULL_TREE;
10518 : }
10519 66667 : else if (CTZ_DEFINED_VALUE_AT_ZERO (SCALAR_TYPE_MODE (arg0_type),
10520 : val) != 2
10521 66667 : || wi::to_widest (arg2) != val)
10522 : arg2 = NULL_TREE;
10523 133091 : if (!direct_internal_fn_supported_p (ifn, arg0_type,
10524 : OPTIMIZE_FOR_BOTH))
10525 : arg2 = NULL_TREE;
10526 132980 : if (arg2 == NULL_TREE)
10527 133044 : arg0 = save_expr (arg0);
10528 : }
10529 226777 : if (fcodei == END_BUILTINS || arg2)
10530 247 : call = build_call_expr_internal_loc (loc, ifn, integer_type_node,
10531 : arg2 ? 2 : 1, arg0, arg2);
10532 : else
10533 226620 : call = build_call_expr_loc (loc, builtin_decl_explicit (fcodei), 1,
10534 : arg0);
10535 : }
10536 265781 : if (addend)
10537 4362 : call = fold_build2 (PLUS_EXPR, integer_type_node, call,
10538 : build_int_cst (integer_type_node, addend));
10539 265781 : if (arg1 && arg2 == NULL_TREE)
10540 137355 : call = fold_build3 (COND_EXPR, integer_type_node,
10541 : fold_build2 (NE_EXPR, boolean_type_node,
10542 : arg0, build_zero_cst (arg0_type)),
10543 : call, arg1);
10544 :
10545 : return call;
10546 : }
10547 :
10548 : /* Fold or build a __builtin_bswapg (ARG) (if IFN is IFN_BSWAP) or
10549 : __builtin_bitreverseg (ARG (otherwise) call. The FE should have
10550 : verified earlier that the argument type is unsigned INTEGER_TYPE
10551 : or BITINT_TYPE, for __builtin_bswapg with precision divisible by 8. */
10552 :
10553 : tree
10554 152 : fold_build_builtin_bswapg_bitreverseg (location_t loc, enum internal_fn ifn,
10555 : tree arg)
10556 : {
10557 152 : tree type = TYPE_MAIN_VARIANT (TREE_TYPE (arg));
10558 152 : if (ifn == IFN_BSWAP && TYPE_PRECISION (type) == 8)
10559 11 : return fold_convert_loc (loc, type, arg);
10560 141 : struct { tree type; built_in_function bswap, bitreverse; } fns[]
10561 141 : = { { unsigned_char_type_node, END_BUILTINS, BUILT_IN_BITREVERSE8 },
10562 141 : { uint16_type_node, BUILT_IN_BSWAP16, BUILT_IN_BITREVERSE16 },
10563 141 : { uint32_type_node, BUILT_IN_BSWAP32, BUILT_IN_BITREVERSE32 },
10564 141 : { uint64_type_node, BUILT_IN_BSWAP64, BUILT_IN_BITREVERSE64 },
10565 141 : { uint128_type_node, BUILT_IN_BSWAP128, BUILT_IN_BITREVERSE128 } };
10566 141 : if (TREE_CODE (arg) == INTEGER_CST)
10567 : {
10568 76 : wide_int res;
10569 76 : if (ifn == IFN_BSWAP)
10570 37 : res = wi::bswap (wi::to_wide (arg));
10571 : else
10572 45 : res = wi::bitreverse (wi::to_wide (arg));
10573 76 : return wide_int_to_tree (type, res);
10574 76 : }
10575 256 : for (unsigned i = 0; i < ARRAY_SIZE (fns); ++i)
10576 239 : if (fns[i].type
10577 239 : && TYPE_PRECISION (fns[i].type) >= TYPE_PRECISION (type))
10578 : {
10579 48 : arg = fold_convert_loc (loc, fns[i].type, arg);
10580 48 : tree fndecl
10581 48 : = builtin_decl_explicit (ifn == IFN_BSWAP
10582 : ? fns[i].bswap : fns[i].bitreverse);
10583 48 : tree ret = build_call_expr_loc (loc, fndecl, 1, arg);
10584 48 : if (TYPE_PRECISION (type) != TYPE_PRECISION (fns[i].type))
10585 4 : ret = fold_build2_loc (loc, RSHIFT_EXPR, fns[i].type, ret,
10586 : build_int_cst (unsigned_type_node,
10587 4 : TYPE_PRECISION (fns[i].type)
10588 4 : - TYPE_PRECISION (type)));
10589 48 : return fold_convert_loc (loc, type, ret);
10590 : }
10591 17 : gcc_assert (TREE_CODE (type) == BITINT_TYPE);
10592 17 : return build_call_expr_internal_loc (loc, ifn, type, 1, arg);
10593 : }
10594 :
10595 : /* Fold __builtin_{add,sub}c{,l,ll} into pair of internal functions
10596 : that return both result of arithmetics and overflowed boolean
10597 : flag in a complex integer result. */
10598 :
10599 : static tree
10600 55 : fold_builtin_addc_subc (location_t loc, enum built_in_function fcode,
10601 : tree *args)
10602 : {
10603 55 : enum internal_fn ifn;
10604 :
10605 55 : switch (fcode)
10606 : {
10607 : case BUILT_IN_ADDC:
10608 : case BUILT_IN_ADDCL:
10609 : case BUILT_IN_ADDCLL:
10610 : ifn = IFN_ADD_OVERFLOW;
10611 : break;
10612 29 : case BUILT_IN_SUBC:
10613 29 : case BUILT_IN_SUBCL:
10614 29 : case BUILT_IN_SUBCLL:
10615 29 : ifn = IFN_SUB_OVERFLOW;
10616 29 : break;
10617 0 : default:
10618 0 : gcc_unreachable ();
10619 : }
10620 :
10621 55 : tree type = TREE_TYPE (args[0]);
10622 55 : tree ctype = build_complex_type (type);
10623 55 : tree call = build_call_expr_internal_loc (loc, ifn, ctype, 2,
10624 : args[0], args[1]);
10625 : /* Force SAVE_EXPR even for calls which satisfy tree_invariant_p_1,
10626 : as while the call itself is const, the REALPART_EXPR store is
10627 : certainly not. And in any case, we want just one call,
10628 : not multiple and trying to CSE them later. */
10629 55 : TREE_SIDE_EFFECTS (call) = 1;
10630 55 : tree tgt = save_expr (call);
10631 55 : tree intres = build1_loc (loc, REALPART_EXPR, type, tgt);
10632 55 : tree ovfres = build1_loc (loc, IMAGPART_EXPR, type, tgt);
10633 55 : call = build_call_expr_internal_loc (loc, ifn, ctype, 2,
10634 : intres, args[2]);
10635 55 : TREE_SIDE_EFFECTS (call) = 1;
10636 55 : tgt = save_expr (call);
10637 55 : intres = build1_loc (loc, REALPART_EXPR, type, tgt);
10638 55 : tree ovfres2 = build1_loc (loc, IMAGPART_EXPR, type, tgt);
10639 55 : ovfres = build2_loc (loc, BIT_IOR_EXPR, type, ovfres, ovfres2);
10640 55 : tree mem_arg3 = build_fold_indirect_ref_loc (loc, args[3]);
10641 55 : tree store
10642 55 : = fold_build2_loc (loc, MODIFY_EXPR, void_type_node, mem_arg3, ovfres);
10643 55 : return build2_loc (loc, COMPOUND_EXPR, type, store, intres);
10644 : }
10645 :
10646 : /* Fold a call to __builtin_FILE to a constant string. */
10647 :
10648 : static inline tree
10649 5789 : fold_builtin_FILE (location_t loc)
10650 : {
10651 5789 : if (const char *fname = LOCATION_FILE (loc))
10652 : {
10653 : /* The documentation says this builtin is equivalent to the preprocessor
10654 : __FILE__ macro so it appears appropriate to use the same file prefix
10655 : mappings. */
10656 5789 : fname = remap_macro_filename (fname);
10657 5789 : return build_string_literal (fname);
10658 : }
10659 :
10660 0 : return build_string_literal ("");
10661 : }
10662 :
10663 : /* Fold a call to __builtin_FUNCTION to a constant string. */
10664 :
10665 : static inline tree
10666 68 : fold_builtin_FUNCTION ()
10667 : {
10668 68 : const char *name = "";
10669 :
10670 68 : if (current_function_decl)
10671 43 : name = lang_hooks.decl_printable_name (current_function_decl, 0);
10672 :
10673 68 : return build_string_literal (name);
10674 : }
10675 :
10676 : /* Fold a call to __builtin_LINE to an integer constant. */
10677 :
10678 : static inline tree
10679 11545 : fold_builtin_LINE (location_t loc, tree type)
10680 : {
10681 11545 : return build_int_cst (type, LOCATION_LINE (loc));
10682 : }
10683 :
10684 : /* Fold a call to built-in function FNDECL with 0 arguments.
10685 : This function returns NULL_TREE if no simplification was possible. */
10686 :
10687 : static tree
10688 24044758 : fold_builtin_0 (location_t loc, tree fndecl)
10689 : {
10690 24044758 : tree type = TREE_TYPE (TREE_TYPE (fndecl));
10691 24044758 : enum built_in_function fcode = DECL_FUNCTION_CODE (fndecl);
10692 24044758 : switch (fcode)
10693 : {
10694 5789 : case BUILT_IN_FILE:
10695 5789 : return fold_builtin_FILE (loc);
10696 :
10697 68 : case BUILT_IN_FUNCTION:
10698 68 : return fold_builtin_FUNCTION ();
10699 :
10700 11545 : case BUILT_IN_LINE:
10701 11545 : return fold_builtin_LINE (loc, type);
10702 :
10703 33910 : CASE_FLT_FN (BUILT_IN_INF):
10704 33910 : CASE_FLT_FN_FLOATN_NX (BUILT_IN_INF):
10705 33910 : case BUILT_IN_INFD32:
10706 33910 : case BUILT_IN_INFD64:
10707 33910 : case BUILT_IN_INFD128:
10708 33910 : case BUILT_IN_INFD64X:
10709 33910 : return fold_builtin_inf (loc, type, true);
10710 :
10711 229702 : CASE_FLT_FN (BUILT_IN_HUGE_VAL):
10712 229702 : CASE_FLT_FN_FLOATN_NX (BUILT_IN_HUGE_VAL):
10713 229702 : return fold_builtin_inf (loc, type, false);
10714 :
10715 0 : case BUILT_IN_CLASSIFY_TYPE:
10716 0 : return fold_builtin_classify_type (NULL_TREE);
10717 :
10718 20577305 : case BUILT_IN_UNREACHABLE:
10719 : /* Rewrite any explicit calls to __builtin_unreachable. */
10720 20577305 : if (sanitize_flags_p (SANITIZE_UNREACHABLE))
10721 91 : return build_builtin_unreachable (loc);
10722 : break;
10723 :
10724 : default:
10725 : break;
10726 : }
10727 : return NULL_TREE;
10728 : }
10729 :
10730 : /* Fold a call to built-in function FNDECL with 1 argument, ARG0.
10731 : This function returns NULL_TREE if no simplification was possible. */
10732 :
10733 : static tree
10734 20223807 : fold_builtin_1 (location_t loc, tree expr, tree fndecl, tree arg0)
10735 : {
10736 20223807 : tree type = TREE_TYPE (TREE_TYPE (fndecl));
10737 20223807 : enum built_in_function fcode = DECL_FUNCTION_CODE (fndecl);
10738 :
10739 20223807 : if (error_operand_p (arg0))
10740 : return NULL_TREE;
10741 :
10742 20223807 : if (tree ret = fold_const_call (as_combined_fn (fcode), type, arg0))
10743 : return ret;
10744 :
10745 19596916 : switch (fcode)
10746 : {
10747 3115536 : case BUILT_IN_CONSTANT_P:
10748 3115536 : {
10749 3115536 : tree val = fold_builtin_constant_p (arg0);
10750 :
10751 : /* Gimplification will pull the CALL_EXPR for the builtin out of
10752 : an if condition. When not optimizing, we'll not CSE it back.
10753 : To avoid link error types of regressions, return false now. */
10754 3115536 : if (!val && !optimize)
10755 1558 : val = integer_zero_node;
10756 :
10757 : return val;
10758 : }
10759 :
10760 2078 : case BUILT_IN_CLASSIFY_TYPE:
10761 2078 : return fold_builtin_classify_type (arg0);
10762 :
10763 476464 : case BUILT_IN_STRLEN:
10764 476464 : return fold_builtin_strlen (loc, expr, type, arg0);
10765 :
10766 378195 : CASE_FLT_FN (BUILT_IN_FABS):
10767 378195 : CASE_FLT_FN_FLOATN_NX (BUILT_IN_FABS):
10768 378195 : case BUILT_IN_FABSD32:
10769 378195 : case BUILT_IN_FABSD64:
10770 378195 : case BUILT_IN_FABSD128:
10771 378195 : case BUILT_IN_FABSD64X:
10772 378195 : return fold_builtin_fabs (loc, arg0, type);
10773 :
10774 101153 : case BUILT_IN_ABS:
10775 101153 : case BUILT_IN_LABS:
10776 101153 : case BUILT_IN_LLABS:
10777 101153 : case BUILT_IN_IMAXABS:
10778 101153 : case BUILT_IN_UABS:
10779 101153 : case BUILT_IN_ULABS:
10780 101153 : case BUILT_IN_ULLABS:
10781 101153 : case BUILT_IN_UMAXABS:
10782 101153 : return fold_builtin_abs (loc, arg0, type);
10783 :
10784 25461 : CASE_FLT_FN (BUILT_IN_CONJ):
10785 25461 : if (validate_arg (arg0, COMPLEX_TYPE)
10786 25461 : && TREE_CODE (TREE_TYPE (TREE_TYPE (arg0))) == REAL_TYPE)
10787 25461 : return fold_build1_loc (loc, CONJ_EXPR, type, arg0);
10788 : break;
10789 :
10790 764 : CASE_FLT_FN (BUILT_IN_CREAL):
10791 764 : if (validate_arg (arg0, COMPLEX_TYPE)
10792 764 : && TREE_CODE (TREE_TYPE (TREE_TYPE (arg0))) == REAL_TYPE)
10793 764 : return non_lvalue_loc (loc, fold_build1_loc (loc, REALPART_EXPR, type, arg0));
10794 : break;
10795 :
10796 1884 : CASE_FLT_FN (BUILT_IN_CIMAG):
10797 1884 : if (validate_arg (arg0, COMPLEX_TYPE)
10798 1884 : && TREE_CODE (TREE_TYPE (TREE_TYPE (arg0))) == REAL_TYPE)
10799 1884 : return non_lvalue_loc (loc, fold_build1_loc (loc, IMAGPART_EXPR, type, arg0));
10800 : break;
10801 :
10802 104371 : CASE_FLT_FN (BUILT_IN_CARG):
10803 104371 : CASE_FLT_FN_FLOATN_NX (BUILT_IN_CARG):
10804 104371 : return fold_builtin_carg (loc, arg0, type);
10805 :
10806 211 : case BUILT_IN_ISASCII:
10807 211 : return fold_builtin_isascii (loc, arg0);
10808 :
10809 168 : case BUILT_IN_TOASCII:
10810 168 : return fold_builtin_toascii (loc, arg0);
10811 :
10812 325 : case BUILT_IN_ISDIGIT:
10813 325 : return fold_builtin_isdigit (loc, arg0);
10814 :
10815 625691 : CASE_FLT_FN (BUILT_IN_FINITE):
10816 625691 : case BUILT_IN_FINITED32:
10817 625691 : case BUILT_IN_FINITED64:
10818 625691 : case BUILT_IN_FINITED128:
10819 625691 : case BUILT_IN_ISFINITE:
10820 625691 : {
10821 625691 : tree ret = fold_builtin_classify (loc, fndecl, arg0, BUILT_IN_ISFINITE);
10822 625691 : if (ret)
10823 : return ret;
10824 625359 : return fold_builtin_interclass_mathfn (loc, fndecl, arg0);
10825 : }
10826 :
10827 710621 : CASE_FLT_FN (BUILT_IN_ISINF):
10828 710621 : case BUILT_IN_ISINFD32:
10829 710621 : case BUILT_IN_ISINFD64:
10830 710621 : case BUILT_IN_ISINFD128:
10831 710621 : {
10832 710621 : tree ret = fold_builtin_classify (loc, fndecl, arg0, BUILT_IN_ISINF);
10833 710621 : if (ret)
10834 : return ret;
10835 710370 : return fold_builtin_interclass_mathfn (loc, fndecl, arg0);
10836 : }
10837 :
10838 239896 : case BUILT_IN_ISNORMAL:
10839 239896 : return fold_builtin_interclass_mathfn (loc, fndecl, arg0);
10840 :
10841 708 : case BUILT_IN_ISINF_SIGN:
10842 708 : return fold_builtin_classify (loc, fndecl, arg0, BUILT_IN_ISINF_SIGN);
10843 :
10844 243014 : CASE_FLT_FN (BUILT_IN_ISNAN):
10845 243014 : case BUILT_IN_ISNAND32:
10846 243014 : case BUILT_IN_ISNAND64:
10847 243014 : case BUILT_IN_ISNAND128:
10848 243014 : {
10849 243014 : tree ret = fold_builtin_classify (loc, fndecl, arg0, BUILT_IN_ISNAN);
10850 243014 : if (ret)
10851 : return ret;
10852 242890 : return fold_builtin_interclass_mathfn (loc, fndecl, arg0);
10853 : }
10854 :
10855 27815 : case BUILT_IN_ISSIGNALING:
10856 27815 : return fold_builtin_classify (loc, fndecl, arg0, BUILT_IN_ISSIGNALING);
10857 :
10858 635983 : case BUILT_IN_FREE:
10859 635983 : if (integer_zerop (arg0))
10860 1077 : return build_empty_stmt (loc);
10861 : break;
10862 :
10863 11441 : case BUILT_IN_CLZG:
10864 11441 : case BUILT_IN_CTZG:
10865 11441 : case BUILT_IN_CLRSBG:
10866 11441 : case BUILT_IN_FFSG:
10867 11441 : case BUILT_IN_PARITYG:
10868 11441 : case BUILT_IN_POPCOUNTG:
10869 11441 : return fold_builtin_bit_query (loc, fcode, arg0, NULL_TREE);
10870 :
10871 : default:
10872 : break;
10873 : }
10874 :
10875 : return NULL_TREE;
10876 :
10877 : }
10878 :
10879 : /* Folds a call EXPR (which may be null) to built-in function FNDECL
10880 : with 2 arguments, ARG0 and ARG1. This function returns NULL_TREE
10881 : if no simplification was possible. */
10882 :
10883 : static tree
10884 19481152 : fold_builtin_2 (location_t loc, tree expr, tree fndecl, tree arg0, tree arg1)
10885 : {
10886 19481152 : tree type = TREE_TYPE (TREE_TYPE (fndecl));
10887 19481152 : enum built_in_function fcode = DECL_FUNCTION_CODE (fndecl);
10888 :
10889 19481152 : if (error_operand_p (arg0)
10890 19481152 : || error_operand_p (arg1))
10891 : return NULL_TREE;
10892 :
10893 19481148 : if (tree ret = fold_const_call (as_combined_fn (fcode), type, arg0, arg1))
10894 : return ret;
10895 :
10896 19264891 : switch (fcode)
10897 : {
10898 6504 : CASE_FLT_FN_REENT (BUILT_IN_GAMMA): /* GAMMA_R */
10899 6504 : CASE_FLT_FN_REENT (BUILT_IN_LGAMMA): /* LGAMMA_R */
10900 6504 : if (validate_arg (arg0, REAL_TYPE)
10901 6504 : && validate_arg (arg1, POINTER_TYPE))
10902 6504 : return do_mpfr_lgamma_r (arg0, arg1, type);
10903 : break;
10904 :
10905 115911 : CASE_FLT_FN (BUILT_IN_FREXP):
10906 115911 : return fold_builtin_frexp (loc, arg0, arg1, type);
10907 :
10908 92826 : CASE_FLT_FN (BUILT_IN_MODF):
10909 92826 : return fold_builtin_modf (loc, arg0, arg1, type);
10910 :
10911 2560 : case BUILT_IN_STRSPN:
10912 2560 : return fold_builtin_strspn (loc, expr, arg0, arg1, type);
10913 :
10914 2465 : case BUILT_IN_STRCSPN:
10915 2465 : return fold_builtin_strcspn (loc, expr, arg0, arg1, type);
10916 :
10917 100317 : case BUILT_IN_STRPBRK:
10918 100317 : return fold_builtin_strpbrk (loc, expr, arg0, arg1, type);
10919 :
10920 6750626 : case BUILT_IN_EXPECT:
10921 6750626 : return fold_builtin_expect (loc, arg0, arg1, NULL_TREE, NULL_TREE);
10922 :
10923 950425 : case BUILT_IN_ISGREATER:
10924 950425 : return fold_builtin_unordered_cmp (loc, fndecl,
10925 950425 : arg0, arg1, UNLE_EXPR, LE_EXPR);
10926 479886 : case BUILT_IN_ISGREATEREQUAL:
10927 479886 : return fold_builtin_unordered_cmp (loc, fndecl,
10928 479886 : arg0, arg1, UNLT_EXPR, LT_EXPR);
10929 241559 : case BUILT_IN_ISLESS:
10930 241559 : return fold_builtin_unordered_cmp (loc, fndecl,
10931 241559 : arg0, arg1, UNGE_EXPR, GE_EXPR);
10932 1105275 : case BUILT_IN_ISLESSEQUAL:
10933 1105275 : return fold_builtin_unordered_cmp (loc, fndecl,
10934 1105275 : arg0, arg1, UNGT_EXPR, GT_EXPR);
10935 239693 : case BUILT_IN_ISLESSGREATER:
10936 239693 : return fold_builtin_unordered_cmp (loc, fndecl,
10937 239693 : arg0, arg1, UNEQ_EXPR, EQ_EXPR);
10938 240883 : case BUILT_IN_ISUNORDERED:
10939 240883 : return fold_builtin_unordered_cmp (loc, fndecl,
10940 : arg0, arg1, UNORDERED_EXPR,
10941 240883 : NOP_EXPR);
10942 :
10943 709 : case BUILT_IN_ISEQSIG:
10944 709 : return fold_builtin_iseqsig (loc, arg0, arg1);
10945 :
10946 : /* We do the folding for va_start in the expander. */
10947 : case BUILT_IN_VA_START:
10948 : break;
10949 :
10950 201103 : case BUILT_IN_OBJECT_SIZE:
10951 201103 : case BUILT_IN_DYNAMIC_OBJECT_SIZE:
10952 201103 : return fold_builtin_object_size (arg0, arg1, fcode);
10953 :
10954 105502 : case BUILT_IN_ATOMIC_ALWAYS_LOCK_FREE:
10955 105502 : return fold_builtin_atomic_always_lock_free (arg0, arg1);
10956 :
10957 38817 : case BUILT_IN_ATOMIC_IS_LOCK_FREE:
10958 38817 : return fold_builtin_atomic_is_lock_free (arg0, arg1);
10959 :
10960 176544 : case BUILT_IN_CLZG:
10961 176544 : case BUILT_IN_CTZG:
10962 176544 : return fold_builtin_bit_query (loc, fcode, arg0, arg1);
10963 :
10964 : default:
10965 : break;
10966 : }
10967 : return NULL_TREE;
10968 : }
10969 :
10970 : /* Fold a call to built-in function FNDECL with 3 arguments, ARG0, ARG1,
10971 : and ARG2.
10972 : This function returns NULL_TREE if no simplification was possible. */
10973 :
10974 : static tree
10975 7418370 : fold_builtin_3 (location_t loc, tree fndecl,
10976 : tree arg0, tree arg1, tree arg2)
10977 : {
10978 7418370 : tree type = TREE_TYPE (TREE_TYPE (fndecl));
10979 7418370 : enum built_in_function fcode = DECL_FUNCTION_CODE (fndecl);
10980 :
10981 7418370 : if (error_operand_p (arg0)
10982 7418370 : || error_operand_p (arg1)
10983 14836740 : || error_operand_p (arg2))
10984 : return NULL_TREE;
10985 :
10986 7418368 : if (tree ret = fold_const_call (as_combined_fn (fcode), type,
10987 : arg0, arg1, arg2))
10988 : return ret;
10989 :
10990 7401341 : switch (fcode)
10991 : {
10992 :
10993 145 : CASE_FLT_FN (BUILT_IN_SINCOS):
10994 145 : return fold_builtin_sincos (loc, arg0, arg1, arg2);
10995 :
10996 99940 : CASE_FLT_FN (BUILT_IN_REMQUO):
10997 99940 : if (validate_arg (arg0, REAL_TYPE)
10998 99940 : && validate_arg (arg1, REAL_TYPE)
10999 199880 : && validate_arg (arg2, POINTER_TYPE))
11000 99940 : return do_mpfr_remquo (arg0, arg1, arg2);
11001 : break;
11002 :
11003 2568558 : case BUILT_IN_MEMCMP:
11004 2568558 : return fold_builtin_memcmp (loc, arg0, arg1, arg2);
11005 :
11006 518630 : case BUILT_IN_EXPECT:
11007 518630 : return fold_builtin_expect (loc, arg0, arg1, arg2, NULL_TREE);
11008 :
11009 395 : case BUILT_IN_EXPECT_WITH_PROBABILITY:
11010 395 : return fold_builtin_expect (loc, arg0, arg1, NULL_TREE, arg2);
11011 :
11012 509878 : case BUILT_IN_ADD_OVERFLOW:
11013 509878 : case BUILT_IN_SUB_OVERFLOW:
11014 509878 : case BUILT_IN_MUL_OVERFLOW:
11015 509878 : case BUILT_IN_ADD_OVERFLOW_P:
11016 509878 : case BUILT_IN_SUB_OVERFLOW_P:
11017 509878 : case BUILT_IN_MUL_OVERFLOW_P:
11018 509878 : case BUILT_IN_SADD_OVERFLOW:
11019 509878 : case BUILT_IN_SADDL_OVERFLOW:
11020 509878 : case BUILT_IN_SADDLL_OVERFLOW:
11021 509878 : case BUILT_IN_SSUB_OVERFLOW:
11022 509878 : case BUILT_IN_SSUBL_OVERFLOW:
11023 509878 : case BUILT_IN_SSUBLL_OVERFLOW:
11024 509878 : case BUILT_IN_SMUL_OVERFLOW:
11025 509878 : case BUILT_IN_SMULL_OVERFLOW:
11026 509878 : case BUILT_IN_SMULLL_OVERFLOW:
11027 509878 : case BUILT_IN_UADD_OVERFLOW:
11028 509878 : case BUILT_IN_UADDL_OVERFLOW:
11029 509878 : case BUILT_IN_UADDLL_OVERFLOW:
11030 509878 : case BUILT_IN_USUB_OVERFLOW:
11031 509878 : case BUILT_IN_USUBL_OVERFLOW:
11032 509878 : case BUILT_IN_USUBLL_OVERFLOW:
11033 509878 : case BUILT_IN_UMUL_OVERFLOW:
11034 509878 : case BUILT_IN_UMULL_OVERFLOW:
11035 509878 : case BUILT_IN_UMULLL_OVERFLOW:
11036 509878 : return fold_builtin_arith_overflow (loc, fcode, arg0, arg1, arg2);
11037 :
11038 : default:
11039 : break;
11040 : }
11041 : return NULL_TREE;
11042 : }
11043 :
11044 : /* Folds a call EXPR (which may be null) to built-in function FNDECL.
11045 : ARGS is an array of NARGS arguments. IGNORE is true if the result
11046 : of the function call is ignored. This function returns NULL_TREE
11047 : if no simplification was possible. */
11048 :
11049 : static tree
11050 73786032 : fold_builtin_n (location_t loc, tree expr, tree fndecl, tree *args,
11051 : int nargs, bool)
11052 : {
11053 73786032 : tree ret = NULL_TREE;
11054 :
11055 73786032 : switch (nargs)
11056 : {
11057 24044758 : case 0:
11058 24044758 : ret = fold_builtin_0 (loc, fndecl);
11059 24044758 : break;
11060 20223807 : case 1:
11061 20223807 : ret = fold_builtin_1 (loc, expr, fndecl, args[0]);
11062 20223807 : break;
11063 19481152 : case 2:
11064 19481152 : ret = fold_builtin_2 (loc, expr, fndecl, args[0], args[1]);
11065 19481152 : break;
11066 7418370 : case 3:
11067 7418370 : ret = fold_builtin_3 (loc, fndecl, args[0], args[1], args[2]);
11068 7418370 : break;
11069 2617945 : default:
11070 2617945 : ret = fold_builtin_varargs (loc, fndecl, args, nargs);
11071 2617945 : break;
11072 : }
11073 73786032 : if (ret)
11074 : {
11075 10058099 : ret = build1 (NOP_EXPR, TREE_TYPE (ret), ret);
11076 10058099 : SET_EXPR_LOCATION (ret, loc);
11077 10058099 : return ret;
11078 : }
11079 : return NULL_TREE;
11080 : }
11081 :
11082 : /* Construct a new CALL_EXPR to FNDECL using the tail of the argument
11083 : list ARGS along with N new arguments in NEWARGS. SKIP is the number
11084 : of arguments in ARGS to be omitted. OLDNARGS is the number of
11085 : elements in ARGS. */
11086 :
11087 : static tree
11088 4 : rewrite_call_expr_valist (location_t loc, int oldnargs, tree *args,
11089 : int skip, tree fndecl, int n, va_list newargs)
11090 : {
11091 4 : int nargs = oldnargs - skip + n;
11092 4 : tree *buffer;
11093 :
11094 4 : if (n > 0)
11095 : {
11096 0 : int i, j;
11097 :
11098 0 : buffer = XALLOCAVEC (tree, nargs);
11099 0 : for (i = 0; i < n; i++)
11100 0 : buffer[i] = va_arg (newargs, tree);
11101 0 : for (j = skip; j < oldnargs; j++, i++)
11102 0 : buffer[i] = args[j];
11103 : }
11104 : else
11105 4 : buffer = args + skip;
11106 :
11107 4 : return build_call_expr_loc_array (loc, fndecl, nargs, buffer);
11108 : }
11109 :
11110 : /* Return true if FNDECL shouldn't be folded right now.
11111 : If a built-in function has an inline attribute always_inline
11112 : wrapper, defer folding it after always_inline functions have
11113 : been inlined, otherwise e.g. -D_FORTIFY_SOURCE checking
11114 : might not be performed. */
11115 :
11116 : bool
11117 154553266 : avoid_folding_inline_builtin (tree fndecl)
11118 : {
11119 154553266 : return (DECL_DECLARED_INLINE_P (fndecl)
11120 13268 : && DECL_DISREGARD_INLINE_LIMITS (fndecl)
11121 13226 : && cfun
11122 13226 : && !cfun->always_inline_functions_inlined
11123 154566492 : && lookup_attribute ("always_inline", DECL_ATTRIBUTES (fndecl)));
11124 : }
11125 :
11126 : /* A wrapper function for builtin folding that prevents warnings for
11127 : "statement without effect" and the like, caused by removing the
11128 : call node earlier than the warning is generated. */
11129 :
11130 : tree
11131 203600543 : fold_call_expr (location_t loc, tree exp, bool ignore)
11132 : {
11133 203600543 : tree ret = NULL_TREE;
11134 203600543 : tree fndecl = get_callee_fndecl (exp);
11135 201823960 : if (fndecl && fndecl_built_in_p (fndecl)
11136 : /* If CALL_EXPR_VA_ARG_PACK is set, the arguments aren't finalized
11137 : yet. Defer folding until we see all the arguments
11138 : (after inlining). */
11139 263578766 : && !CALL_EXPR_VA_ARG_PACK (exp))
11140 : {
11141 59978192 : int nargs = call_expr_nargs (exp);
11142 :
11143 : /* Before gimplification CALL_EXPR_VA_ARG_PACK is not set, but
11144 : instead last argument is __builtin_va_arg_pack (). Defer folding
11145 : even in that case, until arguments are finalized. */
11146 59978192 : if (nargs && TREE_CODE (CALL_EXPR_ARG (exp, nargs - 1)) == CALL_EXPR)
11147 : {
11148 223183 : tree fndecl2 = get_callee_fndecl (CALL_EXPR_ARG (exp, nargs - 1));
11149 223183 : if (fndecl2 && fndecl_built_in_p (fndecl2, BUILT_IN_VA_ARG_PACK))
11150 : return NULL_TREE;
11151 : }
11152 :
11153 59978123 : if (avoid_folding_inline_builtin (fndecl))
11154 : return NULL_TREE;
11155 :
11156 59974585 : if (DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_MD)
11157 71889762 : return targetm.fold_builtin (fndecl, call_expr_nargs (exp),
11158 71889762 : CALL_EXPR_ARGP (exp), ignore);
11159 : else
11160 : {
11161 24029704 : tree *args = CALL_EXPR_ARGP (exp);
11162 24029704 : ret = fold_builtin_n (loc, exp, fndecl, args, nargs, ignore);
11163 24029704 : if (ret)
11164 : return ret;
11165 : }
11166 : }
11167 : return NULL_TREE;
11168 : }
11169 :
11170 : /* Fold a CALL_EXPR with type TYPE with FN as the function expression.
11171 : N arguments are passed in the array ARGARRAY. Return a folded
11172 : expression or NULL_TREE if no simplification was possible. */
11173 :
11174 : tree
11175 79409802 : fold_builtin_call_array (location_t loc, tree,
11176 : tree fn,
11177 : int n,
11178 : tree *argarray)
11179 : {
11180 79409802 : if (TREE_CODE (fn) != ADDR_EXPR)
11181 : return NULL_TREE;
11182 :
11183 79409802 : tree fndecl = TREE_OPERAND (fn, 0);
11184 79409802 : if (TREE_CODE (fndecl) == FUNCTION_DECL
11185 79409802 : && fndecl_built_in_p (fndecl))
11186 : {
11187 : /* If last argument is __builtin_va_arg_pack (), arguments to this
11188 : function are not finalized yet. Defer folding until they are. */
11189 78799717 : if (n && TREE_CODE (argarray[n - 1]) == CALL_EXPR)
11190 : {
11191 137417 : tree fndecl2 = get_callee_fndecl (argarray[n - 1]);
11192 137417 : if (fndecl2 && fndecl_built_in_p (fndecl2, BUILT_IN_VA_ARG_PACK))
11193 : return NULL_TREE;
11194 : }
11195 78799678 : if (avoid_folding_inline_builtin (fndecl))
11196 : return NULL_TREE;
11197 78799678 : if (DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_MD)
11198 35179574 : return targetm.fold_builtin (fndecl, n, argarray, false);
11199 : else
11200 43620104 : return fold_builtin_n (loc, NULL_TREE, fndecl, argarray, n, false);
11201 : }
11202 :
11203 : return NULL_TREE;
11204 : }
11205 :
11206 : /* Construct a new CALL_EXPR using the tail of the argument list of EXP
11207 : along with N new arguments specified as the "..." parameters. SKIP
11208 : is the number of arguments in EXP to be omitted. This function is used
11209 : to do varargs-to-varargs transformations. */
11210 :
11211 : static tree
11212 4 : rewrite_call_expr (location_t loc, tree exp, int skip, tree fndecl, int n, ...)
11213 : {
11214 4 : va_list ap;
11215 4 : tree t;
11216 :
11217 4 : va_start (ap, n);
11218 8 : t = rewrite_call_expr_valist (loc, call_expr_nargs (exp),
11219 4 : CALL_EXPR_ARGP (exp), skip, fndecl, n, ap);
11220 4 : va_end (ap);
11221 :
11222 4 : return t;
11223 : }
11224 :
11225 : /* Validate a single argument ARG against a tree code CODE representing
11226 : a type. Return true when argument is valid. */
11227 :
11228 : static bool
11229 15455634 : validate_arg (const_tree arg, enum tree_code code)
11230 : {
11231 15455634 : if (!arg)
11232 : return false;
11233 15455611 : else if (code == POINTER_TYPE)
11234 7173066 : return POINTER_TYPE_P (TREE_TYPE (arg));
11235 8282545 : else if (code == INTEGER_TYPE)
11236 3797787 : return INTEGRAL_TYPE_P (TREE_TYPE (arg));
11237 4484758 : return code == TREE_CODE (TREE_TYPE (arg));
11238 : }
11239 :
11240 : /* This function validates the types of a function call argument list
11241 : against a specified list of tree_codes. If the last specifier is a 0,
11242 : that represents an ellipses, otherwise the last specifier must be a
11243 : VOID_TYPE.
11244 :
11245 : This is the GIMPLE version of validate_arglist. Eventually we want to
11246 : completely convert builtins.cc to work from GIMPLEs and the tree based
11247 : validate_arglist will then be removed. */
11248 :
11249 : bool
11250 136 : validate_gimple_arglist (const gcall *call, ...)
11251 : {
11252 136 : enum tree_code code;
11253 136 : bool res = 0;
11254 136 : va_list ap;
11255 136 : const_tree arg;
11256 136 : size_t i;
11257 :
11258 136 : va_start (ap, call);
11259 136 : i = 0;
11260 :
11261 544 : do
11262 : {
11263 544 : code = (enum tree_code) va_arg (ap, int);
11264 544 : switch (code)
11265 : {
11266 0 : case 0:
11267 : /* This signifies an ellipses, any further arguments are all ok. */
11268 0 : res = true;
11269 0 : goto end;
11270 136 : case VOID_TYPE:
11271 : /* This signifies an endlink, if no arguments remain, return
11272 : true, otherwise return false. */
11273 136 : res = (i == gimple_call_num_args (call));
11274 136 : goto end;
11275 408 : default:
11276 : /* If no parameters remain or the parameter's code does not
11277 : match the specified code, return false. Otherwise continue
11278 : checking any remaining arguments. */
11279 408 : arg = gimple_call_arg (call, i++);
11280 408 : if (!validate_arg (arg, code))
11281 0 : goto end;
11282 : break;
11283 : }
11284 : }
11285 : while (1);
11286 :
11287 : /* We need gotos here since we can only have one VA_CLOSE in a
11288 : function. */
11289 136 : end: ;
11290 136 : va_end (ap);
11291 :
11292 136 : return res;
11293 : }
11294 :
11295 : /* Default target-specific builtin expander that does nothing. */
11296 :
11297 : rtx
11298 0 : default_expand_builtin (tree exp ATTRIBUTE_UNUSED,
11299 : rtx target ATTRIBUTE_UNUSED,
11300 : rtx subtarget ATTRIBUTE_UNUSED,
11301 : machine_mode mode ATTRIBUTE_UNUSED,
11302 : int ignore ATTRIBUTE_UNUSED)
11303 : {
11304 0 : return NULL_RTX;
11305 : }
11306 :
11307 : /* Returns true is EXP represents data that would potentially reside
11308 : in a readonly section. */
11309 :
11310 : bool
11311 210733 : readonly_data_expr (tree exp)
11312 : {
11313 210733 : STRIP_NOPS (exp);
11314 :
11315 210733 : if (TREE_CODE (exp) != ADDR_EXPR)
11316 : return false;
11317 :
11318 26717 : exp = get_base_address (TREE_OPERAND (exp, 0));
11319 26717 : if (!exp)
11320 : return false;
11321 :
11322 : /* Make sure we call decl_readonly_section only for trees it
11323 : can handle (since it returns true for everything it doesn't
11324 : understand). */
11325 26717 : if (TREE_CODE (exp) == STRING_CST
11326 5775 : || TREE_CODE (exp) == CONSTRUCTOR
11327 5775 : || (VAR_P (exp) && TREE_STATIC (exp)))
11328 23561 : return decl_readonly_section (exp, 0);
11329 : else
11330 : return false;
11331 : }
11332 :
11333 : /* Simplify a call to the strpbrk builtin. S1 and S2 are the arguments
11334 : to the call, and TYPE is its return type.
11335 :
11336 : Return NULL_TREE if no simplification was possible, otherwise return the
11337 : simplified form of the call as a tree.
11338 :
11339 : The simplified form may be a constant or other expression which
11340 : computes the same value, but in a more efficient manner (including
11341 : calls to other builtin functions).
11342 :
11343 : The call may contain arguments which need to be evaluated, but
11344 : which are not useful to determine the result of the call. In
11345 : this case we return a chain of COMPOUND_EXPRs. The LHS of each
11346 : COMPOUND_EXPR will be an argument which must be evaluated.
11347 : COMPOUND_EXPRs are chained through their RHS. The RHS of the last
11348 : COMPOUND_EXPR in the chain will contain the tree for the simplified
11349 : form of the builtin function call. */
11350 :
11351 : static tree
11352 100317 : fold_builtin_strpbrk (location_t loc, tree, tree s1, tree s2, tree type)
11353 : {
11354 100317 : if (!validate_arg (s1, POINTER_TYPE)
11355 100317 : || !validate_arg (s2, POINTER_TYPE))
11356 : return NULL_TREE;
11357 :
11358 100317 : tree fn;
11359 100317 : const char *p1, *p2;
11360 :
11361 100317 : p2 = c_getstr (s2);
11362 100317 : if (p2 == NULL)
11363 : return NULL_TREE;
11364 :
11365 92 : p1 = c_getstr (s1);
11366 92 : if (p1 != NULL)
11367 : {
11368 22 : const char *r = strpbrk (p1, p2);
11369 22 : tree tem;
11370 :
11371 22 : if (r == NULL)
11372 0 : return build_int_cst (TREE_TYPE (s1), 0);
11373 :
11374 : /* Return an offset into the constant string argument. */
11375 22 : tem = fold_build_pointer_plus_hwi_loc (loc, s1, r - p1);
11376 22 : return fold_convert_loc (loc, type, tem);
11377 : }
11378 :
11379 70 : if (p2[0] == '\0')
11380 : /* strpbrk(x, "") == NULL.
11381 : Evaluate and ignore s1 in case it had side-effects. */
11382 26 : return omit_one_operand_loc (loc, type, integer_zero_node, s1);
11383 :
11384 44 : if (p2[1] != '\0')
11385 : return NULL_TREE; /* Really call strpbrk. */
11386 :
11387 41 : fn = builtin_decl_implicit (BUILT_IN_STRCHR);
11388 41 : if (!fn)
11389 : return NULL_TREE;
11390 :
11391 : /* New argument list transforming strpbrk(s1, s2) to
11392 : strchr(s1, s2[0]). */
11393 41 : return build_call_expr_loc (loc, fn, 2, s1,
11394 41 : build_int_cst (integer_type_node, p2[0]));
11395 : }
11396 :
11397 : /* Simplify a call to the strspn builtin. S1 and S2 are the arguments
11398 : to the call.
11399 :
11400 : Return NULL_TREE if no simplification was possible, otherwise return the
11401 : simplified form of the call as a tree.
11402 :
11403 : The simplified form may be a constant or other expression which
11404 : computes the same value, but in a more efficient manner (including
11405 : calls to other builtin functions).
11406 :
11407 : The call may contain arguments which need to be evaluated, but
11408 : which are not useful to determine the result of the call. In
11409 : this case we return a chain of COMPOUND_EXPRs. The LHS of each
11410 : COMPOUND_EXPR will be an argument which must be evaluated.
11411 : COMPOUND_EXPRs are chained through their RHS. The RHS of the last
11412 : COMPOUND_EXPR in the chain will contain the tree for the simplified
11413 : form of the builtin function call. */
11414 :
11415 : static tree
11416 2560 : fold_builtin_strspn (location_t loc, tree expr, tree s1, tree s2, tree type)
11417 : {
11418 2560 : if (!validate_arg (s1, POINTER_TYPE)
11419 2560 : || !validate_arg (s2, POINTER_TYPE))
11420 : return NULL_TREE;
11421 :
11422 2560 : if (!check_nul_terminated_array (expr, s1)
11423 2560 : || !check_nul_terminated_array (expr, s2))
11424 : return NULL_TREE;
11425 :
11426 2502 : const char *p1 = c_getstr (s1), *p2 = c_getstr (s2);
11427 :
11428 : /* If either argument is "", return NULL_TREE. */
11429 2502 : if ((p1 && *p1 == '\0') || (p2 && *p2 == '\0'))
11430 : /* Evaluate and ignore both arguments in case either one has
11431 : side-effects. */
11432 147 : return omit_two_operands_loc (loc, type, size_zero_node, s1, s2);
11433 : return NULL_TREE;
11434 : }
11435 :
11436 : /* Simplify a call to the strcspn builtin. S1 and S2 are the arguments
11437 : to the call.
11438 :
11439 : Return NULL_TREE if no simplification was possible, otherwise return the
11440 : simplified form of the call as a tree.
11441 :
11442 : The simplified form may be a constant or other expression which
11443 : computes the same value, but in a more efficient manner (including
11444 : calls to other builtin functions).
11445 :
11446 : The call may contain arguments which need to be evaluated, but
11447 : which are not useful to determine the result of the call. In
11448 : this case we return a chain of COMPOUND_EXPRs. The LHS of each
11449 : COMPOUND_EXPR will be an argument which must be evaluated.
11450 : COMPOUND_EXPRs are chained through their RHS. The RHS of the last
11451 : COMPOUND_EXPR in the chain will contain the tree for the simplified
11452 : form of the builtin function call. */
11453 :
11454 : static tree
11455 2465 : fold_builtin_strcspn (location_t loc, tree expr, tree s1, tree s2, tree type)
11456 : {
11457 2465 : if (!validate_arg (s1, POINTER_TYPE)
11458 2465 : || !validate_arg (s2, POINTER_TYPE))
11459 : return NULL_TREE;
11460 :
11461 2465 : if (!check_nul_terminated_array (expr, s1)
11462 2465 : || !check_nul_terminated_array (expr, s2))
11463 : return NULL_TREE;
11464 :
11465 : /* If the first argument is "", return NULL_TREE. */
11466 2407 : const char *p1 = c_getstr (s1);
11467 2407 : if (p1 && *p1 == '\0')
11468 : {
11469 : /* Evaluate and ignore argument s2 in case it has
11470 : side-effects. */
11471 65 : return omit_one_operand_loc (loc, type, size_zero_node, s2);
11472 : }
11473 :
11474 : /* If the second argument is "", return __builtin_strlen(s1). */
11475 2342 : const char *p2 = c_getstr (s2);
11476 2342 : if (p2 && *p2 == '\0')
11477 : {
11478 81 : tree fn = builtin_decl_implicit (BUILT_IN_STRLEN);
11479 :
11480 : /* If the replacement _DECL isn't initialized, don't do the
11481 : transformation. */
11482 81 : if (!fn)
11483 : return NULL_TREE;
11484 :
11485 81 : return fold_convert_loc (loc, type,
11486 81 : build_call_expr_loc (loc, fn, 1, s1));
11487 : }
11488 : return NULL_TREE;
11489 : }
11490 :
11491 : /* Fold the next_arg or va_start call EXP. Returns true if there was an error
11492 : produced. False otherwise. This is done so that we don't output the error
11493 : or warning twice or three times. */
11494 :
11495 : bool
11496 42132 : fold_builtin_next_arg (tree exp, bool va_start_p)
11497 : {
11498 42132 : tree fntype = TREE_TYPE (current_function_decl);
11499 42132 : int nargs = call_expr_nargs (exp);
11500 42132 : tree arg;
11501 : /* There is good chance the current input_location points inside the
11502 : definition of the va_start macro (perhaps on the token for
11503 : builtin) in a system header, so warnings will not be emitted.
11504 : Use the location in real source code. */
11505 42132 : location_t current_location =
11506 42132 : linemap_unwind_to_first_non_reserved_loc (line_table, input_location,
11507 : NULL);
11508 :
11509 42132 : if (!stdarg_p (fntype))
11510 : {
11511 8 : error ("%<va_start%> used in function with fixed arguments");
11512 8 : return true;
11513 : }
11514 :
11515 42124 : if (va_start_p)
11516 : {
11517 41966 : if (va_start_p && (nargs != 2))
11518 : {
11519 0 : error ("wrong number of arguments to function %<va_start%>");
11520 0 : return true;
11521 : }
11522 41966 : arg = CALL_EXPR_ARG (exp, 1);
11523 : }
11524 : /* We use __builtin_va_start (ap, 0, 0) or __builtin_next_arg (0, 0)
11525 : when we checked the arguments and if needed issued a warning. */
11526 : else
11527 : {
11528 158 : if (nargs == 0)
11529 : {
11530 : /* Evidently an out of date version of <stdarg.h>; can't validate
11531 : va_start's second argument, but can still work as intended. */
11532 0 : warning_at (current_location,
11533 0 : OPT_Wvarargs,
11534 : "%<__builtin_next_arg%> called without an argument");
11535 0 : return true;
11536 : }
11537 158 : else if (nargs > 1)
11538 : {
11539 0 : error ("wrong number of arguments to function %<__builtin_next_arg%>");
11540 0 : return true;
11541 : }
11542 158 : arg = CALL_EXPR_ARG (exp, 0);
11543 : }
11544 :
11545 42124 : if (TREE_CODE (arg) == SSA_NAME
11546 42124 : && SSA_NAME_VAR (arg))
11547 : arg = SSA_NAME_VAR (arg);
11548 :
11549 : /* We destructively modify the call to be __builtin_va_start (ap, 0)
11550 : or __builtin_next_arg (0) the first time we see it, after checking
11551 : the arguments and if needed issuing a warning. */
11552 42124 : if (!integer_zerop (arg))
11553 : {
11554 7025 : tree last_parm = tree_last (DECL_ARGUMENTS (current_function_decl));
11555 :
11556 : /* Strip off all nops for the sake of the comparison. This
11557 : is not quite the same as STRIP_NOPS. It does more.
11558 : We must also strip off INDIRECT_EXPR for C++ reference
11559 : parameters. */
11560 14052 : while (CONVERT_EXPR_P (arg)
11561 14063 : || INDIRECT_REF_P (arg))
11562 11 : arg = TREE_OPERAND (arg, 0);
11563 7025 : if (arg != last_parm)
11564 : {
11565 : /* FIXME: Sometimes with the tree optimizers we can get the
11566 : not the last argument even though the user used the last
11567 : argument. We just warn and set the arg to be the last
11568 : argument so that we will get wrong-code because of
11569 : it. */
11570 12 : warning_at (current_location,
11571 12 : OPT_Wvarargs,
11572 : "second parameter of %<va_start%> not last named argument");
11573 : }
11574 :
11575 : /* Undefined by C99 7.15.1.4p4 (va_start):
11576 : "If the parameter parmN is declared with the register storage
11577 : class, with a function or array type, or with a type that is
11578 : not compatible with the type that results after application of
11579 : the default argument promotions, the behavior is undefined."
11580 : */
11581 7013 : else if (DECL_REGISTER (arg))
11582 : {
11583 12 : warning_at (current_location,
11584 12 : OPT_Wvarargs,
11585 : "undefined behavior when second parameter of "
11586 : "%<va_start%> is declared with %<register%> storage");
11587 : }
11588 :
11589 : /* We want to verify the second parameter just once before the tree
11590 : optimizers are run and then avoid keeping it in the tree,
11591 : as otherwise we could warn even for correct code like:
11592 : void foo (int i, ...)
11593 : { va_list ap; i++; va_start (ap, i); va_end (ap); } */
11594 7025 : if (va_start_p)
11595 7023 : CALL_EXPR_ARG (exp, 1) = integer_zero_node;
11596 : else
11597 2 : CALL_EXPR_ARG (exp, 0) = integer_zero_node;
11598 : }
11599 : return false;
11600 : }
11601 :
11602 :
11603 : /* Expand a call EXP to __builtin_object_size. */
11604 :
11605 : static rtx
11606 620 : expand_builtin_object_size (tree exp)
11607 : {
11608 620 : tree ost;
11609 620 : int object_size_type;
11610 620 : tree fndecl = get_callee_fndecl (exp);
11611 :
11612 620 : if (!validate_arglist (exp, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
11613 : {
11614 0 : error ("first argument of %qD must be a pointer, second integer constant",
11615 : fndecl);
11616 0 : expand_builtin_trap ();
11617 0 : return const0_rtx;
11618 : }
11619 :
11620 620 : ost = CALL_EXPR_ARG (exp, 1);
11621 620 : STRIP_NOPS (ost);
11622 :
11623 620 : if (TREE_CODE (ost) != INTEGER_CST
11624 620 : || tree_int_cst_sgn (ost) < 0
11625 1240 : || compare_tree_int (ost, 3) > 0)
11626 : {
11627 0 : error ("last argument of %qD is not integer constant between 0 and 3",
11628 : fndecl);
11629 0 : expand_builtin_trap ();
11630 0 : return const0_rtx;
11631 : }
11632 :
11633 620 : object_size_type = tree_to_shwi (ost);
11634 :
11635 620 : return object_size_type < 2 ? constm1_rtx : const0_rtx;
11636 : }
11637 :
11638 : /* Expand EXP, a call to the __mem{cpy,pcpy,move,set}_chk builtin.
11639 : FCODE is the BUILT_IN_* to use.
11640 : Return NULL_RTX if we failed; the caller should emit a normal call,
11641 : otherwise try to get the result in TARGET, if convenient (and in
11642 : mode MODE if that's convenient). */
11643 :
11644 : static rtx
11645 837 : expand_builtin_memory_chk (tree exp, rtx target, machine_mode mode,
11646 : enum built_in_function fcode)
11647 : {
11648 1410 : if (!validate_arglist (exp,
11649 : POINTER_TYPE,
11650 : fcode == BUILT_IN_MEMSET_CHK
11651 : ? INTEGER_TYPE : POINTER_TYPE,
11652 : INTEGER_TYPE, INTEGER_TYPE, VOID_TYPE))
11653 : return NULL_RTX;
11654 :
11655 837 : tree dest = CALL_EXPR_ARG (exp, 0);
11656 837 : tree src = CALL_EXPR_ARG (exp, 1);
11657 837 : tree len = CALL_EXPR_ARG (exp, 2);
11658 837 : tree size = CALL_EXPR_ARG (exp, 3);
11659 :
11660 : /* FIXME: Set access mode to write only for memset et al. */
11661 837 : bool sizes_ok = check_access (exp, len, /*maxread=*/NULL_TREE,
11662 : /*srcstr=*/NULL_TREE, size, access_read_write);
11663 :
11664 837 : if (!tree_fits_uhwi_p (size))
11665 : return NULL_RTX;
11666 :
11667 627 : if (tree_fits_uhwi_p (len) || integer_all_onesp (size))
11668 : {
11669 : /* Avoid transforming the checking call to an ordinary one when
11670 : an overflow has been detected or when the call couldn't be
11671 : validated because the size is not constant. */
11672 186 : if (!sizes_ok && !integer_all_onesp (size) && tree_int_cst_lt (size, len))
11673 : return NULL_RTX;
11674 :
11675 0 : tree fn = NULL_TREE;
11676 : /* If __builtin_mem{cpy,pcpy,move,set}_chk is used, assume
11677 : mem{cpy,pcpy,move,set} is available. */
11678 0 : switch (fcode)
11679 : {
11680 0 : case BUILT_IN_MEMCPY_CHK:
11681 0 : fn = builtin_decl_explicit (BUILT_IN_MEMCPY);
11682 0 : break;
11683 0 : case BUILT_IN_MEMPCPY_CHK:
11684 0 : fn = builtin_decl_explicit (BUILT_IN_MEMPCPY);
11685 0 : break;
11686 0 : case BUILT_IN_MEMMOVE_CHK:
11687 0 : fn = builtin_decl_explicit (BUILT_IN_MEMMOVE);
11688 0 : break;
11689 0 : case BUILT_IN_MEMSET_CHK:
11690 0 : fn = builtin_decl_explicit (BUILT_IN_MEMSET);
11691 0 : break;
11692 : default:
11693 : break;
11694 : }
11695 :
11696 0 : if (! fn)
11697 : return NULL_RTX;
11698 :
11699 0 : fn = build_call_nofold_loc (EXPR_LOCATION (exp), fn, 3, dest, src, len);
11700 0 : gcc_assert (TREE_CODE (fn) == CALL_EXPR);
11701 0 : CALL_EXPR_TAILCALL (fn) = CALL_EXPR_TAILCALL (exp);
11702 0 : return expand_expr (fn, target, mode, EXPAND_NORMAL);
11703 : }
11704 441 : else if (fcode == BUILT_IN_MEMSET_CHK)
11705 : return NULL_RTX;
11706 : else
11707 : {
11708 293 : unsigned int dest_align = get_pointer_alignment (dest);
11709 :
11710 : /* If DEST is not a pointer type, call the normal function. */
11711 293 : if (dest_align == 0)
11712 : return NULL_RTX;
11713 :
11714 : /* If SRC and DEST are the same (and not volatile), do nothing. */
11715 293 : if (operand_equal_p (src, dest, 0))
11716 : {
11717 0 : tree expr;
11718 :
11719 0 : if (fcode != BUILT_IN_MEMPCPY_CHK)
11720 : {
11721 : /* Evaluate and ignore LEN in case it has side-effects. */
11722 0 : expand_expr (len, const0_rtx, VOIDmode, EXPAND_NORMAL);
11723 0 : return expand_expr (dest, target, mode, EXPAND_NORMAL);
11724 : }
11725 :
11726 0 : expr = fold_build_pointer_plus (dest, len);
11727 0 : return expand_expr (expr, target, mode, EXPAND_NORMAL);
11728 : }
11729 :
11730 : /* __memmove_chk special case. */
11731 293 : if (fcode == BUILT_IN_MEMMOVE_CHK)
11732 : {
11733 79 : unsigned int src_align = get_pointer_alignment (src);
11734 :
11735 79 : if (src_align == 0)
11736 : return NULL_RTX;
11737 :
11738 : /* If src is categorized for a readonly section we can use
11739 : normal __memcpy_chk. */
11740 79 : if (readonly_data_expr (src))
11741 : {
11742 15 : tree fn = builtin_decl_explicit (BUILT_IN_MEMCPY_CHK);
11743 15 : if (!fn)
11744 : return NULL_RTX;
11745 15 : fn = build_call_nofold_loc (EXPR_LOCATION (exp), fn, 4,
11746 : dest, src, len, size);
11747 15 : gcc_assert (TREE_CODE (fn) == CALL_EXPR);
11748 15 : CALL_EXPR_TAILCALL (fn) = CALL_EXPR_TAILCALL (exp);
11749 15 : return expand_expr (fn, target, mode, EXPAND_NORMAL);
11750 : }
11751 : }
11752 : return NULL_RTX;
11753 : }
11754 : }
11755 :
11756 : /* Emit warning if a buffer overflow is detected at compile time. */
11757 :
11758 : static void
11759 1086 : maybe_emit_chk_warning (tree exp, enum built_in_function fcode)
11760 : {
11761 : /* The source string. */
11762 1086 : tree srcstr = NULL_TREE;
11763 : /* The size of the destination object returned by __builtin_object_size. */
11764 1086 : tree objsize = NULL_TREE;
11765 : /* The string that is being concatenated with (as in __strcat_chk)
11766 : or null if it isn't. */
11767 1086 : tree catstr = NULL_TREE;
11768 : /* The maximum length of the source sequence in a bounded operation
11769 : (such as __strncat_chk) or null if the operation isn't bounded
11770 : (such as __strcat_chk). */
11771 1086 : tree maxread = NULL_TREE;
11772 : /* The exact size of the access (such as in __strncpy_chk). */
11773 1086 : tree size = NULL_TREE;
11774 : /* The access by the function that's checked. Except for snprintf
11775 : both writing and reading is checked. */
11776 1086 : access_mode mode = access_read_write;
11777 :
11778 1086 : switch (fcode)
11779 : {
11780 275 : case BUILT_IN_STRCPY_CHK:
11781 275 : case BUILT_IN_STPCPY_CHK:
11782 275 : srcstr = CALL_EXPR_ARG (exp, 1);
11783 275 : objsize = CALL_EXPR_ARG (exp, 2);
11784 275 : break;
11785 :
11786 151 : case BUILT_IN_STRCAT_CHK:
11787 : /* For __strcat_chk the warning will be emitted only if overflowing
11788 : by at least strlen (dest) + 1 bytes. */
11789 151 : catstr = CALL_EXPR_ARG (exp, 0);
11790 151 : srcstr = CALL_EXPR_ARG (exp, 1);
11791 151 : objsize = CALL_EXPR_ARG (exp, 2);
11792 151 : break;
11793 :
11794 108 : case BUILT_IN_STRNCAT_CHK:
11795 108 : catstr = CALL_EXPR_ARG (exp, 0);
11796 108 : srcstr = CALL_EXPR_ARG (exp, 1);
11797 108 : maxread = CALL_EXPR_ARG (exp, 2);
11798 108 : objsize = CALL_EXPR_ARG (exp, 3);
11799 108 : break;
11800 :
11801 243 : case BUILT_IN_STRNCPY_CHK:
11802 243 : case BUILT_IN_STPNCPY_CHK:
11803 243 : srcstr = CALL_EXPR_ARG (exp, 1);
11804 243 : size = CALL_EXPR_ARG (exp, 2);
11805 243 : objsize = CALL_EXPR_ARG (exp, 3);
11806 243 : break;
11807 :
11808 309 : case BUILT_IN_SNPRINTF_CHK:
11809 309 : case BUILT_IN_VSNPRINTF_CHK:
11810 309 : maxread = CALL_EXPR_ARG (exp, 1);
11811 309 : objsize = CALL_EXPR_ARG (exp, 3);
11812 : /* The only checked access the write to the destination. */
11813 309 : mode = access_write_only;
11814 309 : break;
11815 0 : default:
11816 0 : gcc_unreachable ();
11817 : }
11818 :
11819 1086 : if (catstr && maxread)
11820 : {
11821 : /* Check __strncat_chk. There is no way to determine the length
11822 : of the string to which the source string is being appended so
11823 : just warn when the length of the source string is not known. */
11824 108 : check_strncat_sizes (exp, objsize);
11825 108 : return;
11826 : }
11827 :
11828 978 : check_access (exp, size, maxread, srcstr, objsize, mode);
11829 : }
11830 :
11831 : /* Emit warning if a buffer overflow is detected at compile time
11832 : in __sprintf_chk/__vsprintf_chk calls. */
11833 :
11834 : static void
11835 1328 : maybe_emit_sprintf_chk_warning (tree exp, enum built_in_function fcode)
11836 : {
11837 1328 : tree size, len, fmt;
11838 1328 : const char *fmt_str;
11839 1328 : int nargs = call_expr_nargs (exp);
11840 :
11841 : /* Verify the required arguments in the original call. */
11842 :
11843 1328 : if (nargs < 4)
11844 : return;
11845 1328 : size = CALL_EXPR_ARG (exp, 2);
11846 1328 : fmt = CALL_EXPR_ARG (exp, 3);
11847 :
11848 1328 : if (! tree_fits_uhwi_p (size) || integer_all_onesp (size))
11849 : return;
11850 :
11851 : /* Check whether the format is a literal string constant. */
11852 1307 : fmt_str = c_getstr (fmt);
11853 1307 : if (fmt_str == NULL)
11854 : return;
11855 :
11856 1271 : if (!init_target_chars ())
11857 : return;
11858 :
11859 : /* If the format doesn't contain % args or %%, we know its size. */
11860 1271 : if (strchr (fmt_str, target_percent) == 0)
11861 22 : len = build_int_cstu (size_type_node, strlen (fmt_str));
11862 : /* If the format is "%s" and first ... argument is a string literal,
11863 : we know it too. */
11864 1249 : else if (fcode == BUILT_IN_SPRINTF_CHK
11865 1095 : && strcmp (fmt_str, target_percent_s) == 0)
11866 : {
11867 49 : tree arg;
11868 :
11869 49 : if (nargs < 5)
11870 : return;
11871 49 : arg = CALL_EXPR_ARG (exp, 4);
11872 49 : if (! POINTER_TYPE_P (TREE_TYPE (arg)))
11873 : return;
11874 :
11875 45 : len = c_strlen (arg, 1);
11876 45 : if (!len || ! tree_fits_uhwi_p (len))
11877 : return;
11878 : }
11879 : else
11880 : return;
11881 :
11882 : /* Add one for the terminating nul. */
11883 34 : len = fold_build2 (PLUS_EXPR, TREE_TYPE (len), len, size_one_node);
11884 :
11885 34 : check_access (exp, /*size=*/NULL_TREE, /*maxread=*/NULL_TREE, len, size,
11886 : access_write_only);
11887 : }
11888 :
11889 : /* Fold a call to __builtin_object_size with arguments PTR and OST,
11890 : if possible. */
11891 :
11892 : static tree
11893 201103 : fold_builtin_object_size (tree ptr, tree ost, enum built_in_function fcode)
11894 : {
11895 201103 : tree bytes;
11896 201103 : int object_size_type;
11897 :
11898 201103 : if (!validate_arg (ptr, POINTER_TYPE)
11899 201103 : || !validate_arg (ost, INTEGER_TYPE))
11900 : return NULL_TREE;
11901 :
11902 201103 : STRIP_NOPS (ost);
11903 :
11904 201103 : if (TREE_CODE (ost) != INTEGER_CST
11905 201103 : || tree_int_cst_sgn (ost) < 0
11906 402206 : || compare_tree_int (ost, 3) > 0)
11907 : return NULL_TREE;
11908 :
11909 201103 : object_size_type = tree_to_shwi (ost);
11910 :
11911 : /* __builtin_object_size doesn't evaluate side-effects in its arguments;
11912 : if there are any side-effects, it returns (size_t) -1 for types 0 and 1
11913 : and (size_t) 0 for types 2 and 3. */
11914 201103 : if (TREE_SIDE_EFFECTS (ptr))
11915 603 : return build_int_cst_type (size_type_node, object_size_type < 2 ? -1 : 0);
11916 :
11917 200500 : if (fcode == BUILT_IN_DYNAMIC_OBJECT_SIZE)
11918 67467 : object_size_type |= OST_DYNAMIC;
11919 :
11920 200500 : if (TREE_CODE (ptr) == ADDR_EXPR)
11921 : {
11922 12232 : compute_builtin_object_size (ptr, object_size_type, &bytes);
11923 12232 : if ((object_size_type & OST_DYNAMIC)
11924 10886 : || int_fits_type_p (bytes, size_type_node))
11925 12232 : return fold_convert (size_type_node, bytes);
11926 : }
11927 188268 : else if (TREE_CODE (ptr) == SSA_NAME)
11928 : {
11929 : /* If object size is not known yet, delay folding until
11930 : later. Maybe subsequent passes will help determining
11931 : it. */
11932 102230 : if (compute_builtin_object_size (ptr, object_size_type, &bytes)
11933 102230 : && ((object_size_type & OST_DYNAMIC)
11934 2538 : || int_fits_type_p (bytes, size_type_node)))
11935 4808 : return fold_convert (size_type_node, bytes);
11936 : }
11937 :
11938 : return NULL_TREE;
11939 : }
11940 :
11941 : /* Builtins with folding operations that operate on "..." arguments
11942 : need special handling; we need to store the arguments in a convenient
11943 : data structure before attempting any folding. Fortunately there are
11944 : only a few builtins that fall into this category. FNDECL is the
11945 : function, EXP is the CALL_EXPR for the call. */
11946 :
11947 : static tree
11948 2617945 : fold_builtin_varargs (location_t loc, tree fndecl, tree *args, int nargs)
11949 : {
11950 2617945 : enum built_in_function fcode = DECL_FUNCTION_CODE (fndecl);
11951 2617945 : tree ret = NULL_TREE;
11952 :
11953 2617945 : switch (fcode)
11954 : {
11955 104514 : case BUILT_IN_FPCLASSIFY:
11956 104514 : ret = fold_builtin_fpclassify (loc, args, nargs);
11957 104514 : break;
11958 :
11959 55 : case BUILT_IN_ADDC:
11960 55 : case BUILT_IN_ADDCL:
11961 55 : case BUILT_IN_ADDCLL:
11962 55 : case BUILT_IN_SUBC:
11963 55 : case BUILT_IN_SUBCL:
11964 55 : case BUILT_IN_SUBCLL:
11965 55 : return fold_builtin_addc_subc (loc, fcode, args);
11966 :
11967 : default:
11968 : break;
11969 : }
11970 104514 : if (ret)
11971 : {
11972 104514 : ret = build1 (NOP_EXPR, TREE_TYPE (ret), ret);
11973 104514 : SET_EXPR_LOCATION (ret, loc);
11974 104514 : suppress_warning (ret);
11975 104514 : return ret;
11976 : }
11977 : return NULL_TREE;
11978 : }
11979 :
11980 : /* Initialize format string characters in the target charset. */
11981 :
11982 : bool
11983 290517 : init_target_chars (void)
11984 : {
11985 290517 : static bool init;
11986 290517 : if (!init)
11987 : {
11988 115421 : target_newline = lang_hooks.to_target_charset ('\n');
11989 115421 : target_percent = lang_hooks.to_target_charset ('%');
11990 115421 : target_c = lang_hooks.to_target_charset ('c');
11991 115421 : target_s = lang_hooks.to_target_charset ('s');
11992 115421 : if (target_newline == 0 || target_percent == 0 || target_c == 0
11993 115421 : || target_s == 0)
11994 : return false;
11995 :
11996 115421 : target_percent_c[0] = target_percent;
11997 115421 : target_percent_c[1] = target_c;
11998 115421 : target_percent_c[2] = '\0';
11999 :
12000 115421 : target_percent_s[0] = target_percent;
12001 115421 : target_percent_s[1] = target_s;
12002 115421 : target_percent_s[2] = '\0';
12003 :
12004 115421 : target_percent_s_newline[0] = target_percent;
12005 115421 : target_percent_s_newline[1] = target_s;
12006 115421 : target_percent_s_newline[2] = target_newline;
12007 115421 : target_percent_s_newline[3] = '\0';
12008 :
12009 115421 : init = true;
12010 : }
12011 : return true;
12012 : }
12013 :
12014 : /* Helper function for do_mpfr_arg*(). Ensure M is a normal number
12015 : and no overflow/underflow occurred. INEXACT is true if M was not
12016 : exactly calculated. TYPE is the tree type for the result. This
12017 : function assumes that you cleared the MPFR flags and then
12018 : calculated M to see if anything subsequently set a flag prior to
12019 : entering this function. Return NULL_TREE if any checks fail. */
12020 :
12021 : static tree
12022 2979 : do_mpfr_ckconv (mpfr_srcptr m, tree type, int inexact)
12023 : {
12024 : /* Proceed iff we get a normal number, i.e. not NaN or Inf and no
12025 : overflow/underflow occurred. If -frounding-math, proceed iff the
12026 : result of calling FUNC was exact. */
12027 4832 : if (mpfr_number_p (m) && !mpfr_overflow_p () && !mpfr_underflow_p ()
12028 4832 : && (!flag_rounding_math || !inexact))
12029 : {
12030 1853 : REAL_VALUE_TYPE rr;
12031 :
12032 1853 : real_from_mpfr (&rr, m, type, MPFR_RNDN);
12033 : /* Proceed iff GCC's REAL_VALUE_TYPE can hold the MPFR value,
12034 : check for overflow/underflow. If the REAL_VALUE_TYPE is zero
12035 : but the mpfr_t is not, then we underflowed in the
12036 : conversion. */
12037 1853 : if (real_isfinite (&rr)
12038 1853 : && (rr.cl == rvc_zero) == (mpfr_zero_p (m) != 0))
12039 : {
12040 1853 : REAL_VALUE_TYPE rmode;
12041 :
12042 1853 : real_convert (&rmode, TYPE_MODE (type), &rr);
12043 : /* Proceed iff the specified mode can hold the value. */
12044 1853 : if (real_identical (&rmode, &rr))
12045 1853 : return build_real (type, rmode);
12046 : }
12047 : }
12048 : return NULL_TREE;
12049 : }
12050 :
12051 : /* Helper function for do_mpc_arg*(). Ensure M is a normal complex
12052 : number and no overflow/underflow occurred. INEXACT is true if M
12053 : was not exactly calculated. TYPE is the tree type for the result.
12054 : This function assumes that you cleared the MPFR flags and then
12055 : calculated M to see if anything subsequently set a flag prior to
12056 : entering this function. Return NULL_TREE if any checks fail, if
12057 : FORCE_CONVERT is true, then bypass the checks. */
12058 :
12059 : static tree
12060 4171 : do_mpc_ckconv (mpc_srcptr m, tree type, int inexact, int force_convert)
12061 : {
12062 : /* Proceed iff we get a normal number, i.e. not NaN or Inf and no
12063 : overflow/underflow occurred. If -frounding-math, proceed iff the
12064 : result of calling FUNC was exact. */
12065 4171 : if (force_convert
12066 4171 : || (mpfr_number_p (mpc_realref (m)) && mpfr_number_p (mpc_imagref (m))
12067 3852 : && !mpfr_overflow_p () && !mpfr_underflow_p ()
12068 3852 : && (!flag_rounding_math || !inexact)))
12069 : {
12070 3992 : REAL_VALUE_TYPE re, im;
12071 :
12072 3992 : real_from_mpfr (&re, mpc_realref (m), TREE_TYPE (type), MPFR_RNDN);
12073 3992 : real_from_mpfr (&im, mpc_imagref (m), TREE_TYPE (type), MPFR_RNDN);
12074 : /* Proceed iff GCC's REAL_VALUE_TYPE can hold the MPFR values,
12075 : check for overflow/underflow. If the REAL_VALUE_TYPE is zero
12076 : but the mpfr_t is not, then we underflowed in the
12077 : conversion. */
12078 3992 : if (force_convert
12079 3992 : || (real_isfinite (&re) && real_isfinite (&im)
12080 3852 : && (re.cl == rvc_zero) == (mpfr_zero_p (mpc_realref (m)) != 0)
12081 3852 : && (im.cl == rvc_zero) == (mpfr_zero_p (mpc_imagref (m)) != 0)))
12082 : {
12083 3992 : REAL_VALUE_TYPE re_mode, im_mode;
12084 :
12085 3992 : real_convert (&re_mode, TYPE_MODE (TREE_TYPE (type)), &re);
12086 3992 : real_convert (&im_mode, TYPE_MODE (TREE_TYPE (type)), &im);
12087 : /* Proceed iff the specified mode can hold the value. */
12088 3992 : if (force_convert
12089 3992 : || (real_identical (&re_mode, &re)
12090 3852 : && real_identical (&im_mode, &im)))
12091 3992 : return build_complex (type, build_real (TREE_TYPE (type), re_mode),
12092 7984 : build_real (TREE_TYPE (type), im_mode));
12093 : }
12094 : }
12095 : return NULL_TREE;
12096 : }
12097 :
12098 : /* If arguments ARG0 and ARG1 are REAL_CSTs, call mpfr_remquo() to set
12099 : the pointer *(ARG_QUO) and return the result. The type is taken
12100 : from the type of ARG0 and is used for setting the precision of the
12101 : calculation and results. */
12102 :
12103 : static tree
12104 99940 : do_mpfr_remquo (tree arg0, tree arg1, tree arg_quo)
12105 : {
12106 99940 : tree const type = TREE_TYPE (arg0);
12107 99940 : tree result = NULL_TREE;
12108 :
12109 99940 : STRIP_NOPS (arg0);
12110 99940 : STRIP_NOPS (arg1);
12111 :
12112 : /* To proceed, MPFR must exactly represent the target floating point
12113 : format, which only happens when the target base equals two. */
12114 99940 : if (REAL_MODE_FORMAT (TYPE_MODE (type))->b == 2
12115 99940 : && TREE_CODE (arg0) == REAL_CST && !TREE_OVERFLOW (arg0)
12116 102245 : && TREE_CODE (arg1) == REAL_CST && !TREE_OVERFLOW (arg1))
12117 : {
12118 2305 : const REAL_VALUE_TYPE *const ra0 = TREE_REAL_CST_PTR (arg0);
12119 2305 : const REAL_VALUE_TYPE *const ra1 = TREE_REAL_CST_PTR (arg1);
12120 :
12121 2305 : if (real_isfinite (ra0) && real_isfinite (ra1))
12122 : {
12123 2305 : const struct real_format *fmt = REAL_MODE_FORMAT (TYPE_MODE (type));
12124 2305 : const int prec = fmt->p;
12125 2305 : const mpfr_rnd_t rnd = fmt->round_towards_zero? MPFR_RNDZ : MPFR_RNDN;
12126 2305 : tree result_rem;
12127 2305 : long integer_quo;
12128 2305 : mpfr_t m0, m1;
12129 :
12130 2305 : mpfr_inits2 (prec, m0, m1, NULL);
12131 2305 : mpfr_from_real (m0, ra0, MPFR_RNDN);
12132 2305 : mpfr_from_real (m1, ra1, MPFR_RNDN);
12133 2305 : mpfr_clear_flags ();
12134 2305 : mpfr_remquo (m0, &integer_quo, m0, m1, rnd);
12135 : /* Remquo is independent of the rounding mode, so pass
12136 : inexact=0 to do_mpfr_ckconv(). */
12137 2305 : result_rem = do_mpfr_ckconv (m0, type, /*inexact=*/ 0);
12138 2305 : mpfr_clears (m0, m1, NULL);
12139 2305 : if (result_rem)
12140 : {
12141 : /* MPFR calculates quo in the host's long so it may
12142 : return more bits in quo than the target int can hold
12143 : if sizeof(host long) > sizeof(target int). This can
12144 : happen even for native compilers in LP64 mode. In
12145 : these cases, modulo the quo value with the largest
12146 : number that the target int can hold while leaving one
12147 : bit for the sign. */
12148 1179 : if (sizeof (integer_quo) * CHAR_BIT > INT_TYPE_SIZE)
12149 1179 : integer_quo %= (long)(1UL << (INT_TYPE_SIZE - 1));
12150 :
12151 : /* Dereference the quo pointer argument. */
12152 1179 : arg_quo = build_fold_indirect_ref (arg_quo);
12153 : /* Proceed iff a valid pointer type was passed in. */
12154 1179 : if (TYPE_MAIN_VARIANT (TREE_TYPE (arg_quo)) == integer_type_node)
12155 : {
12156 : /* Set the value. */
12157 1179 : tree result_quo
12158 1179 : = fold_build2 (MODIFY_EXPR, TREE_TYPE (arg_quo), arg_quo,
12159 : build_int_cst (TREE_TYPE (arg_quo),
12160 : integer_quo));
12161 1179 : TREE_SIDE_EFFECTS (result_quo) = 1;
12162 : /* Combine the quo assignment with the rem. */
12163 1179 : result = fold_build2 (COMPOUND_EXPR, type,
12164 : result_quo, result_rem);
12165 1179 : suppress_warning (result, OPT_Wunused_value);
12166 1179 : result = non_lvalue (result);
12167 : }
12168 : }
12169 : }
12170 : }
12171 99940 : return result;
12172 : }
12173 :
12174 : /* If ARG is a REAL_CST, call mpfr_lgamma() on it and return the
12175 : resulting value as a tree with type TYPE. The mpfr precision is
12176 : set to the precision of TYPE. We assume that this mpfr function
12177 : returns zero if the result could be calculated exactly within the
12178 : requested precision. In addition, the integer pointer represented
12179 : by ARG_SG will be dereferenced and set to the appropriate signgam
12180 : (-1,1) value. */
12181 :
12182 : static tree
12183 6504 : do_mpfr_lgamma_r (tree arg, tree arg_sg, tree type)
12184 : {
12185 6504 : tree result = NULL_TREE;
12186 :
12187 6504 : STRIP_NOPS (arg);
12188 :
12189 : /* To proceed, MPFR must exactly represent the target floating point
12190 : format, which only happens when the target base equals two. Also
12191 : verify ARG is a constant and that ARG_SG is an int pointer. */
12192 6504 : if (REAL_MODE_FORMAT (TYPE_MODE (type))->b == 2
12193 6504 : && TREE_CODE (arg) == REAL_CST && !TREE_OVERFLOW (arg)
12194 6470 : && TREE_CODE (TREE_TYPE (arg_sg)) == POINTER_TYPE
12195 12974 : && TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (arg_sg))) == integer_type_node)
12196 : {
12197 6470 : const REAL_VALUE_TYPE *const ra = TREE_REAL_CST_PTR (arg);
12198 :
12199 : /* In addition to NaN and Inf, the argument cannot be zero or a
12200 : negative integer. */
12201 6470 : if (real_isfinite (ra)
12202 6470 : && ra->cl != rvc_zero
12203 12940 : && !(real_isneg (ra) && real_isinteger (ra, TYPE_MODE (type))))
12204 : {
12205 674 : const struct real_format *fmt = REAL_MODE_FORMAT (TYPE_MODE (type));
12206 674 : const int prec = fmt->p;
12207 674 : const mpfr_rnd_t rnd = fmt->round_towards_zero? MPFR_RNDZ : MPFR_RNDN;
12208 674 : int inexact, sg;
12209 674 : tree result_lg;
12210 :
12211 674 : auto_mpfr m (prec);
12212 674 : mpfr_from_real (m, ra, MPFR_RNDN);
12213 674 : mpfr_clear_flags ();
12214 674 : inexact = mpfr_lgamma (m, &sg, m, rnd);
12215 674 : result_lg = do_mpfr_ckconv (m, type, inexact);
12216 674 : if (result_lg)
12217 : {
12218 674 : tree result_sg;
12219 :
12220 : /* Dereference the arg_sg pointer argument. */
12221 674 : arg_sg = build_fold_indirect_ref (arg_sg);
12222 : /* Assign the signgam value into *arg_sg. */
12223 674 : result_sg = fold_build2 (MODIFY_EXPR,
12224 : TREE_TYPE (arg_sg), arg_sg,
12225 : build_int_cst (TREE_TYPE (arg_sg), sg));
12226 674 : TREE_SIDE_EFFECTS (result_sg) = 1;
12227 : /* Combine the signgam assignment with the lgamma result. */
12228 674 : result = non_lvalue (fold_build2 (COMPOUND_EXPR, type,
12229 : result_sg, result_lg));
12230 : }
12231 674 : }
12232 : }
12233 :
12234 6504 : return result;
12235 : }
12236 :
12237 : /* If arguments ARG0 and ARG1 are a COMPLEX_CST, call the two-argument
12238 : mpc function FUNC on it and return the resulting value as a tree
12239 : with type TYPE. The mpfr precision is set to the precision of
12240 : TYPE. We assume that function FUNC returns zero if the result
12241 : could be calculated exactly within the requested precision. If
12242 : DO_NONFINITE is true, then fold expressions containing Inf or NaN
12243 : in the arguments and/or results. */
12244 :
12245 : tree
12246 4523 : do_mpc_arg2 (tree arg0, tree arg1, tree type, int do_nonfinite,
12247 : int (*func)(mpc_ptr, mpc_srcptr, mpc_srcptr, mpc_rnd_t))
12248 : {
12249 4523 : tree result = NULL_TREE;
12250 :
12251 4523 : STRIP_NOPS (arg0);
12252 4523 : STRIP_NOPS (arg1);
12253 :
12254 : /* To proceed, MPFR must exactly represent the target floating point
12255 : format, which only happens when the target base equals two. */
12256 4523 : if (TREE_CODE (arg0) == COMPLEX_CST && !TREE_OVERFLOW (arg0)
12257 4523 : && SCALAR_FLOAT_TYPE_P (TREE_TYPE (TREE_TYPE (arg0)))
12258 4523 : && TREE_CODE (arg1) == COMPLEX_CST && !TREE_OVERFLOW (arg1)
12259 4523 : && SCALAR_FLOAT_TYPE_P (TREE_TYPE (TREE_TYPE (arg1)))
12260 9046 : && REAL_MODE_FORMAT (TYPE_MODE (TREE_TYPE (TREE_TYPE (arg0))))->b == 2)
12261 : {
12262 4523 : const REAL_VALUE_TYPE *const re0 = TREE_REAL_CST_PTR (TREE_REALPART (arg0));
12263 4523 : const REAL_VALUE_TYPE *const im0 = TREE_REAL_CST_PTR (TREE_IMAGPART (arg0));
12264 4523 : const REAL_VALUE_TYPE *const re1 = TREE_REAL_CST_PTR (TREE_REALPART (arg1));
12265 4523 : const REAL_VALUE_TYPE *const im1 = TREE_REAL_CST_PTR (TREE_IMAGPART (arg1));
12266 :
12267 4523 : if (do_nonfinite
12268 4523 : || (real_isfinite (re0) && real_isfinite (im0)
12269 4059 : && real_isfinite (re1) && real_isfinite (im1)))
12270 : {
12271 4171 : const struct real_format *const fmt =
12272 4171 : REAL_MODE_FORMAT (TYPE_MODE (TREE_TYPE (type)));
12273 4171 : const int prec = fmt->p;
12274 4171 : const mpfr_rnd_t rnd = fmt->round_towards_zero
12275 4171 : ? MPFR_RNDZ : MPFR_RNDN;
12276 4171 : const mpc_rnd_t crnd = fmt->round_towards_zero ? MPC_RNDZZ : MPC_RNDNN;
12277 4171 : int inexact;
12278 4171 : mpc_t m0, m1;
12279 :
12280 4171 : mpc_init2 (m0, prec);
12281 4171 : mpc_init2 (m1, prec);
12282 4171 : mpfr_from_real (mpc_realref (m0), re0, rnd);
12283 4171 : mpfr_from_real (mpc_imagref (m0), im0, rnd);
12284 4171 : mpfr_from_real (mpc_realref (m1), re1, rnd);
12285 4171 : mpfr_from_real (mpc_imagref (m1), im1, rnd);
12286 4171 : mpfr_clear_flags ();
12287 4171 : inexact = func (m0, m0, m1, crnd);
12288 4171 : result = do_mpc_ckconv (m0, type, inexact, do_nonfinite);
12289 4171 : mpc_clear (m0);
12290 4171 : mpc_clear (m1);
12291 : }
12292 : }
12293 :
12294 4523 : return result;
12295 : }
12296 :
12297 : /* A wrapper function for builtin folding that prevents warnings for
12298 : "statement without effect" and the like, caused by removing the
12299 : call node earlier than the warning is generated. */
12300 :
12301 : tree
12302 6136290 : fold_call_stmt (gcall *stmt, bool ignore)
12303 : {
12304 6136290 : tree ret = NULL_TREE;
12305 6136290 : tree fndecl = gimple_call_fndecl (stmt);
12306 6136290 : location_t loc = gimple_location (stmt);
12307 6136290 : if (fndecl && fndecl_built_in_p (fndecl)
12308 12272580 : && !gimple_call_va_arg_pack_p (stmt))
12309 : {
12310 6136224 : int nargs = gimple_call_num_args (stmt);
12311 6136224 : tree *args = (nargs > 0
12312 6136224 : ? gimple_call_arg_ptr (stmt, 0)
12313 : : &error_mark_node);
12314 :
12315 6136224 : if (avoid_folding_inline_builtin (fndecl))
12316 : return NULL_TREE;
12317 6136224 : if (DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_MD)
12318 : {
12319 0 : return targetm.fold_builtin (fndecl, nargs, args, ignore);
12320 : }
12321 : else
12322 : {
12323 6136224 : ret = fold_builtin_n (loc, NULL_TREE, fndecl, args, nargs, ignore);
12324 6136224 : if (ret)
12325 : {
12326 : /* Propagate location information from original call to
12327 : expansion of builtin. Otherwise things like
12328 : maybe_emit_chk_warning, that operate on the expansion
12329 : of a builtin, will use the wrong location information. */
12330 5093 : if (gimple_has_location (stmt))
12331 : {
12332 5092 : tree realret = ret;
12333 5092 : if (TREE_CODE (ret) == NOP_EXPR)
12334 5092 : realret = TREE_OPERAND (ret, 0);
12335 5092 : if (CAN_HAVE_LOCATION_P (realret)
12336 9313 : && !EXPR_HAS_LOCATION (realret))
12337 6 : SET_EXPR_LOCATION (realret, loc);
12338 : return realret;
12339 : }
12340 : return ret;
12341 : }
12342 : }
12343 : }
12344 : return NULL_TREE;
12345 : }
12346 :
12347 : /* Look up the function in builtin_decl that corresponds to DECL
12348 : and set ASMSPEC as its user assembler name. DECL must be a
12349 : function decl that declares a builtin. */
12350 :
12351 : void
12352 156250 : set_builtin_user_assembler_name (tree decl, const char *asmspec)
12353 : {
12354 156250 : gcc_assert (fndecl_built_in_p (decl, BUILT_IN_NORMAL)
12355 : && asmspec != 0);
12356 :
12357 156250 : tree builtin = builtin_decl_explicit (DECL_FUNCTION_CODE (decl));
12358 156250 : set_user_assembler_name (builtin, asmspec);
12359 :
12360 156250 : if (DECL_FUNCTION_CODE (decl) == BUILT_IN_FFS
12361 156250 : && INT_TYPE_SIZE < BITS_PER_WORD)
12362 : {
12363 1 : scalar_int_mode mode = int_mode_for_size (INT_TYPE_SIZE, 0).require ();
12364 1 : set_user_assembler_libfunc ("ffs", asmspec);
12365 1 : set_optab_libfunc (ffs_optab, mode, "ffs");
12366 : }
12367 156250 : }
12368 :
12369 : /* Return true if DECL is a builtin that expands to a constant or similarly
12370 : simple code. */
12371 : bool
12372 32527360 : is_simple_builtin (tree decl)
12373 : {
12374 32527360 : if (decl && fndecl_built_in_p (decl, BUILT_IN_NORMAL))
12375 31207467 : switch (DECL_FUNCTION_CODE (decl))
12376 : {
12377 : /* Builtins that expand to constants. */
12378 : case BUILT_IN_CONSTANT_P:
12379 : case BUILT_IN_EXPECT:
12380 : case BUILT_IN_OBJECT_SIZE:
12381 : case BUILT_IN_UNREACHABLE:
12382 : /* Simple register moves or loads from stack. */
12383 : case BUILT_IN_ASSUME_ALIGNED:
12384 : case BUILT_IN_RETURN_ADDRESS:
12385 : case BUILT_IN_EXTRACT_RETURN_ADDR:
12386 : case BUILT_IN_FROB_RETURN_ADDR:
12387 : case BUILT_IN_RETURN:
12388 : case BUILT_IN_AGGREGATE_INCOMING_ADDRESS:
12389 : case BUILT_IN_FRAME_ADDRESS:
12390 : case BUILT_IN_VA_END:
12391 : case BUILT_IN_STACK_SAVE:
12392 : case BUILT_IN_STACK_RESTORE:
12393 : case BUILT_IN_DWARF_CFA:
12394 : case BUILT_IN_CALL_CODE_ADDRESS:
12395 : case BUILT_IN_CALL_STATIC_CHAIN:
12396 : /* Exception state returns or moves registers around. */
12397 : case BUILT_IN_EH_FILTER:
12398 : case BUILT_IN_EH_POINTER:
12399 : case BUILT_IN_EH_COPY_VALUES:
12400 : return true;
12401 :
12402 28020832 : default:
12403 28020832 : return false;
12404 : }
12405 :
12406 : return false;
12407 : }
12408 :
12409 : /* Return true if DECL is a builtin that is not expensive, i.e., they are
12410 : most probably expanded inline into reasonably simple code. This is a
12411 : superset of is_simple_builtin. */
12412 : bool
12413 19498225 : is_inexpensive_builtin (tree decl)
12414 : {
12415 19498225 : if (!decl)
12416 : return false;
12417 19483714 : else if (DECL_BUILT_IN_CLASS (decl) == BUILT_IN_MD)
12418 : return true;
12419 18137428 : else if (DECL_BUILT_IN_CLASS (decl) == BUILT_IN_NORMAL)
12420 15173254 : switch (DECL_FUNCTION_CODE (decl))
12421 : {
12422 : case BUILT_IN_ABS:
12423 : CASE_BUILT_IN_ALLOCA:
12424 : case BUILT_IN_BSWAP16:
12425 : case BUILT_IN_BSWAP32:
12426 : case BUILT_IN_BSWAP64:
12427 : case BUILT_IN_BSWAP128:
12428 : case BUILT_IN_BITREVERSE8:
12429 : case BUILT_IN_BITREVERSE16:
12430 : case BUILT_IN_BITREVERSE32:
12431 : case BUILT_IN_BITREVERSE64:
12432 : case BUILT_IN_BITREVERSE128:
12433 : case BUILT_IN_CLZ:
12434 : case BUILT_IN_CLZIMAX:
12435 : case BUILT_IN_CLZL:
12436 : case BUILT_IN_CLZLL:
12437 : case BUILT_IN_CTZ:
12438 : case BUILT_IN_CTZIMAX:
12439 : case BUILT_IN_CTZL:
12440 : case BUILT_IN_CTZLL:
12441 : case BUILT_IN_FFS:
12442 : case BUILT_IN_FFSIMAX:
12443 : case BUILT_IN_FFSL:
12444 : case BUILT_IN_FFSLL:
12445 : case BUILT_IN_IMAXABS:
12446 : case BUILT_IN_FINITE:
12447 : case BUILT_IN_FINITEF:
12448 : case BUILT_IN_FINITEL:
12449 : case BUILT_IN_FINITED32:
12450 : case BUILT_IN_FINITED64:
12451 : case BUILT_IN_FINITED128:
12452 : case BUILT_IN_FPCLASSIFY:
12453 : case BUILT_IN_ISFINITE:
12454 : case BUILT_IN_ISINF_SIGN:
12455 : case BUILT_IN_ISINF:
12456 : case BUILT_IN_ISINFF:
12457 : case BUILT_IN_ISINFL:
12458 : case BUILT_IN_ISINFD32:
12459 : case BUILT_IN_ISINFD64:
12460 : case BUILT_IN_ISINFD128:
12461 : case BUILT_IN_ISNAN:
12462 : case BUILT_IN_ISNANF:
12463 : case BUILT_IN_ISNANL:
12464 : case BUILT_IN_ISNAND32:
12465 : case BUILT_IN_ISNAND64:
12466 : case BUILT_IN_ISNAND128:
12467 : case BUILT_IN_ISNORMAL:
12468 : case BUILT_IN_ISGREATER:
12469 : case BUILT_IN_ISGREATEREQUAL:
12470 : case BUILT_IN_ISLESS:
12471 : case BUILT_IN_ISLESSEQUAL:
12472 : case BUILT_IN_ISLESSGREATER:
12473 : case BUILT_IN_ISUNORDERED:
12474 : case BUILT_IN_ISEQSIG:
12475 : case BUILT_IN_VA_ARG_PACK:
12476 : case BUILT_IN_VA_ARG_PACK_LEN:
12477 : case BUILT_IN_VA_COPY:
12478 : case BUILT_IN_TRAP:
12479 : case BUILT_IN_UNREACHABLE_TRAP:
12480 : case BUILT_IN_SAVEREGS:
12481 : case BUILT_IN_POPCOUNTL:
12482 : case BUILT_IN_POPCOUNTLL:
12483 : case BUILT_IN_POPCOUNTIMAX:
12484 : case BUILT_IN_POPCOUNT:
12485 : case BUILT_IN_PARITYL:
12486 : case BUILT_IN_PARITYLL:
12487 : case BUILT_IN_PARITYIMAX:
12488 : case BUILT_IN_PARITY:
12489 : case BUILT_IN_LABS:
12490 : case BUILT_IN_LLABS:
12491 : case BUILT_IN_PREFETCH:
12492 : case BUILT_IN_ACC_ON_DEVICE:
12493 : return true;
12494 :
12495 14515565 : default:
12496 14515565 : return is_simple_builtin (decl);
12497 : }
12498 :
12499 : return false;
12500 : }
12501 :
12502 : /* Return true if T is a constant and the value cast to a target char
12503 : can be represented by a host char.
12504 : Store the casted char constant in *P if so. */
12505 :
12506 : bool
12507 3617 : target_char_cst_p (tree t, char *p)
12508 : {
12509 3617 : if (!tree_fits_uhwi_p (t) || CHAR_TYPE_SIZE != HOST_BITS_PER_CHAR)
12510 : return false;
12511 :
12512 1913 : *p = (char)tree_to_uhwi (t);
12513 1913 : return true;
12514 : }
12515 :
12516 : /* Return true if the builtin DECL is implemented in a standard library.
12517 : Otherwise return false which doesn't guarantee it is not (thus the list
12518 : of handled builtins below may be incomplete). */
12519 :
12520 : bool
12521 42288 : builtin_with_linkage_p (tree decl)
12522 : {
12523 42288 : if (DECL_BUILT_IN_CLASS (decl) == BUILT_IN_NORMAL)
12524 42004 : switch (DECL_FUNCTION_CODE (decl))
12525 : {
12526 1304 : CASE_FLT_FN (BUILT_IN_ACOS):
12527 1304 : CASE_FLT_FN_FLOATN_NX (BUILT_IN_ACOS):
12528 1304 : CASE_FLT_FN (BUILT_IN_ACOSH):
12529 1304 : CASE_FLT_FN_FLOATN_NX (BUILT_IN_ACOSH):
12530 1304 : CASE_FLT_FN (BUILT_IN_ASIN):
12531 1304 : CASE_FLT_FN_FLOATN_NX (BUILT_IN_ASIN):
12532 1304 : CASE_FLT_FN (BUILT_IN_ASINH):
12533 1304 : CASE_FLT_FN_FLOATN_NX (BUILT_IN_ASINH):
12534 1304 : CASE_FLT_FN (BUILT_IN_ATAN):
12535 1304 : CASE_FLT_FN_FLOATN_NX (BUILT_IN_ATAN):
12536 1304 : CASE_FLT_FN (BUILT_IN_ATANH):
12537 1304 : CASE_FLT_FN_FLOATN_NX (BUILT_IN_ATANH):
12538 1304 : CASE_FLT_FN (BUILT_IN_ATAN2):
12539 1304 : CASE_FLT_FN_FLOATN_NX (BUILT_IN_ATAN2):
12540 1304 : CASE_FLT_FN (BUILT_IN_CBRT):
12541 1304 : CASE_FLT_FN_FLOATN_NX (BUILT_IN_CBRT):
12542 1304 : CASE_FLT_FN (BUILT_IN_CEIL):
12543 1304 : CASE_FLT_FN_FLOATN_NX (BUILT_IN_CEIL):
12544 1304 : CASE_FLT_FN (BUILT_IN_COPYSIGN):
12545 1304 : CASE_FLT_FN_FLOATN_NX (BUILT_IN_COPYSIGN):
12546 1304 : CASE_FLT_FN (BUILT_IN_COS):
12547 1304 : CASE_FLT_FN_FLOATN_NX (BUILT_IN_COS):
12548 1304 : CASE_FLT_FN (BUILT_IN_COSH):
12549 1304 : CASE_FLT_FN_FLOATN_NX (BUILT_IN_COSH):
12550 1304 : CASE_FLT_FN (BUILT_IN_ERF):
12551 1304 : CASE_FLT_FN_FLOATN_NX (BUILT_IN_ERF):
12552 1304 : CASE_FLT_FN (BUILT_IN_ERFC):
12553 1304 : CASE_FLT_FN_FLOATN_NX (BUILT_IN_ERFC):
12554 1304 : CASE_FLT_FN (BUILT_IN_EXP):
12555 1304 : CASE_FLT_FN_FLOATN_NX (BUILT_IN_EXP):
12556 1304 : CASE_FLT_FN (BUILT_IN_EXP2):
12557 1304 : CASE_FLT_FN_FLOATN_NX (BUILT_IN_EXP2):
12558 1304 : CASE_FLT_FN (BUILT_IN_EXPM1):
12559 1304 : CASE_FLT_FN_FLOATN_NX (BUILT_IN_EXPM1):
12560 1304 : CASE_FLT_FN (BUILT_IN_FABS):
12561 1304 : CASE_FLT_FN_FLOATN_NX (BUILT_IN_FABS):
12562 1304 : CASE_FLT_FN (BUILT_IN_FDIM):
12563 1304 : CASE_FLT_FN_FLOATN_NX (BUILT_IN_FDIM):
12564 1304 : CASE_FLT_FN (BUILT_IN_FLOOR):
12565 1304 : CASE_FLT_FN_FLOATN_NX (BUILT_IN_FLOOR):
12566 1304 : CASE_FLT_FN (BUILT_IN_FMA):
12567 1304 : CASE_FLT_FN_FLOATN_NX (BUILT_IN_FMA):
12568 1304 : CASE_FLT_FN (BUILT_IN_FMAX):
12569 1304 : CASE_FLT_FN_FLOATN_NX (BUILT_IN_FMAX):
12570 1304 : CASE_FLT_FN (BUILT_IN_FMIN):
12571 1304 : CASE_FLT_FN_FLOATN_NX (BUILT_IN_FMIN):
12572 1304 : CASE_FLT_FN (BUILT_IN_FMOD):
12573 1304 : CASE_FLT_FN_FLOATN_NX (BUILT_IN_FMOD):
12574 1304 : CASE_FLT_FN (BUILT_IN_FREXP):
12575 1304 : CASE_FLT_FN_FLOATN_NX (BUILT_IN_FREXP):
12576 1304 : CASE_FLT_FN (BUILT_IN_HYPOT):
12577 1304 : CASE_FLT_FN_FLOATN_NX (BUILT_IN_HYPOT):
12578 1304 : CASE_FLT_FN (BUILT_IN_ILOGB):
12579 1304 : CASE_FLT_FN_FLOATN_NX (BUILT_IN_ILOGB):
12580 1304 : CASE_FLT_FN (BUILT_IN_LDEXP):
12581 1304 : CASE_FLT_FN_FLOATN_NX (BUILT_IN_LDEXP):
12582 1304 : CASE_FLT_FN (BUILT_IN_LGAMMA):
12583 1304 : CASE_FLT_FN_FLOATN_NX (BUILT_IN_LGAMMA):
12584 1304 : CASE_FLT_FN (BUILT_IN_LLRINT):
12585 1304 : CASE_FLT_FN_FLOATN_NX (BUILT_IN_LLRINT):
12586 1304 : CASE_FLT_FN (BUILT_IN_LLROUND):
12587 1304 : CASE_FLT_FN_FLOATN_NX (BUILT_IN_LLROUND):
12588 1304 : CASE_FLT_FN (BUILT_IN_LOG):
12589 1304 : CASE_FLT_FN_FLOATN_NX (BUILT_IN_LOG):
12590 1304 : CASE_FLT_FN (BUILT_IN_LOG10):
12591 1304 : CASE_FLT_FN_FLOATN_NX (BUILT_IN_LOG10):
12592 1304 : CASE_FLT_FN (BUILT_IN_LOG1P):
12593 1304 : CASE_FLT_FN_FLOATN_NX (BUILT_IN_LOG1P):
12594 1304 : CASE_FLT_FN (BUILT_IN_LOG2):
12595 1304 : CASE_FLT_FN_FLOATN_NX (BUILT_IN_LOG2):
12596 1304 : CASE_FLT_FN (BUILT_IN_LOGB):
12597 1304 : CASE_FLT_FN_FLOATN_NX (BUILT_IN_LOGB):
12598 1304 : CASE_FLT_FN (BUILT_IN_LRINT):
12599 1304 : CASE_FLT_FN_FLOATN_NX (BUILT_IN_LRINT):
12600 1304 : CASE_FLT_FN (BUILT_IN_LROUND):
12601 1304 : CASE_FLT_FN_FLOATN_NX (BUILT_IN_LROUND):
12602 1304 : CASE_FLT_FN (BUILT_IN_MODF):
12603 1304 : CASE_FLT_FN_FLOATN_NX (BUILT_IN_MODF):
12604 1304 : CASE_FLT_FN (BUILT_IN_NAN):
12605 1304 : CASE_FLT_FN_FLOATN_NX (BUILT_IN_NAN):
12606 1304 : CASE_FLT_FN (BUILT_IN_NEARBYINT):
12607 1304 : CASE_FLT_FN_FLOATN_NX (BUILT_IN_NEARBYINT):
12608 1304 : CASE_FLT_FN (BUILT_IN_NEXTAFTER):
12609 1304 : CASE_FLT_FN_FLOATN_NX (BUILT_IN_NEXTAFTER):
12610 1304 : CASE_FLT_FN (BUILT_IN_NEXTTOWARD):
12611 1304 : CASE_FLT_FN (BUILT_IN_POW):
12612 1304 : CASE_FLT_FN_FLOATN_NX (BUILT_IN_POW):
12613 1304 : CASE_FLT_FN (BUILT_IN_REMAINDER):
12614 1304 : CASE_FLT_FN_FLOATN_NX (BUILT_IN_REMAINDER):
12615 1304 : CASE_FLT_FN (BUILT_IN_REMQUO):
12616 1304 : CASE_FLT_FN_FLOATN_NX (BUILT_IN_REMQUO):
12617 1304 : CASE_FLT_FN (BUILT_IN_RINT):
12618 1304 : CASE_FLT_FN_FLOATN_NX (BUILT_IN_RINT):
12619 1304 : CASE_FLT_FN (BUILT_IN_ROUND):
12620 1304 : CASE_FLT_FN_FLOATN_NX (BUILT_IN_ROUND):
12621 1304 : CASE_FLT_FN (BUILT_IN_SCALBLN):
12622 1304 : CASE_FLT_FN_FLOATN_NX (BUILT_IN_SCALBLN):
12623 1304 : CASE_FLT_FN (BUILT_IN_SCALBN):
12624 1304 : CASE_FLT_FN_FLOATN_NX (BUILT_IN_SCALBN):
12625 1304 : CASE_FLT_FN (BUILT_IN_SIN):
12626 1304 : CASE_FLT_FN_FLOATN_NX (BUILT_IN_SIN):
12627 1304 : CASE_FLT_FN (BUILT_IN_SINH):
12628 1304 : CASE_FLT_FN_FLOATN_NX (BUILT_IN_SINH):
12629 1304 : CASE_FLT_FN (BUILT_IN_SINCOS):
12630 1304 : CASE_FLT_FN (BUILT_IN_SQRT):
12631 1304 : CASE_FLT_FN_FLOATN_NX (BUILT_IN_SQRT):
12632 1304 : CASE_FLT_FN (BUILT_IN_TAN):
12633 1304 : CASE_FLT_FN_FLOATN_NX (BUILT_IN_TAN):
12634 1304 : CASE_FLT_FN (BUILT_IN_TANH):
12635 1304 : CASE_FLT_FN_FLOATN_NX (BUILT_IN_TANH):
12636 1304 : CASE_FLT_FN (BUILT_IN_TGAMMA):
12637 1304 : CASE_FLT_FN_FLOATN_NX (BUILT_IN_TGAMMA):
12638 1304 : CASE_FLT_FN (BUILT_IN_TRUNC):
12639 1304 : CASE_FLT_FN_FLOATN_NX (BUILT_IN_TRUNC):
12640 1304 : return true;
12641 :
12642 16 : case BUILT_IN_STPCPY:
12643 16 : case BUILT_IN_STPNCPY:
12644 : /* stpcpy is both referenced in libiberty's pex-win32.c and provided
12645 : by libiberty's stpcpy.c for MinGW targets so we need to return true
12646 : in order to be able to build libiberty in LTO mode for them. */
12647 16 : return true;
12648 :
12649 : default:
12650 : break;
12651 : }
12652 : return false;
12653 : }
12654 :
12655 : /* Return true if OFFRNG is bounded to a subrange of offset values
12656 : valid for the largest possible object. */
12657 :
12658 : bool
12659 501 : access_ref::offset_bounded () const
12660 : {
12661 501 : tree min = TYPE_MIN_VALUE (ptrdiff_type_node);
12662 501 : tree max = TYPE_MAX_VALUE (ptrdiff_type_node);
12663 975 : return wi::to_offset (min) <= offrng[0] && offrng[1] <= wi::to_offset (max);
12664 : }
12665 :
12666 : /* If CALLEE has known side effects, fill in INFO and return true.
12667 : See tree-ssa-structalias.cc:find_func_aliases
12668 : for the list of builtins we might need to handle here. */
12669 :
12670 : attr_fnspec
12671 113397479 : builtin_fnspec (tree callee)
12672 : {
12673 113397479 : built_in_function code = DECL_FUNCTION_CODE (callee);
12674 :
12675 113397479 : switch (code)
12676 : {
12677 : /* All the following functions read memory pointed to by
12678 : their second argument and write memory pointed to by first
12679 : argument.
12680 : strcat/strncat additionally reads memory pointed to by the first
12681 : argument. */
12682 133258 : case BUILT_IN_STRCAT:
12683 133258 : case BUILT_IN_STRCAT_CHK:
12684 133258 : return "1cW 1 ";
12685 42125 : case BUILT_IN_STRNCAT:
12686 42125 : case BUILT_IN_STRNCAT_CHK:
12687 42125 : return "1cW 13";
12688 262952 : case BUILT_IN_STRCPY:
12689 262952 : case BUILT_IN_STRCPY_CHK:
12690 262952 : return "1cO 1 ";
12691 32336 : case BUILT_IN_STPCPY:
12692 32336 : case BUILT_IN_STPCPY_CHK:
12693 32336 : return ".cO 1 ";
12694 19219079 : case BUILT_IN_STRNCPY:
12695 19219079 : case BUILT_IN_MEMCPY:
12696 19219079 : case BUILT_IN_MEMMOVE:
12697 19219079 : case BUILT_IN_TM_MEMCPY:
12698 19219079 : case BUILT_IN_TM_MEMMOVE:
12699 19219079 : case BUILT_IN_STRNCPY_CHK:
12700 19219079 : case BUILT_IN_MEMCPY_CHK:
12701 19219079 : case BUILT_IN_MEMMOVE_CHK:
12702 19219079 : return "1cO313";
12703 143700 : case BUILT_IN_MEMPCPY:
12704 143700 : case BUILT_IN_MEMPCPY_CHK:
12705 143700 : return ".cO313";
12706 58163 : case BUILT_IN_STPNCPY:
12707 58163 : case BUILT_IN_STPNCPY_CHK:
12708 58163 : return ".cO313";
12709 0 : case BUILT_IN_BCOPY:
12710 0 : return ".c23O3";
12711 0 : case BUILT_IN_BZERO:
12712 0 : return ".cO2";
12713 9410513 : case BUILT_IN_MEMCMP:
12714 9410513 : case BUILT_IN_MEMCMP_EQ:
12715 9410513 : case BUILT_IN_BCMP:
12716 9410513 : case BUILT_IN_STRNCMP:
12717 9410513 : case BUILT_IN_STRNCMP_EQ:
12718 9410513 : case BUILT_IN_STRNCASECMP:
12719 9410513 : return ".cR3R3";
12720 :
12721 : /* The following functions read memory pointed to by their
12722 : first argument. */
12723 773 : CASE_BUILT_IN_TM_LOAD (1):
12724 773 : CASE_BUILT_IN_TM_LOAD (2):
12725 773 : CASE_BUILT_IN_TM_LOAD (4):
12726 773 : CASE_BUILT_IN_TM_LOAD (8):
12727 773 : CASE_BUILT_IN_TM_LOAD (FLOAT):
12728 773 : CASE_BUILT_IN_TM_LOAD (DOUBLE):
12729 773 : CASE_BUILT_IN_TM_LOAD (LDOUBLE):
12730 773 : CASE_BUILT_IN_TM_LOAD (M64):
12731 773 : CASE_BUILT_IN_TM_LOAD (M128):
12732 773 : CASE_BUILT_IN_TM_LOAD (M256):
12733 773 : case BUILT_IN_TM_LOG:
12734 773 : case BUILT_IN_TM_LOG_1:
12735 773 : case BUILT_IN_TM_LOG_2:
12736 773 : case BUILT_IN_TM_LOG_4:
12737 773 : case BUILT_IN_TM_LOG_8:
12738 773 : case BUILT_IN_TM_LOG_FLOAT:
12739 773 : case BUILT_IN_TM_LOG_DOUBLE:
12740 773 : case BUILT_IN_TM_LOG_LDOUBLE:
12741 773 : case BUILT_IN_TM_LOG_M64:
12742 773 : case BUILT_IN_TM_LOG_M128:
12743 773 : case BUILT_IN_TM_LOG_M256:
12744 773 : return ".cR ";
12745 :
12746 520612 : case BUILT_IN_INDEX:
12747 520612 : case BUILT_IN_RINDEX:
12748 520612 : case BUILT_IN_STRCHR:
12749 520612 : case BUILT_IN_STRLEN:
12750 520612 : case BUILT_IN_STRRCHR:
12751 520612 : return ".cR ";
12752 56735 : case BUILT_IN_STRNLEN:
12753 56735 : return ".cR2";
12754 :
12755 : /* These read memory pointed to by the first argument.
12756 : Allocating memory does not have any side-effects apart from
12757 : being the definition point for the pointer.
12758 : Unix98 specifies that errno is set on allocation failure. */
12759 18233 : case BUILT_IN_STRDUP:
12760 18233 : return "mCR ";
12761 13308 : case BUILT_IN_STRNDUP:
12762 13308 : return "mCR2";
12763 : /* Allocating memory does not have any side-effects apart from
12764 : being the definition point for the pointer. */
12765 11275359 : case BUILT_IN_MALLOC:
12766 11275359 : case BUILT_IN_ALIGNED_ALLOC:
12767 11275359 : case BUILT_IN_CALLOC:
12768 11275359 : case BUILT_IN_GOMP_ALLOC:
12769 11275359 : return "mC";
12770 845937 : CASE_BUILT_IN_ALLOCA:
12771 845937 : return "mc";
12772 : /* These read memory pointed to by the first argument with size
12773 : in the third argument. */
12774 726691 : case BUILT_IN_MEMCHR:
12775 726691 : return ".cR3";
12776 : /* These read memory pointed to by the first and second arguments. */
12777 11556405 : case BUILT_IN_STRSTR:
12778 11556405 : case BUILT_IN_STRPBRK:
12779 11556405 : case BUILT_IN_STRCASECMP:
12780 11556405 : case BUILT_IN_STRCSPN:
12781 11556405 : case BUILT_IN_STRSPN:
12782 11556405 : case BUILT_IN_STRCMP:
12783 11556405 : case BUILT_IN_STRCMP_EQ:
12784 11556405 : return ".cR R ";
12785 : /* Freeing memory kills the pointed-to memory. More importantly
12786 : the call has to serve as a barrier for moving loads and stores
12787 : across it. */
12788 6531054 : case BUILT_IN_STACK_RESTORE:
12789 6531054 : case BUILT_IN_FREE:
12790 6531054 : case BUILT_IN_GOMP_FREE:
12791 6531054 : return ".co ";
12792 108417 : case BUILT_IN_VA_END:
12793 108417 : return ".cO ";
12794 : /* Realloc serves both as allocation point and deallocation point. */
12795 1079369 : case BUILT_IN_REALLOC:
12796 1079369 : case BUILT_IN_GOMP_REALLOC:
12797 1079369 : return ".Cw ";
12798 15732 : case BUILT_IN_GAMMA_R:
12799 15732 : case BUILT_IN_GAMMAF_R:
12800 15732 : case BUILT_IN_GAMMAL_R:
12801 15732 : case BUILT_IN_LGAMMA_R:
12802 15732 : case BUILT_IN_LGAMMAF_R:
12803 15732 : case BUILT_IN_LGAMMAL_R:
12804 15732 : return ".C. Ot";
12805 43890 : case BUILT_IN_FREXP:
12806 43890 : case BUILT_IN_FREXPF:
12807 43890 : case BUILT_IN_FREXPL:
12808 43890 : case BUILT_IN_MODF:
12809 43890 : case BUILT_IN_MODFF:
12810 43890 : case BUILT_IN_MODFL:
12811 43890 : return ".c. Ot";
12812 7586 : case BUILT_IN_REMQUO:
12813 7586 : case BUILT_IN_REMQUOF:
12814 7586 : case BUILT_IN_REMQUOL:
12815 7586 : return ".c. . Ot";
12816 164 : case BUILT_IN_SINCOS:
12817 164 : case BUILT_IN_SINCOSF:
12818 164 : case BUILT_IN_SINCOSL:
12819 164 : return ".c. OtOt";
12820 4364374 : case BUILT_IN_MEMSET:
12821 4364374 : case BUILT_IN_MEMSET_CHK:
12822 4364374 : case BUILT_IN_TM_MEMSET:
12823 4364374 : return "1cO3";
12824 366 : CASE_BUILT_IN_TM_STORE (1):
12825 366 : CASE_BUILT_IN_TM_STORE (2):
12826 366 : CASE_BUILT_IN_TM_STORE (4):
12827 366 : CASE_BUILT_IN_TM_STORE (8):
12828 366 : CASE_BUILT_IN_TM_STORE (FLOAT):
12829 366 : CASE_BUILT_IN_TM_STORE (DOUBLE):
12830 366 : CASE_BUILT_IN_TM_STORE (LDOUBLE):
12831 366 : CASE_BUILT_IN_TM_STORE (M64):
12832 366 : CASE_BUILT_IN_TM_STORE (M128):
12833 366 : CASE_BUILT_IN_TM_STORE (M256):
12834 366 : return ".cO ";
12835 2443470 : case BUILT_IN_STACK_SAVE:
12836 2443470 : case BUILT_IN_RETURN:
12837 2443470 : case BUILT_IN_EH_POINTER:
12838 2443470 : case BUILT_IN_EH_FILTER:
12839 2443470 : case BUILT_IN_UNWIND_RESUME:
12840 2443470 : case BUILT_IN_CXA_END_CLEANUP:
12841 2443470 : case BUILT_IN_EH_COPY_VALUES:
12842 2443470 : case BUILT_IN_FRAME_ADDRESS:
12843 2443470 : case BUILT_IN_APPLY_ARGS:
12844 2443470 : case BUILT_IN_ASAN_BEFORE_DYNAMIC_INIT:
12845 2443470 : case BUILT_IN_ASAN_AFTER_DYNAMIC_INIT:
12846 2443470 : case BUILT_IN_PREFETCH:
12847 2443470 : case BUILT_IN_DWARF_CFA:
12848 2443470 : case BUILT_IN_RETURN_ADDRESS:
12849 2443470 : return ".c";
12850 2193592 : case BUILT_IN_ASSUME_ALIGNED:
12851 2193592 : case BUILT_IN_EXPECT:
12852 2193592 : case BUILT_IN_EXPECT_WITH_PROBABILITY:
12853 2193592 : return "1cX ";
12854 : /* But posix_memalign stores a pointer into the memory pointed to
12855 : by its first argument. */
12856 5776 : case BUILT_IN_POSIX_MEMALIGN:
12857 5776 : return ".cOt";
12858 4438 : case BUILT_IN_OMP_GET_MAPPED_PTR:
12859 4438 : return ". R ";
12860 :
12861 42283072 : default:
12862 42283072 : return "";
12863 : }
12864 : }
|