[llvm] [SPIRV] Support for the extension SPV_EXT_image_raw10_raw12 (PR #160032)

Aadesh Premkumar via llvm-commits llvm-commits at lists.llvm.org
Sun Sep 21 22:23:05 PDT 2025


https://github.com/aadeshps-mcw created https://github.com/llvm/llvm-project/pull/160032

--Added support for SPV_EXT_image_raw10_raw12 extension.

>From 5752f0670c4cad89f7dc29284096391eb6244a2b Mon Sep 17 00:00:00 2001
From: Aadesh PremKumar <aadesh.premkumar at multicorewareinc.com>
Date: Thu, 28 Aug 2025 14:17:26 +0530
Subject: [PATCH] --Added support for SPV_EXT_image_raw10_raw12 extension.

---
 llvm/lib/Target/SPIRV/SPIRVBuiltins.cpp       | 30 +++++++++++++
 llvm/lib/Target/SPIRV/SPIRVBuiltins.td        |  2 +
 llvm/lib/Target/SPIRV/SPIRVCommandLine.cpp    |  4 +-
 llvm/lib/Target/SPIRV/SPIRVModuleAnalysis.cpp | 43 ++++++++++++++++++
 .../lib/Target/SPIRV/SPIRVSymbolicOperands.td |  3 ++
 .../SPV_EXT_image_raw10_raw12/constant_use.ll | 32 +++++++++++++
 .../SPV_EXT_image_raw10_raw12/writer.ll       | 45 +++++++++++++++++++
 7 files changed, 158 insertions(+), 1 deletion(-)
 create mode 100644 llvm/test/CodeGen/SPIRV/extensions/SPV_EXT_image_raw10_raw12/constant_use.ll
 create mode 100644 llvm/test/CodeGen/SPIRV/extensions/SPV_EXT_image_raw10_raw12/writer.ll

diff --git a/llvm/lib/Target/SPIRV/SPIRVBuiltins.cpp b/llvm/lib/Target/SPIRV/SPIRVBuiltins.cpp
index 2abd9d36f7606..b00e7c34c09d5 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,
@@ -2339,6 +2356,17 @@ 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) {
@@ -2948,6 +2976,8 @@ std::optional<bool> lowerBuiltin(const StringRef DemangledCall,
     return generateTernaryBitwiseFunctionINTELInst(Call.get(), MIRBuilder, GR);
   case SPIRV::Block2DLoadStore:
     return generate2DBlockIOINTELInst(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 d08560bb6565a..31cec3417b59d 100644
--- a/llvm/lib/Target/SPIRV/SPIRVBuiltins.td
+++ b/llvm/lib/Target/SPIRV/SPIRVBuiltins.td
@@ -69,6 +69,7 @@ def ExtendedBitOps : BuiltinGroup;
 def BindlessINTEL : BuiltinGroup;
 def TernaryBitwiseINTEL : BuiltinGroup;
 def Block2DLoadStore : BuiltinGroup;
+def ImageChannelDataTypes : BuiltinGroup;
 
 //===----------------------------------------------------------------------===//
 // Class defining a demangled builtin record. The information in the record
@@ -1445,6 +1446,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 e7da5504b2d58..4526468be014d 100644
--- a/llvm/lib/Target/SPIRV/SPIRVCommandLine.cpp
+++ b/llvm/lib/Target/SPIRV/SPIRVCommandLine.cpp
@@ -147,7 +147,9 @@ static const std::map<std::string, SPIRV::Extension::Extension, std::less<>>
         {"SPV_KHR_float_controls2",
          SPIRV::Extension::Extension::SPV_KHR_float_controls2},
         {"SPV_INTEL_tensor_float32_conversion",
-         SPIRV::Extension::Extension::SPV_INTEL_tensor_float32_conversion}};
+         SPIRV::Extension::Extension::SPV_INTEL_tensor_float32_conversion},
+        {"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 8039cf0c432fa..45be657547ed0 100644
--- a/llvm/lib/Target/SPIRV/SPIRVModuleAnalysis.cpp
+++ b/llvm/lib/Target/SPIRV/SPIRVModuleAnalysis.cpp
@@ -1432,6 +1432,49 @@ 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 d2824ee2d2caf..51ddafa08663f 100644
--- a/llvm/lib/Target/SPIRV/SPIRVSymbolicOperands.td
+++ b/llvm/lib/Target/SPIRV/SPIRVSymbolicOperands.td
@@ -382,6 +382,7 @@ defm SPV_INTEL_2d_block_io : ExtensionOperand<122, [EnvOpenCL]>;
 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_EXT_image_raw10_raw12 :ExtensionOperand<126, [EnvOpenCL]>;
 
 //===----------------------------------------------------------------------===//
 // Multiclass used to define Capabilities enum values and at the same time
@@ -1078,6 +1079,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))



More information about the llvm-commits mailing list