Skip to content

Commit ce46e1a

Browse files
committed
[NFC][SLP] Cleanup: Simplify traversal loop in SLPVectorizerPass::vectorizeHorReduction().
This includes a couple of changes: 1. Moves the code that changes the root node out of the `TryToReduce` lambda and out of the traversal loop. 2. Since that code moved, there isn't much left in `TryToReduce` so the code was inlined. 3. The phi node variable `P` was also being used as a flag that turns on/off the exploration of operands as new seeds. This patch uses a new variable `TryOperandsAsNewSeeds` for this. 4. Simplifies the code executed when vectorization fails. The logic of the code should be identical to the original, but I may be missing something not caught by tests. Differential Revision: https://reviews.llvm.org/D149627
1 parent 24f8122 commit ce46e1a

File tree

1 file changed

+55
-42
lines changed

1 file changed

+55
-42
lines changed

llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp

Lines changed: 55 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -14078,16 +14078,43 @@ static Instruction *tryGetSecondaryReductionRoot(PHINode *Phi,
1407814078
return nullptr;
1407914079
}
1408014080

14081+
/// \p Returns the first operand of \p I that does not match \p Phi. If
14082+
/// operand is not an instruction it returns nullptr.
14083+
static Instruction *getNonPhiOperand(Instruction *I, PHINode *Phi) {
14084+
Value *Op0 = nullptr;
14085+
Value *Op1 = nullptr;
14086+
if (!matchRdxBop(I, Op0, Op1))
14087+
return nullptr;
14088+
return dyn_cast<Instruction>(Op0 == Phi ? Op1 : Op0);
14089+
}
14090+
14091+
/// \Returns true if \p I is a candidate instruction for reduction vectorization.
14092+
static bool isReductionCandidate(Instruction *I) {
14093+
bool IsSelect = match(I, m_Select(m_Value(), m_Value(), m_Value()));
14094+
Value *B0 = nullptr, *B1 = nullptr;
14095+
bool IsBinop = matchRdxBop(I, B0, B1);
14096+
return IsBinop || IsSelect;
14097+
}
14098+
1408114099
bool SLPVectorizerPass::vectorizeHorReduction(
1408214100
PHINode *P, Instruction *Root, BasicBlock *BB, BoUpSLP &R, TargetTransformInfo *TTI,
1408314101
SmallVectorImpl<WeakTrackingVH> &PostponedInsts) {
1408414102
if (!ShouldVectorizeHor)
1408514103
return false;
14086-
if (!isa<BinaryOperator>(Root))
14087-
P = nullptr;
14104+
bool TryOperandsAsNewSeeds = P && isa<BinaryOperator>(Root);
1408814105

1408914106
if (Root->getParent() != BB || isa<PHINode>(Root))
1409014107
return false;
14108+
14109+
// If we can find a secondary reduction root, use that instead.
14110+
auto SelectRoot = [&]() {
14111+
if (TryOperandsAsNewSeeds && isReductionCandidate(Root) &&
14112+
HorizontalReduction::getRdxKind(Root) != RecurKind::None)
14113+
if (Instruction *NewRoot = tryGetSecondaryReductionRoot(P, Root))
14114+
return NewRoot;
14115+
return Root;
14116+
};
14117+
1409114118
// Start analysis starting from Root instruction. If horizontal reduction is
1409214119
// found, try to vectorize it. If it is not a horizontal reduction or
1409314120
// vectorization is not possible or not effective, and currently analyzed
@@ -14100,28 +14127,32 @@ bool SLPVectorizerPass::vectorizeHorReduction(
1410014127
// If a horizintal reduction was not matched or vectorized we collect
1410114128
// instructions for possible later attempts for vectorization.
1410214129
std::queue<std::pair<Instruction *, unsigned>> Stack;
14103-
Stack.emplace(Root, 0);
14130+
Stack.emplace(SelectRoot(), 0);
1410414131
SmallPtrSet<Value *, 8> VisitedInstrs;
1410514132
bool Res = false;
14106-
auto &&TryToReduce = [this, TTI, &P, &R](Instruction *Inst, Value *&B0,
14107-
Value *&B1) -> Value * {
14133+
auto &&TryToReduce = [this, TTI, &R](Instruction *Inst) -> Value * {
1410814134
if (R.isAnalyzedReductionRoot(Inst))
1410914135
return nullptr;
14110-
bool IsBinop = matchRdxBop(Inst, B0, B1);
14111-
bool IsSelect = match(Inst, m_Select(m_Value(), m_Value(), m_Value()));
14112-
if (IsBinop || IsSelect) {
14113-
assert((!P || is_contained(P->operands(), Inst)) &&
14114-
"Phi needs to use the binary operator");
14115-
if (P && HorizontalReduction::getRdxKind(Inst) != RecurKind::None)
14116-
if (Instruction *NewRoot = tryGetSecondaryReductionRoot(P, Inst))
14117-
Inst = NewRoot;
14118-
14119-
HorizontalReduction HorRdx;
14120-
if (HorRdx.matchAssociativeReduction(Inst, *SE, *DL, *TLI))
14121-
return HorRdx.tryToReduce(R, TTI, *TLI);
14136+
if (!isReductionCandidate(Inst))
14137+
return nullptr;
14138+
HorizontalReduction HorRdx;
14139+
if (!HorRdx.matchAssociativeReduction(Inst, *SE, *DL, *TLI))
14140+
return nullptr;
14141+
return HorRdx.tryToReduce(R, TTI, *TLI);
14142+
};
14143+
auto TryAppendToPostponedInsts = [&](Instruction *FutureSeed) {
14144+
if (TryOperandsAsNewSeeds && FutureSeed == Root) {
14145+
FutureSeed = getNonPhiOperand(Root, P);
14146+
if (!FutureSeed)
14147+
return false;
1412214148
}
14123-
return nullptr;
14149+
// Do not collect CmpInst or InsertElementInst/InsertValueInst as their
14150+
// analysis is done separately.
14151+
if (!isa<CmpInst, InsertElementInst, InsertValueInst>(FutureSeed))
14152+
PostponedInsts.push_back(FutureSeed);
14153+
return true;
1412414154
};
14155+
1412514156
while (!Stack.empty()) {
1412614157
Instruction *Inst;
1412714158
unsigned Level;
@@ -14132,37 +14163,19 @@ bool SLPVectorizerPass::vectorizeHorReduction(
1413214163
// iteration while stack was populated before that happened.
1413314164
if (R.isDeleted(Inst))
1413414165
continue;
14135-
Value *B0 = nullptr, *B1 = nullptr;
14136-
if (Value *V = TryToReduce(Inst, B0, B1)) {
14166+
if (Value *VectorizedV = TryToReduce(Inst)) {
1413714167
Res = true;
14138-
// Set P to nullptr to avoid re-analysis of phi node in
14139-
// matchAssociativeReduction function unless this is the root node.
14140-
P = nullptr;
14141-
if (auto *I = dyn_cast<Instruction>(V)) {
14168+
if (auto *I = dyn_cast<Instruction>(VectorizedV)) {
1414214169
// Try to find another reduction.
1414314170
Stack.emplace(I, Level);
1414414171
continue;
1414514172
}
1414614173
} else {
14147-
bool IsBinop = B0 && B1;
14148-
if (P && IsBinop) {
14149-
Inst = dyn_cast<Instruction>(B0);
14150-
if (Inst == P)
14151-
Inst = dyn_cast<Instruction>(B1);
14152-
if (!Inst) {
14153-
// Set P to nullptr to avoid re-analysis of phi node in
14154-
// matchAssociativeReduction function unless this is the root node.
14155-
P = nullptr;
14156-
continue;
14157-
}
14174+
// We could not vectorize `Inst` so try to use it as a future seed.
14175+
if (!TryAppendToPostponedInsts(Inst)) {
14176+
assert(Stack.empty() && "Expected empty stack");
14177+
break;
1415814178
}
14159-
// Set P to nullptr to avoid re-analysis of phi node in
14160-
// matchAssociativeReduction function unless this is the root node.
14161-
P = nullptr;
14162-
// Do not collect CmpInst or InsertElementInst/InsertValueInst as their
14163-
// analysis is done separately.
14164-
if (!isa<CmpInst, InsertElementInst, InsertValueInst>(Inst))
14165-
PostponedInsts.push_back(Inst);
1416614179
}
1416714180

1416814181
// Try to vectorize operands.

0 commit comments

Comments
 (0)