mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2025-05-21 12:38:45 +00:00
Update LoopUnswitch pass to preserve DomiantorTree.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@37771 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
558f1b8439
commit
cce624a7a9
@ -35,6 +35,7 @@
|
|||||||
#include "llvm/Analysis/ConstantFolding.h"
|
#include "llvm/Analysis/ConstantFolding.h"
|
||||||
#include "llvm/Analysis/LoopInfo.h"
|
#include "llvm/Analysis/LoopInfo.h"
|
||||||
#include "llvm/Analysis/LoopPass.h"
|
#include "llvm/Analysis/LoopPass.h"
|
||||||
|
#include "llvm/Analysis/Dominators.h"
|
||||||
#include "llvm/Transforms/Utils/Cloning.h"
|
#include "llvm/Transforms/Utils/Cloning.h"
|
||||||
#include "llvm/Transforms/Utils/Local.h"
|
#include "llvm/Transforms/Utils/Local.h"
|
||||||
#include "llvm/Transforms/Utils/BasicBlockUtils.h"
|
#include "llvm/Transforms/Utils/BasicBlockUtils.h"
|
||||||
@ -82,6 +83,7 @@ namespace {
|
|||||||
virtual void getAnalysisUsage(AnalysisUsage &AU) const {
|
virtual void getAnalysisUsage(AnalysisUsage &AU) const {
|
||||||
AU.addRequiredID(LoopSimplifyID);
|
AU.addRequiredID(LoopSimplifyID);
|
||||||
AU.addPreservedID(LoopSimplifyID);
|
AU.addPreservedID(LoopSimplifyID);
|
||||||
|
AU.addPreserved<DominatorTree>();
|
||||||
AU.addRequired<LoopInfo>();
|
AU.addRequired<LoopInfo>();
|
||||||
AU.addPreserved<LoopInfo>();
|
AU.addPreserved<LoopInfo>();
|
||||||
AU.addRequiredID(LCSSAID);
|
AU.addRequiredID(LCSSAID);
|
||||||
@ -109,6 +111,11 @@ namespace {
|
|||||||
void RewriteLoopBodyWithConditionConstant(Loop *L, Value *LIC,
|
void RewriteLoopBodyWithConditionConstant(Loop *L, Value *LIC,
|
||||||
Constant *Val, bool isEqual);
|
Constant *Val, bool isEqual);
|
||||||
|
|
||||||
|
void EmitPreheaderBranchOnCondition(Value *LIC, Constant *Val,
|
||||||
|
BasicBlock *TrueDest,
|
||||||
|
BasicBlock *FalseDest,
|
||||||
|
Instruction *InsertPt);
|
||||||
|
|
||||||
void SimplifyCode(std::vector<Instruction*> &Worklist);
|
void SimplifyCode(std::vector<Instruction*> &Worklist);
|
||||||
void RemoveBlockIfDead(BasicBlock *BB,
|
void RemoveBlockIfDead(BasicBlock *BB,
|
||||||
std::vector<Instruction*> &Worklist);
|
std::vector<Instruction*> &Worklist);
|
||||||
@ -413,6 +420,9 @@ BasicBlock *LoopUnswitch::SplitBlock(BasicBlock *Old, Instruction *SplitPt) {
|
|||||||
if (Loop *L = LI->getLoopFor(Old))
|
if (Loop *L = LI->getLoopFor(Old))
|
||||||
L->addBasicBlockToLoop(New, *LI);
|
L->addBasicBlockToLoop(New, *LI);
|
||||||
|
|
||||||
|
if (DominatorTree *DT = getAnalysisToUpdate<DominatorTree>())
|
||||||
|
DT->addNewBlock(New, Old);
|
||||||
|
|
||||||
return New;
|
return New;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -429,30 +439,8 @@ BasicBlock *LoopUnswitch::SplitEdge(BasicBlock *BB, BasicBlock *Succ) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// If this is a critical edge, let SplitCriticalEdge do it.
|
// If this is a critical edge, let SplitCriticalEdge do it.
|
||||||
Loop *OrigDestBBL = LI->getLoopFor(BB->getTerminator()->getSuccessor(SuccNum));
|
if (SplitCriticalEdge(BB->getTerminator(), SuccNum, this))
|
||||||
if (SplitCriticalEdge(BB->getTerminator(), SuccNum)) {
|
return LatchTerm->getSuccessor(SuccNum);
|
||||||
BasicBlock *NewBB = LatchTerm->getSuccessor(SuccNum);
|
|
||||||
|
|
||||||
Loop *BBL = LI->getLoopFor(BB);
|
|
||||||
if (!BBL || !OrigDestBBL)
|
|
||||||
return NewBB;
|
|
||||||
|
|
||||||
// If edge is inside a loop then NewBB is part of same loop.
|
|
||||||
if (BBL == OrigDestBBL)
|
|
||||||
BBL->addBasicBlockToLoop(NewBB, *LI);
|
|
||||||
// If edge is entering loop then NewBB is part of outer loop.
|
|
||||||
else if (BBL->contains(OrigDestBBL->getHeader()))
|
|
||||||
BBL->addBasicBlockToLoop(NewBB, *LI);
|
|
||||||
// If edge is from an inner loop to outer loop then NewBB is part
|
|
||||||
// of outer loop.
|
|
||||||
else if (OrigDestBBL->contains(BBL->getHeader()))
|
|
||||||
OrigDestBBL->addBasicBlockToLoop(NewBB, *LI);
|
|
||||||
// Else edge is connecting two loops and NewBB is part of their parent loop
|
|
||||||
else if (Loop *PL = OrigDestBBL->getParentLoop())
|
|
||||||
PL->addBasicBlockToLoop(NewBB, *LI);
|
|
||||||
|
|
||||||
return NewBB;
|
|
||||||
}
|
|
||||||
|
|
||||||
// If the edge isn't critical, then BB has a single successor or Succ has a
|
// If the edge isn't critical, then BB has a single successor or Succ has a
|
||||||
// single pred. Split the block.
|
// single pred. Split the block.
|
||||||
@ -486,6 +474,26 @@ static inline void RemapInstruction(Instruction *I,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// CloneDomInfo - NewBB is cloned from Orig basic block. Now clone Dominator Info.
|
||||||
|
// If Orig is in Loop then find and use Orig dominator's cloned block as NewBB
|
||||||
|
// dominator.
|
||||||
|
void CloneDomInfo(BasicBlock *NewBB, BasicBlock *Orig, Loop *L,
|
||||||
|
DominatorTree *DT,
|
||||||
|
DenseMap<const Value*, Value*> &VM) {
|
||||||
|
|
||||||
|
DomTreeNode *OrigNode = DT->getNode(Orig);
|
||||||
|
if (!OrigNode)
|
||||||
|
return;
|
||||||
|
BasicBlock *OrigIDom = OrigNode->getBlock();
|
||||||
|
BasicBlock *NewIDom = OrigIDom;
|
||||||
|
if (L->contains(OrigIDom)) {
|
||||||
|
if (!DT->getNode(OrigIDom))
|
||||||
|
CloneDomInfo(NewIDom, OrigIDom, L, DT, VM);
|
||||||
|
NewIDom = cast<BasicBlock>(VM[OrigIDom]);
|
||||||
|
}
|
||||||
|
DT->addNewBlock(NewBB, OrigIDom);
|
||||||
|
}
|
||||||
|
|
||||||
/// CloneLoop - Recursively clone the specified loop and all of its children,
|
/// CloneLoop - Recursively clone the specified loop and all of its children,
|
||||||
/// mapping the blocks with the specified map.
|
/// mapping the blocks with the specified map.
|
||||||
static Loop *CloneLoop(Loop *L, Loop *PL, DenseMap<const Value*, Value*> &VM,
|
static Loop *CloneLoop(Loop *L, Loop *PL, DenseMap<const Value*, Value*> &VM,
|
||||||
@ -510,10 +518,10 @@ static Loop *CloneLoop(Loop *L, Loop *PL, DenseMap<const Value*, Value*> &VM,
|
|||||||
/// EmitPreheaderBranchOnCondition - Emit a conditional branch on two values
|
/// EmitPreheaderBranchOnCondition - Emit a conditional branch on two values
|
||||||
/// if LIC == Val, branch to TrueDst, otherwise branch to FalseDest. Insert the
|
/// if LIC == Val, branch to TrueDst, otherwise branch to FalseDest. Insert the
|
||||||
/// code immediately before InsertPt.
|
/// code immediately before InsertPt.
|
||||||
static void EmitPreheaderBranchOnCondition(Value *LIC, Constant *Val,
|
void LoopUnswitch::EmitPreheaderBranchOnCondition(Value *LIC, Constant *Val,
|
||||||
BasicBlock *TrueDest,
|
BasicBlock *TrueDest,
|
||||||
BasicBlock *FalseDest,
|
BasicBlock *FalseDest,
|
||||||
Instruction *InsertPt) {
|
Instruction *InsertPt) {
|
||||||
// Insert a conditional branch on LIC to the two preheaders. The original
|
// Insert a conditional branch on LIC to the two preheaders. The original
|
||||||
// code is the true version and the new code is the false version.
|
// code is the true version and the new code is the false version.
|
||||||
Value *BranchVal = LIC;
|
Value *BranchVal = LIC;
|
||||||
@ -524,7 +532,15 @@ static void EmitPreheaderBranchOnCondition(Value *LIC, Constant *Val,
|
|||||||
std::swap(TrueDest, FalseDest);
|
std::swap(TrueDest, FalseDest);
|
||||||
|
|
||||||
// Insert the new branch.
|
// Insert the new branch.
|
||||||
new BranchInst(TrueDest, FalseDest, BranchVal, InsertPt);
|
BranchInst *BRI = new BranchInst(TrueDest, FalseDest, BranchVal, InsertPt);
|
||||||
|
|
||||||
|
// Update dominator info.
|
||||||
|
if (DominatorTree *DT = getAnalysisToUpdate<DominatorTree>()) {
|
||||||
|
// BranchVal is a new preheader so it dominates true and false destination
|
||||||
|
// loop headers.
|
||||||
|
DT->changeImmediateDominator(TrueDest, BRI->getParent());
|
||||||
|
DT->changeImmediateDominator(FalseDest, BRI->getParent());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -574,7 +590,6 @@ void LoopUnswitch::UnswitchTrivialCondition(Loop *L, Value *Cond,
|
|||||||
++NumTrivial;
|
++NumTrivial;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/// VersionLoop - We determined that the loop is profitable to unswitch when LIC
|
/// VersionLoop - We determined that the loop is profitable to unswitch when LIC
|
||||||
/// equal Val. Split it into loop versions and test the condition outside of
|
/// equal Val. Split it into loop versions and test the condition outside of
|
||||||
/// either loop. Return the loops created as Out1/Out2.
|
/// either loop. Return the loops created as Out1/Out2.
|
||||||
@ -666,6 +681,14 @@ void LoopUnswitch::UnswitchNontrivialCondition(Value *LIC, Constant *Val,
|
|||||||
ValueMap[LoopBlocks[i]] = New; // Keep the BB mapping.
|
ValueMap[LoopBlocks[i]] = New; // Keep the BB mapping.
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Update dominator info
|
||||||
|
if (DominatorTree *DT = getAnalysisToUpdate<DominatorTree>())
|
||||||
|
for (unsigned i = 0, e = LoopBlocks.size(); i != e; ++i) {
|
||||||
|
BasicBlock *LBB = LoopBlocks[i];
|
||||||
|
BasicBlock *NBB = NewBlocks[i];
|
||||||
|
CloneDomInfo(NBB, LBB, L, DT, ValueMap);
|
||||||
|
}
|
||||||
|
|
||||||
// Splice the newly inserted blocks into the function right before the
|
// Splice the newly inserted blocks into the function right before the
|
||||||
// original preheader.
|
// original preheader.
|
||||||
F->getBasicBlockList().splice(LoopBlocks[0], F->getBasicBlockList(),
|
F->getBasicBlockList().splice(LoopBlocks[0], F->getBasicBlockList(),
|
||||||
|
Loading…
x
Reference in New Issue
Block a user