Skip to content

Commit 5311f92

Browse files
Addressed comments
1 parent ed540f2 commit 5311f92

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
@@ -8549,14 +8549,15 @@ void LoopVectorizationPlanner::buildVPlansWithVPRecipes(ElementCount MinVF,
85498549
for (ElementCount VF = MinVF; ElementCount::isKnownLT(VF, MaxVFTimes2);) {
85508550
VFRange SubRange = {VF, MaxVFTimes2};
85518551
if (auto Plan = tryToBuildVPlanWithVPRecipes(SubRange)) {
8552+
bool IsScalarVPlan = Plan->hasVF(ElementCount::getFixed(1));
85528553
// Now optimize the initial VPlan.
8553-
if (!Plan->hasVF(ElementCount::getFixed(1)))
8554+
if (!IsScalarVPlan)
85548555
VPlanTransforms::truncateToMinimalBitwidths(
85558556
*Plan, CM.getMinimalBitwidths(), PSE.getSE()->getContext());
85568557
VPlanTransforms::optimize(*Plan, *PSE.getSE());
85578558
// TODO: try to put it close to addActiveLaneMask().
85588559
// Discard the plan if it is not EVL-compatible
8559-
if (CM.foldTailWithEVL() &&
8560+
if (!IsScalarVPlan && CM.foldTailWithEVL() &&
85608561
!VPlanTransforms::tryAddExplicitVectorLength(*Plan))
85618562
break;
85628563
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
@@ -1335,9 +1335,9 @@ class VPInstruction : public VPRecipeWithIRFlags {
13351335
/// ingredient. This recipe covers most of the traditional vectorization cases
13361336
/// where each ingredient transforms into a vectorized version of itself.
13371337
class VPWidenRecipe : public VPRecipeWithIRFlags {
1338-
protected:
13391338
unsigned Opcode;
13401339

1340+
protected:
13411341
template <typename IterT>
13421342
VPWidenRecipe(unsigned VPDefOpcode, Instruction &I,
13431343
iterator_range<IterT> Operands)
@@ -1371,7 +1371,6 @@ class VPWidenRecipe : public VPRecipeWithIRFlags {
13711371
};
13721372

13731373
class VPWidenEVLRecipe : public VPWidenRecipe {
1374-
private:
13751374
using VPRecipeWithIRFlags::transferFlags;
13761375

13771376
public:
@@ -1380,6 +1379,10 @@ class VPWidenEVLRecipe : public VPWidenRecipe {
13801379
: VPWidenRecipe(VPDef::VPWidenEVLSC, I, Operands) {
13811380
addOperand(&EVL);
13821381
}
1382+
VPWidenEVLRecipe(VPWidenRecipe *W, VPValue &EVL)
1383+
: VPWidenEVLRecipe(*W->getUnderlyingInstr(), W->operands(), EVL) {
1384+
this->transferFlags(*W);
1385+
}
13831386

13841387
~VPWidenEVLRecipe() override = default;
13851388

@@ -1397,9 +1400,6 @@ class VPWidenEVLRecipe : public VPWidenRecipe {
13971400
VPValue *getEVL() { return getOperand(getNumOperands() - 1); }
13981401
const VPValue *getEVL() const { return getOperand(getNumOperands() - 1); }
13991402

1400-
/// A helper function to create widen EVL recipe from regular widen recipe.
1401-
static VPWidenEVLRecipe *create(VPWidenRecipe *W, VPValue &EVL);
1402-
14031403
/// Produce widened copies of all Ingredients.
14041404
void execute(VPTransformState &State) override final;
14051405

llvm/lib/Transforms/Vectorize/VPlanAnalysis.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -239,7 +239,8 @@ Type *VPTypeAnalysis::inferScalarType(const VPValue *V) {
239239
return inferScalarType(R->getOperand(0));
240240
})
241241
.Case<VPBlendRecipe, VPInstruction, VPWidenRecipe, VPReplicateRecipe,
242-
VPWidenCallRecipe, VPWidenMemoryRecipe, VPWidenSelectRecipe>(
242+
VPWidenCallRecipe, VPWidenMemoryRecipe, VPWidenSelectRecipe,
243+
VPWidenEVLRecipe>(
243244
[this](const auto *R) { return inferScalarTypeForRecipe(R); })
244245
.Case<VPInterleaveRecipe>([V](const VPInterleaveRecipe *R) {
245246
// 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
@@ -997,20 +997,14 @@ void VPWidenRecipe::execute(VPTransformState &State) {
997997
#endif
998998
}
999999

1000-
VPWidenEVLRecipe *VPWidenEVLRecipe::create(VPWidenRecipe *W, VPValue &EVL) {
1001-
auto *R = new VPWidenEVLRecipe(*W->getUnderlyingInstr(), W->operands(), EVL);
1002-
R->transferFlags(*W);
1003-
return R;
1004-
}
1005-
10061000
void VPWidenEVLRecipe::execute(VPTransformState &State) {
10071001
assert(State.UF == 1 && "Expected only UF == 1 when vectorizing with "
10081002
"explicit vector length.");
10091003
VPValue *Op0 = getOperand(0);
10101004

10111005
// If it's scalar operation, hand translation over to VPWidenRecipe
1012-
if (!State.get(Op0, 0)->getType()->isVectorTy())
1013-
return VPWidenRecipe::execute(State);
1006+
assert(State.get(Op0, 0)->getType()->isVectorTy() &&
1007+
"VPWidenEVLRecipe should not be used for scalars");
10141008

10151009
VPValue *EVL = getEVL();
10161010
Value *EVLArg = State.get(EVL, 0, /*NeedsScalar=*/true);
@@ -1049,10 +1043,7 @@ bool VPWidenEVLRecipe::onlyFirstLaneUsed(const VPValue *Op) const {
10491043
assert(is_contained(operands(), Op) && "Op must be an operand of the recipe");
10501044
// EVL in that recipe is always the last operand, thus any use before means
10511045
// the VPValue should be vectorized.
1052-
for (unsigned I = 0, E = getNumOperands() - 1; I != E; ++I)
1053-
if (getOperand(I) == Op)
1054-
return false;
1055-
return true;
1046+
return getEVL() == Op;
10561047
}
10571048

10581049
#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
@@ -1069,7 +1060,7 @@ void VPWidenEVLRecipe::print(raw_ostream &O, const Twine &Indent,
10691060
VPSlotTracker &SlotTracker) const {
10701061
O << Indent << "WIDEN vp ";
10711062
printAsOperand(O, SlotTracker);
1072-
O << " = " << Instruction::getOpcodeName(Opcode);
1063+
O << " = " << Instruction::getOpcodeName(getOpcode());
10731064
printFlags(O);
10741065
printOperands(O, SlotTracker);
10751066
}

llvm/lib/Transforms/Vectorize/VPlanTransforms.cpp

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

13001300
/// Replace recipes with their EVL variants.
13011301
static void transformRecipestoEVLRecipes(VPlan &Plan, VPValue &EVL) {
1302+
VPDominatorTree VPDT;
1303+
VPDT.recalculate(Plan);
13021304
DenseSet<VPRecipeBase *> ToRemove;
13031305

13041306
ReversePostOrderTraversal<VPBlockDeepTraversalWrapper<VPBlockBase *>> RPOT(
13051307
Plan.getEntry());
13061308
DenseSet<VPValue *> HeaderMasks = collectAllHeaderMasks(Plan);
13071309
for (VPBasicBlock *VPBB :
13081310
reverse(VPBlockUtils::blocksOnly<VPBasicBlock>(RPOT))) {
1309-
// The recipes in the block are processed in reverse order, to catch chains
1310-
// of dead recipes.
13111311
for (VPRecipeBase &R : make_early_inc_range(reverse(*VPBB))) {
1312+
if (!properlyDominates(EVL.getDefiningRecipe(), &R, VPDT))
1313+
continue;
1314+
13121315
TypeSwitch<VPRecipeBase *>(&R)
13131316
.Case<VPWidenLoadRecipe>([&](VPWidenLoadRecipe *L) {
13141317
VPValue *NewMask =
@@ -1330,7 +1333,7 @@ static void transformRecipestoEVLRecipes(VPlan &Plan, VPValue &EVL) {
13301333
if (!Instruction::isBinaryOp(Opcode) &&
13311334
!Instruction::isUnaryOp(Opcode))
13321335
return;
1333-
auto *N = VPWidenEVLRecipe::create(W, EVL);
1336+
auto *N = new VPWidenEVLRecipe(W, EVL);
13341337
N->insertBefore(W);
13351338
W->replaceAllUsesWith(N);
13361339
ToRemove.insert(W);
@@ -1345,8 +1348,6 @@ static void transformRecipestoEVLRecipes(VPlan &Plan, VPValue &EVL) {
13451348
recursivelyDeleteDeadRecipes(HeaderMask);
13461349
}
13471350

1348-
1349-
13501351
/// Add a VPEVLBasedIVPHIRecipe and related recipes to \p Plan and
13511352
/// replaces all uses except the canonical IV increment of
13521353
/// 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)