[PATCH] D11410: [GMR] Teach GlobalsModRef to distinguish an important and safe case of no-alias with non-addr-taken globals: they cannot alias a captured pointer.
Chandler Carruth
chandlerc at gmail.com
Thu Jul 23 20:03:41 PDT 2015
chandlerc updated this revision to Diff 30555.
chandlerc added a comment.
Rebase to ToT
http://reviews.llvm.org/D11410
Files:
lib/Analysis/IPA/GlobalsModRef.cpp
Index: lib/Analysis/IPA/GlobalsModRef.cpp
===================================================================
--- lib/Analysis/IPA/GlobalsModRef.cpp
+++ lib/Analysis/IPA/GlobalsModRef.cpp
@@ -675,6 +675,52 @@
if ((GV1 || GV2) && GV1 != GV2)
return NoAlias;
+ // There are particular cases where we can conclude no-alias between
+ // a non-addr-taken global and some other underlying object. Specifically,
+ // a non-addr-taken global is known to not be captured by any function. It
+ // is also incorrect for a transformation to introduce a capture of
+ // a global in a way that is observable when it was not there previously.
+ // One function being transformed to introduce a capture which could
+ // possibly be observed (via loading from a global for example) within
+ // another function is never safe. If the observation is made through
+ // non-atomic operations on different threads, it is a data-race and UB. If
+ // the observation is well defined, by being observed the transformation
+ // would have changed program behavior by introducing the capture, making
+ // it an invalid transform.
+ //
+ // This property does require that transformation which *temporarily*
+ // capture a global that was not previously captured, prior to restoring
+ // it, cannot rely on the results of GMR::alias. This seems a reasonable
+ // restriction, although currently there is no way to enforce it. There is
+ // also no realistic optimization pass that would make this mistake. The
+ // closest example is a transformation pass which does reg2mem of SSA
+ // values but stores them into global variables temporarily before
+ // restoring the global variable's value. This could be useful to expose
+ // "benign" races for example. However, it seems reasonable to require that
+ // a pass which introduces captures of global variables in this way to
+ // either not trust AA results while the capture is active, or to be forced
+ // to operate as a module pass that cannot co-exist with an alias analysis
+ // such as GMR.
+ if ((GV1 || GV2) && GV1 != GV2) {
+ const Value *UV = GV1 ? UV2 : UV1;
+
+ // In order to know that the underlying object cannot alias the
+ // non-addr-taken global, we must know that it would have to be an
+ // escape. Thus if the underlying object is a function argument, a load
+ // from a global, or the return of a function, it cannot alias.
+ if (isa<Argument>(UV) || isa<CallInst>(UV) || isa<InvokeInst>(UV)) {
+ // Arguments to functions or returns from functions are inherently
+ // capturing, so we can immediately classify those as not aliasing any
+ // non-addr-taken globals.
+ return NoAlias;
+ } else if (auto *LI = dyn_cast<LoadInst>(UV)) {
+ // A pointer loaded from a global would have been captured, and we know
+ // that GV is non-addr-taken, so no alias.
+ if (isa<GlobalValue>(LI->getPointerOperand()))
+ return NoAlias;
+ }
+ }
+
// Otherwise if they are both derived from the same addr-taken global, we
// can't know the two accesses don't overlap.
}
-------------- next part --------------
A non-text attachment was scrubbed...
Name: D11410.30555.patch
Type: text/x-patch
Size: 3213 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20150724/41e5a547/attachment.bin>
More information about the llvm-commits
mailing list