[Mlir-commits] [mlir] [XeVM] Refactor the SPIR-V generation to use SPIR-V backend API. (PR #189494)

Md Abdullah Shahneous Bari llvmlistbot at llvm.org
Mon Mar 30 14:49:20 PDT 2026


https://github.com/mshahneo created https://github.com/llvm/llvm-project/pull/189494

Currently, we use 2 different approach to generate SPIR-V based on compilation target. If compilation target is `assembly/isa`, an MLIR interface `translateToISA` is used to convert an LLVM module to SPIR-V text. For other cases (`bin/fatbin` compilation target) SPIR-V backend API is used to generate SPIR-V binary.

SPIR-V backend API is more powerful, as lets one pass the necessary extensions which is a must if one is using any advanced or vendor-specific SPIR-V features.

This PR discontinues the usage of MLIR API and consolidates to use SPIR-V API.

It also ensures that SPIR-V generated from MLIR side is always in binary format (for both XeVM target and SPIR-V target).

>From bd7adaf989a923559b8d7aa25555138419f2f406 Mon Sep 17 00:00:00 2001
From: "Shahneous Bari, Md Abdullah" <md.abdullah.shahneous.bari at intel.com>
Date: Mon, 30 Mar 2026 21:37:37 +0000
Subject: [PATCH] [XeVM] Refactor the SPIR-V generation to use SPIR-V backend
 API.

Currently, we use 2 different approach to generate SPIR-V based
on compilation target. If compilation target is `assembly/isa`,
an MLIR interface `translateToISA` is used to convert an LLVM
module to SPIR-V text. For other cases (`bin/fatbin` compilation
target) SPIR-V backend API is used to generate SPIR-V binary.

SPIR-V backend API is more powerful, as lets one pass the
necessary extensions which is a must if one is using any
advanced or vendor-specific SPIR-V features.

This PR discontinues the usage of MLIR API and consolidates to
use SPIR-V API.

It also ensures that SPIR-V generated from MLIR side is always in
binary format (for both XeVM target and SPIR-V target).
---
 mlir/lib/Target/LLVM/XeVM/Target.cpp | 69 +++++++++-------------------
 1 file changed, 21 insertions(+), 48 deletions(-)

diff --git a/mlir/lib/Target/LLVM/XeVM/Target.cpp b/mlir/lib/Target/LLVM/XeVM/Target.cpp
index 83eec5e9d5549..e95771d9317a0 100644
--- a/mlir/lib/Target/LLVM/XeVM/Target.cpp
+++ b/mlir/lib/Target/LLVM/XeVM/Target.cpp
@@ -306,54 +306,6 @@ SPIRVSerializer::moduleToObject(llvm::Module &llvmModule) {
       "The `SPIRV` target was not built. Please enable "
       "it when building LLVM.");
 #else
-
-  // Return SPIRV text if the compilation target is `assembly`.
-  // Note: Optimization passes are skipped and SPIRV extensions are
-  // not supported in this mode.
-  if (targetOptions.getCompilationTarget() ==
-      gpu::CompilationTarget::Assembly) {
-    FailureOr<llvm::TargetMachine *> targetMachine = getOrCreateTargetMachine();
-    if (failed(targetMachine))
-      return getGPUModuleOp().emitError()
-             << "Target Machine unavailable for triple " << triple
-             << ", can't optimize with LLVM\n";
-
-    FailureOr<SmallString<0>> serializedISA =
-        translateModuleToISA(llvmModule, **targetMachine,
-                             [&]() { return getGPUModuleOp().emitError(); });
-    if (failed(serializedISA))
-      return getGPUModuleOp().emitError()
-             << "Failed translating the module to ISA." << triple
-             << ", can't compile with LLVM\n";
-
-#define DEBUG_TYPE "serialize-to-isa"
-    LLVM_DEBUG({
-      llvm::dbgs() << "SPIR-V for module: " << getGPUModuleOp().getNameAttr()
-                   << "\n";
-      llvm::dbgs() << *serializedISA << "\n";
-      llvm::dbgs().flush();
-    });
-#undef DEBUG_TYPE
-
-    // Make sure to include the null terminator.
-    StringRef bin(serializedISA->c_str(), serializedISA->size() + 1);
-    return SmallVector<char, 0>(bin.begin(), bin.end());
-  }
-
-  // Binary generation path for SPIR-V target. Optimization and SPIR-V
-  // extensions are enabled in this path. In this path, first the SPIR-V binary
-  // is generated directly using the SPIR-V backends `SPIRVTranslateModule` API.
-  // Resultant SPIR-V is then fed to `ocloc` compiler (Intel's OpenCL Offline
-  // Compiler) to generate the final binary for Intel GPUs.
-
-  // @TODO: This part is doing exact same SPIR-V code generation as the previous
-  // section under (targetOptions.getCompilationTarget() ==
-  // gpu::CompilationTarget::Assembly) condition. Only execption is, it enables
-  // optimization and SPIRV extensions support for SPIRV binary output. We need
-  // to decide which one do we use for our SPIRV code generation, and remove the
-  // other one to avoid confusion. For now, we keep both to have more
-  // flexibility for testing and comparison.
-
   std::string serializedSPIRVBinary;
   std::string ErrMsg;
   std::vector<std::string> Opts;
@@ -375,6 +327,27 @@ SPIRVSerializer::moduleToObject(llvm::Module &llvmModule) {
 
   StringRef spirvBin(serializedSPIRVBinary.c_str(),
                      serializedSPIRVBinary.size());
+
+  // Return SPIRV binary if the compilation target is `assembly`. Optimization
+  // and SPIR-V extensions are enabled for SPIR-V binary output in both paths
+  // (assembly and binary) as of now. SPIR-V binary
+  // is generated directly using the SPIR-V backends `SPIRVTranslate` API.
+  if (targetOptions.getCompilationTarget() ==
+      gpu::CompilationTarget::Assembly) {
+#define DEBUG_TYPE "serialize-to-isa"
+    LLVM_DEBUG({
+      llvm::dbgs() << "SPIR-V for module: " << getGPUModuleOp().getNameAttr()
+                   << "\n";
+      llvm::dbgs() << serializedSPIRVBinary << "\n";
+      llvm::dbgs().flush();
+    });
+#undef DEBUG_TYPE
+    return SmallVector<char, 0>(spirvBin.begin(), spirvBin.end());
+  }
+
+  // Return native binary. Compile the SPIR-V binary to native binary for Intel
+  // GPUs using `ocloc` compiler (Intel's OpenCL Offline Compiler).
+
   return compileToBinary(spirvBin, "-spirv_input");
 #endif // LLVM_HAS_SPIRV_TARGET
 }



More information about the Mlir-commits mailing list