[LLVMdev] [RFC][PATCH][OPENCL] synchronization scopes redux

Sahasrabuddhe, Sameer sameer.sahasrabuddhe at amd.com
Thu Dec 11 02:58:33 PST 2014


Hi all,

Attached is a sequence of patches that changes the IR to support more 
than two synchronization scopes. This is still a work in progress, and 
these patches are only meant to start a more detailed discussion on the 
way forward.

One big issue is the absence of any backend that actually makes use of 
intermediate synchronization scopes. This work is meant to be just one 
part of the ground work required for landing the much-anticipated HSAIL 
backend. Also, more work might be needed for emitting atomic 
instructions via Clang.

The proposed syntax for synchronization scope is as follows:

 1. Synchronization scopes are of arbitrary width, but implemented as
    unsigned in the bitcode, just like address spaces.
 2. Cross-thread is default, but now encoded as 0.
 3. Keyword 'singlethread' is unchanged, but now encoded as the largest
    integer (which happens to be ~0U in bitcode).
 4. New syntax "synchscope(n)" for other scopes.
 5. There is no keyword for cross-thread, but it can be specified as
    "synchscope(0)".

This change breaks forward compatibility for the bitcode, since the 
meaning of the zero/one values are now changed.

  enum SynchronizationScope {
-  SingleThread = 0,
-  CrossThread = 1
+  CrossThread = 0,
+  SingleThread = ~0U
  };

The change passes almost all lit tests including one new test (see patch 
0005). The failing tests are specifically checking for forward 
compatibility:

Failing Tests (3):
     LLVM :: Bitcode/cmpxchg-upgrade.ll
     LLVM :: Bitcode/memInstructions.3.2.ll
     LLVM :: Bitcode/weak-cmpxchg-upgrade.ll

This breakage remains even if we reverse the order of synchronization 
scopes. One simple way to preserve compatibility is to retain 0 and 1 
with their current meanings, and specify that intermediate scopes are 
represented in an ordered way with numbers greater than one. But this is 
pretty ugly to work with. Would appreciate inputs on how to fix this!

Sameer.

-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/llvm-dev/attachments/20141211/5746b487/attachment.html>
-------------- next part --------------
From 5b5df41609593d6e96b6be511850f63ae6d0f30e Mon Sep 17 00:00:00 2001
From: Sameer Sahasrabuddhe <sameer.sahasrabuddhe at amd.com>
Date: Mon, 1 Dec 2014 12:00:08 +0530
Subject: [PATCH 1/5] selection DAG

Use a separate unsigned field in MemSDNode to store the synchronization scope.
TODO: eliminate the bit from SubclassData that is now unused.
---
 include/llvm/CodeGen/SelectionDAG.h              | 14 +++++++-------
 include/llvm/CodeGen/SelectionDAGNodes.h         | 20 +++++++++-----------
 lib/CodeGen/SelectionDAG/SelectionDAG.cpp        | 14 +++++++-------
 lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp |  8 ++++----
 4 files changed, 27 insertions(+), 29 deletions(-)

diff --git a/include/llvm/CodeGen/SelectionDAG.h b/include/llvm/CodeGen/SelectionDAG.h
index 4950797..53560b9 100644
--- a/include/llvm/CodeGen/SelectionDAG.h
+++ b/include/llvm/CodeGen/SelectionDAG.h
@@ -761,31 +761,31 @@ public:
                            MachinePointerInfo PtrInfo, unsigned Alignment,
                            AtomicOrdering SuccessOrdering,
                            AtomicOrdering FailureOrdering,
-                           SynchronizationScope SynchScope);
+                           unsigned SynchScope);
   SDValue getAtomicCmpSwap(unsigned Opcode, SDLoc dl, EVT MemVT, SDVTList VTs,
                            SDValue Chain, SDValue Ptr, SDValue Cmp, SDValue Swp,
                            MachineMemOperand *MMO,
                            AtomicOrdering SuccessOrdering,
                            AtomicOrdering FailureOrdering,
-                           SynchronizationScope SynchScope);
+                           unsigned SynchScope);
 
   /// getAtomic - Gets a node for an atomic op, produces result (if relevant)
   /// and chain and takes 2 operands.
   SDValue getAtomic(unsigned Opcode, SDLoc dl, EVT MemVT, SDValue Chain,
                     SDValue Ptr, SDValue Val, const Value *PtrVal,
                     unsigned Alignment, AtomicOrdering Ordering,
-                    SynchronizationScope SynchScope);
+                    unsigned SynchScope);
   SDValue getAtomic(unsigned Opcode, SDLoc dl, EVT MemVT, SDValue Chain,
                     SDValue Ptr, SDValue Val, MachineMemOperand *MMO,
                     AtomicOrdering Ordering,
-                    SynchronizationScope SynchScope);
+                    unsigned SynchScope);
 
   /// getAtomic - Gets a node for an atomic op, produces result and chain and
   /// takes 1 operand.
   SDValue getAtomic(unsigned Opcode, SDLoc dl, EVT MemVT, EVT VT,
                     SDValue Chain, SDValue Ptr, MachineMemOperand *MMO,
                     AtomicOrdering Ordering,
-                    SynchronizationScope SynchScope);
+                    unsigned SynchScope);
 
   /// getAtomic - Gets a node for an atomic op, produces result and chain and
   /// takes N operands.
@@ -793,10 +793,10 @@ public:
                     ArrayRef<SDValue> Ops, MachineMemOperand *MMO,
                     AtomicOrdering SuccessOrdering,
                     AtomicOrdering FailureOrdering,
-                    SynchronizationScope SynchScope);
+                    unsigned SynchScope);
   SDValue getAtomic(unsigned Opcode, SDLoc dl, EVT MemVT, SDVTList VTList,
                     ArrayRef<SDValue> Ops, MachineMemOperand *MMO,
-                    AtomicOrdering Ordering, SynchronizationScope SynchScope);
+                    AtomicOrdering Ordering, unsigned SynchScope);
 
   /// getMemIntrinsicNode - Creates a MemIntrinsicNode that may produce a
   /// result and takes a list of operands. Opcode may be INTRINSIC_VOID,
diff --git a/include/llvm/CodeGen/SelectionDAGNodes.h b/include/llvm/CodeGen/SelectionDAGNodes.h
index e4ef3db..74ab130 100644
--- a/include/llvm/CodeGen/SelectionDAGNodes.h
+++ b/include/llvm/CodeGen/SelectionDAGNodes.h
@@ -1080,6 +1080,7 @@ private:
 protected:
   /// MMO - Memory reference information.
   MachineMemOperand *MMO;
