[AliasAnalysis] Treat invariant.start as read-memory
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 Reviewers: sanjoy, reames, majnemer, dberlin Subscribers: llvm-commits Differential Revision: https://reviews.llvm.org/D23214 llvm-svn: 278138
This commit is contained in:
@@ -781,6 +781,32 @@ ModRefInfo BasicAAResult::getModRefInfo(ImmutableCallSite CS,
|
||||
if (isIntrinsicCall(CS, Intrinsic::experimental_guard))
|
||||
return MRI_Ref;
|
||||
|
||||
// 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. Consider:
|
||||
// *ptr = 40;
|
||||
// *ptr = 50;
|
||||
// invariant_start(ptr)
|
||||
// int val = *ptr;
|
||||
// print(val);
|
||||
//
|
||||
// This cannot be transformed to:
|
||||
//
|
||||
// *ptr = 40;
|
||||
// invariant_start(ptr)
|
||||
// *ptr = 50;
|
||||
// int val = *ptr;
|
||||
// print(val);
|
||||
//
|
||||
// The transformation will cause the second store to be ignored (based on
|
||||
// rules of invariant.start) and print 40, while the first program always
|
||||
// prints 50.
|
||||
if (isIntrinsicCall(CS, Intrinsic::invariant_start))
|
||||
return MRI_Ref;
|
||||
|
||||
// The AAResultBase base class has some smarts, lets use them.
|
||||
return AAResultBase::getModRefInfo(CS, Loc);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user