[llvm] 2c26d56 - [SPIRV] Support for the extension SPV_EXT_image_raw10_raw12 (#160032)

via llvm-commits llvm-commits at lists.llvm.org
Mon Dec 15 23:57:41 PST 2025


Author: Aadesh Premkumar
Date: 2025-12-15T23:57:36-08:00
New Revision: 2c26d56045e6a83905662caf1c967ab543496493

URL: https://github.com/llvm/llvm-project/commit/2c26d56045e6a83905662caf1c967ab543496493
DIFF: https://github.com/llvm/llvm-project/commit/2c26d56045e6a83905662caf1c967ab543496493.diff

LOG: [SPIRV] Support for the extension SPV_EXT_image_raw10_raw12 (#160032)

Added support for SPV_EXT_image_raw10_raw12 extension.

Added: 
    llvm/test/CodeGen/SPIRV/extensions/SPV_EXT_image_raw10_raw12/constant_use.ll
    llvm/test/CodeGen/SPIRV/extensions/SPV_EXT_image_raw10_raw12/writer.ll

Modified: 
    llvm/docs/SPIRVUsage.rst
    llvm/lib/Target/SPIRV/SPIRVBuiltins.cpp
    llvm/lib/Target/SPIRV/SPIRVBuiltins.td
    llvm/lib/Target/SPIRV/SPIRVCommandLine.cpp
    llvm/lib/Target/SPIRV/SPIRVModuleAnalysis.cpp
    llvm/lib/Target/SPIRV/SPIRVSymbolicOperands.td

Removed: 
    


################################################################################
diff  --git a/llvm/docs/SPIRVUsage.rst b/llvm/docs/SPIRVUsage.rst
index e2f85ba3c2774..9915b67592978 100644
--- a/llvm/docs/SPIRVUsage.rst
+++ b/llvm/docs/SPIRVUsage.rst
@@ -249,6 +249,8 @@ Below is a list of supported SPIR-V extensions, sorted alphabetically by their e
      - Adds new pipe read and write functions that have blocking semantics instead of the non-blocking semantics of the existing pipe read/write functions.
    * - ``SPV_ALTERA_arbitrary_precision_fixed_point``
      - Add instructions for fixed point arithmetic. The extension works without SPV_ALTERA_arbitrary_precision_integers, but together they allow greater flexibility in representing arbitrary precision data types.
+   * - ``SPV_EXT_image_raw10_raw12``
+     - Adds Image Channel Data Type definitions for RAW10 and RAW12 image formats.
 
 
 SPIR-V representation in LLVM IR

diff  --git a/llvm/lib/Target/SPIRV/SPIRVBuiltins.cpp b/llvm/lib/Target/SPIRV/SPIRVBuiltins.cpp
index b111909fc25cc..f7186d15a46ea 100644
--- a/llvm/lib/Target/SPIRV/SPIRVBuiltins.cpp
+++ b/llvm/lib/Target/SPIRV/SPIRVBuiltins.cpp
@@ -1076,6 +1076,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,
@@ -2536,6 +2553,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) {
@@ -3188,6 +3215,8 @@ std::optional<bool> lowerBuiltin(const StringRef DemangledCall,
     return generateBlockingPipesInst(Call.get(), MIRBuilder, GR);
   case SPIRV::ArbitraryPrecisionFixedPoint:
     return generateAPFixedPointInst(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 98440856387c9..84f8f809561bb 100644
--- a/llvm/lib/Target/SPIRV/SPIRVBuiltins.td
+++ b/llvm/lib/Target/SPIRV/SPIRVBuiltins.td
@@ -73,6 +73,7 @@ def Pipe : BuiltinGroup;
 def PredicatedLoadStore : BuiltinGroup;
 def ArbitraryPrecisionFixedPoint : BuiltinGroup;
 def BlockingPipes : BuiltinGroup;
+def ImageChannelDataTypes : BuiltinGroup;
 
 //===----------------------------------------------------------------------===//
 // Class defining a demangled builtin record. The information in the record
@@ -1494,6 +1495,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 04c54f9b0e53d..74bef26984089 100644
--- a/llvm/lib/Target/SPIRV/SPIRVCommandLine.cpp
+++ b/llvm/lib/Target/SPIRV/SPIRVCommandLine.cpp
@@ -176,7 +176,9 @@ static const std::map<StringRef, SPIRV::Extension::Extension>
         {"SPV_INTEL_int4", SPIRV::Extension::Extension::SPV_INTEL_int4},
         {"SPV_ALTERA_arbitrary_precision_fixed_point",
          SPIRV::Extension::Extension::
-             SPV_ALTERA_arbitrary_precision_fixed_point}};
+             SPV_ALTERA_arbitrary_precision_fixed_point},
+        {"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 ba0593164905d..babce22d4f583 100644
--- a/llvm/lib/Target/SPIRV/SPIRVModuleAnalysis.cpp
+++ b/llvm/lib/Target/SPIRV/SPIRVModuleAnalysis.cpp
@@ -1650,6 +1650,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 078f1dff839ea..7335882d7af4f 100644
--- a/llvm/lib/Target/SPIRV/SPIRVSymbolicOperands.td
+++ b/llvm/lib/Target/SPIRV/SPIRVSymbolicOperands.td
@@ -393,6 +393,7 @@ defm SPV_INTEL_16bit_atomics : ExtensionOperand<130, [EnvVulkan, EnvOpenCL]>;
 defm SPV_ALTERA_arbitrary_precision_fixed_point : ExtensionOperand<131, [EnvOpenCL, EnvVulkan]>;
 defm SPV_NV_shader_atomic_fp16_vector
     : ExtensionOperand<132, [EnvVulkan, EnvOpenCL]>;
+defm SPV_EXT_image_raw10_raw12 :ExtensionOperand<133, [EnvOpenCL, EnvVulkan]>;
 
 //===----------------------------------------------------------------------===//
 // Multiclass used to define Capabilities enum values and at the same time
@@ -1115,6 +1116,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