Skip to content

Commit e3e2fd3

Browse files
Addressed comments
1 parent f7f90bc commit e3e2fd3

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
@@ -8458,14 +8458,15 @@ void LoopVectorizationPlanner::buildVPlansWithVPRecipes(ElementCount MinVF,
84588458
for (ElementCount VF = MinVF; ElementCount::isKnownLT(VF, MaxVFTimes2);) {
84598459
VFRange SubRange = {VF, MaxVFTimes2};
84608460
if (auto Plan = tryToBuildVPlanWithVPRecipes(SubRange)) {
8461+
bool IsScalarVPlan = Plan->hasVF(ElementCount::getFixed(1));
84618462
// Now optimize the initial VPlan.
8462-
if (!Plan->hasVF(ElementCount::getFixed(1)))
8463+
if (!IsScalarVPlan)
84638464
VPlanTransforms::truncateToMinimalBitwidths(
84648465
*Plan, CM.getMinimalBitwidths(), PSE.getSE()->getContext());
84658466
VPlanTransforms::optimize(*Plan, *PSE.getSE());
84668467
// TODO: try to put it close to addActiveLaneMask().
84678468
// Discard the plan if it is not EVL-compatible
8468-
if (CM.foldTailWithEVL() &&
8469+
if (!IsScalarVPlan && CM.foldTailWithEVL() &&
84698470
!VPlanTransforms::tryAddExplicitVectorLength(*Plan))
84708471
break;
84718472
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
@@ -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
@@ -1054,20 +1054,14 @@ void VPWidenRecipe::execute(VPTransformState &State) {
10541054
#endif
10551055
}
10561056

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

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

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

11151106
#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
@@ -1126,7 +1117,7 @@ void VPWidenEVLRecipe::print(raw_ostream &O, const Twine &Indent,
11261117
VPSlotTracker &SlotTracker) const {
11271118
O << Indent << "WIDEN vp ";
11281119
printAsOperand(O, SlotTracker);
1129-
O << " = " << Instruction::getOpcodeName(Opcode);
1120+
O << " = " << Instruction::getOpcodeName(getOpcode());
11301121
printFlags(O);
11311122
printOperands(O, SlotTracker);
11321123
}

llvm/lib/Transforms/Vectorize/VPlanTransforms.cpp

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

13861386
/// Replace recipes with their EVL variants.
13871387
static void transformRecipestoEVLRecipes(VPlan &Plan, VPValue &EVL) {
1388+
VPDominatorTree VPDT;
1389+
VPDT.recalculate(Plan);
13881390
DenseSet<VPRecipeBase *> ToRemove;
13891391

13901392
ReversePostOrderTraversal<VPBlockDeepTraversalWrapper<VPBlockBase *>> RPOT(
13911393
Plan.getEntry());
13921394
DenseSet<VPValue *> HeaderMasks = collectAllHeaderMasks(Plan);
13931395
for (VPBasicBlock *VPBB :
13941396
reverse(VPBlockUtils::blocksOnly<VPBasicBlock>(RPOT))) {
1395-
// The recipes in the block are processed in reverse order, to catch chains
1396-
// of dead recipes.
13971397
for (VPRecipeBase &R : make_early_inc_range(reverse(*VPBB))) {
1398+
if (!properlyDominates(EVL.getDefiningRecipe(), &R, VPDT))
1399+
continue;
1400+
13981401
TypeSwitch<VPRecipeBase *>(&R)
13991402
.Case<VPWidenLoadRecipe>([&](VPWidenLoadRecipe *L) {
14001403
VPValue *NewMask =
@@ -1416,7 +1419,7 @@ static void transformRecipestoEVLRecipes(VPlan &Plan, VPValue &EVL) {
14161419
if (!Instruction::isBinaryOp(Opcode) &&
14171420
!Instruction::isUnaryOp(Opcode))
14181421
return;
1419-
auto *N = VPWidenEVLRecipe::create(W, EVL);
1422+
auto *N = new VPWidenEVLRecipe(W, EVL);
14201423
N->insertBefore(W);
14211424
W->replaceAllUsesWith(N);
14221425
ToRemove.insert(W);
@@ -1431,8 +1434,6 @@ static void transformRecipestoEVLRecipes(VPlan &Plan, VPValue &EVL) {
14311434
recursivelyDeleteDeadRecipes(HeaderMask);
14321435
}
14331436

1434-
1435-
14361437
/// Add a VPEVLBasedIVPHIRecipe and related recipes to \p Plan and
14371438
/// replaces all uses except the canonical IV increment of
14381439
/// 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)