summaryrefslogtreecommitdiffstats
path: root/llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp
diff options
context:
space:
mode:
authorMatthew Simpson <mssimpso@codeaurora.org>2016-08-18 19:50:32 +0000
committerMatthew Simpson <mssimpso@codeaurora.org>2016-08-18 19:50:32 +0000
commit11db6b6b8c01161e0e67de462552e481194515e9 (patch)
treea504cdb74ce050a70db28e7d5c3847e6a82e03ef /llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp
parent075d0c23d5885d926a3497bd3504df1d81f04270 (diff)
downloadbcm5719-llvm-11db6b6b8c01161e0e67de462552e481194515e9.tar.gz
bcm5719-llvm-11db6b6b8c01161e0e67de462552e481194515e9.zip
[SLP] Initialize VectorizedValue when gathering
We abort building vectorizable trees in some cases (e.g., if the maximum recursion depth is reached, if the region size is too large, etc.). If this happens for a reduction, we can be left with a root entry that needs to be gathered. For these cases, we need make sure we actually set VectorizedValue to the resulting vector. This patch ensures we properly set VectorizedValue, and it also ensures the insertelement sequence generated for the gathers is inserted at the correct location. Reference: https://llvm.org/bugs/show_bug.cgi?id=28330 Differential Revison: https://reviews.llvm.org/D23410 llvm-svn: 279125
Diffstat (limited to 'llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp')
-rw-r--r--llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp74
1 files changed, 66 insertions, 8 deletions
diff --git a/llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp b/llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp
index 83d1aff07fe..9c0b053e3e1 100644
--- a/llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp
+++ b/llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp
@@ -2153,11 +2153,61 @@ void BoUpSLP::reorderInputsAccordingToOpcode(ArrayRef<Value *> VL,
}
void BoUpSLP::setInsertPointAfterBundle(ArrayRef<Value *> VL) {
- Instruction *VL0 = cast<Instruction>(VL[0]);
- BasicBlock::iterator NextInst(VL0);
- ++NextInst;
- Builder.SetInsertPoint(VL0->getParent(), NextInst);
- Builder.SetCurrentDebugLocation(VL0->getDebugLoc());
+
+ // Get the basic block this bundle is in. All instructions in the bundle
+ // should be in this block.
+ auto *Front = cast<Instruction>(VL.front());
+ auto *BB = Front->getParent();
+ assert(all_of(make_range(VL.begin(), VL.end()), [&](Value *V) -> bool {
+ return cast<Instruction>(V)->getParent() == BB;
+ }));
+
+ // The last instruction in the bundle in program order.
+ Instruction *LastInst = nullptr;
+
+ // Find the last instruction. The common case should be that BB has been
+ // scheduled, and the last instruction is VL.back(). So we start with
+ // VL.back() and iterate over schedule data until we reach the end of the
+ // bundle. The end of the bundle is marked by null ScheduleData.
+ if (BlocksSchedules.count(BB)) {
+ auto *Bundle = BlocksSchedules[BB]->getScheduleData(VL.back());
+ if (Bundle && Bundle->isPartOfBundle())
+ for (; Bundle; Bundle = Bundle->NextInBundle)
+ LastInst = Bundle->Inst;
+ }
+
+ // LastInst can still be null at this point if there's either not an entry
+ // for BB in BlocksSchedules or there's no ScheduleData available for
+ // VL.back(). This can be the case if buildTree_rec aborts for various
+ // reasons (e.g., the maximum recursion depth is reached, the maximum region
+ // size is reached, etc.). ScheduleData is initialized in the scheduling
+ // "dry-run".
+ //
+ // If this happens, we can still find the last instruction by brute force. We
+ // iterate forwards from Front (inclusive) until we either see all
+ // instructions in the bundle or reach the end of the block. If Front is the
+ // last instruction in program order, LastInst will be set to Front, and we
+ // will visit all the remaining instructions in the block.
+ //
+ // One of the reasons we exit early from buildTree_rec is to place an upper
+ // bound on compile-time. Thus, taking an additional compile-time hit here is
+ // not ideal. However, this should be exceedingly rare since it requires that
+ // we both exit early from buildTree_rec and that the bundle be out-of-order
+ // (causing us to iterate all the way to the end of the block).
+ if (!LastInst) {
+ SmallPtrSet<Value *, 16> Bundle(VL.begin(), VL.end());
+ for (auto &I : make_range(BasicBlock::iterator(Front), BB->end())) {
+ if (Bundle.erase(&I))
+ LastInst = &I;
+ if (Bundle.empty())
+ break;
+ }
+ }
+
+ // Set the insertion point after the last instruction in the bundle. Set the
+ // debug location to Front.
+ Builder.SetInsertPoint(BB, next(BasicBlock::iterator(LastInst)));
+ Builder.SetCurrentDebugLocation(Front->getDebugLoc());
}
Value *BoUpSLP::Gather(ArrayRef<Value *> VL, VectorType *Ty) {
@@ -2235,7 +2285,9 @@ Value *BoUpSLP::vectorizeTree(TreeEntry *E) {
if (E->NeedToGather) {
setInsertPointAfterBundle(E->Scalars);
- return Gather(E->Scalars, VecTy);
+ auto *V = Gather(E->Scalars, VecTy);
+ E->VectorizedValue = V;
+ return V;
}
unsigned Opcode = getSameOpcode(E->Scalars);
@@ -2282,7 +2334,10 @@ Value *BoUpSLP::vectorizeTree(TreeEntry *E) {
E->VectorizedValue = V;
return V;
}
- return Gather(E->Scalars, VecTy);
+ setInsertPointAfterBundle(E->Scalars);
+ auto *V = Gather(E->Scalars, VecTy);
+ E->VectorizedValue = V;
+ return V;
}
case Instruction::ExtractValue: {
if (canReuseExtract(E->Scalars, Instruction::ExtractValue)) {
@@ -2294,7 +2349,10 @@ Value *BoUpSLP::vectorizeTree(TreeEntry *E) {
E->VectorizedValue = V;
return propagateMetadata(V, E->Scalars);
}
- return Gather(E->Scalars, VecTy);
+ setInsertPointAfterBundle(E->Scalars);
+ auto *V = Gather(E->Scalars, VecTy);
+ E->VectorizedValue = V;
+ return V;
}
case Instruction::ZExt:
case Instruction::SExt:
OpenPOWER on IntegriCloud