mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2025-06-23 17:24:48 +00:00
Three major changes:
1. Rip out LoopRotate's domfrontier updating code. It isn't needed now that LICM doesn't use DF and it is super complex and gross. 2. Make DomTree updating code a lot simpler and faster. The old loop over all the blocks was just to find a block?? 3. Change the code that inserts the new preheader to just use SplitCriticalEdge instead of doing an overcomplex reimplementation of it. No behavior change, except for the name of the inserted preheader. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@123072 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
@ -15,7 +15,6 @@
|
|||||||
#include "llvm/Transforms/Scalar.h"
|
#include "llvm/Transforms/Scalar.h"
|
||||||
#include "llvm/Function.h"
|
#include "llvm/Function.h"
|
||||||
#include "llvm/Analysis/CodeMetrics.h"
|
#include "llvm/Analysis/CodeMetrics.h"
|
||||||
#include "llvm/Analysis/DominanceFrontier.h"
|
|
||||||
#include "llvm/Analysis/LoopPass.h"
|
#include "llvm/Analysis/LoopPass.h"
|
||||||
#include "llvm/Analysis/InstructionSimplify.h"
|
#include "llvm/Analysis/InstructionSimplify.h"
|
||||||
#include "llvm/Analysis/ScalarEvolution.h"
|
#include "llvm/Analysis/ScalarEvolution.h"
|
||||||
@ -46,7 +45,6 @@ namespace {
|
|||||||
// LCSSA form makes instruction renaming easier.
|
// LCSSA form makes instruction renaming easier.
|
||||||
virtual void getAnalysisUsage(AnalysisUsage &AU) const {
|
virtual void getAnalysisUsage(AnalysisUsage &AU) const {
|
||||||
AU.addPreserved<DominatorTree>();
|
AU.addPreserved<DominatorTree>();
|
||||||
AU.addPreserved<DominanceFrontier>();
|
|
||||||
AU.addRequired<LoopInfo>();
|
AU.addRequired<LoopInfo>();
|
||||||
AU.addPreserved<LoopInfo>();
|
AU.addPreserved<LoopInfo>();
|
||||||
AU.addRequiredID(LoopSimplifyID);
|
AU.addRequiredID(LoopSimplifyID);
|
||||||
@ -296,7 +294,7 @@ bool LoopRotate::rotateLoop(Loop *L) {
|
|||||||
// Also, since this original header only has one predecessor, zap its
|
// Also, since this original header only has one predecessor, zap its
|
||||||
// PHI nodes, which are now trivial.
|
// PHI nodes, which are now trivial.
|
||||||
FoldSingleEntryPHINodes(OrigHeader);
|
FoldSingleEntryPHINodes(OrigHeader);
|
||||||
|
|
||||||
// TODO: We could just go ahead and merge OrigHeader into its predecessor
|
// TODO: We could just go ahead and merge OrigHeader into its predecessor
|
||||||
// at this point, if we don't mind updating dominator info.
|
// at this point, if we don't mind updating dominator info.
|
||||||
|
|
||||||
@ -309,130 +307,37 @@ bool LoopRotate::rotateLoop(Loop *L) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/// After loop rotation, loop pre-header has multiple sucessors.
|
/// Update LoopInfo, DominatorTree, and DomFrontiers to reflect the CFG change
|
||||||
/// Insert one forwarding basic block to ensure that loop pre-header
|
/// we just made. Then split edges as necessary to preserve LoopSimplify form.
|
||||||
/// has only one successor.
|
|
||||||
void LoopRotate::preserveCanonicalLoopForm(Loop *L, BasicBlock *OrigHeader,
|
void LoopRotate::preserveCanonicalLoopForm(Loop *L, BasicBlock *OrigHeader,
|
||||||
BasicBlock *OrigPreHeader,
|
BasicBlock *OrigPreHeader,
|
||||||
BasicBlock *OrigLatch,
|
BasicBlock *OrigLatch,
|
||||||
BasicBlock *NewHeader,
|
BasicBlock *NewHeader,
|
||||||
BasicBlock *Exit) {
|
BasicBlock *Exit) {
|
||||||
|
assert(L->getHeader() == NewHeader && "Latch block is our new header");
|
||||||
// Right now original pre-header has two successors, new header and
|
|
||||||
// exit block. Insert new block between original pre-header and
|
|
||||||
// new header such that loop's new pre-header has only one successor.
|
|
||||||
BasicBlock *NewPreHeader =
|
|
||||||
BasicBlock::Create(OrigHeader->getContext(), "bb.nph",
|
|
||||||
OrigHeader->getParent(), NewHeader);
|
|
||||||
if (Loop *PL = LI->getLoopFor(OrigPreHeader))
|
|
||||||
PL->addBasicBlockToLoop(NewPreHeader, LI->getBase());
|
|
||||||
BranchInst::Create(NewHeader, NewPreHeader);
|
|
||||||
|
|
||||||
BranchInst *OrigPH_BI = cast<BranchInst>(OrigPreHeader->getTerminator());
|
|
||||||
if (OrigPH_BI->getSuccessor(0) == NewHeader)
|
|
||||||
OrigPH_BI->setSuccessor(0, NewPreHeader);
|
|
||||||
else {
|
|
||||||
assert(OrigPH_BI->getSuccessor(1) == NewHeader &&
|
|
||||||
"Unexpected original pre-header terminator");
|
|
||||||
OrigPH_BI->setSuccessor(1, NewPreHeader);
|
|
||||||
}
|
|
||||||
|
|
||||||
PHINode *PN;
|
|
||||||
for (BasicBlock::iterator I = NewHeader->begin();
|
|
||||||
(PN = dyn_cast<PHINode>(I)); ++I) {
|
|
||||||
int index = PN->getBasicBlockIndex(OrigPreHeader);
|
|
||||||
assert(index != -1 && "Expected incoming value from Original PreHeader");
|
|
||||||
PN->setIncomingBlock(index, NewPreHeader);
|
|
||||||
assert(PN->getBasicBlockIndex(OrigPreHeader) == -1 &&
|
|
||||||
"Expected only one incoming value from Original PreHeader");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (DominatorTree *DT = getAnalysisIfAvailable<DominatorTree>()) {
|
if (DominatorTree *DT = getAnalysisIfAvailable<DominatorTree>()) {
|
||||||
DT->addNewBlock(NewPreHeader, OrigPreHeader);
|
// Since OrigPreheader now has the conditional branch to Exit block, it is
|
||||||
DT->changeImmediateDominator(L->getHeader(), NewPreHeader);
|
// the dominator of Exit.
|
||||||
DT->changeImmediateDominator(Exit, OrigPreHeader);
|
DT->changeImmediateDominator(Exit, OrigPreHeader);
|
||||||
for (Loop::block_iterator BI = L->block_begin(), BE = L->block_end();
|
DT->changeImmediateDominator(NewHeader, OrigPreHeader);
|
||||||
BI != BE; ++BI) {
|
|
||||||
BasicBlock *B = *BI;
|
// Update OrigHeader to be dominated by the new header block.
|
||||||
if (L->getHeader() != B) {
|
|
||||||
DomTreeNode *Node = DT->getNode(B);
|
|
||||||
if (Node && Node->getBlock() == OrigHeader)
|
|
||||||
DT->changeImmediateDominator(*BI, L->getHeader());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
DT->changeImmediateDominator(OrigHeader, OrigLatch);
|
DT->changeImmediateDominator(OrigHeader, OrigLatch);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (DominanceFrontier *DF = getAnalysisIfAvailable<DominanceFrontier>()) {
|
// Right now OrigPreHeader has two successors, NewHeader and ExitBlock, and
|
||||||
// New Preheader's dominance frontier is Exit block.
|
// thus is not a preheader anymore. Split the edge to form a real preheader.
|
||||||
DominanceFrontier::DomSetType NewPHSet;
|
BasicBlock *NewPH = SplitCriticalEdge(OrigPreHeader, NewHeader, this);
|
||||||
NewPHSet.insert(Exit);
|
NewPH->setName(NewHeader->getName() + ".lr.ph");
|
||||||
DF->addBasicBlock(NewPreHeader, NewPHSet);
|
|
||||||
|
// Preserve canonical loop form, which means Exit block should have only one
|
||||||
// New Header's dominance frontier now includes itself and Exit block
|
// predecessor.
|
||||||
DominanceFrontier::iterator HeadI = DF->find(L->getHeader());
|
SplitCriticalEdge(L->getLoopLatch(), Exit, this);
|
||||||
if (HeadI != DF->end()) {
|
|
||||||
DominanceFrontier::DomSetType & HeaderSet = HeadI->second;
|
|
||||||
HeaderSet.clear();
|
|
||||||
HeaderSet.insert(L->getHeader());
|
|
||||||
HeaderSet.insert(Exit);
|
|
||||||
} else {
|
|
||||||
DominanceFrontier::DomSetType HeaderSet;
|
|
||||||
HeaderSet.insert(L->getHeader());
|
|
||||||
HeaderSet.insert(Exit);
|
|
||||||
DF->addBasicBlock(L->getHeader(), HeaderSet);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Original header (new Loop Latch)'s dominance frontier is Exit.
|
|
||||||
DominanceFrontier::iterator LatchI = DF->find(L->getLoopLatch());
|
|
||||||
if (LatchI != DF->end()) {
|
|
||||||
DominanceFrontier::DomSetType &LatchSet = LatchI->second;
|
|
||||||
LatchSet = LatchI->second;
|
|
||||||
LatchSet.clear();
|
|
||||||
LatchSet.insert(Exit);
|
|
||||||
} else {
|
|
||||||
DominanceFrontier::DomSetType LatchSet;
|
|
||||||
LatchSet.insert(Exit);
|
|
||||||
DF->addBasicBlock(L->getHeader(), LatchSet);
|
|
||||||
}
|
|
||||||
|
|
||||||
// If a loop block dominates new loop latch then add to its frontiers
|
|
||||||
// new header and Exit and remove new latch (which is equal to original
|
|
||||||
// header).
|
|
||||||
BasicBlock *NewLatch = L->getLoopLatch();
|
|
||||||
|
|
||||||
assert(NewLatch == OrigHeader && "NewLatch is inequal to OrigHeader");
|
|
||||||
|
|
||||||
if (DominatorTree *DT = getAnalysisIfAvailable<DominatorTree>()) {
|
|
||||||
for (Loop::block_iterator BI = L->block_begin(), BE = L->block_end();
|
|
||||||
BI != BE; ++BI) {
|
|
||||||
BasicBlock *B = *BI;
|
|
||||||
if (!DT->dominates(B, NewLatch)) continue;
|
|
||||||
|
|
||||||
DominanceFrontier::iterator BDFI = DF->find(B);
|
|
||||||
if (BDFI != DF->end()) {
|
|
||||||
DominanceFrontier::DomSetType &BSet = BDFI->second;
|
|
||||||
BSet.erase(NewLatch);
|
|
||||||
BSet.insert(L->getHeader());
|
|
||||||
BSet.insert(Exit);
|
|
||||||
} else {
|
|
||||||
DominanceFrontier::DomSetType BSet;
|
|
||||||
BSet.insert(L->getHeader());
|
|
||||||
BSet.insert(Exit);
|
|
||||||
DF->addBasicBlock(B, BSet);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Preserve canonical loop form, which means Exit block should
|
|
||||||
// have only one predecessor.
|
|
||||||
SplitEdge(L->getLoopLatch(), Exit, this);
|
|
||||||
|
|
||||||
assert(NewHeader && L->getHeader() == NewHeader &&
|
assert(NewHeader && L->getHeader() == NewHeader &&
|
||||||
"Invalid loop header after loop rotation");
|
"Invalid loop header after loop rotation");
|
||||||
assert(NewPreHeader && L->getLoopPreheader() == NewPreHeader &&
|
assert(L->getLoopPreheader() == NewPH &&
|
||||||
"Invalid loop preheader after loop rotation");
|
"Invalid loop preheader after loop rotation");
|
||||||
assert(L->getLoopLatch() &&
|
assert(L->getLoopLatch() && "Invalid loop latch after loop rotation");
|
||||||
"Invalid loop latch after loop rotation");
|
|
||||||
}
|
}
|
||||||
|
@ -34,9 +34,9 @@ for.end: ; preds = %for.cond
|
|||||||
|
|
||||||
; CHECK: define void @test
|
; CHECK: define void @test
|
||||||
; CHECK-NEXT: entry:
|
; CHECK-NEXT: entry:
|
||||||
; CHECK-NEXT: br i1 true, label %bb.nph, label %for.end
|
; CHECK-NEXT: br i1 true, label %for.body.lr.ph, label %for.end
|
||||||
; CHECK-NOT: :
|
; CHECK-NOT: :
|
||||||
; CHECK: bb.nph:
|
; CHECK: for.body.lr.ph:
|
||||||
; CHECK-NEXT: br label %for.body
|
; CHECK-NEXT: br label %for.body
|
||||||
; CHECK-NOT: :
|
; CHECK-NOT: :
|
||||||
; CHECK: for.body:
|
; CHECK: for.body:
|
||||||
|
Reference in New Issue
Block a user