[Mesa-dev] [PATCH 04/12] R600/structurizer: improve loop handling
Christian König
deathsimple at vodafone.de
Thu Feb 14 02:43:02 PST 2013
From: Christian König <christian.koenig at amd.com>
Generate more than one loop if it seems to make sense.
Signed-off-by: Christian König <christian.koenig at amd.com>
---
lib/Target/R600/AMDGPUStructurizeCFG.cpp | 344 +++++++++++++-----------------
1 file changed, 148 insertions(+), 196 deletions(-)
diff --git a/lib/Target/R600/AMDGPUStructurizeCFG.cpp b/lib/Target/R600/AMDGPUStructurizeCFG.cpp
index e97e049..c2b084a 100644
--- a/lib/Target/R600/AMDGPUStructurizeCFG.cpp
+++ b/lib/Target/R600/AMDGPUStructurizeCFG.cpp
@@ -43,6 +43,7 @@ typedef DenseMap<DomTreeNode *, unsigned> DTN2UnsignedMap;
typedef DenseMap<BasicBlock *, PhiMap> BBPhiMap;
typedef DenseMap<BasicBlock *, Value *> BBPredicates;
typedef DenseMap<BasicBlock *, BBPredicates> PredMap;
+typedef DenseMap<BasicBlock *, BasicBlock*> BB2BBMap;
typedef DenseMap<BasicBlock *, BBVector> BB2BBVecMap;
// The name for newly created blocks.
@@ -175,29 +176,30 @@ class AMDGPUStructurizeCFG : public RegionPass {
RNVector Order;
BBSet Visited;
- PredMap Predicates;
+
BBPhiMap DeletedPhis;
BB2BBVecMap AddedPhis;
+
+ PredMap Predicates;
BranchVector Conditions;
- BasicBlock *LoopStart;
- BasicBlock *LoopEnd;
- BBSet LoopTargets;
- BBPredicates LoopPred;
+ BB2BBMap Loops;
+ PredMap LoopPreds;
+ BranchVector LoopConds;
- void orderNodes();
+ RegionNode *PrevNode;
- Value *buildCondition(BranchInst *Term, unsigned Idx, bool Invert);
+ void orderNodes();
- bool analyzeLoopStart(BasicBlock *From, BasicBlock *To, Value *Condition);
+ void analyzeLoops(RegionNode *N);
- void analyzeNode(RegionNode *N);
+ Value *buildCondition(BranchInst *Term, unsigned Idx, bool Invert);
- void analyzeLoopEnd(RegionNode *N);
+ void gatherPredicates(RegionNode *N);
void collectInfos();
- void insertConditions();
+ void insertConditions(bool Loops);
void delPhiValues(BasicBlock *From, BasicBlock *To);
@@ -212,17 +214,19 @@ class AMDGPUStructurizeCFG : public RegionPass {
BasicBlock *getNextFlow(BasicBlock *Dominator);
- BasicBlock *needPrefix(RegionNode *&Prev, RegionNode *Node);
+ BasicBlock *needPrefix(bool NeedEmpty);
BasicBlock *needPostfix(BasicBlock *Flow, bool ExitUseAllowed);
- RegionNode *getNextPrev(BasicBlock *Next);
+ void setPrevNode(BasicBlock *BB);
bool dominatesPredicates(BasicBlock *BB, RegionNode *Node);
- bool isPredictableTrue(RegionNode *Who, RegionNode *Where);
+ bool isPredictableTrue(RegionNode *Node);
+
+ void wireFlow(bool ExitUseAllowed, BasicBlock *LoopEnd);
- RegionNode *wireFlow(RegionNode *&Prev, bool ExitUseAllowed);
+ void handleLoops(bool ExitUseAllowed, BasicBlock *LoopEnd);
void createFlow();
@@ -278,6 +282,29 @@ void AMDGPUStructurizeCFG::orderNodes() {
}
}
+/// \brief Determine the end of the loops
+void AMDGPUStructurizeCFG::analyzeLoops(RegionNode *N) {
+
+ if (N->isSubRegion()) {
+ // Test for exit as back edge
+ BasicBlock *Exit = N->getNodeAs<Region>()->getExit();
+ if (Visited.count(Exit))
+ Loops[Exit] = N->getEntry();
+
+ } else {
+ // Test for sucessors as back edge
+ BasicBlock *BB = N->getNodeAs<BasicBlock>();
+ BranchInst *Term = cast<BranchInst>(BB->getTerminator());
+
+ for (unsigned i = 0, e = Term->getNumSuccessors(); i != e; ++i) {
+ BasicBlock *Succ = Term->getSuccessor(i);
+
+ if (Visited.count(Succ))
+ Loops[Succ] = BB;
+ }
+ }
+}
+
/// \brief Build the condition for one edge
Value *AMDGPUStructurizeCFG::buildCondition(BranchInst *Term, unsigned Idx,
bool Invert) {
@@ -291,54 +318,20 @@ Value *AMDGPUStructurizeCFG::buildCondition(BranchInst *Term, unsigned Idx,
return Cond;
}
-/// \brief Analyze the start of a loop and insert predicates as necessary
-bool AMDGPUStructurizeCFG::analyzeLoopStart(BasicBlock *From, BasicBlock *To,
- Value *Condition) {
- LoopPred[From] = Condition;
- LoopTargets.insert(To);
- if (!LoopStart) {
- LoopStart = To;
- return true;
-
- } else if (LoopStart == To)
- return true;
-
- // We need to handle the case of intersecting loops, e. g.
- //
- // /----<-----
- // | |
- // -> A -> B -> C -> D
- // | |
- // -----<----/
-
- RNVector::reverse_iterator OI = Order.rbegin(), OE = Order.rend();
-
- for (;OI != OE; ++OI)
- if ((*OI)->getEntry() == LoopStart)
- break;
-
- for (;OI != OE && (*OI)->getEntry() != To; ++OI) {
- BBPredicates &Pred = Predicates[(*OI)->getEntry()];
- if (!Pred.count(From))
- Pred[From] = Condition;
- }
- return false;
-}
-
/// \brief Analyze the predecessors of each block and build up predicates
-void AMDGPUStructurizeCFG::analyzeNode(RegionNode *N) {
+void AMDGPUStructurizeCFG::gatherPredicates(RegionNode *N) {
+
RegionInfo *RI = ParentRegion->getRegionInfo();
BasicBlock *BB = N->getEntry();
BBPredicates &Pred = Predicates[BB];
+ BBPredicates &LPred = LoopPreds[BB];
for (pred_iterator PI = pred_begin(BB), PE = pred_end(BB);
PI != PE; ++PI) {
- if (!ParentRegion->contains(*PI)) {
- // It's a branch from outside into our region entry
- Pred[*PI] = BoolTrue;
+ // Ignore it if it's a branch from outside into our region entry
+ if (!ParentRegion->contains(*PI))
continue;
- }
Region *R = RI->getRegionFor(*PI);
if (R == ParentRegion) {
@@ -355,7 +348,7 @@ void AMDGPUStructurizeCFG::analyzeNode(RegionNode *N) {
if (Term->isConditional()) {
// Try to treat it like an ELSE block
BasicBlock *Other = Term->getSuccessor(!i);
- if (Visited.count(Other) && !LoopTargets.count(Other) &&
+ if (Visited.count(Other) && !Loops.count(Other) &&
!Pred.count(Other) && !Pred.count(*PI)) {
Pred[Other] = BoolFalse;
@@ -363,13 +356,12 @@ void AMDGPUStructurizeCFG::analyzeNode(RegionNode *N) {
continue;
}
}
-
+ Pred[*PI] = buildCondition(Term, i, false);
+
} else {
// Back edge
- if (analyzeLoopStart(*PI, BB, buildCondition(Term, i, true)))
- continue;
+ LPred[*PI] = buildCondition(Term, i, true);
}
- Pred[*PI] = buildCondition(Term, i, false);
}
} else {
@@ -383,34 +375,10 @@ void AMDGPUStructurizeCFG::analyzeNode(RegionNode *N) {
continue;
BasicBlock *Entry = R->getEntry();
- if (!Visited.count(Entry))
- if (analyzeLoopStart(Entry, BB, BoolFalse))
- continue;
-
- Pred[Entry] = BoolTrue;
- }
- }
-}
-
-/// \brief Determine the end of the loop
-void AMDGPUStructurizeCFG::analyzeLoopEnd(RegionNode *N) {
-
- if (N->isSubRegion()) {
- // Test for exit as back edge
- BasicBlock *Exit = N->getNodeAs<Region>()->getExit();
- if (Visited.count(Exit))
- LoopEnd = N->getEntry();
-
- } else {
- // Test for sucessors as back edge
- BasicBlock *BB = N->getNodeAs<BasicBlock>();
- BranchInst *Term = cast<BranchInst>(BB->getTerminator());
-
- for (unsigned i = 0, e = Term->getNumSuccessors(); i != e; ++i) {
- BasicBlock *Succ = Term->getSuccessor(i);
-
- if (Visited.count(Succ))
- LoopEnd = BB;
+ if (Visited.count(Entry))
+ Pred[Entry] = BoolTrue;
+ else
+ LPred[Entry] = BoolFalse;
}
}
}
@@ -422,9 +390,8 @@ void AMDGPUStructurizeCFG::collectInfos() {
Predicates.clear();
// and loop infos
- LoopStart = LoopEnd = 0;
- LoopTargets.clear();
- LoopPred.clear();
+ Loops.clear();
+ LoopPreds.clear();
// Reset the visited nodes
Visited.clear();
@@ -433,42 +400,37 @@ void AMDGPUStructurizeCFG::collectInfos() {
OI != OE; ++OI) {
// Analyze all the conditions leading to a node
- analyzeNode(*OI);
+ gatherPredicates(*OI);
// Remember that we've seen this node
Visited.insert((*OI)->getEntry());
- // Find the last back edge
- analyzeLoopEnd(*OI);
+ // Find the last back edges
+ analyzeLoops(*OI);
}
-
- // Both or neither must be set
- assert(!LoopStart == !LoopEnd);
}
/// \brief Insert the missing branch conditions
-void AMDGPUStructurizeCFG::insertConditions() {
+void AMDGPUStructurizeCFG::insertConditions(bool Loops) {
+ BranchVector &Conds = Loops ? LoopConds : Conditions;
+ Value *Default = Loops ? BoolTrue : BoolFalse;
SSAUpdater PhiInserter;
- for (BranchVector::iterator I = Conditions.begin(),
- E = Conditions.end(); I != E; ++I) {
+ for (BranchVector::iterator I = Conds.begin(),
+ E = Conds.end(); I != E; ++I) {
BranchInst *Term = *I;
- BasicBlock *Parent = Term->getParent();
-
assert(Term->isConditional());
- Value *Default = (Parent == LoopEnd) ? BoolTrue : BoolFalse;
+ BasicBlock *Parent = Term->getParent();
+ BasicBlock *SuccTrue = Term->getSuccessor(0);
+ BasicBlock *SuccFalse = Term->getSuccessor(1);
PhiInserter.Initialize(Boolean, "");
PhiInserter.AddAvailableValue(&Func->getEntryBlock(), Default);
- if (Parent == LoopEnd)
- PhiInserter.AddAvailableValue(LoopStart, BoolTrue);
- else
- PhiInserter.AddAvailableValue(Parent, BoolFalse);
+ PhiInserter.AddAvailableValue(Loops ? SuccFalse : Parent, Default);
- BasicBlock *Succ = Term->getSuccessor(0);
- BBPredicates &Preds = (Parent == LoopEnd) ? LoopPred : Predicates[Succ];
+ BBPredicates &Preds = Loops ? LoopPreds[SuccFalse] : Predicates[SuccTrue];
NearestCommonDominator Dominator(DT);
Dominator.addBlock(Parent, false);
@@ -648,54 +610,24 @@ BasicBlock *AMDGPUStructurizeCFG::getNextFlow(BasicBlock *Dominator) {
}
/// \brief Create a new or reuse the previous node as flow node
-BasicBlock *AMDGPUStructurizeCFG::needPrefix(RegionNode *&Prev,
- RegionNode *Node) {
-
- if (!Prev || Prev->isSubRegion() ||
- (Node && Node->getEntry() == LoopStart)) {
-
- // We need to insert a flow node, first figure out the dominator
- DomTreeNode *Dominator = Prev ? DT->getNode(Prev->getEntry()) : 0;
- if (!Dominator)
- Dominator = DT->getNode(Node->getEntry())->getIDom();
- assert(Dominator && "Illegal loop to function entry");
-
- // then create the flow node
- BasicBlock *Flow = getNextFlow(Dominator->getBlock());
-
- // wire up the new flow
- if (Prev) {
- changeExit(Prev, Flow, true);
- } else {
- // Parent regions entry needs predicates, create a new region entry
- BasicBlock *Entry = Node->getEntry();
- for (pred_iterator I = pred_begin(Entry), E = pred_end(Entry);
- I != E;) {
-
- BasicBlock *BB = *(I++);
- if (ParentRegion->contains(BB))
- continue;
+BasicBlock *AMDGPUStructurizeCFG::needPrefix(bool NeedEmpty) {
- // Remove PHY values from outside to our entry node
- delPhiValues(BB, Entry);
+ BasicBlock *Entry = PrevNode->getEntry();
- // Update the branch instructions
- BB->getTerminator()->replaceUsesOfWith(Entry, Flow);
- }
+ if (!PrevNode->isSubRegion()) {
+ killTerminator(Entry);
+ if (!NeedEmpty || Entry->getFirstInsertionPt() == Entry->end())
+ return Entry;
- // Populate the region tree with the new entry
- for (Region *R = ParentRegion; R && R->getEntry() == Entry;
- R = R->getParent()) {
- R->replaceEntry(Flow);
- }
- }
- Prev = ParentRegion->getBBNode(Flow);
+ }
- } else {
- killTerminator(Prev->getEntry());
- }
+ // create a new flow node
+ BasicBlock *Flow = getNextFlow(Entry);
- return Prev->getEntry();
+ // and wire it up
+ changeExit(PrevNode, Flow, true);
+ PrevNode = ParentRegion->getBBNode(Flow);
+ return Flow;
}
/// \brief Returns the region exit if possible, otherwise just a new flow node
@@ -711,9 +643,9 @@ BasicBlock *AMDGPUStructurizeCFG::needPostfix(BasicBlock *Flow,
return getNextFlow(Flow);
}
-/// \brief Returns the region node for Netx, or null if Next is the exit
-RegionNode *AMDGPUStructurizeCFG::getNextPrev(BasicBlock *Next) {
- return ParentRegion->contains(Next) ? ParentRegion->getBBNode(Next) : 0;
+/// \brief Set the previous node
+void AMDGPUStructurizeCFG::setPrevNode(BasicBlock *BB) {
+ PrevNode = ParentRegion->contains(BB) ? ParentRegion->getBBNode(BB) : 0;
}
/// \brief Does BB dominate all the predicates of Node ?
@@ -729,11 +661,14 @@ bool AMDGPUStructurizeCFG::dominatesPredicates(BasicBlock *BB, RegionNode *Node)
}
/// \brief Can we predict that this node will always be called?
-bool AMDGPUStructurizeCFG::isPredictableTrue(RegionNode *Who,
- RegionNode *Where) {
+bool AMDGPUStructurizeCFG::isPredictableTrue(RegionNode *Node) {
- BBPredicates &Preds = Predicates[Who->getEntry()];
- bool Dominated = Where == 0;
+ BBPredicates &Preds = Predicates[Node->getEntry()];
+ bool Dominated = false;
+
+ // Regionentry is always true
+ if (PrevNode == 0)
+ return true;
for (BBPredicates::iterator I = Preds.begin(), E = Preds.end();
I != E; ++I) {
@@ -741,7 +676,7 @@ bool AMDGPUStructurizeCFG::isPredictableTrue(RegionNode *Who,
if (I->second != BoolTrue)
return false;
- if (!Dominated && DT->dominates(I->first, Where->getEntry()))
+ if (!Dominated && DT->dominates(I->first, PrevNode->getEntry()))
Dominated = true;
}
@@ -750,45 +685,69 @@ bool AMDGPUStructurizeCFG::isPredictableTrue(RegionNode *Who,
}
/// Take one node from the order vector and wire it up
-RegionNode *AMDGPUStructurizeCFG::wireFlow(RegionNode *&Prev,
- bool ExitUseAllowed) {
+void AMDGPUStructurizeCFG::wireFlow(bool ExitUseAllowed,
+ BasicBlock *LoopEnd) {
RegionNode *Node = Order.pop_back_val();
+ Visited.insert(Node->getEntry());
- if (isPredictableTrue(Node, Prev)) {
+ if (isPredictableTrue(Node)) {
// Just a linear flow
- if (Prev) {
- changeExit(Prev, Node->getEntry(), true);
+ if (PrevNode) {
+ changeExit(PrevNode, Node->getEntry(), true);
}
- Prev = Node;
+ PrevNode = Node;
} else {
// Insert extra prefix node (or reuse last one)
- BasicBlock *Flow = needPrefix(Prev, Node);
- if (Node->getEntry() == LoopStart)
- LoopStart = Flow;
+ BasicBlock *Flow = needPrefix(false);
// Insert extra postfix node (or use exit instead)
BasicBlock *Entry = Node->getEntry();
- BasicBlock *Next = needPostfix(Flow, ExitUseAllowed && Entry != LoopEnd);
+ BasicBlock *Next = needPostfix(Flow, ExitUseAllowed);
// let it point to entry and next block
Conditions.push_back(BranchInst::Create(Entry, Next, BoolUndef, Flow));
addPhiValues(Flow, Entry);
DT->changeImmediateDominator(Entry, Flow);
- Prev = Node;
- while (!Order.empty() && Node->getEntry() != LoopEnd &&
- !LoopTargets.count(Order.back()->getEntry()) &&
+ PrevNode = Node;
+ while (!Order.empty() && !Visited.count(LoopEnd) &&
dominatesPredicates(Entry, Order.back())) {
- Node = wireFlow(Prev, false);
+ handleLoops(false, LoopEnd);
}
- changeExit(Prev, Next, false);
- Prev = getNextPrev(Next);
+ changeExit(PrevNode, Next, false);
+ setPrevNode(Next);
}
+}
- return Node;
+void AMDGPUStructurizeCFG::handleLoops(bool ExitUseAllowed,
+ BasicBlock *LoopEnd) {
+ RegionNode *Node = Order.back();
+ BasicBlock *LoopStart = Node->getEntry();
+
+ if (!Loops.count(LoopStart)) {
+ wireFlow(ExitUseAllowed, LoopEnd);
+ return;
+ }
+
+ if (!isPredictableTrue(Node))
+ LoopStart = needPrefix(true);
+
+ LoopEnd = Loops[Node->getEntry()];
+ wireFlow(false, LoopEnd);
+ while (!Visited.count(LoopEnd)) {
+ handleLoops(false, LoopEnd);
+ }
+
+ // Create an extra loop end node
+ LoopEnd = needPrefix(false);
+ BasicBlock *Next = needPostfix(LoopEnd, ExitUseAllowed);
+ LoopConds.push_back(BranchInst::Create(Next, LoopStart,
+ BoolUndef, LoopEnd));
+ addPhiValues(LoopEnd, LoopStart);
+ setPrevNode(Next);
}
/// After this function control flow looks like it should be, but
@@ -801,26 +760,17 @@ void AMDGPUStructurizeCFG::createFlow() {
DeletedPhis.clear();
AddedPhis.clear();
Conditions.clear();
+ LoopConds.clear();
- RegionNode *Prev = 0;
- while (!Order.empty()) {
-
- RegionNode *Node = wireFlow(Prev, EntryDominatesExit);
-
- // Create an extra loop end node
- if (Node->getEntry() == LoopEnd) {
- LoopEnd = needPrefix(Prev, 0);
- BasicBlock *Next = needPostfix(LoopEnd, EntryDominatesExit);
+ PrevNode = 0;
+ Visited.clear();
- Conditions.push_back(BranchInst::Create(Next, LoopStart,
- BoolUndef, LoopEnd));
- addPhiValues(LoopEnd, LoopStart);
- Prev = getNextPrev(Next);
- }
+ while (!Order.empty()) {
+ handleLoops(EntryDominatesExit, 0);
}
- if (Prev)
- changeExit(Prev, Exit, EntryDominatesExit);
+ if (PrevNode)
+ changeExit(PrevNode, Exit, EntryDominatesExit);
else
assert(EntryDominatesExit);
}
@@ -880,19 +830,21 @@ bool AMDGPUStructurizeCFG::runOnRegion(Region *R, RGPassManager &RGM) {
orderNodes();
collectInfos();
createFlow();
- insertConditions();
+ insertConditions(false);
+ insertConditions(true);
setPhiValues();
rebuildSSA();
// Cleanup
Order.clear();
Visited.clear();
- Predicates.clear();
DeletedPhis.clear();
AddedPhis.clear();
+ Predicates.clear();
Conditions.clear();
- LoopTargets.clear();
- LoopPred.clear();
+ Loops.clear();
+ LoopPreds.clear();
+ LoopConds.clear();
return true;
}
--
1.7.10.4
More information about the mesa-dev
mailing list