@@ -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.
22572247static 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