Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
67 changes: 67 additions & 0 deletions clang/lib/Sema/SPIRVBuiltins.td
Original file line number Diff line number Diff line change
Expand Up @@ -398,11 +398,14 @@ def AIGenTypeNNoScalar : GenericType<"AIGenTypeNNoScalar", TLAllInts, VecNoS
// All integer to unsigned
def AI2UGenTypeN : GenericType<"AI2UGenTypeN", TLAllUIntsTwice, VecAndScalar>;
// Signed integer
def SGenType1 : GenericType<"SGenType1", TLSignedInts, Vec1>;
def SGenTypeN : GenericType<"SGenTypeN", TLSignedInts, VecAndScalar>;
// Unsigned integer
def UGenType1 : GenericType<"UGenType1", TLUnsignedInts, Vec1>;
def UGenTypeN : GenericType<"UGenTypeN", TLUnsignedInts, VecAndScalar>;
def UInt4 : GenericType<"UInt4", TypeList<[UInt]>, Vec4>;
// Float
def FGenType1 : GenericType<"FGenType1", TLFloat, Vec1>;
def FGenTypeN : GenericType<"FGenTypeN", TLFloat, VecAndScalar>;
// (u)int, (u)long, and all floats
def IntLongFloatGenType1 : GenericType<"IntLongFloatGenType1", TLIntLongFloats, Vec1>;
Expand Down Expand Up @@ -1020,6 +1023,70 @@ foreach name = ["SubgroupBlockWriteINTEL"] in {
}
}

// 3.56.18. Atomic Instructions

foreach AS = [GlobalAS, LocalAS, PrivateAS, GenericAS] in {
def : SPVBuiltin<
"AtomicLoad", [AGenType1, PointerType<AGenType1, AS>, Int, Int],
Attr.Convergent>;

def : SPVBuiltin<"AtomicStore",
[Void, PointerType<AGenType1, AS>, Int, Int, AGenType1],
Attr.Convergent>;

def : SPVBuiltin<"AtomicExchange",
[AGenType1, PointerType<AGenType1, AS>, Int, Int, AGenType1],
Attr.Convergent>;

foreach name = ["AtomicCompareExchange", "AtomicCompareExchangeWeak"] in {
def : SPVBuiltin<name,
[AIGenType1, PointerType<AIGenType1, AS>, Int, Int, Int,
AIGenType1, AIGenType1],
Attr.Convergent>;
}

foreach name = ["AtomicIIncrement", "AtomicIDecrement"] in {
def : SPVBuiltin<name, [AIGenType1, PointerType<AIGenType1, AS>, Int, Int],
Attr.Convergent>;
}

foreach name = ["AtomicSMin", "AtomicSMax"] in {
def : SPVBuiltin<name,
[SGenType1, PointerType<SGenType1, AS>, Int, Int,
SGenType1],
Attr.Convergent>;
}

foreach name = ["AtomicUMin", "AtomicUMax"] in {
def : SPVBuiltin<name,
[UGenType1, PointerType<UGenType1, AS>, Int, Int,
UGenType1],
Attr.Convergent>;
}

foreach name = ["AtomicIAdd", "AtomicISub", "AtomicAnd", "AtomicOr",
"AtomicXor"] in {
def : SPVBuiltin<name,
[AIGenType1, PointerType<AIGenType1, AS>, Int, Int,
AIGenType1],
Attr.Convergent>;
}

def : SPVBuiltin<
"AtomicFlagTestAndSet", [Bool, PointerType<Int, AS>, Int, Int],
Attr.Convergent>;

def : SPVBuiltin<"AtomicFlagClear", [Void, PointerType<Int, AS>, Int, Int],
Attr.Convergent>;

foreach name = ["AtomicFMaxEXT", "AtomicFMinEXT", "AtomicFAddEXT"] in {
def : SPVBuiltin<name,
[FGenType1, PointerType<FGenType1, AS>, Int, Int,
FGenType1],
Attr.Convergent>;
}
}

// 3.56.24. Non-Uniform Instructions

