------- Comment #3 from jakub at gcc dot gnu dot org 2010-02-15 17:06 ------- The problem here is missing INSN location on insn generated by insert_restore with -g (without -g it has one). Before IRA we have: (note 26 25 27 5 [bb 5] NOTE_INSN_BASIC_BLOCK)
(call_insn 27 26 28 5 pr42918.c:14 (call (mem:QI (symbol_ref:DI ("fv") [flags 0x41] <function_decl 0x7feab75d6b00 fv>) [0 S1 A8]) (const_int 0 [0x0])) 638 {*call_0} (nil) (nil)) (note 28 27 30 5 ("lab") NOTE_INSN_DELETED_LABEL 3) (debug_insn 30 28 34 5 (var_location:SI i (reg/v:SI 59 [ i ])) -1 (nil)) at the end of a basic block (obviously with -g0 the debug_insn is missing). Now save_call_clobbered_regs restores all still saved regs at the end of a basic block, when the bb doesn't end with a jump, it restores after the last insn mentioned in reload_insn_chain for that bb, when it is a jump, then before it. As DEBUG_INSNs are included in reload_insn_chain, that is for -g after the DEBUG_INSN (and as insert_restore inserts after that insn, the insn has no location as DEBUG_INSN has no location either). For -g0 that is after the call insn, which has location and thus the restore insn gets the location of the call. Although emit_insn_after ignores DEBUG_INSNs, it doesn't ignore notes and there is this deleted label note in between. Changing save_call_clobbered_regs to restore all regs after the last non-debug insn in a bb wouldn't work well, as the restore insn invalidates the hard regs that could still hold something in the debug insn. I guess we could remember the INSN_LOCATOR of the last non-debug insn in the reload chain and use emit_insn_after_setloc in insert_restore (going to test it now), but wonder whether the fact that the deleted label is now after the hard reg restore insn in the -g0 case and before it in the -g case couldn't introduce other -fcompare-debug differences on other testcases. -- http://gcc.gnu.org/bugzilla/show_bug.cgi?id=42918