------- 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

Reply via email to