-----BEGIN PGP SIGNED MESSAGE----- Hash: SHA1 Updated based on some comments from Bernd; specifically the other use of delete_dead_insn has been removed.
WRT the assembly differences on MIPS Bernd referred to; what ultimately caused this problem were two dead insns that had been previously eliminated by reload were still in the insn stream and inhibited an if-conversion which resulted in slightly different assembly code, but shouldn't have had any significant impact on the performance or size of the resulting code. The dead insns were deleted by the post-reload DCE pass (which obviously runs after post-reload if conversion). If we really wanted to get those insns out of the stream, we could flag when reload deleted insns which might result in dead code remaining in the stream, then conditionally run DCE immediately after reload. I didn't think this was worth doing right now, but if someone objects I can certainly look into it. Bootstrapped and regression tested on x86_64-unknown-linux-gnu. Jeff -----BEGIN PGP SIGNATURE----- Version: GnuPG v1.4.11 (GNU/Linux) Comment: Using GnuPG with Fedora - http://enigmail.mozdev.org/ iQEcBAEBAgAGBQJN3+RCAAoJEBRtltQi2kC7qUMH/3Z8NB8bogEnVvS7qF6eubu0 UNWp2HzJ/QnvxgKQiJUBar/kOF3y20kl2oZpqIoPVea2TqmeZ/lfuS1+lzWWxC/t HGvjBWfkA60DkcDxFmHn0TadoqL11eAWEzsRRf/HfEn6I3rnrO3vP0RR3X8Dtiqe qeFf8HVY8ysQoaFTyaiMLLo7yePmvlVy+HTsg+s3F0Yvg18P2WoJjpM/EY2y/tUR QmIcFi8q4Q92YsfBpjweY6NyqepKrATAZT+CcFdc7GFvfa5TZQj9gGhWqPHiHQ5w 3c8RmKbaGEWhPSjIgmcqtY/FpY2CoRDn2BMosr8N4F0FMN2PkQlU8E7hTE2V6eM= =UeKy -----END PGP SIGNATURE-----
PR middle-end/48770 * ira.c (update_equiv_regs): Update comment. * reload1.c (reload): Don't call delete_dead_insn to delete insns which create equivalences. (eliminate_regs_in_insn): Likewise. (delete_dead_insn): Remove. PR middle-end/48770 * gcc.dg/pr48770.c: New test. Index: testsuite/gcc.dg/pr48770.c =================================================================== *** testsuite/gcc.dg/pr48770.c (revision 0) --- testsuite/gcc.dg/pr48770.c (revision 0) *************** *** 0 **** --- 1,21 ---- + /* { dg-do run } */ + /* { dg-options "-O -fprofile-arcs -fPIC -fno-dce -fno-forward-propagate" } */ + + int test_goto2 (int f) + { + int i; + for (i = 0; ({_Bool a = i < 10;a;}); i++) + { + if (i == f) + goto lab2; + } + return 4; + lab2: + return 8; + } + + int main () + { + test_goto2 (30); + return 0; + } Index: ira.c =================================================================== *** ira.c (revision 174066) --- ira.c (working copy) *************** update_equiv_regs (void) *** 2842,2848 **** If we don't have a REG_EQUIV note, see if this insn is loading a register used only in one basic block from a MEM. If so, and the MEM remains unchanged for the life of the register, add a REG_EQUIV ! note. */ note = find_reg_note (insn, REG_EQUIV, NULL_RTX); --- 2842,2848 ---- If we don't have a REG_EQUIV note, see if this insn is loading a register used only in one basic block from a MEM. If so, and the MEM remains unchanged for the life of the register, add a REG_EQUIV ! note, this creates a block local equivalence. */ note = find_reg_note (insn, REG_EQUIV, NULL_RTX); Index: reload1.c =================================================================== *** reload1.c (revision 174066) --- reload1.c (working copy) *************** static void delete_caller_save_insns (vo *** 356,362 **** static void spill_failure (rtx, enum reg_class); static void count_spilled_pseudo (int, int, int); - static void delete_dead_insn (rtx); static void alter_reg (int, int, bool); static void set_label_offsets (rtx, rtx, int); static void check_eliminable_occurrences (rtx); --- 356,361 ---- *************** reload (rtx first, int global) *** 1011,1021 **** mark_elimination (ep->from, ep->to); /* If a pseudo has no hard reg, delete the insns that made the equivalence. ! If that insn didn't set the register (i.e., it copied the register to ! memory), just delete that insn instead of the equivalencing insn plus ! anything now dead. If we call delete_dead_insn on that insn, we may ! delete the insn that actually sets the register if the register dies ! there and that is incorrect. */ for (i = FIRST_PSEUDO_REGISTER; i < max_regno; i++) { --- 1010,1024 ---- mark_elimination (ep->from, ep->to); /* If a pseudo has no hard reg, delete the insns that made the equivalence. ! We used to recursively delete anything else now dead. That is incorrect ! if that insn didn't set the register (i.e., it copied the register to ! memory); it is also incorrect for a block local equivalence as the memory ! address may refer to another pseudo which still needs proper ! initialization. ! ! That code predated running dead code elimination after reload, so rather ! that trying to identify all the dead code here (and get it wrong), just ! delete the equivalencing insn and let DCE do its job. */ for (i = FIRST_PSEUDO_REGISTER; i < max_regno; i++) { *************** reload (rtx first, int global) *** 1034,1041 **** if (NOTE_P (equiv_insn) || can_throw_internal (equiv_insn)) ; - else if (reg_set_p (regno_reg_rtx[i], PATTERN (equiv_insn))) - delete_dead_insn (equiv_insn); else SET_INSN_DELETED (equiv_insn); } --- 1037,1042 ---- *************** spill_failure (rtx insn, enum reg_class *** 2114,2140 **** } } - /* Delete an unneeded INSN and any previous insns who sole purpose is loading - data that is dead in INSN. */ - - static void - delete_dead_insn (rtx insn) - { - rtx prev = prev_active_insn (insn); - rtx prev_dest; - - /* If the previous insn sets a register that dies in our insn, delete it - too. */ - if (prev && GET_CODE (PATTERN (prev)) == SET - && (prev_dest = SET_DEST (PATTERN (prev)), REG_P (prev_dest)) - && reg_mentioned_p (prev_dest, PATTERN (insn)) - && find_regno_note (insn, REG_DEAD, REGNO (prev_dest)) - && ! side_effects_p (SET_SRC (PATTERN (prev)))) - delete_dead_insn (prev); - - SET_INSN_DELETED (insn); - } - /* Modify the home of pseudo-reg I. The new home is present in reg_renumber[I]. --- 2115,2120 ---- *************** eliminate_regs_in_insn (rtx insn, int re *** 3319,3325 **** process it since it won't be used unless something changes. */ if (replace) { ! delete_dead_insn (insn); return 1; } val = 1; --- 3299,3305 ---- process it since it won't be used unless something changes. */ if (replace) { ! SET_INSN_DELETED (insn); return 1; } val = 1;