diff --git a/llvm/lib/Target/SPIRV/SPIRVBuiltins.cpp b/llvm/lib/Target/SPIRV/SPIRVBuiltins.cpp index f704d3afdea78..28044f6f03550 100644 --- a/llvm/lib/Target/SPIRV/SPIRVBuiltins.cpp +++ b/llvm/lib/Target/SPIRV/SPIRVBuiltins.cpp @@ -1078,6 +1078,23 @@ static bool buildTernaryBitwiseFunctionINTELInst( return true; } +static bool buildImageChannelDataTypeInst(const SPIRV::IncomingCall *Call, + unsigned Opcode, + MachineIRBuilder &MIRBuilder, + SPIRVGlobalRegistry *GR) { + if (Call->isSpirvOp()) + return buildOpFromWrapper(MIRBuilder, Opcode, Call, + GR->getSPIRVTypeID(Call->ReturnType)); + + auto MIB = MIRBuilder.buildInstr(Opcode) + .addDef(Call->ReturnRegister) + .addUse(GR->getSPIRVTypeID(Call->ReturnType)); + for (unsigned i = 0; i < Call->Arguments.size(); ++i) + MIB.addUse(Call->Arguments[i]); + + return true; +} + /// Helper function for building Intel's 2d block io instructions. static bool build2DBlockIOINTELInst(const SPIRV::IncomingCall *Call, unsigned Opcode, @@ -2374,6 +2391,16 @@ generateTernaryBitwiseFunctionINTELInst(const SPIRV::IncomingCall *Call, return buildTernaryBitwiseFunctionINTELInst(Call, Opcode, MIRBuilder, GR); } +static bool generateImageChannelDataTypeInst(const SPIRV::IncomingCall *Call, + MachineIRBuilder &MIRBuilder, + SPIRVGlobalRegistry *GR) { + const SPIRV::DemangledBuiltin *Builtin = Call->Builtin; + unsigned Opcode = + SPIRV::lookupNativeBuiltin(Builtin->Name, Builtin->Set)->Opcode; + + return buildImageChannelDataTypeInst(Call, Opcode, MIRBuilder, GR); +} + static bool generate2DBlockIOINTELInst(const SPIRV::IncomingCall *Call, MachineIRBuilder &MIRBuilder, SPIRVGlobalRegistry *GR) { @@ -2999,6 +3026,8 @@ std::optional lowerBuiltin(const StringRef DemangledCall, return generate2DBlockIOINTELInst(Call.get(), MIRBuilder, GR); case SPIRV::Pipe: return generatePipeInst(Call.get(), MIRBuilder, GR); + case SPIRV::ImageChannelDataTypes: + return generateImageChannelDataTypeInst(Call.get(), MIRBuilder, GR); } return false; } diff --git a/llvm/lib/Target/SPIRV/SPIRVBuiltins.td b/llvm/lib/Target/SPIRV/SPIRVBuiltins.td index 2a8deb6bf498b..390e4724cc916 100644 --- a/llvm/lib/Target/SPIRV/SPIRVBuiltins.td +++ b/llvm/lib/Target/SPIRV/SPIRVBuiltins.td @@ -70,6 +70,7 @@ def BindlessINTEL : BuiltinGroup; def TernaryBitwiseINTEL : BuiltinGroup; def Block2DLoadStore : BuiltinGroup; def Pipe : BuiltinGroup; +def ImageChannelDataTypes : BuiltinGroup; //===----------------------------------------------------------------------===// // Class defining a demangled builtin record. The information in the record @@ -1469,6 +1470,7 @@ defm : DemangledImageQueryBuiltin<"get_image_array_size", OpenCL_std, 3>; defm : DemangledNativeBuiltin<"get_image_num_samples", OpenCL_std, ImageMiscQuery, 1, 1, OpImageQuerySamples>; defm : DemangledNativeBuiltin<"get_image_num_mip_levels", OpenCL_std, ImageMiscQuery, 1, 1, OpImageQueryLevels>; +defm : DemangledNativeBuiltin<"get_image_channel_data_type", OpenCL_std, ImageChannelDataTypes, 1, 1, OpImageQueryFormat>; //===----------------------------------------------------------------------===// // Class defining a "convert_destType<_sat><_roundingMode>" call record for diff --git a/llvm/lib/Target/SPIRV/SPIRVCommandLine.cpp b/llvm/lib/Target/SPIRV/SPIRVCommandLine.cpp index 85ea9e156cb97..d8d08b2c58eb0 100644 --- a/llvm/lib/Target/SPIRV/SPIRVCommandLine.cpp +++ b/llvm/lib/Target/SPIRV/SPIRVCommandLine.cpp @@ -151,7 +151,9 @@ static const std::map> {"SPV_KHR_bfloat16", SPIRV::Extension::Extension::SPV_KHR_bfloat16}, {"SPV_EXT_relaxed_printf_string_address_space", SPIRV::Extension::Extension:: - SPV_EXT_relaxed_printf_string_address_space}}; + SPV_EXT_relaxed_printf_string_address_space}, + {"SPV_EXT_image_raw10_raw12", + SPIRV::Extension::Extension::SPV_EXT_image_raw10_raw12}}; bool SPIRVExtensionsParser::parse(cl::Option &O, StringRef ArgName, StringRef ArgValue, diff --git a/llvm/lib/Target/SPIRV/SPIRVModuleAnalysis.cpp b/llvm/lib/Target/SPIRV/SPIRVModuleAnalysis.cpp index bc159d5c9a113..3a97bd856ce81 100644 --- a/llvm/lib/Target/SPIRV/SPIRVModuleAnalysis.cpp +++ b/llvm/lib/Target/SPIRV/SPIRVModuleAnalysis.cpp @@ -1489,6 +1489,48 @@ void addInstrRequirements(const MachineInstr &MI, } break; } + case SPIRV::OpImageQueryFormat: { + Register ResultReg = MI.getOperand(0).getReg(); + const MachineRegisterInfo &MRI = MI.getMF()->getRegInfo(); + static const unsigned CompareOps[] = { + SPIRV::OpIEqual, SPIRV::OpINotEqual, + SPIRV::OpUGreaterThan, SPIRV::OpUGreaterThanEqual, + SPIRV::OpULessThan, SPIRV::OpULessThanEqual, + SPIRV::OpSGreaterThan, SPIRV::OpSGreaterThanEqual, + SPIRV::OpSLessThan, SPIRV::OpSLessThanEqual}; + + auto CheckAndAddExtension = [&](int64_t ImmVal) { + if (ImmVal == 4323 || ImmVal == 4324) { + if (ST.canUseExtension(SPIRV::Extension::SPV_EXT_image_raw10_raw12)) + Reqs.addExtension(SPIRV::Extension::SPV_EXT_image_raw10_raw12); + else + report_fatal_error("This requires the " + "SPV_EXT_image_raw10_raw12 extension"); + } + }; + + for (MachineInstr &UseInst : MRI.use_instructions(ResultReg)) { + unsigned Opc = UseInst.getOpcode(); + + if (Opc == SPIRV::OpSwitch) { + for (const MachineOperand &Op : UseInst.operands()) + if (Op.isImm()) + CheckAndAddExtension(Op.getImm()); + } else if (llvm::is_contained(CompareOps, Opc)) { + for (unsigned i = 1; i < UseInst.getNumOperands(); ++i) { + Register UseReg = UseInst.getOperand(i).getReg(); + MachineInstr *ConstInst = MRI.getVRegDef(UseReg); + if (ConstInst && ConstInst->getOpcode() == SPIRV::OpConstantI) { + int64_t ImmVal = ConstInst->getOperand(2).getImm(); + if (ImmVal) + CheckAndAddExtension(ImmVal); + } + } + } + } + break; + } + case SPIRV::OpGroupNonUniformShuffle: case SPIRV::OpGroupNonUniformShuffleXor: Reqs.addCapability(SPIRV::Capability::GroupNonUniformShuffle); diff --git a/llvm/lib/Target/SPIRV/SPIRVSymbolicOperands.td b/llvm/lib/Target/SPIRV/SPIRVSymbolicOperands.td index 66ce5a2d67c3e..0761e047dfbc3 100644 --- a/llvm/lib/Target/SPIRV/SPIRVSymbolicOperands.td +++ b/llvm/lib/Target/SPIRV/SPIRVSymbolicOperands.td @@ -385,6 +385,7 @@ defm SPV_INTEL_int4 : ExtensionOperand<123, [EnvOpenCL]>; defm SPV_KHR_float_controls2 : ExtensionOperand<124, [EnvVulkan, EnvOpenCL]>; defm SPV_INTEL_tensor_float32_conversion : ExtensionOperand<125, [EnvOpenCL]>; defm SPV_KHR_bfloat16 : ExtensionOperand<126, [EnvVulkan, EnvOpenCL]>; +defm SPV_EXT_image_raw10_raw12 :ExtensionOperand<127, [EnvOpenCL]>; //===----------------------------------------------------------------------===// // Multiclass used to define Capabilities enum values and at the same time @@ -1084,6 +1085,8 @@ defm HalfFloat : ImageChannelDataTypeOperand<13, [Kernel]>; defm Float : ImageChannelDataTypeOperand<14, [Kernel]>; defm UnormInt24 : ImageChannelDataTypeOperand<15, [Kernel]>; defm UnormInt101010_2 : ImageChannelDataTypeOperand<16, [Kernel]>; +defm UnsignedIntRaw10EXT : ImageChannelDataTypeOperand<17, [Kernel]>; +defm UnsignedIntRaw12EXT : ImageChannelDataTypeOperand<18, [Kernel]>; //===----------------------------------------------------------------------===// // Multiclass used to define ImageOperand enum values and at the same time diff --git a/llvm/test/CodeGen/SPIRV/extensions/SPV_EXT_image_raw10_raw12/constant_use.ll b/llvm/test/CodeGen/SPIRV/extensions/SPV_EXT_image_raw10_raw12/constant_use.ll new file mode 100644 index 0000000000000..680a74f89b1d9 --- /dev/null +++ b/llvm/test/CodeGen/SPIRV/extensions/SPV_EXT_image_raw10_raw12/constant_use.ll @@ -0,0 +1,32 @@ +; RUN: llc -verify-machineinstrs -O0 -mtriple=spirv32-unknown-unknown --spirv-ext=+SPV_EXT_image_raw10_raw12 %s -o - | FileCheck %s +; RUN: %if spirv-tools %{ llc -O0 -mtriple=spirv64-unknown-unknown %s --spirv-ext=+SPV_EXT_image_raw10_raw12 -o - -filetype=obj | spirv-val %} + +; CHECK-NOT: OpExtension "SPV_EXT_image_raw10_raw12" + +define dso_local spir_kernel void @test_raw1012(ptr addrspace(1) noundef writeonly align 4 captures(none) %dst, i32 noundef %value) { +entry: + switch i32 %value, label %sw.epilog [ + i32 4323, label %sw.epilog.sink.split + i32 4324, label %sw.bb1 + ] + +sw.bb1: + br label %sw.epilog.sink.split + +sw.epilog.sink.split: + %.sink = phi i32 [ 12, %sw.bb1 ], [ 10, %entry ] + store i32 %.sink, ptr addrspace(1) %dst, align 4 + br label %sw.epilog + +sw.epilog: + %0 = add i32 %value, -4323 + %or.cond = icmp ult i32 %0, 2 + br i1 %or.cond, label %if.then, label %if.end + +if.then: + store i32 1012, ptr addrspace(1) %dst, align 4 + br label %if.end + +if.end: + ret void +} diff --git a/llvm/test/CodeGen/SPIRV/extensions/SPV_EXT_image_raw10_raw12/writer.ll b/llvm/test/CodeGen/SPIRV/extensions/SPV_EXT_image_raw10_raw12/writer.ll new file mode 100644 index 0000000000000..41f6940d06782 --- /dev/null +++ b/llvm/test/CodeGen/SPIRV/extensions/SPV_EXT_image_raw10_raw12/writer.ll @@ -0,0 +1,45 @@ +; RUN: llc -verify-machineinstrs -O0 -mtriple=spirv32-unknown-unknown --spirv-ext=+SPV_EXT_image_raw10_raw12 %s -o - | FileCheck %s +; RUN: %if spirv-tools %{ llc -O0 -mtriple=spirv64-unknown-unknown %s --spirv-ext=+SPV_EXT_image_raw10_raw12 -o - -filetype=obj | spirv-val %} + +; CHECK: OpExtension "SPV_EXT_image_raw10_raw12" + + define dso_local spir_kernel void @test_raw1012(ptr addrspace(1) noundef writeonly align 4 captures(none) %dst, target("spirv.Image", void, 1, 0, 0, 0, 0, 0, 0) %img) { + entry: + %call = tail call spir_func i32 @_Z27get_image_channel_data_type14ocl_image2d_ro(target("spirv.Image", void, 1, 0, 0, 0, 0, 0, 0) %img) + switch i32 %call, label %sw.epilog [ + i32 4304, label %sw.epilog.sink.split + i32 4323, label %sw.bb1 + i32 4324, label %sw.bb2 + ] + + sw.bb1: + br label %sw.epilog.sink.split + + sw.bb2: + br label %sw.epilog.sink.split + + sw.epilog.sink.split: + %.sink = phi i32 [ 12, %sw.bb2 ], [ 10, %sw.bb1 ], [ 8, %entry ] + store i32 %.sink, ptr addrspace(1) %dst, align 4 + br label %sw.epilog + + sw.epilog: + %call3 = tail call spir_func i32 @_Z27get_image_channel_data_type14ocl_image2d_ro(target("spirv.Image", void, 1, 0, 0, 0, 0, 0, 0) %img) + %cmp = icmp eq i32 %call3, 4323 + br i1 %cmp, label %if.end7.sink.split, label %if.else + + if.else: + %call4 = tail call spir_func i32 @_Z27get_image_channel_data_type14ocl_image2d_ro(target("spirv.Image", void, 1, 0, 0, 0, 0, 0, 0) %img) + %cmp5 = icmp eq i32 %call4, 4324 + br i1 %cmp5, label %if.end7.sink.split, label %if.end7 + + if.end7.sink.split: + %.sink14 = phi i32 [ 1010, %sw.epilog ], [ 1212, %if.else ] + store i32 %.sink14, ptr addrspace(1) %dst, align 4 + br label %if.end7 + + if.end7: + ret void + } + + declare spir_func i32 @_Z27get_image_channel_data_type14ocl_image2d_ro(target("spirv.Image", void, 1, 0, 0, 0, 0, 0, 0))