This is an archive of the discontinued LLVM Phabricator instance.

[VPlan] Disallow sinking side-effecting first order recurrence users
ClosedPublic

Authored by ebrevnov on May 23 2023, 5:06 AM.

Details

Summary

We started seeing new failure after D142886. Looks like it enabled new cases and we hit an assert:
assert(Current->getNumDefinedValues() == 1 &&

"only recipes with a single defined value expected");

When we do instruction sinking for the first order recurrence we hit an assert if instruction doesn't have single def. In case instruction doesn't produce any new def there is no new users and nothing to sink.

Diff Detail

Event Timeline

ebrevnov created this revision.May 23 2023, 5:06 AM
Herald added a project: Restricted Project. · View Herald TranscriptMay 23 2023, 5:06 AM
ebrevnov requested review of this revision.May 23 2023, 5:06 AM
ebrevnov edited the summary of this revision. (Show Details)May 23 2023, 5:09 AM
ebrevnov added a reviewer: fhahn.
fhahn added inline comments.
llvm/lib/Transforms/Vectorize/VPlanTransforms.cpp
682

I *think* this would not be safe in all cases; e.g. if we have a store here than we would need to sink a store, which may not be legal if there are other loads in the loop and we would sink past them (would be good to add a test case)

I *think* to start with, it would be good to prevent sinking instructions with side-effects in TryPushSinkCandidate.

There's a patch series that moves memory legality checking to VPlan (D142895 and following) which support s sinking some memory operations.

llvm/test/Transforms/LoopVectorize/first-order-recurrence-chains-vplan.ll
112

I *think* it would also be good to check actual codegen for the test in llvm/test/Transforms/LoopVectorize/first-order-recurrence-chains.ll.

151

nit: using loop as block name would be more descriptive.

152

nit: It would be easier to read if the induction phi would be named iv, and the recurrence phis something like for.X.

156

does this need addrspace(1)? Also, would be good to pass in the base pointer as arg, to avoid UB in test.

ebrevnov added inline comments.Jun 1 2023, 2:12 AM
llvm/lib/Transforms/Vectorize/VPlanTransforms.cpp
682

My understanding that legality of sinking is checked in isFixedOrderRecurrence. It's checked for every use regardless of number of defs. Thus we should fail to recognize FOR in your case (because it rejects any side-effecting instruction currently). Am I missing something?

llvm/test/Transforms/LoopVectorize/first-order-recurrence-chains-vplan.ll
112

Do you suggest to update CHECKs for all cases inside this file?

151

ok. will fix.

152

ok. will fix.

156

ok. will fix.

fhahn added inline comments.Jun 6 2023, 2:17 AM
llvm/lib/Transforms/Vectorize/VPlanTransforms.cpp
682

This is not longer completely true, whether the users of recurrences can be re-ordered or not is checked based on VPlan, which is more powerful. Note that the test case hasn't been vectorized before re-ordering based on VPlan (see https://llvm.godbolt.org/z/8d9PM353T). Until we check for aliasing based on VPlan (patches mentioned in earlier comments), we should bail out when trying to sink recipes that may have side effects.

llvm/test/Transforms/LoopVectorize/first-order-recurrence-chains-vplan.ll
112

No, adding a separate test here llvm/test/Transforms/LoopVectorize/first-order-recurrence-chains.ll, but it is probably not needed, checking the VPlan only is simpler.

ebrevnov added inline comments.Jun 14 2023, 1:01 AM
llvm/lib/Transforms/Vectorize/VPlanTransforms.cpp
682

This is not longer completely true, ...

I understand the intent to do legality checking on VPlan, but at the moment it doesn't seem to be fully the case. In particular, there is a check that sink candidate doesn't have side effects in RecurrenceDescriptor::isFixedOrderRecurrence:

if (SinkCandidate->getParent() != PhiBB ||
    SinkCandidate->mayHaveSideEffects() ||
    SinkCandidate->mayReadFromMemory() || SinkCandidate->isTerminator())
  return false;

That means we can't meet side effecting user of FOR in sinkRecurrenceUsersAfterPrevious. So I don't understand why we need another check here.

Maybe, what you mean is to move the check from RecurrenceDescriptor::isFixedOrderRecurrence to sinkRecurrenceUsersAfterPrevious? Could you clarify.

PS: It looks like comment for 'adjustFixedOrderRecurrences' is a bit outdated since it still assumes that legality is checked before.

/// The current implementation assumes all users can be sunk after the previous
/// value, which is enforced by earlier legality checks.

gentle ping...

fhahn added inline comments.Jun 22 2023, 3:16 AM
llvm/lib/Transforms/Vectorize/VPlanTransforms.cpp
682

That means we can't meet side effecting user of FOR in sinkRecurrenceUsersAfterPrevious. So I don't understand why we need another check here.

This is true in most cases, but your test case uncovered a scenario where this is not the case. Before sinkRecurrenceUsersAfterPrevious was introduced to handle the re-ordering, the code was unable to reorder the code in the test case due to limitations in the old implementation.

Now we can re-order, but this means we need to check for side effects to catch cases where the original order of instructions doesn't require sinking an instruction with side effects, but does so after sinking operands for a different FOR.

fhahn added inline comments.Jun 22 2023, 3:18 AM
llvm/lib/Transforms/Vectorize/VPlanTransforms.cpp
682

Maybe, what you mean is to move the check from RecurrenceDescriptor::isFixedOrderRecurrence to sinkRecurrenceUsersAfterPrevious? Could you clarify.

I think for now we need the checks in both places still, but the checks in RecurrenceDescriptor::isFixedOrderRecurrence will be removed as part of D142895 and following.

ebrevnov updated this revision to Diff 535728.Jun 29 2023, 5:00 AM

Prevent sinking side-effecting instructions

Florian, I've addressed yours concerns. Please take a look now.

fhahn accepted this revision.Jul 3 2023, 5:32 AM

LGTM with inline comments, thanks! first-order-recurrence-multiply-recurrences.ll needs updating, but the change there is fine and expected. We will be able to vectorize this again once FOR splice doesn't need to be considered as having side-effects.

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

nit: indentation seems off here, please make sure the patch is formatted properly before landing.

680

For now, I think with the fix above the original assert should be kept and handling for recipes with zero defined values should not be needed. If not, at least the assert will help to surface a test case.

This revision is now accepted and ready to land.Jul 3 2023, 5:32 AM

Florian, thank you for review.

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

Fixed.

680

Ok, restored assert back.

This revision was landed with ongoing or failed builds.Jul 4 2023, 2:53 AM
This revision was automatically updated to reflect the committed changes.
fhahn added a comment.Aug 2 2023, 6:50 AM

Just realized the commit title is not in line with the implementation :(

ebrevnov retitled this revision from [VPlan] Allow sinking of instructions with no defs to [VPlan] Disallow sinking side-effecting first order recurrence users .Aug 2 2023, 10:59 PM

Just realized the commit title is not in line with the implementation :(

Indeed, fixed. Thanks!