------- Comment #9 from zadeck at naturalbridge dot com 2007-06-26 23:01 ------- Subject: Re: [Bug target/32437] ICE in df_refs_verify, at df-scan.c:4058
This patch fixes a problem introduced with the patch to fix pr32437. In that patch we introduced recursion in dce:deleteable_insn_p in order to properly process UNSPECs that occur inside of PARALLELS. When we did that, we went too far and introduced problems with CLOBBERs and USEs that occur inside of PARALLELs. This patch fixes that. This patch has the side effect of making the bug reported in pr32481 hide, but the bug is still there. The underlying problem is that there is a rarely executed path in combine:try_combine that does not undo the changes it makes when the transformation fails. We are waiting to talk to iant (or any other combine expert) to determine if the bug is that it is not undoing what it needs to or that we need to rescan the changes because that change is not supposed to be undone. Our attempts to make the undo work on our own have only resulted in death and destruction. Kenny 2007-06-26 Kenneth Zadeck <[EMAIL PROTECTED]> PR middle-end/32481 *dce.c (deletable_insn_p): Add extra parameter to indicate top level. Restructure to process USE and CLOBBER differently. (prescan_insns_for_dce): Add extra parameter. Index: dce.c =================================================================== --- dce.c (revision 126045) +++ dce.c (working copy) @@ -59,15 +59,54 @@ static bitmap_obstack dce_tmp_bitmap_obs static sbitmap marked = NULL; /* Return true if INSN with BODY is a normal instruction that can be - deleted by the DCE pass. */ + deleted by the DCE pass. STRICT_TOP_LEVEL is false if this is a + recursive call. See the note above the CLOBBER case */ static bool -deletable_insn_p (rtx insn, rtx body, bool fast) +deletable_insn_p (rtx insn, rtx body, bool fast, bool strict_top_level) { rtx x; + + if (!NONJUMP_INSN_P (insn)) + return false; + switch (GET_CODE (body)) { + case CLOBBER: + /* A CLOBBER at the strict_top_level (i.e. not inside of a + parallel) is different than one that is inside of a parallel. + Strict_top_level CLOBBERS are put there for some possibly + magic purpose. + + However, a clobber inside of a parallel means that this part + of the insn just messes with a register while the real work + is done by the other arms. These clobbers do not effect our + ability to delete the insn. */ + if (strict_top_level) + { + if (fast) + { + /* A CLOBBER of a dead pseudo register serves no purpose. + That is not necessarily true for hard registers until + after reload. */ + x = XEXP (body, 0); + return REG_P (x) && (!HARD_REGISTER_P (x) || reload_completed); + } + else + /* Because of the way that use-def chains are built, it is not + possible to tell if the clobber is dead because it can + never be the target of a use-def chain. */ + return false; + } + break; + case USE: + /* Strict top level uses can never be deleted. All others are + noise. */ + if (strict_top_level) + return false; + break; + case PREFETCH: case TRAP_IF: /* The UNSPEC case was added here because the ia-64 claims that @@ -79,42 +118,27 @@ deletable_insn_p (rtx insn, rtx body, bo case UNSPEC: return false; - case CLOBBER: - if (fast) - { - /* A CLOBBER of a dead pseudo register serves no purpose. - That is not necessarily true for hard registers until - after reload. */ - x = XEXP (body, 0); - return REG_P (x) && (!HARD_REGISTER_P (x) || reload_completed); - } - else - /* Because of the way that use-def chains are built, it is not - possible to tell if the clobber is dead because it can - never be the target of a use-def chain. */ - return false; - case PARALLEL: { int i; + gcc_assert (strict_top_level); for (i = XVECLEN (body, 0) - 1; i >= 0; i--) - if (!deletable_insn_p (insn, XVECEXP (body, 0, i), fast)) + if (!deletable_insn_p (insn, XVECEXP (body, 0, i), fast, false)) return false; - return true; + break; } default: - if (!NONJUMP_INSN_P (insn)) - return false; - - if (volatile_insn_p (body)) - return false; - - if (flag_non_call_exceptions && may_trap_p (body)) - return false; - - return true; + break; } + + if (volatile_insn_p (body)) + return false; + + if (flag_non_call_exceptions && may_trap_p (body)) + return false; + + return true; } @@ -369,7 +393,7 @@ prescan_insns_for_dce (bool fast) rtx note = find_reg_note (insn, REG_LIBCALL_ID, NULL_RTX); if (note) mark_libcall (insn, fast); - else if (deletable_insn_p (insn, PATTERN (insn), fast)) + else if (deletable_insn_p (insn, PATTERN (insn), fast, true)) mark_nonreg_stores (PATTERN (insn), insn, fast); else mark_insn (insn, fast); -- http://gcc.gnu.org/bugzilla/show_bug.cgi?id=32481