1/* Conditional Dead Call Elimination pass for the GNU compiler.
2 Copyright (C) 2008-2024 Free Software Foundation, Inc.
3 Contributed by Xinliang David Li <davidxl@google.com>
4
5This file is part of GCC.
6
7GCC is free software; you can redistribute it and/or modify it
8under the terms of the GNU General Public License as published by the
9Free Software Foundation; either version 3, or (at your option) any
10later version.
11
12GCC is distributed in the hope that it will be useful, but WITHOUT
13ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
14FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
15for more details.
16
17You should have received a copy of the GNU General Public License
18along with GCC; see the file COPYING3. If not see
19<http://www.gnu.org/licenses/>. */
20
21#include "config.h"
22#include "system.h"
23#include "coretypes.h"
24#include "backend.h"
25#include "tree.h"
26#include "gimple.h"
27#include "cfghooks.h"
28#include "tree-pass.h"
29#include "ssa.h"
30#include "gimple-pretty-print.h"
31#include "fold-const.h"
32#include "stor-layout.h"
33#include "gimple-iterator.h"
34#include "tree-cfg.h"
35#include "tree-into-ssa.h"
36#include "builtins.h"
37#include "internal-fn.h"
38#include "tree-dfa.h"
39
40
41/* This pass serves two closely-related purposes:
42
43 1. It conditionally executes calls that set errno if (a) the result of
44 the call is unused and (b) a simple range check on the arguments can
45 detect most cases where errno does not need to be set.
46
47 This is the "conditional dead-code elimination" that gave the pass
48 its original name, since the call is dead for most argument values.
49 The calls for which it helps are usually part of the C++ abstraction
50 penalty exposed after inlining.
51
52 2. It looks for calls to built-in functions that set errno and whose
53 result is used. It checks whether there is an associated internal
54 function that doesn't set errno and whether the target supports
55 that internal function. If so, the pass uses the internal function
56 to compute the result of the built-in function but still arranges
57 for errno to be set when necessary. There are two ways of setting
58 errno:
59
60 a. by protecting the original call with the same argument checks as (1)
61
62 b. by protecting the original call with a check that the result
63 of the internal function is not equal to itself (i.e. is NaN).
64
65 (b) requires that NaNs are the only erroneous results. It is not
66 appropriate for functions like log, which returns ERANGE for zero
67 arguments. (b) is also likely to perform worse than (a) because it
68 requires the result to be calculated first. The pass therefore uses
69 (a) when it can and uses (b) as a fallback.
70
71 For (b) the pass can replace the original call with a call to
72 IFN_SET_EDOM, if the target supports direct assignments to errno.
73
74 In both cases, arguments that require errno to be set should occur
75 rarely in practice. Checks of the errno result should also be rare,
76 but the compiler would need powerful interprocedural analysis to
77 prove that errno is not checked. It's much easier to add argument
78 checks or result checks instead.
79
80 An example of (1) is:
81
82 log (x); // Mostly dead call
83 ==>
84 if (__builtin_islessequal (x, 0))
85 log (x);
86
87 With this change, call to log (x) is effectively eliminated, as
88 in the majority of the cases, log won't be called with x out of
89 range. The branch is totally predictable, so the branch cost
90 is low.
91
92 An example of (2) is:
93
94 y = sqrt (x);
95 ==>
96 if (__builtin_isless (x, 0))
97 y = sqrt (x);
98 else
99 y = IFN_SQRT (x);
100 In the vast majority of cases we should then never need to call sqrt.
101
102 Note that library functions are not supposed to clear errno to zero without
103 error. See IEEE Std 1003.1, section 2.3 Error Numbers, and section 7.5:3 of
104 ISO/IEC 9899 (C99).
105
106 The condition wrapping the builtin call is conservatively set to avoid too
107 aggressive (wrong) shrink wrapping. */
108
109
110/* A structure for representing input domain of
111 a function argument in integer. If the lower
112 bound is -inf, has_lb is set to false. If the
113 upper bound is +inf, has_ub is false.
114 is_lb_inclusive and is_ub_inclusive are flags
115 to indicate if lb and ub value are inclusive
116 respectively. */
117
118struct inp_domain
119{
120 int lb;
121 int ub;
122 bool has_lb;
123 bool has_ub;
124 bool is_lb_inclusive;
125 bool is_ub_inclusive;
126};
127
128/* A helper function to construct and return an input
129 domain object. LB is the lower bound, HAS_LB is
130 a boolean flag indicating if the lower bound exists,
131 and LB_INCLUSIVE is a boolean flag indicating if the
132 lower bound is inclusive or not. UB, HAS_UB, and
133 UB_INCLUSIVE have the same meaning, but for upper
134 bound of the domain. */
135
136static inp_domain
137get_domain (int lb, bool has_lb, bool lb_inclusive,
138 int ub, bool has_ub, bool ub_inclusive)
139{
140 inp_domain domain;
141 domain.lb = lb;
142 domain.has_lb = has_lb;
143 domain.is_lb_inclusive = lb_inclusive;
144 domain.ub = ub;
145 domain.has_ub = has_ub;
146 domain.is_ub_inclusive = ub_inclusive;
147 return domain;
148}
149
150/* A helper function to check the target format for the
151 argument type. In this implementation, only IEEE formats
152 are supported. ARG is the call argument to be checked.
153 Returns true if the format is supported. To support other
154 target formats, function get_no_error_domain needs to be
155 enhanced to have range bounds properly computed. Since
156 the check is cheap (very small number of candidates
157 to be checked), the result is not cached for each float type. */
158
159static bool
160check_target_format (tree arg)
161{
162 tree type;
163 machine_mode mode;
164 const struct real_format *rfmt;
165
166 type = TREE_TYPE (arg);
167 mode = TYPE_MODE (type);
168 rfmt = REAL_MODE_FORMAT (mode);
169 if ((mode == SFmode
170 && (rfmt == &ieee_single_format || rfmt == &mips_single_format
171 || rfmt == &motorola_single_format))
172 || (mode == DFmode
173 && (rfmt == &ieee_double_format || rfmt == &mips_double_format
174 || rfmt == &motorola_double_format))
175 /* For long double, we cannot really check XFmode
176 which is only defined on intel platforms.
177 Candidate pre-selection using builtin function
178 code guarantees that we are checking formats
179 for long double modes: double, quad, and extended. */
180 || (mode != SFmode && mode != DFmode
181 && (rfmt == &ieee_quad_format
182 || rfmt == &mips_quad_format
183 || rfmt == &ieee_extended_motorola_format
184 || rfmt == &ieee_extended_intel_96_format
185 || rfmt == &ieee_extended_intel_128_format
186 || rfmt == &ieee_extended_intel_96_round_53_format)))
187 return true;
188
189 return false;
190}
191
192
193/* A helper function to help select calls to pow that are suitable for
194 conditional DCE transformation. It looks for pow calls that can be
195 guided with simple conditions. Such calls either have constant base
196 values or base values converted from integers. Returns true if
197 the pow call POW_CALL is a candidate. */
198
199/* The maximum integer bit size for base argument of a pow call
200 that is suitable for shrink-wrapping transformation. */
201#define MAX_BASE_INT_BIT_SIZE 32
202
203static bool
204check_pow (gcall *pow_call)
205{
206 tree base, expn;
207 enum tree_code bc, ec;
208
209 if (gimple_call_num_args (gs: pow_call) != 2)
210 return false;
211
212 base = gimple_call_arg (gs: pow_call, index: 0);
213 expn = gimple_call_arg (gs: pow_call, index: 1);
214
215 if (!check_target_format (arg: expn))
216 return false;
217
218 bc = TREE_CODE (base);
219 ec = TREE_CODE (expn);
220
221 /* Folding candidates are not interesting.
222 Can actually assert that it is already folded. */
223 if (ec == REAL_CST && bc == REAL_CST)
224 return false;
225
226 if (bc == REAL_CST)
227 {
228 /* Only handle a fixed range of constant. */
229 REAL_VALUE_TYPE mv;
230 REAL_VALUE_TYPE bcv = TREE_REAL_CST (base);
231 if (real_equal (&bcv, &dconst1))
232 return false;
233 if (real_less (&bcv, &dconst1))
234 return false;
235 real_from_integer (&mv, TYPE_MODE (TREE_TYPE (base)), 256, UNSIGNED);
236 if (real_less (&mv, &bcv))
237 return false;
238 return true;
239 }
240 else if (bc == SSA_NAME)
241 {
242 tree base_val0, type;
243 gimple *base_def;
244 int bit_sz;
245
246 /* Only handles cases where base value is converted
247 from integer values. */
248 base_def = SSA_NAME_DEF_STMT (base);
249 if (gimple_code (g: base_def) != GIMPLE_ASSIGN)
250 return false;
251
252 if (gimple_assign_rhs_code (gs: base_def) != FLOAT_EXPR)
253 return false;
254 base_val0 = gimple_assign_rhs1 (gs: base_def);
255
256 type = TREE_TYPE (base_val0);
257 if (TREE_CODE (type) != INTEGER_TYPE)
258 return false;
259 bit_sz = TYPE_PRECISION (type);
260 /* If the type of the base is too wide,
261 the resulting shrink wrapping condition
262 will be too conservative. */
263 if (bit_sz > MAX_BASE_INT_BIT_SIZE)
264 return false;
265
266 return true;
267 }
268 else
269 return false;
270}
271
272/* A helper function to help select candidate function calls that are
273 suitable for conditional DCE. Candidate functions must have single
274 valid input domain in this implementation except for pow (see check_pow).
275 Returns true if the function call is a candidate. */
276
277static bool
278check_builtin_call (gcall *bcall)
279{
280 tree arg;
281
282 arg = gimple_call_arg (gs: bcall, index: 0);
283 return check_target_format (arg);
284}
285
286/* Return true if built-in function call CALL calls a math function
287 and if we know how to test the range of its arguments to detect _most_
288 situations in which errno is not set. The test must err on the side
289 of treating non-erroneous values as potentially erroneous. */
290
291static bool
292can_test_argument_range (gcall *call)
293{
294 switch (DECL_FUNCTION_CODE (decl: gimple_call_fndecl (gs: call)))
295 {
296 /* Trig functions. */
297 CASE_FLT_FN (BUILT_IN_ACOS):
298 CASE_FLT_FN_FLOATN_NX (BUILT_IN_ACOS):
299 CASE_FLT_FN (BUILT_IN_ASIN):
300 CASE_FLT_FN_FLOATN_NX (BUILT_IN_ASIN):
301 /* Hyperbolic functions. */
302 CASE_FLT_FN (BUILT_IN_ACOSH):
303 CASE_FLT_FN_FLOATN_NX (BUILT_IN_ACOSH):
304 CASE_FLT_FN (BUILT_IN_ATANH):
305 CASE_FLT_FN_FLOATN_NX (BUILT_IN_ATANH):
306 CASE_FLT_FN (BUILT_IN_COSH):
307 CASE_FLT_FN_FLOATN_NX (BUILT_IN_COSH):
308 CASE_FLT_FN (BUILT_IN_SINH):
309 CASE_FLT_FN_FLOATN_NX (BUILT_IN_SINH):
310 /* Log functions. */
311 CASE_FLT_FN (BUILT_IN_LOG):
312 CASE_FLT_FN_FLOATN_NX (BUILT_IN_LOG):
313 CASE_FLT_FN (BUILT_IN_LOG2):
314 CASE_FLT_FN_FLOATN_NX (BUILT_IN_LOG2):
315 CASE_FLT_FN (BUILT_IN_LOG10):
316 CASE_FLT_FN_FLOATN_NX (BUILT_IN_LOG10):
317 CASE_FLT_FN (BUILT_IN_LOG1P):
318 CASE_FLT_FN_FLOATN_NX (BUILT_IN_LOG1P):
319 /* Exp functions. */
320 CASE_FLT_FN (BUILT_IN_EXP):
321 CASE_FLT_FN_FLOATN_NX (BUILT_IN_EXP):
322 CASE_FLT_FN (BUILT_IN_EXP2):
323 CASE_FLT_FN_FLOATN_NX (BUILT_IN_EXP2):
324 CASE_FLT_FN (BUILT_IN_EXP10):
325 CASE_FLT_FN (BUILT_IN_EXPM1):
326 CASE_FLT_FN_FLOATN_NX (BUILT_IN_EXPM1):
327 CASE_FLT_FN (BUILT_IN_POW10):
328 /* Sqrt. */
329 CASE_FLT_FN (BUILT_IN_SQRT):
330 CASE_FLT_FN_FLOATN_NX (BUILT_IN_SQRT):
331 return check_builtin_call (bcall: call);
332 /* Special one: two argument pow. */
333 case BUILT_IN_POW:
334 return check_pow (pow_call: call);
335 default:
336 break;
337 }
338
339 return false;
340}
341
342/* Return true if CALL can produce a domain error (EDOM) but can never
343 produce a pole, range overflow or range underflow error (all ERANGE).
344 This means that we can tell whether a function would have set errno
345 by testing whether the result is a NaN. */
346
347static bool
348edom_only_function (gcall *call)
349{
350 switch (DECL_FUNCTION_CODE (decl: gimple_call_fndecl (gs: call)))
351 {
352 CASE_FLT_FN (BUILT_IN_ACOS):
353 CASE_FLT_FN_FLOATN_NX (BUILT_IN_ACOS):
354 CASE_FLT_FN (BUILT_IN_ASIN):
355 CASE_FLT_FN_FLOATN_NX (BUILT_IN_ASIN):
356 CASE_FLT_FN (BUILT_IN_ATAN):
357 CASE_FLT_FN_FLOATN_NX (BUILT_IN_ATAN):
358 CASE_FLT_FN (BUILT_IN_COS):
359 CASE_FLT_FN_FLOATN_NX (BUILT_IN_COS):
360 CASE_FLT_FN (BUILT_IN_SIGNIFICAND):
361 CASE_FLT_FN (BUILT_IN_SIN):
362 CASE_FLT_FN_FLOATN_NX (BUILT_IN_SIN):
363 CASE_FLT_FN (BUILT_IN_SQRT):
364 CASE_FLT_FN_FLOATN_NX (BUILT_IN_SQRT):
365 CASE_FLT_FN (BUILT_IN_FMOD):
366 CASE_FLT_FN_FLOATN_NX (BUILT_IN_FMOD):
367 CASE_FLT_FN (BUILT_IN_REMAINDER):
368 CASE_FLT_FN_FLOATN_NX (BUILT_IN_REMAINDER):
369 return true;
370
371 default:
372 return false;
373 }
374}
375
376/* Return true if it is structurally possible to guard CALL. */
377
378static bool
379can_guard_call_p (gimple *call)
380{
381 return (!stmt_ends_bb_p (call)
382 || find_fallthru_edge (edges: gimple_bb (g: call)->succs));
383}
384
385/* For a comparison code return the comparison code we should use if we don't
386 HONOR_NANS. */
387
388static enum tree_code
389comparison_code_if_no_nans (tree_code code)
390{
391 switch (code)
392 {
393 case UNLT_EXPR:
394 return LT_EXPR;
395 case UNGT_EXPR:
396 return GT_EXPR;
397 case UNLE_EXPR:
398 return LE_EXPR;
399 case UNGE_EXPR:
400 return GE_EXPR;
401 case UNEQ_EXPR:
402 return EQ_EXPR;
403 case LTGT_EXPR:
404 return NE_EXPR;
405
406 case LT_EXPR:
407 case GT_EXPR:
408 case LE_EXPR:
409 case GE_EXPR:
410 case EQ_EXPR:
411 case NE_EXPR:
412 return code;
413
414 default:
415 gcc_unreachable ();
416 }
417}
418
419/* A helper function to generate gimple statements for one bound
420 comparison, so that the built-in function is called whenever
421 TCODE <ARG, LBUB> is *false*. TEMP_NAME1/TEMP_NAME2 are names
422 of the temporaries, CONDS is a vector holding the produced GIMPLE
423 statements, and NCONDS points to the variable holding the number of
424 logical comparisons. CONDS is either empty or a list ended with a
425 null tree. */
426
427static void
428gen_one_condition (tree arg, int lbub,
429 enum tree_code tcode,
430 const char *temp_name1,
431 const char *temp_name2,
432 vec<gimple *> conds,
433 unsigned *nconds)
434{
435 if (!HONOR_NANS (arg))
436 tcode = comparison_code_if_no_nans (code: tcode);
437
438 tree lbub_real_cst, lbub_cst, float_type;
439 tree temp, tempn, tempc, tempcn;
440 gassign *stmt1;
441 gassign *stmt2;
442 gcond *stmt3;
443
444 float_type = TREE_TYPE (arg);
445 lbub_cst = build_int_cst (integer_type_node, lbub);
446 lbub_real_cst = build_real_from_int_cst (float_type, lbub_cst);
447
448 temp = create_tmp_var (float_type, temp_name1);
449 stmt1 = gimple_build_assign (temp, arg);
450 tempn = make_ssa_name (var: temp, stmt: stmt1);
451 gimple_assign_set_lhs (gs: stmt1, lhs: tempn);
452
453 tempc = create_tmp_var (boolean_type_node, temp_name2);
454 stmt2 = gimple_build_assign (tempc,
455 fold_build2 (tcode,
456 boolean_type_node,
457 tempn, lbub_real_cst));
458 tempcn = make_ssa_name (var: tempc, stmt: stmt2);
459 gimple_assign_set_lhs (gs: stmt2, lhs: tempcn);
460
461 stmt3 = gimple_build_cond_from_tree (tempcn, NULL_TREE, NULL_TREE);
462 conds.quick_push (obj: stmt1);
463 conds.quick_push (obj: stmt2);
464 conds.quick_push (obj: stmt3);
465 (*nconds)++;
466}
467
468/* A helper function to generate GIMPLE statements for
469 out of input domain check. ARG is the call argument
470 to be runtime checked, DOMAIN holds the valid domain
471 for the given function, CONDS points to the vector
472 holding the result GIMPLE statements. *NCONDS is
473 the number of logical comparisons. This function
474 produces no more than two logical comparisons, one
475 for lower bound check, one for upper bound check. */
476
477static void
478gen_conditions_for_domain (tree arg, inp_domain domain,
479 vec<gimple *> conds,
480 unsigned *nconds)
481{
482 if (domain.has_lb)
483 gen_one_condition (arg, lbub: domain.lb,
484 tcode: (domain.is_lb_inclusive
485 ? UNGE_EXPR : UNGT_EXPR),
486 temp_name1: "DCE_COND_LB", temp_name2: "DCE_COND_LB_TEST",
487 conds, nconds);
488
489 if (domain.has_ub)
490 {
491 /* Now push a separator. */
492 if (domain.has_lb)
493 conds.quick_push (NULL);
494
495 gen_one_condition (arg, lbub: domain.ub,
496 tcode: (domain.is_ub_inclusive
497 ? UNLE_EXPR : UNLT_EXPR),
498 temp_name1: "DCE_COND_UB", temp_name2: "DCE_COND_UB_TEST",
499 conds, nconds);
500 }
501}
502
503
504/* A helper function to generate condition
505 code for the y argument in call pow (some_const, y).
506 See candidate selection in check_pow. Since the
507 candidates' base values have a limited range,
508 the guarded code generated for y are simple:
509 if (__builtin_isgreater (y, max_y))
510 pow (const, y);
511 Note max_y can be computed separately for each
512 const base, but in this implementation, we
513 choose to compute it using the max base
514 in the allowed range for the purpose of
515 simplicity. BASE is the constant base value,
516 EXPN is the expression for the exponent argument,
517 *CONDS is the vector to hold resulting statements,
518 and *NCONDS is the number of logical conditions. */
519
520static void
521gen_conditions_for_pow_cst_base (tree base, tree expn,
522 vec<gimple *> conds,
523 unsigned *nconds)
524{
525 inp_domain exp_domain;
526 /* Validate the range of the base constant to make
527 sure it is consistent with check_pow. */
528 REAL_VALUE_TYPE mv;
529 REAL_VALUE_TYPE bcv = TREE_REAL_CST (base);
530 gcc_assert (!real_equal (&bcv, &dconst1)
531 && !real_less (&bcv, &dconst1));
532 real_from_integer (&mv, TYPE_MODE (TREE_TYPE (base)), 256, UNSIGNED);
533 gcc_assert (!real_less (&mv, &bcv));
534
535 exp_domain = get_domain (lb: 0, has_lb: false, lb_inclusive: false,
536 ub: 127, has_ub: true, ub_inclusive: false);
537
538 gen_conditions_for_domain (arg: expn, domain: exp_domain,
539 conds, nconds);
540}
541
542/* Generate error condition code for pow calls with
543 non constant base values. The candidates selected
544 have their base argument value converted from
545 integer (see check_pow) value (1, 2, 4 bytes), and
546 the max exp value is computed based on the size
547 of the integer type (i.e. max possible base value).
548 The resulting input domain for exp argument is thus
549 conservative (smaller than the max value allowed by
550 the runtime value of the base). BASE is the integer
551 base value, EXPN is the expression for the exponent
552 argument, *CONDS is the vector to hold resulting
553 statements, and *NCONDS is the number of logical
554 conditions. */
555
556static void
557gen_conditions_for_pow_int_base (tree base, tree expn,
558 vec<gimple *> conds,
559 unsigned *nconds)
560{
561 gimple *base_def;
562 tree base_val0;
563 tree int_type;
564 tree temp, tempn;
565 tree cst0;
566 gimple *stmt1, *stmt2;
567 int bit_sz, max_exp;
568 inp_domain exp_domain;
569
570 base_def = SSA_NAME_DEF_STMT (base);
571 base_val0 = gimple_assign_rhs1 (gs: base_def);
572 int_type = TREE_TYPE (base_val0);
573 bit_sz = TYPE_PRECISION (int_type);
574 gcc_assert (bit_sz > 0
575 && bit_sz <= MAX_BASE_INT_BIT_SIZE);
576
577 /* Determine the max exp argument value according to
578 the size of the base integer. The max exp value
579 is conservatively estimated assuming IEEE754 double
580 precision format. */
581 if (bit_sz == 8)
582 max_exp = 128;
583 else if (bit_sz == 16)
584 max_exp = 64;
585 else
586 {
587 gcc_assert (bit_sz == MAX_BASE_INT_BIT_SIZE);
588 max_exp = 32;
589 }
590
591 /* For pow ((double)x, y), generate the following conditions:
592 cond 1:
593 temp1 = x;
594 if (__builtin_islessequal (temp1, 0))
595
596 cond 2:
597 temp2 = y;
598 if (__builtin_isgreater (temp2, max_exp_real_cst)) */
599
600 /* Generate condition in reverse order -- first
601 the condition for the exp argument. */
602
603 exp_domain = get_domain (lb: 0, has_lb: false, lb_inclusive: false,
604 ub: max_exp, has_ub: true, ub_inclusive: true);
605
606 gen_conditions_for_domain (arg: expn, domain: exp_domain,
607 conds, nconds);
608
609 /* Now generate condition for the base argument.
610 Note it does not use the helper function
611 gen_conditions_for_domain because the base
612 type is integer. */
613
614 /* Push a separator. */
615 conds.quick_push (NULL);
616
617 temp = create_tmp_var (int_type, "DCE_COND1");
618 cst0 = build_int_cst (int_type, 0);
619 stmt1 = gimple_build_assign (temp, base_val0);
620 tempn = make_ssa_name (var: temp, stmt: stmt1);
621 gimple_assign_set_lhs (gs: stmt1, lhs: tempn);
622 stmt2 = gimple_build_cond (GT_EXPR, tempn, cst0, NULL_TREE, NULL_TREE);
623
624 conds.quick_push (obj: stmt1);
625 conds.quick_push (obj: stmt2);
626 (*nconds)++;
627}
628
629/* Method to generate conditional statements for guarding conditionally
630 dead calls to pow. One or more statements can be generated for
631 each logical condition. Statement groups of different conditions
632 are separated by a NULL tree and they are stored in the vec
633 conds. The number of logical conditions are stored in *nconds.
634
635 See C99 standard, 7.12.7.4:2, for description of pow (x, y).
636 The precise condition for domain errors are complex. In this
637 implementation, a simplified (but conservative) valid domain
638 for x and y are used: x is positive to avoid dom errors, while
639 y is smaller than a upper bound (depending on x) to avoid range
640 errors. Runtime code is generated to check x (if not constant)
641 and y against the valid domain. If it is out, jump to the call,
642 otherwise the call is bypassed. POW_CALL is the call statement,
643 *CONDS is a vector holding the resulting condition statements,
644 and *NCONDS is the number of logical conditions. */
645
646static void
647gen_conditions_for_pow (gcall *pow_call, vec<gimple *> conds,
648 unsigned *nconds)
649{
650 tree base, expn;
651 enum tree_code bc;
652
653 gcc_checking_assert (check_pow (pow_call));
654
655 *nconds = 0;
656
657 base = gimple_call_arg (gs: pow_call, index: 0);
658 expn = gimple_call_arg (gs: pow_call, index: 1);
659
660 bc = TREE_CODE (base);
661
662 if (bc == REAL_CST)
663 gen_conditions_for_pow_cst_base (base, expn, conds, nconds);
664 else if (bc == SSA_NAME)
665 gen_conditions_for_pow_int_base (base, expn, conds, nconds);
666 else
667 gcc_unreachable ();
668}
669
670/* A helper routine to help computing the valid input domain
671 for a builtin function. See C99 7.12.7 for details. In this
672 implementation, we only handle single region domain. The
673 resulting region can be conservative (smaller) than the actual
674 one and rounded to integers. Some of the bounds are documented
675 in the standard, while other limit constants are computed
676 assuming IEEE floating point format (for SF and DF modes).
677 Since IEEE only sets minimum requirements for long double format,
678 different long double formats exist under different implementations
679 (e.g, 64 bit double precision (DF), 80 bit double-extended
680 precision (XF), and 128 bit quad precision (TF) ). For simplicity,
681 in this implementation, the computed bounds for long double assume
682 64 bit format (DF) except when it is IEEE quad or extended with the same
683 emax, and are therefore sometimes conservative. Another assumption is
684 that single precision float type is always SF mode, and double type is DF
685 mode. This function is quite implementation specific, so it may not be
686 suitable to be part of builtins.cc. This needs to be revisited later
687 to see if it can be leveraged in x87 assembly expansion. */
688
689static inp_domain
690get_no_error_domain (enum built_in_function fnc)
691{
692 switch (fnc)
693 {
694 /* Trig functions: return [-1, +1] */
695 CASE_FLT_FN (BUILT_IN_ACOS):
696 CASE_FLT_FN_FLOATN_NX (BUILT_IN_ACOS):
697 CASE_FLT_FN (BUILT_IN_ASIN):
698 CASE_FLT_FN_FLOATN_NX (BUILT_IN_ASIN):
699 return get_domain (lb: -1, has_lb: true, lb_inclusive: true,
700 ub: 1, has_ub: true, ub_inclusive: true);
701 /* Hyperbolic functions. */
702 CASE_FLT_FN (BUILT_IN_ACOSH):
703 CASE_FLT_FN_FLOATN_NX (BUILT_IN_ACOSH):
704 /* acosh: [1, +inf) */
705 return get_domain (lb: 1, has_lb: true, lb_inclusive: true,
706 ub: 1, has_ub: false, ub_inclusive: false);
707 CASE_FLT_FN (BUILT_IN_ATANH):
708 CASE_FLT_FN_FLOATN_NX (BUILT_IN_ATANH):
709 /* atanh: (-1, +1) */
710 return get_domain (lb: -1, has_lb: true, lb_inclusive: false,
711 ub: 1, has_ub: true, ub_inclusive: false);
712 case BUILT_IN_COSHF16:
713 case BUILT_IN_SINHF16:
714 /* coshf16: (-11, +11) */
715 return get_domain (lb: -11, has_lb: true, lb_inclusive: false,
716 ub: 11, has_ub: true, ub_inclusive: false);
717 case BUILT_IN_COSHF:
718 case BUILT_IN_SINHF:
719 case BUILT_IN_COSHF32:
720 case BUILT_IN_SINHF32:
721 /* coshf: (-89, +89) */
722 return get_domain (lb: -89, has_lb: true, lb_inclusive: false,
723 ub: 89, has_ub: true, ub_inclusive: false);
724 case BUILT_IN_COSH:
725 case BUILT_IN_SINH:
726 case BUILT_IN_COSHF64:
727 case BUILT_IN_SINHF64:
728 case BUILT_IN_COSHF32X:
729 case BUILT_IN_SINHF32X:
730 /* cosh: (-710, +710) */
731 return get_domain (lb: -710, has_lb: true, lb_inclusive: false,
732 ub: 710, has_ub: true, ub_inclusive: false);
733 case BUILT_IN_COSHF128:
734 case BUILT_IN_SINHF128:
735 /* coshf128: (-11357, +11357) */
736 return get_domain (lb: -11357, has_lb: true, lb_inclusive: false,
737 ub: 11357, has_ub: true, ub_inclusive: false);
738 case BUILT_IN_COSHL:
739 case BUILT_IN_SINHL:
740 if (REAL_MODE_FORMAT (TYPE_MODE (long_double_type_node))->emax == 16384)
741 return get_no_error_domain (fnc: BUILT_IN_COSHF128);
742 return get_no_error_domain (fnc: BUILT_IN_COSH);
743 case BUILT_IN_COSHF64X:
744 case BUILT_IN_SINHF64X:
745 if (REAL_MODE_FORMAT (TYPE_MODE (float64x_type_node))->emax == 16384)
746 return get_no_error_domain (fnc: BUILT_IN_COSHF128);
747 return get_no_error_domain (fnc: BUILT_IN_COSH);
748 /* Log functions: (0, +inf) */
749 CASE_FLT_FN (BUILT_IN_LOG):
750 CASE_FLT_FN_FLOATN_NX (BUILT_IN_LOG):
751 CASE_FLT_FN (BUILT_IN_LOG2):
752 CASE_FLT_FN_FLOATN_NX (BUILT_IN_LOG2):
753 CASE_FLT_FN (BUILT_IN_LOG10):
754 CASE_FLT_FN_FLOATN_NX (BUILT_IN_LOG10):
755 return get_domain (lb: 0, has_lb: true, lb_inclusive: false,
756 ub: 0, has_ub: false, ub_inclusive: false);
757 CASE_FLT_FN (BUILT_IN_LOG1P):
758 CASE_FLT_FN_FLOATN_NX (BUILT_IN_LOG1P):
759 return get_domain (lb: -1, has_lb: true, lb_inclusive: false,
760 ub: 0, has_ub: false, ub_inclusive: false);
761 /* Exp functions. */
762 case BUILT_IN_EXPF16:
763 case BUILT_IN_EXPM1F16:
764 /* expf16: (-inf, 11) */
765 return get_domain (lb: -1, has_lb: false, lb_inclusive: false,
766 ub: 11, has_ub: true, ub_inclusive: false);
767 case BUILT_IN_EXPF:
768 case BUILT_IN_EXPM1F:
769 case BUILT_IN_EXPF32:
770 case BUILT_IN_EXPM1F32:
771 /* expf: (-inf, 88) */
772 return get_domain (lb: -1, has_lb: false, lb_inclusive: false,
773 ub: 88, has_ub: true, ub_inclusive: false);
774 case BUILT_IN_EXP:
775 case BUILT_IN_EXPM1:
776 case BUILT_IN_EXPF64:
777 case BUILT_IN_EXPM1F64:
778 case BUILT_IN_EXPF32X:
779 case BUILT_IN_EXPM1F32X:
780 /* exp: (-inf, 709) */
781 return get_domain (lb: -1, has_lb: false, lb_inclusive: false,
782 ub: 709, has_ub: true, ub_inclusive: false);
783 case BUILT_IN_EXPF128:
784 case BUILT_IN_EXPM1F128:
785 /* expf128: (-inf, 11356) */
786 return get_domain (lb: -1, has_lb: false, lb_inclusive: false,
787 ub: 11356, has_ub: true, ub_inclusive: false);
788 case BUILT_IN_EXPL:
789 case BUILT_IN_EXPM1L:
790 if (REAL_MODE_FORMAT (TYPE_MODE (long_double_type_node))->emax == 16384)
791 return get_no_error_domain (fnc: BUILT_IN_EXPF128);
792 return get_no_error_domain (fnc: BUILT_IN_EXP);
793 case BUILT_IN_EXPF64X:
794 case BUILT_IN_EXPM1F64X:
795 if (REAL_MODE_FORMAT (TYPE_MODE (float64x_type_node))->emax == 16384)
796 return get_no_error_domain (fnc: BUILT_IN_EXPF128);
797 return get_no_error_domain (fnc: BUILT_IN_EXP);
798 case BUILT_IN_EXP2F16:
799 /* exp2f16: (-inf, 16) */
800 return get_domain (lb: -1, has_lb: false, lb_inclusive: false,
801 ub: 16, has_ub: true, ub_inclusive: false);
802 case BUILT_IN_EXP2F:
803 case BUILT_IN_EXP2F32:
804 /* exp2f: (-inf, 128) */
805 return get_domain (lb: -1, has_lb: false, lb_inclusive: false,
806 ub: 128, has_ub: true, ub_inclusive: false);
807 case BUILT_IN_EXP2:
808 case BUILT_IN_EXP2F64:
809 case BUILT_IN_EXP2F32X:
810 /* exp2: (-inf, 1024) */
811 return get_domain (lb: -1, has_lb: false, lb_inclusive: false,
812 ub: 1024, has_ub: true, ub_inclusive: false);
813 case BUILT_IN_EXP2F128:
814 /* exp2f128: (-inf, 16384) */
815 return get_domain (lb: -1, has_lb: false, lb_inclusive: false,
816 ub: 16384, has_ub: true, ub_inclusive: false);
817 case BUILT_IN_EXP2L:
818 if (REAL_MODE_FORMAT (TYPE_MODE (long_double_type_node))->emax == 16384)
819 return get_no_error_domain (fnc: BUILT_IN_EXP2F128);
820 return get_no_error_domain (fnc: BUILT_IN_EXP2);
821 case BUILT_IN_EXP2F64X:
822 if (REAL_MODE_FORMAT (TYPE_MODE (float64x_type_node))->emax == 16384)
823 return get_no_error_domain (fnc: BUILT_IN_EXP2F128);
824 return get_no_error_domain (fnc: BUILT_IN_EXP2);
825 case BUILT_IN_EXP10F:
826 case BUILT_IN_POW10F:
827 /* exp10f: (-inf, 38) */
828 return get_domain (lb: -1, has_lb: false, lb_inclusive: false,
829 ub: 38, has_ub: true, ub_inclusive: false);
830 case BUILT_IN_EXP10:
831 case BUILT_IN_POW10:
832 /* exp10: (-inf, 308) */
833 return get_domain (lb: -1, has_lb: false, lb_inclusive: false,
834 ub: 308, has_ub: true, ub_inclusive: false);
835 case BUILT_IN_EXP10L:
836 case BUILT_IN_POW10L:
837 if (REAL_MODE_FORMAT (TYPE_MODE (long_double_type_node))->emax == 16384)
838 /* exp10l: (-inf, 4932) */
839 return get_domain (lb: -1, has_lb: false, lb_inclusive: false,
840 ub: 4932, has_ub: true, ub_inclusive: false);
841 return get_no_error_domain (fnc: BUILT_IN_EXP10);
842 /* sqrt: [0, +inf) */
843 CASE_FLT_FN (BUILT_IN_SQRT):
844 CASE_FLT_FN_FLOATN_NX (BUILT_IN_SQRT):
845 return get_domain (lb: 0, has_lb: true, lb_inclusive: true,
846 ub: 0, has_ub: false, ub_inclusive: false);
847 default:
848 gcc_unreachable ();
849 }
850
851 gcc_unreachable ();
852}
853
854/* The function to generate shrink wrap conditions for a partially
855 dead builtin call whose return value is not used anywhere,
856 but has to be kept live due to potential error condition.
857 BI_CALL is the builtin call, CONDS is the vector of statements
858 for condition code, NCODES is the pointer to the number of
859 logical conditions. Statements belonging to different logical
860 condition are separated by NULL tree in the vector. */
861
862static void
863gen_shrink_wrap_conditions (gcall *bi_call, const vec<gimple *> &conds,
864 unsigned int *nconds)
865{
866 gcall *call;
867 tree fn;
868 enum built_in_function fnc;
869
870 gcc_assert (nconds && conds.exists ());
871 gcc_assert (conds.length () == 0);
872 gcc_assert (is_gimple_call (bi_call));
873
874 call = bi_call;
875 fn = gimple_call_fndecl (gs: call);
876 gcc_assert (fn && fndecl_built_in_p (fn));
877 fnc = DECL_FUNCTION_CODE (decl: fn);
878 *nconds = 0;
879
880 if (fnc == BUILT_IN_POW)
881 gen_conditions_for_pow (pow_call: call, conds, nconds);
882 else
883 {
884 tree arg;
885 inp_domain domain = get_no_error_domain (fnc);
886 *nconds = 0;
887 arg = gimple_call_arg (gs: bi_call, index: 0);
888 gen_conditions_for_domain (arg, domain, conds, nconds);
889 }
890
891 return;
892}
893
894/* Shrink-wrap BI_CALL so that it is only called when one of the NCONDS
895 conditions in CONDS is false. Also move BI_NEWCALL to a new basic block
896 when it is non-null, it is called while all of the CONDS are true. */
897
898static void
899shrink_wrap_one_built_in_call_with_conds (gcall *bi_call,
900 const vec <gimple *> &conds,
901 unsigned int nconds,
902 gcall *bi_newcall = NULL)
903{
904 gimple_stmt_iterator bi_call_bsi;
905 basic_block bi_call_bb, bi_newcall_bb, join_tgt_bb, guard_bb;
906 edge join_tgt_in_edge_from_call, join_tgt_in_edge_fall_thru;
907 edge bi_call_in_edge0, guard_bb_in_edge;
908 unsigned tn_cond_stmts;
909 unsigned ci;
910 gimple *cond_expr = NULL;
911 gimple *cond_expr_start;
912
913 /* The cfg we want to create looks like this:
914 [guard n-1] <- guard_bb (old block)
915 | \
916 | [guard n-2] }
917 | / \ }
918 | / ... } new blocks
919 | / [guard 0] }
920 | / / | }
921 [call] | <- bi_call_bb }
922 \ [newcall] <-bi_newcall_bb}
923 \ |
924 [join] <- join_tgt_bb (old iff call must end bb)
925 possible EH edges (only if [join] is old)
926
927 When [join] is new, the immediate dominators for these blocks are:
928
929 1. [guard n-1]: unchanged
930 2. [call]: [guard n-1]
931 3. [newcall]: [guard 0]
932 4. [guard m]: [guard m+1] for 0 <= m <= n-2
933 5. [join]: [guard n-1]
934
935 We punt for the more complex case of [join] being old and
936 simply free the dominance info. We also punt on postdominators,
937 which aren't expected to be available at this point anyway. */
938 bi_call_bb = gimple_bb (g: bi_call);
939
940 /* Now find the join target bb -- split bi_call_bb if needed. */
941 if (stmt_ends_bb_p (bi_call))
942 {
943 /* We checked that there was a fallthrough edge in
944 can_guard_call_p. */
945 join_tgt_in_edge_from_call = find_fallthru_edge (edges: bi_call_bb->succs);
946 gcc_assert (join_tgt_in_edge_from_call);
947 /* We don't want to handle PHIs. */
948 if (EDGE_COUNT (join_tgt_in_edge_from_call->dest->preds) > 1)
949 join_tgt_bb = split_edge (join_tgt_in_edge_from_call);
950 else
951 {
952 join_tgt_bb = join_tgt_in_edge_from_call->dest;
953 /* We may have degenerate PHIs in the destination. Propagate
954 those out. */
955 for (gphi_iterator i = gsi_start_phis (join_tgt_bb); !gsi_end_p (i);)
956 {
957 gphi *phi = i.phi ();
958 replace_uses_by (gimple_phi_result (gs: phi),
959 gimple_phi_arg_def (gs: phi, index: 0));
960 remove_phi_node (&i, true);
961 }
962 }
963 }
964 else
965 {
966 join_tgt_in_edge_from_call = split_block (bi_call_bb, bi_call);
967 join_tgt_bb = join_tgt_in_edge_from_call->dest;
968 }
969
970 bi_call_bsi = gsi_for_stmt (bi_call);
971
972 /* Now it is time to insert the first conditional expression
973 into bi_call_bb and split this bb so that bi_call is
974 shrink-wrapped. */
975 tn_cond_stmts = conds.length ();
976 cond_expr = NULL;
977 cond_expr_start = conds[0];
978 for (ci = 0; ci < tn_cond_stmts; ci++)
979 {
980 gimple *c = conds[ci];
981 gcc_assert (c || ci != 0);
982 if (!c)
983 break;
984 gsi_insert_before (&bi_call_bsi, c, GSI_SAME_STMT);
985 cond_expr = c;
986 }
987 ci++;
988 gcc_assert (cond_expr && gimple_code (cond_expr) == GIMPLE_COND);
989
990 typedef std::pair<edge, edge> edge_pair;
991 auto_vec<edge_pair, 8> edges;
992
993 bi_call_in_edge0 = split_block (bi_call_bb, cond_expr);
994 bi_call_in_edge0->flags &= ~EDGE_FALLTHRU;
995 bi_call_in_edge0->flags |= EDGE_FALSE_VALUE;
996 guard_bb = bi_call_bb;
997 bi_call_bb = bi_call_in_edge0->dest;
998 join_tgt_in_edge_fall_thru = make_edge (guard_bb, join_tgt_bb,
999 EDGE_TRUE_VALUE);
1000
1001 edges.reserve (nelems: nconds);
1002 edges.quick_push (obj: edge_pair (bi_call_in_edge0, join_tgt_in_edge_fall_thru));
1003
1004 /* Code generation for the rest of the conditions */
1005 for (unsigned int i = 1; i < nconds; ++i)
1006 {
1007 unsigned ci0;
1008 edge bi_call_in_edge;
1009 gimple_stmt_iterator guard_bsi = gsi_for_stmt (cond_expr_start);
1010 ci0 = ci;
1011 cond_expr_start = conds[ci0];
1012 for (; ci < tn_cond_stmts; ci++)
1013 {
1014 gimple *c = conds[ci];
1015 gcc_assert (c || ci != ci0);
1016 if (!c)
1017 break;
1018 gsi_insert_before (&guard_bsi, c, GSI_SAME_STMT);
1019 cond_expr = c;
1020 }
1021 ci++;
1022 gcc_assert (cond_expr && gimple_code (cond_expr) == GIMPLE_COND);
1023 guard_bb_in_edge = split_block (guard_bb, cond_expr);
1024 guard_bb_in_edge->flags &= ~EDGE_FALLTHRU;
1025 guard_bb_in_edge->flags |= EDGE_TRUE_VALUE;
1026
1027 bi_call_in_edge = make_edge (guard_bb, bi_call_bb, EDGE_FALSE_VALUE);
1028 edges.quick_push (obj: edge_pair (bi_call_in_edge, guard_bb_in_edge));
1029 }
1030
1031 /* Move BI_NEWCALL to new basic block when it is non-null. */
1032 if (bi_newcall)
1033 {
1034 /* Get bi_newcall_bb by split join_tgt_in_edge_fall_thru edge,
1035 and move BI_NEWCALL to bi_newcall_bb. */
1036 bi_newcall_bb = split_edge (join_tgt_in_edge_fall_thru);
1037 gimple_stmt_iterator to_gsi = gsi_start_bb (bb: bi_newcall_bb);
1038 gimple_stmt_iterator from_gsi = gsi_for_stmt (bi_newcall);
1039 gsi_move_before (&from_gsi, &to_gsi);
1040 join_tgt_in_edge_fall_thru = EDGE_SUCC (bi_newcall_bb, 0);
1041 join_tgt_bb = join_tgt_in_edge_fall_thru->dest;
1042
1043 tree bi_newcall_lhs = gimple_call_lhs (gs: bi_newcall);
1044 tree bi_call_lhs = gimple_call_lhs (gs: bi_call);
1045 if (!bi_call_lhs)
1046 {
1047 bi_call_lhs = copy_ssa_name (var: bi_newcall_lhs);
1048 gimple_call_set_lhs (gs: bi_call, lhs: bi_call_lhs);
1049 SSA_NAME_DEF_STMT (bi_call_lhs) = bi_call;
1050 }
1051
1052 /* Create phi node for lhs of BI_CALL and BI_NEWCALL. */
1053 gphi *new_phi = create_phi_node (copy_ssa_name (var: bi_newcall_lhs),
1054 join_tgt_bb);
1055 SSA_NAME_OCCURS_IN_ABNORMAL_PHI (PHI_RESULT (new_phi))
1056 = SSA_NAME_OCCURS_IN_ABNORMAL_PHI (bi_newcall_lhs);
1057 add_phi_arg (new_phi, bi_call_lhs, join_tgt_in_edge_from_call,
1058 gimple_location (g: bi_call));
1059 add_phi_arg (new_phi, bi_newcall_lhs, join_tgt_in_edge_fall_thru,
1060 gimple_location (g: bi_newcall));
1061
1062 /* Replace all use of original return value with result of phi node. */
1063 use_operand_p use_p;
1064 gimple *use_stmt;
1065 imm_use_iterator iterator;
1066 FOR_EACH_IMM_USE_STMT (use_stmt, iterator, bi_newcall_lhs)
1067 if (use_stmt != new_phi)
1068 FOR_EACH_IMM_USE_ON_STMT (use_p, iterator)
1069 SET_USE (use_p, PHI_RESULT (new_phi));
1070 }
1071
1072 /* Now update the probability and profile information, processing the
1073 guards in order of execution.
1074
1075 There are two approaches we could take here. On the one hand we
1076 could assign a probability of X to the call block and distribute
1077 that probability among its incoming edges. On the other hand we
1078 could assign a probability of X to each individual call edge.
1079
1080 The choice only affects calls that have more than one condition.
1081 In those cases, the second approach would give the call block
1082 a greater probability than the first. However, the difference
1083 is only small, and our chosen X is a pure guess anyway.
1084
1085 Here we take the second approach because it's slightly simpler
1086 and because it's easy to see that it doesn't lose profile counts. */
1087 bi_call_bb->count = profile_count::zero ();
1088 while (!edges.is_empty ())
1089 {
1090 edge_pair e = edges.pop ();
1091 edge call_edge = e.first;
1092 edge nocall_edge = e.second;
1093 basic_block src_bb = call_edge->src;
1094 gcc_assert (src_bb == nocall_edge->src);
1095
1096 call_edge->probability = profile_probability::very_unlikely ();
1097 nocall_edge->probability = profile_probability::always ()
1098 - call_edge->probability;
1099
1100 bi_call_bb->count += call_edge->count ();
1101
1102 if (nocall_edge->dest != join_tgt_bb)
1103 nocall_edge->dest->count = src_bb->count - bi_call_bb->count;
1104 }
1105
1106 if (dom_info_available_p (CDI_DOMINATORS))
1107 {
1108 /* The split_blocks leave [guard 0] as the immediate dominator
1109 of [call] and [call] as the immediate dominator of [join].
1110 Fix them up. */
1111 set_immediate_dominator (CDI_DOMINATORS, bi_call_bb, guard_bb);
1112 set_immediate_dominator (CDI_DOMINATORS, join_tgt_bb, guard_bb);
1113 }
1114
1115 if (dump_file && (dump_flags & TDF_DETAILS))
1116 {
1117 location_t loc;
1118 loc = gimple_location (g: bi_call);
1119 fprintf (stream: dump_file,
1120 format: "%s:%d: note: function call is shrink-wrapped"
1121 " into error conditions.\n",
1122 LOCATION_FILE (loc), LOCATION_LINE (loc));
1123 }
1124}
1125
1126/* Shrink-wrap BI_CALL so that it is only called when it might set errno
1127 (but is always called if it would set errno). */
1128
1129static void
1130shrink_wrap_one_built_in_call (gcall *bi_call)
1131{
1132 unsigned nconds = 0;
1133 auto_vec<gimple *, 12> conds;
1134 gen_shrink_wrap_conditions (bi_call, conds, nconds: &nconds);
1135 gcc_assert (nconds != 0);
1136 shrink_wrap_one_built_in_call_with_conds (bi_call, conds, nconds);
1137}
1138
1139/* Return true if built-in function call CALL could be implemented using
1140 a combination of an internal function to compute the result and a
1141 separate call to set errno. */
1142
1143static bool
1144can_use_internal_fn (gcall *call)
1145{
1146 /* Only replace calls that set errno. */
1147 if (!gimple_vdef (g: call))
1148 return false;
1149
1150 /* See whether there is an internal function for this built-in. */
1151 if (replacement_internal_fn (call) == IFN_LAST)
1152 return false;
1153
1154 /* See whether we can catch all cases where errno would be set,
1155 while still avoiding the call in most cases. */
1156 if (!can_test_argument_range (call)
1157 && !edom_only_function (call))
1158 return false;
1159
1160 return true;
1161}
1162
1163/* Implement built-in function call CALL using an internal function. */
1164
1165static void
1166use_internal_fn (gcall *call)
1167{
1168 /* We'll be inserting another call with the same arguments after the
1169 lhs has been set, so prevent any possible coalescing failure from
1170 having both values live at once. See PR 71020. */
1171 replace_abnormal_ssa_names (call);
1172
1173 unsigned nconds = 0;
1174 auto_vec<gimple *, 12> conds;
1175 bool is_arg_conds = false;
1176 if (can_test_argument_range (call))
1177 {
1178 gen_shrink_wrap_conditions (bi_call: call, conds, nconds: &nconds);
1179 is_arg_conds = true;
1180 gcc_assert (nconds != 0);
1181 }
1182 else
1183 gcc_assert (edom_only_function (call));
1184
1185 internal_fn ifn = replacement_internal_fn (call);
1186 gcc_assert (ifn != IFN_LAST);
1187
1188 /* Construct the new call, with the same arguments as the original one. */
1189 auto_vec <tree, 16> args;
1190 unsigned int nargs = gimple_call_num_args (gs: call);
1191 for (unsigned int i = 0; i < nargs; ++i)
1192 args.safe_push (obj: gimple_call_arg (gs: call, index: i));
1193 gcall *new_call = gimple_build_call_internal_vec (ifn, args);
1194 gimple_set_location (g: new_call, location: gimple_location (g: call));
1195 gimple_call_set_nothrow (s: new_call, nothrow_p: gimple_call_nothrow_p (s: call));
1196
1197 /* Transfer the LHS to the new call. */
1198 tree lhs = gimple_call_lhs (gs: call);
1199 gimple_call_set_lhs (gs: new_call, lhs);
1200 gimple_call_set_lhs (gs: call, NULL_TREE);
1201 SSA_NAME_DEF_STMT (lhs) = new_call;
1202
1203 /* Insert the new call. */
1204 gimple_stmt_iterator gsi = gsi_for_stmt (call);
1205 gsi_insert_before (&gsi, new_call, GSI_SAME_STMT);
1206
1207 if (nconds == 0)
1208 {
1209 /* Skip the call if LHS == LHS. If we reach here, EDOM is the only
1210 valid errno value and it is used iff the result is NaN. */
1211 conds.quick_push (obj: gimple_build_cond (EQ_EXPR, lhs, lhs,
1212 NULL_TREE, NULL_TREE));
1213 nconds++;
1214
1215 /* Try replacing the original call with a direct assignment to
1216 errno, via an internal function. */
1217 if (set_edom_supported_p () && !stmt_ends_bb_p (call))
1218 {
1219 gimple_stmt_iterator gsi = gsi_for_stmt (call);
1220 gcall *new_call = gimple_build_call_internal (IFN_SET_EDOM, 0);
1221 gimple_move_vops (new_call, call);
1222 gimple_set_location (g: new_call, location: gimple_location (g: call));
1223 gsi_replace (&gsi, new_call, false);
1224 call = new_call;
1225 }
1226 }
1227 shrink_wrap_one_built_in_call_with_conds (bi_call: call, conds, nconds,
1228 bi_newcall: is_arg_conds ? new_call : NULL);
1229}
1230
1231/* The top level function for conditional dead code shrink
1232 wrapping transformation. */
1233
1234static void
1235shrink_wrap_conditional_dead_built_in_calls (const vec<gcall *> &calls)
1236{
1237 unsigned i = 0;
1238
1239 unsigned n = calls.length ();
1240 for (; i < n ; i++)
1241 {
1242 gcall *bi_call = calls[i];
1243 if (gimple_call_lhs (gs: bi_call))
1244 use_internal_fn (call: bi_call);
1245 else
1246 shrink_wrap_one_built_in_call (bi_call);
1247 }
1248}
1249
1250namespace {
1251
1252const pass_data pass_data_call_cdce =
1253{
1254 .type: GIMPLE_PASS, /* type */
1255 .name: "cdce", /* name */
1256 .optinfo_flags: OPTGROUP_NONE, /* optinfo_flags */
1257 .tv_id: TV_TREE_CALL_CDCE, /* tv_id */
1258 .properties_required: ( PROP_cfg | PROP_ssa ), /* properties_required */
1259 .properties_provided: 0, /* properties_provided */
1260 .properties_destroyed: 0, /* properties_destroyed */
1261 .todo_flags_start: 0, /* todo_flags_start */
1262 .todo_flags_finish: 0, /* todo_flags_finish */
1263};
1264
1265class pass_call_cdce : public gimple_opt_pass
1266{
1267public:
1268 pass_call_cdce (gcc::context *ctxt)
1269 : gimple_opt_pass (pass_data_call_cdce, ctxt)
1270 {}
1271
1272 /* opt_pass methods: */
1273 bool gate (function *) final override
1274 {
1275 /* The limit constants used in the implementation
1276 assume IEEE floating point format. Other formats
1277 can be supported in the future if needed. */
1278 return flag_tree_builtin_call_dce != 0;
1279 }
1280
1281 unsigned int execute (function *) final override;
1282
1283}; // class pass_call_cdce
1284
1285unsigned int
1286pass_call_cdce::execute (function *fun)
1287{
1288 basic_block bb;
1289 gimple_stmt_iterator i;
1290 auto_vec<gcall *> cond_dead_built_in_calls;
1291 FOR_EACH_BB_FN (bb, fun)
1292 {
1293 /* Skip blocks that are being optimized for size, since our
1294 transformation always increases code size. */
1295 if (optimize_bb_for_size_p (bb))
1296 continue;
1297
1298 /* Collect dead call candidates. */
1299 for (i = gsi_start_bb (bb); !gsi_end_p (i); gsi_next (i: &i))
1300 {
1301 gcall *stmt = dyn_cast <gcall *> (p: gsi_stmt (i));
1302 if (stmt
1303 && gimple_call_builtin_p (stmt, BUILT_IN_NORMAL)
1304 && (gimple_call_lhs (gs: stmt)
1305 ? can_use_internal_fn (call: stmt)
1306 : can_test_argument_range (call: stmt))
1307 && can_guard_call_p (call: stmt))
1308 {
1309 if (dump_file && (dump_flags & TDF_DETAILS))
1310 {
1311 fprintf (stream: dump_file, format: "Found conditional dead call: ");
1312 print_gimple_stmt (dump_file, stmt, 0, TDF_SLIM);
1313 fprintf (stream: dump_file, format: "\n");
1314 }
1315 if (!cond_dead_built_in_calls.exists ())
1316 cond_dead_built_in_calls.create (nelems: 64);
1317 cond_dead_built_in_calls.safe_push (obj: stmt);
1318 }
1319 }
1320 }
1321
1322 if (!cond_dead_built_in_calls.exists ())
1323 return 0;
1324
1325 shrink_wrap_conditional_dead_built_in_calls (calls: cond_dead_built_in_calls);
1326 free_dominance_info (CDI_POST_DOMINATORS);
1327 /* As we introduced new control-flow we need to insert PHI-nodes
1328 for the call-clobbers of the remaining call. */
1329 mark_virtual_operands_for_renaming (fun);
1330 return TODO_update_ssa;
1331}
1332
1333} // anon namespace
1334
1335gimple_opt_pass *
1336make_pass_call_cdce (gcc::context *ctxt)
1337{
1338 return new pass_call_cdce (ctxt);
1339}
1340

source code of gcc/tree-call-cdce.cc