[Mlir-commits] [mlir] [mlir][spirv] Add SPIR-V NonSemantic.Graph.DebugInfo (PR #199519)

llvmlistbot at llvm.org llvmlistbot at llvm.org
Mon May 25 04:49:50 PDT 2026


llvmorg-github-actions[bot] wrote:


<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-mlir-spirv

@llvm/pr-subscribers-mlir-tosa

Author: Davide Grohmann (davidegrohmann)

<details>
<summary>Changes</summary>

Add serialization and deserialization support for the NonSemantic.Graph.DebugInfo.1 extended instruction set used with ARM graph modules.

Definition:
https://github.com/KhronosGroup/SPIRV-Registry/blob/main/nonsemantic/NonSemantic.Graph.DebugInfo.asciidoc

Serialize DebugGraph, DebugOperation, and DebugTensor records when debug info is enabled. DebugOperation now references the DebugGraph result id, and debug graph records are emitted before operations that reference them. DebugTensor records cover graph inputs, graph outputs, and tensor-typed spirv.Constant results.

Deserialize the debug records back into MLIR locations for graphs, TOSA operation results, tensors, and materialized tensor constants. Avoid default-inserting empty Values while applying debug records, and diagnose undefined debug ids instead.

Add round-trip lit coverage for FileLineColLoc, NameLoc, FusedLoc, grouped TOSA ops, and missing extension diagnostics. Add a binary-level serialization unit test for DebugGraph/DebugOperation references, ordering, and DebugTensor records for inputs, outputs, and constants.

---

Patch is 46.03 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/199519.diff


10 Files Affected:

- (added) mlir/include/mlir/Target/SPIRV/SPIRVExtInstSets.h (+40) 
- (modified) mlir/lib/Conversion/TosaToSPIRVTosa/TosaToSPIRVTosaPass.cpp (+1) 
- (modified) mlir/lib/Target/SPIRV/Deserialization/DeserializeOps.cpp (+108-2) 
- (modified) mlir/lib/Target/SPIRV/Deserialization/Deserializer.h (+8) 
- (modified) mlir/lib/Target/SPIRV/Serialization/SerializeOps.cpp (+161) 
- (modified) mlir/lib/Target/SPIRV/Serialization/Serializer.cpp (+40-5) 
- (modified) mlir/lib/Target/SPIRV/Serialization/Serializer.h (+28) 
- (added) mlir/test/Target/SPIRV/debug-info.mlir (+131) 
- (modified) mlir/unittests/Dialect/SPIRV/DeserializationTest.cpp (+46) 
- (modified) mlir/unittests/Dialect/SPIRV/SerializationTest.cpp (+206) 


``````````diff
diff --git a/mlir/include/mlir/Target/SPIRV/SPIRVExtInstSets.h b/mlir/include/mlir/Target/SPIRV/SPIRVExtInstSets.h
new file mode 100644
index 0000000000000..88ee32c5defb1
--- /dev/null
+++ b/mlir/include/mlir/Target/SPIRV/SPIRVExtInstSets.h
@@ -0,0 +1,40 @@
+//===- SPIRVExtInstSets.h - SPIR-V ext inst sets ----------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file declares extended instruction set constants used by SPIR-V
+// (de)serialization.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef MLIR_TARGET_SPIRV_SPIRVEXTINSTSETS_H
+#define MLIR_TARGET_SPIRV_SPIRVEXTINSTSETS_H
+
+#include "llvm/ADT/StringRef.h"
+#include <cstdint>
+
+namespace mlir {
+namespace spirv {
+
+/// Extension set name for TOSA ops.
+constexpr StringLiteral extTosa("TOSA.001000.1");
+
+/// Extension set name for non-semantic graph debug info.
+constexpr StringLiteral extDebugInfo("NonSemantic.Graph.DebugInfo.1");
+
+/// Instruction opcodes in the NonSemantic.Graph.DebugInfo.1 extended
+/// instruction set.
+enum class GraphDebugInfoExtInst : uint32_t {
+  DebugGraph = 1,
+  DebugOperation = 2,
+  DebugTensor = 3,
+};
+
+} // namespace spirv
+} // namespace mlir
+
+#endif // MLIR_TARGET_SPIRV_SPIRVEXTINSTSETS_H
diff --git a/mlir/lib/Conversion/TosaToSPIRVTosa/TosaToSPIRVTosaPass.cpp b/mlir/lib/Conversion/TosaToSPIRVTosa/TosaToSPIRVTosaPass.cpp
index bef30e84b3289..b5ae5c0275b26 100644
--- a/mlir/lib/Conversion/TosaToSPIRVTosa/TosaToSPIRVTosaPass.cpp
+++ b/mlir/lib/Conversion/TosaToSPIRVTosa/TosaToSPIRVTosaPass.cpp
@@ -51,6 +51,7 @@ spirv::VerCapExtAttr getDefaultVerCapExtAttr(MLIRContext *context) {
           spirv::Extension::SPV_EXT_replicated_composites,
           spirv::Extension::SPV_KHR_bfloat16,
           spirv::Extension::SPV_EXT_float8,
+          spirv::Extension::SPV_KHR_non_semantic_info,
       },
       context);
 }
