aboutsummaryrefslogtreecommitdiff
path: root/llvm/lib/CodeGen/RegAllocFast.cpp
diff options
context:
space:
mode:
authorDimitry Andric <dim@FreeBSD.org>2021-07-29 20:15:26 +0000
committerDimitry Andric <dim@FreeBSD.org>2021-07-29 20:15:26 +0000
commit344a3780b2e33f6ca763666c380202b18aab72a3 (patch)
treef0b203ee6eb71d7fdd792373e3c81eb18d6934dd /llvm/lib/CodeGen/RegAllocFast.cpp
parentb60736ec1405bb0a8dd40989f67ef4c93da068ab (diff)
downloadsrc-344a3780b2e33f6ca763666c380202b18aab72a3.tar.gz
src-344a3780b2e33f6ca763666c380202b18aab72a3.zip
the upstream release/13.x branch was created.
Diffstat (limited to 'llvm/lib/CodeGen/RegAllocFast.cpp')
-rw-r--r--llvm/lib/CodeGen/RegAllocFast.cpp176
1 files changed, 111 insertions, 65 deletions
diff --git a/llvm/lib/CodeGen/RegAllocFast.cpp b/llvm/lib/CodeGen/RegAllocFast.cpp
index 6e548d4a93c8..707161d5a8b0 100644
--- a/llvm/lib/CodeGen/RegAllocFast.cpp
+++ b/llvm/lib/CodeGen/RegAllocFast.cpp
@@ -27,6 +27,7 @@
#include "llvm/CodeGen/MachineInstrBuilder.h"
#include "llvm/CodeGen/MachineOperand.h"
#include "llvm/CodeGen/MachineRegisterInfo.h"
+#include "llvm/CodeGen/RegAllocCommon.h"
#include "llvm/CodeGen/RegAllocRegistry.h"
#include "llvm/CodeGen/RegisterClassInfo.h"
#include "llvm/CodeGen/TargetInstrInfo.h"
@@ -69,7 +70,13 @@ namespace {
public:
static char ID;
- RegAllocFast() : MachineFunctionPass(ID), StackSlotForVirtReg(-1) {}
+ RegAllocFast(const RegClassFilterFunc F = allocateAllRegClasses,
+ bool ClearVirtRegs_ = true) :
+ MachineFunctionPass(ID),
+ ShouldAllocateClass(F),
+ StackSlotForVirtReg(-1),
+ ClearVirtRegs(ClearVirtRegs_) {
+ }
private:
MachineFrameInfo *MFI;
@@ -77,6 +84,7 @@ namespace {
const TargetRegisterInfo *TRI;
const TargetInstrInfo *TII;
RegisterClassInfo RegClassInfo;
+ const RegClassFilterFunc ShouldAllocateClass;
/// Basic block currently being allocated.
MachineBasicBlock *MBB;
@@ -84,6 +92,8 @@ namespace {
/// Maps virtual regs to the frame index where these values are spilled.
IndexedMap<int, VirtReg2IndexFunctor> StackSlotForVirtReg;
+ bool ClearVirtRegs;
+
/// Everything we know about a live virtual register.
struct LiveReg {
MachineInstr *LastUse = nullptr; ///< Last instr to use reg.
@@ -108,7 +118,7 @@ namespace {
/// Stores assigned virtual registers present in the bundle MI.
DenseMap<Register, MCPhysReg> BundleVirtRegsMap;
- DenseMap<unsigned, SmallVector<MachineInstr *, 2>> LiveDbgValueMap;
+ DenseMap<unsigned, SmallVector<MachineOperand *, 2>> LiveDbgValueMap;
/// List of DBG_VALUE that we encountered without the vreg being assigned
/// because they were placed after the last use of the vreg.
DenseMap<unsigned, SmallVector<MachineInstr *, 1>> DanglingDbgValues;
@@ -147,6 +157,8 @@ namespace {
RegUnitSet UsedInInstr;
RegUnitSet PhysRegUses;
SmallVector<uint16_t, 8> DefOperandIndexes;
+ // Register masks attached to the current instruction.
+ SmallVector<const uint32_t *> RegMasks;
void setPhysRegState(MCPhysReg PhysReg, unsigned NewState);
bool isPhysRegFree(MCPhysReg PhysReg) const;
@@ -157,8 +169,17 @@ namespace {
UsedInInstr.insert(*Units);
}
+ // Check if physreg is clobbered by instruction's regmask(s).
+ bool isClobberedByRegMasks(MCPhysReg PhysReg) const {
+ return llvm::any_of(RegMasks, [PhysReg](const uint32_t *Mask) {
+ return MachineOperand::clobbersPhysReg(Mask, PhysReg);
+ });
+ }
+
/// Check if a physreg or any of its aliases are used in this instruction.
bool isRegUsedInInstr(MCPhysReg PhysReg, bool LookAtPhysRegUses) const {
+ if (LookAtPhysRegUses && isClobberedByRegMasks(PhysReg))
+ return true;
for (MCRegUnitIterator Units(PhysReg, TRI); Units.isValid(); ++Units) {
if (UsedInInstr.count(*Units))
return true;
@@ -202,8 +223,12 @@ namespace {
}
MachineFunctionProperties getSetProperties() const override {
- return MachineFunctionProperties().set(
+ if (ClearVirtRegs) {
+ return MachineFunctionProperties().set(
MachineFunctionProperties::Property::NoVRegs);
+ }
+
+ return MachineFunctionProperties();
}
MachineFunctionProperties getClearedProperties() const override {
@@ -406,9 +431,15 @@ void RegAllocFast::spill(MachineBasicBlock::iterator Before, Register VirtReg,
// When we spill a virtual register, we will have spill instructions behind
// every definition of it, meaning we can switch all the DBG_VALUEs over
// to just reference the stack slot.
- SmallVectorImpl<MachineInstr *> &LRIDbgValues = LiveDbgValueMap[VirtReg];
- for (MachineInstr *DBG : LRIDbgValues) {
- MachineInstr *NewDV = buildDbgValueForSpill(*MBB, Before, *DBG, FI);
+ SmallVectorImpl<MachineOperand *> &LRIDbgOperands = LiveDbgValueMap[VirtReg];
+ SmallDenseMap<MachineInstr *, SmallVector<const MachineOperand *>>
+ SpilledOperandsMap;
+ for (MachineOperand *MO : LRIDbgOperands)
+ SpilledOperandsMap[MO->getParent()].push_back(MO);
+ for (auto MISpilledOperands : SpilledOperandsMap) {
+ MachineInstr &DBG = *MISpilledOperands.first;
+ MachineInstr *NewDV = buildDbgValueForSpill(
+ *MBB, Before, *MISpilledOperands.first, FI, MISpilledOperands.second);
assert(NewDV->getParent() == MBB && "dangling parent pointer");
(void)NewDV;
LLVM_DEBUG(dbgs() << "Inserting debug info due to spill:\n" << *NewDV);
@@ -424,14 +455,19 @@ void RegAllocFast::spill(MachineBasicBlock::iterator Before, Register VirtReg,
}
// Rewrite unassigned dbg_values to use the stack slot.
- MachineOperand &MO = DBG->getOperand(0);
- if (MO.isReg() && MO.getReg() == 0)
- updateDbgValueForSpill(*DBG, FI);
+ // TODO We can potentially do this for list debug values as well if we know
+ // how the dbg_values are getting unassigned.
+ if (DBG.isNonListDebugValue()) {
+ MachineOperand &MO = DBG.getDebugOperand(0);
+ if (MO.isReg() && MO.getReg() == 0) {
+ updateDbgValueForSpill(DBG, FI, 0);
+ }
+ }
}
// Now this register is spilled there is should not be any DBG_VALUE
// pointing to this register because they are all pointing to spilled value
// now.
- LRIDbgValues.clear();
+ LRIDbgOperands.clear();
}
/// Insert reload instruction for \p PhysReg before \p Before.
@@ -623,8 +659,7 @@ void RegAllocFast::assignDanglingDebugValues(MachineInstr &Definition,
SmallVectorImpl<MachineInstr*> &Dangling = UDBGValIter->second;
for (MachineInstr *DbgValue : Dangling) {
assert(DbgValue->isDebugValue());
- MachineOperand &MO = DbgValue->getOperand(0);
- if (!MO.isReg())
+ if (!DbgValue->hasDebugOperandForReg(VirtReg))
continue;
// Test whether the physreg survives from the definition to the DBG_VALUE.
@@ -639,9 +674,11 @@ void RegAllocFast::assignDanglingDebugValues(MachineInstr &Definition,
break;
}
}
- MO.setReg(SetToReg);
- if (SetToReg != 0)
- MO.setIsRenamable();
+ for (MachineOperand &MO : DbgValue->getDebugOperandsForReg(VirtReg)) {
+ MO.setReg(SetToReg);
+ if (SetToReg != 0)
+ MO.setIsRenamable();
+ }
}
Dangling.clear();
}
@@ -1076,6 +1113,7 @@ void RegAllocFast::allocateInstruction(MachineInstr &MI) {
// operands and early-clobbers.
UsedInInstr.clear();
+ RegMasks.clear();
BundleVirtRegsMap.clear();
// Scan for special cases; Apply pre-assigned register defs to state.
@@ -1115,6 +1153,7 @@ void RegAllocFast::allocateInstruction(MachineInstr &MI) {
}
} else if (MO.isRegMask()) {
HasRegMask = true;
+ RegMasks.push_back(MO.getRegMask());
}
}
@@ -1230,6 +1269,9 @@ void RegAllocFast::allocateInstruction(MachineInstr &MI) {
continue;
}
+ assert((!MO.isTied() || !isClobberedByRegMasks(MO.getReg())) &&
+ "tied def assigned to clobbered register");
+
// Do not free tied operands and early clobbers.
if (MO.isTied() || MO.isEarlyClobber())
continue;
@@ -1246,20 +1288,16 @@ void RegAllocFast::allocateInstruction(MachineInstr &MI) {
// Displace clobbered registers.
if (HasRegMask) {
- for (const MachineOperand &MO : MI.operands()) {
- if (MO.isRegMask()) {
- // MRI bookkeeping.
- MRI->addPhysRegsUsedFromRegMask(MO.getRegMask());
-
- // Displace clobbered registers.
- const uint32_t *Mask = MO.getRegMask();
- for (LiveRegMap::iterator LRI = LiveVirtRegs.begin(),
- LRIE = LiveVirtRegs.end(); LRI != LRIE; ++LRI) {
- MCPhysReg PhysReg = LRI->PhysReg;
- if (PhysReg != 0 && MachineOperand::clobbersPhysReg(Mask, PhysReg))
- displacePhysReg(MI, PhysReg);
- }
- }
+ assert(!RegMasks.empty() && "expected RegMask");
+ // MRI bookkeeping.
+ for (const auto *RM : RegMasks)
+ MRI->addPhysRegsUsedFromRegMask(RM);
+
+ // Displace clobbered registers.
+ for (const LiveReg &LR : LiveVirtRegs) {
+ MCPhysReg PhysReg = LR.PhysReg;
+ if (PhysReg != 0 && isClobberedByRegMasks(PhysReg))
+ displacePhysReg(MI, PhysReg);
}
}
@@ -1361,37 +1399,40 @@ void RegAllocFast::allocateInstruction(MachineInstr &MI) {
}
void RegAllocFast::handleDebugValue(MachineInstr &MI) {
- MachineOperand &MO = MI.getDebugOperand(0);
-
// Ignore DBG_VALUEs that aren't based on virtual registers. These are
// mostly constants and frame indices.
- if (!MO.isReg())
- return;
- Register Reg = MO.getReg();
- if (!Register::isVirtualRegister(Reg))
- return;
+ for (Register Reg : MI.getUsedDebugRegs()) {
+ if (!Register::isVirtualRegister(Reg))
+ continue;
- // Already spilled to a stackslot?
- int SS = StackSlotForVirtReg[Reg];
- if (SS != -1) {
- // Modify DBG_VALUE now that the value is in a spill slot.
- updateDbgValueForSpill(MI, SS);
- LLVM_DEBUG(dbgs() << "Rewrite DBG_VALUE for spilled memory: " << MI);
- return;
- }
+ // Already spilled to a stackslot?
+ int SS = StackSlotForVirtReg[Reg];
+ if (SS != -1) {
+ // Modify DBG_VALUE now that the value is in a spill slot.
+ updateDbgValueForSpill(MI, SS, Reg);
+ LLVM_DEBUG(dbgs() << "Rewrite DBG_VALUE for spilled memory: " << MI);
+ continue;
+ }
- // See if this virtual register has already been allocated to a physical
- // register or spilled to a stack slot.
- LiveRegMap::iterator LRI = findLiveVirtReg(Reg);
- if (LRI != LiveVirtRegs.end() && LRI->PhysReg) {
- setPhysReg(MI, MO, LRI->PhysReg);
- } else {
- DanglingDbgValues[Reg].push_back(&MI);
- }
+ // See if this virtual register has already been allocated to a physical
+ // register or spilled to a stack slot.
+ LiveRegMap::iterator LRI = findLiveVirtReg(Reg);
+ SmallVector<MachineOperand *> DbgOps;
+ for (MachineOperand &Op : MI.getDebugOperandsForReg(Reg))
+ DbgOps.push_back(&Op);
+
+ if (LRI != LiveVirtRegs.end() && LRI->PhysReg) {
+ // Update every use of Reg within MI.
+ for (auto &RegMO : DbgOps)
+ setPhysReg(MI, *RegMO, LRI->PhysReg);
+ } else {
+ DanglingDbgValues[Reg].push_back(&MI);
+ }
- // If Reg hasn't been spilled, put this DBG_VALUE in LiveDbgValueMap so
- // that future spills of Reg will have DBG_VALUEs.
- LiveDbgValueMap[Reg].push_back(&MI);
+ // If Reg hasn't been spilled, put this DBG_VALUE in LiveDbgValueMap so
+ // that future spills of Reg will have DBG_VALUEs.
+ LiveDbgValueMap[Reg].append(DbgOps.begin(), DbgOps.end());
+ }
}
void RegAllocFast::handleBundle(MachineInstr &MI) {
@@ -1425,10 +1466,8 @@ void RegAllocFast::allocateBasicBlock(MachineBasicBlock &MBB) {
RegUnitStates.assign(TRI->getNumRegUnits(), regFree);
assert(LiveVirtRegs.empty() && "Mapping not cleared from last block?");
- for (MachineBasicBlock *Succ : MBB.successors()) {
- for (const MachineBasicBlock::RegisterMaskPair &LI : Succ->liveins())
- setPhysRegState(LI.PhysReg, regPreAssigned);
- }
+ for (auto &LiveReg : MBB.liveouts())
+ setPhysRegState(LiveReg.PhysReg, regPreAssigned);
Coalesced.clear();
@@ -1473,13 +1512,12 @@ void RegAllocFast::allocateBasicBlock(MachineBasicBlock &MBB) {
for (auto &UDBGPair : DanglingDbgValues) {
for (MachineInstr *DbgValue : UDBGPair.second) {
assert(DbgValue->isDebugValue() && "expected DBG_VALUE");
- MachineOperand &MO = DbgValue->getOperand(0);
// Nothing to do if the vreg was spilled in the meantime.
- if (!MO.isReg())
+ if (!DbgValue->hasDebugOperandForReg(UDBGPair.first))
continue;
LLVM_DEBUG(dbgs() << "Register did not survive for " << *DbgValue
<< '\n');
- MO.setReg(0);
+ DbgValue->setDebugValueUndef();
}
}
DanglingDbgValues.clear();
@@ -1515,9 +1553,11 @@ bool RegAllocFast::runOnMachineFunction(MachineFunction &MF) {
for (MachineBasicBlock &MBB : MF)
allocateBasicBlock(MBB);
- // All machine operands and other references to virtual registers have been
- // replaced. Remove the virtual registers.
- MRI->clearVirtRegs();
+ if (ClearVirtRegs) {
+ // All machine operands and other references to virtual registers have been
+ // replaced. Remove the virtual registers.
+ MRI->clearVirtRegs();
+ }
StackSlotForVirtReg.clear();
LiveDbgValueMap.clear();
@@ -1527,3 +1567,9 @@ bool RegAllocFast::runOnMachineFunction(MachineFunction &MF) {
FunctionPass *llvm::createFastRegisterAllocator() {
return new RegAllocFast();
}
+
+FunctionPass *llvm::createFastRegisterAllocator(
+ std::function<bool(const TargetRegisterInfo &TRI,
+ const TargetRegisterClass &RC)> Ftor, bool ClearVirtRegs) {
+ return new RegAllocFast(Ftor, ClearVirtRegs);
+}