Skip to content

Commit 7c2493d

Browse files
committed
Change the way to convert reverse operation When EVL lowering.
1 parent 715a55f commit 7c2493d

File tree

2 files changed

+61
-28
lines changed

2 files changed

+61
-28
lines changed

llvm/lib/Transforms/Vectorize/VPlanPatternMatch.h

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -245,7 +245,8 @@ struct Recipe_match {
245245
if constexpr (std::is_same<RecipeTy, VPScalarIVStepsRecipe>::value ||
246246
std::is_same<RecipeTy, VPCanonicalIVPHIRecipe>::value ||
247247
std::is_same<RecipeTy, VPDerivedIVRecipe>::value ||
248-
std::is_same<RecipeTy, VPWidenGEPRecipe>::value)
248+
std::is_same<RecipeTy, VPWidenGEPRecipe>::value ||
249+
std::is_same<RecipeTy, VPVectorEndPointerRecipe>::value)
249250
return DefR;
250251
else
251252
return DefR && DefR->getOpcode() == Opcode;
@@ -550,6 +551,16 @@ m_LogicalOr(const Op0_t &Op0, const Op1_t &Op1) {
550551
return m_Select(Op0, m_True(), Op1);
551552
}
552553

554+
template <typename Op0_t, typename Op1_t>
555+
using VPVectorEndPointer_match =
556+
Recipe_match<std::tuple<Op0_t, Op1_t>, 0, false, VPVectorEndPointerRecipe>;
557+
558+
template <typename Op0_t, typename Op1_t>
559+
inline VPVectorEndPointer_match<Op0_t, Op1_t>
560+
m_VectorEndPointer(const Op0_t &Op0, const Op1_t &Op1) {
561+
return VPVectorEndPointer_match<Op0_t, Op1_t>({Op0, Op1});
562+
}
563+
553564
template <typename Op0_t, typename Op1_t, typename Op2_t>
554565
using VPScalarIVSteps_match = Recipe_match<std::tuple<Op0_t, Op1_t, Op2_t>, 0,
555566
false, VPScalarIVStepsRecipe>;

llvm/lib/Transforms/Vectorize/VPlanTransforms.cpp

Lines changed: 49 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -2151,6 +2151,22 @@ void VPlanTransforms::addActiveLaneMask(
21512151
HeaderMask->eraseFromParent();
21522152
}
21532153

2154+
/// If \p R is a VPInstruction::Reverse, return a VPWidenIntrinsicRecipe
2155+
/// for the vp.reverse intrinsic using \p EVL. Returns nullptr otherwise.
2156+
static VPWidenIntrinsicRecipe *
2157+
getEVLReverse(VPRecipeBase &R, VPTypeAnalysis &TypeInfo, VPValue &EVL) {
2158+
VPValue *ReversedVal;
2159+
if (!match(&R,
2160+
m_VPInstruction<VPInstruction::Reverse>(m_VPValue(ReversedVal))))
2161+
return nullptr;
2162+
2163+
auto *Reverse = cast<VPInstruction>(&R);
2164+
VPlan *Plan = Reverse->getParent()->getPlan();
2165+
return new VPWidenIntrinsicRecipe(
2166+
Intrinsic::experimental_vp_reverse, {ReversedVal, Plan->getTrue(), &EVL},
2167+
TypeInfo.inferScalarType(Reverse), Reverse->getDebugLoc());
2168+
}
2169+
21542170
/// Try to optimize a \p CurRecipe masked by \p HeaderMask to a corresponding
21552171
/// EVL-based recipe without the header mask. Returns nullptr if no EVL-based
21562172
/// recipe could be created.
@@ -2227,32 +2243,6 @@ static VPRecipeBase *optimizeMaskToEVL(VPValue *HeaderMask,
22272243
.Default([&](VPRecipeBase *R) { return nullptr; });
22282244
}
22292245

