https://gcc.gnu.org/bugzilla/show_bug.cgi?id=116460

--- Comment #14 from Richard Biener <rguenth at gcc dot gnu.org> ---
(In reply to Andrew Pinski from comment #13)
> (In reply to Andrew Pinski from comment #8)
> > ./a.ltrans6.ltrans.212t.forwprop4
> > 
> > Removing dead stmt noDataCandVec$_M_start_888 = PHI <_1783(176), _577(186)>
> > ...
> > Removing dead stmt:_598 = _888 + 16;
> > 
> > So it looks like we remove the statement defining _888 and then removing the
> > use.
> > The removal of _888 happens directly from forwprop while _598 definition
> > removal comes from simple_dce_from_worklist .
> > 
> > The ICE happens because the ssa name _888 has already been freed so the type
> > is null (and not in this case a pointer) since this was originally a pointer
> > plus.
> > 
> > Trying to reduce this further.
> 
> _888 definition is from a BB which is going to be removed so we should not
> need to mark its uses as being needed for dce worklist. But I am not sure
> how to detect that case.

forwprop shouldn't remove _888 if there's a use left.  When adding
simple_dce_from_worklist, did you remove some manual stmt removal
(adding to to_remove)?  Having both is a bit ugly (see also
remove_prop_source_from_use), but the sets need to be separate to
avoid interactions like this.

Ah, we have

          /* Substitute from our lattice.  We need to do so only once.  */
          bool substituted_p = false;
          use_operand_p usep; 
          ssa_op_iter iter;
          FOR_EACH_SSA_USE_OPERAND (usep, stmt, iter, SSA_OP_USE)
            {
              tree use = USE_FROM_PTR (usep);
              tree val = fwprop_ssa_val (use);
              if (val && val != use)
                {
                  if (!is_gimple_debug (stmt))
                    bitmap_set_bit (simple_dce_worklist, SSA_NAME_VERSION
(use)); 

I think that's problematic iff 'use' as definition is already in to_remove.

Note to_remove also removes in "proper" order for debug stmt generation
while simple_dce_from_worklist doesn't iff the DCEd bits are not
independent.

OK, so the issue is that when we add

noDataCandVec$_M_start_3 = PHI <_158(9), _51(12)>

to to_remove the uses are

noDataCandVec$_M_start_3 : -->5 uses.
# DEBUG __i$_M_current => noDataCandVec$_M_start_3 + 1
_56 = noDataCandVec$_M_finish_75 - noDataCandVec$_M_start_3;
ivtmp.163_15 = (unsigned long) noDataCandVec$_M_start_3;
_108 = noDataCandVec$_M_start_3 + 15;
# DEBUG __first$_M_current => noDataCandVec$_M_start_3
_57 = noDataCandVec$_M_start_3 + 16;
# DEBUG __first => noDataCandVec$_M_start_3
if (noDataCandVec$_M_start_3 != noDataCandVec$_M_finish_75)
# DEBUG __first => noDataCandVec$_M_start_3
# DEBUG __first => noDataCandVec$_M_start_3
# DEBUG noDataCandVec$_M_start => noDataCandVec$_M_start_3

and _3 is in BB 13 while the use in _57 = noDataCandVec$_M_start_3 + 16 is
in BB 15 and we are not processing this block as it is compute dead.
So the uses in dead stmts are not replaced which is what confuses
simple_dce_from_worklist.

Note it's _57 that ends up on the worklist somehow even though it's def is in
a dead BB(!?).  That's from

              auto_vec<tree, 8> uses;
              FOR_EACH_SSA_USE_OPERAND (usep, stmt, iter, SSA_OP_USE)
                if (uses.space (1))
                  uses.quick_push (USE_FROM_PTR (usep));

              if (fold_stmt (&gsi, fwprop_ssa_val, simple_dce_worklist))  

on

if (noDataCandVec$_M_start_3 != noDataCandVec$_M_finish_75)

in BB 19 which we do process.  That's because we enter a loop and handle
those conservatively with respect to reachability.

We can improved this as noted in the comment:

              /* With dominators we could improve backedge handling
                 when e->src is dominated by bb.  But for irreducible
                 regions we have to take all backedges conservatively.
                 We can handle single-block cycles as we know the
                 dominator relationship here.  */

but the latent issue remains.  I'm not sure I fully got it as a simple
patch like below doesn't fix it.

diff --git a/gcc/tree-ssa-forwprop.cc b/gcc/tree-ssa-forwprop.cc
index 9595555138c..cd3e68bd226 100644
--- a/gcc/tree-ssa-forwprop.cc
+++ b/gcc/tree-ssa-forwprop.cc
@@ -4143,9 +4144,18 @@ pass_forwprop::execute (function *fun)
        }
       gimple_stmt_iterator gsi = gsi_for_stmt (stmt);
       if (gimple_code (stmt) == GIMPLE_PHI)
-       remove_phi_node (&gsi, true);
+       {
+         bitmap_clear_bit (simple_dce_worklist,
+                           SSA_NAME_VERSION (gimple_phi_result (stmt)));
+         remove_phi_node (&gsi, true);
+       }
       else
        {
+         def_operand_p def_p;
+         ssa_op_iter op_iter;
+         FOR_EACH_SSA_DEF_OPERAND (def_p, stmt, op_iter, SSA_OP_DEF)
+           bitmap_clear_bit (simple_dce_worklist,
+                             SSA_NAME_VERSION (DEF_FROM_PTR (def_p)));
          unlink_stmt_vdef (stmt);
          gsi_remove (&gsi, true);
          release_defs (stmt);

I'm testing the following which makes the issue latent.

diff --git a/gcc/tree-ssa-forwprop.cc b/gcc/tree-ssa-forwprop.cc
index 9595555138c..070299255f1 100644
--- a/gcc/tree-ssa-forwprop.cc
+++ b/gcc/tree-ssa-forwprop.cc
@@ -3536,12 +3536,11 @@ pass_forwprop::execute (function *fun)
       FOR_EACH_EDGE (e, ei, bb->preds)
        {
          if ((e->flags & EDGE_EXECUTABLE)
-             /* With dominators we could improve backedge handling
-                when e->src is dominated by bb.  But for irreducible
-                regions we have to take all backedges conservatively.
-                We can handle single-block cycles as we know the
-                dominator relationship here.  */
-             || bb_to_rpo[e->src->index] > i)
+             /* We can handle backedges in natural loops correctly but
+                for irreducible regions we have to take all backedges
+                conservatively when we did not visit the source yet.  */
+             || (bb_to_rpo[e->src->index] > i
+                 && !dominated_by_p (CDI_DOMINATORS, e->src, e->dest)))
            {
              any = true;
              break;

Reply via email to