===================================================================
@@ -41,9 +41,12 @@ #define GCC_REGRENAME_H
bitmap_head conflicts;
/* Conflicts with untracked hard registers. */
HARD_REG_SET hard_conflicts;
+ /* Which registers are fully or partially clobbered by the calls that
+ the chain crosses. */
+ HARD_REG_SET call_clobber_mask;
- /* Nonzero if the chain crosses a call. */
- unsigned int need_caller_save_reg:1;
+ /* A bitmask of ABIs used by the calls that the chain crosses. */
+ unsigned int call_abis : NUM_ABI_IDS;
/* Nonzero if the register is used in a way that prevents renaming,
such as the SET_DEST of a CALL_INSN or an asm operand that used
to be a hard register. */
===================================================================
@@ -33,6 +33,7 @@
#include "addresses.h"
#include "cfganal.h"
#include "tree-pass.h"
+#include "function-abi.h"
#include "regrename.h"
/* This file implements the RTL register renaming pass of the compiler. It is
@@ -303,6 +304,18 @@ merge_overlapping_regs (HARD_REG_SET *ps
}
}
+/* Return true if (reg:MODE REGNO) would be clobbered by a call covered
+ by THIS_HEAD. */
+
+static bool
+call_clobbered_in_chain_p (du_head *this_head, machine_mode mode,
+ unsigned int regno)
+{
+ return call_clobbered_in_region_p (this_head->call_abis,
+ this_head->call_clobber_mask,
+ mode, regno);
+}
+
/* Check if NEW_REG can be the candidate register to rename for
REG in THIS_HEAD chain. THIS_UNAVAILABLE is a set of unavailable hard
registers. */
@@ -322,7 +335,7 @@ check_new_reg_p (int reg ATTRIBUTE_UNUSE
|| global_regs[new_reg + i]
/* Can't use regs which aren't saved by the prologue. */
|| (! df_regs_ever_live_p (new_reg + i)
- && ! call_used_or_fixed_reg_p (new_reg + i))
+ && ! crtl->abi->clobbers_full_reg_p (new_reg + i))
#ifdef LEAF_REGISTERS
/* We can't use a non-leaf register if we're in a
leaf function. */
@@ -337,11 +350,8 @@ check_new_reg_p (int reg ATTRIBUTE_UNUSE
for (tmp = this_head->first; tmp; tmp = tmp->next_use)
if ((!targetm.hard_regno_mode_ok (new_reg, GET_MODE (*tmp->loc))
&& ! DEBUG_INSN_P (tmp->insn))
- || (this_head->need_caller_save_reg
- && ! (targetm.hard_regno_call_part_clobbered
- (0, reg, GET_MODE (*tmp->loc)))
- && (targetm.hard_regno_call_part_clobbered
- (0, new_reg, GET_MODE (*tmp->loc)))))
+ || call_clobbered_in_chain_p (this_head, GET_MODE (*tmp->loc),
+ new_reg))
return false;
return true;
@@ -363,12 +373,6 @@ find_rename_reg (du_head_p this_head, en
int pass;
int best_new_reg = old_reg;
- /* Further narrow the set of registers we can use for renaming.
- If the chain needs a call-saved register, mark the call-used
- registers as unavailable. */
- if (this_head->need_caller_save_reg)
- *unavailable |= call_used_or_fixed_regs;
-
/* Mark registers that overlap this chain's lifetime as unavailable. */
merge_overlapping_regs (unavailable, this_head);
@@ -499,7 +503,7 @@ rename_chains (void)
{
fprintf (dump_file, "Register %s in insn %d",
reg_names[reg], INSN_UID (this_head->first->insn));
- if (this_head->need_caller_save_reg)
+ if (this_head->call_abis)
fprintf (dump_file, " crosses a call");
}
@@ -680,7 +684,8 @@ merge_chains (du_head_p c1, du_head_p c2
c1->hard_conflicts |= c2->hard_conflicts;
bitmap_ior_into (&c1->conflicts, &c2->conflicts);
- c1->need_caller_save_reg |= c2->need_caller_save_reg;
+ c1->call_clobber_mask |= c2->call_clobber_mask;
+ c1->call_abis |= c2->call_abis;
c1->cannot_rename |= c2->cannot_rename;
}
@@ -1834,9 +1839,14 @@ build_def_use (basic_block bb)
requires a caller-saved reg. */
if (CALL_P (insn))
{
+ function_abi abi = call_insn_abi (insn);
class du_head *p;
for (p = open_chains; p; p = p->next_chain)
- p->need_caller_save_reg = 1;
+ {
+ p->call_abis |= (1 << abi.id ());
+ p->call_clobber_mask |= abi.full_and_partial_reg_clobbers ();
+ p->hard_conflicts |= abi.full_reg_clobbers ();
+ }
}
/* Step 5: Close open chains that overlap writes. Similar to
===================================================================
@@ -37,6 +37,7 @@ #define INCLUDE_LIST
#include "insn-attr.h"
#include "context.h"
#include "tree-pass.h"
+#include "function-abi.h"
#include "regrename.h"
#include "aarch64-protos.h"
@@ -281,7 +282,7 @@ rename_single_chain (du_head_p head, HAR
{
fprintf (dump_file, "Register %s in insn %d", reg_names[reg],
INSN_UID (head->first->insn));
- if (head->need_caller_save_reg)
+ if (head->call_abis)
fprintf (dump_file, " crosses a call");
}
===================================================================
@@ -38,6 +38,7 @@ #define INCLUDE_LIST
#include "optabs.h"
#include "regs.h"
#include "recog.h"
+#include "function-abi.h"
#include "regrename.h"
#include "print-rtl.h"
===================================================================
@@ -55,6 +55,7 @@ #define IN_TARGET_CODE 1
#include "sel-sched.h"
#include "debug.h"
#include "hw-doloop.h"
+#include "function-abi.h"
#include "regrename.h"
#include "dumpfile.h"
#include "builtins.h"