summaryrefslogtreecommitdiffstats
path: root/llvm/lib/CodeGen/TailDuplicator.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'llvm/lib/CodeGen/TailDuplicator.cpp')
-rw-r--r--llvm/lib/CodeGen/TailDuplicator.cpp114
1 files changed, 80 insertions, 34 deletions
diff --git a/llvm/lib/CodeGen/TailDuplicator.cpp b/llvm/lib/CodeGen/TailDuplicator.cpp
index 1ea15afc170..eb0fdc9c3e2 100644
--- a/llvm/lib/CodeGen/TailDuplicator.cpp
+++ b/llvm/lib/CodeGen/TailDuplicator.cpp
@@ -303,20 +303,21 @@ void TailDuplicator::addSSAUpdateEntry(unsigned OrigReg, unsigned NewReg,
/// source register that's contributed by PredBB and update SSA update map.
void TailDuplicator::processPHI(
MachineInstr *MI, MachineBasicBlock *TailBB, MachineBasicBlock *PredBB,
- DenseMap<unsigned, unsigned> &LocalVRMap,
- SmallVectorImpl<std::pair<unsigned, unsigned>> &Copies,
+ DenseMap<unsigned, RegSubRegPair> &LocalVRMap,
+ SmallVectorImpl<std::pair<unsigned, RegSubRegPair>> &Copies,
const DenseSet<unsigned> &RegsUsedByPhi, bool Remove) {
unsigned DefReg = MI->getOperand(0).getReg();
unsigned SrcOpIdx = getPHISrcRegOpIdx(MI, PredBB);
assert(SrcOpIdx && "Unable to find matching PHI source?");
unsigned SrcReg = MI->getOperand(SrcOpIdx).getReg();
+ unsigned SrcSubReg = MI->getOperand(SrcOpIdx).getSubReg();
const TargetRegisterClass *RC = MRI->getRegClass(DefReg);
- LocalVRMap.insert(std::make_pair(DefReg, SrcReg));
+ LocalVRMap.insert(std::make_pair(DefReg, RegSubRegPair(SrcReg, SrcSubReg)));
// Insert a copy from source to the end of the block. The def register is the
// available value liveout of the block.
unsigned NewDef = MRI->createVirtualRegister(RC);
- Copies.push_back(std::make_pair(NewDef, SrcReg));
+ Copies.push_back(std::make_pair(NewDef, RegSubRegPair(SrcReg, SrcSubReg)));
if (isDefLiveOut(DefReg, TailBB, MRI) || RegsUsedByPhi.count(DefReg))
addSSAUpdateEntry(DefReg, NewDef, PredBB);
@@ -334,7 +335,8 @@ void TailDuplicator::processPHI(
/// the source operands due to earlier PHI translation.
void TailDuplicator::duplicateInstruction(
MachineInstr *MI, MachineBasicBlock *TailBB, MachineBasicBlock *PredBB,
- MachineFunction &MF, DenseMap<unsigned, unsigned> &LocalVRMap,
+ MachineFunction &MF,
+ DenseMap<unsigned, RegSubRegPair> &LocalVRMap,
const DenseSet<unsigned> &UsedByPhi) {
MachineInstr *NewMI = TII->duplicate(MI, MF);
if (PreRegAlloc) {
@@ -349,17 +351,63 @@ void TailDuplicator::duplicateInstruction(
const TargetRegisterClass *RC = MRI->getRegClass(Reg);
unsigned NewReg = MRI->createVirtualRegister(RC);
MO.setReg(NewReg);
- LocalVRMap.insert(std::make_pair(Reg, NewReg));
+ LocalVRMap.insert(std::make_pair(Reg, RegSubRegPair(NewReg, 0)));
if (isDefLiveOut(Reg, TailBB, MRI) || UsedByPhi.count(Reg))
addSSAUpdateEntry(Reg, NewReg, PredBB);
} else {
- DenseMap<unsigned, unsigned>::iterator VI = LocalVRMap.find(Reg);
+ auto VI = LocalVRMap.find(Reg);
if (VI != LocalVRMap.end()) {
- MO.setReg(VI->second);
+ // Need to make sure that the register class of the mapped register
+ // will satisfy the constraints of the class of the register being
+ // replaced.
+ auto *OrigRC = MRI->getRegClass(Reg);
+ auto *MappedRC = MRI->getRegClass(VI->second.Reg);
+ const TargetRegisterClass *ConstrRC;
+ if (VI->second.SubReg != 0) {
+ ConstrRC = TRI->getMatchingSuperRegClass(MappedRC, OrigRC,
+ VI->second.SubReg);
+ if (ConstrRC) {
+ // The actual constraining (as in "find appropriate new class")
+ // is done by getMatchingSuperRegClass, so now we only need to
+ // change the class of the mapped register.
+ MRI->setRegClass(VI->second.Reg, ConstrRC);
+ }
+ } else {
+ // For mapped registers that do not have sub-registers, simply
+ // restrict their class to match the original one.
+ ConstrRC = MRI->constrainRegClass(VI->second.Reg, OrigRC);
+ }
+
+ if (ConstrRC) {
+ // If the class constraining succeeded, we can simply replace
+ // the old register with the mapped one.
+ MO.setReg(VI->second.Reg);
+ // We have Reg -> VI.Reg:VI.SubReg, so if Reg is used with a
+ // sub-register, we need to compose the sub-register indices.
+ MO.setSubReg(TRI->composeSubRegIndices(MO.getSubReg(),
+ VI->second.SubReg));
+ } else {
+ // The direct replacement is not possible, due to failing register
+ // class constraints. An explicit COPY is necessary. Create one
+ // that can be reused
+ auto *NewRC = MI->getRegClassConstraint(i, TII, TRI);
+ if (NewRC == nullptr)
+ NewRC = OrigRC;
+ unsigned NewReg = MRI->createVirtualRegister(NewRC);
+ BuildMI(*PredBB, MI, MI->getDebugLoc(),
+ TII->get(TargetOpcode::COPY), NewReg)
+ .addReg(VI->second.Reg, 0, VI->second.SubReg);
+ LocalVRMap.erase(VI);
+ LocalVRMap.insert(std::make_pair(Reg, RegSubRegPair(NewReg, 0)));
+ MO.setReg(NewReg);
+ // The composed VI.Reg:VI.SubReg is replaced with NewReg, which
+ // is equivalent to the whole register Reg. Hence, Reg:subreg
+ // is same as NewReg:subreg, so keep the sub-register index
+ // unchanged.
+ }
// Clear any kill flags from this operand. The new register could
// have uses after this one, so kills are not valid here.
MO.setIsKill(false);
- MRI->constrainRegClass(VI->second, MRI->getRegClass(Reg));
}
}
}
@@ -734,8 +782,8 @@ bool TailDuplicator::tailDuplicate(MachineFunction &MF, bool IsSimple,
}
// Clone the contents of TailBB into PredBB.
- DenseMap<unsigned, unsigned> LocalVRMap;
- SmallVector<std::pair<unsigned, unsigned>, 4> CopyInfos;
+ DenseMap<unsigned, RegSubRegPair> LocalVRMap;
+ SmallVector<std::pair<unsigned, RegSubRegPair>, 4> CopyInfos;
// Use instr_iterator here to properly handle bundles, e.g.
// ARM Thumb2 IT block.
MachineBasicBlock::instr_iterator I = TailBB->instr_begin();
@@ -752,12 +800,7 @@ bool TailDuplicator::tailDuplicate(MachineFunction &MF, bool IsSimple,
duplicateInstruction(MI, TailBB, PredBB, MF, LocalVRMap, UsedByPhi);
}
}
- MachineBasicBlock::iterator Loc = PredBB->getFirstTerminator();
- for (unsigned i = 0, e = CopyInfos.size(); i != e; ++i) {
- Copies.push_back(BuildMI(*PredBB, Loc, DebugLoc(),
- TII->get(TargetOpcode::COPY), CopyInfos[i].first)
- .addReg(CopyInfos[i].second));
- }
+ appendCopies(PredBB, CopyInfos, Copies);
// Simplify
TII->AnalyzeBranch(*PredBB, PredTBB, PredFBB, PredCond, true);
@@ -792,8 +835,8 @@ bool TailDuplicator::tailDuplicate(MachineFunction &MF, bool IsSimple,
DEBUG(dbgs() << "\nMerging into block: " << *PrevBB
<< "From MBB: " << *TailBB);
if (PreRegAlloc) {
- DenseMap<unsigned, unsigned> LocalVRMap;
- SmallVector<std::pair<unsigned, unsigned>, 4> CopyInfos;
+ DenseMap<unsigned, RegSubRegPair> LocalVRMap;
+ SmallVector<std::pair<unsigned, RegSubRegPair>, 4> CopyInfos;
MachineBasicBlock::iterator I = TailBB->begin();
// Process PHI instructions first.
while (I != TailBB->end() && I->isPHI()) {
@@ -812,13 +855,7 @@ bool TailDuplicator::tailDuplicate(MachineFunction &MF, bool IsSimple,
duplicateInstruction(MI, TailBB, PrevBB, MF, LocalVRMap, UsedByPhi);
MI->eraseFromParent();
}
- MachineBasicBlock::iterator Loc = PrevBB->getFirstTerminator();
- for (unsigned i = 0, e = CopyInfos.size(); i != e; ++i) {
- Copies.push_back(BuildMI(*PrevBB, Loc, DebugLoc(),
- TII->get(TargetOpcode::COPY),
- CopyInfos[i].first)
- .addReg(CopyInfos[i].second));
- }
+ appendCopies(PrevBB, CopyInfos, Copies);
} else {
// No PHIs to worry about, just splice the instructions over.
PrevBB->splice(PrevBB->end(), TailBB, TailBB->begin(), TailBB->end());
@@ -863,8 +900,8 @@ bool TailDuplicator::tailDuplicate(MachineFunction &MF, bool IsSimple,
if (PredBB->succ_size() != 1)
continue;
- DenseMap<unsigned, unsigned> LocalVRMap;
- SmallVector<std::pair<unsigned, unsigned>, 4> CopyInfos;
+ DenseMap<unsigned, RegSubRegPair> LocalVRMap;
+ SmallVector<std::pair<unsigned, RegSubRegPair>, 4> CopyInfos;
MachineBasicBlock::iterator I = TailBB->begin();
// Process PHI instructions first.
while (I != TailBB->end() && I->isPHI()) {
@@ -873,17 +910,26 @@ bool TailDuplicator::tailDuplicate(MachineFunction &MF, bool IsSimple,
MachineInstr *MI = &*I++;
processPHI(MI, TailBB, PredBB, LocalVRMap, CopyInfos, UsedByPhi, false);
}
- MachineBasicBlock::iterator Loc = PredBB->getFirstTerminator();
- for (unsigned i = 0, e = CopyInfos.size(); i != e; ++i) {
- Copies.push_back(BuildMI(*PredBB, Loc, DebugLoc(),
- TII->get(TargetOpcode::COPY), CopyInfos[i].first)
- .addReg(CopyInfos[i].second));
- }
+ appendCopies(PredBB, CopyInfos, Copies);
}
return Changed;
}
+/// At the end of the block \p MBB generate COPY instructions between registers
+/// described by \p CopyInfos. Append resulting instructions to \p Copies.
+void TailDuplicator::appendCopies(MachineBasicBlock *MBB,
+ SmallVectorImpl<std::pair<unsigned,RegSubRegPair>> &CopyInfos,
+ SmallVectorImpl<MachineInstr*> &Copies) {
+ MachineBasicBlock::iterator Loc = MBB->getFirstTerminator();
+ const MCInstrDesc &CopyD = TII->get(TargetOpcode::COPY);
+ for (auto &CI : CopyInfos) {
+ auto C = BuildMI(*MBB, Loc, DebugLoc(), CopyD, CI.first)
+ .addReg(CI.second.Reg, 0, CI.second.SubReg);
+ Copies.push_back(C);
+ }
+}
+
/// Remove the specified dead machine basic block from the function, updating
/// the CFG.
void TailDuplicator::removeDeadBlock(MachineBasicBlock *MBB) {
OpenPOWER on IntegriCloud