Skip to content

Commit

Permalink
Clarify rules for reserved regs, fix aarch64 ones.
Browse files Browse the repository at this point in the history
No test case necessary as the problematic condition is checked with the
newly introduced assertAllSuperRegsMarked() function.

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

llvm-svn: 288277
  • Loading branch information
MatzeB committed Nov 30, 2016
1 parent 1cba0a9 commit c52fe29
Show file tree
Hide file tree
Showing 6 changed files with 70 additions and 31 deletions.
18 changes: 16 additions & 2 deletions llvm/include/llvm/Target/TargetRegisterInfo.h
Original file line number Diff line number Diff line change
Expand Up @@ -486,8 +486,14 @@ class TargetRegisterInfo : public MCRegisterInfo {

/// Returns a bitset indexed by physical register number indicating if a
/// register is a special register that has particular uses and should be
/// considered unavailable at all times, e.g. SP, RA. This is
/// used by register scavenger to determine what registers are free.
/// considered unavailable at all times, e.g. stack pointer, return address.
/// A reserved register:
/// - is not allocatable
/// - is considered always live
/// - is ignored by liveness tracking
/// It is often necessary to reserve the super registers of a reserved
/// register as well, to avoid them getting allocated indirectly. You may use
/// markSuperRegs() and checkAllSuperRegsMarked() in this case.
virtual BitVector getReservedRegs(const MachineFunction &MF) const = 0;

/// Returns true if PhysReg is unallocatable and constant throughout the
Expand Down Expand Up @@ -942,6 +948,14 @@ class TargetRegisterInfo : public MCRegisterInfo {
/// getFrameRegister - This method should return the register used as a base
/// for values allocated in the current stack frame.
virtual unsigned getFrameRegister(const MachineFunction &MF) const = 0;

/// Mark a register and all its aliases as reserved in the given set.
void markSuperRegs(BitVector &RegisterSet, unsigned Reg) const;

/// Returns true if for every register in the set all super registers are part
/// of the set as well.
bool checkAllSuperRegsMarked(const BitVector &RegisterSet,
ArrayRef<MCPhysReg> Exceptions = ArrayRef<MCPhysReg>()) const;
};


Expand Down
10 changes: 0 additions & 10 deletions llvm/lib/CodeGen/MachineVerifier.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -527,16 +527,6 @@ void MachineVerifier::visitMachineFunctionBefore() {
lastIndex = SlotIndex();
regsReserved = MRI->getReservedRegs();

// A sub-register of a reserved register is also reserved
for (int Reg = regsReserved.find_first(); Reg>=0;
Reg = regsReserved.find_next(Reg)) {
for (MCSubRegIterator SubRegs(Reg, TRI); SubRegs.isValid(); ++SubRegs) {
// FIXME: This should probably be:
// assert(regsReserved.test(*SubRegs) && "Non-reserved sub-register");
regsReserved.set(*SubRegs);
}
}

markReachable(&MF->front());

// Build a set of the basic blocks in the function.
Expand Down
30 changes: 30 additions & 0 deletions llvm/lib/CodeGen/TargetRegisterInfo.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,36 @@ TargetRegisterInfo::TargetRegisterInfo(const TargetRegisterInfoDesc *ID,

TargetRegisterInfo::~TargetRegisterInfo() {}

void TargetRegisterInfo::markSuperRegs(BitVector &RegisterSet, unsigned Reg)
const {
for (MCSuperRegIterator AI(Reg, this, true); AI.isValid(); ++AI)
RegisterSet.set(*AI);
}

bool TargetRegisterInfo::checkAllSuperRegsMarked(const BitVector &RegisterSet,
ArrayRef<MCPhysReg> Exceptions) const {
// Check that all super registers of reserved regs are reserved as well.
BitVector Checked(getNumRegs());
for (int Reg = RegisterSet.find_first(); Reg>=0;
Reg = RegisterSet.find_next(Reg)) {
if (Checked[Reg])
continue;
for (MCSuperRegIterator SR(Reg, this); SR.isValid(); ++SR) {
if (!RegisterSet[*SR] && !is_contained(Exceptions, Reg)) {
dbgs() << "Error: Super register " << PrintReg(*SR, this)
<< " of reserved register " << PrintReg(Reg, this)
<< " is not reserved.\n";
return false;
}

// We transitively check superregs. So we can remember this for later
// to avoid compiletime explosion in deep register hierarchies.
Checked.set(*SR);
}
}
return true;
}

namespace llvm {

Printable PrintReg(unsigned Reg, const TargetRegisterInfo *TRI,
Expand Down
21 changes: 11 additions & 10 deletions llvm/lib/Target/AArch64/AArch64RegisterInfo.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -118,26 +118,27 @@ AArch64RegisterInfo::getReservedRegs(const MachineFunction &MF) const {

// FIXME: avoid re-calculating this every time.
BitVector Reserved(getNumRegs());
Reserved.set(AArch64::SP);
Reserved.set(AArch64::XZR);
Reserved.set(AArch64::WSP);
Reserved.set(AArch64::WZR);
markSuperRegs(Reserved, AArch64::SP);
markSuperRegs(Reserved, AArch64::XZR);
markSuperRegs(Reserved, AArch64::WSP);
markSuperRegs(Reserved, AArch64::WZR);

if (TFI->hasFP(MF) || TT.isOSDarwin()) {
Reserved.set(AArch64::FP);
Reserved.set(AArch64::W29);
markSuperRegs(Reserved, AArch64::FP);
markSuperRegs(Reserved, AArch64::W29);
}

if (MF.getSubtarget<AArch64Subtarget>().isX18Reserved()) {
Reserved.set(AArch64::X18); // Platform register
Reserved.set(AArch64::W18);
markSuperRegs(Reserved, AArch64::X18); // Platform register
markSuperRegs(Reserved, AArch64::W18);
}

if (hasBasePointer(MF)) {
Reserved.set(AArch64::X19);
Reserved.set(AArch64::W19);
markSuperRegs(Reserved, AArch64::X19);
markSuperRegs(Reserved, AArch64::W19);
}

assert(checkAllSuperRegsMarked(Reserved));
return Reserved;
}

Expand Down
20 changes: 11 additions & 9 deletions llvm/lib/Target/ARM/ARMBaseRegisterInfo.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -167,27 +167,29 @@ getReservedRegs(const MachineFunction &MF) const {

// FIXME: avoid re-calculating this every time.
BitVector Reserved(getNumRegs());
Reserved.set(ARM::SP);
Reserved.set(ARM::PC);
Reserved.set(ARM::FPSCR);
Reserved.set(ARM::APSR_NZCV);
markSuperRegs(Reserved, ARM::SP);
markSuperRegs(Reserved, ARM::PC);
markSuperRegs(Reserved, ARM::FPSCR);
markSuperRegs(Reserved, ARM::APSR_NZCV);
if (TFI->hasFP(MF))
Reserved.set(getFramePointerReg(STI));
markSuperRegs(Reserved, getFramePointerReg(STI));
if (hasBasePointer(MF))
Reserved.set(BasePtr);
markSuperRegs(Reserved, BasePtr);
// Some targets reserve R9.
if (STI.isR9Reserved())
Reserved.set(ARM::R9);
markSuperRegs(Reserved, ARM::R9);
// Reserve D16-D31 if the subtarget doesn't support them.
if (!STI.hasVFP3() || STI.hasD16()) {
static_assert(ARM::D31 == ARM::D16 + 15, "Register list not consecutive!");
Reserved.set(ARM::D16, ARM::D31 + 1);
for (unsigned R = 0; R < 16; ++R)
markSuperRegs(Reserved, ARM::D16 + R);
}
const TargetRegisterClass *RC = &ARM::GPRPairRegClass;
for(TargetRegisterClass::iterator I = RC->begin(), E = RC->end(); I!=E; ++I)
for (MCSubRegIterator SI(*I, this); SI.isValid(); ++SI)
if (Reserved.test(*SI)) Reserved.set(*I);
if (Reserved.test(*SI)) markSuperRegs(Reserved, *I);

assert(checkAllSuperRegsMarked(Reserved));
return Reserved;
}

Expand Down
2 changes: 2 additions & 0 deletions llvm/lib/Target/X86/X86RegisterInfo.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -558,6 +558,8 @@ BitVector X86RegisterInfo::getReservedRegs(const MachineFunction &MF) const {
}
}

assert(checkAllSuperRegsMarked(Reserved,
{X86::SIL, X86::DIL, X86::BPL, X86::SPL}));
return Reserved;
}

Expand Down

0 comments on commit c52fe29

Please sign in to comment.