re PR tree-optimization/90402 (ICE in slpeel_duplicate_current_defs_from_edges)
authorRichard Biener <rguenther@suse.de>
Mon, 13 May 2019 11:37:21 +0000 (11:37 +0000)
committerRichard Biener <rguenth@gcc.gnu.org>
Mon, 13 May 2019 11:37:21 +0000 (11:37 +0000)
2019-05-13  Richard Biener  <rguenther@suse.de>

PR tree-optimization/90402
* tree-if-conv.c (tree_if_conversion): Value number only
the loop body by making the latch an exit of the region
as well.
* tree-ssa-sccvn.c (process_bb): Add flag whether to skip
processing PHIs.
(do_rpo_vn): Deal with multiple edges into the entry block
that are not backedges inside the region by skipping PHIs
of the entry block.

* gcc.dg/torture/pr90402-1.c: New testcase.

From-SVN: r271125

gcc/ChangeLog
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.dg/torture/pr90402-1.c [new file with mode: 0644]
gcc/tree-if-conv.c
gcc/tree-ssa-sccvn.c

index 42448f5..925d23c 100644 (file)
@@ -1,5 +1,17 @@
 2019-05-13  Richard Biener  <rguenther@suse.de>
 
+       PR tree-optimization/90402
+       * tree-if-conv.c (tree_if_conversion): Value number only
+       the loop body by making the latch an exit of the region
+       as well.
+       * tree-ssa-sccvn.c (process_bb): Add flag whether to skip
+       processing PHIs.
+       (do_rpo_vn): Deal with multiple edges into the entry block
+       that are not backedges inside the region by skipping PHIs
+       of the entry block.
+
+2019-05-13  Richard Biener  <rguenther@suse.de>
+
        PR tree-optimization/90316
        * tree-ssa-pre.c (insert_aux): Fold into ...
        (insert): ... this function.  Use a RPO walk to reduce the
index 286bfe2..ebefd00 100644 (file)
@@ -1,3 +1,8 @@
+2019-05-13  Richard Biener  <rguenther@suse.de>
+
+       PR tree-optimization/90402
+       * gcc.dg/torture/pr90402-1.c: New testcase.
+
 2019-05-12  Iain Sandoe  <iain@sandoe.co.uk>
            Dominique d'Humieres  <dominiq@gcc.gnu.org>
 
diff --git a/gcc/testsuite/gcc.dg/torture/pr90402-1.c b/gcc/testsuite/gcc.dg/torture/pr90402-1.c
new file mode 100644 (file)
index 0000000..c4bd894
--- /dev/null
@@ -0,0 +1,26 @@
+/* { dg-do compile } */
+/* { dg-additional-options "-mavx" { target x86_64-*-* i?86-*-* } } */
+
+int kn, ha;
+
+int
+c7 (void)
+{
+}
+
+void
+ul (int w3)
+{
+  kn = c7 ();
+
+  while (w3 < 1)
+    {
+      ha += !!kn ? 1 : w3;
+
+      for (kn = 0; kn < 2; ++kn)
+       {
+       }
+
+      ++w3;
+    }
+}
index ec2db00..98566e3 100644 (file)
@@ -3066,10 +3066,12 @@ tree_if_conversion (struct loop *loop, vec<gimple *> *preds)
   ifcvt_local_dce (loop->header);
 
   /* Perform local CSE, this esp. helps the vectorizer analysis if loads
-     and stores are involved.
+     and stores are involved.  CSE only the loop body, not the entry
+     PHIs, those are to be kept in sync with the non-if-converted copy.
      ???  We'll still keep dead stores though.  */
   exit_bbs = BITMAP_ALLOC (NULL);
   bitmap_set_bit (exit_bbs, single_exit (loop)->dest->index);
+  bitmap_set_bit (exit_bbs, loop->latch->index);
   todo |= do_rpo_vn (cfun, loop_preheader_edge (loop), exit_bbs);
   BITMAP_FREE (exit_bbs);
 
