[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



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