This is an archive of the discontinued LLVM Phabricator instance.

[IR] Memory intrinsics are not unconditionally `nosync`
ClosedPublic

Authored by nhaehnle on May 11 2021, 5:42 PM.

Details

Summary
Remove the `nosync` attribute from the memory intrinsic definitions
(i.e. memset, memcpy, memmove).

Like native memory accesses, memory intrinsics can be volatile. This is
indicated by an immarg in the intrinsic call. All else equal, a volatile
memory intrinsic is `sync`, so we cannot annotate the intrinsic functions
themselves as `nosync`. The attributor and function-attr passes know to
take the volatile bit into account.

Since `nosync` is a default attribute, this means we have to stop using
the DefaultAttrIntrinsic tablegen class for memory intrinsics, and
specify all default attributes other than `nosync` explicitly.

Most of the test changes are trivial churn, but one test case
(in nosync.ll) was in fact incorrect before this change.

Diff Detail

Event Timeline

nhaehnle created this revision.May 11 2021, 5:42 PM
nhaehnle requested review of this revision.May 11 2021, 5:42 PM
Herald added a reviewer: baziotis. · View Herald Transcript
Herald added a project: Restricted Project. · View Herald Transcript
Herald added a subscriber: bbn. · View Herald Transcript
nhaehnle updated this revision to Diff 344621.May 11 2021, 5:51 PM

Fired too quickly, the Attributor actually had a bug and an incorrect lit test. This version should fix that.

nhaehnle retitled this revision from [FunctionAttr][Attributor][nosync] Remove redundant check to [FunctionAttr][Attributor] Cleanup `nosync` checks of memory intrinsics.May 11 2021, 5:52 PM
nhaehnle edited the summary of this revision. (Show Details)
jdoerfert added inline comments.May 11 2021, 6:06 PM
llvm/lib/Transforms/IPO/AttributorAttributes.cpp
1337 ↗(On Diff #344621)

This doesn't make sense to me now. I think I figured out my problem (below) but I wanted to keep my reasoning:
So, a memintrinsic is either nosync or it is not. Let's play this through:

  1. We add nosync to the ones that are not volatile we don't need this because of the check below. This doesn't seem to be the case right now.
  2. We don't add nosync to any memintrinsics and we need to check them explicitly, this is what the old code was supposed to do (I imagine) but the new code doesn't do that. That said, we add nosync so it's actually 3).
  3. We add nosync to all memintrinsics regardless if they are volatile or not. This seems to be plain wrong. The new code will filter the ones out that we wrongly annotated so the error does not propagate. I doubt this is the right strategy though. We should go with 1) or 2) instead.
llvm/test/Transforms/Attributor/nosync.ll
419

FWIW, this looks like a bug to me too.

reames requested changes to this revision.May 11 2021, 7:07 PM
reames added inline comments.
llvm/lib/Transforms/IPO/FunctionAttrs.cpp
1519 ↗(On Diff #344621)

This removal breaks our ability to infer nosync on a non-volatile memset, exactly as the comment describes. There should be a test for this, if there isn't, let me know and I'll add one.

This revision now requires changes to proceed.May 11 2021, 7:07 PM
jdoerfert added inline comments.May 11 2021, 7:35 PM
llvm/lib/Transforms/IPO/FunctionAttrs.cpp
1519 ↗(On Diff #344621)

I think what happened is:

MemXXX was not marked nosync before, we had to derive it explicitly. To be correct, we checked for the volatile flag. Here and in the Attributor code above.
Then the DefaultAttrsIntrinsic change came and memXXX was marked nosync regardless of the volatile flag. That is wrong as I stated in my comment above. In the Attributor code above this patch now filters the wrongly annotated calls, in this code it doesn't and they just split through and propagate the wrong nosync flag further. Intrinsics.td need to be changed.

nhaehnle updated this revision to Diff 346337.May 18 2021, 9:09 PM
nhaehnle edited the summary of this revision. (Show Details)

Invert the logic of the patch: mem intrinsics shouldn't be unconditionally marked nosync in the first place.

nhaehnle retitled this revision from [FunctionAttr][Attributor] Cleanup `nosync` checks of memory intrinsics to [IR] Memory intrinsics are not unconditionally `nosync`.May 18 2021, 9:10 PM
nhaehnle edited the summary of this revision. (Show Details)

LGTM, let @reames should also comment.

reames accepted this revision.May 19 2021, 10:36 AM

Also LGTM, thanks!

This revision is now accepted and ready to land.May 19 2021, 10:36 AM
This revision was landed with ongoing or failed builds.May 20 2021, 6:41 PM
This revision was automatically updated to reflect the committed changes.