2230-
static void convertToEVLReverse(VPlan &Plan, VPTypeAnalysis &TypeInfo,
2231-
VPValue &AllOneMask, VPValue &EVL) {
2232-
SmallVector<VPRecipeBase *> ToRemove;
2233-
2234-
for (VPBasicBlock *VPBB : VPBlockUtils::blocksOnly<VPBasicBlock>(
2235-
vp_depth_first_shallow(Plan.getVectorLoopRegion()->getEntry()))) {
2236-
for (VPRecipeBase &R : make_early_inc_range(reverse(*VPBB))) {
2237-
auto *VPI = dyn_cast<VPInstruction>(&R);
2238-
if (!VPI || VPI->getOpcode() != VPInstruction::Reverse)
2239-
continue;
2240-
2241-
SmallVector<VPValue *> Ops(VPI->operands());
2242-
Ops.append({&AllOneMask, &EVL});
2243-
auto *NewReverse = new VPWidenIntrinsicRecipe(
2244-
Intrinsic::experimental_vp_reverse, Ops,
2245-
TypeInfo.inferScalarType(VPI), VPI->getDebugLoc());
2246-
NewReverse->insertBefore(VPI);
2247-
VPI->replaceAllUsesWith(NewReverse);
2248-
ToRemove.push_back(VPI);
2249-
}
2250-
}
2251-
2252-
for (VPRecipeBase *R : ToRemove)
2253-
R->eraseFromParent();
2254-
}
2255-
22562246
/// Replace recipes with their EVL variants.
22572247
static void transformRecipestoEVLRecipes(VPlan &Plan, VPValue &EVL) {
22582248
VPTypeAnalysis TypeInfo(Plan);
@@ -2365,8 +2355,40 @@ static void transformRecipestoEVLRecipes(VPlan &Plan, VPValue &EVL) {
23652355
CurVPV->replaceAllUsesWith(EVLRecipe->getVPSingleValue());
23662356
}
23672357
ToErase.push_back(CurRecipe);
2358+
2359+
// Convert general reverse operations on loaded values and stored values
2360+
// into vp.reverse, when the VPVectorEndPointerRecipe adjusting the access
2361+
// address uses EVL instead of VF.
2362+
// TODO: Extend conversion along the def-use/use-def chain, as reverse
2363+
// operations may be eliminated or moved in the future.
2364+
if (auto *MemR = dyn_cast<VPWidenMemoryRecipe>(EVLRecipe);
2365+
MemR && match(MemR->getAddr(),
2366+
m_VectorEndPointer(m_VPValue(), m_Specific(&EVL)))) {
2367+
assert(MemR->isReverse() &&
2368+
"Only reverse access uses VPVectorEndPointerRecipe as address");
2369+
VPRecipeBase *Candidate = nullptr;
2370+
if (auto *LoadR = dyn_cast<VPWidenLoadEVLRecipe>(MemR)) {
2371+
assert(LoadR->getNumUsers() == 1 &&
2372+
"Unexpected user number of reverse load");
2373+
Candidate = cast<VPRecipeBase>(*LoadR->user_begin());
2374+
} else if (auto *StoreR = dyn_cast<VPWidenStoreEVLRecipe>(MemR)) {
2375+
VPValue *StoredVal = StoreR->getStoredValue();
2376+
// Skip if the stored value is not defined in the loop region.
2377+
if (StoredVal->isDefinedOutsideLoopRegions())
2378+
continue;
2379+
Candidate = StoredVal->getDefiningRecipe();
2380+
}
2381+
assert(Candidate && "Must have one reverse operation for reverse access");
2382+
2383+
VPWidenIntrinsicRecipe *NewReverse =
2384+
getEVLReverse(*Candidate, TypeInfo, EVL);
2385+
assert(NewReverse &&
2386+
"Unable to get an EVL reverse when tail folding by EVL");
2387+
NewReverse->insertBefore(Candidate);
2388+
cast<VPInstruction>(Candidate)->replaceAllUsesWith(NewReverse);
2389+
ToErase.push_back(Candidate);
2390+
}
23682391
}
2369-
convertToEVLReverse(Plan, TypeInfo, *AllOneMask, EVL);
23702392
// Remove dead EVL mask.
23712393
if (EVLMask->getNumUsers() == 0)
23722394
ToErase.push_back(EVLMask->getDefiningRecipe());

0 commit comments

Comments
 (0)