[llvm] r255931 - Polish atomic pointers

JF Bastien via llvm-commits llvm-commits at lists.llvm.org
Thu Dec 17 14:09:19 PST 2015


Author: jfb
Date: Thu Dec 17 16:09:19 2015
New Revision: 255931

URL: http://llvm.org/viewvc/llvm-project?rev=255931&view=rev
Log:
Polish atomic pointers

Summary:
I didn't realize that we already allowed atomic load/store of pointers,
it was added in 2012 by r162146. This patch updates the documentation
and tightens the verifier by using DataLayout to make sure that the
stored size is byte-sized and power-of-two. DataLayout is also used for
integers, and while I'm here I updated the corresponding code for
cmpxchg and rmw.

See the following discussion for context and upcoming changes to
add floating-point and vector atomics:
  https://groups.google.com/forum/#!topic/llvm-dev/Nh0P_E3CRoo/discussion

Reviewers: reames

Subscribers: llvm-commits

Differential Revision: http://reviews.llvm.org/D15512

Modified:
    llvm/trunk/docs/LangRef.rst
    llvm/trunk/lib/IR/Verifier.cpp
    llvm/trunk/test/Verifier/atomics.ll

Modified: llvm/trunk/docs/LangRef.rst
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/docs/LangRef.rst?rev=255931&r1=255930&r2=255931&view=diff
==============================================================================
--- llvm/trunk/docs/LangRef.rst (original)
+++ llvm/trunk/docs/LangRef.rst Thu Dec 17 16:09:19 2015
@@ -6847,17 +6847,16 @@ then the optimizer is not allowed to mod
 execution of this ``load`` with other :ref:`volatile
 operations <volatile>`.
 
-If the ``load`` is marked as ``atomic``, it takes an extra
-:ref:`ordering <ordering>` and optional ``singlethread`` argument. The
-``release`` and ``acq_rel`` orderings are not valid on ``load``
-instructions. Atomic loads produce :ref:`defined <memmodel>` results
-when they may see multiple atomic stores. The type of the pointee must
-be an integer or floating point type whose bit width is a power of two,
-greater than or equal to eight, and less than or equal to a 
-target-specific size limit. ``align`` must be explicitly specified on
-atomic loads, and the load has undefined behavior if the alignment is 
-not set to a value which is at least the size in bytes of the pointee.
-``!nontemporal`` does not have any defined semantics for atomic loads.
+If the ``load`` is marked as ``atomic``, it takes an extra :ref:`ordering
+<ordering>` and optional ``singlethread`` argument. The ``release`` and
+``acq_rel`` orderings are not valid on ``load`` instructions. Atomic loads
+produce :ref:`defined <memmodel>` results when they may see multiple atomic
+stores. The type of the pointee must be an integer, pointer, or floating-point
+type whose bit width is a power of two greater than or equal to eight and less
+than or equal to a target-specific size limit.  ``align`` must be explicitly
+specified on atomic loads, and the load has undefined behavior if the alignment
+is not set to a value which is at least the size in bytes of the
+pointee. ``!nontemporal`` does not have any defined semantics for atomic loads.
 
 The optional constant ``align`` argument specifies the alignment of the
 operation (that is, the alignment of the memory address). A value of 0
@@ -6972,18 +6971,16 @@ then the optimizer is not allowed to mod
 execution of this ``store`` with other :ref:`volatile
 operations <volatile>`.
 
-If the ``store`` is marked as ``atomic``, it takes an extra
-:ref:`ordering <ordering>` and optional ``singlethread`` argument. The
-``acquire`` and ``acq_rel`` orderings aren't valid on ``store``
-instructions. Atomic loads produce :ref:`defined <memmodel>` results
-when they may see multiple atomic stores. The type of the pointee must
-be an integer or floating point type whose bit width is a power of two,
-greater than or equal to eight, and less than or equal to a 
-target-specific size limit.  ``align`` must be explicitly specified 
-on atomic stores, and the store has undefined behavior if the alignment
-is not set to a value which is at least the size in bytes of the 
-pointee. ``!nontemporal`` does not have any defined semantics for 
-atomic stores.
+If the ``store`` is marked as ``atomic``, it takes an extra :ref:`ordering
+<ordering>` and optional ``singlethread`` argument. The ``acquire`` and
+``acq_rel`` orderings aren't valid on ``store`` instructions. Atomic loads
+produce :ref:`defined <memmodel>` results when they may see multiple atomic
+stores. The type of the pointee must be an integer, pointer, or floating-point
+type whose bit width is a power of two greater than or equal to eight and less
+than or equal to a target-specific size limit.  ``align`` must be explicitly
+specified on atomic stores, and the store has undefined behavior if the
+alignment is not set to a value which is at least the size in bytes of the
+pointee. ``!nontemporal`` does not have any defined semantics for atomic stores.
 
 The optional constant ``align`` argument specifies the alignment of the
 operation (that is, the alignment of the memory address). A value of 0

Modified: llvm/trunk/lib/IR/Verifier.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/IR/Verifier.cpp?rev=255931&r1=255930&r2=255931&view=diff
==============================================================================
--- llvm/trunk/lib/IR/Verifier.cpp (original)
+++ llvm/trunk/lib/IR/Verifier.cpp Thu Dec 17 16:09:19 2015
@@ -207,6 +207,8 @@ class Verifier : public InstVisitor<Veri
   /// Cache of constants visited in search of ConstantExprs.
   SmallPtrSet<const Constant *, 32> ConstantExprVisited;
 
+  void checkAtomicMemAccessSize(const Module *M, Type *Ty,
+                                const Instruction *I);
 public:
   explicit Verifier(raw_ostream &OS)
       : VerifierSupport(OS), Context(nullptr), LandingPadResultTy(nullptr),
