Skip to content

Commit 7ed94d7

Browse files
committed
Split the appoarch that transforms the reverse to vp.reverse for loaded result and stored value
1 parent b7591e9 commit 7ed94d7

File tree

2 files changed

+56
-53
lines changed

2 files changed

+56
-53
lines changed

llvm/lib/Transforms/Vectorize/VPlan.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3492,6 +3492,15 @@ struct VPWidenStoreEVLRecipe final : public VPWidenMemoryRecipe {
34923492
setMask(Mask);
34933493
}
34943494

3495+
VPWidenStoreEVLRecipe(VPWidenStoreRecipe &S, VPValue *Addr,
3496+
VPValue *StoredVal, VPValue &EVL, VPValue *Mask)
3497+
: VPWidenMemoryRecipe(VPDef::VPWidenStoreEVLSC, S.getIngredient(),
3498+
{Addr, StoredVal, &EVL}, S.isConsecutive(),
3499+
S.isReverse(), S, S.getDebugLoc()) {
3500+
assert(isReverse() && "Only reverse access need to set new stored value");
3501+
setMask(Mask);
3502+
}
3503+
34953504
VP_CLASSOF_IMPL(VPDef::VPWidenStoreEVLSC)
34963505

34973506
/// Return the address accessed by this recipe.

llvm/lib/Transforms/Vectorize/VPlanTransforms.cpp

Lines changed: 47 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -2630,22 +2630,6 @@ static inline RemoveMask_match<Op0_t, Op1_t> m_RemoveMask(const Op0_t &In,
26302630
return RemoveMask_match<Op0_t, Op1_t>(In, Out);
26312631
}
26322632

