From f35bcbc5d0803d2e92b8f725a1b2165d144ab156 Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Fri, 14 Nov 1997 06:51:00 -0800 Subject: [PATCH] expr.c (expand_builtin_setjmp): Set current_function_has_nonlocal_label. * expr.c (expand_builtin_setjmp): Set current_function_has_nonlocal_label. * stupid.c (stupid_life_analysis): If has_nonlocal_label, kill call-saved registers across calls. * alpha.md (exception_receiver): Remove. (nonlocal_goto_receiver_osf): New (nonlocal_goto_receiver_vms): Renamed from nonlocal_goto_receiver. (nonlocal_goto_receiver): New, select _osf or _vms. From-SVN: r16492 --- gcc/ChangeLog | 10 ++++++++++ gcc/config/alpha/alpha.md | 21 ++++++++++++++++++--- gcc/expr.c | 7 +------ gcc/stupid.c | 38 +++++++++++++++++++++++++++----------- 4 files changed, 56 insertions(+), 20 deletions(-) diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 61e6835318e..c7d4a414319 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,5 +1,15 @@ Fri Nov 14 07:24:20 1997 Richard Henderson + * expr.c (expand_builtin_setjmp): Set + current_function_has_nonlocal_label. + * stupid.c (stupid_life_analysis): If has_nonlocal_label, kill + call-saved registers across calls. + + * alpha.md (exception_receiver): Remove. + (nonlocal_goto_receiver_osf): New + (nonlocal_goto_receiver_vms): Renamed from nonlocal_goto_receiver. + (nonlocal_goto_receiver): New, select _osf or _vms. + * alpha.c (output_prolog [*]): Prefix entry labels with '$' to keep them from being propogated to the object file. (alpha_write_linkage): Likewise. diff --git a/gcc/config/alpha/alpha.md b/gcc/config/alpha/alpha.md index bd4f43d0909..5a7218dbd4e 100644 --- a/gcc/config/alpha/alpha.md +++ b/gcc/config/alpha/alpha.md @@ -4683,12 +4683,15 @@ } }") -(define_insn "exception_receiver" +;; Ideally we should be able to define nonlocal_goto and arrange +;; for the pc to be in a known place. Or perhaps branch back via +;; br instead of jmp. +(define_insn "nonlocal_goto_receiver_osf" [(unspec_volatile [(const_int 0)] 2)] "! TARGET_OPEN_VMS && ! TARGET_WINDOWS_NT" - ".long 0xc3a00000\;ldgp $29,0($29)") + "br $29,$LGOTO%=\\n$LGOTO%=:\;ldgp $29,0($29)") -(define_expand "nonlocal_goto_receiver" +(define_expand "nonlocal_goto_receiver_vms" [(unspec_volatile [(const_int 0)] 1) (set (reg:DI 27) (mem:DI (reg:DI 29))) (unspec_volatile [(const_int 0)] 1) @@ -4696,6 +4699,18 @@ "TARGET_OPEN_VMS" "") +(define_expand "nonlocal_goto_receiver" + [(unspec_volatile [(const_int 0)] 2)] + "" + " +{ + if (TARGET_OPEN_VMS) + emit_insn(gen_nonlocal_goto_receiver_vms ()); + else if (!TARGET_WINDOWS_NT) + emit_insn(gen_nonlocal_goto_receiver_osf ()); + DONE; +}") + (define_insn "arg_home" [(unspec [(const_int 0)] 0) (use (reg:DI 1)) diff --git a/gcc/expr.c b/gcc/expr.c index a18b09e9aba..7545c43ea8d 100644 --- a/gcc/expr.c +++ b/gcc/expr.c @@ -8213,12 +8213,7 @@ expand_builtin_setjmp (buf_addr, target) #endif emit_move_insn (virtual_stack_vars_rtx, hard_frame_pointer_rtx); - /* Do we need to do something like: - - current_function_has_nonlocal_label = 1; - - here? It seems like we might have to, or some subset of that - functionality, but I am unsure. (mrs) */ + current_function_has_nonlocal_label = 1; #if ARG_POINTER_REGNUM != HARD_FRAME_POINTER_REGNUM if (fixed_regs[ARG_POINTER_REGNUM]) diff --git a/gcc/stupid.c b/gcc/stupid.c index b68b196bcaa..028539aa193 100644 --- a/gcc/stupid.c +++ b/gcc/stupid.c @@ -42,8 +42,8 @@ Boston, MA 02111-1307, USA. */ pseudo reg is computed. Then the pseudo regs are ordered by priority and assigned hard regs in priority order. */ -#include #include "config.h" +#include #include "rtl.h" #include "hard-reg-set.h" #include "regs.h" @@ -230,21 +230,34 @@ stupid_life_analysis (f, nregs, file) && NOTE_LINE_NUMBER (insn) == NOTE_INSN_SETJMP) last_setjmp_suid = INSN_SUID (insn); - /* Mark all call-clobbered regs as live after each call insn - so that a pseudo whose life span includes this insn - will not go in one of them. + /* Mark all call-clobbered regs as dead after each call insn so that + a pseudo whose life span includes this insn will not go in one of + them. If the function contains a non-local goto, mark all hard + registers dead (except for stack related bits). + Then mark those regs as all dead for the continuing scan of the insns before the call. */ if (GET_CODE (insn) == CALL_INSN) { last_call_suid = INSN_SUID (insn); - IOR_HARD_REG_SET (after_insn_hard_regs[last_call_suid], - call_used_reg_set); - for (i = 0; i < FIRST_PSEUDO_REGISTER; i++) - if (call_used_regs[i]) - regs_live[i] = 0; + if (current_function_has_nonlocal_label) + { + IOR_COMPL_HARD_REG_SET (after_insn_hard_regs[last_call_suid], + fixed_reg_set); + for (i = 0; i < FIRST_PSEUDO_REGISTER; i++) + if (! fixed_regs[i]) + regs_live[i] = 0; + } + else + { + IOR_HARD_REG_SET (after_insn_hard_regs[last_call_suid], + call_used_reg_set); + for (i = 0; i < FIRST_PSEUDO_REGISTER; i++) + if (call_used_regs[i]) + regs_live[i] = 0; + } /* It is important that this be done after processing the insn's pattern because we want the function result register to still @@ -269,8 +282,11 @@ stupid_life_analysis (f, nregs, file) register int r = reg_order[i]; /* Some regnos disappear from the rtl. Ignore them to avoid crash. - Also don't allocate registers that cross a setjmp. */ - if (regno_reg_rtx[r] == 0 || regs_crosses_setjmp[r]) + Also don't allocate registers that cross a setjmp, or live across + a call if this function receives a nonlocal goto. */ + if (regno_reg_rtx[r] == 0 || regs_crosses_setjmp[r] + || (REG_N_CALLS_CROSSED (r) > 0 + && current_function_has_nonlocal_label)) continue; /* Now find the best hard-register class for this pseudo register */ -- 2.30.2