summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlexey Sotkin <alexey.sotkin@intel.com>2018-02-06 22:08:41 +0300
committerYaxun (Sam) Liu <yaxun.liu@amd.com>2018-02-06 14:08:41 -0500
commit2bb7e2eaafef38229e21a10b4da9050dae194492 (patch)
tree2f747b7c2585035e7240e31c98b436c6d3abd004
parentd526f83cce796953e06f35c9be7f769bf44b1065 (diff)
[SPIRV] Fix capabilities for Atomic instructions (#227)
-rw-r--r--lib/SPIRV/libSPIRV/SPIRVInstruction.h26
-rw-r--r--test/AtomicCompareExchange_cl20.ll3
-rw-r--r--test/capability-Int64Atomics-store.ll38
-rw-r--r--test/capability-Int64Atomics.ll38
4 files changed, 103 insertions, 2 deletions
diff --git a/lib/SPIRV/libSPIRV/SPIRVInstruction.h b/lib/SPIRV/libSPIRV/SPIRVInstruction.h
index 7fb0758..ae5d778 100644
--- a/lib/SPIRV/libSPIRV/SPIRVInstruction.h
+++ b/lib/SPIRV/libSPIRV/SPIRVInstruction.h
@@ -2044,10 +2044,32 @@ _SPIRV_OP(GroupCommitReadPipe, false, 6)
_SPIRV_OP(GroupCommitWritePipe, false, 6)
#undef _SPIRV_OP
-class SPIRVAtomicInstBase:public SPIRVInstTemplateBase {
+class SPIRVAtomicInstBase : public SPIRVInstTemplateBase {
public:
SPIRVCapVec getRequiredCapability() const override {
- return getVec(CapabilityInt64Atomics);
+ SPIRVCapVec CapVec;
+ // Most of atomic instructions do not require any capabilities
+ // ... unless they operate on 64-bit integers.
+ if (hasType() && getType()->isTypeInt(64)) {
+ // In SPIRV 1.2 spec only 2 atomic instructions have no result type:
+ // 1. OpAtomicStore - need to check type of the Value operand
+ // 2. OpAtomicFlagClear - doesn't require Int64Atomics capability.
+ CapVec.push_back(CapabilityInt64Atomics);
+ }
+ // Per the spec OpAtomicCompareExchangeWeak, OpAtomicFlagTestAndSet and
+ // OpAtomicFlagClear instructions require kernel capability. But this
+ // capability should be added by setting OpenCL memory model.
+ return CapVec;
+ }
+
+ // Overriding the following method only because of OpAtomicStore.
+ // We have to declare Int64Atomics capability if the Value operand is int64.
+ void setOpWords(const std::vector<SPIRVWord> &TheOps) override {
+ SPIRVInstTemplateBase::setOpWords(TheOps);
+ static const unsigned ValueOperandIndex = 3;
+ if (getOpCode() == OpAtomicStore &&
+ getOperand(ValueOperandIndex)->getType()->isTypeInt(64))
+ Module->addCapability(CapabilityInt64Atomics);
}
};
diff --git a/test/AtomicCompareExchange_cl20.ll b/test/AtomicCompareExchange_cl20.ll
index be6a85a..3dc4f39 100644
--- a/test/AtomicCompareExchange_cl20.ll
+++ b/test/AtomicCompareExchange_cl20.ll
@@ -5,6 +5,9 @@ target triple = "spir-unknown-unknown"
; CHECK: 3 Source 3 200000
+; Int64Atomics capability must be declared only if atomic builtins have 64-bit integers arguments.
+; CHECK-NOT: Capability Int64Atomics
+
; CHECK: Name [[Pointer:[0-9]+]] "object"
; CHECK: Name [[ComparatorPtr:[0-9]+]] "expected"
; CHECK: Name [[Value:[0-9]+]] "desired"
diff --git a/test/capability-Int64Atomics-store.ll b/test/capability-Int64Atomics-store.ll
new file mode 100644
index 0000000..4bceae4
--- /dev/null
+++ b/test/capability-Int64Atomics-store.ll
@@ -0,0 +1,38 @@
+; OpenCL C source:
+; #pragma OPENCL EXTENSION cl_khr_int64_base_atomics : enable
+; #pragma OPENCL EXTENSION cl_khr_int64_extended_atomics : enable
+;
+; void foo (volatile atomic_long *object, long desired) {
+; atomic_store(object, desired);
+;}
+
+; RUN: llvm-as < %s | llvm-spirv -spirv-text -o - | FileCheck %s
+
+; CHECK: Capability Int64Atomics
+
+target datalayout = "e-i64:64-v16:16-v24:32-v32:32-v48:64-v96:128-v192:256-v256:256-v512:512-v1024:1024-n8:16:32:64"
+target triple = "spir64"
+
+; Function Attrs: nounwind
+define spir_func void @foo(i64 addrspace(4)* %object, i64 %desired) #0 {
+entry:
+ tail call spir_func void @_Z12atomic_storePVU3AS4U7_Atomicll(i64 addrspace(4)* %object, i64 %desired) #2
+ ret void
+}
+
+declare spir_func void @_Z12atomic_storePVU3AS4U7_Atomicll(i64 addrspace(4)*, i64) #1
+
+attributes #0 = { nounwind "less-precise-fpmad"="false" "no-frame-pointer-elim"="false" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "no-realign-stack" "stack-protector-buffer-size"="8" "unsafe-fp-math"="false" "use-soft-float"="false" }
+attributes #1 = { "less-precise-fpmad"="false" "no-frame-pointer-elim"="false" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "no-realign-stack" "stack-protector-buffer-size"="8" "unsafe-fp-math"="false" "use-soft-float"="false" }
+attributes #2 = { nounwind }
+
+!opencl.enable.FP_CONTRACT = !{}
+!opencl.spir.version = !{!0}
+!opencl.ocl.version = !{!1}
+!opencl.used.extensions = !{!2}
+!opencl.used.optional.core.features = !{!2}
+!opencl.compiler.options = !{!2}
+
+!0 = !{i32 1, i32 2}
+!1 = !{i32 2, i32 0}
+!2 = !{}
diff --git a/test/capability-Int64Atomics.ll b/test/capability-Int64Atomics.ll
new file mode 100644
index 0000000..7152b89
--- /dev/null
+++ b/test/capability-Int64Atomics.ll
@@ -0,0 +1,38 @@
+; OpenCL C source:
+; #pragma OPENCL EXTENSION cl_khr_int64_base_atomics : enable
+; #pragma OPENCL EXTENSION cl_khr_int64_extended_atomics : enable
+;
+; void foo (volatile atomic_long *object, long desired) {
+; atomic_fetch_xor(object, desired);
+;}
+
+; RUN: llvm-as < %s | llvm-spirv -spirv-text -o - | FileCheck %s
+
+; CHECK: Capability Int64Atomics
+
+target datalayout = "e-i64:64-v16:16-v24:32-v32:32-v48:64-v96:128-v192:256-v256:256-v512:512-v1024:1024-n8:16:32:64"
+target triple = "spir64"
+
+; Function Attrs: nounwind
+define spir_func void @foo(i64 addrspace(4)* %object, i64 %desired) #0 {
+entry:
+ %call = tail call spir_func i64 @_Z16atomic_fetch_xorPVU3AS4U7_Atomicll(i64 addrspace(4)* %object, i64 %desired) #2
+ ret void
+}
+
+declare spir_func i64 @_Z16atomic_fetch_xorPVU3AS4U7_Atomicll(i64 addrspace(4)*, i64) #1
+
+attributes #0 = { nounwind "less-precise-fpmad"="false" "no-frame-pointer-elim"="false" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "no-realign-stack" "stack-protector-buffer-size"="8" "unsafe-fp-math"="false" "use-soft-float"="false" }
+attributes #1 = { "less-precise-fpmad"="false" "no-frame-pointer-elim"="false" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "no-realign-stack" "stack-protector-buffer-size"="8" "unsafe-fp-math"="false" "use-soft-float"="false" }
+attributes #2 = { nounwind }
+
+!opencl.enable.FP_CONTRACT = !{}
+!opencl.spir.version = !{!0}
+!opencl.ocl.version = !{!1}
+!opencl.used.extensions = !{!2}
+!opencl.used.optional.core.features = !{!2}
+!opencl.compiler.options = !{!2}
+
+!0 = !{i32 1, i32 2}
+!1 = !{i32 2, i32 0}
+!2 = !{}