Skip to content

Commit 2107e14

Browse files
Addressed comments
1 parent a1ddf84 commit 2107e14

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
@@ -8465,14 +8465,15 @@ void LoopVectorizationPlanner::buildVPlansWithVPRecipes(ElementCount MinVF,
84658465
for (ElementCount VF = MinVF; ElementCount::isKnownLT(VF, MaxVFTimes2);) {
84668466
VFRange SubRange = {VF, MaxVFTimes2};
84678467
if (auto Plan = tryToBuildVPlanWithVPRecipes(SubRange)) {
8468+
bool IsScalarVPlan = Plan->hasVF(ElementCount::getFixed(1));
84688469
// Now optimize the initial VPlan.
8469-
if (!Plan->hasVF(ElementCount::getFixed(1)))
8470+
if (!IsScalarVPlan)
84708471
VPlanTransforms::truncateToMinimalBitwidths(
84718472
*Plan, CM.getMinimalBitwidths(), PSE.getSE()->getContext());
84728473
VPlanTransforms::optimize(*Plan, *PSE.getSE());
84738474
// TODO: try to put it close to addActiveLaneMask().
84748475
// Discard the plan if it is not EVL-compatible
8475-
if (CM.foldTailWithEVL() &&
8476+
if (!IsScalarVPlan && CM.foldTailWithEVL() &&
84768477
!VPlanTransforms::tryAddExplicitVectorLength(*Plan))
84778478
break;
84788479
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
@@ -1347,9 +1347,9 @@ class VPInstruction : public VPRecipeWithIRFlags {
13471347
/// ingredient. This recipe covers most of the traditional vectorization cases
13481348
/// where each ingredient transforms into a vectorized version of itself.
13491349
class VPWidenRecipe : public VPRecipeWithIRFlags {
1350-
protected:
13511350
unsigned Opcode;
13521351

1352+
protected:
13531353
template <typename IterT>
13541354
VPWidenRecipe(unsigned VPDefOpcode, Instruction &I,
13551355
iterator_range<IterT> Operands)
@@ -1383,7 +1383,6 @@ class VPWidenRecipe : public VPRecipeWithIRFlags {
13831383
};
13841384

13851385
class VPWidenEVLRecipe : public VPWidenRecipe {
1386-
private:
13871386
using VPRecipeWithIRFlags::transferFlags;
13881387

13891388
public:
@@ -1392,6 +1391,10 @@ class VPWidenEVLRecipe : public VPWidenRecipe {
13921391
: VPWidenRecipe(VPDef::VPWidenEVLSC, I, Operands) {
13931392
addOperand(&EVL);
13941393
}
1394+
VPWidenEVLRecipe(VPWidenRecipe *W, VPValue &EVL)
1395+
: VPWidenEVLRecipe(*W->getUnderlyingInstr(), W->operands(), EVL) {
1396+
this->transferFlags(*W);
1397+
}
13951398

13961399
~VPWidenEVLRecipe() override = default;
13971400

@@ -1409,9 +1412,6 @@ class VPWidenEVLRecipe : public VPWidenRecipe {
14091412
VPValue *getEVL() { return getOperand(getNumOperands() - 1); }
14101413
const VPValue *getEVL() const { return getOperand(getNumOperands() - 1); }
14111414

1412-
/// A helper function to create widen EVL recipe from regular widen recipe.
1413-
static VPWidenEVLRecipe *create(VPWidenRecipe *W, VPValue &EVL);
1414-
14151415
/// Produce widened copies of all Ingredients.
14161416
void execute(VPTransformState &State) override final;
14171417

llvm/lib/Transforms/Vectorize/VPlanAnalysis.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -262,7 +262,8 @@ Type *VPTypeAnalysis::inferScalarType(const VPValue *V) {
262262
return inferScalarType(R->getOperand(0));
263263
})
264264
.Case<VPBlendRecipe, VPInstruction, VPWidenRecipe, VPReplicateRecipe,
265-
VPWidenCallRecipe, VPWidenMemoryRecipe, VPWidenSelectRecipe>(
265+
VPWidenCallRecipe, VPWidenMemoryRecipe, VPWidenSelectRecipe,
266+
VPWidenEVLRecipe>(
266267
[this](const auto *R) { return inferScalarTypeForRecipe(R); })
267268
.Case<VPInterleaveRecipe>([V](const VPInterleaveRecipe *R) {
268269
// 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
@@ -1055,20 +1055,14 @@ void VPWidenRecipe::execute(VPTransformState &State) {
10551055
#endif
10561056
}
10571057

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

10691063
// If it's scalar operation, hand translation over to VPWidenRecipe
1070-
if (!State.get(Op0, 0)->getType()->isVectorTy())
1071-
return VPWidenRecipe::execute(State);
1064+
assert(State.get(Op0, 0)->getType()->isVectorTy() &&
1065+
"VPWidenEVLRecipe should not be used for scalars");
10721066

10731067
VPValue *EVL = getEVL();
10741068
Value *EVLArg = State.get(EVL, 0, /*NeedsScalar=*/true);
@@ -1107,10 +1101,7 @@ bool VPWidenEVLRecipe::onlyFirstLaneUsed(const VPValue *Op) const {
11071101
assert(is_contained(operands(), Op) && "Op must be an operand of the recipe");
11081102
// EVL in that recipe is always the last operand, thus any use before means
11091103
// the VPValue should be vectorized.
1110-
for (unsigned I = 0, E = getNumOperands() - 1; I != E; ++I)
1111-
if (getOperand(I) == Op)
1112-
return false;
1113-
return true;
1104+
return getEVL() == Op;
11141105
}
11151106

11161107
#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
@@ -1127,7 +1118,7 @@ void VPWidenEVLRecipe::print(raw_ostream &O, const Twine &Indent,
11271118
VPSlotTracker &SlotTracker) const {
11281119
O << Indent << "WIDEN vp ";
11291120
printAsOperand(O, SlotTracker);
1130-
O << " = " << Instruction::getOpcodeName(Opcode);
1121+
O << " = " << Instruction::getOpcodeName(getOpcode());
11311122
printFlags(O);
11321123
printOperands(O, SlotTracker);
11331124
}

llvm/lib/Transforms/Vectorize/VPlanTransforms.cpp

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

14071407
/// Replace recipes with their EVL variants.
14081408
static void transformRecipestoEVLRecipes(VPlan &Plan, VPValue &EVL) {
1409+
VPDominatorTree VPDT;
1410+
VPDT.recalculate(Plan);
14091411
DenseSet<VPRecipeBase *> ToRemove;
14101412

14111413
ReversePostOrderTraversal<VPBlockDeepTraversalWrapper<VPBlockBase *>> RPOT(
14121414
Plan.getEntry());
14131415
DenseSet<VPValue *> HeaderMasks = collectAllHeaderMasks(Plan);
14141416
for (VPBasicBlock *VPBB :
14151417
reverse(VPBlockUtils::blocksOnly<VPBasicBlock>(RPOT))) {
1416-
// The recipes in the block are processed in reverse order, to catch chains
1417-
// of dead recipes.
14181418
for (VPRecipeBase &R : make_early_inc_range(reverse(*VPBB))) {
1419+
if (!properlyDominates(EVL.getDefiningRecipe(), &R, VPDT))
1420+
continue;
1421+
14191422
TypeSwitch<VPRecipeBase *>(&R)
14201423
.Case<VPWidenLoadRecipe>([&](VPWidenLoadRecipe *L) {
14211424
VPValue *NewMask =
@@ -1437,7 +1440,7 @@ static void transformRecipestoEVLRecipes(VPlan &Plan, VPValue &EVL) {
14371440
if (!Instruction::isBinaryOp(Opcode) &&
14381441
!Instruction::isUnaryOp(Opcode))
14391442
return;
1440-
auto *N = VPWidenEVLRecipe::create(W, EVL);
1443+
auto *N = new VPWidenEVLRecipe(W, EVL);
14411444
N->insertBefore(W);
14421445
W->replaceAllUsesWith(N);
14431446
ToRemove.insert(W);
@@ -1452,8 +1455,6 @@ static void transformRecipestoEVLRecipes(VPlan &Plan, VPValue &EVL) {
14521455
recursivelyDeleteDeadRecipes(HeaderMask);
14531456
}
14541457

1455-
1456-
14571458
/// Add a VPEVLBasedIVPHIRecipe and related recipes to \p Plan and
14581459
/// replaces all uses except the canonical IV increment of
14591460
/// 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)