1 /* Elimination of redundant checks.
2 Copyright (C) 2004 Free Software Foundation, Inc.
3 Contributed by Sebastian Pop <sebastian.pop@cri.ensmp.fr>
5 This file is part of GCC.
7 GCC is free software; you can redistribute it and/or modify it under
8 the terms of the GNU General Public License as published by the Free
9 Software Foundation; either version 2, or (at your option) any later
12 GCC is distributed in the hope that it will be useful, but WITHOUT ANY
13 WARRANTY; without even the implied warranty of MERCHANTABILITY or
14 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
17 You should have received a copy of the GNU General Public License
18 along with GCC; see the file COPYING. If not, write to the Free
19 Software Foundation, 59 Temple Place - Suite 330, Boston, MA
25 Compute the scalar evolutions for all the scalar variables of a
26 condition expression, and based on this information performs a
27 proof. The condition is rewritten based on the result of this
32 Example 1: A simple illustration of the algorithm.
34 Given the COND_EXPR "if (a < b)" with "a -> {2, +, 1}_1" and "b
35 -> {3, +, 1}_1", the proof consists in comparing these evolution
36 functions: is it always true for a given iteration x that "{2, +,
37 1}_1 (x) < {3, +, 1}_1 (x)"? The answer is yes, and the test of
38 the condition is consequently replaced by "1".
42 There is no further readings for the moment.
44 Based on the fact that this algorithm is similar to the Value
45 Range Propagation you can have a look at the corresponding
51 #include "coretypes.h"
57 /* These RTL headers are needed for basic-block.h. */
59 #include "basic-block.h"
60 #include "diagnostic.h"
61 #include "tree-flow.h"
62 #include "tree-dump.h"
65 #include "tree-chrec.h"
66 #include "tree-data-ref.h"
67 #include "tree-scalar-evolution.h"
68 #include "tree-pass.h"
72 /* Given two integer constants A and B, determine whether "A >= B". */
75 tree_is_ge (tree a
, tree b
, bool *res
)
77 tree cmp
= fold (build2 (GE_EXPR
, boolean_type_node
, a
, b
));
78 if (TREE_CODE (cmp
) != INTEGER_CST
)
81 *res
= (tree_int_cst_sgn (cmp
) != 0);
85 /* Determines whether "CHREC0 (x) > CHREC1 (x)" for all the integers x
86 such that "0 <= x < nb_iter". When this property is statically
87 computable, set VALUE and return true. */
90 prove_truth_value_gt (tree type
, tree chrec0
, tree chrec1
, bool *value
)
92 tree diff
= chrec_fold_minus (type
, chrec0
, chrec1
);
93 return chrec_is_positive (diff
, value
);
96 /* Determines whether "CHREC0 (x) < CHREC1 (x)" for all the integers
97 x such that "x >= 0". When this property is statically computable,
98 set VALUE and return true. */
101 prove_truth_value_lt (tree type
, tree chrec0
, tree chrec1
, bool *value
)
103 return prove_truth_value_gt (type
, chrec1
, chrec0
, value
);
106 /* Determines whether "CHREC0 (x) <= CHREC1 (x)" for all the integers
107 x such that "x >= 0". When this property is statically computable,
108 set VALUE and return true. */
111 prove_truth_value_le (tree type
, tree chrec0
, tree chrec1
, bool *value
)
113 if (prove_truth_value_gt (type
, chrec0
, chrec1
, value
))
122 /* Determines whether "CHREC0 (x) >= CHREC1 (x)" for all the integers
123 x such that "x >= 0". When this property is statically computable,
124 set VALUE and return true. */
127 prove_truth_value_ge (tree type
, tree chrec0
, tree chrec1
, bool *value
)
129 if (prove_truth_value_gt (type
, chrec1
, chrec0
, value
))
138 /* Determines whether "CHREC0 (x) == CHREC1 (x)" for all the integers
139 x such that "x >= 0". When this property is statically computable,
140 set VALUE and return true. */
143 prove_truth_value_eq (tree type
, tree chrec0
, tree chrec1
, bool *value
)
145 tree diff
= chrec_fold_minus (type
, chrec0
, chrec1
);
147 if (TREE_CODE (diff
) == INTEGER_CST
)
149 if (integer_zerop (diff
))
162 /* Determines whether "CHREC0 (x) != CHREC1 (x)" for all the integers
163 x such that "x >= 0". When this property is statically computable,
164 set VALUE and return true. */
167 prove_truth_value_ne (tree type
, tree chrec0
, tree chrec1
, bool *value
)
169 if (prove_truth_value_eq (type
, chrec0
, chrec1
, value
))
178 /* Try to determine whether "CHREC0 (x) CODE CHREC1 (x)", using
179 symbolic computations. When this property is computable, set VALUE
183 prove_truth_value_symbolic (enum tree_code code
, tree chrec0
, tree chrec1
,
186 tree type0
= chrec_type (chrec0
);
187 tree type1
= chrec_type (chrec1
);
189 /* Disabled for the moment. */
198 return prove_truth_value_eq (type1
, chrec0
, chrec1
, value
);
201 return prove_truth_value_ne (type1
, chrec0
, chrec1
, value
);
204 return prove_truth_value_lt (type1
, chrec0
, chrec1
, value
);
207 return prove_truth_value_le (type1
, chrec0
, chrec1
, value
);
210 return prove_truth_value_gt (type1
, chrec0
, chrec1
, value
);
213 return prove_truth_value_ge (type1
, chrec0
, chrec1
, value
);
220 /* Return the negation of the comparison code. */
222 static inline enum tree_code
223 not_code (enum tree_code code
)
245 /* Determine whether "CHREC0 (x) CODE CHREC1 (x)", for all the
246 integers x such that "0 <= x <= NB_ITERS_IN_LOOP". When this
247 property is statically computable, set VALUE and return true. */
250 prove_truth_value (tree cond
,
257 tree nb_iters_in_then
= chrec_dont_know
;
258 tree nb_iters_in_else
= chrec_dont_know
;
259 struct tree_niter_desc niter_desc
;
260 struct loop
*loop
= loop_containing_stmt (cond
);
261 tree nb_iters_in_loop
= number_of_iterations_in_loop (loop
);
267 if (chrec_contains_undetermined (nb_iters_in_loop
))
268 return prove_truth_value_symbolic (code
, chrec0
, chrec1
, value
);
270 /* Compute the number of iterations that fall in the THEN clause,
271 and the number of iterations that fall in the ELSE clause. */
272 bb
= bb_for_stmt (cond
);
273 if (EDGE_COUNT (bb
->succs
) != 2)
276 FOR_EACH_EDGE (e
, ei
, bb
->succs
)
278 if (e
->flags
& EDGE_FALSE_VALUE
)
280 if (!number_of_iterations_exit (loop
, e
, &niter_desc
, false))
283 type
= TREE_TYPE (niter_desc
.niter
);
284 if (integer_nonzerop (niter_desc
.may_be_zero
))
285 nb_iters_in_then
= build_int_cst (type
, 0);
286 else if (integer_zerop (niter_desc
.may_be_zero
))
287 nb_iters_in_then
= niter_desc
.niter
;
290 if (e
->flags
& EDGE_TRUE_VALUE
)
292 if (!number_of_iterations_exit (loop
, e
, &niter_desc
, false))
295 type
= TREE_TYPE (niter_desc
.niter
);
296 if (integer_nonzerop (niter_desc
.may_be_zero
))
297 nb_iters_in_else
= build_int_cst (type
, 0);
298 else if (integer_zerop (niter_desc
.may_be_zero
))
299 nb_iters_in_else
= niter_desc
.niter
;
303 if (dump_file
&& (dump_flags
& TDF_DETAILS
))
305 fprintf (dump_file
, " (nb_iters_in_loop = ");
306 print_generic_expr (dump_file
, nb_iters_in_loop
, 0);
307 fprintf (dump_file
, ")\n (nb_iters_in_then = ");
308 print_generic_expr (dump_file
, nb_iters_in_then
, 0);
309 fprintf (dump_file
, ")\n (nb_iters_in_else = ");
310 print_generic_expr (dump_file
, nb_iters_in_else
, 0);
311 fprintf (dump_file
, ")\n");
314 if (chrec_contains_undetermined (nb_iters_in_then
)
315 || chrec_contains_undetermined (nb_iters_in_else
))
316 return prove_truth_value_symbolic (code
, chrec0
, chrec1
, value
);
318 if (nb_iters_in_then
== chrec_known
319 && integer_zerop (nb_iters_in_else
))
325 if (nb_iters_in_else
== chrec_known
326 && integer_zerop (nb_iters_in_then
))
332 if (TREE_CODE (nb_iters_in_then
) == INTEGER_CST
333 && TREE_CODE (nb_iters_in_else
) == INTEGER_CST
)
335 if (integer_zerop (nb_iters_in_then
)
336 && tree_is_ge (nb_iters_in_else
, nb_iters_in_loop
, &val
)
343 if (integer_zerop (nb_iters_in_else
)
344 && tree_is_ge (nb_iters_in_then
, nb_iters_in_loop
, &val
)
352 return prove_truth_value_symbolic (code
, chrec0
, chrec1
, value
);
355 /* Remove the check by setting the condition COND to VALUE. */
358 remove_redundant_check (tree cond
, bool value
)
360 /* A dead COND_EXPR means the condition is dead. We don't change any
361 flow, just replace the expression with a constant. */
362 if (dump_file
&& (dump_flags
& TDF_DETAILS
))
363 fprintf (dump_file
, "Replacing one of the conditions.\n");
366 COND_EXPR_COND (cond
) = boolean_true_node
;
369 COND_EXPR_COND (cond
) = boolean_false_node
;
374 /* If the condition TEST is decidable at compile time, then eliminate
378 try_eliminate_check (tree cond
)
381 tree test
, opnd0
, opnd1
;
383 struct loop
*loop
= loop_containing_stmt (cond
);
384 tree nb_iters
= number_of_iterations_in_loop (loop
);
387 if (chrec_contains_undetermined (nb_iters
))
390 if (dump_file
&& (dump_flags
& TDF_DETAILS
))
392 fprintf (dump_file
, "(try_eliminate_check \n");
393 fprintf (dump_file
, " (cond = ");
394 print_generic_expr (dump_file
, cond
, 0);
395 fprintf (dump_file
, ")\n");
398 test
= COND_EXPR_COND (cond
);
399 code
= TREE_CODE (test
);
403 /* Matched "if (opnd0)" ie, "if (opnd0 != 0)". */
405 chrec0
= instantiate_parameters
406 (loop
, analyze_scalar_evolution (loop
, opnd0
));
407 if (chrec_contains_undetermined (chrec0
))
410 chrec1
= fold_convert (TREE_TYPE (opnd0
), integer_zero_node
);
420 opnd0
= TREE_OPERAND (test
, 0);
421 opnd1
= TREE_OPERAND (test
, 1);
423 chrec0
= instantiate_parameters
424 (loop
, analyze_scalar_evolution (loop
, opnd0
));
425 chrec1
= instantiate_parameters
426 (loop
, analyze_scalar_evolution (loop
, opnd1
));
428 if (chrec_contains_undetermined (chrec0
)
429 || chrec_contains_undetermined (chrec1
))
438 if (dump_file
&& (dump_flags
& TDF_DETAILS
))
440 fprintf (dump_file
, " (test = ");
441 print_generic_expr (dump_file
, test
, 0);
442 fprintf (dump_file
, ")\n (loop_nb = %d)\n", loop
->num
);
443 fprintf (dump_file
, " (nb_iters = ");
444 print_generic_expr (dump_file
, nb_iters
, 0);
445 fprintf (dump_file
, ")\n (chrec0 = ");
446 print_generic_expr (dump_file
, chrec0
, 0);
447 fprintf (dump_file
, ")\n (chrec1 = ");
448 print_generic_expr (dump_file
, chrec1
, 0);
449 fprintf (dump_file
, ")\n");
452 if (prove_truth_value (cond
, code
, chrec0
, chrec1
, &value
))
453 remove_redundant_check (cond
, value
);
456 if (dump_file
&& (dump_flags
& TDF_DETAILS
))
457 fprintf (dump_file
, ")\n");
460 /* Walk over all the statements, searching for conditional statements.
462 A better way to determine the conditional expressions that are good
463 candidates for elimination would be needed. For the moment
464 systematically search the conditional expressions over the whole
468 eliminate_redundant_checks (struct loops
*loops ATTRIBUTE_UNUSED
)
471 block_stmt_iterator bsi
;
473 bb
= BASIC_BLOCK (0);
474 if (bb
&& bb
->loop_father
)
477 struct loop
*loop
= bb
->loop_father
;
479 /* Don't try to prove anything about the loop exit
480 conditions: avoid the block that contains the condition
481 that guards the exit of the loop. */
482 if (!loop
->single_exit
483 || loop
->single_exit
->src
== bb
)
486 for (bsi
= bsi_start (bb
); !bsi_end_p (bsi
); bsi_next (&bsi
))
488 tree expr
= bsi_stmt (bsi
);
490 switch (TREE_CODE (expr
))
493 try_eliminate_check (expr
);