Skip to content
This repository has been archived by the owner on Apr 23, 2020. It is now read-only.

Commit

Permalink
Enhance synchscope representation
Browse files Browse the repository at this point in the history
  OpenCL 2.0 introduces the notion of memory scopes in atomic operations to
  global and local memory. These scopes restrict how synchronization is
  achieved, which can result in improved performance.

  This change extends existing notion of synchronization scopes in LLVM to
  support arbitrary scopes expressed as target-specific strings, in addition to
  the already defined scopes (single thread, system).

  The LLVM IR and MIR syntax for expressing synchronization scopes has changed
  to use *syncscope("<scope>")*, where <scope> can be "singlethread" (this
  replaces *singlethread* keyword), or a target-specific name. As before, if
  the scope is not specified, it defaults to CrossThread/System scope.

  Implementation details:
    - Mapping from synchronization scope name/string to synchronization scope id
      is stored in LLVM context;
    - CrossThread/System and SingleThread scopes are pre-defined to efficiently
      check for known scopes without comparing strings;
    - Synchronization scope names are stored in SYNC_SCOPE_NAMES_BLOCK in
      the bitcode.

Differential Revision: https://reviews.llvm.org/D21723



git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@307722 91177308-0d34-0410-b5e6-96231b3b80d8
  • Loading branch information
kzhuravl committed Jul 11, 2017
1 parent fdda7ea commit 8f85685
Show file tree
Hide file tree
Showing 69 changed files with 1,227 additions and 791 deletions.
80 changes: 45 additions & 35 deletions docs/LangRef.rst
Original file line number Diff line number Diff line change
Expand Up @@ -2209,12 +2209,21 @@ For a simpler introduction to the ordering constraints, see the
same address in this global order. This corresponds to the C++0x/C1x
``memory_order_seq_cst`` and Java volatile.

.. _singlethread:
.. _syncscope:

If an atomic operation is marked ``singlethread``, it only *synchronizes
with* or participates in modification and seq\_cst total orderings with
other operations running in the same thread (for example, in signal
handlers).
If an atomic operation is marked ``syncscope("singlethread")``, it only
*synchronizes with* and only participates in the seq\_cst total orderings of
other operations running in the same thread (for example, in signal handlers).

If an atomic operation is marked ``syncscope("<target-scope>")``, where
``<target-scope>`` is a target specific synchronization scope, then it is target
dependent if it *synchronizes with* and participates in the seq\_cst total
orderings of other operations.

Otherwise, an atomic operation that is not marked ``syncscope("singlethread")``
or ``syncscope("<target-scope>")`` *synchronizes with* and participates in the
seq\_cst total orderings of other operations that are not marked
``syncscope("singlethread")`` or ``syncscope("<target-scope>")``.

.. _fastmath:

Expand Down Expand Up @@ -7380,7 +7389,7 @@ Syntax:
::

