aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorZdenek Dvorak <ook@ucw.cz>2007-11-30 01:32:04 +0100
committerZdenek Dvorak <rakdver@gcc.gnu.org>2007-11-30 00:32:04 +0000
commit13285d512dac6411da329c63f6a52b81e88df7a1 (patch)
tree573fc12944ab74427d5b1d5768b2a39ac6ed4847
parent54bded776c12100d755e2976fbd5f1b6733ea64b (diff)
downloadgcc-13285d512dac6411da329c63f6a52b81e88df7a1.zip
gcc-13285d512dac6411da329c63f6a52b81e88df7a1.tar.gz
gcc-13285d512dac6411da329c63f6a52b81e88df7a1.tar.bz2
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
-rw-r--r--gcc/ChangeLog11
-rw-r--r--gcc/testsuite/ChangeLog5
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/pr34244.c130
-rw-r--r--gcc/tree-scalar-evolution.c13
-rw-r--r--gcc/tree-scalar-evolution.h1
-rw-r--r--gcc/tree-vrp.c32
6 files changed, 191 insertions, 1 deletions
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 <ook@ucw.cz>
+
+ 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 <jh@suse.cz>
Jakub Jelinek <jakub@redhat.com>
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 <ook@ucw.cz>
+
+ PR tree-optimization/34244
+ * gcc.dg/tree-ssa/pr34244.c: New test.
+
2007-11-29 Jakub Jelinek <jakub@redhat.com>
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 ();