re PR tree-optimization/71132 (gcc ICE at -O3 on valid code on x86_64-linux-gnu with...
authorRichard Biener <rguenther@suse.de>
Tue, 17 May 2016 12:53:30 +0000 (12:53 +0000)
committerRichard Biener <rguenth@gcc.gnu.org>
Tue, 17 May 2016 12:53:30 +0000 (12:53 +0000)
2016-05-17  Richard Biener  <rguenther@suse.de>

PR tree-optimization/71132
* tree-loop-distribution.c (create_rdg_cd_edges): Pass in loop.
Only add control dependences for blocks in the loop.
(build_rdg): Adjust.
(generate_code_for_partition): Return whether loop should
be destroyed and delay that.
(distribute_loop): Likewise.
(pass_loop_distribution::execute): Record loops to be destroyed
and perform delayed destroying of loops.

* gcc.dg/torture/pr71132.c: New testcase.

From-SVN: r236320

gcc/ChangeLog
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.dg/torture/pr71132.c [new file with mode: 0644]
gcc/tree-loop-distribution.c

index 3c6030d427ad04e871ccc3275f9fd3759235d493..72ea2966c1f3e8edbd38f090672c4758a5fbce51 100644 (file)
@@ -1,3 +1,15 @@
+2016-05-17  Richard Biener  <rguenther@suse.de>
+
+       PR tree-optimization/71132
+       * tree-loop-distribution.c (create_rdg_cd_edges): Pass in loop.
+       Only add control dependences for blocks in the loop.
+       (build_rdg): Adjust.
+       (generate_code_for_partition): Return whether loop should
+       be destroyed and delay that.
+       (distribute_loop): Likewise.
+       (pass_loop_distribution::execute): Record loops to be destroyed
+       and perform delayed destroying of loops.
+
 2016-05-17  Kyrylo Tkachov  <kyrylo.tkachov@arm.com>
 
        PR target/70809
index 51126cb2df2870378f749ff60f084dbcd4d66c21..cc3570ca7ba130a8e85dddaa451de1411cae2ef8 100644 (file)
@@ -1,3 +1,8 @@
+2016-05-17  Richard Biener  <rguenther@suse.de>
+
+       PR tree-optimization/71132
+       * gcc.dg/torture/pr71132.c: New testcase.
+
 2016-05-17  Christophe Lyon  <christophe.lyon@linaro.org>
 
        * g++.dg/inherit/think1.C: Fix dg-do and dg-skip order.
diff --git a/gcc/testsuite/gcc.dg/torture/pr71132.c b/gcc/testsuite/gcc.dg/torture/pr71132.c
new file mode 100644 (file)
index 0000000..2991718
--- /dev/null
@@ -0,0 +1,24 @@
+/* { dg-do compile } */
+
+typedef unsigned size_t;
+struct {
+    unsigned char buf[sizeof(long)];
+} a;
+size_t b;
+int main()
+{
+  size_t c, i;
+  unsigned char *d;
+  for (; c < sizeof(long);)
+    {
+      d = a.buf;
+      b = 0;
+      for (; b < i; b++)
+       *d++ = '\0';
+      for (; c < b; c++)
+       *d++ = 'a';
+      c = 0;
+      for (; i < sizeof(long); i++)
+       ;
+    }
+}
index 3e1074090ac472bcd632ffcf367c3f9c32c3b1f3..a801348453a46bab3f438494422fbedd087d5c01 100644 (file)
@@ -312,7 +312,7 @@ create_rdg_flow_edges (struct graph *rdg)
 /* Creates the edges of the reduced dependence graph RDG.  */
 
 static void
-create_rdg_cd_edges (struct graph *rdg, control_dependences *cd)
+create_rdg_cd_edges (struct graph *rdg, control_dependences *cd, loop_p loop)
 {
   int i;
 
@@ -324,6 +324,7 @@ create_rdg_cd_edges (struct graph *rdg, control_dependences *cd)
          edge_iterator ei;
          edge e;
          FOR_EACH_EDGE (e, ei, gimple_bb (stmt)->preds)
+           if (flow_bb_inside_loop_p (loop, e->src))
              create_edge_for_control_dependence (rdg, e->src, i, cd);
        }
       else
@@ -455,7 +456,7 @@ build_rdg (vec<loop_p> loop_nest, control_dependences *cd)
 
   create_rdg_flow_edges (rdg);
   if (cd)
-    create_rdg_cd_edges (rdg, cd);
+    create_rdg_cd_edges (rdg, cd, loop_nest[0]);
 
   datarefs.release ();
 
@@ -917,9 +918,9 @@ destroy_loop (struct loop *loop)
                           recompute_dominator (CDI_DOMINATORS, dest));
 }
 
