Skip to content

Commit

Permalink
Disable Callee Saved Registers
Browse files Browse the repository at this point in the history
Each Calling convention (CC) defines a static list of registers that should be preserved by a callee function. All other registers should be saved by the caller.
Some CCs use additional condition: If the register is used for passing/returning arguments – the caller needs to save it - even if it is part of the Callee Saved Registers (CSR) list.
The current LLVM implementation doesn’t support it. It will save a register if it is part of the static CSR list and will not care if the register is passed/returned by the callee.
The solution is to dynamically allocate the CSR lists (Only for these CCs). The lists will be updated with actual registers that should be saved by the callee.
Since we need the allocated lists to live as long as the function exists, the list should reside inside the Machine Register Info (MRI) which is a property of the Machine Function and managed by it (and has the same life span).
The lists should be saved in the MRI and populated upon LowerCall and LowerFormalArguments.
The patch will also assist to implement future no_caller_saved_regsiters attribute intended for interrupt handler CC.

Differential Revision: https://reviews.llvm.org/D28566

llvm-svn: 297715
  • Loading branch information
Oren Ben Simhon committed Mar 14, 2017
1 parent 2d26210 commit fe34c5e
Show file tree
Hide file tree
Showing 19 changed files with 258 additions and 89 deletions.
20 changes: 20 additions & 0 deletions llvm/include/llvm/CodeGen/MachineRegisterInfo.h
Expand Up @@ -73,6 +73,16 @@ class MachineRegisterInfo {
VirtReg2IndexFunctor>
VRegInfo;

/// The flag is true upon \p UpdatedCSRs initialization
/// and false otherwise.
bool IsUpdatedCSRsInitizialied;

/// Contains the updated callee saved register list.
/// As opposed to the static list defined in register info,
/// all registers that were disabled (in CalleeSaveDisableRegs)
/// are removed from the list.
SmallVector<MCPhysReg, 16> UpdatedCSRs;

/// RegAllocHints - This vector records register allocation hints for virtual
/// registers. For each virtual register, it keeps a register and hint type
/// pair making up the allocation hint. Hint type is target specific except
Expand Down Expand Up @@ -207,6 +217,16 @@ class MachineRegisterInfo {
// Register Info
//===--------------------------------------------------------------------===//

/// Disables the register from the list of CSRs.
/// I.e. the register will not appear as part of the CSR mask.
/// \see UpdatedCalleeSavedRegs.
void disableCalleeSavedRegister(unsigned Reg);

/// Returns list of callee saved registers.
/// The function returns the updated CSR list (after taking into account
/// registers that are disabled from the CSR list).
const MCPhysReg *getCalleeSavedRegs() const;

// Strictly for use by MachineInstr.cpp.
void addRegOperandToUseList(MachineOperand *MO);

Expand Down
13 changes: 7 additions & 6 deletions llvm/include/llvm/CodeGen/RegisterClassInfo.h
Expand Up @@ -56,10 +56,11 @@ class RegisterClassInfo {

// Callee saved registers of last MF. Assumed to be valid until the next
// runOnFunction() call.
const MCPhysReg *CalleeSaved = nullptr;
// Used only to determine if an update was made to CalleeSavedAliases.
const MCPhysReg *CalleeSavedRegs = nullptr;

// Map register number to CalleeSaved index + 1;
SmallVector<uint8_t, 4> CSRNum;
// Map register alias to the callee saved Register.
SmallVector<MCPhysReg, 4> CalleeSavedAliases;

// Reserved registers in the current MF.
BitVector Reserved;
Expand Down Expand Up @@ -108,11 +109,11 @@ class RegisterClassInfo {
}

/// getLastCalleeSavedAlias - Returns the last callee saved register that
/// overlaps PhysReg, or 0 if Reg doesn't overlap a CSR.
/// overlaps PhysReg, or 0 if Reg doesn't overlap a CalleeSavedAliases.
unsigned getLastCalleeSavedAlias(unsigned PhysReg) const {
assert(TargetRegisterInfo::isPhysicalRegister(PhysReg));
if (unsigned N = CSRNum[PhysReg])
return CalleeSaved[N-1];
if (PhysReg < CalleeSavedAliases.size())
return CalleeSavedAliases[PhysReg];
return 0;
}

Expand Down
4 changes: 3 additions & 1 deletion llvm/include/llvm/Target/TargetRegisterInfo.h
Expand Up @@ -426,7 +426,9 @@ class TargetRegisterInfo : public MCRegisterInfo {
/// this target. The register should be in the order of desired callee-save
/// stack frame offset. The first register is closest to the incoming stack
/// pointer if stack grows down, and vice versa.
///
/// Notice: This function does not take into account disabled CSRs.
/// In most cases you will want to use instead the function
/// getCalleeSavedRegs that is implemented in MachineRegisterInfo.
virtual const MCPhysReg*
getCalleeSavedRegs(const MachineFunction *MF) const = 0;

Expand Down
3 changes: 2 additions & 1 deletion llvm/lib/CodeGen/AggressiveAntiDepBreaker.cpp
Expand Up @@ -163,7 +163,8 @@ void AggressiveAntiDepBreaker::StartBlock(MachineBasicBlock *BB) {
// callee-saved register that is not saved in the prolog.
const MachineFrameInfo &MFI = MF.getFrameInfo();
BitVector Pristine = MFI.getPristineRegs(MF);
for (const MCPhysReg *I = TRI->getCalleeSavedRegs(&MF); *I; ++I) {
for (const MCPhysReg *I = MF.getRegInfo().getCalleeSavedRegs(); *I;
++I) {
unsigned Reg = *I;
if (!IsReturnBlock && !Pristine.test(Reg)) continue;
for (MCRegAliasIterator AI(Reg, TRI, true); AI.isValid(); ++AI) {
Expand Down
3 changes: 2 additions & 1 deletion llvm/lib/CodeGen/CriticalAntiDepBreaker.cpp
Expand Up @@ -71,7 +71,8 @@ void CriticalAntiDepBreaker::StartBlock(MachineBasicBlock *BB) {
// callee-saved register that is not saved in the prolog.
const MachineFrameInfo &MFI = MF.getFrameInfo();
BitVector Pristine = MFI.getPristineRegs(MF);
for (const MCPhysReg *I = TRI->getCalleeSavedRegs(&MF); *I; ++I) {
for (const MCPhysReg *I = MF.getRegInfo().getCalleeSavedRegs(); *I;
++I) {
if (!IsReturnBlock && !Pristine.test(*I)) continue;
for (MCRegAliasIterator AI(*I, TRI, true); AI.isValid(); ++AI) {
unsigned Reg = *AI;
Expand Down
7 changes: 5 additions & 2 deletions llvm/lib/CodeGen/LivePhysRegs.cpp
Expand Up @@ -160,7 +160,9 @@ void LivePhysRegs::addBlockLiveIns(const MachineBasicBlock &MBB) {
static void addPristines(LivePhysRegs &LiveRegs, const MachineFunction &MF,
const MachineFrameInfo &MFI,
const TargetRegisterInfo &TRI) {
for (const MCPhysReg *CSR = TRI.getCalleeSavedRegs(&MF); CSR && *CSR; ++CSR)
const MachineRegisterInfo &MRI = MF.getRegInfo();
for (const MCPhysReg *CSR = MRI.getCalleeSavedRegs(); CSR && *CSR;
++CSR)
LiveRegs.addReg(*CSR);
for (const CalleeSavedInfo &Info : MFI.getCalleeSavedInfo())
LiveRegs.removeReg(Info.getReg());
Expand All @@ -179,7 +181,8 @@ void LivePhysRegs::addLiveOuts(const MachineBasicBlock &MBB) {
if (MBB.isReturnBlock()) {
// The return block has no successors whose live-ins we could merge
// below. So instead we add the callee saved registers manually.
for (const MCPhysReg *I = TRI->getCalleeSavedRegs(&MF); *I; ++I)
const MachineRegisterInfo &MRI = MF.getRegInfo();
for (const MCPhysReg *I = MRI.getCalleeSavedRegs(); *I; ++I)
addReg(*I);
} else {
addPristines(*this, MF, MFI, *TRI);
Expand Down
4 changes: 3 additions & 1 deletion llvm/lib/CodeGen/MachineFunction.cpp
Expand Up @@ -860,7 +860,9 @@ BitVector MachineFrameInfo::getPristineRegs(const MachineFunction &MF) const {
if (!isCalleeSavedInfoValid())
return BV;

for (const MCPhysReg *CSR = TRI->getCalleeSavedRegs(&MF); CSR && *CSR; ++CSR)
const MachineRegisterInfo &MRI = MF.getRegInfo();
for (const MCPhysReg *CSR = MRI.getCalleeSavedRegs(); CSR && *CSR;
++CSR)
BV.set(*CSR);

// Saved CSRs are not pristine.
Expand Down
17 changes: 15 additions & 2 deletions llvm/lib/CodeGen/MachineInstr.cpp
Expand Up @@ -262,8 +262,21 @@ bool MachineOperand::isIdenticalTo(const MachineOperand &Other) const {
return getBlockAddress() == Other.getBlockAddress() &&
getOffset() == Other.getOffset();
case MachineOperand::MO_RegisterMask:
case MachineOperand::MO_RegisterLiveOut:
return getRegMask() == Other.getRegMask();
case MachineOperand::MO_RegisterLiveOut: {
// Shallow compare of the two RegMasks
const uint32_t *RegMask = getRegMask();
const uint32_t *OtherRegMask = Other.getRegMask();
if (RegMask == OtherRegMask)
return true;

// Calculate the size of the RegMask
const MachineFunction *MF = getParent()->getParent()->getParent();
const TargetRegisterInfo *TRI = MF->getSubtarget().getRegisterInfo();
unsigned RegMaskSize = (TRI->getNumRegs() + 31) / 32;

// Deep compare of the two RegMasks
return std::equal(RegMask, RegMask + RegMaskSize, OtherRegMask);
}
case MachineOperand::MO_MCSymbol:
return getMCSymbol() == Other.getMCSymbol();
case MachineOperand::MO_CFIIndex:
Expand Down
36 changes: 34 additions & 2 deletions llvm/lib/CodeGen/MachineRegisterInfo.cpp
Expand Up @@ -42,8 +42,9 @@ static cl::opt<bool> EnableSubRegLiveness("enable-subreg-liveness", cl::Hidden,
void MachineRegisterInfo::Delegate::anchor() {}

MachineRegisterInfo::MachineRegisterInfo(MachineFunction *MF)
: MF(MF), TracksSubRegLiveness(MF->getSubtarget().enableSubRegLiveness() &&
EnableSubRegLiveness) {
: MF(MF), IsUpdatedCSRsInitizialied(false),
TracksSubRegLiveness(MF->getSubtarget().enableSubRegLiveness() &&
EnableSubRegLiveness) {
unsigned NumRegs = getTargetRegisterInfo()->getNumRegs();
VRegInfo.reserve(256);
RegAllocHints.reserve(256);
Expand Down Expand Up @@ -556,3 +557,34 @@ bool MachineRegisterInfo::isPhysRegUsed(unsigned PhysReg) const {
}
return false;
}

void MachineRegisterInfo::disableCalleeSavedRegister(unsigned Reg) {

const TargetRegisterInfo *TRI = getTargetRegisterInfo();
assert(Reg && (Reg < TRI->getNumRegs()) &&
"Trying to disable an invalid register");

if (!IsUpdatedCSRsInitizialied) {
const MCPhysReg *CSR = TRI->getCalleeSavedRegs(MF);
for (const MCPhysReg *I = CSR; *I; ++I)
UpdatedCSRs.push_back(*I);

// Zero value represents the end of the register list
// (no more registers should be pushed).
UpdatedCSRs.push_back(0);

IsUpdatedCSRsInitizialied = true;
}

// Remove the register (and its aliases from the list).
for (MCRegAliasIterator AI(Reg, TRI, true); AI.isValid(); ++AI)
UpdatedCSRs.erase(std::remove(UpdatedCSRs.begin(), UpdatedCSRs.end(), *AI),
UpdatedCSRs.end());
}

const MCPhysReg *MachineRegisterInfo::getCalleeSavedRegs() const {
if (IsUpdatedCSRsInitizialied)
return UpdatedCSRs.data();

return getTargetRegisterInfo()->getCalleeSavedRegs(MF);
}
2 changes: 1 addition & 1 deletion llvm/lib/CodeGen/PrologEpilogInserter.cpp
Expand Up @@ -336,7 +336,7 @@ static void assignCalleeSavedSpillSlots(MachineFunction &F,
return;

const TargetRegisterInfo *RegInfo = F.getSubtarget().getRegisterInfo();
const MCPhysReg *CSRegs = RegInfo->getCalleeSavedRegs(&F);
const MCPhysReg *CSRegs = F.getRegInfo().getCalleeSavedRegs();

std::vector<CalleeSavedInfo> CSI;
for (unsigned i = 0; CSRegs[i]; ++i) {
Expand Down
2 changes: 1 addition & 1 deletion llvm/lib/CodeGen/RegAllocPBQP.cpp
Expand Up @@ -573,7 +573,7 @@ void RegAllocPBQP::findVRegIntervalsToAlloc(const MachineFunction &MF,

static bool isACalleeSavedRegister(unsigned reg, const TargetRegisterInfo &TRI,
const MachineFunction &MF) {
const MCPhysReg *CSR = TRI.getCalleeSavedRegs(&MF);
const MCPhysReg *CSR = MF.getRegInfo().getCalleeSavedRegs();
for (unsigned i = 0; CSR[i] != 0; ++i)
if (TRI.regsOverlap(reg, CSR[i]))
return true;
Expand Down
23 changes: 13 additions & 10 deletions llvm/lib/CodeGen/RegisterClassInfo.cpp
Expand Up @@ -24,6 +24,7 @@
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/Target/TargetFrameLowering.h"
#include "llvm/Target/TargetRegisterInfo.h"
#include "llvm/Target/TargetSubtargetInfo.h"
#include <algorithm>
Expand Down Expand Up @@ -56,18 +57,20 @@ void RegisterClassInfo::runOnMachineFunction(const MachineFunction &mf) {

// Does this MF have different CSRs?
assert(TRI && "no register info set");
const MCPhysReg *CSR = TRI->getCalleeSavedRegs(MF);
if (Update || CSR != CalleeSaved) {
// Build a CSRNum map. Every CSR alias gets an entry pointing to the last

// Get the callee saved registers.
const MCPhysReg *CSR = MF->getRegInfo().getCalleeSavedRegs();
if (Update || CSR != CalleeSavedRegs) {
// Build a CSRAlias map. Every CSR alias saves the last
// overlapping CSR.
CSRNum.clear();
CSRNum.resize(TRI->getNumRegs(), 0);
for (unsigned N = 0; unsigned Reg = CSR[N]; ++N)
for (MCRegAliasIterator AI(Reg, TRI, true); AI.isValid(); ++AI)
CSRNum[*AI] = N + 1; // 0 means no CSR, 1 means CalleeSaved[0], ...
CalleeSavedAliases.resize(TRI->getNumRegs(), 0);
for (const MCPhysReg *I = CSR; *I; ++I)
for (MCRegAliasIterator AI(*I, TRI, true); AI.isValid(); ++AI)
CalleeSavedAliases[*AI] = *I;

Update = true;
}
CalleeSaved = CSR;
CalleeSavedRegs = CSR;

// Different reserved registers?
const BitVector &RR = MF->getRegInfo().getReservedRegs();
Expand Down Expand Up @@ -111,7 +114,7 @@ void RegisterClassInfo::compute(const TargetRegisterClass *RC) const {
unsigned Cost = TRI->getCostPerUse(PhysReg);
MinCost = std::min(MinCost, Cost);

if (CSRNum[PhysReg])
if (CalleeSavedAliases[PhysReg])
// PhysReg aliases a CSR, save it for later.
CSRAlias.push_back(PhysReg);
else {
Expand Down
2 changes: 1 addition & 1 deletion llvm/lib/CodeGen/TargetFrameLoweringImpl.cpp
Expand Up @@ -73,7 +73,7 @@ void TargetFrameLowering::determineCalleeSaves(MachineFunction &MF,
return;

// Get the callee saved register list...
const MCPhysReg *CSRegs = TRI.getCalleeSavedRegs(&MF);
const MCPhysReg *CSRegs = MF.getRegInfo().getCalleeSavedRegs();

// Early exit if there are no callee saved registers.
if (!CSRegs || CSRegs[0] == 0)
Expand Down

0 comments on commit fe34c5e

Please sign in to comment.