Remove old autovect-branch by moving to "dead" directory.
[official-gcc.git] / old-autovect-branch / gcc / tree-elim-check.c
blob0fa28b3e16730e31f6f33c58913e83dd633ad36e
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
10 version.
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
15 for more details.
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
20 02111-1307, USA. */
22 /*
23 Description:
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
28 static proof.
30 Examples:
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".
40 Further readings:
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
46 papers: ...
49 #include "config.h"
50 #include "system.h"
51 #include "coretypes.h"
52 #include "tm.h"
53 #include "errors.h"
54 #include "ggc.h"
55 #include "tree.h"
57 /* These RTL headers are needed for basic-block.h. */
58 #include "rtl.h"
59 #include "basic-block.h"
60 #include "diagnostic.h"
61 #include "tree-flow.h"
62 #include "tree-dump.h"
63 #include "timevar.h"
64 #include "cfgloop.h"
65 #include "tree-chrec.h"
66 #include "tree-data-ref.h"
67 #include "tree-scalar-evolution.h"
68 #include "tree-pass.h"
69 #include "flags.h"
72 /* Given two integer constants A and B, determine whether "A >= B". */
74 static inline bool
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)
79 return false;
81 *res = (tree_int_cst_sgn (cmp) != 0);
82 return true;
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. */
89 static inline bool
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. */
100 static inline bool
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. */
110 static inline bool
111 prove_truth_value_le (tree type, tree chrec0, tree chrec1, bool *value)
113 if (prove_truth_value_gt (type, chrec0, chrec1, value))
115 *value = !*value;
116 return true;
119 return false;
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. */
126 static inline bool
127 prove_truth_value_ge (tree type, tree chrec0, tree chrec1, bool *value)
129 if (prove_truth_value_gt (type, chrec1, chrec0, value))
131 *value = !*value;
132 return true;
135 return false;
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. */
142 static inline bool
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))
150 *value = true;
152 else
153 *value = false;
155 return true;
158 else
159 return false;
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. */
166 static inline bool
167 prove_truth_value_ne (tree type, tree chrec0, tree chrec1, bool *value)
169 if (prove_truth_value_eq (type, chrec0, chrec1, value))
171 *value = !*value;
172 return true;
175 return false;
178 /* Try to determine whether "CHREC0 (x) CODE CHREC1 (x)", using
179 symbolic computations. When this property is computable, set VALUE
180 and return true. */
182 static bool
183 prove_truth_value_symbolic (enum tree_code code, tree chrec0, tree chrec1,
184 bool *value)
186 tree type0 = chrec_type (chrec0);
187 tree type1 = chrec_type (chrec1);
189 /* Disabled for the moment. */
190 return false;
192 if (type0 != type1)
193 return false;
195 switch (code)
197 case EQ_EXPR:
198 return prove_truth_value_eq (type1, chrec0, chrec1, value);
200 case NE_EXPR:
201 return prove_truth_value_ne (type1, chrec0, chrec1, value);
203 case LT_EXPR:
204 return prove_truth_value_lt (type1, chrec0, chrec1, value);
206 case LE_EXPR:
207 return prove_truth_value_le (type1, chrec0, chrec1, value);
209 case GT_EXPR:
210 return prove_truth_value_gt (type1, chrec0, chrec1, value);
212 case GE_EXPR:
213 return prove_truth_value_ge (type1, chrec0, chrec1, value);
215 default:
216 return false;
220 /* Return the negation of the comparison code. */
222 static inline enum tree_code
223 not_code (enum tree_code code)
225 switch (code)
227 case EQ_EXPR:
228 return NE_EXPR;
229 case NE_EXPR:
230 return EQ_EXPR;
231 case LT_EXPR:
232 return GE_EXPR;
233 case LE_EXPR:
234 return GT_EXPR;
235 case GT_EXPR:
236 return LE_EXPR;
237 case GE_EXPR:
238 return LT_EXPR;
240 default:
241 return 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. */
249 static bool
250 prove_truth_value (tree cond,
251 enum tree_code code,
252 tree chrec0,
253 tree chrec1,
254 bool *value)
256 bool val = false;
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);
262 tree type;
263 basic_block bb;
264 edge e;
265 edge_iterator ei;
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)
274 return false;
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))
281 return 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))
293 return 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))
321 *value = true;
322 return true;
325 if (nb_iters_in_else == chrec_known
326 && integer_zerop (nb_iters_in_then))
328 *value = false;
329 return true;
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)
337 && val)
339 *value = false;
340 return true;
343 if (integer_zerop (nb_iters_in_else)
344 && tree_is_ge (nb_iters_in_then, nb_iters_in_loop, &val)
345 && val)
347 *value = true;
348 return true;
352 return prove_truth_value_symbolic (code, chrec0, chrec1, value);
355 /* Remove the check by setting the condition COND to VALUE. */
357 static inline void
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");
365 if (value == true)
366 COND_EXPR_COND (cond) = boolean_true_node;
368 else
369 COND_EXPR_COND (cond) = boolean_false_node;
371 update_stmt (cond);
374 /* If the condition TEST is decidable at compile time, then eliminate
375 the check. */
377 static void
378 try_eliminate_check (tree cond)
380 bool value;
381 tree test, opnd0, opnd1;
382 tree chrec0, chrec1;
383 struct loop *loop = loop_containing_stmt (cond);
384 tree nb_iters = number_of_iterations_in_loop (loop);
385 enum tree_code code;
387 if (chrec_contains_undetermined (nb_iters))
388 return;
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);
400 switch (code)
402 case SSA_NAME:
403 /* Matched "if (opnd0)" ie, "if (opnd0 != 0)". */
404 opnd0 = test;
405 chrec0 = instantiate_parameters
406 (loop, analyze_scalar_evolution (loop, opnd0));
407 if (chrec_contains_undetermined (chrec0))
408 goto end;
410 chrec1 = fold_convert (TREE_TYPE (opnd0), integer_zero_node);
411 code = NE_EXPR;
412 break;
414 case LT_EXPR:
415 case LE_EXPR:
416 case GT_EXPR:
417 case GE_EXPR:
418 case EQ_EXPR:
419 case NE_EXPR:
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))
430 goto end;
432 break;
434 default:
435 goto end;
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);
455 end:;
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
465 function. */
467 void
468 eliminate_redundant_checks (struct loops *loops ATTRIBUTE_UNUSED)
470 basic_block bb;
471 block_stmt_iterator bsi;
473 bb = BASIC_BLOCK (0);
474 if (bb && bb->loop_father)
475 FOR_EACH_BB (bb)
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)
484 continue;
486 for (bsi = bsi_start (bb); !bsi_end_p (bsi); bsi_next (&bsi))
488 tree expr = bsi_stmt (bsi);
490 switch (TREE_CODE (expr))
492 case COND_EXPR:
493 try_eliminate_check (expr);
494 break;
496 default:
497 break;