<result> = load [volatile] <ty>, <ty>* <pointer>[, align <alignment>][, !nontemporal !<index>][, !invariant.load !<index>][, !invariant.group !<index>][, !nonnull !<index>][, !dereferenceable !<deref_bytes_node>][, !dereferenceable_or_null !<deref_bytes_node>][, !align !<align_node>]
<result> = load atomic [volatile] <ty>, <ty>* <pointer> [singlethread] <ordering>, align <alignment> [, !invariant.group !<index>]
<result> = load atomic [volatile] <ty>, <ty>* <pointer> [syncscope("<target-scope>")] <ordering>, align <alignment> [, !invariant.group !<index>]
!<index> = !{ i32 1 }
!<deref_bytes_node> = !{i64 <dereferenceable_bytes>}
!<align_node> = !{ i64 <value_alignment> }
Expand All @@ -7401,14 +7410,14 @@ modify the number or order of 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, 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
<ordering>` and optional ``syncscope("<target-scope>")`` 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
Expand Down Expand Up @@ -7509,7 +7518,7 @@ Syntax:
::

store [volatile] <ty> <value>, <ty>* <pointer>[, align <alignment>][, !nontemporal !<index>][, !invariant.group !<index>] ; yields void
store atomic [volatile] <ty> <value>, <ty>* <pointer> [singlethread] <ordering>, align <alignment> [, !invariant.group !<index>] ; yields void
store atomic [volatile] <ty> <value>, <ty>* <pointer> [syncscope("<target-scope>")] <ordering>, align <alignment> [, !invariant.group !<index>] ; yields void

Overview:
"""""""""
Expand All @@ -7529,14 +7538,14 @@ allowed to modify the number or order of execution of this ``store`` with other
structural type <t_opaque>`) can be stored.

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
<ordering>` and optional ``syncscope("<target-scope>")`` 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
Expand Down Expand Up @@ -7597,7 +7606,7 @@ Syntax:

::

fence [singlethread] <ordering> ; yields void
fence [syncscope("<target-scope>")] <ordering> ; yields void

Overview:
"""""""""
Expand Down Expand Up @@ -7631,17 +7640,17 @@ A ``fence`` which has ``seq_cst`` ordering, in addition to having both
``acquire`` and ``release`` semantics specified above, participates in
the global program order of other ``seq_cst`` operations and/or fences.

The optional ":ref:`singlethread <singlethread>`" argument specifies
that the fence only synchronizes with other fences in the same thread.
(This is useful for interacting with signal handlers.)
A ``fence`` instruction can also take an optional
":ref:`syncscope <syncscope>`" argument.

Example:
""""""""

.. code-block:: llvm
fence acquire ; yields void
fence singlethread seq_cst ; yields void
fence acquire ; yields void
fence syncscope("singlethread") seq_cst ; yields void
fence syncscope("agent") seq_cst ; yields void
.. _i_cmpxchg:

Expand All @@ -7653,7 +7662,7 @@ Syntax:

::

cmpxchg [weak] [volatile] <ty>* <pointer>, <ty> <cmp>, <ty> <new> [singlethread] <success ordering> <failure ordering> ; yields { ty, i1 }
cmpxchg [weak] [volatile] <ty>* <pointer>, <ty> <cmp>, <ty> <new> [syncscope("<target-scope>")] <success ordering> <failure ordering> ; yields { ty, i1 }

Overview:
"""""""""
Expand Down Expand Up @@ -7682,10 +7691,8 @@ must be at least ``monotonic``, the ordering constraint on failure must be no
stronger than that on success, and the failure ordering cannot be either
``release`` or ``acq_rel``.

The optional "``singlethread``" argument declares that the ``cmpxchg``
is only atomic with respect to code (usually signal handlers) running in
the same thread as the ``cmpxchg``. Otherwise the cmpxchg is atomic with
respect to all other code in the system.
A ``cmpxchg`` instruction can also take an optional
":ref:`syncscope <syncscope>`" argument.

The pointer passed into cmpxchg must have alignment greater than or
equal to the size in memory of the operand.
Expand Down Expand Up @@ -7739,7 +7746,7 @@ Syntax:

::

atomicrmw [volatile] <operation> <ty>* <pointer>, <ty> <value> [singlethread] <ordering> ; yields ty
atomicrmw [volatile] <operation> <ty>* <pointer>, <ty> <value> [syncscope("<target-scope>")] <ordering> ; yields ty

Overview:
"""""""""
Expand Down Expand Up @@ -7773,6 +7780,9 @@ be a pointer to that type. If the ``atomicrmw`` is marked as
order of execution of this ``atomicrmw`` with other :ref:`volatile
operations <volatile>`.

A ``atomicrmw`` instruction can also take an optional
":ref:`syncscope <syncscope>`" argument.

Semantics:
""""""""""

Expand Down
12 changes: 6 additions & 6 deletions include/llvm/Bitcode/LLVMBitCodes.h
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,8 @@ enum BlockIDs {
FULL_LTO_GLOBALVAL_SUMMARY_BLOCK_ID,

SYMTAB_BLOCK_ID,

SYNC_SCOPE_NAMES_BLOCK_ID,
};

/// Identification block contains a string that describes the producer details,
Expand Down Expand Up @@ -172,6 +174,10 @@ enum OperandBundleTagCode {
OPERAND_BUNDLE_TAG = 1, // TAG: [strchr x N]
};

enum SyncScopeNameCode {
SYNC_SCOPE_NAME = 1,
};

// Value symbol table codes.
enum ValueSymtabCodes {
VST_CODE_ENTRY = 1, // VST_ENTRY: [valueid, namechar x N]
Expand Down Expand Up @@ -404,12 +410,6 @@ enum AtomicOrderingCodes {
ORDERING_SEQCST = 6
};

/// Encoded SynchronizationScope values.
enum AtomicSynchScopeCodes {
SYNCHSCOPE_SINGLETHREAD = 0,
SYNCHSCOPE_CROSSTHREAD = 1
};

/// Markers and flags for call instruction.
enum CallMarkersFlags {
CALL_TAIL = 0,
Expand Down
2 changes: 1 addition & 1 deletion include/llvm/CodeGen/MachineFunction.h
Original file line number Diff line number Diff line change
Expand Up @@ -650,7 +650,7 @@ class MachineFunction {
MachinePointerInfo PtrInfo, MachineMemOperand::Flags f, uint64_t s,
unsigned base_alignment, const AAMDNodes &AAInfo = AAMDNodes(),
const MDNode *Ranges = nullptr,
SynchronizationScope SynchScope = CrossThread,
SyncScope::ID SSID = SyncScope::System,
AtomicOrdering Ordering = AtomicOrdering::NotAtomic,
AtomicOrdering FailureOrdering = AtomicOrdering::NotAtomic);

Expand Down
12 changes: 6 additions & 6 deletions include/llvm/CodeGen/MachineMemOperand.h
Original file line number Diff line number Diff line change
Expand Up @@ -124,8 +124,8 @@ class MachineMemOperand {
private:
/// Atomic information for this memory operation.
struct MachineAtomicInfo {
/// Synchronization scope for this memory operation.
unsigned SynchScope : 1; // enum SynchronizationScope
/// Synchronization scope ID for this memory operation.
unsigned SSID : 8; // SyncScope::ID
/// Atomic ordering requirements for this memory operation. For cmpxchg
/// atomic operations, atomic ordering requirements when store occurs.
unsigned Ordering : 4; // enum AtomicOrdering
Expand All @@ -152,7 +152,7 @@ class MachineMemOperand {
unsigned base_alignment,
const AAMDNodes &AAInfo = AAMDNodes(),
const MDNode *Ranges = nullptr,
SynchronizationScope SynchScope = CrossThread,
SyncScope::ID SSID = SyncScope::System,
AtomicOrdering Ordering = AtomicOrdering::NotAtomic,
AtomicOrdering FailureOrdering = AtomicOrdering::NotAtomic);

Expand Down Expand Up @@ -202,9 +202,9 @@ class MachineMemOperand {
/// Return the range tag for the memory reference.
const MDNode *getRanges() const { return Ranges; }

/// Return the synchronization scope for this memory operation.
SynchronizationScope getSynchScope() const {
return static_cast<SynchronizationScope>(AtomicInfo.SynchScope);
/// Returns the synchronization scope ID for this memory operation.
SyncScope::ID getSyncScopeID() const {
return static_cast<SyncScope::ID>(AtomicInfo.SSID);
}

/// Return the atomic ordering requirements for this memory operation. For
Expand Down
4 changes: 2 additions & 2 deletions include/llvm/CodeGen/SelectionDAG.h
Original file line number Diff line number Diff line change
Expand Up @@ -927,7 +927,7 @@ class SelectionDAG {
SDValue Cmp, SDValue Swp, MachinePointerInfo PtrInfo,
unsigned Alignment, AtomicOrdering SuccessOrdering,
AtomicOrdering FailureOrdering,
SynchronizationScope SynchScope);
SyncScope::ID SSID);
SDValue getAtomicCmpSwap(unsigned Opcode, const SDLoc &dl, EVT MemVT,
SDVTList VTs, SDValue Chain, SDValue Ptr,
SDValue Cmp, SDValue Swp, MachineMemOperand *MMO);
Expand All @@ -937,7 +937,7 @@ class SelectionDAG {
SDValue getAtomic(unsigned Opcode, const SDLoc &dl, EVT MemVT, SDValue Chain,
SDValue Ptr, SDValue Val, const Value *PtrVal,
unsigned Alignment, AtomicOrdering Ordering,
SynchronizationScope SynchScope);
SyncScope::ID SSID);
SDValue getAtomic(unsigned Opcode, const SDLoc &dl, EVT MemVT, SDValue Chain,
SDValue Ptr, SDValue Val, MachineMemOperand *MMO);

Expand Down
4 changes: 2 additions & 2 deletions include/llvm/CodeGen/SelectionDAGNodes.h
Original file line number Diff line number Diff line change
Expand Up @@ -1213,8 +1213,8 @@ class MemSDNode : public SDNode {
/// Returns the Ranges that describes the dereference.
const MDNode *getRanges() const { return MMO->getRanges(); }

/// Return the synchronization scope for this memory operation.
SynchronizationScope getSynchScope() const { return MMO->getSynchScope(); }
/// Returns the synchronization scope ID for this memory operation.
SyncScope::ID getSyncScopeID() const { return MMO->getSyncScopeID(); }

/// Return the atomic ordering requirements for this memory operation. For
/// cmpxchg atomic operations, return the atomic ordering requirements when
Expand Down
12 changes: 6 additions & 6 deletions include/llvm/IR/IRBuilder.h
Original file line number Diff line number Diff line change
Expand Up @@ -1203,22 +1203,22 @@ class IRBuilder : public IRBuilderBase, public Inserter {
return SI;
}
FenceInst *CreateFence(AtomicOrdering Ordering,
SynchronizationScope SynchScope = CrossThread,
SyncScope::ID SSID = SyncScope::System,
const Twine &Name = "") {
return Insert(new FenceInst(Context, Ordering, SynchScope), Name);
return Insert(new FenceInst(Context, Ordering, SSID), Name);
}
AtomicCmpXchgInst *
CreateAtomicCmpXchg(Value *Ptr, Value *Cmp, Value *New,
AtomicOrdering SuccessOrdering,
AtomicOrdering FailureOrdering,
SynchronizationScope SynchScope = CrossThread) {
SyncScope::ID SSID = SyncScope::System) {
return Insert(new AtomicCmpXchgInst(Ptr, Cmp, New, SuccessOrdering,
FailureOrdering, SynchScope));
FailureOrdering, SSID));
}
AtomicRMWInst *CreateAtomicRMW(AtomicRMWInst::BinOp Op, Value *Ptr, Value *Val,
AtomicOrdering Ordering,
SynchronizationScope SynchScope = CrossThread) {
return Insert(new AtomicRMWInst(Op, Ptr, Val, Ordering, SynchScope));
SyncScope::ID SSID = SyncScope::System) {
return Insert(new AtomicRMWInst(Op, Ptr, Val, Ordering, SSID));
}
Value *CreateGEP(Value *Ptr, ArrayRef<Value *> IdxList,
const Twine &Name = "") {
Expand Down
Loading

0 comments on commit 8f85685

Please sign in to comment.