[Mlir-commits] [mlir] [mlir][debug] Convert DbgIntrOp to DebugRecords directly. (PR #154926)

Abid Qadeer llvmlistbot at llvm.org
Tue Aug 26 03:55:12 PDT 2025


https://github.com/abidh updated https://github.com/llvm/llvm-project/pull/154926

>From eebfc31b09cac4d8259903413817dc4fe58d86bf Mon Sep 17 00:00:00 2001
From: Abid Qadeer <haqadeer at amd.com>
Date: Wed, 20 Aug 2025 18:08:04 +0100
Subject: [PATCH 1/2] [mlir] Convert to DebugRecords directly.

Currently the DbgIntrOp are first converted to llvm intrinsics
which are laterr translated to debug records by a call of
convertToNewDbgValues. This is not only inefficient but also makes
the code that works on intermediate IR unnecessarily complicated. This
PR converts the DbgIntrOp directly to debug records.

The conversion is relatively simple but there is a bit of code
repetition due to how the APIs in the DIBuilders are named. Also noticed
that DISubprogramAttr is inherited from DIScopeAttr while in llvm, the
DISubprogram inherits from DILocalScope. I am going to fix this
separately and then we could use FusedLocWith<LLVM::DILocalScopeAttr>
and cast to <DILocalScope> will be much safer.
---
 .../mlir/Dialect/LLVMIR/LLVMIntrinsicOps.td   | 81 ++++++++++++++-----
 .../LLVMIR/LLVMToLLVMIRTranslation.cpp        |  1 +
 mlir/lib/Target/LLVMIR/ModuleTranslation.cpp  |  5 --
 3 files changed, 60 insertions(+), 27 deletions(-)

diff --git a/mlir/include/mlir/Dialect/LLVMIR/LLVMIntrinsicOps.td b/mlir/include/mlir/Dialect/LLVMIR/LLVMIntrinsicOps.td
index 5e2461b4508e4..f964eb079a725 100644
--- a/mlir/include/mlir/Dialect/LLVMIR/LLVMIntrinsicOps.td
+++ b/mlir/include/mlir/Dialect/LLVMIR/LLVMIntrinsicOps.td
@@ -673,22 +673,6 @@ def LLVM_CoroPromiseOp : LLVM_IntrOp<"coro.promise", [], [], [], 1> {
 
 class LLVM_DbgIntrOp<string name, string argName, list<Trait> traits = []>
     : LLVM_IntrOp<name, [], [], traits, 0> {
-  let llvmBuilder = [{
-    // Debug intrinsics without debug locations are invalid.
-    if(!builder.getCurrentDebugLocation())
-      return success();
-    llvm::Module *module = builder.GetInsertBlock()->getModule();
-    llvm::LLVMContext &ctx = module->getContext();
-    llvm::Function *fn =
-      llvm::Intrinsic::getOrInsertDeclaration(module, llvm::Intrinsic::}]
-       # !subst(".", "_", name) # [{);
-    builder.CreateCall(fn, {
-        llvm::MetadataAsValue::get(ctx,
-            llvm::ValueAsMetadata::get(moduleTranslation.lookupValue(opInst.getOperand(0)))),
-        llvm::MetadataAsValue::get(ctx, moduleTranslation.translateDebugInfo($varInfo)),
-        llvm::MetadataAsValue::get(ctx, moduleTranslation.translateExpression($locationExpr)),
-      });
-  }];
   let mlirBuilder = [{
     // Add debug intrindic to the list of intrinsics that need to be converted once the
     // full function was converted.
@@ -711,6 +695,28 @@ def LLVM_DbgDeclareOp : LLVM_DbgIntrOp<"dbg.declare", "addr", [
     LLVM_DILocalVariableAttr:$varInfo,
     DefaultValuedAttr<LLVM_DIExpressionAttr, "{}">:$locationExpr
   );
+  let llvmBuilder = [{
+    // Debug intrinsics without debug locations are invalid.
+    if(!builder.getCurrentDebugLocation())
+      return success();
+    llvm::Function *parentFn = builder.GetInsertBlock()->getParent();
+    llvm::DILocalScope *scope;
+    if (auto scopeLoc =
+            opInst.getLoc()->findInstanceOf<FusedLocWith<LLVM::DIScopeAttr>>())
+      scope = llvm::cast<llvm::DILocalScope>(
+          moduleTranslation.translateDebugInfo(scopeLoc.getMetadata()));
+    else
+      scope = parentFn->getSubprogram();
+
+    llvm::Module *module = builder.GetInsertBlock()->getModule();
+    llvm::DIBuilder DB(*module);
+    DB.insertDeclare(moduleTranslation.lookupValue(opInst.getOperand(0)),
+                     llvm::cast<llvm::DILocalVariable>(
+                         moduleTranslation.translateDebugInfo($varInfo)),
+                     moduleTranslation.translateExpression($locationExpr),
+                     moduleTranslation.translateLoc(opInst.getLoc(), scope),
+                     builder.GetInsertPoint());
+  }];
 }
 
 def LLVM_DbgValueOp : LLVM_DbgIntrOp<"dbg.value", "value",
@@ -721,6 +727,29 @@ def LLVM_DbgValueOp : LLVM_DbgIntrOp<"dbg.value", "value",
     LLVM_DILocalVariableAttr:$varInfo,
     DefaultValuedAttr<LLVM_DIExpressionAttr, "{}">:$locationExpr
   );
+  let llvmBuilder = [{
+    // Debug intrinsics without debug locations are invalid.
+    if(!builder.getCurrentDebugLocation())
+      return success();
+    llvm::Function *parentFn = builder.GetInsertBlock()->getParent();
+    llvm::DILocalScope *scope;
+    if (auto scopeLoc =
+            opInst.getLoc()->findInstanceOf<FusedLocWith<LLVM::DIScopeAttr>>())
+      scope = llvm::cast<llvm::DILocalScope>(
+          moduleTranslation.translateDebugInfo(scopeLoc.getMetadata()));
+    else
+      scope = parentFn->getSubprogram();
+
+    llvm::Module *module = builder.GetInsertBlock()->getModule();
+    llvm::DIBuilder DB(*module);
+    DB.insertDbgValueIntrinsic(
+        moduleTranslation.lookupValue(opInst.getOperand(0)),
+        llvm::cast<llvm::DILocalVariable>(
+            moduleTranslation.translateDebugInfo($varInfo)),
+        moduleTranslation.translateExpression($locationExpr),
+        moduleTranslation.translateLoc(opInst.getLoc(), scope),
+        builder.GetInsertPoint());
+  }];
 }
 
 def LLVM_DbgLabelOp : LLVM_IntrOp<"dbg.label", [], [], [], 0> {
@@ -730,13 +759,21 @@ def LLVM_DbgLabelOp : LLVM_IntrOp<"dbg.label", [], [], [], 0> {
     // Debug intrinsics without debug locations are invalid.
     if(!builder.getCurrentDebugLocation())
       return success();
+    llvm::Function *parentFn = builder.GetInsertBlock()->getParent();
+    llvm::DILocalScope *scope;
+    if (auto scopeLoc =
+            opInst.getLoc()->findInstanceOf<FusedLocWith<LLVM::DIScopeAttr>>())
+      scope = llvm::cast<llvm::DILocalScope>(
+          moduleTranslation.translateDebugInfo(scopeLoc.getMetadata()));
+    else
+      scope = parentFn->getSubprogram();
+
     llvm::Module *module = builder.GetInsertBlock()->getModule();
-    llvm::LLVMContext &ctx = module->getContext();
-    llvm::Function *fn =
-      llvm::Intrinsic::getOrInsertDeclaration(module, llvm::Intrinsic::dbg_label);
-    builder.CreateCall(fn, {
-        llvm::MetadataAsValue::get(ctx, moduleTranslation.translateDebugInfo($label))
-      });
+    llvm::DIBuilder DB(*module);
+    DB.insertLabel(
+        llvm::cast<llvm::DILabel>(moduleTranslation.translateDebugInfo($label)),
+        moduleTranslation.translateLoc(opInst.getLoc(), scope),
+        builder.GetInsertPoint());
   }];
   let mlirBuilder = [{
     DILabelAttr labelAttr = $_label_attr($label);
diff --git a/mlir/lib/Target/LLVMIR/Dialect/LLVMIR/LLVMToLLVMIRTranslation.cpp b/mlir/lib/Target/LLVMIR/Dialect/LLVMIR/LLVMToLLVMIRTranslation.cpp
index 0f675a0a5df5d..611d8d1960e0e 100644
--- a/mlir/lib/Target/LLVMIR/Dialect/LLVMIR/LLVMToLLVMIRTranslation.cpp
+++ b/mlir/lib/Target/LLVMIR/Dialect/LLVMIR/LLVMToLLVMIRTranslation.cpp
@@ -18,6 +18,7 @@
 #include "mlir/Target/LLVMIR/ModuleTranslation.h"
 
 #include "llvm/ADT/TypeSwitch.h"
+#include "llvm/IR/DIBuilder.h"
 #include "llvm/IR/IRBuilder.h"
 #include "llvm/IR/InlineAsm.h"
 #include "llvm/IR/Instructions.h"
diff --git a/mlir/lib/Target/LLVMIR/ModuleTranslation.cpp b/mlir/lib/Target/LLVMIR/ModuleTranslation.cpp
index b3a06e2be7fe6..d9aae529d19b6 100644
--- a/mlir/lib/Target/LLVMIR/ModuleTranslation.cpp
+++ b/mlir/lib/Target/LLVMIR/ModuleTranslation.cpp
@@ -2407,11 +2407,6 @@ mlir::translateModuleToLLVMIR(Operation *module, llvm::LLVMContext &llvmContext,
   if (failed(translator.convertUnresolvedBlockAddress()))
     return nullptr;
 
-  // Once we've finished constructing elements in the module, we should convert
-  // it to use the debug info format desired by LLVM.
-  // See https://llvm.org/docs/RemoveDIsDebugInfo.html
-  translator.llvmModule->convertToNewDbgValues();
-
   // Add the necessary debug info module flags, if they were not encoded in MLIR
   // beforehand.
   translator.debugTranslation->addModuleFlagsIfNotPresent();

>From 68b60572a5aa052da25e0c100c99fe3e304b51bc Mon Sep 17 00:00:00 2001
From: Abid Qadeer <haqadeer at amd.com>
Date: Tue, 26 Aug 2025 11:40:13 +0100
Subject: [PATCH 2/2] Fix review comments.

1. Refactor some code into a separate function to avoid duplication.
2. Some name and comments update.
---
 .../mlir/Dialect/LLVMIR/LLVMIntrinsicOps.td   | 48 ++++++-------------
 .../LLVMIR/LLVMToLLVMIRTranslation.cpp        | 10 ++++
 2 files changed, 25 insertions(+), 33 deletions(-)

diff --git a/mlir/include/mlir/Dialect/LLVMIR/LLVMIntrinsicOps.td b/mlir/include/mlir/Dialect/LLVMIR/LLVMIntrinsicOps.td
index f964eb079a725..fa2e10c9cdee5 100644
--- a/mlir/include/mlir/Dialect/LLVMIR/LLVMIntrinsicOps.td
+++ b/mlir/include/mlir/Dialect/LLVMIR/LLVMIntrinsicOps.td
@@ -696,21 +696,15 @@ def LLVM_DbgDeclareOp : LLVM_DbgIntrOp<"dbg.declare", "addr", [
     DefaultValuedAttr<LLVM_DIExpressionAttr, "{}">:$locationExpr
   );
   let llvmBuilder = [{
-    // Debug intrinsics without debug locations are invalid.
+    // Debug records without debug locations are invalid.
     if(!builder.getCurrentDebugLocation())
       return success();
-    llvm::Function *parentFn = builder.GetInsertBlock()->getParent();
-    llvm::DILocalScope *scope;
-    if (auto scopeLoc =
-            opInst.getLoc()->findInstanceOf<FusedLocWith<LLVM::DIScopeAttr>>())
-      scope = llvm::cast<llvm::DILocalScope>(
-          moduleTranslation.translateDebugInfo(scopeLoc.getMetadata()));
-    else
-      scope = parentFn->getSubprogram();
+    llvm::DILocalScope *scope = getLocalScopeFromLoc(builder, opInst.getLoc(),
+                                                     moduleTranslation);
 
     llvm::Module *module = builder.GetInsertBlock()->getModule();
-    llvm::DIBuilder DB(*module);
-    DB.insertDeclare(moduleTranslation.lookupValue(opInst.getOperand(0)),
+    llvm::DIBuilder debugInfoBuilder(*module);
+    debugInfoBuilder.insertDeclare(moduleTranslation.lookupValue(opInst.getOperand(0)),
                      llvm::cast<llvm::DILocalVariable>(
                          moduleTranslation.translateDebugInfo($varInfo)),
                      moduleTranslation.translateExpression($locationExpr),
@@ -728,21 +722,15 @@ def LLVM_DbgValueOp : LLVM_DbgIntrOp<"dbg.value", "value",
     DefaultValuedAttr<LLVM_DIExpressionAttr, "{}">:$locationExpr
   );
   let llvmBuilder = [{
-    // Debug intrinsics without debug locations are invalid.
+    // Debug records without debug locations are invalid.
     if(!builder.getCurrentDebugLocation())
       return success();
-    llvm::Function *parentFn = builder.GetInsertBlock()->getParent();
-    llvm::DILocalScope *scope;
-    if (auto scopeLoc =
-            opInst.getLoc()->findInstanceOf<FusedLocWith<LLVM::DIScopeAttr>>())
-      scope = llvm::cast<llvm::DILocalScope>(
-          moduleTranslation.translateDebugInfo(scopeLoc.getMetadata()));
-    else
-      scope = parentFn->getSubprogram();
+    llvm::DILocalScope *scope = getLocalScopeFromLoc(builder, opInst.getLoc(),
+                                                     moduleTranslation);
 
     llvm::Module *module = builder.GetInsertBlock()->getModule();
-    llvm::DIBuilder DB(*module);
-    DB.insertDbgValueIntrinsic(
+    llvm::DIBuilder debugInfoBuilder(*module);
+    debugInfoBuilder.insertDbgValueIntrinsic(
         moduleTranslation.lookupValue(opInst.getOperand(0)),
         llvm::cast<llvm::DILocalVariable>(
             moduleTranslation.translateDebugInfo($varInfo)),
@@ -756,21 +744,15 @@ def LLVM_DbgLabelOp : LLVM_IntrOp<"dbg.label", [], [], [], 0> {
   let summary = "Relates the program to a debug information label.";
   let arguments = (ins LLVM_DILabelAttr:$label);
   let llvmBuilder = [{
-    // Debug intrinsics without debug locations are invalid.
+    // Debug records without debug locations are invalid.
     if(!builder.getCurrentDebugLocation())
       return success();
-    llvm::Function *parentFn = builder.GetInsertBlock()->getParent();
-    llvm::DILocalScope *scope;
-    if (auto scopeLoc =
-            opInst.getLoc()->findInstanceOf<FusedLocWith<LLVM::DIScopeAttr>>())
-      scope = llvm::cast<llvm::DILocalScope>(
-          moduleTranslation.translateDebugInfo(scopeLoc.getMetadata()));
-    else
-      scope = parentFn->getSubprogram();
+    llvm::DILocalScope *scope = getLocalScopeFromLoc(builder, opInst.getLoc(),
+                                                     moduleTranslation);
 
     llvm::Module *module = builder.GetInsertBlock()->getModule();
-    llvm::DIBuilder DB(*module);
-    DB.insertLabel(
+    llvm::DIBuilder debugInfoBuilder(*module);
+    debugInfoBuilder.insertLabel(
         llvm::cast<llvm::DILabel>(moduleTranslation.translateDebugInfo($label)),
         moduleTranslation.translateLoc(opInst.getLoc(), scope),
         builder.GetInsertPoint());
diff --git a/mlir/lib/Target/LLVMIR/Dialect/LLVMIR/LLVMToLLVMIRTranslation.cpp b/mlir/lib/Target/LLVMIR/Dialect/LLVMIR/LLVMToLLVMIRTranslation.cpp
index 611d8d1960e0e..70a4c2614c609 100644
--- a/mlir/lib/Target/LLVMIR/Dialect/LLVMIR/LLVMToLLVMIRTranslation.cpp
+++ b/mlir/lib/Target/LLVMIR/Dialect/LLVMIR/LLVMToLLVMIRTranslation.cpp
@@ -359,6 +359,16 @@ static void convertModuleFlagsOp(ArrayAttr flags, llvm::IRBuilderBase &builder,
   }
 }
 
+static llvm::DILocalScope *
+getLocalScopeFromLoc(llvm::IRBuilderBase &builder, Location loc,
+                     LLVM::ModuleTranslation &moduleTranslation) {
+  if (auto scopeLoc = loc->findInstanceOf<FusedLocWith<LLVM::DIScopeAttr>>())
+    if (llvm::DILocalScope *localScope = llvm::dyn_cast<llvm::DILocalScope>(
+            moduleTranslation.translateDebugInfo(scopeLoc.getMetadata())))
+      return localScope;
+  return builder.GetInsertBlock()->getParent()->getSubprogram();
+}
+
 static LogicalResult
 convertOperationImpl(Operation &opInst, llvm::IRBuilderBase &builder,
                      LLVM::ModuleTranslation &moduleTranslation) {



More information about the Mlir-commits mailing list