-/* Generates code for PARTITION.  */
+/* Generates code for PARTITION.  Return whether LOOP needs to be destroyed.  */
 
-static void
+static bool 
 generate_code_for_partition (struct loop *loop,
                             partition *partition, bool copy_p)
 {
@@ -930,7 +931,7 @@ generate_code_for_partition (struct loop *loop,
       gcc_assert (!partition_reduction_p (partition)
                  || !copy_p);
       generate_loops_for_partition (loop, partition, copy_p);
-      return;
+      return false;
 
     case PKIND_MEMSET:
       generate_memset_builtin (loop, partition);
@@ -947,7 +948,8 @@ generate_code_for_partition (struct loop *loop,
   /* Common tail for partitions we turn into a call.  If this was the last
      partition for which we generate code, we have to destroy the loop.  */
   if (!copy_p)
-    destroy_loop (loop);
+    return true;
+  return false;
 }
 
 
@@ -1397,11 +1399,12 @@ pgcmp (const void *v1_, const void *v2_)
 /* Distributes the code from LOOP in such a way that producer
    statements are placed before consumer statements.  Tries to separate
    only the statements from STMTS into separate loops.
-   Returns the number of distributed loops.  */
+   Returns the number of distributed loops.  Set *DESTROY_P to whether
+   LOOP needs to be destroyed.  */
 
 static int
 distribute_loop (struct loop *loop, vec<gimple *> stmts,
-                control_dependences *cd, int *nb_calls)
+                control_dependences *cd, int *nb_calls, bool *destroy_p)
 {
   struct graph *rdg;
   partition *partition;
@@ -1644,11 +1647,12 @@ distribute_loop (struct loop *loop, vec<gimple *> stmts,
   if (dump_file && (dump_flags & TDF_DETAILS))
     dump_rdg_partitions (dump_file, partitions);
 
+  *destroy_p = false;
   FOR_EACH_VEC_ELT (partitions, i, partition)
     {
       if (partition_builtin_p (partition))
        (*nb_calls)++;
-      generate_code_for_partition (loop, partition, i < nbp - 1);
+      *destroy_p |= generate_code_for_partition (loop, partition, i < nbp - 1);
     }
 
  ldist_done:
@@ -1702,6 +1706,7 @@ pass_loop_distribution::execute (function *fun)
   bool changed = false;
   basic_block bb;
   control_dependences *cd = NULL;
+  auto_vec<loop_p> loops_to_be_destroyed;
 
   FOR_ALL_BB_FN (bb, fun)
     {
@@ -1787,8 +1792,12 @@ out:
              cd = new control_dependences (create_edge_list ());
              free_dominance_info (CDI_POST_DOMINATORS);
            }
+         bool destroy_p;
          nb_generated_loops = distribute_loop (loop, work_list, cd,
-                                               &nb_generated_calls);
+                                               &nb_generated_calls,
+                                               &destroy_p);
+         if (destroy_p)
+           loops_to_be_destroyed.safe_push (loop);
        }
 
       if (nb_generated_loops + nb_generated_calls > 0)
@@ -1806,6 +1815,12 @@ out:
   if (cd)
     delete cd;
 
+  /* Destroy loop bodies that could not be reused.  Do this late as we
+     otherwise can end up refering to stale data in control dependences.  */
+  unsigned i;
+  FOR_EACH_VEC_ELT (loops_to_be_destroyed, i, loop)
+    destroy_loop (loop);
+
   if (changed)
     {
       /* Cached scalar evolutions now may refer to wrong or non-existing