This is the mail archive of the
mailing list for the GCC project.
[RFC patch] Use indirect jumps for nonlocal goto's
- From: "John David Anglin" <dave at hiauly1 dot hia dot nrc dot ca>
- To: gcc-patches at gcc dot gnu dot org
- Date: Tue, 8 Jun 2004 16:34:33 -0400 (EDT)
- Subject: [RFC patch] Use indirect jumps for nonlocal goto's
The tree-ssa merge introduced a number of new fails on
hppa2.0w-hp-hpux* involving nested functions. See
In looking at the failure of gcc.c-torture/execute/920428-2.c,
I found that the label used for the nonlocal goto that returns
from the nested function is now loaded in the nested function.
Previously, the address of this label was passed to the nested
function on the stack.
The initial RTL uses an indirect jump for a nonlocal goto on
the PA. However, now that this label is loaded directly in
the nested function, cse changes the indirect jump to a direct
jump. As far as I can tell, there is no way for the backend
to prevent this conversion.
Using a direct jump on the PA doesn't work on the SOM port.
Direct jumps to labels external to a function are interpreted
as calls and they must be made to defined entry points. In
920428-2.c, the linker silently changes the nonlocal goto
jump from f to label l1 to a jump to the beginning of s.
The treatment of direct jumps as calls could result in a
variety of stubs being inserted in the jump path by the
linker. These stubs use the registers allowed in calls.
However, these registers may not be usable in a nonlocal goto.
Use of a direct jump also might mess up the unwind info.
Finally, using a label external to the function currently
being compiled can cause an ICE in insn_current_reference_address.
Looking at the documentation for "jump" and "indirect_jump" in
md.texi, there isn't any distinction on the capabilities of these
two jumps. However, it seems conventional to use indirect jumps
for nonlocal jumps.
The enclosed patch implements a change along these lines. It would
be possible to check for a nonlocal goto in the PA jump pattern and
emit an indirect jump from there. However, we don't have a scratch
register to load the label in that case, so we would have to play
games with scratch locations on the stack or write a register
scrounger. The result would be less efficient.
The change has been tested on hppa2.0w-hp-hpux11.11. It fixes
all the nested function failures in the testsuite but I might have
missed some places where it's possible for indirect to direct
jump conversion to occur.
Ok for main?
J. David Anglin email@example.com
National Research Council of Canada (613) 990-0752 (FAX: 952-6602)
2004-06-08 John David Anglin <firstname.lastname@example.org>
* cse.c (cse_insn): Don't convert an indirect jump to a direct jump
if it has a REG_NON_LOCAL_GOTO note.
* combine.c (cant_combine_insn_p): Likewise.
RCS file: /cvs/gcc/gcc/gcc/cse.c,v
retrieving revision 1.301
diff -u -3 -p -r1.301 cse.c
--- cse.c 25 May 2004 12:04:15 -0000 1.301
+++ cse.c 7 Jun 2004 20:35:33 -0000
@@ -5271,8 +5271,10 @@ cse_insn (rtx insn, rtx libcall_insn)
/* If this was an indirect jump insn, a known label will really be
- cheaper even though it looks more expensive. */
- if (dest == pc_rtx && src_const && GET_CODE (src_const) == LABEL_REF)
+ cheaper even though it looks more expensive. However, the
+ indirect form must be left for a nonlocal goto. */
+ if (dest == pc_rtx && src_const && GET_CODE (src_const) == LABEL_REF
+ && !find_reg_note (insn, REG_NON_LOCAL_GOTO, 0))
src_folded = src_const, src_folded_cost = src_folded_regcost = -1;
/* Terminate loop when replacement made. This must terminate since
RCS file: /cvs/gcc/gcc/gcc/combine.c,v
retrieving revision 1.432
diff -u -3 -p -r1.432 combine.c
--- combine.c 5 Jun 2004 07:59:39 -0000 1.432
+++ combine.c 7 Jun 2004 20:35:35 -0000
@@ -1370,6 +1370,12 @@ cant_combine_insn_p (rtx insn)
if (! INSN_P (insn))
+ /* Don't combine a nonlocal goto insn. Doing so can cause problems
+ determining the reference address of the branch and in branching
+ to addresses external to the current function. */
+ if (JUMP_P (insn) && find_reg_note (insn, REG_NON_LOCAL_GOTO, 0))
+ return 1;
/* Never combine loads and stores involving hard regs that are likely
to be spilled. The register allocator can usually handle such
reg-reg moves by tying. If we allow the combiner to make