diff --git a/mlir/lib/Target/SPIRV/Deserialization/DeserializeOps.cpp b/mlir/lib/Target/SPIRV/Deserialization/DeserializeOps.cpp
index f65b559ed1369..54cd47716a254 100644
--- a/mlir/lib/Target/SPIRV/Deserialization/DeserializeOps.cpp
+++ b/mlir/lib/Target/SPIRV/Deserialization/DeserializeOps.cpp
@@ -17,6 +17,7 @@
 #include "mlir/IR/Builders.h"
 #include "mlir/IR/Location.h"
 #include "mlir/Target/SPIRV/SPIRVBinaryUtils.h"
+#include "mlir/Target/SPIRV/SPIRVExtInstSets.h"
 #include "llvm/ADT/STLExtras.h"
 #include "llvm/ADT/SmallVector.h"
 #include "llvm/Support/Debug.h"
@@ -35,6 +36,12 @@ static inline spirv::Opcode extractOpcode(uint32_t word) {
   return static_cast<spirv::Opcode>(word & 0xffff);
 }
 
+/// Returns a NameLoc location from the given debug info string.
+static inline NameLoc getLocFromDebugInfoString(OpBuilder &builder,
+                                                StringRef source) {
+  return NameLoc::get(builder.getStringAttr(source));
+}
+
 //===----------------------------------------------------------------------===//
 // Instruction
 //===----------------------------------------------------------------------===//
