[Committed] PR 27802: Handle noreturn functions in reg-stack
Roger Sayle
roger@eyesopen.com
Fri Jun 16 13:38:00 GMT 2006
The following patch resolves the P1 regression PR middle-end/27802
which is an ICE-on-valid in reg-stack.c on x86. I believe there
are two middle-end problems here; the major one addressed below
is that reg-stack.c can't currently handle noreturn functions that
have floating point return types, i.e. reg-stack stack doesn't know
what to do with the stack registers that would otherwise be returned
from the noreturn call. Currently it attempts to insert pop insns
after the no-return call, upseting cfg_verify by producing basic
blocks containing control flow instructions.
The second lesser issue is the fact that in the original testcase, GCC
assumes "double longjmp(void);" is a noreturn function. Normally, the
recognition of standard functions is handled by the middle-end's builtins
mechanism, that tests whether the arguments are compatible before
"recognizing" c90/c99 functions and assuming their semantics.
Unfortunately, "longjmp" has argument types that are O/S specific,
so GCC can't match it via the usual mechanisms, and instead performs
strcmp on the identifier. I think this mechanism needs to be made more
robust, for example, checking that longjmp/siglongjmp are declared to
have a "void" return type. Not quite sure the best way to do that yet.
The following patch has been tested on i686-pc-linux-gnu with a full
"make bootstrap", all default languages including Ada, and regression
tested with a top-level "make -k check" with no new failures.
Committed to mainline as revision 114721. I'll backport it to
the gcc-4_1-branch shortly.
2006-06-16 Roger Sayle <roger@eyesopen.com>
PR middle-end/27802
* reg-stack.c (subst_stack_regs): Handle noreturn function calls
that (would) return their results in stack registers.
* gcc.dg/pr27802-1.c: New test case.
Index: reg-stack.c
===================================================================
*** reg-stack.c (revision 114659)
--- reg-stack.c (working copy)
*************** subst_stack_regs (rtx insn, stack regsta
*** 2282,2287 ****
--- 2282,2297 ----
if (NOTE_P (insn) || INSN_DELETED_P (insn))
return control_flow_insn_deleted;
+ /* If this a noreturn call, we can't insert pop insns after it.
+ Instead, reset the stack state to empty. */
+ if (CALL_P (insn)
+ && find_reg_note (insn, REG_NORETURN, NULL))
+ {
+ regstack->top = -1;
+ CLEAR_HARD_REG_SET (regstack->reg_set);
+ return control_flow_insn_deleted;
+ }
+
/* If there is a REG_UNUSED note on a stack register on this insn,
the indicated reg must be popped. The REG_UNUSED note is removed,
since the form of the newly emitted pop insn references the reg,
/* Noreturn functions returning FP types used to confuse reg-stack on x86. */
/* { dg-do compile } */
/* { dg-options "-O2" } */
double bar1() __attribute__((noreturn));
void foo1() { bar1(); }
double bar2() __attribute__((noreturn));
double foo2() { return bar2(); }
void bar3() __attribute__((noreturn));
double foo3() { bar3(); }
double bar4() __attribute__((noreturn));
double foo4() { bar4(); }
Roger
--
More information about the Gcc-patches
mailing list