tree-loop-distribution.c (enum rdg_dep_type): Add control_dd.
authorRichard Biener <rguenther@suse.de>
Mon, 16 Sep 2013 08:10:28 +0000 (08:10 +0000)
committerRichard Biener <rguenth@gcc.gnu.org>
Mon, 16 Sep 2013 08:10:28 +0000 (08:10 +0000)
2013-09-16  Richard Biener  <rguenther@suse.de>

* tree-loop-distribution.c (enum rdg_dep_type): Add control_dd.
(dot_rdg_1): Handle control_dd.
(create_edge_for_control_dependence): New function.
(create_rdg_edges): Add control dependences if asked for.
(build_rdg): Likewise.
(generate_loops_for_partition): If there are not necessary
control stmts remove all their dependencies.
(collect_condition_stmts, rdg_flag_loop_exits): Remove.
(distribute_loop): Pass on control dependences.
(tree_loop_distribution): Compute control dependences and remove
restriction on number of loop nodes.

* gcc.dg/tree-ssa/ldist-22.c: New testcase.

From-SVN: r202619

gcc/ChangeLog
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.dg/tree-ssa/ldist-22.c [new file with mode: 0644]
gcc/tree-loop-distribution.c

index ea26a50c11eb3f6761f9c0cf92d313aee8f74038..373bd8fc5cd64389280a26a83446bf132fa02aa0 100644 (file)
@@ -1,3 +1,17 @@
+2013-09-16  Richard Biener  <rguenther@suse.de>
+
+       * tree-loop-distribution.c (enum rdg_dep_type): Add control_dd.
+       (dot_rdg_1): Handle control_dd.
+       (create_edge_for_control_dependence): New function.
+       (create_rdg_edges): Add control dependences if asked for.
+       (build_rdg): Likewise.
+       (generate_loops_for_partition): If there are not necessary
+       control stmts remove all their dependencies.
+       (collect_condition_stmts, rdg_flag_loop_exits): Remove.
+       (distribute_loop): Pass on control dependences.
+       (tree_loop_distribution): Compute control dependences and remove
+       restriction on number of loop nodes.
+
 2013-09-16  Jakub Jelinek  <jakub@redhat.com>
 
        * ipa-prop.c (ipa_compute_jump_functions_for_edge): Return early
index 99d0c36beff665260318e427edfdc3523d94c342..6b9b3bc205bc4c0053fc6236ff483e43944975b8 100644 (file)
@@ -1,3 +1,7 @@
+2013-09-16  Richard Biener  <rguenther@suse.de>
+
+       * gcc.dg/tree-ssa/ldist-22.c: New testcase.
+
 2013-09-16  Adam Butcher  <adam@jessamine.co.uk>
 
        * g++.dg/cpp0x/auto9.C: Downgrade two previously expected errors (now
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ldist-22.c b/gcc/testsuite/gcc.dg/tree-ssa/ldist-22.c
new file mode 100644 (file)
index 0000000..f6fff77
--- /dev/null
@@ -0,0 +1,32 @@
+/* { dg-do run } */
+/* { dg-options "-O3 -fdump-tree-ldist-details" } */
+
+extern void abort (void);
+
+int a[1024], b[1024];
+
+void __attribute__((noinline,noclone))
+foo (void)
+{
+  int i;
+  for (i = 0; i < 1024; ++i)
+    {
+      a[i] = 0;
+      if (i > 100)
+       b[i] = i;
+    }
+}
+
+int main()
+{
+  b[100] = 1;
+  foo ();
+  if (b[100] != 1 || b[101] != 101)
+    abort ();
+  if (a[0] != 0 || a[101] != 0)
+    abort ();
+  return;
+}
+
+/* { dg-final { scan-tree-dump "generated memset zero" "ldist" } } */
+/* { dg-final { cleanup-tree-dump "ldist" } } */
index ca3d2ed40f8c3f1558acd3de2cc8707007a6168f..e3e4e12b0256c33bddce54e31e4c8ce8cc2cb735 100644 (file)
@@ -92,7 +92,10 @@ enum rdg_dep_type
   output_dd = 'o',
 
   /* Read After Read (RAR).  */
-  input_dd = 'i'
+  input_dd = 'i',
+
+  /* Control dependence (execute conditional on).  */
+  control_dd = 'c'
 };
 
 /* Dependence information attached to an edge of the RDG.  */
@@ -218,6 +221,10 @@ dot_rdg_1 (FILE *file, struct graph *rdg)
              fprintf (file, "%d -> %d [label=anti] \n", i, e->dest);
              break;
 
