[Mlir-commits] [mlir] [mlir][gpu] Extend `mgpumoduleLoadJIT` API to add assemblySize parameter (PR #189429)
Md Abdullah Shahneous Bari
llvmlistbot at llvm.org
Fri Apr 3 10:19:41 PDT 2026
https://github.com/mshahneo updated https://github.com/llvm/llvm-project/pull/189429
>From e265fe669c8ad4ad827b02b58cbc938d94154208 Mon Sep 17 00:00:00 2001
From: "Shahneous Bari, Md Abdullah" <md.abdullah.shahneous.bari at intel.com>
Date: Mon, 30 Mar 2026 16:37:45 +0000
Subject: [PATCH 1/8] [mlir][gpu] Extend `mgpumoduleLoadJIT` API to add
assemblySize parameter
When JITing SPIR-V using LevelZero API, it expects the length
of the string since passed input data is a `void *`.
Problem is, getting the length of the string is not possible using
something like `strlen(reinterpret_cast<char *>(data))` in
`mgpuModuleLoadJIT` implementation. Becasuse the SPIR-V binary
contains null bytes (i.e., the data is binary SPIR-V,
not null-terminated text).
As a result we need to pass the `assmeblySize` via the
`mgpuModuleLoadJIT(void* data, int optLevel, size_t assmeblySize)`.
---
.../ExecutionEngine/CudaRuntimeWrappers.cpp | 4 +--
.../LevelZeroRuntimeWrappers.cpp | 6 ++--
.../ExecutionEngine/RocmRuntimeWrappers.cpp | 3 +-
.../Target/LLVMIR/Dialect/GPU/CMakeLists.txt | 1 +
.../LLVMIR/Dialect/GPU/SelectObjectAttr.cpp | 30 +++++++++++++++----
5 files changed, 32 insertions(+), 12 deletions(-)
diff --git a/mlir/lib/ExecutionEngine/CudaRuntimeWrappers.cpp b/mlir/lib/ExecutionEngine/CudaRuntimeWrappers.cpp
index f203363e16ea2..6307e0b59f3d2 100644
--- a/mlir/lib/ExecutionEngine/CudaRuntimeWrappers.cpp
+++ b/mlir/lib/ExecutionEngine/CudaRuntimeWrappers.cpp
@@ -124,8 +124,8 @@ mgpuModuleLoad(void *data, size_t /*gpuBlobSize*/) {
return module;
}
-extern "C" MLIR_CUDA_WRAPPERS_EXPORT CUmodule mgpuModuleLoadJIT(void *data,
- int optLevel) {
+extern "C" MLIR_CUDA_WRAPPERS_EXPORT CUmodule
+mgpuModuleLoadJIT(void *data, int optLevel, size_t /*assmeblySize*/) {
ScopedContext scopedContext;
CUmodule module = nullptr;
char jitErrorBuffer[4096] = {0};
diff --git a/mlir/lib/ExecutionEngine/LevelZeroRuntimeWrappers.cpp b/mlir/lib/ExecutionEngine/LevelZeroRuntimeWrappers.cpp
index 01965da038820..75e997ead233d 100644
--- a/mlir/lib/ExecutionEngine/LevelZeroRuntimeWrappers.cpp
+++ b/mlir/lib/ExecutionEngine/LevelZeroRuntimeWrappers.cpp
@@ -520,10 +520,10 @@ extern "C" ze_module_handle_t mgpuModuleLoad(const void *data,
return catchAll([&]() { return loadModule(data, gpuBlobSize); });
}
-extern "C" ze_module_handle_t mgpuModuleLoadJIT(void *data, int optLevel) {
+extern "C" ze_module_handle_t mgpuModuleLoadJIT(void *data, int optLevel,
+ size_t assemblySize) {
return catchAll([&]() {
- return loadModule(data, strlen(reinterpret_cast<char *>(data)),
- ZE_MODULE_FORMAT_IL_SPIRV);
+ return loadModule(data, assemblySize, ZE_MODULE_FORMAT_IL_SPIRV);
});
}
diff --git a/mlir/lib/ExecutionEngine/RocmRuntimeWrappers.cpp b/mlir/lib/ExecutionEngine/RocmRuntimeWrappers.cpp
index b984149ca6dea..e729e4f9fca9d 100644
--- a/mlir/lib/ExecutionEngine/RocmRuntimeWrappers.cpp
+++ b/mlir/lib/ExecutionEngine/RocmRuntimeWrappers.cpp
@@ -38,7 +38,8 @@ extern "C" hipModule_t mgpuModuleLoad(void *data, size_t /*gpuBlobSize*/) {
return module;
}
-extern "C" hipModule_t mgpuModuleLoadJIT(void *data, int optLevel) {
+extern "C" hipModule_t mgpuModuleLoadJIT(void *data, int optLevel,
+ size_t /*assmeblySize*/) {
assert(false && "This function is not available in HIP.");
return nullptr;
}
diff --git a/mlir/lib/Target/LLVMIR/Dialect/GPU/CMakeLists.txt b/mlir/lib/Target/LLVMIR/Dialect/GPU/CMakeLists.txt
index 11816ff5c2c1f..dd54dc10e1abe 100644
--- a/mlir/lib/Target/LLVMIR/Dialect/GPU/CMakeLists.txt
+++ b/mlir/lib/Target/LLVMIR/Dialect/GPU/CMakeLists.txt
@@ -9,6 +9,7 @@ add_mlir_translation_library(MLIRGPUToLLVMIRTranslation
MLIRIR
MLIRGPUDialect
MLIRLLVMDialect
+ MLIRXeVMTarget
MLIRSupport
MLIRTargetLLVMIRExport
)
diff --git a/mlir/lib/Target/LLVMIR/Dialect/GPU/SelectObjectAttr.cpp b/mlir/lib/Target/LLVMIR/Dialect/GPU/SelectObjectAttr.cpp
index 85fac86743a13..8e31a6e26fc4d 100644
--- a/mlir/lib/Target/LLVMIR/Dialect/GPU/SelectObjectAttr.cpp
+++ b/mlir/lib/Target/LLVMIR/Dialect/GPU/SelectObjectAttr.cpp
@@ -13,7 +13,10 @@
#include "mlir/Dialect/GPU/IR/CompilationInterfaces.h"
#include "mlir/Dialect/GPU/IR/GPUDialect.h"
+#include "mlir/Dialect/LLVMIR/XeVMDialect.h"
+#include "mlir/Dialect/SPIRV/IR/SPIRVAttributes.h"
+#include "mlir/Target/LLVM/XeVM/Target.h"
#include "mlir/Target/LLVMIR/Dialect/GPU/GPUToLLVMIRTranslation.h"
#include "mlir/Target/LLVMIR/Export.h"
#include "mlir/Target/LLVMIR/ModuleTranslation.h"
@@ -98,8 +101,15 @@ static LogicalResult embedBinaryImpl(StringRef moduleName,
// Embed the object as a global string.
// Add null for assembly output for JIT paths that expect null-terminated
- // strings.
- bool addNull = (object.getFormat() == gpu::CompilationTarget::Assembly);
+ // strings. SPIR-V (for both XeVM and SPIR-V target) is passed as a binary
+ // blob and should not have a null terminator.
+ auto xevmTarget = dyn_cast<xevm::XeVMTargetAttr>(object.getTarget());
+ bool isXeVMSPIRV =
+ xevmTarget && xevmTarget.getTriple() == "spirv64-unknown-unknown";
+ bool isSPIRVTarget = isa<spirv::TargetEnvAttr>(object.getTarget());
+
+ bool addNull = !(isXeVMSPIRV || isSPIRVTarget) &&
+ (object.getFormat() == gpu::CompilationTarget::Assembly);
StringRef serializedStr = object.getObject().getValue();
Constant *serializedCst =
ConstantDataArray::getString(module.getContext(), serializedStr, addNull);
@@ -142,16 +152,24 @@ static LogicalResult embedBinaryImpl(StringRef moduleName,
auto *loadBlock = BasicBlock::Create(module.getContext(), "entry", loadFn);
builder.SetInsertPoint(loadBlock);
Value *moduleObj = [&] {
+ Constant *binarySize =
+ ConstantInt::get(i64Ty, serializedStr.size() + (addNull ? 1 : 0));
if (object.getFormat() == gpu::CompilationTarget::Assembly) {
FunctionCallee moduleLoadFn = module.getOrInsertFunction(
- "mgpuModuleLoadJIT", FunctionType::get(ptrTy, {ptrTy, i32Ty}, false));
+ "mgpuModuleLoadJIT", FunctionType::get(ptrTy,
+ {
+ ptrTy,
+ i32Ty,
+ i64Ty,
+ },
+ false));
+
Constant *optValue = ConstantInt::get(i32Ty, optLevel);
- return builder.CreateCall(moduleLoadFn, {serializedObj, optValue});
+ return builder.CreateCall(moduleLoadFn,
+ {serializedObj, optValue, binarySize});
}
FunctionCallee moduleLoadFn = module.getOrInsertFunction(
"mgpuModuleLoad", FunctionType::get(ptrTy, {ptrTy, i64Ty}, false));
- Constant *binarySize =
- ConstantInt::get(i64Ty, serializedStr.size() + (addNull ? 1 : 0));
return builder.CreateCall(moduleLoadFn, {serializedObj, binarySize});
}();
builder.CreateStore(moduleObj, modulePtr);
>From 3eda8e1902cedecf43148614c60e326f0fb3bee9 Mon Sep 17 00:00:00 2001
From: "Shahneous Bari, Md Abdullah" <md.abdullah.shahneous.bari at intel.com>
Date: Mon, 30 Mar 2026 20:39:50 +0000
Subject: [PATCH 2/8] Address review comments.
Fix the layering issue.
---
mlir/lib/Target/LLVM/XeVM/Target.cpp | 13 +++++-
.../Target/LLVMIR/Dialect/GPU/CMakeLists.txt | 1 -
.../LLVMIR/Dialect/GPU/SelectObjectAttr.cpp | 42 ++++++++++---------
mlir/lib/Target/SPIRV/Target.cpp | 13 ++++++
4 files changed, 47 insertions(+), 22 deletions(-)
diff --git a/mlir/lib/Target/LLVM/XeVM/Target.cpp b/mlir/lib/Target/LLVM/XeVM/Target.cpp
index 83eec5e9d5549..fd6c190f42ad2 100644
--- a/mlir/lib/Target/LLVM/XeVM/Target.cpp
+++ b/mlir/lib/Target/LLVM/XeVM/Target.cpp
@@ -475,10 +475,19 @@ XeVMTargetAttrImpl::createObject(Attribute attribute, Operation *module,
gpu::CompilationTarget format = options.getCompilationTarget();
auto xeTarget = cast<XeVMTargetAttr>(attribute);
SmallVector<NamedAttribute, 2> properties;
- if (format == gpu::CompilationTarget::Assembly)
+ if (format == gpu::CompilationTarget::Assembly) {
properties.push_back(
builder.getNamedAttr("O", builder.getI32IntegerAttr(xeTarget.getO())));
-
+ // If the object is serialized from a SPIR-V target, attach bool attribute
+ // "requires_null_terminator=false". Since, SPIR-V is a binary format it
+ // does not require a null terminator.
+ if (xeTarget.getTriple().starts_with("spirv")) {
+ properties.push_back(builder.getNamedAttr(
+ "requires_null_terminator",
+ builder.getBoolAttr(
+ false /*SPIR-V binary does not need null terminator*/)));
+ }
+ }
DictionaryAttr objectProps;
if (!properties.empty())
objectProps = builder.getDictionaryAttr(properties);
diff --git a/mlir/lib/Target/LLVMIR/Dialect/GPU/CMakeLists.txt b/mlir/lib/Target/LLVMIR/Dialect/GPU/CMakeLists.txt
index dd54dc10e1abe..11816ff5c2c1f 100644
--- a/mlir/lib/Target/LLVMIR/Dialect/GPU/CMakeLists.txt
+++ b/mlir/lib/Target/LLVMIR/Dialect/GPU/CMakeLists.txt
@@ -9,7 +9,6 @@ add_mlir_translation_library(MLIRGPUToLLVMIRTranslation
MLIRIR
MLIRGPUDialect
MLIRLLVMDialect
- MLIRXeVMTarget
MLIRSupport
MLIRTargetLLVMIRExport
)
diff --git a/mlir/lib/Target/LLVMIR/Dialect/GPU/SelectObjectAttr.cpp b/mlir/lib/Target/LLVMIR/Dialect/GPU/SelectObjectAttr.cpp
index 8e31a6e26fc4d..8650985adb5cb 100644
--- a/mlir/lib/Target/LLVMIR/Dialect/GPU/SelectObjectAttr.cpp
+++ b/mlir/lib/Target/LLVMIR/Dialect/GPU/SelectObjectAttr.cpp
@@ -99,17 +99,32 @@ namespace llvm {
static LogicalResult embedBinaryImpl(StringRef moduleName,
gpu::ObjectAttr object, Module &module) {
+ // Default JIT optimization level.
+ auto optLevel = APInt::getZero(32);
+ std::optional<StringRef> section = std::nullopt;
+ bool addNull = (object.getFormat() == gpu::CompilationTarget::Assembly);
+
+ if (DictionaryAttr objectProps = object.getProperties()) {
+ if (auto sectionAttr = dyn_cast_or_null<StringAttr>(
+ objectProps.get(gpu::elfSectionName))) {
+ section = sectionAttr.getValue();
+ }
+ // Check if there's an optimization level embedded in the object.
+ if (auto optAttr = dyn_cast_or_null<IntegerAttr>(objectProps.get("O")))
+ optLevel = optAttr.getValue();
+ // Check if there's an attribute indicating whether a null terminator is
+ // needed for the object.
+ if (auto nullTerminatorAttr = dyn_cast_or_null<BoolAttr>(
+ objectProps.get("requires_null_terminator"))) {
+ addNull = nullTerminatorAttr.getValue();
+ }
+ }
+
// Embed the object as a global string.
// Add null for assembly output for JIT paths that expect null-terminated
// strings. SPIR-V (for both XeVM and SPIR-V target) is passed as a binary
// blob and should not have a null terminator.
- auto xevmTarget = dyn_cast<xevm::XeVMTargetAttr>(object.getTarget());
- bool isXeVMSPIRV =
- xevmTarget && xevmTarget.getTriple() == "spirv64-unknown-unknown";
- bool isSPIRVTarget = isa<spirv::TargetEnvAttr>(object.getTarget());
- bool addNull = !(isXeVMSPIRV || isSPIRVTarget) &&
- (object.getFormat() == gpu::CompilationTarget::Assembly);
StringRef serializedStr = object.getObject().getValue();
Constant *serializedCst =
ConstantDataArray::getString(module.getContext(), serializedStr, addNull);
@@ -119,19 +134,8 @@ static LogicalResult embedBinaryImpl(StringRef moduleName,
serializedCst, moduleName + "_binary");
serializedObj->setAlignment(MaybeAlign(8));
serializedObj->setUnnamedAddr(GlobalValue::UnnamedAddr::None);
-
- // Default JIT optimization level.
- auto optLevel = APInt::getZero(32);
-
- if (DictionaryAttr objectProps = object.getProperties()) {
- if (auto section = dyn_cast_or_null<StringAttr>(
- objectProps.get(gpu::elfSectionName))) {
- serializedObj->setSection(section.getValue());
- }
- // Check if there's an optimization level embedded in the object.
- if (auto optAttr = dyn_cast_or_null<IntegerAttr>(objectProps.get("O")))
- optLevel = optAttr.getValue();
- }
+ if (section)
+ serializedObj->setSection(*section);
IRBuilder<> builder(module.getContext());
auto *i32Ty = builder.getInt32Ty();
diff --git a/mlir/lib/Target/SPIRV/Target.cpp b/mlir/lib/Target/SPIRV/Target.cpp
index be589b8292874..a07cf0debea1d 100644
--- a/mlir/lib/Target/SPIRV/Target.cpp
+++ b/mlir/lib/Target/SPIRV/Target.cpp
@@ -96,6 +96,19 @@ SPIRVTargetAttrImpl::createObject(Attribute attribute, Operation *module,
gpu::CompilationTarget format = options.getCompilationTarget();
DictionaryAttr objectProps;
Builder builder(attribute.getContext());
+ // If compilation target is assembly, attach bool attribute
+ // "requires_null_terminator=false". This indicates, even if the compilation
+ // target is assembly, a null terminator is not required for SPIR-V. Because
+ // SPIR-V is a binary blob and does not require a null terminator.
+ if (format == gpu::CompilationTarget::Assembly) {
+ objectProps = DictionaryAttr::get(
+ attribute.getContext(),
+ {NamedAttribute(
+ "requires_null_terminator",
+ builder.getBoolAttr(
+ false /*SPIR-V binary does not need null terminator*/))});
+ }
+
return builder.getAttr<gpu::ObjectAttr>(
attribute, format,
builder.getStringAttr(
>From 343aeee09a203e2a0400ee1f67b4cf9be27a7361 Mon Sep 17 00:00:00 2001
From: "Shahneous Bari, Md Abdullah" <md.abdullah.shahneous.bari at intel.com>
Date: Mon, 30 Mar 2026 20:44:06 +0000
Subject: [PATCH 3/8] Remove unncessary headers.
---
mlir/lib/Target/LLVMIR/Dialect/GPU/SelectObjectAttr.cpp | 4 ----
1 file changed, 4 deletions(-)
diff --git a/mlir/lib/Target/LLVMIR/Dialect/GPU/SelectObjectAttr.cpp b/mlir/lib/Target/LLVMIR/Dialect/GPU/SelectObjectAttr.cpp
index 8650985adb5cb..35a359db07577 100644
--- a/mlir/lib/Target/LLVMIR/Dialect/GPU/SelectObjectAttr.cpp
+++ b/mlir/lib/Target/LLVMIR/Dialect/GPU/SelectObjectAttr.cpp
@@ -13,10 +13,6 @@
#include "mlir/Dialect/GPU/IR/CompilationInterfaces.h"
#include "mlir/Dialect/GPU/IR/GPUDialect.h"
-#include "mlir/Dialect/LLVMIR/XeVMDialect.h"
-
-#include "mlir/Dialect/SPIRV/IR/SPIRVAttributes.h"
-#include "mlir/Target/LLVM/XeVM/Target.h"
#include "mlir/Target/LLVMIR/Dialect/GPU/GPUToLLVMIRTranslation.h"
#include "mlir/Target/LLVMIR/Export.h"
#include "mlir/Target/LLVMIR/ModuleTranslation.h"
>From ce58ce0bed5c35eea141a2760508de0ad17f7c9d Mon Sep 17 00:00:00 2001
From: "Shahneous Bari, Md Abdullah" <md.abdullah.shahneous.bari at intel.com>
Date: Tue, 31 Mar 2026 21:39:52 +0000
Subject: [PATCH 4/8] Address review comments.
Handle extra-null terminator in `moduleLoadJIT` implementation
in LevelZeroRuntimeWrapper.
---
.../LevelZeroRuntimeWrappers.cpp | 8 +++-
mlir/lib/Target/LLVM/XeVM/Target.cpp | 13 +-----
.../LLVMIR/Dialect/GPU/SelectObjectAttr.cpp | 41 +++++++------------
mlir/lib/Target/SPIRV/Target.cpp | 12 ------
4 files changed, 24 insertions(+), 50 deletions(-)
diff --git a/mlir/lib/ExecutionEngine/LevelZeroRuntimeWrappers.cpp b/mlir/lib/ExecutionEngine/LevelZeroRuntimeWrappers.cpp
index 75e997ead233d..c4f799fe1ff0f 100644
--- a/mlir/lib/ExecutionEngine/LevelZeroRuntimeWrappers.cpp
+++ b/mlir/lib/ExecutionEngine/LevelZeroRuntimeWrappers.cpp
@@ -522,8 +522,14 @@ extern "C" ze_module_handle_t mgpuModuleLoad(const void *data,
extern "C" ze_module_handle_t mgpuModuleLoadJIT(void *data, int optLevel,
size_t assemblySize) {
+ // Account for extra null terminator added in embedBinaryImpl.
+ // A null terminator is added during embedding binary for assembly format to
+ // support JIT paths that expect null-terminated strings. However, for SPIR-V
+ // binary format, the null terminator is not expected. So we need to subtract
+ // the null terminator when loading SPIR-V binary.
+ auto actualAssemblySize = assemblySize - 1;
return catchAll([&]() {
- return loadModule(data, assemblySize, ZE_MODULE_FORMAT_IL_SPIRV);
+ return loadModule(data, actualAssemblySize, ZE_MODULE_FORMAT_IL_SPIRV);
});
}
diff --git a/mlir/lib/Target/LLVM/XeVM/Target.cpp b/mlir/lib/Target/LLVM/XeVM/Target.cpp
index fd6c190f42ad2..83eec5e9d5549 100644
--- a/mlir/lib/Target/LLVM/XeVM/Target.cpp
+++ b/mlir/lib/Target/LLVM/XeVM/Target.cpp
@@ -475,19 +475,10 @@ XeVMTargetAttrImpl::createObject(Attribute attribute, Operation *module,
gpu::CompilationTarget format = options.getCompilationTarget();
auto xeTarget = cast<XeVMTargetAttr>(attribute);
SmallVector<NamedAttribute, 2> properties;
- if (format == gpu::CompilationTarget::Assembly) {
+ if (format == gpu::CompilationTarget::Assembly)
properties.push_back(
builder.getNamedAttr("O", builder.getI32IntegerAttr(xeTarget.getO())));
- // If the object is serialized from a SPIR-V target, attach bool attribute
- // "requires_null_terminator=false". Since, SPIR-V is a binary format it
- // does not require a null terminator.
- if (xeTarget.getTriple().starts_with("spirv")) {
- properties.push_back(builder.getNamedAttr(
- "requires_null_terminator",
- builder.getBoolAttr(
- false /*SPIR-V binary does not need null terminator*/)));
- }
- }
+
DictionaryAttr objectProps;
if (!properties.empty())
objectProps = builder.getDictionaryAttr(properties);
diff --git a/mlir/lib/Target/LLVMIR/Dialect/GPU/SelectObjectAttr.cpp b/mlir/lib/Target/LLVMIR/Dialect/GPU/SelectObjectAttr.cpp
index 35a359db07577..c25e9a3c36973 100644
--- a/mlir/lib/Target/LLVMIR/Dialect/GPU/SelectObjectAttr.cpp
+++ b/mlir/lib/Target/LLVMIR/Dialect/GPU/SelectObjectAttr.cpp
@@ -95,32 +95,10 @@ namespace llvm {
static LogicalResult embedBinaryImpl(StringRef moduleName,
gpu::ObjectAttr object, Module &module) {
- // Default JIT optimization level.
- auto optLevel = APInt::getZero(32);
- std::optional<StringRef> section = std::nullopt;
- bool addNull = (object.getFormat() == gpu::CompilationTarget::Assembly);
-
- if (DictionaryAttr objectProps = object.getProperties()) {
- if (auto sectionAttr = dyn_cast_or_null<StringAttr>(
- objectProps.get(gpu::elfSectionName))) {
- section = sectionAttr.getValue();
- }
- // Check if there's an optimization level embedded in the object.
- if (auto optAttr = dyn_cast_or_null<IntegerAttr>(objectProps.get("O")))
- optLevel = optAttr.getValue();
- // Check if there's an attribute indicating whether a null terminator is
- // needed for the object.
- if (auto nullTerminatorAttr = dyn_cast_or_null<BoolAttr>(
- objectProps.get("requires_null_terminator"))) {
- addNull = nullTerminatorAttr.getValue();
- }
- }
-
// Embed the object as a global string.
// Add null for assembly output for JIT paths that expect null-terminated
- // strings. SPIR-V (for both XeVM and SPIR-V target) is passed as a binary
- // blob and should not have a null terminator.
-
+ // strings.
+ bool addNull = (object.getFormat() == gpu::CompilationTarget::Assembly);
StringRef serializedStr = object.getObject().getValue();
Constant *serializedCst =
ConstantDataArray::getString(module.getContext(), serializedStr, addNull);
@@ -130,8 +108,19 @@ static LogicalResult embedBinaryImpl(StringRef moduleName,
serializedCst, moduleName + "_binary");
serializedObj->setAlignment(MaybeAlign(8));
serializedObj->setUnnamedAddr(GlobalValue::UnnamedAddr::None);
- if (section)
- serializedObj->setSection(*section);
+
+ // Default JIT optimization level.
+ auto optLevel = APInt::getZero(32);
+
+ if (DictionaryAttr objectProps = object.getProperties()) {
+ if (auto section = dyn_cast_or_null<StringAttr>(
+ objectProps.get(gpu::elfSectionName))) {
+ serializedObj->setSection(section.getValue());
+ }
+ // Check if there's an optimization level embedded in the object.
+ if (auto optAttr = dyn_cast_or_null<IntegerAttr>(objectProps.get("O")))
+ optLevel = optAttr.getValue();
+ }
IRBuilder<> builder(module.getContext());
auto *i32Ty = builder.getInt32Ty();
diff --git a/mlir/lib/Target/SPIRV/Target.cpp b/mlir/lib/Target/SPIRV/Target.cpp
index a07cf0debea1d..80c28d8bd44dd 100644
--- a/mlir/lib/Target/SPIRV/Target.cpp
+++ b/mlir/lib/Target/SPIRV/Target.cpp
@@ -96,18 +96,6 @@ SPIRVTargetAttrImpl::createObject(Attribute attribute, Operation *module,
gpu::CompilationTarget format = options.getCompilationTarget();
DictionaryAttr objectProps;
Builder builder(attribute.getContext());
- // If compilation target is assembly, attach bool attribute
- // "requires_null_terminator=false". This indicates, even if the compilation
- // target is assembly, a null terminator is not required for SPIR-V. Because
- // SPIR-V is a binary blob and does not require a null terminator.
- if (format == gpu::CompilationTarget::Assembly) {
- objectProps = DictionaryAttr::get(
- attribute.getContext(),
- {NamedAttribute(
- "requires_null_terminator",
- builder.getBoolAttr(
- false /*SPIR-V binary does not need null terminator*/))});
- }
return builder.getAttr<gpu::ObjectAttr>(
attribute, format,
>From e64db0f94ee963a32b4dfc938de3e0e77a7cc612 Mon Sep 17 00:00:00 2001
From: "Shahneous Bari, Md Abdullah" <md.abdullah.shahneous.bari at intel.com>
Date: Tue, 31 Mar 2026 21:42:59 +0000
Subject: [PATCH 5/8] Remove an extra space.
---
mlir/lib/Target/SPIRV/Target.cpp | 1 -
1 file changed, 1 deletion(-)
diff --git a/mlir/lib/Target/SPIRV/Target.cpp b/mlir/lib/Target/SPIRV/Target.cpp
index 80c28d8bd44dd..be589b8292874 100644
--- a/mlir/lib/Target/SPIRV/Target.cpp
+++ b/mlir/lib/Target/SPIRV/Target.cpp
@@ -96,7 +96,6 @@ SPIRVTargetAttrImpl::createObject(Attribute attribute, Operation *module,
gpu::CompilationTarget format = options.getCompilationTarget();
DictionaryAttr objectProps;
Builder builder(attribute.getContext());
-
return builder.getAttr<gpu::ObjectAttr>(
attribute, format,
builder.getStringAttr(
>From b8958137ff916f9e49fc2ad0542c3f56e1d95214 Mon Sep 17 00:00:00 2001
From: "Shahneous Bari, Md Abdullah" <md.abdullah.shahneous.bari at intel.com>
Date: Fri, 3 Apr 2026 16:25:05 +0000
Subject: [PATCH 6/8] Address review comments.
---
mlir/lib/ExecutionEngine/LevelZeroRuntimeWrappers.cpp | 3 +++
1 file changed, 3 insertions(+)
diff --git a/mlir/lib/ExecutionEngine/LevelZeroRuntimeWrappers.cpp b/mlir/lib/ExecutionEngine/LevelZeroRuntimeWrappers.cpp
index c4f799fe1ff0f..a5efc6b337080 100644
--- a/mlir/lib/ExecutionEngine/LevelZeroRuntimeWrappers.cpp
+++ b/mlir/lib/ExecutionEngine/LevelZeroRuntimeWrappers.cpp
@@ -527,6 +527,9 @@ extern "C" ze_module_handle_t mgpuModuleLoadJIT(void *data, int optLevel,
// support JIT paths that expect null-terminated strings. However, for SPIR-V
// binary format, the null terminator is not expected. So we need to subtract
// the null terminator when loading SPIR-V binary.
+ assert((assemblySize == 0 ||
+ reinterpret_cast<char *>(data)[assemblySize - 1] == 0) &&
+ "Expected null terminator at the end of the assembly string.");
auto actualAssemblySize = assemblySize - 1;
return catchAll([&]() {
return loadModule(data, actualAssemblySize, ZE_MODULE_FORMAT_IL_SPIRV);
>From 102f4a8b818f76bdd65a8ecca43ab480cf03fefe Mon Sep 17 00:00:00 2001
From: "Shahneous Bari, Md Abdullah" <md.abdullah.shahneous.bari at intel.com>
Date: Fri, 3 Apr 2026 16:27:59 +0000
Subject: [PATCH 7/8] Address review comments.
Add asserts on assemblySize.
---
mlir/lib/ExecutionEngine/LevelZeroRuntimeWrappers.cpp | 2 ++
1 file changed, 2 insertions(+)
diff --git a/mlir/lib/ExecutionEngine/LevelZeroRuntimeWrappers.cpp b/mlir/lib/ExecutionEngine/LevelZeroRuntimeWrappers.cpp
index a5efc6b337080..f4f6afd958e6c 100644
--- a/mlir/lib/ExecutionEngine/LevelZeroRuntimeWrappers.cpp
+++ b/mlir/lib/ExecutionEngine/LevelZeroRuntimeWrappers.cpp
@@ -531,6 +531,8 @@ extern "C" ze_module_handle_t mgpuModuleLoadJIT(void *data, int optLevel,
reinterpret_cast<char *>(data)[assemblySize - 1] == 0) &&
"Expected null terminator at the end of the assembly string.");
auto actualAssemblySize = assemblySize - 1;
+ assert(actualAssemblySize % 4 == 0 &&
+ "SPIR-V binary size must be a multiple of 4");
return catchAll([&]() {
return loadModule(data, actualAssemblySize, ZE_MODULE_FORMAT_IL_SPIRV);
});
>From eee10ed854b613ee0a5e51f0568441cad5f9c842 Mon Sep 17 00:00:00 2001
From: "Shahneous Bari, Md Abdullah" <md.abdullah.shahneous.bari at intel.com>
Date: Fri, 3 Apr 2026 17:00:11 +0000
Subject: [PATCH 8/8] Address review comments.
---
mlir/lib/ExecutionEngine/LevelZeroRuntimeWrappers.cpp | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/mlir/lib/ExecutionEngine/LevelZeroRuntimeWrappers.cpp b/mlir/lib/ExecutionEngine/LevelZeroRuntimeWrappers.cpp
index f4f6afd958e6c..91dab05b5a652 100644
--- a/mlir/lib/ExecutionEngine/LevelZeroRuntimeWrappers.cpp
+++ b/mlir/lib/ExecutionEngine/LevelZeroRuntimeWrappers.cpp
@@ -530,7 +530,7 @@ extern "C" ze_module_handle_t mgpuModuleLoadJIT(void *data, int optLevel,
assert((assemblySize == 0 ||
reinterpret_cast<char *>(data)[assemblySize - 1] == 0) &&
"Expected null terminator at the end of the assembly string.");
- auto actualAssemblySize = assemblySize - 1;
+ size_t actualAssemblySize = assemblySize - 1;
assert(actualAssemblySize % 4 == 0 &&
"SPIR-V binary size must be a multiple of 4");
return catchAll([&]() {
More information about the Mlir-commits
mailing list