@@ -2721,51 +2721,55 @@ _SPIRV_OP(PowN, true, 10)
2721
2721
2722
2722
class SPIRVAtomicInstBase : public SPIRVInstTemplateBase {
2723
2723
public:
2724
- llvm::Optional<ExtensionID> getRequiredExtension () const override {
2725
- if (getOpCode () == OpAtomicFAddEXT)
2726
- return ExtensionID::SPV_EXT_shader_atomic_float_add;
2727
- return {};
2728
- }
2729
-
2730
2724
SPIRVCapVec getRequiredCapability () const override {
2731
- SPIRVCapVec CapVec;
2732
- if (!hasType ())
2733
- return CapVec;
2734
-
2735
- // Most atomic instructionsrequire a specific capability when
2725
+ // Most of the atomic instructions require a specific capability when
2736
2726
// operating on 64-bit integers.
2737
- if (getType ()->isTypeInt (64 )) {
2738
- // In SPIRV 1.2 spec only 2 atomic instructions have no result type:
2739
- // 1. OpAtomicStore - need to check type of the Value operand
2740
- // 2. OpAtomicFlagClear - doesn't require Int64Atomics capability.
2741
- CapVec.push_back (CapabilityInt64Atomics);
2742
- } else if (getOpCode () == OpAtomicFAddEXT) {
2743
- if (getType ()->isTypeFloat (32 ))
2744
- CapVec.push_back (CapabilityAtomicFloat32AddEXT);
2745
- else if (getType ()->isTypeFloat (64 ))
2746
- CapVec.push_back (CapabilityAtomicFloat64AddEXT);
2747
- else
2748
- llvm_unreachable (
2749
- " AtomicFAddEXT can only be generated for f32 or f64 types" );
2750
- }
2751
- // Per the spec OpAtomicCompareExchangeWeak, OpAtomicFlagTestAndSet and
2752
- // OpAtomicFlagClear instructions require kernel capability. But this
2753
- // capability should be added by setting OpenCL memory model.
2754
- return CapVec;
2727
+ // In SPIRV 1.2 spec, only 2 atomic instructions have no result type:
2728
+ // 1. OpAtomicStore - need to check type of the Value operand
2729
+ // 2. OpAtomicFlagClear - doesn't require Int64Atomics capability.
2730
+ // Besides, OpAtomicCompareExchangeWeak, OpAtomicFlagTestAndSet and
2731
+ // OpAtomicFlagClear instructions require the "kernel" capability. But this
2732
+ // capability should be added by setting the OpenCL memory model.
2733
+ if (hasType () && getType ()->isTypeInt (64 ))
2734
+ return {CapabilityInt64Atomics};
2735
+ return {};
2755
2736
}
2756
2737
2757
2738
// Overriding the following method because of particular OpAtomic*
2758
- // instructions. We may have to declare additional capabilities,
2759
- // e.g. based on operand types.
2739
+ // instructions that declare additional capabilities, e.g. based on operand
2740
+ // types.
2741
+ void setOpWords (const std::vector<SPIRVWord> &TheOps) override {
2742
+ SPIRVInstTemplateBase::setOpWords (TheOps);
2743
+ for (auto RC : getRequiredCapability ())
2744
+ Module->addCapability (RC);
2745
+ }
2746
+ };
2747
+
2748
+ class SPIRVAtomicStoreInst : public SPIRVAtomicInstBase {
2749
+ public:
2750
+ // Overriding the following method because of 'const'-related
2751
+ // issues with overriding getRequiredCapability(). TODO: Resolve.
2760
2752
void setOpWords (const std::vector<SPIRVWord> &TheOps) override {
2761
2753
SPIRVInstTemplateBase::setOpWords (TheOps);
2762
2754
static const unsigned ValueOperandIndex = 3 ;
2763
- if (getOpCode () == OpAtomicStore &&
2764
- getOperand (ValueOperandIndex)->getType ()->isTypeInt (64 ))
2755
+ if (getOperand (ValueOperandIndex)->getType ()->isTypeInt (64 ))
2765
2756
Module->addCapability (CapabilityInt64Atomics);
2766
- if (getOpCode () == OpAtomicFAddEXT)
2767
- for (auto RC : getRequiredCapability ())
2768
- Module->addCapability (RC);
2757
+ }
2758
+ };
2759
+
2760
+ class SPIRVAtomicFAddEXTInst : public SPIRVAtomicInstBase {
2761
+ public:
2762
+ llvm::Optional<ExtensionID> getRequiredExtension () const override {
2763
+ return ExtensionID::SPV_EXT_shader_atomic_float_add;
2764
+ }
2765
+
2766
+ SPIRVCapVec getRequiredCapability () const override {
2767
+ assert (hasType ());
2768
+ if (getType ()->isTypeFloat (32 ))
2769
+ return {CapabilityAtomicFloat32AddEXT};
2770
+ assert (getType ()->isTypeFloat (64 ) &&
2771
+ " AtomicFAddEXT can only be generated for f32 or f64 types" );
2772
+ return {CapabilityAtomicFloat64AddEXT};
2769
2773
}
2770
2774
};
2771
2775
@@ -2775,7 +2779,6 @@ class SPIRVAtomicInstBase : public SPIRVInstTemplateBase {
2775
2779
_SPIRV_OP (AtomicFlagTestAndSet, true , 6 )
2776
2780
_SPIRV_OP(AtomicFlagClear, false , 4 )
2777
2781
_SPIRV_OP(AtomicLoad, true , 6 )
2778
- _SPIRV_OP(AtomicStore, false , 5 )
2779
2782
_SPIRV_OP(AtomicExchange, true , 7 )
2780
2783
_SPIRV_OP(AtomicCompareExchange, true , 9 )
2781
2784
_SPIRV_OP(AtomicCompareExchangeWeak, true , 9 )
@@ -2790,9 +2793,14 @@ _SPIRV_OP(AtomicSMax, true, 7)
2790
2793
_SPIRV_OP(AtomicAnd, true , 7 )
2791
2794
_SPIRV_OP(AtomicOr, true , 7 )
2792
2795
_SPIRV_OP(AtomicXor, true , 7 )
2793
- _SPIRV_OP(AtomicFAddEXT, true , 7 )
2794
2796
_SPIRV_OP(MemoryBarrier, false , 3 )
2795
2797
#undef _SPIRV_OP
2798
+ #define _SPIRV_OP (x, BaseClass, ...) \
2799
+ typedef SPIRVInstTemplate<SPIRV##BaseClass, Op##x, __VA_ARGS__> SPIRV##x;
2800
+ // Specialized atomic builtins
2801
+ _SPIRV_OP (AtomicStore, AtomicStoreInst, false , 5 )
2802
+ _SPIRV_OP(AtomicFAddEXT, AtomicFAddEXTInst, true , 7 )
2803
+ #undef _SPIRV_OP
2796
2804
2797
2805
class SPIRVImageInstBase : public SPIRVInstTemplateBase {
2798
2806
public:
0 commit comments