2633-
/// If \p R is a VPInstruction::Reverse, return a VPWidenIntrinsicRecipe
2634-
/// for the vp.reverse intrinsic using \p EVL. Returns nullptr otherwise.
2635-
static VPWidenIntrinsicRecipe *
2636-
getEVLReverse(VPRecipeBase &R, VPTypeAnalysis &TypeInfo, VPValue &EVL) {
2637-
VPValue *ReversedVal;
2638-
if (!match(&R,
2639-
m_VPInstruction<VPInstruction::Reverse>(m_VPValue(ReversedVal))))
2640-
return nullptr;
2641-
2642-
auto *Reverse = cast<VPInstruction>(&R);
2643-
VPlan *Plan = Reverse->getParent()->getPlan();
2644-
return new VPWidenIntrinsicRecipe(
2645-
Intrinsic::experimental_vp_reverse, {ReversedVal, Plan->getTrue(), &EVL},
2646-
TypeInfo.inferScalarType(Reverse), {}, {}, Reverse->getDebugLoc());
2647-
}
2648-
26492633
/// Try to optimize a \p CurRecipe masked by \p HeaderMask to a corresponding
26502634
/// EVL-based recipe without the header mask. Returns nullptr if no EVL-based
26512635
/// recipe could be created.
@@ -2687,12 +2671,31 @@ static VPRecipeBase *optimizeMaskToEVL(VPValue *HeaderMask,
26872671
return new VPWidenStoreEVLRecipe(cast<VPWidenStoreRecipe>(CurRecipe), Addr,
26882672
EVL, Mask);
26892673

2690-
if (match(&CurRecipe, m_MaskedStore(m_VPValue(EndPtr), m_VPValue(),
2674+
VPValue *StoredVal;
2675+
if (match(&CurRecipe, m_MaskedStore(m_VPValue(EndPtr), m_VPValue(StoredVal),
26912676
m_RemoveMask(HeaderMask, Mask))) &&
26922677
match(EndPtr, m_VecEndPtr(m_VPValue(Addr), m_Specific(&Plan->getVF()))) &&
2693-
cast<VPWidenStoreRecipe>(CurRecipe).isReverse())
2694-
return new VPWidenStoreEVLRecipe(cast<VPWidenStoreRecipe>(CurRecipe),
2695-
AdjustEndPtr(EndPtr), EVL, Mask);
2678+
cast<VPWidenStoreRecipe>(CurRecipe).isReverse()) {
2679+
auto *StoreR = cast<VPWidenStoreRecipe>(&CurRecipe);
2680+
// Convert general reverse operations on stored value into vp.reverse.
2681+
// Skip if the stored value is not defined in the loop region.
2682+
if (!StoredVal->isDefinedOutsideLoopRegions()) {
2683+
VPValue *ReversedVal;
2684+
bool IsReverse = match(StoredVal, m_VPInstruction<VPInstruction::Reverse>(
2685+
m_VPValue(ReversedVal)));
2686+
assert(IsReverse && "The stored value of reverse store must be defined "
2687+
"by a reverse operation");
2688+
auto *Reverse = cast<VPInstruction>(StoredVal);
2689+
auto *NewReverse = new VPWidenIntrinsicRecipe(
2690+
Intrinsic::experimental_vp_reverse,
2691+
{ReversedVal, Plan->getTrue(), &EVL},
2692+
TypeInfo.inferScalarType(Reverse), {}, {}, Reverse->getDebugLoc());
2693+
NewReverse->insertBefore(Reverse);
2694+
return new VPWidenStoreEVLRecipe(*StoreR, AdjustEndPtr(EndPtr),
2695+
NewReverse, EVL, Mask);
2696+
}
2697+
return new VPWidenStoreEVLRecipe(*StoreR, AdjustEndPtr(EndPtr), EVL, Mask);
2698+
}
26962699

26972700
if (auto *Rdx = dyn_cast<VPReductionRecipe>(&CurRecipe))
26982701
if (Rdx->isConditional() &&
@@ -2835,41 +2838,32 @@ static void transformRecipestoEVLRecipes(VPlan &Plan, VPValue &EVL) {
28352838
}
28362839
ToErase.push_back(CurRecipe);
28372840

2838-
// Convert general reverse operations on loaded values and stored values
2839-
// into vp.reverse, when the VPVectorEndPointerRecipe adjusting the access
2840-
// address uses EVL instead of VF.
2841-
// TODO: Extend conversion along the def-use/use-def chain, as reverse
2842-
// operations may be eliminated or moved in the future.
2843-
if (auto *MemR = dyn_cast<VPWidenMemoryRecipe>(EVLRecipe)) {
2844-
if (!match(MemR->getAddr(), m_VecEndPtr(m_VPValue(), m_Specific(&EVL))))
2841+
// Convert general reverse operations on loaded results into vp.reverse,
2842+
// when the VPVectorEndPointerRecipe adjusting the access address uses EVL
2843+
// instead of VF.
2844+
if (auto *LoadR = dyn_cast<VPWidenLoadEVLRecipe>(EVLRecipe)) {
2845+
if (!match(LoadR->getAddr(), m_VecEndPtr(m_VPValue(), m_Specific(&EVL))))
28452846
continue;
2846-
assert(MemR->isReverse() &&
2847+
assert(LoadR->isReverse() &&
28472848
"Only reverse access uses VPVectorEndPointerRecipe as address");
2848-
2849-
VPRecipeBase *Candidate = nullptr;
2850-
if (auto *LoadR = dyn_cast<VPWidenLoadEVLRecipe>(MemR)) {
2851-
assert(LoadR->getNumUsers() == 1 &&
2852-
"Unexpected user number of reverse load");
2853-
Candidate = cast<VPRecipeBase>(*LoadR->user_begin());
2854-
} else if (auto *StoreR = dyn_cast<VPWidenStoreEVLRecipe>(MemR)) {
2855-
VPValue *StoredVal = StoreR->getStoredValue();
2856-
// Skip if the stored value is not defined in the loop region.
2857-
if (StoredVal->isDefinedOutsideLoopRegions())
2858-
continue;
2859-
Candidate = StoredVal->getDefiningRecipe();
2860-
}
2861-
assert(Candidate && "Must have one reverse operation for reverse access");
2862-
2863-
if (match(Candidate, m_Intrinsic<Intrinsic::experimental_vp_reverse>()))
2864-
continue;
2865-
2866-
VPWidenIntrinsicRecipe *NewReverse =
2867-
getEVLReverse(*Candidate, TypeInfo, EVL);
2868-
assert(NewReverse &&
2869-
"Unable to get an EVL reverse when tail folding by EVL");
2870-
NewReverse->insertBefore(Candidate);
2871-
cast<VPInstruction>(Candidate)->replaceAllUsesWith(NewReverse);
2872-
ToErase.push_back(Candidate);
2849+
// TODO: Extend conversion along the use-def chain, as reverse operations
2850+
// may be eliminated or sunk in the future.
2851+
assert(LoadR->getNumUsers() == 1 &&
2852+
"Unexpected user number of reverse load");
2853+
auto *UserR = cast<VPRecipeBase>(*LoadR->user_begin());
2854+
VPValue *ReversedVal;
2855+
bool IsReverse = match(UserR, m_VPInstruction<VPInstruction::Reverse>(
2856+
m_VPValue(ReversedVal)));
2857+
assert(IsReverse && "The defined value of reverse load must be used by a "
2858+
"reverse operation");
2859+
auto *Reverse = cast<VPInstruction>(UserR);
2860+
auto *NewReverse = new VPWidenIntrinsicRecipe(
2861+
Intrinsic::experimental_vp_reverse,
2862+
{ReversedVal, Plan.getTrue(), &EVL},
2863+
TypeInfo.inferScalarType(Reverse), {}, {}, Reverse->getDebugLoc());
2864+
NewReverse->insertBefore(Reverse);
2865+
Reverse->replaceAllUsesWith(NewReverse);
2866+
ToErase.push_back(Reverse);
28732867
}
28742868
}
28752869
// Remove dead EVL mask.

0 commit comments

Comments
 (0)