diff options
Diffstat (limited to 'gcc/caller-save.c')
-rw-r--r-- | gcc/caller-save.c | 33 |
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; } |