@@ -2630,6 +2630,22 @@ 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+
26332649// / Try to optimize a \p CurRecipe masked by \p HeaderMask to a corresponding
26342650// / EVL-based recipe without the header mask. Returns nullptr if no EVL-based
26352651// / recipe could be created.
@@ -2704,32 +2720,6 @@ static VPRecipeBase *optimizeMaskToEVL(VPValue *HeaderMask,
27042720 return nullptr ;
27052721}
27062722
2707- static void convertToEVLReverse (VPlan &Plan, VPTypeAnalysis &TypeInfo,
2708- VPValue &EVL) {
2709- SmallVector<VPRecipeBase *> ToRemove;
2710-
2711- for (VPBasicBlock *VPBB : VPBlockUtils::blocksOnly<VPBasicBlock>(
2712- vp_depth_first_shallow (Plan.getVectorLoopRegion ()->getEntry ()))) {
2713- for (VPRecipeBase &R : make_early_inc_range (reverse (*VPBB))) {
2714- auto *VPI = dyn_cast<VPInstruction>(&R);
2715- if (!VPI || VPI->getOpcode () != VPInstruction::Reverse)
2716- continue ;
2717-
2718- SmallVector<VPValue *> Ops (VPI->operands ());
2719- Ops.append ({Plan.getTrue (), &EVL});
2720- auto *NewReverse = new VPWidenIntrinsicRecipe (
2721- Intrinsic::experimental_vp_reverse, Ops,
2722- TypeInfo.inferScalarType (VPI), {}, {}, VPI->getDebugLoc ());
2723- NewReverse->insertBefore (VPI);
2724- VPI->replaceAllUsesWith (NewReverse);
2725- ToRemove.push_back (VPI);
2726- }
2727- }
2728-
2729- for (VPRecipeBase *R : ToRemove)
2730- R->eraseFromParent ();
2731- }
2732-
27332723// / Replace recipes with their EVL variants.
27342724static void transformRecipestoEVLRecipes (VPlan &Plan, VPValue &EVL) {
27352725 VPTypeAnalysis TypeInfo (Plan);
@@ -2844,8 +2834,44 @@ static void transformRecipestoEVLRecipes(VPlan &Plan, VPValue &EVL) {
28442834 }
28452835 }
28462836 ToErase.push_back (CurRecipe);
2837+
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))))
2845+ continue ;
2846+ assert (MemR->isReverse () &&
2847+ " 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);
2873+ }
28472874 }
2848- convertToEVLReverse (Plan, TypeInfo, EVL);
28492875 // Remove dead EVL mask.
28502876 if (EVLMask->getNumUsers () == 0 )
28512877 ToErase.push_back (EVLMask->getDefiningRecipe ());
0 commit comments