diff --git a/llvm/lib/Target/SPIRV/MCTargetDesc/SPIRVBaseInfo.h b/llvm/lib/Target/SPIRV/MCTargetDesc/SPIRVBaseInfo.h --- a/llvm/lib/Target/SPIRV/MCTargetDesc/SPIRVBaseInfo.h +++ b/llvm/lib/Target/SPIRV/MCTargetDesc/SPIRVBaseInfo.h @@ -223,6 +223,8 @@ CapabilityList getSymbolicOperandCapabilities(SPIRV::OperandCategory::OperandCategory Category, uint32_t Value); +CapabilityList +getCapabilitiesEnabledByExtension(SPIRV::Extension::Extension Extension); ExtensionList getSymbolicOperandExtensions(SPIRV::OperandCategory::OperandCategory Category, uint32_t Value); diff --git a/llvm/lib/Target/SPIRV/MCTargetDesc/SPIRVBaseInfo.cpp b/llvm/lib/Target/SPIRV/MCTargetDesc/SPIRVBaseInfo.cpp --- a/llvm/lib/Target/SPIRV/MCTargetDesc/SPIRVBaseInfo.cpp +++ b/llvm/lib/Target/SPIRV/MCTargetDesc/SPIRVBaseInfo.cpp @@ -129,6 +129,24 @@ return Capabilities; } +CapabilityList +getCapabilitiesEnabledByExtension(SPIRV::Extension::Extension Extension) { + const SPIRV::ExtensionEntry *Entry = + SPIRV::lookupSymbolicOperandsEnabledByExtension( + Extension, SPIRV::OperandCategory::CapabilityOperand); + + CapabilityList Capabilities; + while (Entry && + Entry->Category == SPIRV::OperandCategory::CapabilityOperand && + Entry->ReqExtension == Extension) { + Capabilities.push_back( + static_cast(Entry->Value)); + ++Entry; + } + + return Capabilities; +} + ExtensionList getSymbolicOperandExtensions(SPIRV::OperandCategory::OperandCategory Category, uint32_t Value) { diff --git a/llvm/lib/Target/SPIRV/SPIRVGlobalRegistry.cpp b/llvm/lib/Target/SPIRV/SPIRVGlobalRegistry.cpp --- a/llvm/lib/Target/SPIRV/SPIRVGlobalRegistry.cpp +++ b/llvm/lib/Target/SPIRV/SPIRVGlobalRegistry.cpp @@ -81,7 +81,15 @@ MachineIRBuilder &MIRBuilder, bool IsSigned) { assert(Width <= 64 && "Unsupported integer width!"); - if (Width <= 8) + const SPIRVSubtarget &ST = + cast(MIRBuilder.getMF().getSubtarget()); + if (ST.canUseExtension( + SPIRV::Extension::SPV_INTEL_arbitrary_precision_integers)) { + MIRBuilder.buildInstr(SPIRV::OpExtension) + .addImm(SPIRV::Extension::SPV_INTEL_arbitrary_precision_integers); + MIRBuilder.buildInstr(SPIRV::OpCapability) + .addImm(SPIRV::Capability::ArbitraryPrecisionIntegersINTEL); + } else if (Width <= 8) Width = 8; else if (Width <= 16) Width = 16; 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 @@ -574,9 +574,12 @@ // TODO: verify if this needs some checks. addAvailableCaps({Capability::Float16, Capability::Float64}); - // Add cap for SPV_INTEL_optnone. - // FIXME: this should be added only if the target has the extension. - addAvailableCaps({Capability::OptNoneINTEL}); + // Add capabilities enabled by extensions. + for (auto Extension : ST.getAllAvailableExtensions()) { + CapabilityList EnabledCapabilities = + getCapabilitiesEnabledByExtension(Extension); + addAvailableCaps(EnabledCapabilities); + } // TODO: add OpenCL extensions. } diff --git a/llvm/lib/Target/SPIRV/SPIRVSubtarget.h b/llvm/lib/Target/SPIRV/SPIRVSubtarget.h --- a/llvm/lib/Target/SPIRV/SPIRVSubtarget.h +++ b/llvm/lib/Target/SPIRV/SPIRVSubtarget.h @@ -86,6 +86,10 @@ // TODO: implement command line args or other ways to determine this. bool hasOpenCLFullProfile() const { return true; } bool hasOpenCLImageSupport() const { return true; } + const SmallSet & + getAllAvailableExtensions() const { + return AvailableExtensions; + } bool canUseExtension(SPIRV::Extension::Extension E) const; bool canUseExtInstSet(SPIRV::InstructionSet::InstructionSet E) const; @@ -113,6 +117,10 @@ const SPIRVRegisterInfo *getRegisterInfo() const override { return &InstrInfo.getRegisterInfo(); } + + static bool classof(const TargetSubtargetInfo *ST) { + return ST->getTargetTriple().isSPIRV(); + } }; } // namespace llvm 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 @@ -27,6 +27,21 @@ #define GET_SUBTARGETINFO_CTOR #include "SPIRVGenSubtargetInfo.inc" +cl::list Extensions( + "spirv-extensions", cl::desc("SPIR-V extensions"), cl::ZeroOrMore, + cl::Hidden, + cl::values( + clEnumValN(SPIRV::Extension::SPV_INTEL_arbitrary_precision_integers, + "SPV_INTEL_arbitrary_precision_integers", + "Allows generating arbitrary width integer types"), + clEnumValN(SPIRV::Extension::SPV_INTEL_optnone, "SPV_INTEL_optnone", + "Adds OptNoneINTEL value for Function Control mask that " + "indicates a request to not optimize the function"), + clEnumValN(SPIRV::Extension::SPV_KHR_no_integer_wrap_decoration, + "SPV_KHR_no_integer_wrap_decoration", + "Adds decorations to indicate that a given instruction does " + "not cause integer wrapping"))); + // Compare version numbers, but allow 0 to mean unspecified. static bool isAtLeastVer(uint32_t Target, uint32_t VerToCompareTo) { return Target == 0 || Target >= VerToCompareTo; @@ -100,17 +115,13 @@ return isAtLeastVer(SPIRVVersion, 14); } -// TODO: use command line args for this rather than defaults. void SPIRVSubtarget::initAvailableExtensions() { AvailableExtensions.clear(); if (!isOpenCLEnv()) return; - // A default extension for testing. - // FIXME: This should be changed when we can select extensions through a - // command line flag. - AvailableExtensions.insert( - SPIRV::Extension::SPV_KHR_no_integer_wrap_decoration); - AvailableExtensions.insert(SPIRV::Extension::SPV_INTEL_optnone); + + for (auto Extension : Extensions) + AvailableExtensions.insert(Extension); } // 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 @@ -77,6 +77,12 @@ let PrimaryKeyName = "lookupExtensionByCategoryAndValue"; } +// Function to lookup symbolic operands enabled by a given extension. +def lookupSymbolicOperandsEnabledByExtension : SearchIndex { + let Table = ExtensionEntries; + let Key = ["ReqExtension", "Category"]; +} + //===----------------------------------------------------------------------===// // Lookup table for matching symbolic operands (category + 32-bit value) to // SPIR-V capabilities. If an operand requires more than one capability, there @@ -243,7 +249,52 @@ defm SPV_INTEL_unstructured_loop_controls : ExtensionOperand<55>; defm SPV_EXT_demote_to_helper_invocation : ExtensionOperand<56>; defm SPV_INTEL_fpga_reg : ExtensionOperand<57>; -defm SPV_INTEL_optnone : ExtensionOperand<58>; +defm SPV_INTEL_blocking_pipes : ExtensionOperand<58>; +defm SPV_GOOGLE_user_type : ExtensionOperand<59>; +defm SPV_KHR_physical_storage_buffer : ExtensionOperand<60>; +defm SPV_INTEL_kernel_attributes : ExtensionOperand<61>; +defm SPV_KHR_non_semantic_info : ExtensionOperand<62>; +defm SPV_INTEL_io_pipes : ExtensionOperand<63>; +defm SPV_KHR_ray_tracing : ExtensionOperand<64>; +defm SPV_KHR_ray_query : ExtensionOperand<65>; +defm SPV_INTEL_fpga_memory_accesses : ExtensionOperand<66>; +defm SPV_INTEL_arbitrary_precision_integers : ExtensionOperand<67>; +defm SPV_EXT_shader_atomic_float_add : ExtensionOperand<68>; +defm SPV_KHR_terminate_invocation : ExtensionOperand<69>; +defm SPV_KHR_fragment_shading_rate : ExtensionOperand<70>; +defm SPV_EXT_shader_image_int64 : ExtensionOperand<71>; +defm SPV_INTEL_fp_fast_math_mode : ExtensionOperand<72>; +defm SPV_INTEL_fpga_cluster_attributes : ExtensionOperand<73>; +defm SPV_INTEL_loop_fuse : ExtensionOperand<74>; +defm SPV_EXT_shader_atomic_float_min_max : ExtensionOperand<75>; +defm SPV_KHR_workgroup_memory_explicit_layout : ExtensionOperand<76>; +defm SPV_KHR_linkonce_odr : ExtensionOperand<77>; +defm SPV_KHR_expect_assume : ExtensionOperand<78>; +defm SPV_INTEL_fpga_dsp_control : ExtensionOperand<79>; +defm SPV_NV_bindless_texture : ExtensionOperand<80>; +defm SPV_INTEL_fpga_invocation_pipelining_attributes : ExtensionOperand<81>; +defm SPV_KHR_subgroup_uniform_control_flow : ExtensionOperand<82>; +defm SPV_HUAWEI_subpass_shading : ExtensionOperand<83>; +defm SPV_KHR_integer_dot_product : ExtensionOperand<84>; +defm SPV_EXT_shader_atomic_float16_add : ExtensionOperand<85>; +defm SPV_INTEL_runtime_aligned : ExtensionOperand<86>; +defm SPV_KHR_bit_instructions : ExtensionOperand<87>; +defm SPV_NV_ray_tracing_motion_blur : ExtensionOperand<88>; +defm SPV_KHR_uniform_group_instructions : ExtensionOperand<89>; +defm SPV_KHR_subgroup_rotate : ExtensionOperand<90>; +defm SPV_INTEL_split_barrier : ExtensionOperand<91>; +defm SPV_KHR_ray_cull_mask : ExtensionOperand<92>; +defm SPV_KHR_fragment_shader_barycentric : ExtensionOperand<93>; +defm SPV_EXT_relaxed_printf_string_address_space : ExtensionOperand<94>; +defm SPV_EXT_ycbcr_attachments : ExtensionOperand<95>; +defm SPV_EXT_mesh_shader : ExtensionOperand<96>; +defm SPV_ARM_core_builtins : ExtensionOperand<97>; +defm SPV_EXT_opacity_micromap : ExtensionOperand<98>; +defm SPV_NV_shader_invocation_reorder : ExtensionOperand<99>; +defm SPV_INTEL_usm_storage_classes : ExtensionOperand<100>; +defm SPV_INTEL_fpga_latency_control : ExtensionOperand<101>; +defm SPV_INTEL_fpga_argument_interfaces : ExtensionOperand<102>; +defm SPV_INTEL_optnone : ExtensionOperand<103>; //===----------------------------------------------------------------------===// // Multiclass used to define Capabilities enum values and at the same time @@ -397,6 +448,7 @@ defm FragmentDensityEXT : CapabilityOperand<5291, 0, 0, [], [Shader]>; defm PhysicalStorageBufferAddressesEXT : CapabilityOperand<5347, 0, 0, [], [Shader]>; defm CooperativeMatrixNV : CapabilityOperand<5357, 0, 0, [], [Shader]>; +defm ArbitraryPrecisionIntegersINTEL : CapabilityOperand<5844, 0, 0, [SPV_INTEL_arbitrary_precision_integers], [Int8, Int16]>; defm OptNoneINTEL : CapabilityOperand<6094, 0, 0, [SPV_INTEL_optnone], []>; //===----------------------------------------------------------------------===// diff --git a/llvm/test/CodeGen/SPIRV/extensions/SPV_INTEL_arbitrary_precision_integers.ll b/llvm/test/CodeGen/SPIRV/extensions/SPV_INTEL_arbitrary_precision_integers.ll new file mode 100644 --- /dev/null +++ b/llvm/test/CodeGen/SPIRV/extensions/SPV_INTEL_arbitrary_precision_integers.ll @@ -0,0 +1,35 @@ +; RUN: llc -O0 -mtriple=spirv32-unknown-unknown --spirv-extensions=SPV_INTEL_arbitrary_precision_integers %s -o - | FileCheck %s + +define i6 @getConstantI6() { + ret i6 2 +} + +define i13 @getConstantI13() { + ret i13 42 +} + +;; Capabilities: +; CHECK-DAG: OpExtension "SPV_INTEL_arbitrary_precision_integers" +; CHECK-DAG: OpCapability ArbitraryPrecisionIntegersINTEL + +; CHECK-NOT: DAG-FENCE + +;; Names: +; CHECK-DAG: OpName %[[#GET_I6:]] "getConstantI6" +; CHECK-DAG: OpName %[[#GET_I13:]] "getConstantI13" + +; CHECK-NOT: DAG-FENCE + +;; Types and Constants: +; CHECK-DAG: %[[#I6:]] = OpTypeInt 6 0 +; CHECK-DAG: %[[#I13:]] = OpTypeInt 13 0 +; CHECK-DAG: %[[#CST_I6:]] = OpConstant %[[#I6]] 2 +; CHECK-DAG: %[[#CST_I13:]] = OpConstant %[[#I13]] 42 + +; CHECK: %[[#GET_I6]] = OpFunction %[[#I6]] +; CHECK: OpReturnValue %[[#CST_I6]] +; CHECK: OpFunctionEnd + +; CHECK: %[[#GET_I13]] = OpFunction %[[#I13]] +; CHECK: OpReturnValue %[[#CST_I13]] +; CHECK: OpFunctionEnd diff --git a/llvm/test/CodeGen/SPIRV/extensions/SPV_INTEL_optnone.ll b/llvm/test/CodeGen/SPIRV/extensions/SPV_INTEL_optnone.ll new file mode 100644 --- /dev/null +++ b/llvm/test/CodeGen/SPIRV/extensions/SPV_INTEL_optnone.ll @@ -0,0 +1,19 @@ +; RUN: llc -O0 -mtriple=spirv32-unknown-unknown --spirv-extensions=SPV_INTEL_optnone %s -o - | FileCheck %s --check-prefix=CHECK-EXTENSION +; RUN: llc -O0 -mtriple=spirv32-unknown-unknown %s -o - | FileCheck %s --check-prefix=CHECK-NO-EXTENSION + +; CHECK-EXTENSION: OpCapability OptNoneINTEL +; CHECK-EXTENSION: OpExtension "SPV_INTEL_optnone" +; CHECK-NO-EXTENSION-NOT: OpCapability OptNoneINTEL +; CHECK-NO-EXTENSION-NOT: OpExtension "SPV_INTEL_optnone" + +;; Per SPIR-V spec: +;; FunctionControlDontInlineMask = 0x2 (2) +; CHECK-EXTENSION: %[[#]] = OpFunction %[[#]] DontInline + +; Function Attrs: nounwind optnone noinline +define spir_func void @_Z3foov() #0 { +entry: + ret void +} + +attributes #0 = { nounwind optnone noinline } diff --git a/llvm/test/CodeGen/SPIRV/extensions/no_wrap.ll b/llvm/test/CodeGen/SPIRV/extensions/SPV_KHR_no_integer_wrap_decoration.ll rename from llvm/test/CodeGen/SPIRV/extensions/no_wrap.ll rename to llvm/test/CodeGen/SPIRV/extensions/SPV_KHR_no_integer_wrap_decoration.ll --- a/llvm/test/CodeGen/SPIRV/extensions/no_wrap.ll +++ b/llvm/test/CodeGen/SPIRV/extensions/SPV_KHR_no_integer_wrap_decoration.ll @@ -1,4 +1,4 @@ -; RUN: llc -O0 -mtriple=spirv32-unknown-unknown %s -o - | FileCheck %s +; RUN: llc -O0 -mtriple=spirv32-unknown-unknown --spirv-extensions=SPV_KHR_no_integer_wrap_decoration %s -o - | FileCheck %s ; CHECK-DAG: OpExtension "SPV_KHR_no_integer_wrap_decoration" diff --git a/llvm/test/CodeGen/SPIRV/optnone.ll b/llvm/test/CodeGen/SPIRV/optnone.ll deleted file mode 100644 --- a/llvm/test/CodeGen/SPIRV/optnone.ll +++ /dev/null @@ -1,17 +0,0 @@ -;; Check that optnone is correctly ignored when extension is not enabled -; RUN: llc -O0 -mtriple=spirv32-unknown-unknown %s -o - | FileCheck %s --check-prefix=CHECK-SPIRV - -; CHECK-SPIRV: OpCapability OptNoneINTEL -; CHECK-SPIRV: OpExtension "SPV_INTEL_optnone" - -;; Per SPIR-V spec: -;; FunctionControlDontInlineMask = 0x2 (2) -; CHECK-SPIRV: %[[#]] = OpFunction %[[#]] DontInline - -; Function Attrs: nounwind optnone noinline -define spir_func void @_Z3foov() #0 { -entry: - ret void -} - -attributes #0 = { nounwind optnone noinline } diff --git a/llvm/test/CodeGen/SPIRV/transcoding/NoSignedUnsignedWrap.ll b/llvm/test/CodeGen/SPIRV/transcoding/NoSignedUnsignedWrap.ll --- a/llvm/test/CodeGen/SPIRV/transcoding/NoSignedUnsignedWrap.ll +++ b/llvm/test/CodeGen/SPIRV/transcoding/NoSignedUnsignedWrap.ll @@ -7,7 +7,7 @@ ;; ;; Positive tests: ;; -; RUN: llc -O0 -mtriple=spirv32-unknown-unknown %s -o - | FileCheck %s --check-prefixes=CHECK-SPIRV,CHECK-SPIRV-NEGATIVE +; RUN: llc -O0 -mtriple=spirv32-unknown-unknown --spirv-extensions=SPV_KHR_no_integer_wrap_decoration %s -o - | FileCheck %s --check-prefixes=CHECK-SPIRV,CHECK-SPIRV-NEGATIVE ;; ;; Negative tests: ;;