This is an archive of the discontinued LLVM Phabricator instance.

[AliasAnalysis] Treat invariant.start as read-memory
ClosedPublic

Authored by anna on Aug 5 2016, 11:02 AM.

Details

Summary

We teach alias analysis that invariant.start is readonly.
This helps with GVN and memcopy optimizations that currently treat.
invariant.start as a clobber.
We need to treat this as readonly, so that DSE does not incorrectly
remove stores prior to the invariant.start

Diff Detail

Event Timeline

anna updated this revision to Diff 66980.Aug 5 2016, 11:02 AM
anna retitled this revision from to [MDA] Treat invariant.start as non-dependence.
anna updated this object.
anna added reviewers: sanjoy, reames, dberlin.
anna added a subscriber: llvm-commits.
anna added a comment.Aug 5 2016, 10:15 PM

Changing the code to teach Alias analysis (instead of MDA) about the readonly nature of MDA. All the tests are still valid (and checks remain the same).
getModRefInfo is used by MDA, so the implications on the various passes (GVN, Memcpyopt and DSE) should be the same, it’s just that the code change will be within the same code region where other special cases for llvm.assume and guard intrinsics exist.

Making the change in alias analysis rather than MDA stemmed from the discussion in llvm-commits mailing list with dberlin and sanjoy.

anna updated this revision to Diff 67159.Aug 8 2016, 7:00 AM

[Alias Analysis] Mark invariant.start as readonly

We teach alias analysis that invariant.start is readonly.
This helps with GVN and memcopy optimizations that currently treat.
invariant.start as a clobber.
We need to treat this as readonly, so that DSE does not incorrectly
remove stores prior to the invariant.start

This initially started off as a change to teach MDA about invariant.start,
but further discussion prompted the change to alias analysis (where other such
special cases for guards and assume intrinsics exist).

dberlin accepted this revision.Aug 8 2016, 3:56 PM
dberlin edited edge metadata.

Fix the comments, then LGTM

lib/Analysis/BasicAliasAnalysis.cpp
785 ↗(On Diff #67159)

Errr, this is now wrong?

Maybe you mean "were both also marked"?

787 ↗(On Diff #67159)

invariant.start is modeled (invariant.end is still modeled as writing)

This revision is now accepted and ready to land.Aug 8 2016, 3:56 PM
sanjoy added inline comments.Aug 8 2016, 4:01 PM
lib/Analysis/BasicAliasAnalysis.cpp
793 ↗(On Diff #67159)

A more pertinent example is (I think):

*ptr = 40;
*ptr = 50;
invariant_start(ptr)
int val = *ptr;
print(val);

cannot be transformed to

*ptr = 40;
invariant_start(ptr)
*ptr = 50;
int val = *ptr;
print(val);

since the first program (always) prints 50 but the second one can be
optimized to (following the rules of invariant_start):

*ptr = 40;
invariant_start(ptr)
*ptr = 50;  // This store can be ignored
int val = 40;
print(val);
anna marked 2 inline comments as done.Aug 9 2016, 6:25 AM
anna added inline comments.
lib/Analysis/BasicAliasAnalysis.cpp
785 ↗(On Diff #67159)

I'm not sure if the comment is wrong. The comment intended to convey: "In other code such as MDA, instruction->MayWriteToMemory, etc, assumes and invariant.start are marked as read/write, even though they do not modify memory" However, while assume is marked as NoModRef above, we need to mark invariant.start as reading memory.

It actually follows from the above 2 intrinsic comments "assume and experimental_guard" :)
Should I update the comment?

anna retitled this revision from [MDA] Treat invariant.start as non-dependence to [AliasAnalysis] Treat invariant.start as read-memory.Aug 9 2016, 6:26 AM
anna updated this object.
anna edited edge metadata.
anna marked 2 inline comments as done.Aug 9 2016, 9:59 AM
anna added inline comments.
lib/Analysis/BasicAliasAnalysis.cpp
785 ↗(On Diff #67159)

I've updated the comment to:
Like assumes, invariant.start intrinsics were also marked as arbitrarily
writing so that proper control dependencies are maintained but they never
mod any particular memory location visible to the IR.
*Unlike* assumes (which are now modeled as NoModRef), invariant.start intrinsic is now modeled as reading memory. This prevents hoisting the invariant.start intrinsic over stores.

This revision was automatically updated to reflect the committed changes.