]> gcc.gnu.org Git - gcc.git/commitdiff
re PR tree-optimization/34244 (VRP/SCEV miscompiles Firefox)
authorZdenek Dvorak <ook@ucw.cz>
Fri, 30 Nov 2007 00:32:04 +0000 (01:32 +0100)
committerZdenek Dvorak <rakdver@gcc.gnu.org>
Fri, 30 Nov 2007 00:32:04 +0000 (00:32 +0000)
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
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.dg/tree-ssa/pr34244.c [new file with mode: 0644]
gcc/tree-scalar-evolution.c
gcc/tree-scalar-evolution.h
gcc/tree-vrp.c

index 438d303ada7b8adfeae34b18fe32e1ad2b14a8ef..e1215f1bc9ddc5c6f10056471ec5421a685a4508 100644 (file)
@@ -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>
 
index 93e772d194826889d38ef7af09da3da4eaea5a50..4a77150b92afc361f3a6dd851239f86145d04b2d 100644 (file)
@@ -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 (file)
index 0000000..8b538d3
--- /dev/null
@@ -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;
+}
index cc80794c5d9cab5d0f42ca51b0cdb033ca377c62..262ec764b3089199211d32f378c622f95dfae33a 100644 (file)
@@ -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;
index a2ba5848046480ffd1abf728124da44556d3f86b..c722579d9c93167c01c28621ff4a9c5c548e3364 100644 (file)
@@ -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);
index 00264d9a12ca968f8b05b18e1276e74ff0cc2a72..1e1ffaa7e69adfcc707dddf23687debeffec4075 100644 (file)
@@ -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 ();
This page took 0.175196 seconds and 5 git commands to generate.