+          case control_dd:
+             fprintf (file, "%d -> %d [label=control] \n", i, e->dest);
+             break;
+
            default:
              gcc_unreachable ();
            }
@@ -325,10 +332,38 @@ create_rdg_edges_for_scalar (struct graph *rdg, tree def, int idef)
     }
 }
 
+/* Creates an edge for the control dependences of BB to the vertex V.  */
+
+static void
+create_edge_for_control_dependence (struct graph *rdg, basic_block bb,
+                                   int v, control_dependences *cd)
+{
+  bitmap_iterator bi;
+  unsigned edge_n;
+  EXECUTE_IF_SET_IN_BITMAP (cd->get_edges_dependent_on (bb->index),
+                           0, edge_n, bi)
+    {
+      basic_block cond_bb = cd->get_edge (edge_n)->src;
+      gimple stmt = last_stmt (cond_bb);
+      if (stmt && is_ctrl_stmt (stmt))
+       {
+         struct graph_edge *e;
+         int c = rdg_vertex_for_stmt (rdg, stmt);
+         if (c < 0)
+           continue;
+
+         e = add_edge (rdg, c, v);
+         e->data = XNEW (struct rdg_edge);
+         RDGE_TYPE (e) = control_dd;
+         RDGE_RELATION (e) = NULL;
+       }
+    }
+}
+
 /* Creates the edges of the reduced dependence graph RDG.  */
 
 static void
-create_rdg_edges (struct graph *rdg, vec<ddr_p> ddrs)
+create_rdg_edges (struct graph *rdg, vec<ddr_p> ddrs, control_dependences *cd)
 {
   int i;
   struct data_dependence_relation *ddr;
@@ -345,6 +380,21 @@ create_rdg_edges (struct graph *rdg, vec<ddr_p> ddrs)
     FOR_EACH_PHI_OR_STMT_DEF (def_p, RDG_STMT (rdg, i),
                              iter, SSA_OP_DEF)
       create_rdg_edges_for_scalar (rdg, DEF_FROM_PTR (def_p), i);
+
+  if (cd)
+    for (i = 0; i < rdg->n_vertices; i++)
+      {
+       gimple stmt = RDG_STMT (rdg, i);
+       if (gimple_code (stmt) == GIMPLE_PHI)
+         {
+           edge_iterator ei;
+           edge e;
+           FOR_EACH_EDGE (e, ei, gimple_bb (stmt)->preds)
+             create_edge_for_control_dependence (rdg, e->src, i, cd);
+         }
+       else
+         create_edge_for_control_dependence (rdg, gimple_bb (stmt), i, cd);
+      }
 }
 
 /* Build the vertices of the reduced dependence graph RDG.  Return false
@@ -465,7 +515,7 @@ free_rdg (struct graph *rdg)
    scalar dependence.  */
 
 static struct graph *
-build_rdg (vec<loop_p> loop_nest)
+build_rdg (vec<loop_p> loop_nest, control_dependences *cd)
 {
   struct graph *rdg;
   vec<gimple> stmts;
@@ -497,7 +547,7 @@ build_rdg (vec<loop_p> loop_nest)
       free_rdg (rdg);
       return NULL;
     }
-  create_rdg_edges (rdg, dependence_relations);
+  create_rdg_edges (rdg, dependence_relations, cd);
   dependence_relations.release ();
   datarefs.release ();
 
@@ -699,12 +749,28 @@ generate_loops_for_partition (struct loop *loop, partition_t partition,
              && !is_gimple_debug (stmt)
              && !bitmap_bit_p (partition->stmts, gimple_uid (stmt)))
            {
-             unlink_stmt_vdef (stmt);
-             gsi_remove (&bsi, true);
-             release_defs (stmt);
+             /* Choose an arbitrary path through the empty CFG part
+                that this unnecessary control stmt controls.  */
+             if (gimple_code (stmt) == GIMPLE_COND)
+               {
+                 gimple_cond_make_false (stmt);
+                 update_stmt (stmt);
+               }
+             else if (gimple_code (stmt) == GIMPLE_SWITCH)
+               {
+                 gimple_switch_set_index
+                     (stmt, CASE_LOW (gimple_switch_label (stmt, 1)));
+                 update_stmt (stmt);
+               }
+             else
+               {
+                 unlink_stmt_vdef (stmt);
+                 gsi_remove (&bsi, true);
+                 release_defs (stmt);
+                 continue;
+               }
            }
-         else
-           gsi_next (&bsi);
+         gsi_next (&bsi);
        }
     }
 
@@ -1031,62 +1097,6 @@ rdg_flag_vertex_and_dependent (struct graph *rdg, int v, partition_t partition,
   nodes.release ();
 }
 