@@ -42,7 +49,10 @@ static inline spirv::Opcode extractOpcode(uint32_t word) {
 Value spirv::Deserializer::getValue(uint32_t id) {
   if (auto constInfo = getConstant(id)) {
     // Materialize a `spirv.Constant` op at every use site.
-    return spirv::ConstantOp::create(opBuilder, unknownLoc, constInfo->second,
+    Location loc = unknownLoc;
+    if (auto locAttr = constantLocMap.lookup(id))
+      loc = Location(locAttr);
+    return spirv::ConstantOp::create(opBuilder, loc, constInfo->second,
                                      constInfo->first);
   }
   if (std::optional<std::pair<Attribute, Type>> constCompositeReplicateInfo =
@@ -171,8 +181,13 @@ LogicalResult spirv::Deserializer::processInstruction(
     return processCapability(operands);
   case spirv::Opcode::OpExtension:
     return processExtension(operands);
-  case spirv::Opcode::OpExtInst:
+  case spirv::Opcode::OpExtInst: {
+    auto setIt = operands.size() >= 4 ? extendedInstSets.find(operands[2])
+                                      : extendedInstSets.end();
+    if (setIt != extendedInstSets.end() && setIt->second == extDebugInfo)
+      return processDebugInfoExtInst(operands, deferInstructions);
     return processExtInst(operands);
+  }
   case spirv::Opcode::OpExtInstImport:
     return processExtInstImport(operands);
   case spirv::Opcode::OpMemberName:
@@ -388,6 +403,97 @@ LogicalResult spirv::Deserializer::processUndef(ArrayRef<uint32_t> operands) {
   return success();
 }
 
+LogicalResult
+spirv::Deserializer::processDebugInfoExtInst(ArrayRef<uint32_t> operands,
+                                             bool deferInstructions) {
+  if (deferInstructions) {
+    deferredInstructions.emplace_back(spirv::Opcode::OpExtInst, operands);
+    return success();
+  }
+
+  if (operands.size() < 4) {
+    return emitError(unknownLoc,
+                     "OpExtInst must have at least 4 operands, result type "
+                     "<id>, result <id>, set <id> and instruction opcode");
+  }
+
+  auto &extensionSetName = extendedInstSets[operands[2]];
+  assert(extensionSetName == extDebugInfo);
+
+  auto getDebugLoc = [&](uint32_t stringID) -> FailureOr<Location> {
+    auto stringIt = debugInfoMap.find(stringID);
+    if (stringIt == debugInfoMap.end()) {
+      emitError(unknownLoc, "undefined string <id> ")
+          << stringID << " in DebugInfo";
+      return failure();
+    }
+    Location loc = getLocFromDebugInfoString(opBuilder, stringIt->second);
+    return loc;
+  };
+
+  auto instructionID = static_cast<spirv::GraphDebugInfoExtInst>(operands[3]);
+  switch (instructionID) {
+  case spirv::GraphDebugInfoExtInst::DebugGraph: {
+    if (operands.size() < 6)
+      return emitError(unknownLoc, "DebugGraph must have graph and string IDs");
+    auto &graphID = operands[4];
+    auto &stringID = operands[5];
+    auto graphIt = graphMap.find(graphID);
+    if (graphIt == graphMap.end())
+      return emitError(unknownLoc, "undefined graph <id> ")
+             << graphID << " in DebugGraph";
+    FailureOr<Location> loc = getDebugLoc(stringID);
+    if (failed(loc))
+      return failure();
+    graphIt->second->setLoc(*loc);
+    break;
+  }
+  case spirv::GraphDebugInfoExtInst::DebugOperation: {
+    if (operands.size() < 7)
+      return emitError(unknownLoc,
+                       "DebugOperation must have graph, string and "
+                       "instruction IDs");
+    auto &stringID = operands[5];
+    FailureOr<Location> loc = getDebugLoc(stringID);
+    if (failed(loc))
+      return failure();
+    SmallVector<uint32_t> operationIDs;
+    operationIDs.append(std::next(operands.begin(), 6), operands.end());
+    for (auto &operationID : operationIDs) {
+      auto valueIt = valueMap.find(operationID);
+      if (valueIt == valueMap.end())
+        return emitError(unknownLoc, "undefined operation <id> ")
+               << operationID << " in DebugOperation";
+      valueIt->second.setLoc(*loc);
+    }
+    break;
+  }
+  case spirv::GraphDebugInfoExtInst::DebugTensor: {
+    if (operands.size() < 6)
+      return emitError(unknownLoc, "DebugTensor must have tensor and string IDs");
+    auto &stringID = operands[5];
+    auto &tensorID = operands[4];
+    FailureOr<Location> loc = getDebugLoc(stringID);
+    if (failed(loc))
+      return failure();
+    if (constantMap.contains(tensorID)) {
+      constantLocMap[tensorID] = *loc;
+      break;
+    }
+    auto valueIt = valueMap.find(tensorID);
+    if (valueIt == valueMap.end())
+      return emitError(unknownLoc, "undefined tensor <id> ")
+             << tensorID << " in DebugTensor";
+    valueIt->second.setLoc(*loc);
+    break;
+  }
+  default:
+    return failure();
+  }
+
+  return success();
+}
+
 LogicalResult spirv::Deserializer::processExtInst(ArrayRef<uint32_t> operands) {
   if (operands.size() < 4) {
     return emitError(unknownLoc,
diff --git a/mlir/lib/Target/SPIRV/Deserialization/Deserializer.h b/mlir/lib/Target/SPIRV/Deserialization/Deserializer.h
index b2adbb5518789..d2b7dbaad4655 100644
--- a/mlir/lib/Target/SPIRV/Deserialization/Deserializer.h
+++ b/mlir/lib/Target/SPIRV/Deserialization/Deserializer.h
@@ -563,6 +563,11 @@ class Deserializer {
   /// other entries.
   LogicalResult processExtInst(ArrayRef<uint32_t> operands);
 
+  /// Processes a SPIR-V OpExtInst with given `operands` for a DebugInfo
+  /// extension instruction.
+  LogicalResult processDebugInfoExtInst(ArrayRef<uint32_t> operands,
+                                        bool deferInstructions);
+
   /// Dispatches the deserialization of extended instruction set operation based
   /// on the extended instruction set name, and instruction opcode. This is
   /// autogenerated from ODS.
@@ -632,6 +637,9 @@ class Deserializer {
   /// (and type) here. Later when it's used, we materialize the constant.
   DenseMap<uint32_t, std::pair<Attribute, Type>> constantMap;
 
+  // Result <id> to debug location for constants materialized from constantMap.
+  DenseMap<uint32_t, LocationAttr> constantLocMap;
+
   // Result <id> to replicated constant attribute and type mapping.
   ///
   /// In the SPIR-V binary format, OpConstantCompositeReplicateEXT is placed in
diff --git a/mlir/lib/Target/SPIRV/Serialization/SerializeOps.cpp b/mlir/lib/Target/SPIRV/Serialization/SerializeOps.cpp
index 841fc55a8627a..83341519fbc9e 100644
--- a/mlir/lib/Target/SPIRV/Serialization/SerializeOps.cpp
+++ b/mlir/lib/Target/SPIRV/Serialization/SerializeOps.cpp
@@ -16,6 +16,7 @@
 #include "mlir/Dialect/SPIRV/IR/SPIRVEnums.h"
 #include "mlir/IR/RegionGraphTraits.h"
 #include "mlir/Target/SPIRV/SPIRVBinaryUtils.h"
+#include "mlir/Target/SPIRV/SPIRVExtInstSets.h"
 #include "llvm/ADT/DepthFirstIterator.h"
 #include "llvm/ADT/StringExtras.h"
 #include "llvm/Support/Debug.h"
@@ -24,6 +25,33 @@
 
 using namespace mlir;
 
+namespace {
+// Location::print() emits MLIR syntax such as `loc("name")` or
+// `loc(fused["op", "file":1:2])`. NonSemantic.Graph.DebugInfo stores the
+// source/debug name itself in an OpString, so keep this conversion to the
+// payload string explicit.
+std::string getDebugInfoStringFromLoc(Location loc) {
+  if (auto fileLineCol = dyn_cast<FileLineColLoc>(loc)) {
+    return fileLineCol.getFilename().str() + ":" +
+           std::to_string(fileLineCol.getLine()) + ":" +
+           std::to_string(fileLineCol.getColumn());
+  }
+  if (auto nameLoc = dyn_cast<NameLoc>(loc)) {
+    return nameLoc.getName().str();
+  }
+  if (auto fusedLoc = dyn_cast<FusedLoc>(loc)) {
+    std::ostringstream result;
+    std::transform(
+        fusedLoc.getLocations().begin(), fusedLoc.getLocations().end(),
+        std::ostream_iterator<std::string>(result, ";"),
+        [&](const Location loc) { return getDebugInfoStringFromLoc(loc); });
+
+    return result.str();
+  }
+  return "";
+}
+} // namespace
+
 /// A pre-order depth-first visitor function for processing basic blocks.
 ///
 /// Visits the basic blocks starting from the given `headerBlock` in pre-order
@@ -61,6 +89,9 @@ LogicalResult Serializer::processConstantOp(spirv::ConstantOp op) {
   if (auto resultID =
           prepareConstant(op.getLoc(), op.getType(), op.getValue())) {
     valueIDMap[op.getResult()] = resultID;
+    if (isa<spirv::TensorArmType>(op.getType()) &&
+        failed(encodeDebugInfoTensorInst(op.getResult())))
+      return failure();
     return success();
   }
   return failure();
@@ -386,6 +417,121 @@ LogicalResult Serializer::processFuncOp(spirv::FuncOp op) {
   return success();
 }
 
+LogicalResult Serializer::encodeDebugStringInst(const std::string &str,
+                                                uint32_t &stringID) {
+  if (!options.emitDebugInfo)
+    return success();
+
+  SmallVector<uint32_t, 2> operands;
+  stringID = getNextID();
+  operands.push_back(stringID);
+  spirv::encodeStringLiteralInto(operands, str);
+  encodeInstructionInto(debug, spirv::Opcode::OpString, operands);
+
+  return success();
+}
+
+LogicalResult Serializer::encodeDebugInfoGraphInst(spirv::GraphARMOp op,
+                                                   uint32_t &debugGraphID) {
+  if (!options.emitDebugInfo)
+    return success();
+
+  processVoidType(typesGlobalValues);
+
+  uint32_t stringID = 0;
+  if (failed(encodeDebugStringInst(getDebugInfoStringFromLoc(op.getLoc()),
+                                   stringID)))
+    return failure();
+
+  SmallVector<uint32_t, 6> operands;
+  operands.push_back(getTypeID(getVoidType()));
+  debugGraphID = getNextID();
+  operands.push_back(debugGraphID);
+  uint32_t graphID = getOrCreateFunctionID(op.getName());
+  operands.push_back(graphID);
+  operands.push_back(stringID);
+
+  if (failed(encodeExtensionInstruction(
+          nullptr, extDebugInfo,
+          static_cast<uint32_t>(GraphDebugInfoExtInst::DebugGraph), operands,
+          graphsDebugInfo)))
+    return failure();
+
+  return success();
+}
+
+LogicalResult
+Serializer::encodeDebugInfoOperationInst(uint32_t debugGraphID,
+                                         SetVector<Operation *> ops) {
+  if (!options.emitDebugInfo)
+    return success();
+
+  if (ops.empty())
+    return success();
+
+  SmallVector<uint32_t, 4> instructionIDs;
+  for (auto op : ops)
+    for (auto result : op->getOpResults())
+      instructionIDs.push_back(getValueID(result));
+
+  if (instructionIDs.empty())
+    return success();
+
+  processVoidType(typesGlobalValues);
+
+  uint32_t stringID = 0;
+  if (failed(encodeDebugStringInst(getDebugInfoStringFromLoc(ops[0]->getLoc()),
+                                   stringID)))
+    return failure();
+
+  SmallVector<uint32_t, 5> operands;
+  operands.push_back(getTypeID(getVoidType()));
+  operands.push_back(getNextID());
+  operands.push_back(debugGraphID);
+  operands.push_back(stringID);
+  operands.append(instructionIDs);
+
+  if (failed(encodeExtensionInstruction(
+          nullptr, extDebugInfo,
+          static_cast<uint32_t>(GraphDebugInfoExtInst::DebugOperation),
+          operands,
+          graphsDebugInfo)))
+    return failure();
+
+  return success();
+}
+
+LogicalResult Serializer::encodeDebugInfoTensorInst(Value tensor) {
+  if (!options.emitDebugInfo)
+    return success();
+
+  processVoidType(typesGlobalValues);
+
+  auto it = valueIDMap.find(tensor);
+  if (it == valueIDMap.end())
+    return success();
+  auto tensorID = it->second;
+
+  uint32_t stringID = 0;
+  if (failed(encodeDebugStringInst(getDebugInfoStringFromLoc(tensor.getLoc()),
+                                   stringID)))
+    return failure();
+
+  SmallVector<uint32_t, 4> operands;
+  operands.push_back(getTypeID(getVoidType()));
+  operands.push_back(getNextID());
+  operands.push_back(tensorID);
+  operands.push_back(stringID);
+
+  if (failed(encodeExtensionInstruction(
+          nullptr, extDebugInfo,
+          static_cast<uint32_t>(GraphDebugInfoExtInst::DebugTensor), operands,
+          graphsDebugInfo)))
+    return failure();
+
+  return success();
+}
+
 LogicalResult Serializer::processGraphARMOp(spirv::GraphARMOp op) {
   if (op.getNumResults() < 1) {
     return op.emitError("cannot serialize graph with no return types");
@@ -423,6 +569,9 @@ LogicalResult Serializer::processGraphARMOp(spirv::GraphARMOp op) {
 
     encodeInstructionInto(functionHeader, spirv::Opcode::OpGraphInputARM,
                           inputOperands);
+
+    if (failed(encodeDebugInfoTensorInst(arg)))
+      return failure();
   }
 
   if (failed(processBlock(&op.front(), /*omitLabel=*/true)))
@@ -443,6 +592,15 @@ LogicalResult Serializer::processGraphARMOp(spirv::GraphARMOp op) {
   functionHeader.clear();
   functionBody.clear();
 
+  uint32_t debugGraphID = 0;
+  if (failed(encodeDebugInfoGraphInst(op, debugGraphID)))
+    return failure();
+
+  for (const auto &[loc, ops] : tosaOpsMap[funcID]) {
+    if (failed(encodeDebugInfoOperationInst(debugGraphID, ops)))
+      return failure();
+  }
+
   return success();
 }
 
@@ -492,6 +650,9 @@ Serializer::processGraphOutputsARMOp(spirv::GraphOutputsARMOp op) {
     outputOperands.push_back(outputID);
     outputOperands.push_back(indexID);
 
+    if (failed(encodeDebugInfoTensorInst(value)))
+      return failure();
+
     encodeInstructionInto(functionBody, spirv::Opcode::OpGraphSetOutputARM,
                           outputOperands);
   }
diff --git a/mlir/lib/Target/SPIRV/Serialization/Serializer.cpp b/mlir/lib/Target/SPIRV/Serialization/Serializer.cpp
index 11a7bf66d792d..553fcce6c5ea7 100644
--- a/mlir/lib/Target/SPIRV/Serialization/Serializer.cpp
+++ b/mlir/lib/Target/SPIRV/Serialization/Serializer.cpp
@@ -173,6 +173,7 @@ void Serializer::collect(SmallVectorImpl<uint32_t> &binary) {
   binary.append(typesGlobalValues.begin(), typesGlobalValues.end());
   binary.append(functions.begin(), functions.end());
   binary.append(graphs.begin(), graphs.end());
+  binary.append(graphsDebugInfo.begin(), graphsDebugInfo.end());
 }
 
 #ifndef NDEBUG
@@ -632,6 +633,16 @@ Serializer::processTypeImpl(Location loc, Type type, uint32_t &typeID,
   return emitError(loc, "failed to process type: ") << type;
 }
 
+void Serializer::processVoidType(SmallVectorImpl<uint32_t> &binary) {
+  auto voidType = getVoidType();
+  uint32_t voidTypeID = getTypeID(voidType);
+  if (!voidTypeID) {
+    voidTypeID = getNextID();
+    encodeInstructionInto(binary, spirv::Opcode::OpTypeVoid, {voidTypeID});
+    typeIDMap[voidType] = voidTypeID;
+  }
+}
+
 LogicalResult Serializer::prepareBasicType(
     Location loc, Type type, uint32_t resultID, spirv::Opcode &typeEnum,
     SmallVectorImpl<uint32_t> &operands, bool &deferSerialization,
@@ -1612,7 +1623,7 @@ LogicalResult Serializer::emitPhiForBlockArguments(Block *block) {
 
 LogicalResult Serializer::encodeExtensionInstruction(
     Operation *op, StringRef extensionSetName, uint32_t extensionOpcode,
-    ArrayRef<uint32_t> operands) {
+    ArrayRef<uint32_t> operands, SmallVectorImpl<uint32_t> &binary) {
   // Check if the extension has been imported.
   auto &setID = extendedInstSetIDMap[extensionSetName];
   if (!setID) {
@@ -1635,8 +1646,20 @@ LogicalResult Serializer::encodeExtensionInstruction(
   extInstOperands.push_back(setID);
   extInstOperands.push_back(extensionOpcode);
   extInstOperands.append(std::next(operands.begin(), 2), operands.end());
-  encodeInstructionInto(functionBody, spirv::Opcode::OpExtInst,
-                        extInstOperands);
+  encodeInstructionInto(binary, spirv::Opcode::OpExtInst, extInstOperands);
+  return success();
+}
+
+LogicalResult Serializer::encodeExtensionInstruction(
+    Operation *op, StringRef extensionSetName, uint32_t extensionOpcode,
+    ArrayRef<uint32_t> operands) {
+  if (failed(encodeExtensionInstruction(op, extensionSetName, extensionOpcode,
+                                        operands, functionBody)))
+    return failure();
+
+  if (extensionSetName == extTosa)
+    updateTosaOpsMap(op);
+
   return success();
 }
 
@@ -1751,8 +1774,10 @@ LogicalResult Serializer::processOpWithoutGrammarAttr(Operation *op,
   for (Value operand : op->getOperands())
     operands.push_back(getValueID(operand));
 
-  if (failed(emitDebugLine(functionBody, loc)))
-    return failure();
+  if (extInstSet != extTosa)
+    // OpLine cannot be present in graphs
+    if (failed(emitDebugLine(functionBody, loc)))
+      return failure();
 
   if (extInstSet.empty()) {
     encodeInstructionInto(functionBody, static_cast<spirv::Opcode>(opcode),
@@ -1772,6 +1797,16 @@ LogicalResult Serializer::processOpWithoutGrammarAttr(Operation *op,
   return success();
 }
 
+void Serializer::updateTosaOpsMap(Operation *op) {
+  if (!options.emitDebugInfo)
+    return;
+
+  if (auto graphOp = dyn_cast<spirv::GraphARMOp>(op->getParentOp())) {
+    if (auto graphID = getFunctionID(graphOp.getName()))
+      tosaOpsMap[graphID][op->getLoc()].insert(op);
+  }
+}
+
 LogicalResult Serializer::emitDecoration(uint32_t target,
                                          spirv::Decoration decoration,
                                          ArrayRef<uint32_t> params) {
diff --git a/mlir/lib/Target/SPIRV/Serialization/Serializer.h b/mlir/lib/Target/SPIRV/...
[truncated]

``````````

</details>


https://github.com/llvm/llvm-project/pull/199519


More information about the Mlir-commits mailing list