diff options
author | Richard Sandiford <richard.sandiford@arm.com> | 2019-09-30 16:39:38 +0000 |
---|---|---|
committer | Richard Sandiford <rsandifo@gcc.gnu.org> | 2019-09-30 16:39:38 +0000 |
commit | 6d1e98dfd2bfce30640d71df355bedf114229744 (patch) | |
tree | 4fd650f51b146fd95f2345a09063f202a8768f53 /gcc/ira.c | |
parent | 7c3958812bd5e2e139c7f0adf8f03b505fda67f2 (diff) | |
download | gcc-6d1e98dfd2bfce30640d71df355bedf114229744.zip gcc-6d1e98dfd2bfce30640d71df355bedf114229744.tar.gz gcc-6d1e98dfd2bfce30640d71df355bedf114229744.tar.bz2 |
Make ira call df_set_regs_ever_live for extra call-clobbered regs
If we support multiple ABIs in the same translation unit, it can
sometimes be the case that a callee clobbers more registers than
its caller is allowed to. We need to call df_set_regs_ever_live
on these extra registers so that the prologue and epilogue code
can handle them appropriately.
This patch does that in IRA. I wanted to avoid another full
instruction walk just for this, so I combined it with the existing
set_paradoxical_subreg walk. This happens before the first
calculation of elimination offsets.
2019-09-30 Richard Sandiford <richard.sandiford@arm.com>
gcc/
* function-abi.h (function_abi_aggregator): New class.
* function-abi.cc (function_abi_aggregator::caller_save_regs): New
function.
* ira.c (update_equiv_regs_prescan): New function. Call
set_paradoxical_subreg here rather than...
(update_equiv_regs): ...here.
(ira): Call update_equiv_regs_prescan.
From-SVN: r276339
Diffstat (limited to 'gcc/ira.c')
-rw-r--r-- | gcc/ira.c | 41 |
1 files changed, 32 insertions, 9 deletions
@@ -3362,6 +3362,37 @@ def_dominates_uses (int regno) return true; } +/* Scan the instructions before update_equiv_regs. Record which registers + are referenced as paradoxical subregs. Also check for cases in which + the current function needs to save a register that one of its call + instructions clobbers. + + These things are logically unrelated, but it's more efficient to do + them together. */ + +static void +update_equiv_regs_prescan (void) +{ + basic_block bb; + rtx_insn *insn; + function_abi_aggregator callee_abis; + + FOR_EACH_BB_FN (bb, cfun) + FOR_BB_INSNS (bb, insn) + if (NONDEBUG_INSN_P (insn)) + { + set_paradoxical_subreg (insn); + if (CALL_P (insn)) + callee_abis.note_callee_abi (insn_callee_abi (insn)); + } + + HARD_REG_SET extra_caller_saves = callee_abis.caller_save_regs (*crtl->abi); + if (!hard_reg_set_empty_p (extra_caller_saves)) + for (unsigned int regno = 0; regno < FIRST_PSEUDO_REGISTER; ++regno) + if (TEST_HARD_REG_BIT (extra_caller_saves, regno)) + df_set_regs_ever_live (regno, true); +} + /* Find registers that are equivalent to a single value throughout the compilation (either because they can be referenced in memory or are set once from a single constant). Lower their priority for a @@ -3378,15 +3409,6 @@ update_equiv_regs (void) rtx_insn *insn; basic_block bb; - /* Scan insns and set pdx_subregs if the reg is used in a - paradoxical subreg. Don't set such reg equivalent to a mem, - because lra will not substitute such equiv memory in order to - prevent access beyond allocated memory for paradoxical memory subreg. */ - FOR_EACH_BB_FN (bb, cfun) - FOR_BB_INSNS (bb, insn) - if (NONDEBUG_INSN_P (insn)) - set_paradoxical_subreg (insn); - /* Scan the insns and find which registers have equivalences. Do this in a separate scan of the insns because (due to -fcse-follow-jumps) a register can be set below its use. */ @@ -5276,6 +5298,7 @@ ira (FILE *f) init_alias_analysis (); loop_optimizer_init (AVOID_CFG_MODIFICATIONS); reg_equiv = XCNEWVEC (struct equivalence, max_reg_num ()); + update_equiv_regs_prescan (); update_equiv_regs (); /* Don't move insns if live range shrinkage or register |