summaryrefslogtreecommitdiff
path: root/gcc/caller-save.c
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/caller-save.c')
-rw-r--r--gcc/caller-save.c33
1 files changed, 30 insertions, 3 deletions
diff --git a/gcc/caller-save.c b/gcc/caller-save.c
index 39bccc4fc8e..c8f3b145946 100644
--- a/gcc/caller-save.c
+++ b/gcc/caller-save.c
@@ -433,6 +433,8 @@ setup_save_areas (void)
/* Create hard reg saved regs. */
for (chain = reload_insn_chain; chain != 0; chain = next)
{
+ rtx cheap;
+
insn = chain->insn;
next = chain->next;
if (!CALL_P (insn)
@@ -466,6 +468,9 @@ setup_save_areas (void)
new_saved_hard_reg (regno, freq);
SET_HARD_REG_BIT (hard_regs_used, regno);
}
+ cheap = find_reg_note (insn, REG_RETURNED, NULL);
+ if (cheap)
+ cheap = XEXP (cheap, 0);
/* Look through all live pseudos, mark their hard registers. */
EXECUTE_IF_SET_IN_REG_SET
(&chain->live_throughout, FIRST_PSEUDO_REGISTER, regno, rsi)
@@ -473,7 +478,7 @@ setup_save_areas (void)
int r = reg_renumber[regno];
int bound;
- if (r < 0)
+ if (r < 0 || regno_reg_rtx[regno] == cheap)
continue;
bound = r + hard_regno_nregs[r][PSEUDO_REGNO_MODE (regno)];
@@ -508,12 +513,18 @@ setup_save_areas (void)
memset (saved_reg_conflicts, 0, saved_regs_num * saved_regs_num);
for (chain = reload_insn_chain; chain != 0; chain = next)
{
+ rtx cheap;
call_saved_regs_num = 0;
insn = chain->insn;
next = chain->next;
if (!CALL_P (insn)
|| find_reg_note (insn, REG_NORETURN, NULL))
continue;
+
+ cheap = find_reg_note (insn, REG_RETURNED, NULL);
+ if (cheap)
+ cheap = XEXP (cheap, 0);
+
REG_SET_TO_HARD_REG_SET (hard_regs_to_save,
&chain->live_throughout);
COPY_HARD_REG_SET (used_regs, call_used_reg_set);
@@ -546,7 +557,7 @@ setup_save_areas (void)
int r = reg_renumber[regno];
int bound;
- if (r < 0)
+ if (r < 0 || regno_reg_rtx[regno] == cheap)
continue;
bound = r + hard_regno_nregs[r][PSEUDO_REGNO_MODE (regno)];
@@ -796,6 +807,11 @@ save_call_clobbered_regs (void)
unsigned regno;
HARD_REG_SET hard_regs_to_save;
reg_set_iterator rsi;
+ rtx cheap;
+
+ cheap = find_reg_note (insn, REG_RETURNED, NULL);
+ if (cheap)
+ cheap = XEXP (cheap, 0);
/* Use the register life information in CHAIN to compute which
regs are live during the call. */
@@ -817,7 +833,7 @@ save_call_clobbered_regs (void)
int nregs;
enum machine_mode mode;
- if (r < 0)
+ if (r < 0 || regno_reg_rtx[regno] == cheap)
continue;
nregs = hard_regno_nregs[r][PSEUDO_REGNO_MODE (regno)];
mode = HARD_REGNO_CALLER_SAVE_MODE
@@ -851,6 +867,17 @@ save_call_clobbered_regs (void)
for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
if (TEST_HARD_REG_BIT (hard_regs_saved, regno))
n_regs_saved++;
+
+ if (cheap
+ && HARD_REGISTER_P (cheap)
+ && TEST_HARD_REG_BIT (call_used_reg_set, REGNO (cheap)))
+ {
+ rtx call_set = single_set (insn);
+ rtx dest = SET_DEST (call_set);
+ rtx pat = gen_rtx_SET (VOIDmode, cheap,
+ copy_rtx (dest));
+ chain = insert_one_insn (chain, 0, -1, pat);
+ }
}
last = chain;
}