index c3ca49b..b4f6260 100644 (file)
@@ -5979,7 +5979,7 @@ insert_related_predicates_on_edge (enum tree_code code, tree *ops, edge pred_e)
 static unsigned
 process_bb (rpo_elim &avail, basic_block bb,
            bool bb_visited, bool iterate_phis, bool iterate, bool eliminate,
-           bool do_region, bitmap exit_bbs)
+           bool do_region, bitmap exit_bbs, bool skip_phis)
 {
   unsigned todo = 0;
   edge_iterator ei;
@@ -5990,7 +5990,8 @@ process_bb (rpo_elim &avail, basic_block bb,
   /* If we are in loop-closed SSA preserve this state.  This is
      relevant when called on regions from outside of FRE/PRE.  */
   bool lc_phi_nodes = false;
-  if (loops_state_satisfies_p (LOOP_CLOSED_SSA))
+  if (!skip_phis
+      && loops_state_satisfies_p (LOOP_CLOSED_SSA))
     FOR_EACH_EDGE (e, ei, bb->preds)
       if (e->src->loop_father != e->dest->loop_father
          && flow_loop_nested_p (e->dest->loop_father,
@@ -6011,67 +6012,68 @@ process_bb (rpo_elim &avail, basic_block bb,
     }
 
   /* Value-number all defs in the basic-block.  */
-  for (gphi_iterator gsi = gsi_start_phis (bb); !gsi_end_p (gsi);
-       gsi_next (&gsi))
-    {
-      gphi *phi = gsi.phi ();
-      tree res = PHI_RESULT (phi);
-      vn_ssa_aux_t res_info = VN_INFO (res);
-      if (!bb_visited)
-       {
-         gcc_assert (!res_info->visited);
-         res_info->valnum = VN_TOP;
-         res_info->visited = true;
-       }
+  if (!skip_phis)
+    for (gphi_iterator gsi = gsi_start_phis (bb); !gsi_end_p (gsi);
+        gsi_next (&gsi))
+      {
+       gphi *phi = gsi.phi ();
+       tree res = PHI_RESULT (phi);
+       vn_ssa_aux_t res_info = VN_INFO (res);
+       if (!bb_visited)
+         {
+           gcc_assert (!res_info->visited);
+           res_info->valnum = VN_TOP;
+           res_info->visited = true;
+         }
 
-      /* When not iterating force backedge values to varying.  */
-      visit_stmt (phi, !iterate_phis);
-      if (virtual_operand_p (res))
-       continue;
+       /* When not iterating force backedge values to varying.  */
+       visit_stmt (phi, !iterate_phis);
+       if (virtual_operand_p (res))
+         continue;
 
-      /* Eliminate */
-      /* The interesting case is gcc.dg/tree-ssa/pr22230.c for correctness
-        how we handle backedges and availability.
-        And gcc.dg/tree-ssa/ssa-sccvn-2.c for optimization.  */
-      tree val = res_info->valnum;
-      if (res != val && !iterate && eliminate)
-       {
-         if (tree leader = avail.eliminate_avail (bb, res))
-           {
-             if (leader != res
-                 /* Preserve loop-closed SSA form.  */
-                 && (! lc_phi_nodes
-                     || is_gimple_min_invariant (leader)))
-               {
-                 if (dump_file && (dump_flags & TDF_DETAILS))
-                   {
-                     fprintf (dump_file, "Replaced redundant PHI node "
-                              "defining ");
-                     print_generic_expr (dump_file, res);
-                     fprintf (dump_file, " with ");
-                     print_generic_expr (dump_file, leader);
-                     fprintf (dump_file, "\n");
-                   }
-                 avail.eliminations++;
+       /* Eliminate */
+       /* The interesting case is gcc.dg/tree-ssa/pr22230.c for correctness
+          how we handle backedges and availability.
+          And gcc.dg/tree-ssa/ssa-sccvn-2.c for optimization.  */
+       tree val = res_info->valnum;
+       if (res != val && !iterate && eliminate)
+         {
+           if (tree leader = avail.eliminate_avail (bb, res))
+             {
+               if (leader != res
+                   /* Preserve loop-closed SSA form.  */
+                   && (! lc_phi_nodes
+                       || is_gimple_min_invariant (leader)))
+                 {
+                   if (dump_file && (dump_flags & TDF_DETAILS))
+                     {
+                       fprintf (dump_file, "Replaced redundant PHI node "
+                                "defining ");
+                       print_generic_expr (dump_file, res);
+                       fprintf (dump_file, " with ");
+                       print_generic_expr (dump_file, leader);
+                       fprintf (dump_file, "\n");
+                     }
+                   avail.eliminations++;
 
-                 if (may_propagate_copy (res, leader))
-                   {
-                     /* Schedule for removal.  */
-                     avail.to_remove.safe_push (phi);
-                     continue;
-                   }
-                 /* ???  Else generate a copy stmt.  */
-               }
-           }
-       }
-      /* Only make defs available that not already are.  But make
-        sure loop-closed SSA PHI node defs are picked up for
-        downstream uses.  */
-      if (lc_phi_nodes
-         || res == val
-         || ! avail.eliminate_avail (bb, res))
-       avail.eliminate_push_avail (bb, res);
-    }
+                   if (may_propagate_copy (res, leader))
+                     {
+                       /* Schedule for removal.  */
+                       avail.to_remove.safe_push (phi);
+                       continue;
+                     }
+                   /* ???  Else generate a copy stmt.  */
+                 }
+             }
+         }
+       /* Only make defs available that not already are.  But make
+          sure loop-closed SSA PHI node defs are picked up for
+          downstream uses.  */
+       if (lc_phi_nodes
+           || res == val
+           || ! avail.eliminate_avail (bb, res))
+         avail.eliminate_push_avail (bb, res);
+      }
 
   /* For empty BBs mark outgoing edges executable.  For non-empty BBs
      we do this when processing the last stmt as we have to do this
@@ -6415,6 +6417,13 @@ do_rpo_vn (function *fn, edge entry, bitmap exit_bbs,
       bitmap_set_bit (exit_bbs, EXIT_BLOCK);
     }
 
+  /* Clear EDGE_DFS_BACK on "all" entry edges, RPO order compute will
+     re-mark those that are contained in the region.  */
+  edge_iterator ei;
+  edge e;
+  FOR_EACH_EDGE (e, ei, entry->dest->preds)
+    e->flags &= ~EDGE_DFS_BACK;
+
   int *rpo = XNEWVEC (int, n_basic_blocks_for_fn (fn) - NUM_FIXED_BLOCKS);
   int n = rev_post_order_and_mark_dfs_back_seme
     (fn, entry, exit_bbs, !loops_state_satisfies_p (LOOPS_NEED_FIXUP), rpo);
@@ -6425,6 +6434,18 @@ do_rpo_vn (function *fn, edge entry, bitmap exit_bbs,
   if (!do_region)
     BITMAP_FREE (exit_bbs);
 
+  /* If there are any non-DFS_BACK edges into entry->dest skip
+     processing PHI nodes for that block.  This supports
+     value-numbering loop bodies w/o the actual loop.  */
+  FOR_EACH_EDGE (e, ei, entry->dest->preds)
+    if (e != entry
+       && !(e->flags & EDGE_DFS_BACK))
+      break;
+  bool skip_entry_phis = e != NULL;
+  if (skip_entry_phis && dump_file && (dump_flags & TDF_DETAILS))
+    fprintf (dump_file, "Region does not contain all edges into "
+            "the entry block, skipping its PHIs.\n");
+
   int *bb_to_rpo = XNEWVEC (int, last_basic_block_for_fn (fn));
   for (int i = 0; i < n; ++i)
     bb_to_rpo[rpo[i]] = i;
@@ -6454,7 +6475,9 @@ do_rpo_vn (function *fn, edge entry, bitmap exit_bbs,
          edge e;
          edge_iterator ei;
          FOR_EACH_EDGE (e, ei, bb->preds)
-           gcc_assert (e == entry || (e->src->flags & bb_in_region));
+           gcc_assert (e == entry
+                       || (skip_entry_phis && bb == entry->dest)
+                       || (e->src->flags & bb_in_region));
        }
       for (int i = 0; i < n; ++i)
        {
@@ -6499,7 +6522,7 @@ do_rpo_vn (function *fn, edge entry, bitmap exit_bbs,
          if (e->flags & EDGE_DFS_BACK)
            has_backedges = true;
          e->flags &= ~EDGE_EXECUTABLE;
-         if (iterate || e == entry)
+         if (iterate || e == entry || (skip_entry_phis && bb == entry->dest))
            continue;
          if (bb_to_rpo[e->src->index] > i)
            {
@@ -6532,7 +6555,7 @@ do_rpo_vn (function *fn, edge entry, bitmap exit_bbs,
          edge_iterator ei;
          FOR_EACH_EDGE (e, ei, bb->preds)
            {
-             if (e == entry)
+             if (e == entry || (skip_entry_phis && bb == entry->dest))
                continue;
              int max_rpo = MAX (rpo_state[i].max_rpo,
                                 rpo_state[bb_to_rpo[e->src->index]].max_rpo);
@@ -6621,7 +6644,7 @@ do_rpo_vn (function *fn, edge entry, bitmap exit_bbs,
        todo |= process_bb (avail, bb,
                            rpo_state[idx].visited != 0,
                            rpo_state[idx].iterate,
-                           iterate, eliminate, do_region, exit_bbs);
+                           iterate, eliminate, do_region, exit_bbs, false);
        rpo_state[idx].visited++;
 
        /* Verify if changed values flow over executable outgoing backedges
@@ -6719,8 +6742,10 @@ do_rpo_vn (function *fn, edge entry, bitmap exit_bbs,
          edge e;
          FOR_EACH_EDGE (e, ei, bb->preds)
            if (!(e->flags & EDGE_EXECUTABLE)
-               && !rpo_state[bb_to_rpo[e->src->index]].visited
-               && rpo_state[bb_to_rpo[e->src->index]].max_rpo >= (int)idx)
+               && (bb == entry->dest
+                   || (!rpo_state[bb_to_rpo[e->src->index]].visited
+                       && (rpo_state[bb_to_rpo[e->src->index]].max_rpo
+                           >= (int)idx))))
              {
                if (dump_file && (dump_flags & TDF_DETAILS))
                  fprintf (dump_file, "Cannot trust state of predecessor "
@@ -6731,7 +6756,8 @@ do_rpo_vn (function *fn, edge entry, bitmap exit_bbs,
 
          nblk++;
          todo |= process_bb (avail, bb, false, false, false, eliminate,
-                             do_region, exit_bbs);
+                             do_region, exit_bbs,
+                             skip_entry_phis && bb == entry->dest);
          rpo_state[idx].visited++;
 
          FOR_EACH_EDGE (e, ei, bb->succs)
@@ -6813,7 +6839,9 @@ do_rpo_vn (function *fn, edge entry, bitmap exit_bbs,
 }
 
 /* Region-based entry for RPO VN.  Performs value-numbering and elimination
-   on the SEME region specified by ENTRY and EXIT_BBS.  */
+   on the SEME region specified by ENTRY and EXIT_BBS.  If ENTRY is not
+   the only edge into the region at ENTRY->dest PHI nodes in ENTRY->dest
+   are not considered.  */
 
 unsigned
 do_rpo_vn (function *fn, edge entry, bitmap exit_bbs)