@@ -151,59 +151,65 @@ static bool cannotHoistOrSinkRecipe(const VPRecipeBase &R) {
151151
152152static bool sinkScalarOperands (VPlan &Plan) {
153153 auto Iter = vp_depth_first_deep (Plan.getEntry ());
154+ bool ScalarVFOnly = Plan.hasScalarVFOnly ();
154155 bool Changed = false ;
156+
157+ auto IsValidSinkCandidate = [ScalarVFOnly](VPBasicBlock *SinkTo,
158+ VPSingleDefRecipe *Candidate) {
159+ // We only know how to duplicate VPReplicateRecipes and
160+ // VPScalarIVStepsRecipes for now.
161+ if (!isa<VPReplicateRecipe, VPScalarIVStepsRecipe>(Candidate))
162+ return false ;
163+
164+ if (Candidate->getParent () == SinkTo || Candidate->mayHaveSideEffects () ||
165+ Candidate->mayReadOrWriteMemory ())
166+ return false ;
167+
168+ if (auto *RepR = dyn_cast<VPReplicateRecipe>(Candidate))
169+ if (!ScalarVFOnly && RepR->isSingleScalar ())
170+ return false ;
171+
172+ return true ;
173+ };
174+
155175 // First, collect the operands of all recipes in replicate blocks as seeds for
156176 // sinking.
157177 SetVector<std::pair<VPBasicBlock *, VPSingleDefRecipe *>> WorkList;
158178 for (VPRegionBlock *VPR : VPBlockUtils::blocksOnly<VPRegionBlock>(Iter)) {
159179 VPBasicBlock *EntryVPBB = VPR->getEntryBasicBlock ();
160180 if (!VPR->isReplicator () || EntryVPBB->getSuccessors ().size () != 2 )
161181 continue ;
162- VPBasicBlock *VPBB = dyn_cast <VPBasicBlock>(EntryVPBB->getSuccessors ()[ 0 ] );
163- if (!VPBB || VPBB->getSingleSuccessor () != VPR->getExitingBasicBlock ())
182+ VPBasicBlock *VPBB = cast <VPBasicBlock>(EntryVPBB->getSuccessors (). front () );
183+ if (VPBB->getSingleSuccessor () != VPR->getExitingBasicBlock ())
164184 continue ;
165185 for (auto &Recipe : *VPBB) {
166- for (VPValue *Op : Recipe.operands ())
186+ for (VPValue *Op : Recipe.operands ()) {
167187 if (auto *Def =
168188 dyn_cast_or_null<VPSingleDefRecipe>(Op->getDefiningRecipe ()))
169- WorkList.insert ({VPBB, Def});
189+ if (IsValidSinkCandidate (VPBB, Def))
190+ WorkList.insert ({VPBB, Def});
191+ }
170192 }
171193 }
172194
173- bool ScalarVFOnly = Plan.hasScalarVFOnly ();
174195 // Try to sink each replicate or scalar IV steps recipe in the worklist.
175196 for (unsigned I = 0 ; I != WorkList.size (); ++I) {
176197 VPBasicBlock *SinkTo;
177198 VPSingleDefRecipe *SinkCandidate;
178199 std::tie (SinkTo, SinkCandidate) = WorkList[I];
179- if (SinkCandidate->getParent () == SinkTo ||
180- SinkCandidate->mayHaveSideEffects () ||
181- SinkCandidate->mayReadOrWriteMemory ())
182- continue ;
183- if (auto *RepR = dyn_cast<VPReplicateRecipe>(SinkCandidate)) {
184- if (!ScalarVFOnly && RepR->isSingleScalar ())
185- continue ;
186- } else if (!isa<VPScalarIVStepsRecipe>(SinkCandidate))
187- continue ;
188200
189- bool NeedsDuplicating = false ;
190201 // All recipe users of the sink candidate must be in the same block SinkTo
191- // or all users outside of SinkTo must be uniform-after-vectorization (
192- // i.e., only first lane is used) . In the latter case, we need to duplicate
193- // SinkCandidate.
194- auto CanSinkWithUser = [SinkTo, &NeedsDuplicating,
195- SinkCandidate](VPUser *U) {
196- auto *UI = cast<VPRecipeBase>(U);
197- if (UI->getParent () == SinkTo)
198- return true ;
199- NeedsDuplicating = UI->onlyFirstLaneUsed (SinkCandidate);
200- // We only know how to duplicate VPReplicateRecipes and
201- // VPScalarIVStepsRecipes for now.
202- return NeedsDuplicating &&
203- isa<VPReplicateRecipe, VPScalarIVStepsRecipe>(SinkCandidate);
204- };
205- if (!all_of (SinkCandidate->users (), CanSinkWithUser))
202+ // or all users outside of SinkTo must have only their first lane used. In
203+ // the latter case, we need to duplicate SinkCandidate.
204+ auto UsersOutsideSinkTo =
205+ make_filter_range (SinkCandidate->users (), [SinkTo](VPUser *U) {
206+ return cast<VPRecipeBase>(U)->getParent () != SinkTo;
207+ });
208+ if (any_of (UsersOutsideSinkTo, [SinkCandidate](VPUser *U) {
209+ return !U->onlyFirstLaneUsed (SinkCandidate);
210+ }))
206211 continue ;
212+ bool NeedsDuplicating = !UsersOutsideSinkTo.empty ();
207213
208214 if (NeedsDuplicating) {
209215 if (ScalarVFOnly)
@@ -230,7 +236,8 @@ static bool sinkScalarOperands(VPlan &Plan) {
230236 for (VPValue *Op : SinkCandidate->operands ())
231237 if (auto *Def =
232238 dyn_cast_or_null<VPSingleDefRecipe>(Op->getDefiningRecipe ()))
233- WorkList.insert ({SinkTo, Def});
239+ if (IsValidSinkCandidate (SinkTo, Def))
240+ WorkList.insert ({SinkTo, Def});
234241 Changed = true ;
235242 }
236243 return Changed;
0 commit comments