foreach name = ["GroupNonUniformElect"] in {
Expand Down
237 changes: 237 additions & 0 deletions clang/test/CodeGenSPIRV/spirv-builtin-lookup-atomic.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,237 @@
// RUN: %clang_cc1 -triple spir64 -fdeclare-spirv-builtins -emit-llvm %s -o - | FileCheck %s

#define AS_GLOBAL __attribute__((opencl_global))
#define AS_LOCAL __attribute__((opencl_local))
#define AS_PRIVATE __attribute__((opencl_private))
#define AS_GENERIC __attribute__((opencl_generic))

void test_flag(int AS_GLOBAL *a, int AS_LOCAL *b, int AS_PRIVATE *c,
int AS_GENERIC *d) {
__spirv_AtomicFlagTestAndSet(a, 1, 16);
__spirv_AtomicFlagTestAndSet(b, 2, 8);
__spirv_AtomicFlagTestAndSet(c, 4, 4);
__spirv_AtomicFlagTestAndSet(d, 2, 0);

__spirv_AtomicFlagClear(a, 1, 16);
__spirv_AtomicFlagClear(b, 2, 4);
__spirv_AtomicFlagClear(c, 4, 0);
__spirv_AtomicFlagClear(d, 2, 0);
}

template <class T>
void test_signed(T AS_GLOBAL *a, T AS_LOCAL *b, T AS_PRIVATE *c,
T AS_GENERIC *d) {
__spirv_AtomicLoad(a, 1, 16);
__spirv_AtomicLoad(b, 2, 8);
__spirv_AtomicLoad(c, 4, 4);
__spirv_AtomicLoad(d, 2, 0);

__spirv_AtomicStore(a, 1, 16, (T)0);
__spirv_AtomicStore(b, 2, 8, (T)0);
__spirv_AtomicStore(c, 4, 4, (T)0);
__spirv_AtomicStore(d, 2, 0, (T)0);

__spirv_AtomicExchange(a, 1, 16, (T)0);
__spirv_AtomicExchange(b, 2, 8, (T)0);
__spirv_AtomicExchange(c, 4, 4, (T)0);
__spirv_AtomicExchange(d, 2, 0, (T)0);

__spirv_AtomicCompareExchange(a, 1, 16, 0, (T)1, (T)0);
__spirv_AtomicCompareExchange(b, 2, 8, 0, (T)1, (T)0);
__spirv_AtomicCompareExchange(c, 4, 4, 0, (T)1, (T)0);
__spirv_AtomicCompareExchange(d, 2, 0, 0, (T)1, (T)0);

__spirv_AtomicCompareExchangeWeak(a, 1, 16, 0, (T)1, (T)0);
__spirv_AtomicCompareExchangeWeak(b, 2, 8, 0, (T)1, (T)0);
__spirv_AtomicCompareExchangeWeak(c, 4, 4, 0, (T)1, (T)0);
__spirv_AtomicCompareExchangeWeak(d, 2, 0, 0, (T)1, (T)0);

__spirv_AtomicIIncrement(a, 1, 16);
__spirv_AtomicIIncrement(b, 2, 8);
__spirv_AtomicIIncrement(c, 4, 4);
__spirv_AtomicIIncrement(d, 2, 0);

__spirv_AtomicIDecrement(a, 1, 16);
__spirv_AtomicIDecrement(b, 2, 8);
__spirv_AtomicIDecrement(c, 4, 4);
__spirv_AtomicIDecrement(d, 2, 0);

__spirv_AtomicSMin(a, 1, 16, (T)0);
__spirv_AtomicSMin(b, 2, 8, (T)0);
__spirv_AtomicSMin(c, 4, 4, (T)0);
__spirv_AtomicSMin(d, 2, 0, (T)0);

__spirv_AtomicSMax(a, 1, 16, (T)0);
__spirv_AtomicSMax(b, 2, 8, (T)0);
__spirv_AtomicSMax(c, 4, 4, (T)0);
__spirv_AtomicSMax(d, 2, 0, (T)0);

__spirv_AtomicIAdd(a, 1, 16, (T)0);
__spirv_AtomicIAdd(b, 2, 8, (T)0);
__spirv_AtomicIAdd(c, 4, 4, (T)0);
__spirv_AtomicIAdd(d, 2, 0, (T)0);

__spirv_AtomicISub(a, 1, 16, (T)0);
__spirv_AtomicISub(b, 2, 8, (T)0);
__spirv_AtomicISub(c, 4, 4, (T)0);
__spirv_AtomicISub(d, 2, 0, (T)0);

__spirv_AtomicAnd(a, 1, 16, (T)0);
__spirv_AtomicAnd(b, 2, 8, (T)0);
__spirv_AtomicAnd(c, 4, 4, (T)0);
__spirv_AtomicAnd(d, 2, 0, (T)0);

__spirv_AtomicOr(a, 1, 16, (T)0);
__spirv_AtomicOr(b, 2, 8, (T)0);
__spirv_AtomicOr(c, 4, 4, (T)0);
__spirv_AtomicOr(d, 2, 0, (T)0);

__spirv_AtomicXor(a, 1, 16, (T)0);
__spirv_AtomicXor(b, 2, 8, (T)0);
__spirv_AtomicXor(c, 4, 4, (T)0);
__spirv_AtomicXor(d, 2, 0, (T)0);
}

template <class T>
void test_unsigned(T AS_GLOBAL *a, T AS_LOCAL *b, T AS_PRIVATE *c,
T AS_GENERIC *d) {

__spirv_AtomicUMin(a, 1, 16, (T)0);
__spirv_AtomicUMin(b, 2, 8, (T)0);
__spirv_AtomicUMin(c, 4, 4, (T)0);
__spirv_AtomicUMin(d, 2, 0, (T)0);

__spirv_AtomicUMax(a, 1, 16, (T)0);
__spirv_AtomicUMax(b, 2, 8, (T)0);
__spirv_AtomicUMax(c, 4, 4, (T)0);
__spirv_AtomicUMax(d, 2, 0, (T)0);
}

template <class T>
void test_float(T AS_GLOBAL *a, T AS_LOCAL *b, T AS_PRIVATE *c,
T AS_GENERIC *d) {
__spirv_AtomicFMaxEXT(a, 1, 16, (T)0);
__spirv_AtomicFMaxEXT(b, 2, 8, (T)0);
__spirv_AtomicFMaxEXT(c, 4, 4, (T)0);
__spirv_AtomicFMaxEXT(d, 2, 0, (T)0);

__spirv_AtomicFMinEXT(a, 1, 16, (T)0);
__spirv_AtomicFMinEXT(b, 2, 8, (T)0);
__spirv_AtomicFMinEXT(c, 4, 4, (T)0);
__spirv_AtomicFMinEXT(d, 2, 0, (T)0);

__spirv_AtomicFAddEXT(a, 1, 16, (T)0);
__spirv_AtomicFAddEXT(b, 2, 8, (T)0);
__spirv_AtomicFAddEXT(c, 4, 4, (T)0);
__spirv_AtomicFAddEXT(d, 2, 0, (T)0);
}

void foo() {
int AS_GLOBAL *a;
int AS_LOCAL *b;
int AS_PRIVATE *c;
int AS_GENERIC *d;
test_flag(a, b, c, d);

test_signed<int>(a, b, c, d);

unsigned int AS_GLOBAL *ua;
unsigned int AS_LOCAL *ub;
unsigned int AS_PRIVATE *uc;
unsigned int AS_GENERIC *ud;
test_unsigned<unsigned int>(ua, ub, uc, ud);

float AS_GLOBAL *fa;
float AS_LOCAL *fb;
float AS_PRIVATE *fc;
float AS_GENERIC *fd;
test_float<float>(fa, fb, fc, fd);
}

// CHECK: call spir_func noundef zeroext i1 @_Z28__spirv_AtomicFlagTestAndSetPU3AS1iii(
// CHECK: call spir_func noundef zeroext i1 @_Z28__spirv_AtomicFlagTestAndSetPU3AS3iii(
// CHECK: call spir_func noundef zeroext i1 @_Z28__spirv_AtomicFlagTestAndSetPiii(
// CHECK: call spir_func noundef zeroext i1 @_Z28__spirv_AtomicFlagTestAndSetPU3AS4iii(
// CHECK: call spir_func void @_Z23__spirv_AtomicFlagClearPU3AS1iii(
// CHECK: call spir_func void @_Z23__spirv_AtomicFlagClearPU3AS3iii(
// CHECK: call spir_func void @_Z23__spirv_AtomicFlagClearPiii(
// CHECK: call spir_func void @_Z23__spirv_AtomicFlagClearPU3AS4iii(

// CHECK: call spir_func noundef i32 @_Z18__spirv_AtomicLoadPU3AS1iii(
// CHECK: call spir_func noundef i32 @_Z18__spirv_AtomicLoadPU3AS3iii(
// CHECK: call spir_func noundef i32 @_Z18__spirv_AtomicLoadPiii(
// CHECK: call spir_func noundef i32 @_Z18__spirv_AtomicLoadPU3AS4iii(
// CHECK: call spir_func void @_Z19__spirv_AtomicStorePU3AS1iiii(
// CHECK: call spir_func void @_Z19__spirv_AtomicStorePU3AS3iiii(
// CHECK: call spir_func void @_Z19__spirv_AtomicStorePiiii(
// CHECK: call spir_func void @_Z19__spirv_AtomicStorePU3AS4iiii(
// CHECK: call spir_func noundef i32 @_Z22__spirv_AtomicExchangePU3AS1iiii(
// CHECK: call spir_func noundef i32 @_Z22__spirv_AtomicExchangePU3AS3iiii(
// CHECK: call spir_func noundef i32 @_Z22__spirv_AtomicExchangePiiii(
// CHECK: call spir_func noundef i32 @_Z22__spirv_AtomicExchangePU3AS4iiii(
// CHECK: call spir_func noundef i32 @_Z29__spirv_AtomicCompareExchangePU3AS1iiiiii(
// CHECK: call spir_func noundef i32 @_Z29__spirv_AtomicCompareExchangePU3AS3iiiiii(
// CHECK: call spir_func noundef i32 @_Z29__spirv_AtomicCompareExchangePiiiiii(
// CHECK: call spir_func noundef i32 @_Z29__spirv_AtomicCompareExchangePU3AS4iiiiii(
// CHECK: call spir_func noundef i32 @_Z33__spirv_AtomicCompareExchangeWeakPU3AS1iiiiii(
// CHECK: call spir_func noundef i32 @_Z33__spirv_AtomicCompareExchangeWeakPU3AS3iiiiii(
// CHECK: call spir_func noundef i32 @_Z33__spirv_AtomicCompareExchangeWeakPiiiiii(
// CHECK: call spir_func noundef i32 @_Z33__spirv_AtomicCompareExchangeWeakPU3AS4iiiiii(
// CHECK: call spir_func noundef i32 @_Z24__spirv_AtomicIIncrementPU3AS1iii(
// CHECK: call spir_func noundef i32 @_Z24__spirv_AtomicIIncrementPU3AS3iii(
// CHECK: call spir_func noundef i32 @_Z24__spirv_AtomicIIncrementPiii(
// CHECK: call spir_func noundef i32 @_Z24__spirv_AtomicIIncrementPU3AS4iii(
// CHECK: call spir_func noundef i32 @_Z24__spirv_AtomicIDecrementPU3AS1iii(
// CHECK: call spir_func noundef i32 @_Z24__spirv_AtomicIDecrementPU3AS3iii(
// CHECK: call spir_func noundef i32 @_Z24__spirv_AtomicIDecrementPiii(
// CHECK: call spir_func noundef i32 @_Z24__spirv_AtomicIDecrementPU3AS4iii(
// CHECK: call spir_func noundef i32 @_Z18__spirv_AtomicSMinPU3AS1iiii(
// CHECK: call spir_func noundef i32 @_Z18__spirv_AtomicSMinPU3AS3iiii(
// CHECK: call spir_func noundef i32 @_Z18__spirv_AtomicSMinPiiii(
// CHECK: call spir_func noundef i32 @_Z18__spirv_AtomicSMinPU3AS4iiii(
// CHECK: call spir_func noundef i32 @_Z18__spirv_AtomicSMaxPU3AS1iiii(
// CHECK: call spir_func noundef i32 @_Z18__spirv_AtomicSMaxPU3AS3iiii(
// CHECK: call spir_func noundef i32 @_Z18__spirv_AtomicSMaxPiiii(
// CHECK: call spir_func noundef i32 @_Z18__spirv_AtomicSMaxPU3AS4iiii(
// CHECK: call spir_func noundef i32 @_Z18__spirv_AtomicIAddPU3AS1iiii(
// CHECK: call spir_func noundef i32 @_Z18__spirv_AtomicIAddPU3AS3iiii(
// CHECK: call spir_func noundef i32 @_Z18__spirv_AtomicIAddPiiii(
// CHECK: call spir_func noundef i32 @_Z18__spirv_AtomicIAddPU3AS4iiii(
// CHECK: call spir_func noundef i32 @_Z18__spirv_AtomicISubPU3AS1iiii(
// CHECK: call spir_func noundef i32 @_Z18__spirv_AtomicISubPU3AS3iiii(
// CHECK: call spir_func noundef i32 @_Z18__spirv_AtomicISubPiiii(
// CHECK: call spir_func noundef i32 @_Z18__spirv_AtomicISubPU3AS4iiii(
// CHECK: call spir_func noundef i32 @_Z17__spirv_AtomicAndPU3AS1iiii(
// CHECK: call spir_func noundef i32 @_Z17__spirv_AtomicAndPU3AS3iiii(
// CHECK: call spir_func noundef i32 @_Z17__spirv_AtomicAndPiiii(
// CHECK: call spir_func noundef i32 @_Z17__spirv_AtomicAndPU3AS4iiii(
// CHECK: call spir_func noundef i32 @_Z16__spirv_AtomicOrPU3AS1iiii(
// CHECK: call spir_func noundef i32 @_Z16__spirv_AtomicOrPU3AS3iiii(
// CHECK: call spir_func noundef i32 @_Z16__spirv_AtomicOrPiiii(
// CHECK: call spir_func noundef i32 @_Z16__spirv_AtomicOrPU3AS4iiii(
// CHECK: call spir_func noundef i32 @_Z17__spirv_AtomicXorPU3AS1iiii(
// CHECK: call spir_func noundef i32 @_Z17__spirv_AtomicXorPU3AS3iiii(
// CHECK: call spir_func noundef i32 @_Z17__spirv_AtomicXorPiiii(
// CHECK: call spir_func noundef i32 @_Z17__spirv_AtomicXorPU3AS4iiii(

// CHECK: call spir_func noundef i32 @_Z18__spirv_AtomicUMinPU3AS1jiij(
// CHECK: call spir_func noundef i32 @_Z18__spirv_AtomicUMinPU3AS3jiij(
// CHECK: call spir_func noundef i32 @_Z18__spirv_AtomicUMinPjiij(
// CHECK: call spir_func noundef i32 @_Z18__spirv_AtomicUMinPU3AS4jiij(
// CHECK: call spir_func noundef i32 @_Z18__spirv_AtomicUMaxPU3AS1jiij(
// CHECK: call spir_func noundef i32 @_Z18__spirv_AtomicUMaxPU3AS3jiij(
// CHECK: call spir_func noundef i32 @_Z18__spirv_AtomicUMaxPjiij(
// CHECK: call spir_func noundef i32 @_Z18__spirv_AtomicUMaxPU3AS4jiij(

// CHECK: call spir_func noundef float @_Z21__spirv_AtomicFMaxEXTPU3AS1fiif(
// CHECK: call spir_func noundef float @_Z21__spirv_AtomicFMaxEXTPU3AS3fiif(
// CHECK: call spir_func noundef float @_Z21__spirv_AtomicFMaxEXTPfiif(
// CHECK: call spir_func noundef float @_Z21__spirv_AtomicFMaxEXTPU3AS4fiif(
// CHECK: call spir_func noundef float @_Z21__spirv_AtomicFMinEXTPU3AS1fiif(
// CHECK: call spir_func noundef float @_Z21__spirv_AtomicFMinEXTPU3AS3fiif(
// CHECK: call spir_func noundef float @_Z21__spirv_AtomicFMinEXTPfiif(
// CHECK: call spir_func noundef float @_Z21__spirv_AtomicFMinEXTPU3AS4fiif(
// CHECK: call spir_func noundef float @_Z21__spirv_AtomicFAddEXTPU3AS1fiif(
// CHECK: call spir_func noundef float @_Z21__spirv_AtomicFAddEXTPU3AS3fiif(
// CHECK: call spir_func noundef float @_Z21__spirv_AtomicFAddEXTPfiif(
// CHECK: call spir_func noundef float @_Z21__spirv_AtomicFAddEXTPU3AS4fiif(
18 changes: 8 additions & 10 deletions libclc/generic/lib/atomic/atomic_add.cl
Original file line number Diff line number Diff line change
@@ -1,16 +1,14 @@
#include <clc/clc.h>
#include <libspirv/spirv.h>

#define IMPL(TYPE, TYPE_MANGLED, AS, AS_MANGLED) \
_CLC_OVERLOAD _CLC_DEF TYPE atomic_add(volatile AS TYPE *p, TYPE val) { \
/* TODO: Stop manually mangling this name. Need C++ namespaces to get the \
* exact mangling. */ \
return _Z18__spirv_AtomicIAddPU3##AS_MANGLED##TYPE_MANGLED##N5__spv5Scope4FlagENS1_19MemorySemanticsMask4FlagE##TYPE_MANGLED( \
p, Device, SequentiallyConsistent, val); \
#define IMPL(TYPE, AS) \
_CLC_OVERLOAD _CLC_DEF TYPE atomic_add(volatile AS TYPE *p, TYPE val) { \
return __spirv_AtomicIAdd((AS TYPE *)p, Device, SequentiallyConsistent, \
val); \
}

IMPL(int, i, global, AS1)
IMPL(unsigned int, j, global, AS1)
IMPL(int, i, local, AS3)
IMPL(unsigned int, j, local, AS3)
IMPL(int, global)
IMPL(unsigned int, global)
IMPL(int, local)
IMPL(unsigned int, local)
#undef IMPL
18 changes: 8 additions & 10 deletions libclc/generic/lib/atomic/atomic_and.cl
Original file line number Diff line number Diff line change
@@ -1,16 +1,14 @@
#include <clc/clc.h>
#include <libspirv/spirv.h>

#define IMPL(TYPE, TYPE_MANGLED, AS, AS_MANGLED) \
_CLC_OVERLOAD _CLC_DEF TYPE atomic_and(volatile AS TYPE *p, TYPE val) { \
/* TODO: Stop manually mangling this name. Need C++ namespaces to get the \
* exact mangling. */ \
return _Z17__spirv_AtomicAndPU3##AS_MANGLED##TYPE_MANGLED##N5__spv5Scope4FlagENS1_19MemorySemanticsMask4FlagE##TYPE_MANGLED( \
p, Device, SequentiallyConsistent, val); \
#define IMPL(TYPE, AS) \
_CLC_OVERLOAD _CLC_DEF TYPE atomic_and(volatile AS TYPE *p, TYPE val) { \
return __spirv_AtomicAnd((AS TYPE *)p, Device, SequentiallyConsistent, \
val); \
}

IMPL(int, i, global, AS1)
IMPL(unsigned int, j, global, AS1)
IMPL(int, i, local, AS3)
IMPL(unsigned int, j, local, AS3)
IMPL(int, global)
IMPL(unsigned int, global)
IMPL(int, local)
IMPL(unsigned int, local)
#undef IMPL
Loading