aboutsummaryrefslogtreecommitdiff
path: root/gcc/local-alloc.c
diff options
context:
space:
mode:
authorJakub Jelinek <jakub@redhat.com>2005-09-01 07:29:03 +0200
committerJakub Jelinek <jakub@gcc.gnu.org>2005-09-01 07:29:03 +0200
commit95c37cdb41412007974489bb5910372ee4186ee9 (patch)
tree51f172c784c1a0fb89978ba5eedd01b262b307a4 /gcc/local-alloc.c
parent1990cd79695bdc9214496c869fedf53a2194f555 (diff)
downloadgcc-95c37cdb41412007974489bb5910372ee4186ee9.zip
gcc-95c37cdb41412007974489bb5910372ee4186ee9.tar.gz
gcc-95c37cdb41412007974489bb5910372ee4186ee9.tar.bz2
re PR rtl-optimization/23478 (Miscompilation due to reloading of a var that is also used in EH pad)
PR rtl-optimization/23478 * local-alloc.c (struct qty): Add n_throwing_calls_crossed field. (alloc_qty): Initialize it. (update_equiv_regs): Clear REG_N_THROWING_CALLS_CROSSED. (combine_regs): Combine also n_throwing_calls_crossed fields. (find_free_reg): Don't attempt to caller-save pseudos crossing calls that might throw. * global.c (struct allocno): Add throwing_calls_crossed field. (global_alloc): Revert 2005-08-22 change. Initialize throwing_calls_crossed. (find_reg): Don't attempt to caller-save pseudos crossing calls that might throw. From-SVN: r103718
Diffstat (limited to 'gcc/local-alloc.c')
-rw-r--r--gcc/local-alloc.c13
1 files changed, 12 insertions, 1 deletions
diff --git a/gcc/local-alloc.c b/gcc/local-alloc.c
index cd26174..4ee4991 100644
--- a/gcc/local-alloc.c
+++ b/gcc/local-alloc.c
@@ -123,6 +123,11 @@ struct qty
int n_calls_crossed;
+ /* Number of times a reg tied to given qty lives across a CALL_INSN
+ that might throw. */
+
+ int n_throwing_calls_crossed;
+
/* The register number of one pseudo register whose reg_qty value is Q.
This register should be the head of the chain
maintained in reg_next_in_qty. */
@@ -324,6 +329,7 @@ alloc_qty (int regno, enum machine_mode mode, int size, int birth)
qty[qtyno].mode = mode;
qty[qtyno].birth = birth;
qty[qtyno].n_calls_crossed = REG_N_CALLS_CROSSED (regno);
+ qty[qtyno].n_throwing_calls_crossed = REG_N_THROWING_CALLS_CROSSED (regno);
qty[qtyno].min_class = reg_preferred_class (regno);
qty[qtyno].alternate_class = reg_alternate_class (regno);
qty[qtyno].n_refs = REG_N_REFS (regno);
@@ -1170,6 +1176,7 @@ update_equiv_regs (void)
REG_BASIC_BLOCK (regno) = bb->index;
REG_N_CALLS_CROSSED (regno) = 0;
+ REG_N_THROWING_CALLS_CROSSED (regno) = 0;
REG_LIVE_LENGTH (regno) = 2;
if (insn == BB_HEAD (bb))
@@ -2011,6 +2018,8 @@ combine_regs (rtx usedreg, rtx setreg, int may_save_copy, int insn_number,
/* Update info about quantity SQTY. */
qty[sqty].n_calls_crossed += REG_N_CALLS_CROSSED (sreg);
+ qty[sqty].n_throwing_calls_crossed
+ += REG_N_THROWING_CALLS_CROSSED (sreg);
qty[sqty].n_refs += REG_N_REFS (sreg);
qty[sqty].freq += REG_FREQ (sreg);
if (usize < ssize)
@@ -2315,12 +2324,14 @@ find_free_reg (enum reg_class class, enum machine_mode mode, int qtyno,
/* We need not check to see if the current function has nonlocal
labels because we don't put any pseudos that are live over calls in
- registers in that case. */
+ registers in that case. Avoid putting pseudos crossing calls that
+ might throw into call used registers. */
if (! accept_call_clobbered
&& flag_caller_saves
&& ! just_try_suggested
&& qty[qtyno].n_calls_crossed != 0
+ && qty[qtyno].n_throwing_calls_crossed == 0
&& CALLER_SAVE_PROFITABLE (qty[qtyno].n_refs,
qty[qtyno].n_calls_crossed))
{