@@ -132,59 +132,65 @@ bool VPlanTransforms::tryToConvertVPInstructionsToVPRecipes(
132132
133133static bool sinkScalarOperands (VPlan &Plan) {
134134 auto Iter = vp_depth_first_deep (Plan.getEntry ());
135+ bool ScalarVFOnly = Plan.hasScalarVFOnly ();
135136 bool Changed = false ;
137+
138+ auto IsValidSinkCandidate = [ScalarVFOnly](VPBasicBlock *SinkTo,
139+ VPSingleDefRecipe *Candidate) {
140+ // We only know how to duplicate VPReplicateRecipes and
141+ // VPScalarIVStepsRecipes for now.
142+ if (!isa<VPReplicateRecipe, VPScalarIVStepsRecipe>(Candidate))
143+ return false ;
144+
145+ if (Candidate->getParent () == SinkTo || Candidate->mayHaveSideEffects () ||
146+ Candidate->mayReadOrWriteMemory ())
147+ return false ;
148+
149+ if (auto *RepR = dyn_cast<VPReplicateRecipe>(Candidate))
150+ if (!ScalarVFOnly && RepR->isSingleScalar ())
151+ return false ;
152+
153+ return true ;
154+ };
155+
136156 // First, collect the operands of all recipes in replicate blocks as seeds for
137157 // sinking.
138158 SetVector<std::pair<VPBasicBlock *, VPSingleDefRecipe *>> WorkList;
139159 for (VPRegionBlock *VPR : VPBlockUtils::blocksOnly<VPRegionBlock>(Iter)) {
140160 VPBasicBlock *EntryVPBB = VPR->getEntryBasicBlock ();
141161 if (!VPR->isReplicator () || EntryVPBB->getSuccessors ().size () != 2 )
142162 continue ;
143- VPBasicBlock *VPBB = dyn_cast <VPBasicBlock>(EntryVPBB->getSuccessors ()[ 0 ] );
144- if (!VPBB || VPBB->getSingleSuccessor () != VPR->getExitingBasicBlock ())
163+ VPBasicBlock *VPBB = cast <VPBasicBlock>(EntryVPBB->getSuccessors (). front () );
164+ if (VPBB->getSingleSuccessor () != VPR->getExitingBasicBlock ())
145165 continue ;
146166 for (auto &Recipe : *VPBB) {
147- for (VPValue *Op : Recipe.operands ())
167+ for (VPValue *Op : Recipe.operands ()) {
148168 if (auto *Def =
149169 dyn_cast_or_null<VPSingleDefRecipe>(Op->getDefiningRecipe ()))
150- WorkList.insert ({VPBB, Def});
170+ if (IsValidSinkCandidate (VPBB, Def))
171+ WorkList.insert ({VPBB, Def});
172+ }
151173 }
152174 }
153175
154- bool ScalarVFOnly = Plan.hasScalarVFOnly ();
155176 // Try to sink each replicate or scalar IV steps recipe in the worklist.
156177 for (unsigned I = 0 ; I != WorkList.size (); ++I) {
157178 VPBasicBlock *SinkTo;
158179 VPSingleDefRecipe *SinkCandidate;
159180 std::tie (SinkTo, SinkCandidate) = WorkList[I];
160- if (SinkCandidate->getParent () == SinkTo ||
161- SinkCandidate->mayHaveSideEffects () ||
162- SinkCandidate->mayReadOrWriteMemory ())
163- continue ;
164- if (auto *RepR = dyn_cast<VPReplicateRecipe>(SinkCandidate)) {
165- if (!ScalarVFOnly && RepR->isSingleScalar ())
166- continue ;
167- } else if (!isa<VPScalarIVStepsRecipe>(SinkCandidate))
168- continue ;
169181
170- bool NeedsDuplicating = false ;
171182 // All recipe users of the sink candidate must be in the same block SinkTo
172- // or all users outside of SinkTo must be uniform-after-vectorization (
173- // i.e., only first lane is used) . In the latter case, we need to duplicate
174- // SinkCandidate.
175- auto CanSinkWithUser = [SinkTo, &NeedsDuplicating,
176- SinkCandidate](VPUser *U) {
177- auto *UI = cast<VPRecipeBase>(U);
178- if (UI->getParent () == SinkTo)
179- return true ;
180- NeedsDuplicating = UI->onlyFirstLaneUsed (SinkCandidate);
181- // We only know how to duplicate VPReplicateRecipes and
182- // VPScalarIVStepsRecipes for now.
183- return NeedsDuplicating &&
184- isa<VPReplicateRecipe, VPScalarIVStepsRecipe>(SinkCandidate);
185- };
186- if (!all_of (SinkCandidate->users (), CanSinkWithUser))
183+ // or all users outside of SinkTo must have only their first lane used. In
184+ // the latter case, we need to duplicate SinkCandidate.
185+ auto UsersOutsideSinkTo =
186+ make_filter_range (SinkCandidate->users (), [SinkTo](VPUser *U) {
187+ return cast<VPRecipeBase>(U)->getParent () != SinkTo;
188+ });
189+ if (any_of (UsersOutsideSinkTo, [SinkCandidate](VPUser *U) {
190+ return !U->onlyFirstLaneUsed (SinkCandidate);
191+ }))
187192 continue ;
193+ bool NeedsDuplicating = !UsersOutsideSinkTo.empty ();
188194
189195 if (NeedsDuplicating) {
190196 if (ScalarVFOnly)
@@ -211,7 +217,8 @@ static bool sinkScalarOperands(VPlan &Plan) {
211217 for (VPValue *Op : SinkCandidate->operands ())
212218 if (auto *Def =
213219 dyn_cast_or_null<VPSingleDefRecipe>(Op->getDefiningRecipe ()))
214- WorkList.insert ({SinkTo, Def});
220+ if (IsValidSinkCandidate (SinkTo, Def))
221+ WorkList.insert ({SinkTo, Def});
215222 Changed = true ;
216223 }
217224 return Changed;
0 commit comments