@@ -2766,6 +2766,22 @@ static inline RemoveMask_match<Op0_t, Op1_t> m_RemoveMask(const Op0_t &In,
27662766 return RemoveMask_match<Op0_t, Op1_t>(In, Out);
27672767}
27682768
2769+ // / If \p R is a VPInstruction::Reverse, return a VPWidenIntrinsicRecipe
2770+ // / for the vp.reverse intrinsic using \p EVL. Returns nullptr otherwise.
2771+ static VPWidenIntrinsicRecipe *
2772+ getEVLReverse (VPRecipeBase &R, VPTypeAnalysis &TypeInfo, VPValue &EVL) {
2773+ VPValue *ReversedVal;
2774+ if (!match (&R,
2775+ m_VPInstruction<VPInstruction::Reverse>(m_VPValue (ReversedVal))))
2776+ return nullptr ;
2777+
2778+ auto *Reverse = cast<VPInstruction>(&R);
2779+ VPlan *Plan = Reverse->getParent ()->getPlan ();
2780+ return new VPWidenIntrinsicRecipe (
2781+ Intrinsic::experimental_vp_reverse, {ReversedVal, Plan->getTrue (), &EVL},
2782+ TypeInfo.inferScalarType (Reverse), {}, {}, Reverse->getDebugLoc ());
2783+ }
2784+
27692785// / Try to optimize a \p CurRecipe masked by \p HeaderMask to a corresponding
27702786// / EVL-based recipe without the header mask. Returns nullptr if no EVL-based
27712787// / recipe could be created.
@@ -2808,31 +2824,12 @@ static VPRecipeBase *optimizeMaskToEVL(VPValue *HeaderMask,
28082824 return new VPWidenStoreEVLRecipe (cast<VPWidenStoreRecipe>(CurRecipe), Addr,
28092825 EVL, Mask);
28102826
2811- VPValue *StoredVal;
2812- if (match (&CurRecipe, m_MaskedStore (m_VPValue (EndPtr), m_VPValue (StoredVal),
2827+ if (match (&CurRecipe, m_MaskedStore (m_VPValue (EndPtr), m_VPValue (),
28132828 m_RemoveMask (HeaderMask, Mask))) &&
28142829 match (EndPtr, m_VecEndPtr (m_VPValue (Addr), m_Specific (&Plan->getVF ()))) &&
2815- cast<VPWidenStoreRecipe>(CurRecipe).isReverse ()) {
2816- auto *StoreR = cast<VPWidenStoreRecipe>(&CurRecipe);
2817- // Convert general reverse operations on stored value into vp.reverse.
2818- // Skip if the stored value is not defined in the loop region.
2819- if (!StoredVal->isDefinedOutsideLoopRegions ()) {
2820- VPValue *ReversedVal;
2821- bool IsReverse = match (StoredVal, m_VPInstruction<VPInstruction::Reverse>(
2822- m_VPValue (ReversedVal)));
2823- assert (IsReverse && " The stored value of reverse store must be defined "
2824- " by a reverse operation" );
2825- auto *Reverse = cast<VPInstruction>(StoredVal);
2826- auto *NewReverse = new VPWidenIntrinsicRecipe (
2827- Intrinsic::experimental_vp_reverse,
2828- {ReversedVal, Plan->getTrue (), &EVL},
2829- TypeInfo.inferScalarType (Reverse), {}, {}, Reverse->getDebugLoc ());
2830- NewReverse->insertBefore (Reverse);
2831- return new VPWidenStoreEVLRecipe (*StoreR, AdjustEndPtr (EndPtr),
2832- NewReverse, EVL, Mask);
2833- }
2834- return new VPWidenStoreEVLRecipe (*StoreR, AdjustEndPtr (EndPtr), EVL, Mask);
2835- }
2830+ cast<VPWidenStoreRecipe>(CurRecipe).isReverse ())
2831+ return new VPWidenStoreEVLRecipe (cast<VPWidenStoreRecipe>(CurRecipe),
2832+ AdjustEndPtr (EndPtr), EVL, Mask);
28362833
28372834 if (auto *Rdx = dyn_cast<VPReductionRecipe>(&CurRecipe))
28382835 if (Rdx->isConditional () &&
@@ -2983,32 +2980,41 @@ static void transformRecipestoEVLRecipes(VPlan &Plan, VPValue &EVL) {
29832980 }
29842981 ToErase.push_back (CurRecipe);
29852982
2986- // Convert general reverse operations on loaded results into vp.reverse,
2987- // when the VPVectorEndPointerRecipe adjusting the access address uses EVL
2988- // instead of VF.
2989- if (auto *LoadR = dyn_cast<VPWidenLoadEVLRecipe>(EVLRecipe)) {
2990- if (!match (LoadR->getAddr (), m_VecEndPtr (m_VPValue (), m_Specific (&EVL))))
2983+ // Convert general reverse operations on loaded values and stored values
2984+ // into vp.reverse, when the VPVectorEndPointerRecipe adjusting the access
2985+ // address uses EVL instead of VF.
2986+ // TODO: Extend conversion along the def-use/use-def chain, as reverse
2987+ // operations may be eliminated or moved in the future.
2988+ if (auto *MemR = dyn_cast<VPWidenMemoryRecipe>(EVLRecipe)) {
2989+ if (!match (MemR->getAddr (), m_VecEndPtr (m_VPValue (), m_Specific (&EVL))))
29912990 continue ;
2992- assert (LoadR ->isReverse () &&
2991+ assert (MemR ->isReverse () &&
29932992 " Only reverse access uses VPVectorEndPointerRecipe as address" );
2994- // TODO: Extend conversion along the use-def chain, as reverse operations
2995- // may be eliminated or sunk in the future.
2996- assert (LoadR->getNumUsers () == 1 &&
2997- " Unexpected user number of reverse load" );
2998- auto *UserR = cast<VPRecipeBase>(*LoadR->user_begin ());
2999- VPValue *ReversedVal;
3000- bool IsReverse = match (UserR, m_VPInstruction<VPInstruction::Reverse>(
3001- m_VPValue (ReversedVal)));
3002- assert (IsReverse && " The defined value of reverse load must be used by a "
3003- " reverse operation" );
3004- auto *Reverse = cast<VPInstruction>(UserR);
3005- auto *NewReverse = new VPWidenIntrinsicRecipe (
3006- Intrinsic::experimental_vp_reverse,
3007- {ReversedVal, Plan.getTrue (), &EVL},
3008- TypeInfo.inferScalarType (Reverse), {}, {}, Reverse->getDebugLoc ());
3009- NewReverse->insertBefore (Reverse);
3010- Reverse->replaceAllUsesWith (NewReverse);
3011- ToErase.push_back (Reverse);
2993+
2994+ VPRecipeBase *Candidate = nullptr ;
2995+ if (auto *LoadR = dyn_cast<VPWidenLoadEVLRecipe>(MemR)) {
2996+ assert (LoadR->getNumUsers () == 1 &&
2997+ " Unexpected user number of reverse load" );
2998+ Candidate = cast<VPRecipeBase>(*LoadR->user_begin ());
2999+ } else if (auto *StoreR = dyn_cast<VPWidenStoreEVLRecipe>(MemR)) {
3000+ VPValue *StoredVal = StoreR->getStoredValue ();
3001+ // Skip if the stored value is not defined in the loop region.
3002+ if (StoredVal->isDefinedOutsideLoopRegions ())
3003+ continue ;
3004+ Candidate = StoredVal->getDefiningRecipe ();
3005+ }
3006+ assert (Candidate && " Must have one reverse operation for reverse access" );
3007+
3008+ if (match (Candidate, m_Intrinsic<Intrinsic::experimental_vp_reverse>()))
3009+ continue ;
3010+
3011+ VPWidenIntrinsicRecipe *NewReverse =
3012+ getEVLReverse (*Candidate, TypeInfo, EVL);
3013+ assert (NewReverse &&
3014+ " Unable to get an EVL reverse when tail folding by EVL" );
3015+ NewReverse->insertBefore (Candidate);
3016+ cast<VPInstruction>(Candidate)->replaceAllUsesWith (NewReverse);
3017+ ToErase.push_back (Candidate);
30123018 }
30133019 }
30143020 // Remove dead EVL mask.
0 commit comments