[Mlir-commits] [mlir] [mlir][SPIR-V] Deserialize replicated composites as attributes (PR #214469)
Niklas Lithammer
llvmlistbot at llvm.org
Thu Aug 6 05:30:51 PDT 2026
https://github.com/nlithammer created https://github.com/llvm/llvm-project/pull/214469
Some SPIR-V™ instructions encode attribute-like operands as IDs of constant composite instructions. Deserialization currently fails when such an operand is defined by OpConstantCompositeReplicateEXT instead of OpConstantComposite.
Materialize replicated composite constants as splat attributes when they are requested as constants. Check for replicated composites first when materializing SSA values so they remain
spirv.EXT.ConstantCompositeReplicate operations.
>From 2e46bfe9184ee87a134d420064416629b90e7bfe Mon Sep 17 00:00:00 2001
From: Niklas Lithammer <niklas.lithammer at arm.com>
Date: Mon, 20 Jul 2026 10:42:24 +0200
Subject: [PATCH] [mlir][SPIR-V] Deserialize replicated composites as
attributes
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Some SPIR-V™ instructions encode attribute-like operands as IDs of
constant composite instructions. Deserialization currently fails when
such an operand is defined by OpConstantCompositeReplicateEXT instead
of OpConstantComposite.
Materialize replicated composite constants as splat attributes when
they are requested as constants. Check for replicated composites first
when materializing SSA values so they remain
spirv.EXT.ConstantCompositeReplicate operations.
---
.../SPIRV/Deserialization/DeserializeOps.cpp | 12 ++---
.../SPIRV/Deserialization/Deserializer.cpp | 29 ++++++----
.../replicated-composite-tosa-attr.spvasm | 54 +++++++++++++++++++
3 files changed, 79 insertions(+), 16 deletions(-)
create mode 100644 mlir/test/Target/SPIRV/replicated-composite-tosa-attr.spvasm
diff --git a/mlir/lib/Target/SPIRV/Deserialization/DeserializeOps.cpp b/mlir/lib/Target/SPIRV/Deserialization/DeserializeOps.cpp
index 0e6d199eeabf0..66c77c61597d5 100644
--- a/mlir/lib/Target/SPIRV/Deserialization/DeserializeOps.cpp
+++ b/mlir/lib/Target/SPIRV/Deserialization/DeserializeOps.cpp
@@ -46,6 +46,12 @@ static NameLoc getLocFromDebugInfoString(OpBuilder &builder, StringRef source) {
//===----------------------------------------------------------------------===//
Value spirv::Deserializer::getValue(uint32_t id) {
+ if (std::optional<std::pair<Attribute, Type>> constCompositeReplicateInfo =
+ getConstantCompositeReplicate(id)) {
+ return spirv::EXTConstantCompositeReplicateOp::create(
+ opBuilder, unknownLoc, constCompositeReplicateInfo->second,
+ constCompositeReplicateInfo->first);
+ }
if (auto constInfo = getConstant(id)) {
// Materialize a `spirv.Constant` op at every use site.
Location loc = unknownLoc;
@@ -54,12 +60,6 @@ Value spirv::Deserializer::getValue(uint32_t id) {
return spirv::ConstantOp::create(opBuilder, loc, constInfo->second,
constInfo->first);
}
- if (std::optional<std::pair<Attribute, Type>> constCompositeReplicateInfo =
- getConstantCompositeReplicate(id)) {
- return spirv::EXTConstantCompositeReplicateOp::create(
- opBuilder, unknownLoc, constCompositeReplicateInfo->second,
- constCompositeReplicateInfo->first);
- }
if (auto varOp = getGlobalVariable(id)) {
auto addressOfOp =
spirv::AddressOfOp::create(opBuilder, unknownLoc, varOp.getType(),
diff --git a/mlir/lib/Target/SPIRV/Deserialization/Deserializer.cpp b/mlir/lib/Target/SPIRV/Deserialization/Deserializer.cpp
index 6cfe58c43596c..9e44f43ad889d 100644
--- a/mlir/lib/Target/SPIRV/Deserialization/Deserializer.cpp
+++ b/mlir/lib/Target/SPIRV/Deserialization/Deserializer.cpp
@@ -924,9 +924,18 @@ spirv::Deserializer::processGraphEndARM(ArrayRef<uint32_t> operands) {
std::optional<std::pair<Attribute, Type>>
spirv::Deserializer::getConstant(uint32_t id) {
auto constIt = constantMap.find(id);
- if (constIt == constantMap.end())
+ if (constIt != constantMap.end())
+ return constIt->getSecond();
+
+ auto replicatedConstIt = constantCompositeReplicateMap.find(id);
+ if (replicatedConstIt == constantCompositeReplicateMap.end())
return std::nullopt;
- return constIt->getSecond();
+
+ auto [value, type] = replicatedConstIt->getSecond();
+ auto shapedType = dyn_cast<ShapedType>(type);
+ if (!shapedType)
+ return std::nullopt;
+ return std::make_pair(SplatElementsAttr::get(shapedType, value), type);
}
std::optional<std::pair<Attribute, Type>>
@@ -1949,14 +1958,6 @@ LogicalResult spirv::Deserializer::processConstantCompositeReplicateEXT(
uint32_t resultID = operands[1];
uint32_t constantID = operands[2];
- std::optional<std::pair<Attribute, Type>> constantInfo =
- getConstant(constantID);
- if (constantInfo.has_value()) {
- constantCompositeReplicateMap.try_emplace(
- resultID, constantInfo.value().first, resultType);
- return success();
- }
-
std::optional<std::pair<Attribute, Type>> replicatedConstantCompositeInfo =
getConstantCompositeReplicate(constantID);
if (replicatedConstantCompositeInfo.has_value()) {
@@ -1965,6 +1966,14 @@ LogicalResult spirv::Deserializer::processConstantCompositeReplicateEXT(
return success();
}
+ std::optional<std::pair<Attribute, Type>> constantInfo =
+ getConstant(constantID);
+ if (constantInfo.has_value()) {
+ constantCompositeReplicateMap.try_emplace(
+ resultID, constantInfo.value().first, resultType);
+ return success();
+ }
+
return emitError(unknownLoc, "OpConstantCompositeReplicateEXT operand <id> ")
<< constantID
<< " must come from a normal constant or a "
diff --git a/mlir/test/Target/SPIRV/replicated-composite-tosa-attr.spvasm b/mlir/test/Target/SPIRV/replicated-composite-tosa-attr.spvasm
new file mode 100644
index 0000000000000..ec1d076702116
--- /dev/null
+++ b/mlir/test/Target/SPIRV/replicated-composite-tosa-attr.spvasm
@@ -0,0 +1,54 @@
+; RUN: %if spirv-tools %{ spirv-as --target-env spv1.6 %s -o - | mlir-translate --deserialize-spirv - -o - | FileCheck %s %}
+
+; CHECK: spirv.Tosa.Conv2D
+; CHECK-SAME: pad = [0, 0, 0, 0]
+; CHECK-SAME: stride = [1, 1]
+; CHECK-SAME: dilation = [1, 1]
+
+ OpCapability Shader
+ OpCapability TensorsARM
+ OpCapability GraphARM
+ OpCapability ReplicatedCompositesEXT
+ OpExtension "SPV_ARM_tensors"
+ OpExtension "SPV_ARM_graph"
+ OpExtension "SPV_EXT_replicated_composites"
+ %tosa = OpExtInstImport "TOSA.001000.1"
+ OpMemoryModel Logical GLSL450
+
+ %bool = OpTypeBool
+ %false = OpConstantFalse %bool
+ %uint = OpTypeInt 32 0
+ %uint_0 = OpConstant %uint 0
+ %uint_1 = OpConstant %uint 1
+ %uint_2 = OpConstant %uint 2
+ %uint_3 = OpConstant %uint 3
+ %uint_4 = OpConstant %uint 4
+ %float = OpTypeFloat 32
+ %float_0 = OpConstant %float 0
+
+ %array_1 = OpTypeArray %uint %uint_1
+ %array_2 = OpTypeArray %uint %uint_2
+ %array_4 = OpTypeArray %uint %uint_4
+ %shape_1 = OpConstantComposite %array_1 %uint_1
+ %shape_2 = OpConstantComposite %array_1 %uint_2
+ %shape_4 = OpConstantComposite %array_1 %uint_4
+%shape_1x1x1x1 = OpConstantComposite %array_4 %uint_1 %uint_1 %uint_1 %uint_1
+
+ %uint_s2 = OpTypeTensorARM %uint %uint_1 %shape_2
+ %uint_s4 = OpTypeTensorARM %uint %uint_1 %shape_4
+ %float_s1 = OpTypeTensorARM %float %uint_1 %shape_1
+%float_s1x1x1x1 = OpTypeTensorARM %float %uint_4 %shape_1x1x1x1
+
+ %pad = OpConstantComposite %uint_s4 %uint_0 %uint_0 %uint_0 %uint_0
+ %stride = OpConstantCompositeReplicateEXT %uint_s2 %uint_1
+ %dilation = OpConstantComposite %uint_s2 %uint_1 %uint_1
+ %zero_point = OpConstantComposite %float_s1 %float_0
+ %weights = OpGraphConstantARM %float_s1x1x1x1 0
+ %bias = OpGraphConstantARM %float_s1 1
+
+ %graph_type = OpTypeGraphARM 1 %float_s1x1x1x1 %float_s1x1x1x1
+ %graph = OpGraphARM %graph_type
+ %input = OpGraphInputARM %float_s1x1x1x1 %uint_0
+ %output = OpExtInst %float_s1x1x1x1 %tosa CONV2D %pad %stride %dilation %uint_3 %false %input %weights %bias %zero_point %zero_point
+ OpGraphSetOutputARM %output %uint_0
+ OpGraphEndARM
More information about the Mlir-commits
mailing list