mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2025-01-20 12:31:40 +00:00
Run early if-conversion in domtree post-order.
This ordering allows nested if-conversion without using a work list, and it makes it possible to update the dominator tree on the fly as well. Any erased basic blocks will always be dominated by the current post-order position, so the domtree can be pruned without invalidating the iterator. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@160025 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
2b02688b6e
commit
1f523dc45e
@ -19,10 +19,12 @@
|
|||||||
#define DEBUG_TYPE "early-ifcvt"
|
#define DEBUG_TYPE "early-ifcvt"
|
||||||
#include "llvm/Function.h"
|
#include "llvm/Function.h"
|
||||||
#include "llvm/ADT/BitVector.h"
|
#include "llvm/ADT/BitVector.h"
|
||||||
|
#include "llvm/ADT/PostOrderIterator.h"
|
||||||
#include "llvm/ADT/SetVector.h"
|
#include "llvm/ADT/SetVector.h"
|
||||||
#include "llvm/ADT/SmallPtrSet.h"
|
#include "llvm/ADT/SmallPtrSet.h"
|
||||||
#include "llvm/ADT/SparseSet.h"
|
#include "llvm/ADT/SparseSet.h"
|
||||||
#include "llvm/CodeGen/MachineBranchProbabilityInfo.h"
|
#include "llvm/CodeGen/MachineBranchProbabilityInfo.h"
|
||||||
|
#include "llvm/CodeGen/MachineDominators.h"
|
||||||
#include "llvm/CodeGen/MachineFunction.h"
|
#include "llvm/CodeGen/MachineFunction.h"
|
||||||
#include "llvm/CodeGen/MachineFunctionPass.h"
|
#include "llvm/CodeGen/MachineFunctionPass.h"
|
||||||
#include "llvm/CodeGen/MachineRegisterInfo.h"
|
#include "llvm/CodeGen/MachineRegisterInfo.h"
|
||||||
@ -74,6 +76,7 @@ class SSAIfConv {
|
|||||||
const TargetRegisterInfo *TRI;
|
const TargetRegisterInfo *TRI;
|
||||||
MachineRegisterInfo *MRI;
|
MachineRegisterInfo *MRI;
|
||||||
|
|
||||||
|
public:
|
||||||
/// The block containing the conditional branch.
|
/// The block containing the conditional branch.
|
||||||
MachineBasicBlock *Head;
|
MachineBasicBlock *Head;
|
||||||
|
|
||||||
@ -90,9 +93,6 @@ class SSAIfConv {
|
|||||||
/// equal to Tail.
|
/// equal to Tail.
|
||||||
bool isTriangle() const { return TBB == Tail || FBB == Tail; }
|
bool isTriangle() const { return TBB == Tail || FBB == Tail; }
|
||||||
|
|
||||||
/// The branch condition determined by AnalyzeBranch.
|
|
||||||
SmallVector<MachineOperand, 4> Cond;
|
|
||||||
|
|
||||||
/// Information about each phi in the Tail block.
|
/// Information about each phi in the Tail block.
|
||||||
struct PHIInfo {
|
struct PHIInfo {
|
||||||
MachineInstr *PHI;
|
MachineInstr *PHI;
|
||||||
@ -106,6 +106,10 @@ class SSAIfConv {
|
|||||||
|
|
||||||
SmallVector<PHIInfo, 8> PHIs;
|
SmallVector<PHIInfo, 8> PHIs;
|
||||||
|
|
||||||
|
private:
|
||||||
|
/// The branch condition determined by AnalyzeBranch.
|
||||||
|
SmallVector<MachineOperand, 4> Cond;
|
||||||
|
|
||||||
/// Instructions in Head that define values used by the conditional blocks.
|
/// Instructions in Head that define values used by the conditional blocks.
|
||||||
/// The hoisted instructions must be inserted after these instructions.
|
/// The hoisted instructions must be inserted after these instructions.
|
||||||
SmallPtrSet<MachineInstr*, 8> InsertAfter;
|
SmallPtrSet<MachineInstr*, 8> InsertAfter;
|
||||||
@ -144,8 +148,8 @@ public:
|
|||||||
bool canConvertIf(MachineBasicBlock *MBB);
|
bool canConvertIf(MachineBasicBlock *MBB);
|
||||||
|
|
||||||
/// convertIf - If-convert the last block passed to canConvertIf(), assuming
|
/// convertIf - If-convert the last block passed to canConvertIf(), assuming
|
||||||
/// it is possible. Remove any erased blocks from WorkList
|
/// it is possible. Add any erased blocks to RemovedBlocks.
|
||||||
void convertIf(BlockSetVector &WorkList);
|
void convertIf(SmallVectorImpl<MachineBasicBlock*> &RemovedBlocks);
|
||||||
};
|
};
|
||||||
} // end anonymous namespace
|
} // end anonymous namespace
|
||||||
|
|
||||||
@ -425,18 +429,12 @@ bool SSAIfConv::canConvertIf(MachineBasicBlock *MBB) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void eraseBlock(BlockSetVector &WorkList, MachineBasicBlock *MBB) {
|
|
||||||
WorkList.remove(MBB);
|
|
||||||
MBB->eraseFromParent();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/// convertIf - Execute the if conversion after canConvertIf has determined the
|
/// convertIf - Execute the if conversion after canConvertIf has determined the
|
||||||
/// feasibility.
|
/// feasibility.
|
||||||
///
|
///
|
||||||
/// Any basic blocks erased will also be removed from WorkList.
|
/// Any basic blocks erased will be added to RemovedBlocks.
|
||||||
///
|
///
|
||||||
void SSAIfConv::convertIf(BlockSetVector &WorkList) {
|
void SSAIfConv::convertIf(SmallVectorImpl<MachineBasicBlock*> &RemovedBlocks) {
|
||||||
assert(Head && Tail && TBB && FBB && "Call canConvertIf first.");
|
assert(Head && Tail && TBB && FBB && "Call canConvertIf first.");
|
||||||
|
|
||||||
// Move all instructions into Head, except for the terminators.
|
// Move all instructions into Head, except for the terminators.
|
||||||
@ -475,10 +473,14 @@ void SSAIfConv::convertIf(BlockSetVector &WorkList) {
|
|||||||
|
|
||||||
// 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
|
||||||
// through to Tail, and we can join the two blocks.
|
// through to Tail, and we can join the two blocks.
|
||||||
if (TBB != Tail)
|
if (TBB != Tail) {
|
||||||
eraseBlock(WorkList, TBB);
|
RemovedBlocks.push_back(TBB);
|
||||||
if (FBB != Tail)
|
TBB->eraseFromParent();
|
||||||
eraseBlock(WorkList, FBB);
|
}
|
||||||
|
if (FBB != Tail) {
|
||||||
|
RemovedBlocks.push_back(FBB);
|
||||||
|
FBB->eraseFromParent();
|
||||||
|
}
|
||||||
|
|
||||||
assert(Head->succ_empty() && "Additional head successors?");
|
assert(Head->succ_empty() && "Additional head successors?");
|
||||||
if (Head->isLayoutSuccessor(Tail)) {
|
if (Head->isLayoutSuccessor(Tail)) {
|
||||||
@ -488,8 +490,8 @@ void SSAIfConv::convertIf(BlockSetVector &WorkList) {
|
|||||||
Head->splice(Head->end(), Tail,
|
Head->splice(Head->end(), Tail,
|
||||||
Tail->begin(), Tail->end());
|
Tail->begin(), Tail->end());
|
||||||
Head->transferSuccessorsAndUpdatePHIs(Tail);
|
Head->transferSuccessorsAndUpdatePHIs(Tail);
|
||||||
eraseBlock(WorkList, Tail);
|
RemovedBlocks.push_back(Tail);
|
||||||
|
Tail->eraseFromParent();
|
||||||
} else {
|
} else {
|
||||||
// We need a branch to Tail, let code placement work it out later.
|
// We need a branch to Tail, let code placement work it out later.
|
||||||
DEBUG(dbgs() << "Converting to unconditional branch.\n");
|
DEBUG(dbgs() << "Converting to unconditional branch.\n");
|
||||||
@ -510,11 +512,9 @@ class EarlyIfConverter : public MachineFunctionPass {
|
|||||||
const TargetInstrInfo *TII;
|
const TargetInstrInfo *TII;
|
||||||
const TargetRegisterInfo *TRI;
|
const TargetRegisterInfo *TRI;
|
||||||
MachineRegisterInfo *MRI;
|
MachineRegisterInfo *MRI;
|
||||||
|
MachineDominatorTree *DomTree;
|
||||||
SSAIfConv IfConv;
|
SSAIfConv IfConv;
|
||||||
|
|
||||||
// Worklist of head blocks to try for if-conversion.
|
|
||||||
BlockSetVector WorkList;
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
static char ID;
|
static char ID;
|
||||||
EarlyIfConverter() : MachineFunctionPass(ID) {}
|
EarlyIfConverter() : MachineFunctionPass(ID) {}
|
||||||
@ -523,6 +523,7 @@ public:
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
bool tryConvertIf(MachineBasicBlock*);
|
bool tryConvertIf(MachineBasicBlock*);
|
||||||
|
void updateDomTree(ArrayRef<MachineBasicBlock*> Removed);
|
||||||
};
|
};
|
||||||
} // end anonymous namespace
|
} // end anonymous namespace
|
||||||
|
|
||||||
@ -532,34 +533,47 @@ char &llvm::EarlyIfConverterID = EarlyIfConverter::ID;
|
|||||||
INITIALIZE_PASS_BEGIN(EarlyIfConverter,
|
INITIALIZE_PASS_BEGIN(EarlyIfConverter,
|
||||||
"early-ifcvt", "Early If Converter", false, false)
|
"early-ifcvt", "Early If Converter", false, false)
|
||||||
INITIALIZE_PASS_DEPENDENCY(MachineBranchProbabilityInfo)
|
INITIALIZE_PASS_DEPENDENCY(MachineBranchProbabilityInfo)
|
||||||
|
INITIALIZE_PASS_DEPENDENCY(MachineDominatorTree)
|
||||||
INITIALIZE_PASS_END(EarlyIfConverter,
|
INITIALIZE_PASS_END(EarlyIfConverter,
|
||||||
"early-ifcvt", "Early If Converter", false, false)
|
"early-ifcvt", "Early If Converter", false, false)
|
||||||
|
|
||||||
void EarlyIfConverter::getAnalysisUsage(AnalysisUsage &AU) const {
|
void EarlyIfConverter::getAnalysisUsage(AnalysisUsage &AU) const {
|
||||||
AU.addRequired<MachineBranchProbabilityInfo>();
|
AU.addRequired<MachineBranchProbabilityInfo>();
|
||||||
|
AU.addRequired<MachineDominatorTree>();
|
||||||
|
AU.addPreserved<MachineDominatorTree>();
|
||||||
MachineFunctionPass::getAnalysisUsage(AU);
|
MachineFunctionPass::getAnalysisUsage(AU);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Attempt repeated if-conversion on MBB, return true if successful.
|
/// Update the dominator tree after if-conversion erased some blocks.
|
||||||
/// Update WorkList with new opportunities.
|
void EarlyIfConverter::updateDomTree(ArrayRef<MachineBasicBlock*> Removed) {
|
||||||
///
|
// convertIf can remove TBB, FBB, and Tail can be merged into Head.
|
||||||
bool EarlyIfConverter::tryConvertIf(MachineBasicBlock *MBB) {
|
// TBB and FBB should not dominate any blocks.
|
||||||
if (!IfConv.canConvertIf(MBB))
|
// Tail children should be transferred to Head.
|
||||||
return false;
|
MachineDomTreeNode *HeadNode = DomTree->getNode(IfConv.Head);
|
||||||
|
for (unsigned i = 0, e = Removed.size(); i != e; ++i) {
|
||||||
// Repeatedly if-convert MBB, joining Head and Tail may expose more
|
MachineDomTreeNode *Node = DomTree->getNode(Removed[i]);
|
||||||
// opportunities.
|
assert(Node != HeadNode && "Cannot erase the head node");
|
||||||
do IfConv.convertIf(WorkList);
|
while (Node->getNumChildren()) {
|
||||||
while (IfConv.canConvertIf(MBB));
|
assert(Node->getBlock() == IfConv.Tail && "Unexpected children");
|
||||||
|
DomTree->changeImmediateDominator(Node->getChildren().back(), HeadNode);
|
||||||
// It is possible that MBB is now itself a conditional block that can be
|
}
|
||||||
// if-converted.
|
DomTree->eraseNode(Removed[i]);
|
||||||
if (MBB->pred_size() == 1 && MBB->succ_size() == 1)
|
}
|
||||||
WorkList.insert(MBB->pred_begin()[0]);
|
|
||||||
WorkList.remove(MBB);
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Attempt repeated if-conversion on MBB, return true if successful.
|
||||||
|
///
|
||||||
|
bool EarlyIfConverter::tryConvertIf(MachineBasicBlock *MBB) {
|
||||||
|
bool Changed = false;
|
||||||
|
while (IfConv.canConvertIf(MBB)) {
|
||||||
|
// If-convert MBB and update analyses.
|
||||||
|
SmallVector<MachineBasicBlock*, 4> RemovedBlocks;
|
||||||
|
IfConv.convertIf(RemovedBlocks);
|
||||||
|
Changed = true;
|
||||||
|
updateDomTree(RemovedBlocks);
|
||||||
|
}
|
||||||
|
return Changed;
|
||||||
|
}
|
||||||
|
|
||||||
bool EarlyIfConverter::runOnMachineFunction(MachineFunction &MF) {
|
bool EarlyIfConverter::runOnMachineFunction(MachineFunction &MF) {
|
||||||
DEBUG(dbgs() << "********** EARLY IF-CONVERSION **********\n"
|
DEBUG(dbgs() << "********** EARLY IF-CONVERSION **********\n"
|
||||||
@ -568,23 +582,20 @@ bool EarlyIfConverter::runOnMachineFunction(MachineFunction &MF) {
|
|||||||
TII = MF.getTarget().getInstrInfo();
|
TII = MF.getTarget().getInstrInfo();
|
||||||
TRI = MF.getTarget().getRegisterInfo();
|
TRI = MF.getTarget().getRegisterInfo();
|
||||||
MRI = &MF.getRegInfo();
|
MRI = &MF.getRegInfo();
|
||||||
|
DomTree = &getAnalysis<MachineDominatorTree>();
|
||||||
|
|
||||||
bool Changed = false;
|
bool Changed = false;
|
||||||
IfConv.runOnMachineFunction(MF);
|
IfConv.runOnMachineFunction(MF);
|
||||||
|
|
||||||
// Initially visit blocks in layout order. The tryConvertIf() function may
|
// Visit blocks in dominator tree post-order. The post-order enables nested
|
||||||
// erase blocks, but never the head block passed as MFI.
|
// if-conversion in a single pass. The tryConvertIf() function may erase
|
||||||
for (MachineFunction::iterator MFI = MF.begin(), MFE = MF.end(); MFI != MFE;
|
// blocks, but only blocks dominated by the head block. This makes it safe to
|
||||||
++MFI)
|
// update the dominator tree while the post-order iterator is still active.
|
||||||
if (tryConvertIf(MFI))
|
for (po_iterator<MachineDominatorTree*>
|
||||||
|
I = po_begin(DomTree), E = po_end(DomTree); I != E; ++I)
|
||||||
|
if (tryConvertIf(I->getBlock()))
|
||||||
Changed = true;
|
Changed = true;
|
||||||
|
|
||||||
// Revisit blocks identified by tryConvertIf() as candidates for nested
|
|
||||||
// if-conversion.
|
|
||||||
DEBUG(dbgs() << "Revisiting " << WorkList.size() << " blocks.\n");
|
|
||||||
while (!WorkList.empty())
|
|
||||||
tryConvertIf(WorkList.pop_back_val());
|
|
||||||
|
|
||||||
MF.verify(this, "After early if-conversion");
|
MF.verify(this, "After early if-conversion");
|
||||||
return Changed;
|
return Changed;
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user