summaryrefslogtreecommitdiffstats
path: root/llvm/lib/Transforms
diff options
context:
space:
mode:
authorDaniel Berlin <dberlin@dberlin.org>2017-02-12 22:12:20 +0000
committerDaniel Berlin <dberlin@dberlin.org>2017-02-12 22:12:20 +0000
commitdbe8264c93b6aebca35a3d5b6dbc74214af2f52f (patch)
tree1fd90eea2f7e8c61fff55d6d33bf7b4df2083a34 /llvm/lib/Transforms
parenteccb8740d126dbd79b93dfe983a54f65689ec291 (diff)
downloadbcm5719-llvm-dbe8264c93b6aebca35a3d5b6dbc74214af2f52f.tar.gz
bcm5719-llvm-dbe8264c93b6aebca35a3d5b6dbc74214af2f52f.zip
PredicateInfo: Handle critical edges
Summary: This adds support for placing predicateinfo such that it affects critical edges. This fixes the issues mentioned by Nuno on the mailing list. Depends on D29519 Reviewers: davide, nlopes Subscribers: llvm-commits Differential Revision: https://reviews.llvm.org/D29606 llvm-svn: 294921
Diffstat (limited to 'llvm/lib/Transforms')
-rw-r--r--llvm/lib/Transforms/Utils/PredicateInfo.cpp170
1 files changed, 107 insertions, 63 deletions
diff --git a/llvm/lib/Transforms/Utils/PredicateInfo.cpp b/llvm/lib/Transforms/Utils/PredicateInfo.cpp
index 6a01c3432ba..9762f4fc963 100644
--- a/llvm/lib/Transforms/Utils/PredicateInfo.cpp
+++ b/llvm/lib/Transforms/Utils/PredicateInfo.cpp
@@ -66,10 +66,12 @@ struct ValueDFS {
int DFSIn = 0;
int DFSOut = 0;
unsigned int LocalNum = LN_Middle;
- PredicateBase *PInfo = nullptr;
// Only one of Def or Use will be set.
Value *Def = nullptr;
Use *U = nullptr;
+ // Neither PInfo nor PhiOnly participate in the ordering
+ PredicateBase *PInfo = nullptr;
+ bool PhiOnly = false;
};
// This compares ValueDFS structures, creating OrderedBasicBlocks where
@@ -90,12 +92,39 @@ struct ValueDFS_Compare {
bool SameBlock = std::tie(A.DFSIn, A.DFSOut) == std::tie(B.DFSIn, B.DFSOut);
+ // We want to put the def that will get used for a given set of phi uses,
+ // before those phi uses.
+ // So we sort by edge, then by def.
+ // Note that only phi nodes uses and defs can come last.
+ if (SameBlock && A.LocalNum == LN_Last && B.LocalNum == LN_Last)
+ return comparePHIRelated(A, B);
+
if (!SameBlock || A.LocalNum != LN_Middle || B.LocalNum != LN_Middle)
return std::tie(A.DFSIn, A.DFSOut, A.LocalNum, A.Def, A.U) <
std::tie(B.DFSIn, B.DFSOut, B.LocalNum, B.Def, B.U);
return localComesBefore(A, B);
}
+ // For a phi use, or a non-materialized def, return the edge it represents.
+ const std::pair<const BasicBlock *, const BasicBlock *>
+ getBlockEdge(const ValueDFS &VD) const {
+ if (!VD.Def && VD.U) {
+ auto *PHI = cast<PHINode>(VD.U->getUser());
+ return std::make_pair(PHI->getIncomingBlock(*VD.U), PHI->getParent());
+ }
+ // This is really a non-materialized def.
+ auto *PBranch = cast<PredicateBranch>(VD.PInfo);
+ return std::make_pair(PBranch->BranchBB, PBranch->SplitBB);
+ }
+
+ // For two phi related values, return the ordering.
+ bool comparePHIRelated(const ValueDFS &A, const ValueDFS &B) const {
+ auto &ABlockEdge = getBlockEdge(A);
+ auto &BBlockEdge = getBlockEdge(B);
+ // Now sort by block edge and then defs before uses.
+ return std::tie(ABlockEdge, A.Def, A.U) < std::tie(BBlockEdge, B.Def, B.U);
+ }
+
// Get the definition of an instruction that occurs in the middle of a block.
Value *getMiddleDef(const ValueDFS &VD) const {
if (VD.Def)
@@ -160,16 +189,37 @@ struct ValueDFS_Compare {
} // namespace PredicateInfoClasses
-bool PredicateInfo::stackIsInScope(const ValueDFSStack &Stack, int DFSIn,
- int DFSOut) const {
+bool PredicateInfo::stackIsInScope(const ValueDFSStack &Stack,
+ const ValueDFS &VDUse) const {
if (Stack.empty())
return false;
- return DFSIn >= Stack.back().DFSIn && DFSOut <= Stack.back().DFSOut;
+ // If it's a phi only use, make sure it's for this phi node edge, and that the
+ // use is in a phi node. If it's anything else, and the top of the stack is
+ // phionly, we need to pop the stack. We deliberately sort phi uses next to
+ // the defs they must go with so that we can know it's time to pop the stack
+ // when we hit the end of the phi uses for a given def.
+ if (Stack.back().PhiOnly) {
+ if (!VDUse.U)
+ return false;
+ auto *PHI = dyn_cast<PHINode>(VDUse.U->getUser());
+ if (!PHI)
+ return false;
+ // The only phionly defs should be branch info.
+ auto *PBranch = dyn_cast<PredicateBranch>(Stack.back().PInfo);
+ assert(PBranch && "Only branches should have PHIOnly defs");
+ // Check edge
+ BasicBlock *EdgePred = PHI->getIncomingBlock(*VDUse.U);
+ if (EdgePred != PBranch->BranchBB)
+ return false;
+ }
+
+ return (VDUse.DFSIn >= Stack.back().DFSIn &&
+ VDUse.DFSOut <= Stack.back().DFSOut);
}
-void PredicateInfo::popStackUntilDFSScope(ValueDFSStack &Stack, int DFSIn,
- int DFSOut) {
- while (!Stack.empty() && !stackIsInScope(Stack, DFSIn, DFSOut))
+void PredicateInfo::popStackUntilDFSScope(ValueDFSStack &Stack,
+ const ValueDFS &VD) {
+ while (!Stack.empty() && !stackIsInScope(Stack, VD))
Stack.pop_back();
}
@@ -271,20 +321,11 @@ void PredicateInfo::processBranch(BranchInst *BI, BasicBlock *BranchBB,
SmallVector<Value *, 8> CmpOperands;
BasicBlock *FirstBB = BI->getSuccessor(0);
BasicBlock *SecondBB = BI->getSuccessor(1);
- bool FirstSinglePred = FirstBB->getSinglePredecessor();
- bool SecondSinglePred = SecondBB->getSinglePredecessor();
SmallVector<BasicBlock *, 2> SuccsToProcess;
bool isAnd = false;
bool isOr = false;
- // First make sure we have single preds for these successors, as we can't
- // usefully propagate true/false info to them if there are multiple paths to
- // them.
- if (FirstSinglePred)
- SuccsToProcess.push_back(FirstBB);
- if (SecondSinglePred)
- SuccsToProcess.push_back(SecondBB);
- if (SuccsToProcess.empty())
- return;
+ SuccsToProcess.push_back(FirstBB);
+ SuccsToProcess.push_back(SecondBB);
// Second, see if we have a comparison we support
SmallVector<Value *, 2> ComparisonsToProcess;
CmpInst::Predicate Pred;
@@ -321,6 +362,8 @@ void PredicateInfo::processBranch(BranchInst *BI, BasicBlock *BranchBB,
new PredicateBranch(Op, BranchBB, Succ, Cmp, TakenEdge);
AllInfos.push_back(PB);
OperandInfo.Infos.push_back(PB);
+ if (!Succ->getSinglePredecessor())
+ PhiUsesOnly.insert({BranchBB, Succ});
}
}
CmpOperands.clear();
@@ -368,29 +411,14 @@ Value *PredicateInfo::materializeStack(unsigned int &Counter,
RenameIter == RenameStack.begin() ? OrigOp : (RenameIter - 1)->Def;
ValueDFS &Result = *RenameIter;
auto *ValInfo = Result.PInfo;
- // For branches, we can just place the operand in the split block. For
- // assume, we have to place it right before the assume to ensure we dominate
- // all of our uses.
+ // For branches, we can just place the operand in the branch block before
+ // the terminator. For assume, we have to place it right before the assume
+ // to ensure we dominate all of our uses. Always insert right before the
+ // relevant instruction (terminator, assume), so that we insert in proper
+ // order in the case of multiple predicateinfo in the same block.
if (isa<PredicateBranch>(ValInfo)) {
auto *PBranch = cast<PredicateBranch>(ValInfo);
- // It's possible we are trying to insert multiple predicateinfos in the
- // same block at the beginning of the block. When we do this, we need to
- // insert them one after the other, not one before the other. To see if we
- // have already inserted predicateinfo into this block, we see if Op !=
- // OrigOp && Op->getParent() == PBranch->SplitBB. Op must be an
- // instruction we inserted if it's not the original op.
- BasicBlock::iterator InsertPt;
- if (Op == OrigOp ||
- cast<Instruction>(Op)->getParent() != PBranch->SplitBB) {
- InsertPt = PBranch->SplitBB->begin();
- // Insert after last phi node.
- while (isa<PHINode>(InsertPt))
- ++InsertPt;
- } else {
- // Insert after op.
- InsertPt = ++(cast<Instruction>(Op)->getIterator());
- }
- IRBuilder<> B(PBranch->SplitBB, InsertPt);
+ IRBuilder<> B(PBranch->BranchBB->getTerminator());
Function *IF = Intrinsic::getDeclaration(
F.getParent(), Intrinsic::ssa_copy, Op->getType());
Value *PIC = B.CreateCall(IF, Op, Op->getName() + "." + Twine(Counter++));
@@ -400,12 +428,7 @@ Value *PredicateInfo::materializeStack(unsigned int &Counter,
auto *PAssume = dyn_cast<PredicateAssume>(ValInfo);
assert(PAssume &&
"Should not have gotten here without it being an assume");
- // Unlike above, this should already insert in the right order when we
- // insert multiple predicateinfos in the same block. Because we are
- // always inserting right before the assume (instead of the beginning of a
- // block), newer insertions will end up after older ones.
- IRBuilder<> B(PAssume->AssumeInst->getParent(),
- PAssume->AssumeInst->getIterator());
+ IRBuilder<> B(PAssume->AssumeInst);
Function *IF = Intrinsic::getDeclaration(
F.getParent(), Intrinsic::ssa_copy, Op->getType());
Value *PIC = B.CreateCall(IF, Op);
@@ -447,28 +470,49 @@ void PredicateInfo::renameUses(SmallPtrSetImpl<Value *> &OpsToRename) {
// created otherwise.
for (auto &PossibleCopy : ValueInfo.Infos) {
ValueDFS VD;
- BasicBlock *CopyBB = nullptr;
// Determine where we are going to place the copy by the copy type.
// The predicate info for branches always come first, they will get
// materialized in the split block at the top of the block.
// The predicate info for assumes will be somewhere in the middle,
// it will get materialized in front of the assume.
- if (const auto *PBranch = dyn_cast<PredicateBranch>(PossibleCopy)) {
- CopyBB = PBranch->SplitBB;
- VD.LocalNum = LN_First;
- } else if (const auto *PAssume =
- dyn_cast<PredicateAssume>(PossibleCopy)) {
- CopyBB = PAssume->AssumeInst->getParent();
+ if (const auto *PAssume = dyn_cast<PredicateAssume>(PossibleCopy)) {
VD.LocalNum = LN_Middle;
- } else
- llvm_unreachable("Unhandled predicate info type");
- DomTreeNode *DomNode = DT.getNode(CopyBB);
- if (!DomNode)
- continue;
- VD.DFSIn = DomNode->getDFSNumIn();
- VD.DFSOut = DomNode->getDFSNumOut();
- VD.PInfo = PossibleCopy;
- OrderedUses.push_back(VD);
+ DomTreeNode *DomNode = DT.getNode(PAssume->AssumeInst->getParent());
+ if (!DomNode)
+ continue;
+ VD.DFSIn = DomNode->getDFSNumIn();
+ VD.DFSOut = DomNode->getDFSNumOut();
+ VD.PInfo = PossibleCopy;
+ OrderedUses.push_back(VD);
+ } else if (const auto *PBranch =
+ dyn_cast<PredicateBranch>(PossibleCopy)) {
+ // If we can only do phi uses, we treat it like it's in the branch
+ // block, and handle it specially. We know that it goes last, and only
+ // dominate phi uses.
+ if (PhiUsesOnly.count({PBranch->BranchBB, PBranch->SplitBB})) {
+ VD.LocalNum = LN_Last;
+ auto *DomNode = DT.getNode(PBranch->BranchBB);
+ if (DomNode) {
+ VD.DFSIn = DomNode->getDFSNumIn();
+ VD.DFSOut = DomNode->getDFSNumOut();
+ VD.PInfo = PossibleCopy;
+ VD.PhiOnly = true;
+ OrderedUses.push_back(VD);
+ }
+ } else {
+ // Otherwise, we are in the split block (even though we perform
+ // insertion in the branch block).
+ // Insert a possible copy at the split block and before the branch.
+ VD.LocalNum = LN_First;
+ auto *DomNode = DT.getNode(PBranch->SplitBB);
+ if (DomNode) {
+ VD.DFSIn = DomNode->getDFSNumIn();
+ VD.DFSOut = DomNode->getDFSNumOut();
+ VD.PInfo = PossibleCopy;
+ OrderedUses.push_back(VD);
+ }
+ }
+ }
}
convertUsesToDFSOrdered(Op, OrderedUses);
@@ -492,10 +536,10 @@ void PredicateInfo::renameUses(SmallPtrSetImpl<Value *> &OpsToRename) {
<< VD.DFSOut << ")\n");
bool ShouldPush = (VD.Def || PossibleCopy);
- bool OutOfScope = !stackIsInScope(RenameStack, VD.DFSIn, VD.DFSOut);
+ bool OutOfScope = !stackIsInScope(RenameStack, VD);
if (OutOfScope || ShouldPush) {
// Sync to our current scope.
- popStackUntilDFSScope(RenameStack, VD.DFSIn, VD.DFSOut);
+ popStackUntilDFSScope(RenameStack, VD);
ShouldPush |= (VD.Def || PossibleCopy);
if (ShouldPush) {
RenameStack.push_back(VD);
OpenPOWER on IntegriCloud