https://gcc.gnu.org/bugzilla/show_bug.cgi?id=65233
--- Comment #22 from Richard Biener <rguenth at gcc dot gnu.org> --- The error is to do anything that possibly relies on an up-to-date SSA web when need_ssa_update () is true. In fact the polymorphic call code walks to the PHI which is already dead (it's block is gone). So while we don't ICE we certainly look at released stuff still. I remember we had name_registered_for_update_p guards in tree-cfgcleaup.c code, like on the 4.5 branch in cleanup_control_expr_graph: case GIMPLE_COND: { tree lhs = gimple_cond_lhs (stmt); tree rhs = gimple_cond_rhs (stmt); /* For conditions try harder and lookup single-argument PHI nodes. Only do so from the same basic-block though as other basic-blocks may be dead already. */ if (TREE_CODE (lhs) == SSA_NAME && !name_registered_for_update_p (lhs)) { gimple def_stmt = SSA_NAME_DEF_STMT (lhs); the issue with needing cfg-cleanup before update-ssa is unreachable blocks don't play well with computing dominators which update-ssa needs. But we also obviously cannot fix SSA form in this case without removing unreachable blocks first. And if we do that, and then fixup SSA form that will still fail because threading _did_ fail to update the PHI node in BB 13 - where's the definition of SR33_23 supposed to be? I see that it is later updated to be SR.33_45. It's also odd that it chose to duplicate bb 30 at all (to bb 48). I see no good reason to do that. I think a better workaround for the bug is Index: ipa-polymorphic-call.c =================================================================== --- ipa-polymorphic-call.c (revision 221149) +++ ipa-polymorphic-call.c (working copy) @@ -81,6 +81,8 @@ along with GCC; see the file COPYING3. #include "data-streamer.h" #include "lto-streamer.h" #include "streamer-hooks.h" +#include "tree-ssa-operands.h" +#include "tree-into-ssa.h" /* Return true when TYPE contains an polymorphic type and thus is interesting for devirtualization machinery. */ @@ -804,7 +806,7 @@ walk_ssa_copies (tree op, hash_set<tree> STRIP_NOPS (op); while (TREE_CODE (op) == SSA_NAME && !SSA_NAME_IS_DEFAULT_DEF (op) - && SSA_NAME_DEF_STMT (op) + && !name_registered_for_update_p (op) && (gimple_assign_single_p (SSA_NAME_DEF_STMT (op)) || gimple_code (SSA_NAME_DEF_STMT (op)) == GIMPLE_PHI)) { @@ -835,10 +837,7 @@ walk_ssa_copies (tree op, hash_set<tree> { gimple phi = SSA_NAME_DEF_STMT (op); - if (gimple_phi_num_args (phi) > 2 - /* We can be called while cleaning up the CFG and can - have empty PHIs about to be removed. */ - || gimple_phi_num_args (phi) == 0) + if (gimple_phi_num_args (phi) > 2) goto done; if (gimple_phi_num_args (phi) == 1) op = gimple_phi_arg_def (phi, 0); I'm going to bootstrap & test this. Still the block duplication during threading that happens looks odd to me.