In this PR we run into the issue that releasing SSA names from
FRE/PRE elimination corrupts the VN lattice and thus the VN lookup
we perform for removing redudnant stores ICEs.  The patch works
around the particular case by making unreachable code detection
in SCCVN more optimistic by ignoring backedges during reachability
computation and by not doing any elimination on unreachable blocks.

I still have to think about a "proper" fix to the underlying issue
(propagate_value_into_stmt updating stmts on our back).

Bootstrap and regtest running on x86_64-unknown-linux-gnu.

Richard.

2014-05-19  Richard Biener  <rguent...@suse.de>

        PR tree-optimization/61221
        * tree-ssa-pre.c (eliminate_dom_walker::before_dom_children):
        Do nothing for unreachable blocks.
        * tree-ssa-sccvn.c (cond_dom_walker::before_dom_children):
        Improve unreachability detection.

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

Index: gcc/tree-ssa-pre.c
===================================================================
*** gcc/tree-ssa-pre.c  (revision 210608)
--- gcc/tree-ssa-pre.c  (working copy)
*************** eliminate_dom_walker::before_dom_childre
*** 4010,4015 ****
--- 4010,4024 ----
    /* Mark new bb.  */
    el_avail_stack.safe_push (NULL_TREE);
  
+   /* If this block is not reachable do nothing.  */
+   edge_iterator ei;
+   edge e;
+   FOR_EACH_EDGE (e, ei, b->preds)
+     if (e->flags & EDGE_EXECUTABLE)
+       break;
+   if (!e)
+     return;
+ 
    for (gsi = gsi_start_phis (b); !gsi_end_p (gsi);)
      {
        gimple stmt, phi = gsi_stmt (gsi);
Index: gcc/tree-ssa-sccvn.c
===================================================================
*** gcc/tree-ssa-sccvn.c        (revision 210608)
--- gcc/tree-ssa-sccvn.c        (working copy)
*************** cond_dom_walker::before_dom_children (ba
*** 4175,4185 ****
    if (fail)
      return;
  
!   /* If any of the predecessor edges are still marked as possibly
!      executable consider this block reachable.  */
    bool reachable = bb == ENTRY_BLOCK_PTR_FOR_FN (cfun);
    FOR_EACH_EDGE (e, ei, bb->preds)
!     reachable |= (e->flags & EDGE_EXECUTABLE);
  
    /* If the block is not reachable all outgoing edges are not
       executable.  */
--- 4175,4187 ----
    if (fail)
      return;
  
!   /* If any of the predecessor edges that do not come from blocks dominated
!      by us are still marked as possibly executable consider this block
!      reachable.  */
    bool reachable = bb == ENTRY_BLOCK_PTR_FOR_FN (cfun);
    FOR_EACH_EDGE (e, ei, bb->preds)
!     if (!dominated_by_p (CDI_DOMINATORS, e->src, bb))
!       reachable |= (e->flags & EDGE_EXECUTABLE);
  
    /* If the block is not reachable all outgoing edges are not
       executable.  */
Index: gcc/testsuite/gcc.dg/torture/pr61221.c
===================================================================
*** gcc/testsuite/gcc.dg/torture/pr61221.c      (revision 0)
--- gcc/testsuite/gcc.dg/torture/pr61221.c      (working copy)
***************
*** 0 ****
--- 1,32 ----
+ /* { dg-do compile } */
+ 
+ void __assert_fail (void);
+ 
+ int **a, b, c, e, *j;
+ short *d, **f;
+ 
+ int *
+ foo ()
+ {
+   *a = j;
+   if (!(1 & e)) 
+     __assert_fail ();
+   return 0;
+ }
+ 
+ void
+ bar ()
+ {
+   int *g = &b;
+   short **h = &d;
+   if ((f = &d) != h)
+     for (; b;)
+       {
+       int i = 1;
+       if (i)
+         g = foo ();
+       c = 0;
+       }
+   if (!g)
+     __assert_fail ();
+ }

Reply via email to