-/* Initialize CONDS with all the condition statements from the basic
-   blocks of LOOP.  */
-
-static void
-collect_condition_stmts (struct loop *loop, vec<gimple> *conds)
-{
-  unsigned i;
-  edge e;
-  vec<edge> exits = get_loop_exit_edges (loop);
-
-  FOR_EACH_VEC_ELT (exits, i, e)
-    {
-      gimple cond = last_stmt (e->src);
-
-      if (cond)
-       conds->safe_push (cond);
-    }
-
-  exits.release ();
-}
-
-/* Add to PARTITION all the exit condition statements for LOOPS
-   together with all their dependent statements determined from
-   RDG.  */
-
-static void
-rdg_flag_loop_exits (struct graph *rdg, partition_t partition,
-                    bitmap processed)
-{
-  unsigned i;
-  bitmap_iterator bi;
-  vec<gimple> conds;
-  conds.create (3);
-
-  EXECUTE_IF_SET_IN_BITMAP (partition->loops, 0, i, bi)
-    collect_condition_stmts (get_loop (cfun, i), &conds);
-
-  while (!conds.is_empty ())
-    {
-      gimple cond = conds.pop ();
-      int v = rdg_vertex_for_stmt (rdg, cond);
-      if (!already_processed_vertex_p (processed, v))
-       {
-         bitmap saved_loops = BITMAP_ALLOC (NULL);
-         bitmap_copy (saved_loops, partition->loops);
-         rdg_flag_vertex_and_dependent (rdg, v, partition, processed);
-         EXECUTE_IF_AND_COMPL_IN_BITMAP (partition->loops, saved_loops,
-                                         0, i, bi)
-           collect_condition_stmts (get_loop (cfun, i), &conds);
-         BITMAP_FREE (saved_loops);
-       }
-    }
-
-  conds.release ();
-}
-
 /* Returns a partition with all the statements needed for computing
    the vertex V of the RDG, also including the loop exit conditions.  */
 
@@ -1096,7 +1106,6 @@ build_rdg_partition_for_vertex (struct graph *rdg, int v)
   partition_t partition = partition_alloc (NULL, NULL);
   bitmap processed = BITMAP_ALLOC (NULL);
   rdg_flag_vertex_and_dependent (rdg, v, partition, processed);
-  rdg_flag_loop_exits (rdg, partition, processed);
   BITMAP_FREE (processed);
   return partition;
 }
@@ -1463,7 +1472,8 @@ partition_contains_all_rw (struct graph *rdg,
    Returns the number of distributed loops.  */
 
 static int
-distribute_loop (struct loop *loop, vec<gimple> stmts)
+distribute_loop (struct loop *loop, vec<gimple> stmts,
+                control_dependences *cd)
 {
   struct graph *rdg;
   vec<loop_p> loop_nest;
@@ -1479,7 +1489,7 @@ distribute_loop (struct loop *loop, vec<gimple> stmts)
       return 0;
     }
 
-  rdg = build_rdg (loop_nest);
+  rdg = build_rdg (loop_nest, cd);
   if (!rdg)
     {
       if (dump_file && (dump_flags & TDF_DETAILS))
@@ -1631,6 +1641,7 @@ tree_loop_distribution (void)
   loop_iterator li;
   bool changed = false;
   basic_block bb;
+  control_dependences *cd = NULL;
 
   FOR_ALL_BB (bb)
     {
@@ -1660,10 +1671,6 @@ tree_loop_distribution (void)
       if (!optimize_loop_for_speed_p (loop))
        continue;
 
-      /* Only distribute loops with a header and latch for now.  */
-      if (loop->num_nodes > 2)
-       continue;
-
       /* Initialize the worklist with stmts we seed the partitions with.  */
       bbs = get_loop_body_in_dom_order (loop);
       for (i = 0; i < loop->num_nodes; ++i)
@@ -1697,7 +1704,15 @@ out:
       free (bbs);
 
       if (work_list.length () > 0)
-       nb_generated_loops = distribute_loop (loop, work_list);
+       {
+         if (!cd)
+           {
+             calculate_dominance_info (CDI_POST_DOMINATORS);
+             cd = new control_dependences (create_edge_list ());
+             free_dominance_info (CDI_POST_DOMINATORS);
+           }
+         nb_generated_loops = distribute_loop (loop, work_list, cd);
+       }
 
       if (nb_generated_loops > 0)
        changed = true;
@@ -1714,6 +1729,9 @@ out:
       work_list.release ();
     }
 
+  if (cd)
+    delete cd;
+
   if (changed)
     {
       mark_virtual_operands_for_renaming (cfun);