Index: include/llvm/Target/TargetRegisterInfo.h =================================================================== --- include/llvm/Target/TargetRegisterInfo.h +++ include/llvm/Target/TargetRegisterInfo.h @@ -486,8 +486,14 @@ /// 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 assertAllSuperRegsMarked() in this case. virtual BitVector getReservedRegs(const MachineFunction &MF) const = 0; /// Returns true if PhysReg is unallocatable and constant throughout the @@ -935,6 +941,13 @@ /// 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. + void assertAllSuperRegsMarked(const BitVector &RegisterSet) const; }; Index: lib/CodeGen/MachineRegisterInfo.cpp =================================================================== --- lib/CodeGen/MachineRegisterInfo.cpp +++ lib/CodeGen/MachineRegisterInfo.cpp @@ -455,6 +455,31 @@ ReservedRegs = getTargetRegisterInfo()->getReservedRegs(MF); assert(ReservedRegs.size() == getTargetRegisterInfo()->getNumRegs() && "Invalid ReservedRegs vector from target"); + +#ifndef NDEBUG + // Check that each reserved register has at least 1 reserved + // subregister/register units. + const TargetRegisterInfo &TRI = *getTargetRegisterInfo(); + for (int Reg = ReservedRegs.find_first(); Reg>=0; + Reg = ReservedRegs.find_next(Reg)) { + bool FoundReservedRoot = false; + for (MCRegUnitIterator UI(Reg, &TRI); UI.isValid() && !FoundReservedRoot; + ++UI) { + for (MCRegUnitRootIterator RI(*UI, &TRI); RI.isValid(); ++RI) { + if (ReservedRegs[*RI]) { + FoundReservedRoot = true; + break; + } + } + } + + if (!FoundReservedRoot) { + errs() << "Error: None of the subregisters of " << PrintReg(Reg, &TRI) + << " are reserved\n"; + report_fatal_error("Invalid register info."); + } + } +#endif } bool MachineRegisterInfo::isConstantPhysReg(unsigned PhysReg) const { Index: lib/CodeGen/MachineVerifier.cpp =================================================================== --- lib/CodeGen/MachineVerifier.cpp +++ lib/CodeGen/MachineVerifier.cpp @@ -221,7 +221,7 @@ void report_context(SlotIndex Pos) const; void report_context_liverange(const LiveRange &LR) const; void report_context_lanemask(LaneBitmask LaneMask) const; - void report_context_vreg(unsigned VReg) const; + void report_context_reg(unsigned Reg) const; void report_context_vreg_regunit(unsigned VRegOrRegUnit) const; void verifyInlineAsm(const MachineInstr *MI); @@ -497,13 +497,13 @@ errs() << "- liverange: " << LR << '\n'; } -void MachineVerifier::report_context_vreg(unsigned VReg) const { - errs() << "- v. register: " << PrintReg(VReg, TRI) << '\n'; +void MachineVerifier::report_context_reg(unsigned Reg) const { + errs() << "- register: " << PrintReg(Reg, TRI) << '\n'; } void MachineVerifier::report_context_vreg_regunit(unsigned VRegOrUnit) const { if (TargetRegisterInfo::isVirtualRegister(VRegOrUnit)) { - report_context_vreg(VRegOrUnit); + report_context_reg(VRegOrUnit); } else { errs() << "- regunit: " << PrintRegUnit(VRegOrUnit, TRI) << '\n'; } @@ -527,16 +527,6 @@ 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. @@ -1574,7 +1564,7 @@ I = MInfo.vregsRequired.begin(), E = MInfo.vregsRequired.end(); I != E; ++I) { report("Virtual register defs don't dominate all uses.", MF); - report_context_vreg(*I); + report_context_reg(*I); } } Index: lib/CodeGen/TargetRegisterInfo.cpp =================================================================== --- lib/CodeGen/TargetRegisterInfo.cpp +++ lib/CodeGen/TargetRegisterInfo.cpp @@ -40,6 +40,37 @@ TargetRegisterInfo::~TargetRegisterInfo() {} +void TargetRegisterInfo::markSuperRegs(BitVector &RegisterSet, unsigned Reg) + const { + for (MCSuperRegIterator AI(Reg, this, true); AI.isValid(); ++AI) + RegisterSet.set(*AI); +} + +void TargetRegisterInfo::assertAllSuperRegsMarked(const BitVector &RegisterSet) + const { +#ifndef NDEBUG + // 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]) { + errs() << "Error: Super register " << PrintReg(*SR, this) + << " of reserved register " << PrintReg(Reg, this) + << " is not reserved.\n"; + report_fatal_error("Invalid register info."); + } + + // We transitively check superregs. So we can remember this for later + // to avoid compiletime explosion in deep register hierarchies. + Checked.set(*SR); + } + } +#endif +} + namespace llvm { Printable PrintReg(unsigned Reg, const TargetRegisterInfo *TRI, Index: lib/Target/AArch64/AArch64RegisterInfo.cpp =================================================================== --- lib/Target/AArch64/AArch64RegisterInfo.cpp +++ lib/Target/AArch64/AArch64RegisterInfo.cpp @@ -118,26 +118,27 @@ // 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().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); } + assertAllSuperRegsMarked(Reserved); return Reserved; } Index: lib/Target/ARM/ARMBaseRegisterInfo.cpp =================================================================== --- lib/Target/ARM/ARMBaseRegisterInfo.cpp +++ lib/Target/ARM/ARMBaseRegisterInfo.cpp @@ -167,27 +167,29 @@ // 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); + assertAllSuperRegsMarked(Reserved); return Reserved; }