+  unsigned SynchScope;
 
 public:
   MemSDNode(unsigned Opc, unsigned Order, DebugLoc dl, SDVTList VTs,
@@ -1115,8 +1116,8 @@ public:
   AtomicOrdering getOrdering() const {
     return AtomicOrdering((SubclassData >> 8) & 15);
   }
-  SynchronizationScope getSynchScope() const {
-    return SynchronizationScope((SubclassData >> 12) & 1);
+  unsigned getSynchScope() const {
+    return SynchScope;
   }
 
   // Returns the offset from the location of the access.
@@ -1197,22 +1198,19 @@ class AtomicSDNode : public MemSDNode {
 
   void InitAtomic(AtomicOrdering SuccessOrdering,
                   AtomicOrdering FailureOrdering,
-                  SynchronizationScope SynchScope) {
+                  unsigned SynchScope) {
     // This must match encodeMemSDNodeFlags() in SelectionDAG.cpp.
     assert((SuccessOrdering & 15) == SuccessOrdering &&
            "Ordering may not require more than 4 bits!");
     assert((FailureOrdering & 15) == FailureOrdering &&
            "Ordering may not require more than 4 bits!");
-    assert((SynchScope & 1) == SynchScope &&
-           "SynchScope may not require more than 1 bit!");
     SubclassData |= SuccessOrdering << 8;
-    SubclassData |= SynchScope << 12;
+    this->SynchScope = SynchScope;
     this->FailureOrdering = FailureOrdering;
     assert(getSuccessOrdering() == SuccessOrdering &&
            "Ordering encoding error!");
     assert(getFailureOrdering() == FailureOrdering &&
            "Ordering encoding error!");
-    assert(getSynchScope() == SynchScope && "Synch-scope encoding error!");
   }
 
 public:
@@ -1227,7 +1225,7 @@ public:
   AtomicSDNode(unsigned Opc, unsigned Order, DebugLoc dl, SDVTList VTL,
                EVT MemVT, SDValue Chain, SDValue Ptr, SDValue Cmp, SDValue Swp,
                MachineMemOperand *MMO, AtomicOrdering Ordering,
-               SynchronizationScope SynchScope)
+               unsigned SynchScope)
       : MemSDNode(Opc, Order, dl, VTL, MemVT, MMO) {
     InitAtomic(Ordering, Ordering, SynchScope);
     InitOperands(Ops, Chain, Ptr, Cmp, Swp);
@@ -1236,7 +1234,7 @@ public:
                EVT MemVT,
                SDValue Chain, SDValue Ptr,
                SDValue Val, MachineMemOperand *MMO,
-               AtomicOrdering Ordering, SynchronizationScope SynchScope)
+               AtomicOrdering Ordering, unsigned SynchScope)
     : MemSDNode(Opc, Order, dl, VTL, MemVT, MMO) {
     InitAtomic(Ordering, Ordering, SynchScope);
     InitOperands(Ops, Chain, Ptr, Val);
@@ -1245,7 +1243,7 @@ public:
                EVT MemVT,
                SDValue Chain, SDValue Ptr,
                MachineMemOperand *MMO,
-               AtomicOrdering Ordering, SynchronizationScope SynchScope)
+               AtomicOrdering Ordering, unsigned SynchScope)
     : MemSDNode(Opc, Order, dl, VTL, MemVT, MMO) {
     InitAtomic(Ordering, Ordering, SynchScope);
     InitOperands(Ops, Chain, Ptr);
@@ -1254,7 +1252,7 @@ public:
                const SDValue* AllOps, SDUse *DynOps, unsigned NumOps,
                MachineMemOperand *MMO,
                AtomicOrdering SuccessOrdering, AtomicOrdering FailureOrdering,
-               SynchronizationScope SynchScope)
+               unsigned SynchScope)
     : MemSDNode(Opc, Order, dl, VTL, MemVT, MMO) {
     InitAtomic(SuccessOrdering, FailureOrdering, SynchScope);
     assert((DynOps || NumOps <= array_lengthof(Ops)) &&
diff --git a/lib/CodeGen/SelectionDAG/SelectionDAG.cpp b/lib/CodeGen/SelectionDAG/SelectionDAG.cpp
index f9131e7..411d619 100644
--- a/lib/CodeGen/SelectionDAG/SelectionDAG.cpp
+++ b/lib/CodeGen/SelectionDAG/SelectionDAG.cpp
@@ -4372,7 +4372,7 @@ SDValue SelectionDAG::getAtomic(unsigned Opcode, SDLoc dl, EVT MemVT,
                                 MachineMemOperand *MMO,
                                 AtomicOrdering SuccessOrdering,
                                 AtomicOrdering FailureOrdering,
-                                SynchronizationScope SynchScope) {
+                                unsigned SynchScope) {
   FoldingSetNodeID ID;
   ID.AddInteger(MemVT.getRawBits());
   AddNodeIDNode(ID, Opcode, VTList, Ops);
@@ -4406,7 +4406,7 @@ SDValue SelectionDAG::getAtomic(unsigned Opcode, SDLoc dl, EVT MemVT,
                                 SDVTList VTList, ArrayRef<SDValue> Ops,
                                 MachineMemOperand *MMO,
                                 AtomicOrdering Ordering,
-                                SynchronizationScope SynchScope) {
+                                unsigned SynchScope) {
   return getAtomic(Opcode, dl, MemVT, VTList, Ops, MMO, Ordering,
                    Ordering, SynchScope);
 }
@@ -4415,7 +4415,7 @@ SDValue SelectionDAG::getAtomicCmpSwap(
     unsigned Opcode, SDLoc dl, EVT MemVT, SDVTList VTs, SDValue Chain,
     SDValue Ptr, SDValue Cmp, SDValue Swp, MachinePointerInfo PtrInfo,
     unsigned Alignment, AtomicOrdering SuccessOrdering,
-    AtomicOrdering FailureOrdering, SynchronizationScope SynchScope) {
+    AtomicOrdering FailureOrdering, unsigned SynchScope) {
   assert(Opcode == ISD::ATOMIC_CMP_SWAP ||
          Opcode == ISD::ATOMIC_CMP_SWAP_WITH_SUCCESS);
   assert(Cmp.getValueType() == Swp.getValueType() && "Invalid Atomic Op Types");
@@ -4444,7 +4444,7 @@ SDValue SelectionDAG::getAtomicCmpSwap(unsigned Opcode, SDLoc dl, EVT MemVT,
                                        MachineMemOperand *MMO,
                                        AtomicOrdering SuccessOrdering,
                                        AtomicOrdering FailureOrdering,
-                                       SynchronizationScope SynchScope) {
+                                       unsigned SynchScope) {
   assert(Opcode == ISD::ATOMIC_CMP_SWAP ||
          Opcode == ISD::ATOMIC_CMP_SWAP_WITH_SUCCESS);
   assert(Cmp.getValueType() == Swp.getValueType() && "Invalid Atomic Op Types");
@@ -4460,7 +4460,7 @@ SDValue SelectionDAG::getAtomic(unsigned Opcode, SDLoc dl, EVT MemVT,
                                 const Value* PtrVal,
                                 unsigned Alignment,
                                 AtomicOrdering Ordering,
-                                SynchronizationScope SynchScope) {
+                                unsigned SynchScope) {
   if (Alignment == 0)  // Ensure that codegen never sees alignment 0
     Alignment = getEVTAlignment(MemVT);
 
@@ -4490,7 +4490,7 @@ SDValue SelectionDAG::getAtomic(unsigned Opcode, SDLoc dl, EVT MemVT,
                                 SDValue Ptr, SDValue Val,
                                 MachineMemOperand *MMO,
                                 AtomicOrdering Ordering,
-                                SynchronizationScope SynchScope) {
+                                unsigned SynchScope) {
   assert((Opcode == ISD::ATOMIC_LOAD_ADD ||
           Opcode == ISD::ATOMIC_LOAD_SUB ||
           Opcode == ISD::ATOMIC_LOAD_AND ||
@@ -4518,7 +4518,7 @@ SDValue SelectionDAG::getAtomic(unsigned Opcode, SDLoc dl, EVT MemVT,
                                 SDValue Ptr,
                                 MachineMemOperand *MMO,
                                 AtomicOrdering Ordering,
-                                SynchronizationScope SynchScope) {
+                                unsigned SynchScope) {
   assert(Opcode == ISD::ATOMIC_LOAD && "Invalid Atomic Op");
 
   SDVTList VTs = getVTList(VT, MVT::Other);
diff --git a/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp b/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
index c573339..ffbc1ea 100644
--- a/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
+++ b/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
@@ -3708,7 +3708,7 @@ void SelectionDAGBuilder::visitAtomicCmpXchg(const AtomicCmpXchgInst &I) {
   SDLoc dl = getCurSDLoc();
   AtomicOrdering SuccessOrder = I.getSuccessOrdering();
   AtomicOrdering FailureOrder = I.getFailureOrdering();
-  SynchronizationScope Scope = I.getSynchScope();
+  unsigned Scope = I.getSynchScope();
 
   SDValue InChain = getRoot();
 
@@ -3744,7 +3744,7 @@ void SelectionDAGBuilder::visitAtomicRMW(const AtomicRMWInst &I) {
   case AtomicRMWInst::UMin: NT = ISD::ATOMIC_LOAD_UMIN; break;
   }
   AtomicOrdering Order = I.getOrdering();
-  SynchronizationScope Scope = I.getSynchScope();
+  unsigned Scope = I.getSynchScope();
 
   SDValue InChain = getRoot();
 
@@ -3776,7 +3776,7 @@ void SelectionDAGBuilder::visitFence(const FenceInst &I) {
 void SelectionDAGBuilder::visitAtomicLoad(const LoadInst &I) {
   SDLoc dl = getCurSDLoc();
   AtomicOrdering Order = I.getOrdering();
-  SynchronizationScope Scope = I.getSynchScope();
+  unsigned Scope = I.getSynchScope();
 
   SDValue InChain = getRoot();
 
@@ -3811,7 +3811,7 @@ void SelectionDAGBuilder::visitAtomicStore(const StoreInst &I) {
   SDLoc dl = getCurSDLoc();
 
   AtomicOrdering Order = I.getOrdering();
-  SynchronizationScope Scope = I.getSynchScope();
+  unsigned Scope = I.getSynchScope();
 
   SDValue InChain = getRoot();
 
-- 
1.9.1

-------------- next part --------------
From 752aa3c73b9c50e7026783819c2921f8ae6ec1b8 Mon Sep 17 00:00:00 2001
From: Sameer Sahasrabuddhe <sameer.sahasrabuddhe at amd.com>
Date: Mon, 8 Dec 2014 15:12:29 +0530
Subject: [PATCH 2/5] instructions

Use a separate unsigned field in LoadInst, StoreInst, AtomicRMWInst, etc.
TODO: eliminate the unused bit from SubclassData.
---
 include/llvm/IR/IRBuilder.h          |   6 +-
 include/llvm/IR/Instructions.h       | 107 ++++++++++++++++-------------------
 lib/Bitcode/Writer/BitcodeWriter.cpp |   2 +-
 lib/IR/AsmWriter.cpp                 |   4 +-
 lib/IR/AsmWriter.h                   |   4 +-
 lib/IR/Instructions.cpp              |  24 ++++----
 lib/Target/CppBackend/CPPBackend.cpp |   2 +-
 7 files changed, 71 insertions(+), 78 deletions(-)

diff --git a/include/llvm/IR/IRBuilder.h b/include/llvm/IR/IRBuilder.h
index e564ca5..c2b3926 100644
--- a/include/llvm/IR/IRBuilder.h
+++ b/include/llvm/IR/IRBuilder.h
@@ -968,7 +968,7 @@ public:
     return SI;
   }
   FenceInst *CreateFence(AtomicOrdering Ordering,
-                         SynchronizationScope SynchScope = CrossThread,
+                         unsigned SynchScope = CrossThread,
                          const Twine &Name = "") {
     return Insert(new FenceInst(Context, Ordering, SynchScope), Name);
   }
@@ -976,13 +976,13 @@ public:
   CreateAtomicCmpXchg(Value *Ptr, Value *Cmp, Value *New,
                       AtomicOrdering SuccessOrdering,
                       AtomicOrdering FailureOrdering,
-                      SynchronizationScope SynchScope = CrossThread) {
+                      unsigned SynchScope = CrossThread) {
     return Insert(new AtomicCmpXchgInst(Ptr, Cmp, New, SuccessOrdering,
                                         FailureOrdering, SynchScope));
   }
   AtomicRMWInst *CreateAtomicRMW(AtomicRMWInst::BinOp Op, Value *Ptr, Value *Val,
                                  AtomicOrdering Ordering,
-                               SynchronizationScope SynchScope = CrossThread) {
+                                 unsigned SynchScope = CrossThread) {
     return Insert(new AtomicRMWInst(Op, Ptr, Val, Ordering, SynchScope));
   }
   Value *CreateGEP(Value *Ptr, ArrayRef<Value *> IdxList,
diff --git a/include/llvm/IR/Instructions.h b/include/llvm/IR/Instructions.h
index dcf19e0..9e25717 100644
--- a/include/llvm/IR/Instructions.h
+++ b/include/llvm/IR/Instructions.h
@@ -166,6 +166,7 @@ private:
 /// SubclassData field in Value to store whether or not the load is volatile.
 ///
 class LoadInst : public UnaryInstruction {
+  unsigned SynchScope;
   void AssertOK();
 protected:
   LoadInst *clone_impl() const override;
@@ -182,11 +183,11 @@ public:
            unsigned Align, BasicBlock *InsertAtEnd);
   LoadInst(Value *Ptr, const Twine &NameStr, bool isVolatile,
            unsigned Align, AtomicOrdering Order,
-           SynchronizationScope SynchScope = CrossThread,
+           unsigned SynchScope = CrossThread,
            Instruction *InsertBefore = nullptr);
   LoadInst(Value *Ptr, const Twine &NameStr, bool isVolatile,
            unsigned Align, AtomicOrdering Order,
-           SynchronizationScope SynchScope,
+           unsigned SynchScope,
            BasicBlock *InsertAtEnd);
 
   LoadInst(Value *Ptr, const char *NameStr, Instruction *InsertBefore);
@@ -229,20 +230,18 @@ public:
                                (Ordering << 7));
   }
 
-  SynchronizationScope getSynchScope() const {
-    return SynchronizationScope((getSubclassDataFromInstruction() >> 6) & 1);
+  unsigned getSynchScope() const {
+    return SynchScope;
   }
 
-  /// Specify whether this load is ordered with respect to all
-  /// concurrently executing threads, or only with respect to signal handlers
-  /// executing in the same thread.
-  void setSynchScope(SynchronizationScope xthread) {
-    setInstructionSubclassData((getSubclassDataFromInstruction() & ~(1 << 6)) |
-                               (xthread << 6));
+  /// Specify the set of threads, with respect to which, this load
+  /// instruction is ordered.
+  void setSynchScope(unsigned SynchScope) {
+    this->SynchScope = SynchScope;
   }
 
   void setAtomic(AtomicOrdering Ordering,
-                 SynchronizationScope SynchScope = CrossThread) {
+                 unsigned SynchScope = CrossThread) {
     setOrdering(Ordering);
     setSynchScope(SynchScope);
   }
@@ -285,6 +284,7 @@ private:
 /// StoreInst - an instruction for storing to memory
 ///
 class StoreInst : public Instruction {
+  unsigned SynchScope;
   void *operator new(size_t, unsigned) LLVM_DELETED_FUNCTION;
   void AssertOK();
 protected:
@@ -305,11 +305,11 @@ public:
             unsigned Align, BasicBlock *InsertAtEnd);
   StoreInst(Value *Val, Value *Ptr, bool isVolatile,
             unsigned Align, AtomicOrdering Order,
-            SynchronizationScope SynchScope = CrossThread,
+            unsigned SynchScope = CrossThread,
             Instruction *InsertBefore = nullptr);
   StoreInst(Value *Val, Value *Ptr, bool isVolatile,
             unsigned Align, AtomicOrdering Order,
-            SynchronizationScope SynchScope,
+            unsigned SynchScope,
             BasicBlock *InsertAtEnd);
 
 
@@ -348,20 +348,18 @@ public:
                                (Ordering << 7));
   }
 
-  SynchronizationScope getSynchScope() const {
-    return SynchronizationScope((getSubclassDataFromInstruction() >> 6) & 1);
+  unsigned getSynchScope() const {
+    return SynchScope;
   }
 
-  /// Specify whether this store instruction is ordered with respect to all
-  /// concurrently executing threads, or only with respect to signal handlers
-  /// executing in the same thread.
-  void setSynchScope(SynchronizationScope xthread) {
-    setInstructionSubclassData((getSubclassDataFromInstruction() & ~(1 << 6)) |
-                               (xthread << 6));
+  /// Specify the set of threads, with respect to which, this store
+  /// instruction is ordered.
+  void setSynchScope(unsigned SynchScope) {
+    this->SynchScope = SynchScope;
   }
 
   void setAtomic(AtomicOrdering Ordering,
-                 SynchronizationScope SynchScope = CrossThread) {
+                 unsigned SynchScope = CrossThread) {
     setOrdering(Ordering);
     setSynchScope(SynchScope);
   }
@@ -411,8 +409,9 @@ DEFINE_TRANSPARENT_OPERAND_ACCESSORS(StoreInst, Value)
 /// FenceInst - an instruction for ordering other memory operations
 ///
 class FenceInst : public Instruction {
+  unsigned SynchScope;
   void *operator new(size_t, unsigned) LLVM_DELETED_FUNCTION;
-  void Init(AtomicOrdering Ordering, SynchronizationScope SynchScope);
+  void Init(AtomicOrdering Ordering, unsigned SynchScope);
 protected:
   FenceInst *clone_impl() const override;
 public:
@@ -424,10 +423,10 @@ public:
   // Ordering may only be Acquire, Release, AcquireRelease, or
   // SequentiallyConsistent.
   FenceInst(LLVMContext &C, AtomicOrdering Ordering,
-            SynchronizationScope SynchScope = CrossThread,
+            unsigned SynchScope = CrossThread,
             Instruction *InsertBefore = nullptr);
   FenceInst(LLVMContext &C, AtomicOrdering Ordering,
-            SynchronizationScope SynchScope,
+            unsigned SynchScope,
             BasicBlock *InsertAtEnd);
 
   /// Returns the ordering effect of this fence.
@@ -442,16 +441,14 @@ public:
                                (Ordering << 1));
   }
 
-  SynchronizationScope getSynchScope() const {
-    return SynchronizationScope(getSubclassDataFromInstruction() & 1);
+  unsigned getSynchScope() const {
+    return SynchScope;
   }
 
-  /// Specify whether this fence orders other operations with respect to all
-  /// concurrently executing threads, or only with respect to signal handlers
-  /// executing in the same thread.
-  void setSynchScope(SynchronizationScope xthread) {
-    setInstructionSubclassData((getSubclassDataFromInstruction() & ~1) |
-                               xthread);
+  /// Specify the set of threads, with respect to which, this fence
+  /// instruction is ordered.
+  void setSynchScope(unsigned SynchScope) {
+    this->SynchScope = SynchScope;
   }
 
   // Methods for support type inquiry through isa, cast, and dyn_cast:
@@ -478,10 +475,11 @@ private:
 /// there.  Returns the value that was loaded.
 ///
 class AtomicCmpXchgInst : public Instruction {
+  unsigned SynchScope;
   void *operator new(size_t, unsigned) LLVM_DELETED_FUNCTION;
   void Init(Value *Ptr, Value *Cmp, Value *NewVal,
             AtomicOrdering SuccessOrdering, AtomicOrdering FailureOrdering,
-            SynchronizationScope SynchScope);
+            unsigned SynchScope);
 protected:
   AtomicCmpXchgInst *clone_impl() const override;
 public:
@@ -492,12 +490,12 @@ public:
   AtomicCmpXchgInst(Value *Ptr, Value *Cmp, Value *NewVal,
                     AtomicOrdering SuccessOrdering,
                     AtomicOrdering FailureOrdering,
-                    SynchronizationScope SynchScope,
+                    unsigned SynchScope,
                     Instruction *InsertBefore = nullptr);
   AtomicCmpXchgInst(Value *Ptr, Value *Cmp, Value *NewVal,
                     AtomicOrdering SuccessOrdering,
                     AtomicOrdering FailureOrdering,
-                    SynchronizationScope SynchScope,
+                    unsigned SynchScope,
                     BasicBlock *InsertAtEnd);
 
   /// isVolatile - Return true if this is a cmpxchg from a volatile memory
@@ -542,12 +540,10 @@ public:
                                (Ordering << 5));
   }
 
-  /// Specify whether this cmpxchg is atomic and orders other operations with
-  /// respect to all concurrently executing threads, or only with respect to
-  /// signal handlers executing in the same thread.
-  void setSynchScope(SynchronizationScope SynchScope) {
-    setInstructionSubclassData((getSubclassDataFromInstruction() & ~2) |
-                               (SynchScope << 1));
+  /// Specify the set of threads, with respect to which, this cmpxchg
+  /// instruction is ordered.
+  void setSynchScope(unsigned SynchScope) {
+    this->SynchScope = SynchScope;
   }
 
   /// Returns the ordering constraint on this cmpxchg.
@@ -562,8 +558,8 @@ public:
 
   /// Returns whether this cmpxchg is atomic between threads or only within a
   /// single thread.
-  SynchronizationScope getSynchScope() const {
-    return SynchronizationScope((getSubclassDataFromInstruction() & 2) >> 1);
+  unsigned getSynchScope() const {
+    return SynchScope;
   }
 
   Value *getPointerOperand() { return getOperand(0); }
@@ -634,6 +630,7 @@ DEFINE_TRANSPARENT_OPERAND_ACCESSORS(AtomicCmpXchgInst, Value)
 /// the old value.
 ///
 class AtomicRMWInst : public Instruction {
+  unsigned SynchScope;
   void *operator new(size_t, unsigned) LLVM_DELETED_FUNCTION;
 protected:
   AtomicRMWInst *clone_impl() const override;
@@ -676,10 +673,10 @@ public:
     return User::operator new(s, 2);
   }
   AtomicRMWInst(BinOp Operation, Value *Ptr, Value *Val,
-                AtomicOrdering Ordering, SynchronizationScope SynchScope,
+                AtomicOrdering Ordering, unsigned SynchScope,
                 Instruction *InsertBefore = nullptr);
   AtomicRMWInst(BinOp Operation, Value *Ptr, Value *Val,
-                AtomicOrdering Ordering, SynchronizationScope SynchScope,
+                AtomicOrdering Ordering, unsigned SynchScope,
                 BasicBlock *InsertAtEnd);
 
   BinOp getOperation() const {
@@ -716,12 +713,10 @@ public:
                                (Ordering << 2));
   }
 
-  /// Specify whether this RMW orders other operations with respect to all
-  /// concurrently executing threads, or only with respect to signal handlers
-  /// executing in the same thread.
-  void setSynchScope(SynchronizationScope SynchScope) {
-    setInstructionSubclassData((getSubclassDataFromInstruction() & ~2) |
-                               (SynchScope << 1));
+  /// Specify the set of threads with respect to which, this RMW
+  /// instruction orders other operations.
+  void setSynchScope(unsigned SynchScope) {
+    this->SynchScope = SynchScope;
   }
 
   /// Returns the ordering constraint on this RMW.
@@ -729,10 +724,8 @@ public:
     return AtomicOrdering((getSubclassDataFromInstruction() >> 2) & 7);
   }
 
-  /// Returns whether this RMW is atomic between threads or only within a
-  /// single thread.
-  SynchronizationScope getSynchScope() const {
-    return SynchronizationScope((getSubclassDataFromInstruction() & 2) >> 1);
+  unsigned getSynchScope() const {
+    return SynchScope;
   }
 
   Value *getPointerOperand() { return getOperand(0); }
@@ -756,7 +749,7 @@ public:
   }
 private:
   void Init(BinOp Operation, Value *Ptr, Value *Val,
-            AtomicOrdering Ordering, SynchronizationScope SynchScope);
+            AtomicOrdering Ordering, unsigned SynchScope);
   // Shadow Instruction::setInstructionSubclassData with a private forwarding
   // method so that subclasses cannot accidentally use it.
   void setInstructionSubclassData(unsigned short D) {
diff --git a/lib/Bitcode/Writer/BitcodeWriter.cpp b/lib/Bitcode/Writer/BitcodeWriter.cpp
index 0de929e..f2a8fcb 100644
--- a/lib/Bitcode/Writer/BitcodeWriter.cpp
+++ b/lib/Bitcode/Writer/BitcodeWriter.cpp
@@ -131,7 +131,7 @@ static unsigned GetEncodedOrdering(AtomicOrdering Ordering) {
   llvm_unreachable("Invalid ordering");
 }
 
-static unsigned GetEncodedSynchScope(SynchronizationScope SynchScope) {
+static unsigned GetEncodedSynchScope(unsigned SynchScope) {
   switch (SynchScope) {
   case SingleThread: return bitc::SYNCHSCOPE_SINGLETHREAD;
   case CrossThread: return bitc::SYNCHSCOPE_CROSSTHREAD;
diff --git a/lib/IR/AsmWriter.cpp b/lib/IR/AsmWriter.cpp
index 8fe03c0..69d6a97 100644
--- a/lib/IR/AsmWriter.cpp
+++ b/lib/IR/AsmWriter.cpp
@@ -1432,7 +1432,7 @@ void AssemblyWriter::writeOperand(const Value *Operand, bool PrintType) {
 }
 
 void AssemblyWriter::writeAtomic(AtomicOrdering Ordering,
-                                 SynchronizationScope SynchScope) {
+                                 unsigned SynchScope) {
   if (Ordering == NotAtomic)
     return;
 
@@ -1454,7 +1454,7 @@ void AssemblyWriter::writeAtomic(AtomicOrdering Ordering,
 
 void AssemblyWriter::writeAtomicCmpXchg(AtomicOrdering SuccessOrdering,
                                         AtomicOrdering FailureOrdering,
-                                        SynchronizationScope SynchScope) {
+                                        unsigned SynchScope) {
   assert(SuccessOrdering != NotAtomic && FailureOrdering != NotAtomic);
 
   switch (SynchScope) {
diff --git a/lib/IR/AsmWriter.h b/lib/IR/AsmWriter.h
index 60da5ad..f3467f6 100644
--- a/lib/IR/AsmWriter.h
+++ b/lib/IR/AsmWriter.h
@@ -94,10 +94,10 @@ public:
 
   void writeOperand(const Value *Op, bool PrintType);
   void writeParamOperand(const Value *Operand, AttributeSet Attrs,unsigned Idx);
-  void writeAtomic(AtomicOrdering Ordering, SynchronizationScope SynchScope);
+  void writeAtomic(AtomicOrdering Ordering, unsigned SynchScope);
   void writeAtomicCmpXchg(AtomicOrdering SuccessOrdering,
                           AtomicOrdering FailureOrdering,
-                          SynchronizationScope SynchScope);
+                          unsigned SynchScope);
 
   void writeAllMDNodes();
   void writeMDNode(unsigned Slot, const MDNode *Node);
diff --git a/lib/IR/Instructions.cpp b/lib/IR/Instructions.cpp
index 132800e..00d8b92 100644
--- a/lib/IR/Instructions.cpp
+++ b/lib/IR/Instructions.cpp
@@ -995,7 +995,7 @@ LoadInst::LoadInst(Value *Ptr, const Twine &Name, bool isVolatile,
 
 LoadInst::LoadInst(Value *Ptr, const Twine &Name, bool isVolatile, 
                    unsigned Align, AtomicOrdering Order,
-                   SynchronizationScope SynchScope,
+                   unsigned SynchScope,
                    Instruction *InsertBef)
   : UnaryInstruction(cast<PointerType>(Ptr->getType())->getElementType(),
                      Load, Ptr, InsertBef) {
@@ -1008,7 +1008,7 @@ LoadInst::LoadInst(Value *Ptr, const Twine &Name, bool isVolatile,
 
 LoadInst::LoadInst(Value *Ptr, const Twine &Name, bool isVolatile, 
                    unsigned Align, AtomicOrdering Order,
-                   SynchronizationScope SynchScope,
+                   unsigned SynchScope,
                    BasicBlock *InsertAE)
   : UnaryInstruction(cast<PointerType>(Ptr->getType())->getElementType(),
                      Load, Ptr, InsertAE) {
@@ -1142,7 +1142,7 @@ StoreInst::StoreInst(Value *val, Value *addr, bool isVolatile,
 
 StoreInst::StoreInst(Value *val, Value *addr, bool isVolatile,
                      unsigned Align, AtomicOrdering Order,
-                     SynchronizationScope SynchScope,
+                     unsigned SynchScope,
                      Instruction *InsertBefore)
   : Instruction(Type::getVoidTy(val->getContext()), Store,
                 OperandTraits<StoreInst>::op_begin(this),
@@ -1186,7 +1186,7 @@ StoreInst::StoreInst(Value *val, Value *addr, bool isVolatile,
 
 StoreInst::StoreInst(Value *val, Value *addr, bool isVolatile,
                      unsigned Align, AtomicOrdering Order,
-                     SynchronizationScope SynchScope,
+                     unsigned SynchScope,
                      BasicBlock *InsertAtEnd)
   : Instruction(Type::getVoidTy(val->getContext()), Store,
                 OperandTraits<StoreInst>::op_begin(this),
@@ -1216,7 +1216,7 @@ void StoreInst::setAlignment(unsigned Align) {
 void AtomicCmpXchgInst::Init(Value *Ptr, Value *Cmp, Value *NewVal,
                              AtomicOrdering SuccessOrdering,
                              AtomicOrdering FailureOrdering,
-                             SynchronizationScope SynchScope) {
+                             unsigned SynchScope) {
   Op<0>() = Ptr;
   Op<1>() = Cmp;
   Op<2>() = NewVal;
@@ -1247,7 +1247,7 @@ void AtomicCmpXchgInst::Init(Value *Ptr, Value *Cmp, Value *NewVal,
 AtomicCmpXchgInst::AtomicCmpXchgInst(Value *Ptr, Value *Cmp, Value *NewVal,
                                      AtomicOrdering SuccessOrdering,
                                      AtomicOrdering FailureOrdering,
-                                     SynchronizationScope SynchScope,
+                                     unsigned SynchScope,
                                      Instruction *InsertBefore)
     : Instruction(
           StructType::get(Cmp->getType(), Type::getInt1Ty(Cmp->getContext()),
@@ -1260,7 +1260,7 @@ AtomicCmpXchgInst::AtomicCmpXchgInst(Value *Ptr, Value *Cmp, Value *NewVal,
 AtomicCmpXchgInst::AtomicCmpXchgInst(Value *Ptr, Value *Cmp, Value *NewVal,
                                      AtomicOrdering SuccessOrdering,
                                      AtomicOrdering FailureOrdering,
-                                     SynchronizationScope SynchScope,
+                                     unsigned SynchScope,
                                      BasicBlock *InsertAtEnd)
     : Instruction(
           StructType::get(Cmp->getType(), Type::getInt1Ty(Cmp->getContext()),
@@ -1276,7 +1276,7 @@ AtomicCmpXchgInst::AtomicCmpXchgInst(Value *Ptr, Value *Cmp, Value *NewVal,
 
 void AtomicRMWInst::Init(BinOp Operation, Value *Ptr, Value *Val,
                          AtomicOrdering Ordering,
-                         SynchronizationScope SynchScope) {
+                         unsigned SynchScope) {
   Op<0>() = Ptr;
   Op<1>() = Val;
   setOperation(Operation);
@@ -1296,7 +1296,7 @@ void AtomicRMWInst::Init(BinOp Operation, Value *Ptr, Value *Val,
 
 AtomicRMWInst::AtomicRMWInst(BinOp Operation, Value *Ptr, Value *Val,
                              AtomicOrdering Ordering,
-                             SynchronizationScope SynchScope,
+                             unsigned SynchScope,
                              Instruction *InsertBefore)
   : Instruction(Val->getType(), AtomicRMW,
                 OperandTraits<AtomicRMWInst>::op_begin(this),
@@ -1307,7 +1307,7 @@ AtomicRMWInst::AtomicRMWInst(BinOp Operation, Value *Ptr, Value *Val,
 
 AtomicRMWInst::AtomicRMWInst(BinOp Operation, Value *Ptr, Value *Val,
                              AtomicOrdering Ordering,
-                             SynchronizationScope SynchScope,
+                             unsigned SynchScope,
                              BasicBlock *InsertAtEnd)
   : Instruction(Val->getType(), AtomicRMW,
                 OperandTraits<AtomicRMWInst>::op_begin(this),
@@ -1321,7 +1321,7 @@ AtomicRMWInst::AtomicRMWInst(BinOp Operation, Value *Ptr, Value *Val,
 //===----------------------------------------------------------------------===//
 
 FenceInst::FenceInst(LLVMContext &C, AtomicOrdering Ordering, 
-                     SynchronizationScope SynchScope,
+                     unsigned SynchScope,
                      Instruction *InsertBefore)
   : Instruction(Type::getVoidTy(C), Fence, nullptr, 0, InsertBefore) {
   setOrdering(Ordering);
@@ -1329,7 +1329,7 @@ FenceInst::FenceInst(LLVMContext &C, AtomicOrdering Ordering,
 }
 
 FenceInst::FenceInst(LLVMContext &C, AtomicOrdering Ordering, 
-                     SynchronizationScope SynchScope,
+                     unsigned SynchScope,
                      BasicBlock *InsertAtEnd)
   : Instruction(Type::getVoidTy(C), Fence, nullptr, 0, InsertAtEnd) {
   setOrdering(Ordering);
diff --git a/lib/Target/CppBackend/CPPBackend.cpp b/lib/Target/CppBackend/CPPBackend.cpp
index f610fbb..300494c 100644
--- a/lib/Target/CppBackend/CPPBackend.cpp
+++ b/lib/Target/CppBackend/CPPBackend.cpp
@@ -1100,7 +1100,7 @@ static StringRef ConvertAtomicOrdering(AtomicOrdering Ordering) {
   llvm_unreachable("Unknown ordering");
 }
 
-static StringRef ConvertAtomicSynchScope(SynchronizationScope SynchScope) {
+static StringRef ConvertAtomicSynchScope(unsigned SynchScope) {
   switch (SynchScope) {
     case SingleThread: return "SingleThread";
     case CrossThread: return "CrossThread";
-- 
1.9.1

-------------- next part --------------
From ff53894856739c8e03c521b57400faf538cd0757 Mon Sep 17 00:00:00 2001
From: Sameer Sahasrabuddhe <sameer.sahasrabuddhe at amd.com>
Date: Wed, 10 Dec 2014 14:58:17 +0530
Subject: [PATCH 3/5] bitcode

Fix the bitcode reader and writer to transparently deal with unsigned integers
for synchronization scope, instead of trying to interpret them.
---
 include/llvm/Bitcode/LLVMBitCodes.h  |  6 ------
 lib/Bitcode/Reader/BitcodeReader.cpp | 23 +++++------------------
 lib/Bitcode/Writer/BitcodeWriter.cpp | 20 +++++---------------
 3 files changed, 10 insertions(+), 39 deletions(-)

diff --git a/include/llvm/Bitcode/LLVMBitCodes.h b/include/llvm/Bitcode/LLVMBitCodes.h
index c42ecfe..c78218a 100644
--- a/include/llvm/Bitcode/LLVMBitCodes.h
+++ b/include/llvm/Bitcode/LLVMBitCodes.h
@@ -260,12 +260,6 @@ namespace bitc {
     ORDERING_SEQCST = 6
   };
 
-  /// Encoded SynchronizationScope values.
-  enum AtomicSynchScopeCodes {
-    SYNCHSCOPE_SINGLETHREAD = 0,
-    SYNCHSCOPE_CROSSTHREAD = 1
-  };
-
   // The function body block (FUNCTION_BLOCK_ID) describes function bodies.  It
   // can contain a constant block (CONSTANTS_BLOCK_ID).
   enum FunctionCodes {
diff --git a/lib/Bitcode/Reader/BitcodeReader.cpp b/lib/Bitcode/Reader/BitcodeReader.cpp
index cc61806..31c48cd 100644
--- a/lib/Bitcode/Reader/BitcodeReader.cpp
+++ b/lib/Bitcode/Reader/BitcodeReader.cpp
@@ -225,14 +225,6 @@ static AtomicOrdering GetDecodedOrdering(unsigned Val) {
   }
 }
 
-static SynchronizationScope GetDecodedSynchScope(unsigned Val) {
-  switch (Val) {
-  case bitc::SYNCHSCOPE_SINGLETHREAD: return SingleThread;
-  default: // Map unknown scopes to cross-thread.
-  case bitc::SYNCHSCOPE_CROSSTHREAD: return CrossThread;
-  }
-}
-
 static Comdat::SelectionKind getDecodedComdatSelectionKind(unsigned Val) {
   switch (Val) {
   default: // Map unknown selection kinds to any.
@@ -3104,10 +3096,9 @@ std::error_code BitcodeReader::ParseFunctionBody(Function *F) {
         return Error(BitcodeError::InvalidRecord);
       if (Ordering != NotAtomic && Record[OpNum] == 0)
         return Error(BitcodeError::InvalidRecord);
-      SynchronizationScope SynchScope = GetDecodedSynchScope(Record[OpNum+3]);
 
       I = new LoadInst(Op, "", Record[OpNum+1], (1 << Record[OpNum]) >> 1,
-                       Ordering, SynchScope);
+                       Ordering, Record[OpNum+3]);
       InstructionList.push_back(I);
       break;
     }
@@ -3138,12 +3129,11 @@ std::error_code BitcodeReader::ParseFunctionBody(Function *F) {
       if (Ordering == NotAtomic || Ordering == Acquire ||
           Ordering == AcquireRelease)
         return Error(BitcodeError::InvalidRecord);
-      SynchronizationScope SynchScope = GetDecodedSynchScope(Record[OpNum+3]);
       if (Ordering != NotAtomic && Record[OpNum] == 0)
         return Error(BitcodeError::InvalidRecord);
 
       I = new StoreInst(Val, Ptr, Record[OpNum+1], (1 << Record[OpNum]) >> 1,
-                        Ordering, SynchScope);
+                        Ordering, Record[OpNum+3]);
       InstructionList.push_back(I);
       break;
     }
@@ -3162,7 +3152,6 @@ std::error_code BitcodeReader::ParseFunctionBody(Function *F) {
       AtomicOrdering SuccessOrdering = GetDecodedOrdering(Record[OpNum+1]);
       if (SuccessOrdering == NotAtomic || SuccessOrdering == Unordered)
         return Error(BitcodeError::InvalidRecord);
-      SynchronizationScope SynchScope = GetDecodedSynchScope(Record[OpNum+2]);
 
       AtomicOrdering FailureOrdering;
       if (Record.size() < 7)
@@ -3172,7 +3161,7 @@ std::error_code BitcodeReader::ParseFunctionBody(Function *F) {
         FailureOrdering = GetDecodedOrdering(Record[OpNum+3]);
 
       I = new AtomicCmpXchgInst(Ptr, Cmp, New, SuccessOrdering, FailureOrdering,
-                                SynchScope);
+                                Record[OpNum+2]);
       cast<AtomicCmpXchgInst>(I)->setVolatile(Record[OpNum]);
 
       if (Record.size() < 8) {
@@ -3204,8 +3193,7 @@ std::error_code BitcodeReader::ParseFunctionBody(Function *F) {
       AtomicOrdering Ordering = GetDecodedOrdering(Record[OpNum+2]);
       if (Ordering == NotAtomic || Ordering == Unordered)
         return Error(BitcodeError::InvalidRecord);
-      SynchronizationScope SynchScope = GetDecodedSynchScope(Record[OpNum+3]);
-      I = new AtomicRMWInst(Operation, Ptr, Val, Ordering, SynchScope);
+      I = new AtomicRMWInst(Operation, Ptr, Val, Ordering, Record[OpNum+3]);
       cast<AtomicRMWInst>(I)->setVolatile(Record[OpNum+1]);
       InstructionList.push_back(I);
       break;
@@ -3217,8 +3205,7 @@ std::error_code BitcodeReader::ParseFunctionBody(Function *F) {
       if (Ordering == NotAtomic || Ordering == Unordered ||
           Ordering == Monotonic)
         return Error(BitcodeError::InvalidRecord);
-      SynchronizationScope SynchScope = GetDecodedSynchScope(Record[1]);
-      I = new FenceInst(Context, Ordering, SynchScope);
+      I = new FenceInst(Context, Ordering, Record[1]);
       InstructionList.push_back(I);
       break;
     }
diff --git a/lib/Bitcode/Writer/BitcodeWriter.cpp b/lib/Bitcode/Writer/BitcodeWriter.cpp
index f2a8fcb..749a996 100644
--- a/lib/Bitcode/Writer/BitcodeWriter.cpp
+++ b/lib/Bitcode/Writer/BitcodeWriter.cpp
@@ -131,14 +131,6 @@ static unsigned GetEncodedOrdering(AtomicOrdering Ordering) {
   llvm_unreachable("Invalid ordering");
 }
 
-static unsigned GetEncodedSynchScope(unsigned SynchScope) {
-  switch (SynchScope) {
-  case SingleThread: return bitc::SYNCHSCOPE_SINGLETHREAD;
-  case CrossThread: return bitc::SYNCHSCOPE_CROSSTHREAD;
-  }
-  llvm_unreachable("Invalid synch scope");
-}
-
 static void WriteStringRecord(unsigned Code, StringRef Str,
                               unsigned AbbrevToUse, BitstreamWriter &Stream) {
   SmallVector<unsigned, 64> Vals;
@@ -1491,7 +1483,7 @@ static void WriteInstruction(const Instruction &I, unsigned InstID,
     Vals.push_back(cast<LoadInst>(I).isVolatile());
     if (cast<LoadInst>(I).isAtomic()) {
       Vals.push_back(GetEncodedOrdering(cast<LoadInst>(I).getOrdering()));
-      Vals.push_back(GetEncodedSynchScope(cast<LoadInst>(I).getSynchScope()));
+      Vals.push_back(cast<LoadInst>(I).getSynchScope());
     }
     break;
   case Instruction::Store:
@@ -1505,7 +1497,7 @@ static void WriteInstruction(const Instruction &I, unsigned InstID,
     Vals.push_back(cast<StoreInst>(I).isVolatile());
     if (cast<StoreInst>(I).isAtomic()) {
       Vals.push_back(GetEncodedOrdering(cast<StoreInst>(I).getOrdering()));
-      Vals.push_back(GetEncodedSynchScope(cast<StoreInst>(I).getSynchScope()));
+      Vals.push_back(cast<StoreInst>(I).getSynchScope());
     }
     break;
   case Instruction::AtomicCmpXchg:
@@ -1516,8 +1508,7 @@ static void WriteInstruction(const Instruction &I, unsigned InstID,
     Vals.push_back(cast<AtomicCmpXchgInst>(I).isVolatile());
     Vals.push_back(GetEncodedOrdering(
                      cast<AtomicCmpXchgInst>(I).getSuccessOrdering()));
-    Vals.push_back(GetEncodedSynchScope(
-                     cast<AtomicCmpXchgInst>(I).getSynchScope()));
+    Vals.push_back(cast<AtomicCmpXchgInst>(I).getSynchScope());
     Vals.push_back(GetEncodedOrdering(
                      cast<AtomicCmpXchgInst>(I).getFailureOrdering()));
     Vals.push_back(cast<AtomicCmpXchgInst>(I).isWeak());
@@ -1530,13 +1521,12 @@ static void WriteInstruction(const Instruction &I, unsigned InstID,
                      cast<AtomicRMWInst>(I).getOperation()));
     Vals.push_back(cast<AtomicRMWInst>(I).isVolatile());
     Vals.push_back(GetEncodedOrdering(cast<AtomicRMWInst>(I).getOrdering()));
-    Vals.push_back(GetEncodedSynchScope(
-                     cast<AtomicRMWInst>(I).getSynchScope()));
+    Vals.push_back(cast<AtomicRMWInst>(I).getSynchScope());
     break;
   case Instruction::Fence:
     Code = bitc::FUNC_CODE_INST_FENCE;
     Vals.push_back(GetEncodedOrdering(cast<FenceInst>(I).getOrdering()));
-    Vals.push_back(GetEncodedSynchScope(cast<FenceInst>(I).getSynchScope()));
+    Vals.push_back(cast<FenceInst>(I).getSynchScope());
     break;
   case Instruction::Call: {
     const CallInst &CI = cast<CallInst>(I);
-- 
1.9.1

-------------- next part --------------
From 4ee1228021a66b2d8044d83e17ead9b2b31c2f41 Mon Sep 17 00:00:00 2001
From: Sameer Sahasrabuddhe <sameer.sahasrabuddhe at amd.com>
Date: Wed, 10 Dec 2014 16:17:51 +0530
Subject: [PATCH 4/5] clients

Fix various places where the synchronization scope is exposed, such as
backends, language bindings, etc.

Needs more discussion.
---
 lib/IR/Core.cpp                                    |  8 ++++----
 lib/Target/CppBackend/CPPBackend.cpp               |  2 +-
 lib/Target/X86/X86ISelLowering.cpp                 |  5 ++---
 lib/Transforms/Instrumentation/ThreadSanitizer.cpp | 14 ++++++++++----
 4 files changed, 17 insertions(+), 12 deletions(-)

diff --git a/lib/IR/Core.cpp b/lib/IR/Core.cpp
index a25c4d6..dcafbc2 100644
--- a/lib/IR/Core.cpp
+++ b/lib/IR/Core.cpp
@@ -2481,10 +2481,10 @@ static AtomicOrdering mapFromLLVMOrdering(LLVMAtomicOrdering Ordering) {
 }
 
 LLVMValueRef LLVMBuildFence(LLVMBuilderRef B, LLVMAtomicOrdering Ordering,
-                            LLVMBool isSingleThread, const char *Name) {
+                            unsigned SynchScope, const char *Name) {
   return wrap(
     unwrap(B)->CreateFence(mapFromLLVMOrdering(Ordering),
-                           isSingleThread ? SingleThread : CrossThread,
+                           SynchScope,
                            Name));
 }
 
@@ -2730,7 +2730,7 @@ LLVMValueRef LLVMBuildPtrDiff(LLVMBuilderRef B, LLVMValueRef LHS,
 LLVMValueRef LLVMBuildAtomicRMW(LLVMBuilderRef B,LLVMAtomicRMWBinOp op,
                                LLVMValueRef PTR, LLVMValueRef Val,
                                LLVMAtomicOrdering ordering,
-                               LLVMBool singleThread) {
+                               unsigned SynchScope) {
   AtomicRMWInst::BinOp intop;
   switch (op) {
     case LLVMAtomicRMWBinOpXchg: intop = AtomicRMWInst::Xchg; break;
@@ -2746,7 +2746,7 @@ LLVMValueRef LLVMBuildAtomicRMW(LLVMBuilderRef B,LLVMAtomicRMWBinOp op,
     case LLVMAtomicRMWBinOpUMin: intop = AtomicRMWInst::UMin; break;
   }
   return wrap(unwrap(B)->CreateAtomicRMW(intop, unwrap(PTR), unwrap(Val),
-    mapFromLLVMOrdering(ordering), singleThread ? SingleThread : CrossThread));
+    mapFromLLVMOrdering(ordering), SynchScope));
 }
 
 
diff --git a/lib/Target/CppBackend/CPPBackend.cpp b/lib/Target/CppBackend/CPPBackend.cpp
index 300494c..48757ed 100644
--- a/lib/Target/CppBackend/CPPBackend.cpp
+++ b/lib/Target/CppBackend/CPPBackend.cpp
@@ -1105,7 +1105,7 @@ static StringRef ConvertAtomicSynchScope(unsigned SynchScope) {
     case SingleThread: return "SingleThread";
     case CrossThread: return "CrossThread";
   }
-  llvm_unreachable("Unknown synch scope");
+  return utostr(SynchScope);
 }
 
 // printInstruction - This member is called for each Instruction in a function.
diff --git a/lib/Target/X86/X86ISelLowering.cpp b/lib/Target/X86/X86ISelLowering.cpp
index 955cdce..7c64a76 100644
--- a/lib/Target/X86/X86ISelLowering.cpp
+++ b/lib/Target/X86/X86ISelLowering.cpp
@@ -18964,12 +18964,11 @@ static SDValue LowerATOMIC_FENCE(SDValue Op, const X86Subtarget *Subtarget,
   SDLoc dl(Op);
   AtomicOrdering FenceOrdering = static_cast<AtomicOrdering>(
     cast<ConstantSDNode>(Op.getOperand(1))->getZExtValue());
-  SynchronizationScope FenceScope = static_cast<SynchronizationScope>(
-    cast<ConstantSDNode>(Op.getOperand(2))->getZExtValue());
+  unsigned FenceScope = cast<ConstantSDNode>(Op.getOperand(2))->getZExtValue();
 
   // The only fence that needs an instruction is a sequentially-consistent
   // cross-thread fence.
-  if (FenceOrdering == SequentiallyConsistent && FenceScope == CrossThread) {
+  if (FenceOrdering == SequentiallyConsistent && FenceScope != SingleThread) {
     if (hasMFENCE(*Subtarget))
       return DAG.getNode(X86ISD::MFENCE, dl, MVT::Other, Op.getOperand(0));
 
diff --git a/lib/Transforms/Instrumentation/ThreadSanitizer.cpp b/lib/Transforms/Instrumentation/ThreadSanitizer.cpp
index 8a56a1f..4e0bf22 100644
--- a/lib/Transforms/Instrumentation/ThreadSanitizer.cpp
+++ b/lib/Transforms/Instrumentation/ThreadSanitizer.cpp
@@ -298,9 +298,9 @@ void ThreadSanitizer::chooseInstructionsToInstrument(
 
 static bool isAtomic(Instruction *I) {
   if (LoadInst *LI = dyn_cast<LoadInst>(I))
-    return LI->isAtomic() && LI->getSynchScope() == CrossThread;
+    return LI->isAtomic() && LI->getSynchScope() != SingleThread;
   if (StoreInst *SI = dyn_cast<StoreInst>(I))
-    return SI->isAtomic() && SI->getSynchScope() == CrossThread;
+    return SI->isAtomic() && SI->getSynchScope() != SingleThread;
   if (isa<AtomicRMWInst>(I))
     return true;
   if (isa<AtomicCmpXchgInst>(I))
@@ -539,8 +539,14 @@ bool ThreadSanitizer::instrumentAtomic(Instruction *I) {
     I->eraseFromParent();
   } else if (FenceInst *FI = dyn_cast<FenceInst>(I)) {
     Value *Args[] = {createOrdering(&IRB, FI->getOrdering())};
-    Function *F = FI->getSynchScope() == SingleThread ?
-        TsanAtomicSignalFence : TsanAtomicThreadFence;
+    unsigned SynchScope = FI->getSynchScope();
+    Function *F = NULL;
+    switch (SynchScope) {
+      case SingleThread: F = TsanAtomicSignalFence; break;
+      case CrossThread: F = TsanAtomicThreadFence; break;
+      default:
+        llvm_unreachable("unsupported synchronization scope");
+    }
     CallInst *C = CallInst::Create(F, Args);
     ReplaceInstWithInst(I, C);
   }
-- 
1.9.1

-------------- next part --------------
From afe5fe8273e7b70d316fbfe02b4b0de674b11857 Mon Sep 17 00:00:00 2001
From: Sameer Sahasrabuddhe <sameer.sahasrabuddhe at amd.com>
Date: Wed, 10 Dec 2014 16:03:40 +0530
Subject: [PATCH 5/5] assembly

Introduce new syntax in the assembly:
1. crossthread is default.
2. keyword 'singlethread' as before.
3. new syntax "synchscope(n)" for other scopes.
4. synchscope(0) is the same as crossthread.
---
 include/llvm/IR/Instructions.h |  4 ++--
 lib/AsmParser/LLLexer.cpp      |  1 +
 lib/AsmParser/LLParser.cpp     | 35 ++++++++++++++++++++++++++---------
 lib/AsmParser/LLParser.h       |  3 ++-
 lib/AsmParser/LLToken.h        |  1 +
 lib/IR/AsmWriter.cpp           | 23 +++++++++++++++--------
 test/Bitcode/synch_scope.ll    | 18 ++++++++++++++++++
 7 files changed, 65 insertions(+), 20 deletions(-)
 create mode 100644 test/Bitcode/synch_scope.ll

diff --git a/include/llvm/IR/Instructions.h b/include/llvm/IR/Instructions.h
index 9e25717..bb8f3a4 100644
--- a/include/llvm/IR/Instructions.h
+++ b/include/llvm/IR/Instructions.h
@@ -46,8 +46,8 @@ enum AtomicOrdering {
 };
 
 enum SynchronizationScope {
-  SingleThread = 0,
-  CrossThread = 1
+  CrossThread = 0,
+  SingleThread = ~0U
 };
 
 /// Returns true if the ordering is at least as strong as acquire
diff --git a/lib/AsmParser/LLLexer.cpp b/lib/AsmParser/LLLexer.cpp
index ca3c9e8..fc1f1fe 100644
--- a/lib/AsmParser/LLLexer.cpp
+++ b/lib/AsmParser/LLLexer.cpp
@@ -540,6 +540,7 @@ lltok::Kind LLLexer::LexIdentifier() {
   KEYWORD(acq_rel);
   KEYWORD(seq_cst);
   KEYWORD(singlethread);
+  KEYWORD(synchscope);
 
   KEYWORD(nnan);
   KEYWORD(ninf);
diff --git a/lib/AsmParser/LLParser.cpp b/lib/AsmParser/LLParser.cpp
index ca4ba6e..a6e5939 100644
--- a/lib/AsmParser/LLParser.cpp
+++ b/lib/AsmParser/LLParser.cpp
@@ -1617,20 +1617,37 @@ bool LLParser::ParseOptionalCommaAlign(unsigned &Alignment,
 }
 
 /// ParseScopeAndOrdering
-///   if isAtomic: ::= 'singlethread'? AtomicOrdering
+///   if isAtomic: ::= SynchronizationScope ? AtomicOrdering
 ///   else: ::=
 ///
 /// This sets Scope and Ordering to the parsed values.
-bool LLParser::ParseScopeAndOrdering(bool isAtomic, SynchronizationScope &Scope,
+bool LLParser::ParseScopeAndOrdering(bool isAtomic, unsigned &Scope,
                                      AtomicOrdering &Ordering) {
   if (!isAtomic)
     return false;
 
+  ParseOptionalSynchScope(Scope);
+
+  return ParseOrdering(Ordering);
+}
+
+/// ParseOptionalSynchScope
+///   := /*empty*/
+///   := 'singlethread'
+///   := 'synchscope' '(' uint32 ')'
+bool LLParser::ParseOptionalSynchScope(unsigned &Scope) {
   Scope = CrossThread;
-  if (EatIfPresent(lltok::kw_singlethread))
+
+  if (EatIfPresent(lltok::kw_singlethread)) {
     Scope = SingleThread;
+    return false;
+  }
 
-  return ParseOrdering(Ordering);
+  if (!EatIfPresent(lltok::kw_synchscope))
+    return false;
+  return ParseToken(lltok::lparen, "expected '(' in synchronization scope") ||
+         ParseUInt32(Scope) ||
+         ParseToken(lltok::rparen, "expected ')' in synchronization scope");
 }
 
 /// ParseOrdering
@@ -4384,7 +4401,7 @@ int LLParser::ParseLoad(Instruction *&Inst, PerFunctionState &PFS) {
   bool AteExtraComma = false;
   bool isAtomic = false;
   AtomicOrdering Ordering = NotAtomic;
-  SynchronizationScope Scope = CrossThread;
+  unsigned Scope = CrossThread;
 
   if (Lex.getKind() == lltok::kw_atomic) {
     isAtomic = true;
@@ -4425,7 +4442,7 @@ int LLParser::ParseStore(Instruction *&Inst, PerFunctionState &PFS) {
   bool AteExtraComma = false;
   bool isAtomic = false;
   AtomicOrdering Ordering = NotAtomic;
-  SynchronizationScope Scope = CrossThread;
+  unsigned Scope = CrossThread;
 
   if (Lex.getKind() == lltok::kw_atomic) {
     isAtomic = true;
@@ -4468,7 +4485,7 @@ int LLParser::ParseCmpXchg(Instruction *&Inst, PerFunctionState &PFS) {
   bool AteExtraComma = false;
   AtomicOrdering SuccessOrdering = NotAtomic;
   AtomicOrdering FailureOrdering = NotAtomic;
-  SynchronizationScope Scope = CrossThread;
+  unsigned Scope = CrossThread;
   bool isVolatile = false;
   bool isWeak = false;
 
@@ -4521,7 +4538,7 @@ int LLParser::ParseAtomicRMW(Instruction *&Inst, PerFunctionState &PFS) {
   Value *Ptr, *Val; LocTy PtrLoc, ValLoc;
   bool AteExtraComma = false;
   AtomicOrdering Ordering = NotAtomic;
-  SynchronizationScope Scope = CrossThread;
+  unsigned Scope = CrossThread;
   bool isVolatile = false;
   AtomicRMWInst::BinOp Operation;
 
@@ -4574,7 +4591,7 @@ int LLParser::ParseAtomicRMW(Instruction *&Inst, PerFunctionState &PFS) {
 ///   ::= 'fence' 'singlethread'? AtomicOrdering
 int LLParser::ParseFence(Instruction *&Inst, PerFunctionState &PFS) {
   AtomicOrdering Ordering = NotAtomic;
-  SynchronizationScope Scope = CrossThread;
+  unsigned Scope = CrossThread;
   if (ParseScopeAndOrdering(true /*Always atomic*/, Scope, Ordering))
     return true;
 
diff --git a/lib/AsmParser/LLParser.h b/lib/AsmParser/LLParser.h
index d32e58e..fd93b13 100644
--- a/lib/AsmParser/LLParser.h
+++ b/lib/AsmParser/LLParser.h
@@ -227,8 +227,9 @@ namespace llvm {
     bool ParseOptionalCallingConv(unsigned &CC);
     bool ParseOptionalAlignment(unsigned &Alignment);
     bool ParseOptionalDereferenceableBytes(uint64_t &Bytes);
-    bool ParseScopeAndOrdering(bool isAtomic, SynchronizationScope &Scope,
+    bool ParseScopeAndOrdering(bool isAtomic, unsigned &Scope,
                                AtomicOrdering &Ordering);
+    bool ParseOptionalSynchScope(unsigned &Scope);
     bool ParseOrdering(AtomicOrdering &Ordering);
     bool ParseOptionalStackAlignment(unsigned &Alignment);
     bool ParseOptionalCommaAlign(unsigned &Alignment, bool &AteExtraComma);
diff --git a/lib/AsmParser/LLToken.h b/lib/AsmParser/LLToken.h
index a2111ca..ff70e89 100644
--- a/lib/AsmParser/LLToken.h
+++ b/lib/AsmParser/LLToken.h
@@ -63,6 +63,7 @@ namespace lltok {
     kw_atomic,
     kw_unordered, kw_monotonic, kw_acquire, kw_release, kw_acq_rel, kw_seq_cst,
     kw_singlethread,
+    kw_synchscope,
     kw_nnan,
     kw_ninf,
     kw_nsz,
diff --git a/lib/IR/AsmWriter.cpp b/lib/IR/AsmWriter.cpp
index 69d6a97..9a9d97c 100644
--- a/lib/IR/AsmWriter.cpp
+++ b/lib/IR/AsmWriter.cpp
@@ -1431,15 +1431,25 @@ void AssemblyWriter::writeOperand(const Value *Operand, bool PrintType) {
   WriteAsOperandInternal(Out, Operand, &TypePrinter, &Machine, TheModule);
 }
 
+static void printSynchScope(unsigned SynchScope, raw_ostream &Out) {
+  switch (SynchScope) {
+  case CrossThread:
+    break;
+  case SingleThread:
+    Out << " singlethread";
+    break;
+  default:
+    Out << " synchscope(" << SynchScope << ")";
+    break;
+  }
+}
+
 void AssemblyWriter::writeAtomic(AtomicOrdering Ordering,
                                  unsigned SynchScope) {
   if (Ordering == NotAtomic)
     return;
 
-  switch (SynchScope) {
-  case SingleThread: Out << " singlethread"; break;
-  case CrossThread: break;
-  }
+  printSynchScope(SynchScope, Out);
 
   switch (Ordering) {
   default: Out << " <bad ordering " << int(Ordering) << ">"; break;
@@ -1457,10 +1467,7 @@ void AssemblyWriter::writeAtomicCmpXchg(AtomicOrdering SuccessOrdering,
                                         unsigned SynchScope) {
   assert(SuccessOrdering != NotAtomic && FailureOrdering != NotAtomic);
 
-  switch (SynchScope) {
-  case SingleThread: Out << " singlethread"; break;
-  case CrossThread: break;
-  }
+  printSynchScope(SynchScope, Out);
 
   switch (SuccessOrdering) {
   default: Out << " <bad ordering " << int(SuccessOrdering) << ">"; break;
diff --git a/test/Bitcode/synch_scope.ll b/test/Bitcode/synch_scope.ll
new file mode 100644
index 0000000..8be8c14
--- /dev/null
+++ b/test/Bitcode/synch_scope.ll
@@ -0,0 +1,18 @@
+; RUN: llvm-as < %s | llvm-dis | FileCheck %s
+
+define void @test(i32* %addr) {
+   cmpxchg i32* %addr, i32 42, i32 0 monotonic monotonic
+; CHECK: cmpxchg i32* %addr, i32 42, i32 0 monotonic monotonic
+
+   cmpxchg i32* %addr, i32 42, i32 0 singlethread monotonic monotonic
+; CHECK: cmpxchg i32* %addr, i32 42, i32 0 singlethread monotonic monotonic
+
+;  The explicit synchscope should be dropped.
+   cmpxchg i32* %addr, i32 42, i32 0 synchscope(0) monotonic monotonic
+; CHECK: cmpxchg i32* %addr, i32 42, i32 0 monotonic monotonic
+
+   cmpxchg i32* %addr, i32 42, i32 0 synchscope(42) monotonic monotonic
+; CHECK: cmpxchg i32* %addr, i32 42, i32 0 synchscope(42) monotonic monotonic
+
+   ret void
+}
-- 
1.9.1



More information about the llvm-dev mailing list