@@ -2236,7 +2236,14 @@ void VPlanTransforms::materializeBroadcasts(VPlan &Plan) {
22362236 }
22372237}
22382238
2239- static bool supportedLoad (VPWidenRecipe *R0, VPValue *V, unsigned Idx) {
2239+ // / Returns true if \p V used at \p Idx of a wide recipe is defined by a
2240+ // / VPWidenLoadRecipe or VPInterleaveRecipe that can be converted to a narrower
2241+ // / recipe. A VPWidenLoadRecipe can be narrowed to an index independent load if
2242+ // / it feeds all the wide ops at all indices (checked by via the operands of the
2243+ // / wide recipe at lane0, \p R0). A VPInterleaveRecipe can be narrowed to a wide
2244+ // / load, if \p V used at index \p Idx are defined at \p Idx of the interleave
2245+ // / group.
2246+ static bool canNarrowLoad (VPWidenRecipe *R0, VPValue *V, unsigned Idx) {
22402247 auto *DefR = V->getDefiningRecipe ();
22412248 if (!DefR)
22422249 return false ;
@@ -2312,6 +2319,8 @@ void VPlanTransforms::narrowInterleaveGroups(VPlan &Plan, ElementCount VF,
23122319 if (R.mayWriteToMemory () && !InterleaveR)
23132320 return ;
23142321
2322+ // All other ops are allowed, but we reject uses that cannot be converted
2323+ // when checking all allowed consumers (store interleave groups) below.
23152324 if (!InterleaveR)
23162325 continue ;
23172326
@@ -2340,20 +2349,22 @@ void VPlanTransforms::narrowInterleaveGroups(VPlan &Plan, ElementCount VF,
23402349 continue ;
23412350 }
23422351
2343- auto *Lane0 = dyn_cast_or_null<VPWidenRecipe>(
2352+ // Check if all values feeding InterleaveR are matching wide recipes, which
2353+ // operands that can be narrowed.
2354+ auto *WideMember0 = dyn_cast_or_null<VPWidenRecipe>(
23442355 InterleaveR->getStoredValues ()[0 ]->getDefiningRecipe ());
2345- if (!Lane0 )
2356+ if (!WideMember0 )
23462357 return ;
23472358 for (const auto &[I, V] : enumerate(InterleaveR->getStoredValues ())) {
23482359 auto *R = dyn_cast<VPWidenRecipe>(V->getDefiningRecipe ());
2349- if (!R || R->getOpcode () != Lane0->getOpcode () || R->getNumOperands () > 2 )
2360+ if (!R || R->getOpcode () != WideMember0->getOpcode () ||
2361+ R->getNumOperands () > 2 )
23502362 return ;
2351- if (any_of (R->operands (), [Lane0 , Idx = I](VPValue *V) {
2352- return !supportedLoad (Lane0 , V, Idx);
2363+ if (any_of (R->operands (), [WideMember0 , Idx = I](VPValue *V) {
2364+ return !canNarrowLoad (WideMember0 , V, Idx);
23532365 }))
23542366 return ;
23552367 }
2356-
23572368 StoreGroups.push_back (InterleaveR);
23582369 }
23592370
@@ -2386,12 +2397,12 @@ void VPlanTransforms::narrowInterleaveGroups(VPlan &Plan, ElementCount VF,
23862397 // Narrow operation tree rooted at store groups.
23872398 for (auto *StoreGroup : StoreGroups) {
23882399 VPValue *Res = nullptr ;
2389- if (auto *Lane0 = dyn_cast<VPWidenRecipe>(
2400+ if (auto *WideMember0 = dyn_cast<VPWidenRecipe>(
23902401 StoreGroup->getStoredValues ()[0 ]->getDefiningRecipe ())) {
2391- for (unsigned Idx = 0 , E = Lane0 ->getNumOperands (); Idx != E; ++Idx)
2392- Lane0 ->setOperand (
2393- Idx, NarrowOp (Lane0 ->getOperand (Idx)->getDefiningRecipe ()));
2394- Res = Lane0 ;
2402+ for (unsigned Idx = 0 , E = WideMember0 ->getNumOperands (); Idx != E; ++Idx)
2403+ WideMember0 ->setOperand (
2404+ Idx, NarrowOp (WideMember0 ->getOperand (Idx)->getDefiningRecipe ()));
2405+ Res = WideMember0 ;
23952406 } else {
23962407 Res = NarrowOp (StoreGroup->getStoredValues ()[0 ]->getDefiningRecipe ());
23972408 }
0 commit comments