Skip to content

Commit b229fcf

Browse files
Addressed comments
1 parent a84848b commit b229fcf

File tree

7 files changed

+93
-28
lines changed

7 files changed

+93
-28
lines changed

llvm/lib/Transforms/Vectorize/LoopVectorize.cpp

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8457,14 +8457,15 @@ void LoopVectorizationPlanner::buildVPlansWithVPRecipes(ElementCount MinVF,
84578457
for (ElementCount VF = MinVF; ElementCount::isKnownLT(VF, MaxVFTimes2);) {
84588458
VFRange SubRange = {VF, MaxVFTimes2};
84598459
if (auto Plan = tryToBuildVPlanWithVPRecipes(SubRange)) {
8460+
bool IsScalarVPlan = Plan->hasVF(ElementCount::getFixed(1));
84608461
// Now optimize the initial VPlan.
8461-
if (!Plan->hasVF(ElementCount::getFixed(1)))
8462+
if (!IsScalarVPlan)
84628463
VPlanTransforms::truncateToMinimalBitwidths(
84638464
*Plan, CM.getMinimalBitwidths(), PSE.getSE()->getContext());
84648465
VPlanTransforms::optimize(*Plan, *PSE.getSE());
84658466
// TODO: try to put it close to addActiveLaneMask().
84668467
// Discard the plan if it is not EVL-compatible
8467-
if (CM.foldTailWithEVL() &&
8468+
if (!IsScalarVPlan && CM.foldTailWithEVL() &&
84688469
!VPlanTransforms::tryAddExplicitVectorLength(*Plan))
84698470
break;
84708471
assert(verifyVPlanIsValid(*Plan) && "VPlan is invalid");

llvm/lib/Transforms/Vectorize/VPlan.h

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1338,9 +1338,9 @@ class VPInstruction : public VPRecipeWithIRFlags {
13381338
/// ingredient. This recipe covers most of the traditional vectorization cases
13391339
/// where each ingredient transforms into a vectorized version of itself.
13401340
class VPWidenRecipe : public VPRecipeWithIRFlags {
1341-
protected:
13421341
unsigned Opcode;
13431342

1343+
protected:
13441344
template <typename IterT>
13451345
VPWidenRecipe(unsigned VPDefOpcode, Instruction &I,
13461346
iterator_range<IterT> Operands)
@@ -1374,7 +1374,6 @@ class VPWidenRecipe : public VPRecipeWithIRFlags {
13741374
};
13751375

13761376
class VPWidenEVLRecipe : public VPWidenRecipe {
1377-
private:
13781377
using VPRecipeWithIRFlags::transferFlags;
13791378

13801379
public:
@@ -1383,6 +1382,10 @@ class VPWidenEVLRecipe : public VPWidenRecipe {
13831382
: VPWidenRecipe(VPDef::VPWidenEVLSC, I, Operands) {
13841383
addOperand(&EVL);
13851384
}
1385+
VPWidenEVLRecipe(VPWidenRecipe *W, VPValue &EVL)
1386+
: VPWidenEVLRecipe(*W->getUnderlyingInstr(), W->operands(), EVL) {
1387+
this->transferFlags(*W);
1388+
}
13861389

13871390
~VPWidenEVLRecipe() override = default;
13881391

@@ -1400,9 +1403,6 @@ class VPWidenEVLRecipe : public VPWidenRecipe {
14001403
VPValue *getEVL() { return getOperand(getNumOperands() - 1); }
14011404
const VPValue *getEVL() const { return getOperand(getNumOperands() - 1); }
14021405

1403-
/// A helper function to create widen EVL recipe from regular widen recipe.
1404-
static VPWidenEVLRecipe *create(VPWidenRecipe *W, VPValue &EVL);
1405-
14061406
/// Produce widened copies of all Ingredients.
14071407
void execute(VPTransformState &State) override final;
14081408

llvm/lib/Transforms/Vectorize/VPlanAnalysis.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -253,7 +253,8 @@ Type *VPTypeAnalysis::inferScalarType(const VPValue *V) {
253253
return inferScalarType(R->getOperand(0));
254254
})
255255
.Case<VPBlendRecipe, VPInstruction, VPWidenRecipe, VPReplicateRecipe,
256-
VPWidenCallRecipe, VPWidenMemoryRecipe, VPWidenSelectRecipe>(
256+
VPWidenCallRecipe, VPWidenMemoryRecipe, VPWidenSelectRecipe,
257+
VPWidenEVLRecipe>(
257258
[this](const auto *R) { return inferScalarTypeForRecipe(R); })
258259
.Case<VPInterleaveRecipe>([V](const VPInterleaveRecipe *R) {
259260
// TODO: Use info from interleave group.

llvm/lib/Transforms/Vectorize/VPlanRecipes.cpp

Lines changed: 4 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1053,20 +1053,14 @@ void VPWidenRecipe::execute(VPTransformState &State) {
10531053
#endif
10541054
}
10551055

1056-
VPWidenEVLRecipe *VPWidenEVLRecipe::create(VPWidenRecipe *W, VPValue &EVL) {
1057-
auto *R = new VPWidenEVLRecipe(*W->getUnderlyingInstr(), W->operands(), EVL);
1058-
R->transferFlags(*W);
1059-
return R;
1060-
}
1061-
10621056
void VPWidenEVLRecipe::execute(VPTransformState &State) {
10631057
assert(State.UF == 1 && "Expected only UF == 1 when vectorizing with "
10641058
"explicit vector length.");
10651059
VPValue *Op0 = getOperand(0);
10661060

10671061
// If it's scalar operation, hand translation over to VPWidenRecipe
1068-
if (!State.get(Op0, 0)->getType()->isVectorTy())
1069-
return VPWidenRecipe::execute(State);
1062+
assert(State.get(Op0, 0)->getType()->isVectorTy() &&
1063+
"VPWidenEVLRecipe should not be used for scalars");
10701064

10711065
VPValue *EVL = getEVL();
10721066
Value *EVLArg = State.get(EVL, 0, /*NeedsScalar=*/true);
@@ -1105,10 +1099,7 @@ bool VPWidenEVLRecipe::onlyFirstLaneUsed(const VPValue *Op) const {
11051099
assert(is_contained(operands(), Op) && "Op must be an operand of the recipe");
11061100
// EVL in that recipe is always the last operand, thus any use before means
11071101
// the VPValue should be vectorized.
1108-
for (unsigned I = 0, E = getNumOperands() - 1; I != E; ++I)
1109-
if (getOperand(I) == Op)
1110-
return false;
1111-
return true;
1102+
return getEVL() == Op;
11121103
}
11131104

11141105
#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
@@ -1125,7 +1116,7 @@ void VPWidenEVLRecipe::print(raw_ostream &O, const Twine &Indent,
11251116
VPSlotTracker &SlotTracker) const {
11261117
O << Indent << "WIDEN vp ";
11271118
printAsOperand(O, SlotTracker);
1128-
O << " = " << Instruction::getOpcodeName(Opcode);
1119+
O << " = " << Instruction::getOpcodeName(getOpcode());
11291120
printFlags(O);
11301121
printOperands(O, SlotTracker);
11311122
}

llvm/lib/Transforms/Vectorize/VPlanTransforms.cpp

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1387,16 +1387,19 @@ void VPlanTransforms::addActiveLaneMask(
13871387

13881388
/// Replace recipes with their EVL variants.
13891389
static void transformRecipestoEVLRecipes(VPlan &Plan, VPValue &EVL) {
1390+
VPDominatorTree VPDT;
1391+
VPDT.recalculate(Plan);
13901392
DenseSet<VPRecipeBase *> ToRemove;
13911393

13921394
ReversePostOrderTraversal<VPBlockDeepTraversalWrapper<VPBlockBase *>> RPOT(
13931395
Plan.getEntry());
13941396
DenseSet<VPValue *> HeaderMasks = collectAllHeaderMasks(Plan);
13951397
for (VPBasicBlock *VPBB :
13961398
reverse(VPBlockUtils::blocksOnly<VPBasicBlock>(RPOT))) {
1397-
// The recipes in the block are processed in reverse order, to catch chains
1398-
// of dead recipes.
13991399
for (VPRecipeBase &R : make_early_inc_range(reverse(*VPBB))) {
1400+
if (!properlyDominates(EVL.getDefiningRecipe(), &R, VPDT))
1401+
continue;
1402+
14001403
TypeSwitch<VPRecipeBase *>(&R)
14011404
.Case<VPWidenLoadRecipe>([&](VPWidenLoadRecipe *L) {
14021405
VPValue *NewMask =
@@ -1418,7 +1421,7 @@ static void transformRecipestoEVLRecipes(VPlan &Plan, VPValue &EVL) {
14181421
if (!Instruction::isBinaryOp(Opcode) &&
14191422
!Instruction::isUnaryOp(Opcode))
14201423
return;
1421-
auto *N = VPWidenEVLRecipe::create(W, EVL);
1424+
auto *N = new VPWidenEVLRecipe(W, EVL);
14221425
N->insertBefore(W);
14231426
W->replaceAllUsesWith(N);
14241427
ToRemove.insert(W);
@@ -1433,8 +1436,6 @@ static void transformRecipestoEVLRecipes(VPlan &Plan, VPValue &EVL) {
14331436
recursivelyDeleteDeadRecipes(HeaderMask);
14341437
}
14351438

1436-
1437-
14381439
/// Add a VPEVLBasedIVPHIRecipe and related recipes to \p Plan and
14391440
/// replaces all uses except the canonical IV increment of
14401441
/// VPCanonicalIVPHIRecipe with a VPEVLBasedIVPHIRecipe. VPCanonicalIVPHIRecipe

llvm/lib/Transforms/Vectorize/VPlanVerifier.cpp

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
#include "VPlanDominatorTree.h"
1919
#include "llvm/ADT/DepthFirstIterator.h"
2020
#include "llvm/ADT/SmallPtrSet.h"
21+
#include "llvm/ADT/TypeSwitch.h"
2122
#include "llvm/Support/CommandLine.h"
2223

2324
#define DEBUG_TYPE "loop-vectorize"
@@ -35,6 +36,11 @@ class VPlanVerifier {
3536
// VPHeaderPHIRecipes.
3637
bool verifyPhiRecipes(const VPBasicBlock *VPBB);
3738

39+
// Verify that \p EVL is used correctly. The user must be either in EVL-based
40+
// recipes as a last operand or VPInstruction::Add which is incoming value
41+
// into EVL's recipe.
42+
bool verifyEVLRecipe(const VPInstruction &EVL) const;
43+
3844
bool verifyVPBasicBlock(const VPBasicBlock *VPBB);
3945

4046
bool verifyBlock(const VPBlockBase *VPB);
@@ -114,6 +120,64 @@ bool VPlanVerifier::verifyPhiRecipes(const VPBasicBlock *VPBB) {
114120
return true;
115121
}
116122

123+
bool VPlanVerifier::verifyEVLRecipe(const VPInstruction &EVL) const {
124+
if (EVL.getOpcode() != VPInstruction::ExplicitVectorLength) {
125+
errs() << "verifyEVLRecipe should only be called on "
126+
"VPInstruction::ExplicitVectorLength\n";
127+
return false;
128+
}
129+
auto VerifyEVLUse = [&](const VPRecipeBase &R,
130+
const unsigned ExpectedIdx) -> bool {
131+
SmallVector<const VPValue *> Ops(R.operands());
132+
unsigned UseCount = count(Ops, &EVL);
133+
if (UseCount != 1 || Ops[ExpectedIdx] != &EVL) {
134+
errs() << "EVL is used as non-last operand in EVL-based recipe\n";
135+
return false;
136+
}
137+
return true;
138+
};
139+
for (const VPUser *U : EVL.users()) {
140+
if (!TypeSwitch<const VPUser *, bool>(U)
141+
.Case<VPWidenStoreEVLRecipe>([&](const VPWidenStoreEVLRecipe *S) {
142+
return VerifyEVLUse(*S, 2);
143+
})
144+
.Case<VPWidenLoadEVLRecipe>([&](const VPWidenLoadEVLRecipe *L) {
145+
return VerifyEVLUse(*L, 1);
146+
})
147+
.Case<VPWidenEVLRecipe>([&](const VPWidenEVLRecipe *W) {
148+
return VerifyEVLUse(
149+
*W, Instruction::isUnaryOp(W->getOpcode()) ? 1 : 2);
150+
})
151+
.Case<VPScalarCastRecipe>(
152+
[&](const VPScalarCastRecipe *S) { return true; })
153+
.Case<VPInstruction>([&](const VPInstruction *I) {
154+
if (I->getOpcode() != Instruction::Add) {
155+
errs()
156+
<< "EVL is used as an operand in non-VPInstruction::Add\n";
157+
return false;
158+
}
159+
if (I->getNumUsers() != 1) {
160+
errs() << "EVL is used in VPInstruction:Add with multiple "
161+
"users\n";
162+
return false;
163+
}
164+
if (!isa<VPEVLBasedIVPHIRecipe>(*I->users().begin())) {
165+
errs() << "Result of VPInstruction::Add with EVL operand is "
166+
"not used by VPEVLBasedIVPHIRecipe\n";
167+
return false;
168+
}
169+
return true;
170+
})
171+
.Default([&](const VPUser *U) {
172+
errs() << "EVL has unexpected user\n";
173+
return false;
174+
})) {
175+
return false;
176+
}
177+
}
178+
return true;
179+
}
180+
117181
bool VPlanVerifier::verifyVPBasicBlock(const VPBasicBlock *VPBB) {
118182
if (!verifyPhiRecipes(VPBB))
119183
return false;
@@ -150,6 +214,13 @@ bool VPlanVerifier::verifyVPBasicBlock(const VPBasicBlock *VPBB) {
150214
}
151215
}
152216
}
217+
if (const auto *EVL = dyn_cast<VPInstruction>(&R)) {
218+
if (EVL->getOpcode() == VPInstruction::ExplicitVectorLength &&
219+
!verifyEVLRecipe(*EVL)) {
220+
errs() << "EVL VPValue is not used correctly\n";
221+
return false;
222+
}
223+
}
153224
}
154225

155226
auto *IRBB = dyn_cast<VPIRBasicBlock>(VPBB);

llvm/test/Transforms/LoopVectorize/RISCV/vectorize-force-tail-with-evl-bin-unary-ops-args.ll

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,12 @@
22
; RUN: opt -passes=loop-vectorize \
33
; RUN: -force-tail-folding-style=data-with-evl \
44
; RUN: -prefer-predicate-over-epilogue=predicate-dont-vectorize \
5-
; RUN: -mtriple=riscv64 -mattr=+v -S < %s | FileCheck %s --check-prefix=IF-EVL
5+
; RUN: -mtriple=riscv64 -mattr=+v -S %s | FileCheck %s --check-prefix=IF-EVL
66

77
; RUN: opt -passes=loop-vectorize \
88
; RUN: -force-tail-folding-style=none \
99
; RUN: -prefer-predicate-over-epilogue=predicate-dont-vectorize \
10-
; RUN: -mtriple=riscv64 -mattr=+v -S < %s | FileCheck %s --check-prefix=NO-VP
10+
; RUN: -mtriple=riscv64 -mattr=+v -S %s | FileCheck %s --check-prefix=NO-VP
1111

1212

1313
define void @test_and(ptr nocapture %a, ptr nocapture readonly %b) {

0 commit comments

Comments
 (0)