[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