From 13285d512dac6411da329c63f6a52b81e88df7a1 Mon Sep 17 00:00:00 2001 From: Zdenek Dvorak Date: Fri, 30 Nov 2007 01:32:04 +0100 Subject: re PR tree-optimization/34244 (VRP/SCEV miscompiles Firefox) PR tree-optimization/34244 * tree-vrp.c (adjust_range_with_scev): Clear scev cache. (record_numbers_of_iterations): New function. (execute_vrp): Cache the numbers of iterations of loops. * tree-scalar-evolution.c (scev_reset_except_niters): New function. (scev_reset): Use scev_reset_except_niters. * tree-scalar-evolution.h (scev_reset_except_niters): Declare. * gcc.dg/tree-ssa/pr34244.c: New test. From-SVN: r130527 --- gcc/ChangeLog | 11 +++ gcc/testsuite/ChangeLog | 5 ++ gcc/testsuite/gcc.dg/tree-ssa/pr34244.c | 130 ++++++++++++++++++++++++++++++++ gcc/tree-scalar-evolution.c | 13 +++- gcc/tree-scalar-evolution.h | 1 + gcc/tree-vrp.c | 32 ++++++++ 6 files changed, 191 insertions(+), 1 deletion(-) create mode 100644 gcc/testsuite/gcc.dg/tree-ssa/pr34244.c diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 438d303..e1215f1 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,14 @@ +2007-11-29 Zdenek Dvorak + + PR tree-optimization/34244 + * tree-vrp.c (adjust_range_with_scev): Clear scev cache. + (record_numbers_of_iterations): New function. + (execute_vrp): Cache the numbers of iterations of loops. + * tree-scalar-evolution.c (scev_reset_except_niters): + New function. + (scev_reset): Use scev_reset_except_niters. + * tree-scalar-evolution.h (scev_reset_except_niters): Declare. + 2007-11-29 Jan Hubicka Jakub Jelinek diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 93e772d..4a77150 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,8 @@ +2007-11-29 Zdenek Dvorak + + PR tree-optimization/34244 + * gcc.dg/tree-ssa/pr34244.c: New test. + 2007-11-29 Jakub Jelinek PR tree-optimization/33434 diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr34244.c b/gcc/testsuite/gcc.dg/tree-ssa/pr34244.c new file mode 100644 index 0000000..8b538d3 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/pr34244.c @@ -0,0 +1,130 @@ +/* PR tree-optimization/34244 */ +/* { dg-do run } */ +/* { dg-options "-O2 " } */ + +int __attribute__((noinline)) GetParent(void) +{ + static int count = 0; + count++; + switch (count) + { + case 1: + case 3: + case 4: + return 1; + default: + return 0; + } +} +int __attribute__((noinline)) FindCommonAncestor(int aNode1, int aNode2) +{ + if (aNode1 && aNode2) { + int offset = 0; + int anc1 = aNode1; + for (;;) { + ++offset; + int parent = GetParent(); + if (!parent) + break; + anc1 = parent; + } + int anc2 = aNode2; + for (;;) { + --offset; + int parent = GetParent(); + if (!parent) + break; + anc2 = parent; + } + if (anc1 == anc2) { + anc1 = aNode1; + anc2 = aNode2; + while (offset > 0) { + anc1 = GetParent(); + --offset; + } + while (offset < 0) { + anc2 = GetParent(); + ++offset; + } + while (anc1 != anc2) { + anc1 = GetParent(); + anc2 = GetParent(); + } + return anc1; + } + } + return 0; +} +extern void abort (void); +int main() +{ + if (FindCommonAncestor (1, 1) != 0) + abort (); + return 0; +} +/* PR tree-optimization/34244 */ +/* { dg-do run } */ +/* { dg-options "-O2 " } */ + +int __attribute__((noinline)) GetParent(void) +{ + static int count = 0; + count++; + switch (count) + { + case 1: + case 3: + case 4: + return 1; + default: + return 0; + } +} +int __attribute__((noinline)) FindCommonAncestor(int aNode1, int aNode2) +{ + if (aNode1 && aNode2) { + int offset = 0; + int anc1 = aNode1; + for (;;) { + ++offset; + int parent = GetParent(); + if (!parent) + break; + anc1 = parent; + } + int anc2 = aNode2; + for (;;) { + --offset; + int parent = GetParent(); + if (!parent) + break; + anc2 = parent; + } + if (anc1 == anc2) { + anc1 = aNode1; + anc2 = aNode2; + while (offset > 0) { + anc1 = GetParent(); + --offset; + } + while (offset < 0) { + anc2 = GetParent(); + ++offset; + } + while (anc1 != anc2) { + anc1 = GetParent(); + anc2 = GetParent(); + } + return anc1; + } + } + return 0; +} +extern void abort (void); +int main() +{ + if (FindCommonAncestor (1, 1) != 0) + abort (); + return 0; +} diff --git a/gcc/tree-scalar-evolution.c b/gcc/tree-scalar-evolution.c index cc80794..262ec76 100644 --- a/gcc/tree-scalar-evolution.c +++ b/gcc/tree-scalar-evolution.c @@ -2608,6 +2608,16 @@ scev_initialize (void) } } +/* Clean the scalar evolution analysis cache, but preserve the cached + numbers of iterations for the loops. */ + +void +scev_reset_except_niters (void) +{ + if (scalar_evolution_info) + htab_empty (scalar_evolution_info); +} + /* Cleans up the information cached by the scalar evolutions analysis. */ void @@ -2619,7 +2629,8 @@ scev_reset (void) if (!scalar_evolution_info || !current_loops) return; - htab_empty (scalar_evolution_info); + scev_reset_except_niters (); + FOR_EACH_LOOP (li, loop, 0) { loop->nb_iterations = NULL_TREE; diff --git a/gcc/tree-scalar-evolution.h b/gcc/tree-scalar-evolution.h index a2ba584..c722579 100644 --- a/gcc/tree-scalar-evolution.h +++ b/gcc/tree-scalar-evolution.h @@ -27,6 +27,7 @@ extern tree get_loop_exit_condition (const struct loop *); extern void scev_initialize (void); extern void scev_reset (void); +extern void scev_reset_except_niters (void); extern void scev_finalize (void); extern tree analyze_scalar_evolution (struct loop *, tree); extern tree instantiate_parameters (struct loop *, tree); diff --git a/gcc/tree-vrp.c b/gcc/tree-vrp.c index 00264d9..1e1ffaa 100644 --- a/gcc/tree-vrp.c +++ b/gcc/tree-vrp.c @@ -2636,6 +2636,13 @@ adjust_range_with_scev (value_range_t *vr, struct loop *loop, tree stmt, if (vr->type == VR_ANTI_RANGE) return; + /* Ensure that there are not values in the scev cache based on assumptions + on ranges of ssa names that were changed + (in set_value_range/set_value_range_to_varying). Preserve cached numbers + of iterations, that were computed before the start of VRP (we do not + recompute these each time to save the compile time). */ + scev_reset_except_niters (); + chrec = instantiate_parameters (loop, analyze_scalar_evolution (loop, var)); /* Like in PR19590, scev can return a constant function. */ @@ -6047,6 +6054,20 @@ vrp_finalize (void) vr_phi_edge_counts = NULL; } +/* Calculates number of iterations for all loops, to ensure that they are + cached. */ + +static void +record_numbers_of_iterations (void) +{ + loop_iterator li; + struct loop *loop; + + FOR_EACH_LOOP (li, loop, 0) + { + number_of_latch_executions (loop); + } +} /* Main entry point to VRP (Value Range Propagation). This pass is loosely based on J. R. C. Patterson, ``Accurate Static Branch @@ -6101,6 +6122,17 @@ execute_vrp (void) insert_range_assertions (); + /* Compute the # of iterations for each loop before we start the VRP + analysis. The value ranges determined by VRP are used in expression + simplification, that is also used by the # of iterations analysis. + However, in the middle of the VRP analysis, the value ranges do not take + all the possible paths in CFG into account, so they do not have to be + correct, and the # of iterations analysis can obtain wrong results. + This is a problem, since the results of the # of iterations analysis + are cached, so these mistakes would not be corrected when the value + ranges are corrected. */ + record_numbers_of_iterations (); + vrp_initialize (); ssa_propagate (vrp_visit_stmt, vrp_visit_phi_node); vrp_finalize (); -- cgit v1.1