This is an archive of the discontinued LLVM Phabricator instance.

[VPlan] Support sinking recipes with uniform users outside sink target.
ClosedPublic

Authored by fhahn on Jun 14 2021, 12:02 PM.

Details

Summary

This is a first step towards addressing the last remaining limitation of
the VPlan version of sinkScalarOperands: the legacy version can
partially sink operands. For example, if a GEP has uniform users outside
the sink target block, then the legacy version will sink all scalar
GEPs, other than the one for lane 0.

This patch works towards addressing this case in the VPlan version by
detecting such cases and duplicating the sink candidate. All users
outside of the sink target will be updated to use the uniform clone.

Note that this highlights an issue with VPValue naming. If we duplicate
a replicate recipe, they will share the same underlying IR value and
both VPValues will have the same name ir<%gep>.

Diff Detail

Event Timeline

fhahn created this revision.Jun 14 2021, 12:02 PM
fhahn requested review of this revision.Jun 14 2021, 12:02 PM
Herald added a project: Restricted Project. · View Herald TranscriptJun 14 2021, 12:02 PM
Herald added a subscriber: vkmr. · View Herald Transcript
Ayal added inline comments.Jun 27 2021, 2:16 PM
llvm/lib/Transforms/Vectorize/VPlanTransforms.cpp
115–116

Would it simplify the processing below if WorkList contains pairs of RepR along with each of its operands, as a first user thereof, saving the search for it, i.e., for SinkTo?

128

dyn_cast U directly to VPReplicateRecipe?

137

Can assert(SinkTo && "...") - SinkCandidate surely has a ReplicateRecipe user, which got it into WorkList. As commented above, this user could be recorded too in WorkList.

146

Check if SinkCandidate == UI->getAddr() instead of IsGEP?

158

Should Clone and SinkCandidate have distinct names, e.g., append ".cloned" to the former somehow?

165

At this point, all users must be recipes; can do a static cast?

fhahn updated this revision to Diff 372232.Sep 13 2021, 6:26 AM
fhahn marked 6 inline comments as done.

Finally address latest comments, thanks!

llvm/lib/Transforms/Vectorize/VPlanTransforms.cpp
128

The way the various IDs are set up, we need a cast from VPUser -> VPRecipeBase and then a cast from VPRecipeBase -> VPReplicateRecipe. It would be possible to add a classof implementation to do so. Not sure if there's a general way to do so for all recipes in a single place.

But this is not directly relevant any longer, because the code is gone in the current version of the patch.

137

Updated to record it in the worklist directly.

158

Unfortunately this is not possible at the moment, because VPValues do not have associated names that can be changed directly. I added a todo.

Ayal added a comment.Sep 14 2021, 12:20 AM

This looks good to me, thanks for following-up! Adding some last, minor comments.

llvm/lib/Transforms/Vectorize/VPlanTransforms.cpp
115–116

Thanks for following-up! This refactoring could potentially be committed separately, as an NFC.

136

Update comment? By 'uniform' we mean 'uniform-after-vectorization', i.e., only first lane is used. (Truly uniforms - all lanes have same value - are filtered above to avoid sinking.) At the moment, we identify such UAV's by looking for the address operands of widened memory recipes.

138

Might be clearer to give this lambda, which checks two things, a meaningful name?

163

Users are captured as their traversal may modify them. Can alternatively use that iterator which tolerates modification.

169

I is already being used above. Rename?

fhahn updated this revision to Diff 372530.Sep 14 2021, 12:15 PM
fhahn marked 5 inline comments as done.

Address latest comments, thanks!

llvm/lib/Transforms/Vectorize/VPlanTransforms.cpp
115–116

Done in 7359450e6a05

136

Thanks, updated the wording.

138

I renamed it to CanSinkWithUser and flipped the return values accordingly. This seems more natural.

163

Unfortunately the underlying storage for users here is SmallVector, which does not tolerate modifications AFAICT.

169

Changed to Idx.

Ayal accepted this revision.Sep 14 2021, 12:52 PM

Ship it!
Does this turn the original sinkScalarOperands to be "all dead", and should therefore be retired?
May be good to point out that this replacement does involve a (slight) functional change, due to the discrepancy in handling lane zero.

This revision is now accepted and ready to land.Sep 14 2021, 12:52 PM
This revision was landed with ongoing or failed builds.Sep 15 2021, 1:24 AM
This revision was automatically updated to reflect the committed changes.
fhahn added a comment.Sep 15 2021, 1:28 AM

Ship it!
Does this turn the original sinkScalarOperands to be "all dead", and should therefore be retired?
May be good to point out that this replacement does involve a (slight) functional change, due to the discrepancy in handling lane zero.

I think there's one more case we need to tackle before: IV's with vector & scalar users. Currently there will be a single 'widen-induction' recipe, which generates the vector & scalar values of the IV, so we cannot sink the scalar part in the VPlan transform yet.

Ayal added a comment.Sep 22 2021, 3:59 AM

Ship it!
Does this turn the original sinkScalarOperands to be "all dead", and should therefore be retired?
May be good to point out that this replacement does involve a (slight) functional change, due to the discrepancy in handling lane zero.

I think there's one more case we need to tackle before: IV's with vector & scalar users. Currently there will be a single 'widen-induction' recipe, which generates the vector & scalar values of the IV, so we cannot sink the scalar part in the VPlan transform yet.

Ah, right. It would be good to follow-up with a patch that splits 'widen-induction' into two independent single-def recipes, thereby allowing to sink one w/o the other, and hopefully retire the original sinkScalarOperands. Such a refactoring could potentially simplify that recipe's code itself, regardless of sinkScalarOperands.