diff --git a/llvm/lib/Target/SPIRV/SPIRVModuleAnalysis.h b/llvm/lib/Target/SPIRV/SPIRVModuleAnalysis.h --- a/llvm/lib/Target/SPIRV/SPIRVModuleAnalysis.h +++ b/llvm/lib/Target/SPIRV/SPIRVModuleAnalysis.h @@ -110,6 +110,10 @@ bool isCapabilityAvailable(Capability::Capability Cap) const { return AvailableCaps.contains(Cap); } + + // Remove capability ToRemove, but only if IfPresent is present. + void removeCapabilityIf(const Capability::Capability ToRemove, + const Capability::Capability IfPresent); }; using InstrList = SmallVector; diff --git a/llvm/lib/Target/SPIRV/SPIRVModuleAnalysis.cpp b/llvm/lib/Target/SPIRV/SPIRVModuleAnalysis.cpp --- a/llvm/lib/Target/SPIRV/SPIRVModuleAnalysis.cpp +++ b/llvm/lib/Target/SPIRV/SPIRVModuleAnalysis.cpp @@ -15,6 +15,8 @@ //===----------------------------------------------------------------------===// #include "SPIRVModuleAnalysis.h" +#include "MCTargetDesc/SPIRVBaseInfo.h" +#include "MCTargetDesc/SPIRVMCTargetDesc.h" #include "SPIRV.h" #include "SPIRVSubtarget.h" #include "SPIRVTargetMachine.h" @@ -513,6 +515,12 @@ SPIRV::OperandCategory::CapabilityOperand, Cap)); } +void SPIRV::RequirementHandler::removeCapabilityIf(const Capability::Capability ToRemove, + const Capability::Capability IfPresent) { + if (AvailableCaps.contains(IfPresent)) + AvailableCaps.erase(ToRemove); +} + namespace llvm { namespace SPIRV { void RequirementHandler::initAvailableCapabilities(const SPIRVSubtarget &ST) { @@ -554,8 +562,8 @@ // Add cap for SPV_INTEL_optnone. // FIXME: this should be added only if the target has the extension. - addAvailableCaps({Capability::OptNoneINTEL}); - + addAvailableCaps({Capability::OptNoneINTEL, + Capability::BitInstructions}); // TODO: add OpenCL extensions. } } // namespace SPIRV @@ -700,6 +708,12 @@ break; } case SPIRV::OpBitReverse: + case SPIRV::OpBitFieldInsert: + case SPIRV::OpBitFieldSExtract: + case SPIRV::OpBitFieldUExtract: + Reqs.addExtension(SPIRV::Extension::SPV_KHR_bit_instructions); + Reqs.addCapability(SPIRV::Capability::BitInstructions); + break; case SPIRV::OpTypeRuntimeArray: Reqs.addCapability(SPIRV::Capability::Shader); break; @@ -853,6 +867,12 @@ default: break; } + + // If we require capability Shader, then we can remove the requirement for + // the BitInstructions capability, since Shader is a superset capability + // of BitInstructions. + Reqs.removeCapabilityIf(SPIRV::Capability::Shader, + SPIRV::Capability::BitInstructions); } static void collectReqs(const Module &M, SPIRV::ModuleAnalysisInfo &MAI, diff --git a/llvm/lib/Target/SPIRV/SPIRVSubtarget.cpp b/llvm/lib/Target/SPIRV/SPIRVSubtarget.cpp --- a/llvm/lib/Target/SPIRV/SPIRVSubtarget.cpp +++ b/llvm/lib/Target/SPIRV/SPIRVSubtarget.cpp @@ -11,6 +11,7 @@ //===----------------------------------------------------------------------===// #include "SPIRVSubtarget.h" +#include "MCTargetDesc/SPIRVBaseInfo.h" #include "SPIRV.h" #include "SPIRVGlobalRegistry.h" #include "SPIRVLegalizerInfo.h" @@ -101,6 +102,7 @@ AvailableExtensions.insert( SPIRV::Extension::SPV_KHR_no_integer_wrap_decoration); AvailableExtensions.insert(SPIRV::Extension::SPV_INTEL_optnone); + AvailableExtensions.insert(SPIRV::Extension::SPV_KHR_bit_instructions); } // TODO: use command line args for this rather than just defaults. diff --git a/llvm/lib/Target/SPIRV/SPIRVSymbolicOperands.td b/llvm/lib/Target/SPIRV/SPIRVSymbolicOperands.td --- a/llvm/lib/Target/SPIRV/SPIRVSymbolicOperands.td +++ b/llvm/lib/Target/SPIRV/SPIRVSymbolicOperands.td @@ -244,6 +244,7 @@ defm SPV_EXT_demote_to_helper_invocation : ExtensionOperand<56>; defm SPV_INTEL_fpga_reg : ExtensionOperand<57>; defm SPV_INTEL_optnone : ExtensionOperand<58>; +defm SPV_KHR_bit_instructions : ExtensionOperand<59>; //===----------------------------------------------------------------------===// // Multiclass used to define Capabilities enum values and at the same time @@ -398,6 +399,7 @@ defm PhysicalStorageBufferAddressesEXT : CapabilityOperand<5347, 0, 0, [], [Shader]>; defm CooperativeMatrixNV : CapabilityOperand<5357, 0, 0, [], [Shader]>; defm OptNoneINTEL : CapabilityOperand<6094, 0, 0, [SPV_INTEL_optnone], []>; +defm BitInstructions : CapabilityOperand<6025, 0, 0, [SPV_KHR_bit_instructions], []>; //===----------------------------------------------------------------------===// // Multiclass used to define SourceLanguage enum values and at the same time diff --git a/llvm/test/CodeGen/SPIRV/transcoding/OpBitReverse_i32.ll b/llvm/test/CodeGen/SPIRV/transcoding/OpBitReverse_i32.ll --- a/llvm/test/CodeGen/SPIRV/transcoding/OpBitReverse_i32.ll +++ b/llvm/test/CodeGen/SPIRV/transcoding/OpBitReverse_i32.ll @@ -1,5 +1,8 @@ ; RUN: llc -O0 -mtriple=spirv32-unknown-unknown %s -o - | FileCheck %s --check-prefix=CHECK-SPIRV +; CHECK-SPIRV: OpCapability BitInstructions +; CHECK-SPIRV-NEXT: OpExtension "SPV_KHR_bit_instructions" + ; CHECK-SPIRV: %[[#int:]] = OpTypeInt 32 ; CHECK-SPIRV: OpBitReverse %[[#int]]