@@ -2734,6 +2736,14 @@ void Verifier::visitRangeMetadata(Instru
   }
 }
 
+void Verifier::checkAtomicMemAccessSize(const Module *M, Type *Ty,
+                                        const Instruction *I) {
+  unsigned Size = M->getDataLayout().getTypeSizeInBits(Ty);
+  Assert(Size >= 8, "atomic memory access' size must be byte-sized", Ty, I);
+  Assert(!(Size & (Size - 1)),
+         "atomic memory access' operand must have a power-of-two size", Ty, I);
+}
+
 void Verifier::visitLoadInst(LoadInst &LI) {
   PointerType *PTy = dyn_cast<PointerType>(LI.getOperand(0)->getType());
   Assert(PTy, "Load operand must be a pointer.", &LI);
@@ -2745,15 +2755,12 @@ void Verifier::visitLoadInst(LoadInst &L
            "Load cannot have Release ordering", &LI);
     Assert(LI.getAlignment() != 0,
            "Atomic load must specify explicit alignment", &LI);
-    if (!ElTy->isPointerTy()) {
-      Assert(ElTy->isIntegerTy() || ElTy->isFloatingPointTy(),
-             "atomic load operand must have integer or floating point type!",
-             &LI, ElTy);
-      unsigned Size = ElTy->getPrimitiveSizeInBits();
-      Assert(Size >= 8 && !(Size & (Size - 1)),
-             "atomic load operand must be power-of-two byte-sized integer", &LI,
-             ElTy);
-    }
+    Assert(ElTy->isIntegerTy() || ElTy->isPointerTy() ||
+               ElTy->isFloatingPointTy(),
+           "atomic load operand must have integer, pointer, or floating point "
+           "type!",
+           ElTy, &LI);
+    checkAtomicMemAccessSize(M, ElTy, &LI);
   } else {
     Assert(LI.getSynchScope() == CrossThread,
            "Non-atomic load cannot have SynchronizationScope specified", &LI);
@@ -2775,15 +2782,12 @@ void Verifier::visitStoreInst(StoreInst
            "Store cannot have Acquire ordering", &SI);
     Assert(SI.getAlignment() != 0,
            "Atomic store must specify explicit alignment", &SI);
-    if (!ElTy->isPointerTy()) {
-      Assert(ElTy->isIntegerTy() || ElTy->isFloatingPointTy(),
-             "atomic store operand must have integer or floating point type!",
-             &SI, ElTy);
-      unsigned Size = ElTy->getPrimitiveSizeInBits();
-      Assert(Size >= 8 && !(Size & (Size - 1)),
-             "atomic store operand must be power-of-two byte-sized integer",
-             &SI, ElTy);
-    }
+    Assert(ElTy->isIntegerTy() || ElTy->isPointerTy() ||
+               ElTy->isFloatingPointTy(),
+           "atomic store operand must have integer, pointer, or floating point "
+           "type!",
+           ElTy, &SI);
+    checkAtomicMemAccessSize(M, ElTy, &SI);
   } else {
     Assert(SI.getSynchScope() == CrossThread,
            "Non-atomic store cannot have SynchronizationScope specified", &SI);
@@ -2830,9 +2834,7 @@ void Verifier::visitAtomicCmpXchgInst(At
   Type *ElTy = PTy->getElementType();
   Assert(ElTy->isIntegerTy(), "cmpxchg operand must have integer type!", &CXI,
          ElTy);
-  unsigned Size = ElTy->getPrimitiveSizeInBits();
-  Assert(Size >= 8 && !(Size & (Size - 1)),
-         "cmpxchg operand must be power-of-two byte-sized integer", &CXI, ElTy);
+  checkAtomicMemAccessSize(M, ElTy, &CXI);
   Assert(ElTy == CXI.getOperand(1)->getType(),
          "Expected value type does not match pointer operand type!", &CXI,
          ElTy);
@@ -2851,10 +2853,7 @@ void Verifier::visitAtomicRMWInst(Atomic
   Type *ElTy = PTy->getElementType();
   Assert(ElTy->isIntegerTy(), "atomicrmw operand must have integer type!",
          &RMWI, ElTy);
-  unsigned Size = ElTy->getPrimitiveSizeInBits();
-  Assert(Size >= 8 && !(Size & (Size - 1)),
-         "atomicrmw operand must be power-of-two byte-sized integer", &RMWI,
-         ElTy);
+  checkAtomicMemAccessSize(M, ElTy, &RMWI);
   Assert(ElTy == RMWI.getOperand(1)->getType(),
          "Argument value type does not match pointer operand type!", &RMWI,
          ElTy);

Modified: llvm/trunk/test/Verifier/atomics.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Verifier/atomics.ll?rev=255931&r1=255930&r2=255931&view=diff
==============================================================================
--- llvm/trunk/test/Verifier/atomics.ll (original)
+++ llvm/trunk/test/Verifier/atomics.ll Thu Dec 17 16:09:19 2015
@@ -1,7 +1,7 @@
 ; RUN: not opt -verify < %s 2>&1 | FileCheck %s
 
-; CHECK: atomic store operand must have integer or floating point type!
-; CHECK: atomic load operand must have integer or floating point type!
+; CHECK: atomic store operand must have integer, pointer, or floating point type!
+; CHECK: atomic load operand must have integer, pointer, or floating point type!
 
 define void @foo(x86_mmx* %P, x86_mmx %v) {
   store atomic x86_mmx %v, x86_mmx* %P unordered, align 8




More information about the llvm-commits mailing list