Richard Guenther wrote:
On Sun, Sep 20, 2009 at 9:38 AM, Maxim Kuvyrkov <ma...@codesourcery.com> wrote:
...
This code uses eliminate_regs(), which implicitly assumes reload_completed as it uses reg_eliminate[], which assumes that frame_pointer_needed is properly set, which happens in ira.c. However, in some cases this piece of based_loc_descr() can be reached during inlining pass (see backtrace below). When called before reload, eliminate_regs() may return an inconsistent result which is why the assert in based_loc_descr() fails. In the particular testcase I'm investigating, frame_pointer_needed is 0 (initial value), but eliminate_regs returns stack_pointer_rtx because it is guided by reg_eliminate information from the previous function which had frame_pointer_needed set to 1.
...
I think you should avoid calling eliminate_regs for DECL_ABSTRACT current_function_decl. That should cover the inliner path.
Thanks for the insight. Do you mean something like the attached patch? -- Maxim
Index: gcc/dwarf2out.c =================================================================== --- gcc/dwarf2out.c (revision 261914) +++ gcc/dwarf2out.c (working copy) @@ -9862,8 +9862,11 @@ based_loc_descr (rtx reg, HOST_WIDE_INT /* We only use "frame base" when we're sure we're talking about the post-prologue local stack frame. We do this by *not* running register elimination until this point, and recognizing the special - argument pointer and soft frame pointer rtx's. */ - if (reg == arg_pointer_rtx || reg == frame_pointer_rtx) + argument pointer and soft frame pointer rtx's. + We might get here during the inlining pass (DECL_ABSTRACT is true then), + so don't try eliminating registers in such a case. */ + if (!DECL_ABSTRACT (current_function_decl) + && (reg == arg_pointer_rtx || reg == frame_pointer_rtx)) { rtx elim = eliminate_regs (reg, VOIDmode, NULL_RTX); @@ -12224,6 +12227,9 @@ compute_frame_pointer_to_fb_displacement offset += ARG_POINTER_CFA_OFFSET (current_function_decl); #endif + /* Make sure we don't try eliminating registers in abstract function. */ + gcc_assert (!DECL_ABSTRACT (current_function_decl)); + elim = eliminate_regs (reg, VOIDmode, NULL_RTX); if (GET_CODE (elim) == PLUS) { Index: gcc/reload1.c =================================================================== --- gcc/reload1.c (revision 261914) +++ gcc/reload1.c (working copy) @@ -2867,6 +2867,7 @@ eliminate_regs_1 (rtx x, enum machine_mo rtx eliminate_regs (rtx x, enum machine_mode mem_mode, rtx insn) { + gcc_assert (reload_in_progress || reload_completed); return eliminate_regs_1 (x, mem_mode, insn, false); }