Skip to content

Commit dbae0c2

Browse files
artagnonDebadri Basak
authored andcommitted
[VPlan] Rewrite sinkScalarOperands (NFC) (llvm#151696)
Rewrite sinkScalarOperands in VPlanTransforms for clarity, in preparation for follow-up work to extend it to handle more recipes.
1 parent 032529c commit dbae0c2

File tree

1 file changed

+38
-31
lines changed

1 file changed

+38
-31
lines changed

llvm/lib/Transforms/Vectorize/VPlanTransforms.cpp

Lines changed: 38 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -151,59 +151,65 @@ static bool cannotHoistOrSinkRecipe(const VPRecipeBase &R) {
151151

152152
static 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

Comments
 (0)