aboutsummaryrefslogtreecommitdiff
path: root/llvm/lib/CodeGen/PHIElimination.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'llvm/lib/CodeGen/PHIElimination.cpp')
-rw-r--r--llvm/lib/CodeGen/PHIElimination.cpp57
1 files changed, 42 insertions, 15 deletions
diff --git a/llvm/lib/CodeGen/PHIElimination.cpp b/llvm/lib/CodeGen/PHIElimination.cpp
index 592972f..4fde4ec7 100644
--- a/llvm/lib/CodeGen/PHIElimination.cpp
+++ b/llvm/lib/CodeGen/PHIElimination.cpp
@@ -83,7 +83,8 @@ namespace {
bool EliminatePHINodes(MachineFunction &MF, MachineBasicBlock &MBB);
void LowerPHINode(MachineBasicBlock &MBB,
- MachineBasicBlock::iterator LastPHIIt);
+ MachineBasicBlock::iterator LastPHIIt,
+ bool AllEdgesCritical);
/// analyzePHINodes - Gather information about the PHI nodes in
/// here. In particular, we want to map the number of uses of a virtual
@@ -191,7 +192,8 @@ bool PHIElimination::runOnMachineFunction(MachineFunction &MF) {
MRI->leaveSSA();
// Populate VRegPHIUseCount
- analyzePHINodes(MF);
+ if (LV || LIS)
+ analyzePHINodes(MF);
// Eliminate PHI instructions by inserting copies into predecessor blocks.
for (auto &MBB : MF)
@@ -239,8 +241,20 @@ bool PHIElimination::EliminatePHINodes(MachineFunction &MF,
MachineBasicBlock::iterator LastPHIIt =
std::prev(MBB.SkipPHIsAndLabels(MBB.begin()));
+ // If all incoming edges are critical, we try to deduplicate identical PHIs so
+ // that we generate fewer copies. If at any edge is non-critical, we either
+ // have less than two predecessors (=> no PHIs) or a predecessor has only us
+ // as a successor (=> identical PHI node can't occur in different block).
+ bool AllEdgesCritical = MBB.pred_size() >= 2;
+ for (MachineBasicBlock *Pred : MBB.predecessors()) {
+ if (Pred->succ_size() < 2) {
+ AllEdgesCritical = false;
+ break;
+ }
+ }
+
while (MBB.front().isPHI())
- LowerPHINode(MBB, LastPHIIt);
+ LowerPHINode(MBB, LastPHIIt, AllEdgesCritical);
return true;
}
@@ -267,7 +281,8 @@ static bool allPhiOperandsUndefined(const MachineInstr &MPhi,
}
/// LowerPHINode - Lower the PHI node at the top of the specified block.
void PHIElimination::LowerPHINode(MachineBasicBlock &MBB,
- MachineBasicBlock::iterator LastPHIIt) {
+ MachineBasicBlock::iterator LastPHIIt,
+ bool AllEdgesCritical) {
++NumLowered;
MachineBasicBlock::iterator AfterPHIsIt = std::next(LastPHIIt);
@@ -283,6 +298,7 @@ void PHIElimination::LowerPHINode(MachineBasicBlock &MBB,
// Create a new register for the incoming PHI arguments.
MachineFunction &MF = *MBB.getParent();
unsigned IncomingReg = 0;
+ bool EliminateNow = true; // delay elimination of nodes in LoweredPHIs
bool reusedIncoming = false; // Is IncomingReg reused from an earlier PHI?
// Insert a register to register copy at the top of the current block (but
@@ -297,19 +313,28 @@ void PHIElimination::LowerPHINode(MachineBasicBlock &MBB,
TII->get(TargetOpcode::IMPLICIT_DEF), DestReg);
else {
// Can we reuse an earlier PHI node? This only happens for critical edges,
- // typically those created by tail duplication.
- unsigned &entry = LoweredPHIs[MPhi];
- if (entry) {
+ // typically those created by tail duplication. Typically, an identical PHI
+ // node can't occur, so avoid hashing/storing such PHIs, which is somewhat
+ // expensive.
+ unsigned *Entry = nullptr;
+ if (AllEdgesCritical)
+ Entry = &LoweredPHIs[MPhi];
+ if (Entry && *Entry) {
// An identical PHI node was already lowered. Reuse the incoming register.
- IncomingReg = entry;
+ IncomingReg = *Entry;
reusedIncoming = true;
++NumReused;
LLVM_DEBUG(dbgs() << "Reusing " << printReg(IncomingReg) << " for "
<< *MPhi);
} else {
const TargetRegisterClass *RC = MF.getRegInfo().getRegClass(DestReg);
- entry = IncomingReg = MF.getRegInfo().createVirtualRegister(RC);
+ IncomingReg = MF.getRegInfo().createVirtualRegister(RC);
+ if (Entry) {
+ EliminateNow = false;
+ *Entry = IncomingReg;
+ }
}
+
// Give the target possiblity to handle special cases fallthrough otherwise
PHICopy = TII->createPHIDestinationCopy(MBB, AfterPHIsIt, MPhi->getDebugLoc(),
IncomingReg, DestReg);
@@ -445,11 +470,13 @@ void PHIElimination::LowerPHINode(MachineBasicBlock &MBB,
}
// Adjust the VRegPHIUseCount map to account for the removal of this PHI node.
- for (unsigned i = 1; i != MPhi->getNumOperands(); i += 2) {
- if (!MPhi->getOperand(i).isUndef()) {
- --VRegPHIUseCount[BBVRegPair(
- MPhi->getOperand(i + 1).getMBB()->getNumber(),
- MPhi->getOperand(i).getReg())];
+ if (LV || LIS) {
+ for (unsigned i = 1; i != MPhi->getNumOperands(); i += 2) {
+ if (!MPhi->getOperand(i).isUndef()) {
+ --VRegPHIUseCount[BBVRegPair(
+ MPhi->getOperand(i + 1).getMBB()->getNumber(),
+ MPhi->getOperand(i).getReg())];
+ }
}
}
@@ -646,7 +673,7 @@ void PHIElimination::LowerPHINode(MachineBasicBlock &MBB,
}
// Really delete the PHI instruction now, if it is not in the LoweredPHIs map.
- if (reusedIncoming || !IncomingReg) {
+ if (EliminateNow) {
if (LIS)
LIS->RemoveMachineInstrFromMaps(*MPhi);
MF.deleteMachineInstr(MPhi);