mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2025-08-09 11:25:55 +00:00
Handle extra Tail predecessors in if-conversion.
It is still possible to if-convert if the tail block has extra predecessors, but the tail phis must be rewritten instead of being removed. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@161781 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
@@ -140,6 +140,12 @@ private:
|
|||||||
/// Find a valid insertion point in Head.
|
/// Find a valid insertion point in Head.
|
||||||
bool findInsertionPoint();
|
bool findInsertionPoint();
|
||||||
|
|
||||||
|
/// Replace PHI instructions in Tail with selects.
|
||||||
|
void replacePHIInstrs();
|
||||||
|
|
||||||
|
/// Insert selects and rewrite PHI operands to use them.
|
||||||
|
void rewritePHIOperands();
|
||||||
|
|
||||||
public:
|
public:
|
||||||
/// runOnMachineFunction - Initialize per-function data structures.
|
/// runOnMachineFunction - Initialize per-function data structures.
|
||||||
void runOnMachineFunction(MachineFunction &MF) {
|
void runOnMachineFunction(MachineFunction &MF) {
|
||||||
@@ -343,11 +349,7 @@ bool SSAIfConv::canConvertIf(MachineBasicBlock *MBB) {
|
|||||||
if (Succ0->pred_size() != 1 || Succ0->succ_size() != 1)
|
if (Succ0->pred_size() != 1 || Succ0->succ_size() != 1)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
// We could support additional Tail predecessors by updating phis instead of
|
|
||||||
// eliminating them. Let's see an example where it matters first.
|
|
||||||
Tail = Succ0->succ_begin()[0];
|
Tail = Succ0->succ_begin()[0];
|
||||||
if (Tail->pred_size() != 2)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
// This is not a triangle.
|
// This is not a triangle.
|
||||||
if (Tail != Succ1) {
|
if (Tail != Succ1) {
|
||||||
@@ -437,21 +439,11 @@ bool SSAIfConv::canConvertIf(MachineBasicBlock *MBB) {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// replacePHIInstrs - Completely replace PHI instructions with selects.
|
||||||
/// convertIf - Execute the if conversion after canConvertIf has determined the
|
/// This is possible when the only Tail predecessors are the if-converted
|
||||||
/// feasibility.
|
/// blocks.
|
||||||
///
|
void SSAIfConv::replacePHIInstrs() {
|
||||||
/// Any basic blocks erased will be added to RemovedBlocks.
|
assert(Tail->pred_size() == 2 && "Cannot replace PHIs");
|
||||||
///
|
|
||||||
void SSAIfConv::convertIf(SmallVectorImpl<MachineBasicBlock*> &RemovedBlocks) {
|
|
||||||
assert(Head && Tail && TBB && FBB && "Call canConvertIf first.");
|
|
||||||
|
|
||||||
// Move all instructions into Head, except for the terminators.
|
|
||||||
if (TBB != Tail)
|
|
||||||
Head->splice(InsertionPoint, TBB, TBB->begin(), TBB->getFirstTerminator());
|
|
||||||
if (FBB != Tail)
|
|
||||||
Head->splice(InsertionPoint, FBB, FBB->begin(), FBB->getFirstTerminator());
|
|
||||||
|
|
||||||
MachineBasicBlock::iterator FirstTerm = Head->getFirstTerminator();
|
MachineBasicBlock::iterator FirstTerm = Head->getFirstTerminator();
|
||||||
assert(FirstTerm != Head->end() && "No terminators");
|
assert(FirstTerm != Head->end() && "No terminators");
|
||||||
DebugLoc HeadDL = FirstTerm->getDebugLoc();
|
DebugLoc HeadDL = FirstTerm->getDebugLoc();
|
||||||
@@ -467,6 +459,60 @@ void SSAIfConv::convertIf(SmallVectorImpl<MachineBasicBlock*> &RemovedBlocks) {
|
|||||||
PI.PHI->eraseFromParent();
|
PI.PHI->eraseFromParent();
|
||||||
PI.PHI = 0;
|
PI.PHI = 0;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// rewritePHIOperands - When there are additional Tail predecessors, insert
|
||||||
|
/// select instructions in Head and rewrite PHI operands to use the selects.
|
||||||
|
/// Keep the PHI instructions in Tail to handle the other predecessors.
|
||||||
|
void SSAIfConv::rewritePHIOperands() {
|
||||||
|
MachineBasicBlock::iterator FirstTerm = Head->getFirstTerminator();
|
||||||
|
assert(FirstTerm != Head->end() && "No terminators");
|
||||||
|
DebugLoc HeadDL = FirstTerm->getDebugLoc();
|
||||||
|
|
||||||
|
// Convert all PHIs to select instructions inserted before FirstTerm.
|
||||||
|
for (unsigned i = 0, e = PHIs.size(); i != e; ++i) {
|
||||||
|
PHIInfo &PI = PHIs[i];
|
||||||
|
DEBUG(dbgs() << "If-converting " << *PI.PHI);
|
||||||
|
unsigned PHIDst = PI.PHI->getOperand(0).getReg();
|
||||||
|
unsigned DstReg = MRI->createVirtualRegister(MRI->getRegClass(PHIDst));
|
||||||
|
TII->insertSelect(*Head, FirstTerm, HeadDL, DstReg, Cond, PI.TReg, PI.FReg);
|
||||||
|
DEBUG(dbgs() << " --> " << *llvm::prior(FirstTerm));
|
||||||
|
|
||||||
|
// Rewrite PHI operands TPred -> (DstReg, Head), remove FPred.
|
||||||
|
for (unsigned i = PI.PHI->getNumOperands(); i != 1; i -= 2) {
|
||||||
|
MachineBasicBlock *MBB = PI.PHI->getOperand(i-1).getMBB();
|
||||||
|
if (MBB == getTPred()) {
|
||||||
|
PI.PHI->getOperand(i-1).setMBB(Head);
|
||||||
|
PI.PHI->getOperand(i-2).setReg(DstReg);
|
||||||
|
} else if (MBB == getFPred()) {
|
||||||
|
PI.PHI->RemoveOperand(i-1);
|
||||||
|
PI.PHI->RemoveOperand(i-2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
DEBUG(dbgs() << " --> " << *PI.PHI);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// convertIf - Execute the if conversion after canConvertIf has determined the
|
||||||
|
/// feasibility.
|
||||||
|
///
|
||||||
|
/// Any basic blocks erased will be added to RemovedBlocks.
|
||||||
|
///
|
||||||
|
void SSAIfConv::convertIf(SmallVectorImpl<MachineBasicBlock*> &RemovedBlocks) {
|
||||||
|
assert(Head && Tail && TBB && FBB && "Call canConvertIf first.");
|
||||||
|
|
||||||
|
// Move all instructions into Head, except for the terminators.
|
||||||
|
if (TBB != Tail)
|
||||||
|
Head->splice(InsertionPoint, TBB, TBB->begin(), TBB->getFirstTerminator());
|
||||||
|
if (FBB != Tail)
|
||||||
|
Head->splice(InsertionPoint, FBB, FBB->begin(), FBB->getFirstTerminator());
|
||||||
|
|
||||||
|
// Are there extra Tail predecessors?
|
||||||
|
bool ExtraPreds = Tail->pred_size() != 2;
|
||||||
|
if (ExtraPreds)
|
||||||
|
rewritePHIOperands();
|
||||||
|
else
|
||||||
|
replacePHIInstrs();
|
||||||
|
|
||||||
// Fix up the CFG, temporarily leave Head without any successors.
|
// Fix up the CFG, temporarily leave Head without any successors.
|
||||||
Head->removeSuccessor(TBB);
|
Head->removeSuccessor(TBB);
|
||||||
@@ -478,6 +524,7 @@ void SSAIfConv::convertIf(SmallVectorImpl<MachineBasicBlock*> &RemovedBlocks) {
|
|||||||
|
|
||||||
// Fix up Head's terminators.
|
// Fix up Head's terminators.
|
||||||
// It should become a single branch or a fallthrough.
|
// It should become a single branch or a fallthrough.
|
||||||
|
DebugLoc HeadDL = Head->getFirstTerminator()->getDebugLoc();
|
||||||
TII->RemoveBranch(*Head);
|
TII->RemoveBranch(*Head);
|
||||||
|
|
||||||
// Erase the now empty conditional blocks. It is likely that Head can fall
|
// Erase the now empty conditional blocks. It is likely that Head can fall
|
||||||
@@ -492,7 +539,7 @@ void SSAIfConv::convertIf(SmallVectorImpl<MachineBasicBlock*> &RemovedBlocks) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
assert(Head->succ_empty() && "Additional head successors?");
|
assert(Head->succ_empty() && "Additional head successors?");
|
||||||
if (Head->isLayoutSuccessor(Tail)) {
|
if (!ExtraPreds && Head->isLayoutSuccessor(Tail)) {
|
||||||
// Splice Tail onto the end of Head.
|
// Splice Tail onto the end of Head.
|
||||||
DEBUG(dbgs() << "Joining tail BB#" << Tail->getNumber()
|
DEBUG(dbgs() << "Joining tail BB#" << Tail->getNumber()
|
||||||
<< " into head BB#" << Head->getNumber() << '\n');
|
<< " into head BB#" << Head->getNumber() << '\n');
|
||||||
|
@@ -37,3 +37,33 @@ do.end:
|
|||||||
%sub = sub nsw i32 %max.1, %min.1
|
%sub = sub nsw i32 %max.1, %min.1
|
||||||
ret i32 %sub
|
ret i32 %sub
|
||||||
}
|
}
|
||||||
|
|
||||||
|
; CHECK: multipreds
|
||||||
|
; Deal with alternative tail predecessors
|
||||||
|
; CHECK-NOT: LBB
|
||||||
|
; CHECK: cmov
|
||||||
|
; CHECK-NOT: LBB
|
||||||
|
; CHECK: cmov
|
||||||
|
; CHECK-NOT: LBB
|
||||||
|
; CHECK: fprintf
|
||||||
|
|
||||||
|
define void @multipreds(i32 %sw) nounwind uwtable ssp {
|
||||||
|
entry:
|
||||||
|
switch i32 %sw, label %if.then29 [
|
||||||
|
i32 0, label %if.then37
|
||||||
|
i32 127, label %if.end41
|
||||||
|
]
|
||||||
|
|
||||||
|
if.then29:
|
||||||
|
br label %if.end41
|
||||||
|
|
||||||
|
if.then37:
|
||||||
|
br label %if.end41
|
||||||
|
|
||||||
|
if.end41:
|
||||||
|
%exit_status.0 = phi i32 [ 2, %if.then29 ], [ 0, %if.then37 ], [ 66, %entry ]
|
||||||
|
call void (...)* @fprintf(i32 %exit_status.0) nounwind
|
||||||
|
unreachable
|
||||||
|
}
|
||||||
|
|
||||||
|
declare void @fprintf(...) nounwind
|
||||||
|
Reference in New Issue
Block a user