Skip to content

Commit cc2437d

Browse files
Artem Gindinsonvmaksimo
authored andcommitted
Instantiate atomic instructions via inheritance
The objective of this change is to reduce `OpCode`-based branching in the base class for atomic instructions, and to simplify specialization for ones that will be added in future. Signed-off-by: Artem Gindinson <[email protected]>
1 parent bcaa1ca commit cc2437d

File tree

1 file changed

+46
-38
lines changed

1 file changed

+46
-38
lines changed

llvm-spirv/lib/SPIRV/libSPIRV/SPIRVInstruction.h

Lines changed: 46 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -2721,51 +2721,55 @@ _SPIRV_OP(PowN, true, 10)
27212721

27222722
class SPIRVAtomicInstBase : public SPIRVInstTemplateBase {
27232723
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-
27302724
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
27362726
// 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 {};
27552736
}
27562737

27572738
// 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.
27602752
void setOpWords(const std::vector<SPIRVWord> &TheOps) override {
27612753
SPIRVInstTemplateBase::setOpWords(TheOps);
27622754
static const unsigned ValueOperandIndex = 3;
2763-
if (getOpCode() == OpAtomicStore &&
2764-
getOperand(ValueOperandIndex)->getType()->isTypeInt(64))
2755+
if (getOperand(ValueOperandIndex)->getType()->isTypeInt(64))
27652756
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};
27692773
}
27702774
};
27712775

@@ -2775,7 +2779,6 @@ class SPIRVAtomicInstBase : public SPIRVInstTemplateBase {
27752779
_SPIRV_OP(AtomicFlagTestAndSet, true, 6)
27762780
_SPIRV_OP(AtomicFlagClear, false, 4)
27772781
_SPIRV_OP(AtomicLoad, true, 6)
2778-
_SPIRV_OP(AtomicStore, false, 5)
27792782
_SPIRV_OP(AtomicExchange, true, 7)
27802783
_SPIRV_OP(AtomicCompareExchange, true, 9)
27812784
_SPIRV_OP(AtomicCompareExchangeWeak, true, 9)
@@ -2790,9 +2793,14 @@ _SPIRV_OP(AtomicSMax, true, 7)
27902793
_SPIRV_OP(AtomicAnd, true, 7)
27912794
_SPIRV_OP(AtomicOr, true, 7)
27922795
_SPIRV_OP(AtomicXor, true, 7)
2793-
_SPIRV_OP(AtomicFAddEXT, true, 7)
27942796
_SPIRV_OP(MemoryBarrier, false, 3)
27952797
#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
27962804

27972805
class SPIRVImageInstBase : public SPIRVInstTemplateBase {
27982806
public:

0 commit comments

Comments
 (0)