[PATCH] Relax atomic restrictions on memory dependence analysis

Robin Morisset morisset at google.com
Wed Aug 6 17:58:16 PDT 2014


Improve patch for atomics in MemoryDependenceAnalysis based on Philip Reames comments

1) Erase the third part of the patch (dealing with fences/AtomicRMW) as the current code
    was actually fine after testing (I should have tested this first, mea culpa). Replaced
    with a comment explaining why the current code works, as it depends on a non-obvious part
    of the implementation of AliasAnalysis.
2) Expand the original comment to give the intuition of the paper
3) Expand the comments for load/store, and change the wording of the condition so that it is
    clearer what is tested.

Thanks a lot for the comments !
I can still try to split the patch in two if you want, but the third part is gone, and with the
clearer condition it is unclear how I should split the rest: Monotonic accesses are not treated
really specially.

http://reviews.llvm.org/D4797

Files:
  lib/Analysis/MemoryDependenceAnalysis.cpp

Index: lib/Analysis/MemoryDependenceAnalysis.cpp
===================================================================
--- lib/Analysis/MemoryDependenceAnalysis.cpp
+++ lib/Analysis/MemoryDependenceAnalysis.cpp
@@ -371,11 +371,18 @@
   unsigned Limit = BlockScanLimit;
   bool isInvariantLoad = false;
 
-  // Atomic accesses are only a problem if there is an acquire after a release.
-  // See "Compiler testing via a theory of sound optimisations in the C11/C++11
-  //   memory model" in PLDI 2013 for details.
+  // We must be careful with atomic accesses, as they may allow another thread
+  //   to touch this location, cloberring it. Based on the results of
+  //   "Compiler testing via a theory of sound optimisations in the C11/C++11
+  //   memory model" in PLDI 2013, we know that this is only possible if there
+  //   is a release access, followed by an acquire access.
+  // The general idea is that for a discriminating context (i.e. that accesses
+  //   MemLoc) to not be racy, it must synchronize with both the access being
+  //   optimized and the previous one, which requires respectively an acquire
+  //   and a release on this thread.
   // This paper does not prove this result for RMW accesses/fences, so we are
-  // conservative with them.
+  // conservative with them. They are detected as ModRef by the alias analysis,
+  // so this function returns Clobber on them automatically.
   bool HasSeenAcquire = false;
 
   if (isLoad && QueryInst) {
@@ -417,8 +424,10 @@
     // a load depends on another must aliased load from the same value.
     if (LoadInst *LI = dyn_cast<LoadInst>(Inst)) {
       // Atomic loads have complications involved.
-      // Monotonic accesses are not dangerous for this purpose.
-      if ((!LI->isUnordered()) && LI->getOrdering() != Monotonic)
+      // Unordered/Monotonic accesses are not dangerous for this purpose,
+      // and a load cannot be Release or Acquire_Release.
+      if (LI->getOrdering() == Acquire
+              || LI->getOrdering() == SequentiallyConsistent)
         HasSeenAcquire = true;
 
       AliasAnalysis::Location LoadLoc = AA->getLocation(LI);
@@ -477,8 +486,11 @@
 
     if (StoreInst *SI = dyn_cast<StoreInst>(Inst)) {
       // Atomic stores have complications involved.
-      // Monotonic accesses are safe for this purpose.
-      if (HasSeenAcquire && (!SI->isUnordered()) && SI->getOrdering() != Monotonic)
+      // Unordered/Monotonic accesses are not dangerous for this purpose,
+      // and a store cannot be Acquire or Acquire_Release.
+      if (HasSeenAcquire &&
+              (SI->getOrdering() == Release
+               || SI->getOrdering() == SequentiallyConsistent))
         return MemDepResult::getClobber(SI);
 
       // If alias analysis can tell that this store is guaranteed to not modify
@@ -503,25 +515,6 @@
       return MemDepResult::getClobber(Inst);
     }
 
-    // FIXME We are probably too conservative here.
-    if (isa<FenceInst>(Inst)) {
-      return MemDepResult::getClobber(Inst);
-    }
-
-    // FIXME We are probably too conservative here.
-    if (auto RMWI = dyn_cast<AtomicRMWInst>(Inst)) {
-        if (RMWI->getOrdering() != Monotonic) {
-            return MemDepResult::getClobber(Inst);
-        }
-    }
-
-    // FIXME We are probably too conservative here.
-    if (auto CASI = dyn_cast<AtomicCmpXchgInst>(Inst)) {
-        if (CASI->getSuccessOrdering() != Monotonic) {
-            return MemDepResult::getClobber(Inst);
-        }
-    }
-
     // If this is an allocation, and if we know that the accessed pointer is to
     // the allocation, return Def.  This means that there is no dependence and
     // the access can be optimized based on that.  For example, a load could
-------------- next part --------------
A non-text attachment was scrubbed...
Name: D4797.12263.patch
Type: text/x-patch
Size: 3734 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20140807/2d159c6d/attachment.bin>


More information about the llvm-commits mailing list