Skip to content

Commit cabf643

Browse files
authored
[VPlan] EVL transform VPVectorEndPointerRecipe alongisde load/store recipes. NFC (#152542)
This is the first step in untangling the variable step transform and header mask optimizations as described in #152541. Currently we replace all VF users globally in the plan, including VPVectorEndPointerRecipe. However this leaves reversed loads and stores in an incorrect state until they are adjusted in optimizeMaskToEVL. This moves the VPVectorEndPointerRecipe transform so that it is updated in lockstep with the actual load/store recipe. One thought that crossed my mind was that VPInterleaveRecipe could also use VPVectorEndPointerRecipe, in which case we would have also been computing the wrong address because we don't transform it to an EVL recipe which accounts for the reversed address.
1 parent b5e5794 commit cabf643

File tree

2 files changed

+36
-10
lines changed

2 files changed

+36
-10
lines changed

llvm/lib/Transforms/Vectorize/VPlan.h

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -3111,10 +3111,11 @@ struct LLVM_ABI_FOR_TEST VPWidenLoadRecipe final : public VPWidenMemoryRecipe,
31113111
/// using the address to load from, the explicit vector length and an optional
31123112
/// mask.
31133113
struct VPWidenLoadEVLRecipe final : public VPWidenMemoryRecipe, public VPValue {
3114-
VPWidenLoadEVLRecipe(VPWidenLoadRecipe &L, VPValue &EVL, VPValue *Mask)
3114+
VPWidenLoadEVLRecipe(VPWidenLoadRecipe &L, VPValue *Addr, VPValue &EVL,
3115+
VPValue *Mask)
31153116
: VPWidenMemoryRecipe(VPDef::VPWidenLoadEVLSC, L.getIngredient(),
3116-
{L.getAddr(), &EVL}, L.isConsecutive(),
3117-
L.isReverse(), L, L.getDebugLoc()),
3117+
{Addr, &EVL}, L.isConsecutive(), L.isReverse(), L,
3118+
L.getDebugLoc()),
31183119
VPValue(this, &getIngredient()) {
31193120
setMask(Mask);
31203121
}
@@ -3192,11 +3193,11 @@ struct LLVM_ABI_FOR_TEST VPWidenStoreRecipe final : public VPWidenMemoryRecipe {
31923193
/// using the value to store, the address to store to, the explicit vector
31933194
/// length and an optional mask.
31943195
struct VPWidenStoreEVLRecipe final : public VPWidenMemoryRecipe {
3195-
VPWidenStoreEVLRecipe(VPWidenStoreRecipe &S, VPValue &EVL, VPValue *Mask)
3196+
VPWidenStoreEVLRecipe(VPWidenStoreRecipe &S, VPValue *Addr, VPValue &EVL,
3197+
VPValue *Mask)
31963198
: VPWidenMemoryRecipe(VPDef::VPWidenStoreEVLSC, S.getIngredient(),
3197-
{S.getAddr(), S.getStoredValue(), &EVL},
3198-
S.isConsecutive(), S.isReverse(), S,
3199-
S.getDebugLoc()) {
3199+
{Addr, S.getStoredValue(), &EVL}, S.isConsecutive(),
3200+
S.isReverse(), S, S.getDebugLoc()) {
32003201
setMask(Mask);
32013202
}
32023203

llvm/lib/Transforms/Vectorize/VPlanTransforms.cpp

Lines changed: 28 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2138,6 +2138,8 @@ static VPRecipeBase *optimizeMaskToEVL(VPValue *HeaderMask,
21382138
VPRecipeBase &CurRecipe,
21392139
VPTypeAnalysis &TypeInfo,
21402140
VPValue &AllOneMask, VPValue &EVL) {
2141+
// FIXME: Don't transform recipes to EVL recipes if they're not masked by the
2142+
// header mask.
21412143
auto GetNewMask = [&](VPValue *OrigMask) -> VPValue * {
21422144
assert(OrigMask && "Unmasked recipe when folding tail");
21432145
// HeaderMask will be handled using EVL.
@@ -2147,14 +2149,35 @@ static VPRecipeBase *optimizeMaskToEVL(VPValue *HeaderMask,
21472149
return HeaderMask == OrigMask ? nullptr : OrigMask;
21482150
};
21492151

2152+
/// Adjust any end pointers so that they point to the end of EVL lanes not VF.
2153+
auto GetNewAddr = [&CurRecipe, &EVL](VPValue *Addr) -> VPValue * {
2154+
auto *EndPtr = dyn_cast<VPVectorEndPointerRecipe>(Addr);
2155+
if (!EndPtr)
2156+
return Addr;
2157+
assert(EndPtr->getOperand(1) == &EndPtr->getParent()->getPlan()->getVF() &&
2158+
"VPVectorEndPointerRecipe with non-VF VF operand?");
2159+
assert(
2160+
all_of(EndPtr->users(),
2161+
[](VPUser *U) {
2162+
return cast<VPWidenMemoryRecipe>(U)->isReverse();
2163+
}) &&
2164+
"VPVectorEndPointRecipe not used by reversed widened memory recipe?");
2165+
VPVectorEndPointerRecipe *EVLAddr = EndPtr->clone();
2166+
EVLAddr->insertBefore(&CurRecipe);
2167+
EVLAddr->setOperand(1, &EVL);
2168+
return EVLAddr;
2169+
};
2170+
21502171
return TypeSwitch<VPRecipeBase *, VPRecipeBase *>(&CurRecipe)
21512172
.Case<VPWidenLoadRecipe>([&](VPWidenLoadRecipe *L) {
21522173
VPValue *NewMask = GetNewMask(L->getMask());
2153-
return new VPWidenLoadEVLRecipe(*L, EVL, NewMask);
2174+
VPValue *NewAddr = GetNewAddr(L->getAddr());
2175+
return new VPWidenLoadEVLRecipe(*L, NewAddr, EVL, NewMask);
21542176
})
21552177
.Case<VPWidenStoreRecipe>([&](VPWidenStoreRecipe *S) {
21562178
VPValue *NewMask = GetNewMask(S->getMask());
2157-
return new VPWidenStoreEVLRecipe(*S, EVL, NewMask);
2179+
VPValue *NewAddr = GetNewAddr(S->getAddr());
2180+
return new VPWidenStoreEVLRecipe(*S, NewAddr, EVL, NewMask);
21582181
})
21592182
.Case<VPReductionRecipe>([&](VPReductionRecipe *Red) {
21602183
VPValue *NewMask = GetNewMask(Red->getCondOp());
@@ -2189,7 +2212,9 @@ static void transformRecipestoEVLRecipes(VPlan &Plan, VPValue &EVL) {
21892212
IsaPred<VPVectorEndPointerRecipe, VPScalarIVStepsRecipe,
21902213
VPWidenIntOrFpInductionRecipe>) &&
21912214
"User of VF that we can't transform to EVL.");
2192-
Plan.getVF().replaceAllUsesWith(&EVL);
2215+
Plan.getVF().replaceUsesWithIf(&EVL, [](VPUser &U, unsigned Idx) {
2216+
return isa<VPWidenIntOrFpInductionRecipe, VPScalarIVStepsRecipe>(U);
2217+
});
21932218

21942219
assert(all_of(Plan.getVFxUF().users(),
21952220
[&Plan](VPUser *U) {

0 commit comments

Comments
 (0)