[llvm] [DirectX] Lower DbgAssign to DbgValue (PR #200267)
Harald van Dijk via llvm-commits
llvm-commits at lists.llvm.org
Mon Jun 8 09:09:46 PDT 2026
https://github.com/hvdijk updated https://github.com/llvm/llvm-project/pull/200267
>From 0d6c97caeeb5c07e25687e7d453e27fecf4ad3bf Mon Sep 17 00:00:00 2001
From: Harald van Dijk <hdijk at accesssoftek.com>
Date: Thu, 28 May 2026 19:23:15 +0100
Subject: [PATCH 1/4] [DirectX] Lower DbgAssign to DbgValue
DbgAssign is not representable in LLVM 3.7.
---
.../DirectX/DirectXIRPasses/DXILDebugInfo.cpp | 106 ++++++++++++++++--
llvm/test/tools/dxil-dis/dbg-assign.ll | 42 +++++++
2 files changed, 141 insertions(+), 7 deletions(-)
create mode 100644 llvm/test/tools/dxil-dis/dbg-assign.ll
diff --git a/llvm/lib/Target/DirectX/DirectXIRPasses/DXILDebugInfo.cpp b/llvm/lib/Target/DirectX/DirectXIRPasses/DXILDebugInfo.cpp
index 0fa81186000f9..138c2011f263f 100644
--- a/llvm/lib/Target/DirectX/DirectXIRPasses/DXILDebugInfo.cpp
+++ b/llvm/lib/Target/DirectX/DirectXIRPasses/DXILDebugInfo.cpp
@@ -8,6 +8,8 @@
#include "DXILDebugInfo.h"
#include "llvm/BinaryFormat/Dwarf.h"
+#include "llvm/IR/AttributeMask.h"
+#include "llvm/IR/Attributes.h"
#include "llvm/IR/DebugInfo.h"
#include "llvm/IR/Instructions.h"
#include "llvm/IR/IntrinsicsDirectX.h"
@@ -68,14 +70,103 @@ DXILDebugInfoMap DXILDebugInfoPass::run(Module &M) {
DebugInfoFinder DIF;
DIF.processModule(M);
- for (auto &F : M) {
- for (auto &BB : F) {
- for (auto &I : make_early_inc_range(reverse(BB))) {
+ Function *DVDecl = nullptr;
+
+ for (Function &F : M) {
+ bool IsEntryBlock = true;
+ for (BasicBlock &BB : F) {
+ DenseMap<DILocalVariable *, std::pair<Instruction *, DbgValueInst *>>
+ DbgValues;
+ DenseMap<std::pair<DILocalVariable *, DIExpression *>,
+ std::pair<Instruction *, DbgValueInst *>>
+ DbgValueFragments;
+ Instruction *NextNonDebugInst = nullptr;
+ for (Instruction &I : make_early_inc_range(reverse(BB))) {
+ I.eraseMetadataIf([](unsigned KindID, MDNode *) {
+ return KindID == LLVMContext::MD_DIAssignID;
+ });
+ if (!isa<DbgInfoIntrinsic>(I)) {
+ NextNonDebugInst = &I;
+ continue;
+ }
if (auto *DL = dyn_cast<DbgLabelInst>(&I)) {
DL->eraseFromParent();
continue;
}
+ // Process both llvm.dbg.value and llvm.dbg.assign here. We convert
+ // llvm.dbg.assign to llvm.dbg.value by dropping the last arguments, and
+ // remove redundant llvm.dbg.values.
+ if (auto *DV = dyn_cast<DbgValueInst>(&I)) {
+ // Keep track of the last location where we saw any debug value for a
+ // variable.
+ DILocalVariable *V = DV->getVariable();
+ DIExpression *E = DV->getExpression();
+ std::pair<Instruction *, DbgValueInst *> &DbgValue = DbgValues[V];
+ std::pair<Instruction *, DbgValueInst *> &DbgValueFragment =
+ DbgValueFragments[{V, E}];
+ if (DbgValue.second) {
+ // If there is a later value of the same fragment at the same
+ // location, this value is redundant.
+ if (DbgValueFragment.first == NextNonDebugInst) {
+ DV->eraseFromParent();
+ continue;
+ }
+ // If there is a later identical value of the same fragment at a
+ // later point, and there have been no intervening values of
+ // different possibly overlapping fragments, that later value is
+ // redundant.
+ if (DbgValueFragment.second &&
+ DbgValueFragment.second == DbgValue.second &&
+ DbgValueFragment.second->getValue() == DV->getValue()) {
+ DbgValue.second->eraseFromParent();
+ }
+ }
+ // If this is already an llvm.dbg.value instruction, just keep it,
+ // otherwise convert it.
+ DbgValueInst *NewDV;
+ if (DV->getIntrinsicID() == Intrinsic::dbg_value) {
+ NewDV = DV;
+ } else {
+ if (!DVDecl) {
+ DVDecl =
+ Intrinsic::getOrInsertDeclaration(&M, Intrinsic::dbg_value);
+ AttributeMask AM;
+ for (Attribute A : DVDecl->getAttributes().getFnAttrs())
+ if (A.isStringAttribute() ||
+ (A.getKindAsEnum() != Attribute::NoUnwind &&
+ A.getKindAsEnum() != Attribute::Memory))
+ AM.addAttribute(A);
+ DVDecl->removeFnAttrs(AM);
+ }
+ NewDV = cast<DbgValueInst>(
+ CallInst::Create(DVDecl,
+ {DV->getArgOperand(0), DV->getArgOperand(1),
+ DV->getArgOperand(2)},
+ {}, "", std::next(DV->getIterator())));
+ NewDV->setTailCall();
+ NewDV->setDebugLoc(DV->getDebugLoc());
+ DV->eraseFromParent();
+ }
+ DbgValue = DbgValueFragment = {NextNonDebugInst, NewDV};
+ continue;
+ }
+ }
+ // If this is the entry block, if the first value we see for each debug
+ // value is undef, it is redundant.
+ if (IsEntryBlock) {
+ DenseSet<DILocalVariable *> Seen;
+ for (Instruction &I : make_early_inc_range(BB)) {
+ auto *DV = dyn_cast<DbgValueInst>(&I);
+ if (!DV || Seen.contains(DV->getVariable()))
+ continue;
+ if (isa<UndefValue>(DV->getValue())) {
+ DV->eraseFromParent();
+ continue;
+ }
+ Seen.insert(DV->getVariable());
+ }
}
+ IsEntryBlock = false;
}
}
@@ -177,10 +268,11 @@ DXILDebugInfoMap DXILDebugInfoPass::run(Module &M) {
if (auto *SR = dyn_cast<DISubrangeType>(T)) {
DIType *BT = SR->getBaseType();
if (!BT)
- BT = DIBasicType::get(
- SR->getContext(), dwarf::DW_TAG_base_type, SR->getName(),
- SR->getSizeInBits(), SR->getAlignInBits(), dwarf::DW_ATE_unsigned,
- SR->getNumExtraInhabitants(), /*DataSizeInBits=*/0, SR->getFlags());
+ BT = DIBasicType::get(SR->getContext(), dwarf::DW_TAG_base_type,
+ SR->getName(), SR->getSizeInBits(),
+ SR->getAlignInBits(), dwarf::DW_ATE_unsigned,
+ SR->getNumExtraInhabitants(),
+ /*DataSizeInBits=*/0, SR->getFlags());
Res.MDReplace.insert({T, BT});
}
}
diff --git a/llvm/test/tools/dxil-dis/dbg-assign.ll b/llvm/test/tools/dxil-dis/dbg-assign.ll
new file mode 100644
index 0000000000000..5ae256cc74794
--- /dev/null
+++ b/llvm/test/tools/dxil-dis/dbg-assign.ll
@@ -0,0 +1,42 @@
+;; RUN: llc --filetype=obj -o - %s | dxil-dis -o - | FileCheck %s
+
+target triple = "dxil-pc-shadermodel6.3-library"
+
+;; CHECK: define i32 @dbgassign(i32 %a, i32 %b) {
+;; CHECK-NEXT: entry:
+;; CHECK-NEXT: call void @llvm.dbg.value(metadata i32 %a, i64 0, metadata [[LV:![0-9]+]], metadata [[EX:![0-9]+]])
+;; CHECK-NEXT: %add = add nsw i32 %a, %b
+;; CHECK-NEXT: call void @llvm.dbg.value(metadata i32 %add, i64 0, metadata [[LV]], metadata [[EX]])
+;; CHECK-NEXT: ret i32 %add
+;; CHECK-NEXT: }
+
+define i32 @dbgassign(i32 %a, i32 %b) !dbg !5 {
+entry:
+ #dbg_assign(i1 poison, !10, !DIExpression(), !11, ptr poison, !DIExpression(), !12)
+ #dbg_assign(i32 0, !10, !DIExpression(), !13, ptr poison, !DIExpression(), !12)
+ #dbg_assign(i32 %a, !10, !DIExpression(), !14, ptr poison, !DIExpression(), !12)
+ %add = add nsw i32 %a, %b, !dbg !15
+ #dbg_assign(i32 %add, !10, !DIExpression(), !16, ptr poison, !DIExpression(), !12)
+ ret i32 %add
+}
+
+!llvm.dbg.cu = !{!0}
+!llvm.module.flags = !{!2, !3, !4}
+
+!0 = distinct !DICompileUnit(language: DW_LANG_C11, file: !1, producer: "clang", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, splitDebugInlining: false, nameTableKind: None)
+!1 = !DIFile(filename: "dbgassign.c", directory: "")
+!2 = !{i32 7, !"Dwarf Version", i32 4}
+!3 = !{i32 2, !"Debug Info Version", i32 3}
+!4 = !{i32 7, !"debug-info-assignment-tracking", i1 true}
+!5 = distinct !DISubprogram(name: "dbgassign", scope: !1, file: !1, line: 2, type: !6, scopeLine: 2, flags: DIFlagPrototyped | DIFlagAllCallsDescribed, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !0, retainedNodes: !9, keyInstructions: true)
+!6 = !DISubroutineType(types: !7)
+!7 = !{!8, !8, !8}
+!8 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed)
+!9 = !{!10}
+!10 = !DILocalVariable(name: "result", scope: !5, file: !1, line: 3, type: !8)
+!11 = distinct !DIAssignID()
+!12 = !DILocation(line: 0, scope: !5)
+!13 = distinct !DIAssignID()
+!14 = distinct !DIAssignID()
+!15 = !DILocation(line: 7, column: 10, scope: !5, atomGroup: 3, atomRank: 2)
+!16 = distinct !DIAssignID()
>From a4f4dd98e2a0a693c90085cc98304c4d46f39a97 Mon Sep 17 00:00:00 2001
From: Harald van Dijk <hdijk at accesssoftek.com>
Date: Thu, 4 Jun 2026 23:15:09 +0100
Subject: [PATCH 2/4] Add CodeGen test
---
.../CodeGen/DirectX/DebugInfo/dbg-assign.ll | 45 +++++++++++++++++++
1 file changed, 45 insertions(+)
create mode 100644 llvm/test/CodeGen/DirectX/DebugInfo/dbg-assign.ll
diff --git a/llvm/test/CodeGen/DirectX/DebugInfo/dbg-assign.ll b/llvm/test/CodeGen/DirectX/DebugInfo/dbg-assign.ll
new file mode 100644
index 0000000000000..9c682bcf2fe23
--- /dev/null
+++ b/llvm/test/CodeGen/DirectX/DebugInfo/dbg-assign.ll
@@ -0,0 +1,45 @@
+;; RUN: llc -o - %s | FileCheck %s
+
+target triple = "dxil-pc-shadermodel6.3-library"
+
+;; CHECK: define i32 @dbgassign(i32 %a, i32 %b) !dbg [[SP:![0-9]+]] {
+;; CHECK-NEXT: entry:
+;; CHECK-NEXT: ; DXIL: to be replaced with: tail call addrspace(0) void @llvm.dbg.value(metadata i32 %a, i64 0, metadata [[LV:![0-9]+]], metadata !DIExpression())
+;; CHECK-NEXT: tail call void @llvm.dbg.value(metadata i32 %a, metadata [[LV:![0-9]+]], metadata !DIExpression())
+;; CHECK-NEXT: %add = add nsw i32 %a, %b
+;; CHECK-NEXT: ; DXIL: to be replaced with: tail call addrspace(0) void @llvm.dbg.value(metadata i32 %add, i64 0, metadata [[LV]], metadata !DIExpression())
+;; CHECK-NEXT: tail call void @llvm.dbg.value(metadata i32 %add, metadata [[LV]], metadata !DIExpression()
+;; CHECK-NEXT: ret i32 %add
+;; CHECK-NEXT: }
+;; CHECK-NOT: !DIAssignID()
+
+define i32 @dbgassign(i32 %a, i32 %b) !dbg !5 {
+entry:
+ #dbg_assign(i1 poison, !10, !DIExpression(), !11, ptr poison, !DIExpression(), !12)
+ #dbg_assign(i32 0, !10, !DIExpression(), !13, ptr poison, !DIExpression(), !12)
+ #dbg_assign(i32 %a, !10, !DIExpression(), !14, ptr poison, !DIExpression(), !12)
+ %add = add nsw i32 %a, %b, !dbg !15
+ #dbg_assign(i32 %add, !10, !DIExpression(), !16, ptr poison, !DIExpression(), !12)
+ ret i32 %add
+}
+
+!llvm.dbg.cu = !{!0}
+!llvm.module.flags = !{!2, !3, !4}
+
+!0 = distinct !DICompileUnit(language: DW_LANG_C11, file: !1, producer: "clang", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, splitDebugInlining: false, nameTableKind: None)
+!1 = !DIFile(filename: "dbgassign.c", directory: "")
+!2 = !{i32 7, !"Dwarf Version", i32 4}
+!3 = !{i32 2, !"Debug Info Version", i32 3}
+!4 = !{i32 7, !"debug-info-assignment-tracking", i1 true}
+!5 = distinct !DISubprogram(name: "dbgassign", scope: !1, file: !1, line: 2, type: !6, scopeLine: 2, flags: DIFlagPrototyped | DIFlagAllCallsDescribed, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !0, retainedNodes: !9, keyInstructions: true)
+!6 = !DISubroutineType(types: !7)
+!7 = !{!8, !8, !8}
+!8 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed)
+!9 = !{!10}
+!10 = !DILocalVariable(name: "result", scope: !5, file: !1, line: 3, type: !8)
+!11 = distinct !DIAssignID()
+!12 = !DILocation(line: 0, scope: !5)
+!13 = distinct !DIAssignID()
+!14 = distinct !DIAssignID()
+!15 = !DILocation(line: 7, column: 10, scope: !5, atomGroup: 3, atomRank: 2)
+!16 = distinct !DIAssignID()
>From b8f696c7c27f42a16f727f4d0ca1d70cd11df65e Mon Sep 17 00:00:00 2001
From: Harald van Dijk <hdijk at accesssoftek.com>
Date: Mon, 8 Jun 2026 14:22:54 +0100
Subject: [PATCH 3/4] Move DbgValue(Fragment)s out of loop
---
.../DirectX/DirectXIRPasses/DXILDebugInfo.cpp | 187 +++++++++---------
1 file changed, 98 insertions(+), 89 deletions(-)
diff --git a/llvm/lib/Target/DirectX/DirectXIRPasses/DXILDebugInfo.cpp b/llvm/lib/Target/DirectX/DirectXIRPasses/DXILDebugInfo.cpp
index 921675c9b9ce2..9fa5fc689dcdf 100644
--- a/llvm/lib/Target/DirectX/DirectXIRPasses/DXILDebugInfo.cpp
+++ b/llvm/lib/Target/DirectX/DirectXIRPasses/DXILDebugInfo.cpp
@@ -70,103 +70,112 @@ DXILDebugInfoMap DXILDebugInfoPass::run(Module &M) {
DebugInfoFinder DIF;
DIF.processModule(M);
- Function *DVDecl = nullptr;
+ {
+ Function *DVDecl = nullptr;
- for (Function &F : M) {
- bool IsEntryBlock = true;
- for (BasicBlock &BB : F) {
- DenseMap<DILocalVariable *, std::pair<Instruction *, DbgValueInst *>>
- DbgValues;
- DenseMap<std::pair<DILocalVariable *, DIExpression *>,
- std::pair<Instruction *, DbgValueInst *>>
- DbgValueFragments;
- Instruction *NextNonDebugInst = nullptr;
- for (Instruction &I : make_early_inc_range(reverse(BB))) {
- I.eraseMetadataIf([](unsigned KindID, MDNode *) {
- return KindID == LLVMContext::MD_DIAssignID;
- });
- if (!isa<DbgInfoIntrinsic>(I)) {
- NextNonDebugInst = &I;
- continue;
- }
- if (auto *DL = dyn_cast<DbgLabelInst>(&I)) {
- DL->eraseFromParent();
- continue;
- }
- // Process both llvm.dbg.value and llvm.dbg.assign here. We convert
- // llvm.dbg.assign to llvm.dbg.value by dropping the last arguments, and
- // remove redundant llvm.dbg.values.
- if (auto *DV = dyn_cast<DbgValueInst>(&I)) {
- // Keep track of the last location where we saw any debug value for a
- // variable.
- DILocalVariable *V = DV->getVariable();
- DIExpression *E = DV->getExpression();
- std::pair<Instruction *, DbgValueInst *> &DbgValue = DbgValues[V];
- std::pair<Instruction *, DbgValueInst *> &DbgValueFragment =
- DbgValueFragments[{V, E}];
- if (DbgValue.second) {
- // If there is a later value of the same fragment at the same
- // location, this value is redundant.
- if (DbgValueFragment.first == NextNonDebugInst) {
- DV->eraseFromParent();
- continue;
- }
- // If there is a later identical value of the same fragment at a
- // later point, and there have been no intervening values of
- // different possibly overlapping fragments, that later value is
- // redundant.
- if (DbgValueFragment.second &&
- DbgValueFragment.second == DbgValue.second &&
- DbgValueFragment.second->getValue() == DV->getValue()) {
- DbgValue.second->eraseFromParent();
- }
+ // Logically these should be variables in the
+ // for (BasicBlock &BB : F) loop.
+ // They are defined here and cleared at the start of the loop body to avoid
+ // the cost of deconstruction and reconstruction.
+ DenseMap<DILocalVariable *, std::pair<Instruction *, DbgValueInst *>>
+ DbgValues;
+ DenseMap<std::pair<DILocalVariable *, DIExpression *>,
+ std::pair<Instruction *, DbgValueInst *>>
+ DbgValueFragments;
+
+ for (Function &F : M) {
+ bool IsEntryBlock = true;
+ for (BasicBlock &BB : F) {
+ Instruction *NextNonDebugInst = nullptr;
+ DbgValues.clear();
+ DbgValueFragments.clear();
+ for (Instruction &I : make_early_inc_range(reverse(BB))) {
+ I.eraseMetadataIf([](unsigned KindID, MDNode *) {
+ return KindID == LLVMContext::MD_DIAssignID;
+ });
+ if (!isa<DbgInfoIntrinsic>(I)) {
+ NextNonDebugInst = &I;
+ continue;
+ }
+ if (auto *DL = dyn_cast<DbgLabelInst>(&I)) {
+ DL->eraseFromParent();
+ continue;
}
- // If this is already an llvm.dbg.value instruction, just keep it,
- // otherwise convert it.
- DbgValueInst *NewDV;
- if (DV->getIntrinsicID() == Intrinsic::dbg_value) {
- NewDV = DV;
- } else {
- if (!DVDecl) {
- DVDecl =
- Intrinsic::getOrInsertDeclaration(&M, Intrinsic::dbg_value);
- AttributeMask AM;
- for (Attribute A : DVDecl->getAttributes().getFnAttrs())
- if (A.isStringAttribute() ||
- (A.getKindAsEnum() != Attribute::NoUnwind &&
- A.getKindAsEnum() != Attribute::Memory))
- AM.addAttribute(A);
- DVDecl->removeFnAttrs(AM);
+ // Process both llvm.dbg.value and llvm.dbg.assign here. We convert
+ // llvm.dbg.assign to llvm.dbg.value by dropping the last arguments,
+ // and remove redundant llvm.dbg.values.
+ if (auto *DV = dyn_cast<DbgValueInst>(&I)) {
+ // Keep track of the last location where we saw any debug value for
+ // a variable.
+ DILocalVariable *V = DV->getVariable();
+ DIExpression *E = DV->getExpression();
+ std::pair<Instruction *, DbgValueInst *> &DbgValue = DbgValues[V];
+ std::pair<Instruction *, DbgValueInst *> &DbgValueFragment =
+ DbgValueFragments[{V, E}];
+ if (DbgValue.second) {
+ // If there is a later value of the same fragment at the same
+ // location, this value is redundant.
+ if (DbgValueFragment.first == NextNonDebugInst) {
+ DV->eraseFromParent();
+ continue;
+ }
+ // If there is a later identical value of the same fragment at a
+ // later point, and there have been no intervening values of
+ // different possibly overlapping fragments, that later value is
+ // redundant.
+ if (DbgValueFragment.second &&
+ DbgValueFragment.second == DbgValue.second &&
+ DbgValueFragment.second->getValue() == DV->getValue()) {
+ DbgValue.second->eraseFromParent();
+ }
}
- NewDV = cast<DbgValueInst>(
- CallInst::Create(DVDecl,
- {DV->getArgOperand(0), DV->getArgOperand(1),
- DV->getArgOperand(2)},
- {}, "", std::next(DV->getIterator())));
- NewDV->setTailCall();
- NewDV->setDebugLoc(DV->getDebugLoc());
- DV->eraseFromParent();
+ // If this is already an llvm.dbg.value instruction, just keep it,
+ // otherwise convert it.
+ DbgValueInst *NewDV;
+ if (DV->getIntrinsicID() == Intrinsic::dbg_value) {
+ NewDV = DV;
+ } else {
+ if (!DVDecl) {
+ DVDecl =
+ Intrinsic::getOrInsertDeclaration(&M, Intrinsic::dbg_value);
+ AttributeMask AM;
+ for (Attribute A : DVDecl->getAttributes().getFnAttrs())
+ if (A.isStringAttribute() ||
+ (A.getKindAsEnum() != Attribute::NoUnwind &&
+ A.getKindAsEnum() != Attribute::Memory))
+ AM.addAttribute(A);
+ DVDecl->removeFnAttrs(AM);
+ }
+ NewDV = cast<DbgValueInst>(
+ CallInst::Create(DVDecl,
+ {DV->getArgOperand(0), DV->getArgOperand(1),
+ DV->getArgOperand(2)},
+ {}, "", std::next(DV->getIterator())));
+ NewDV->setTailCall();
+ NewDV->setDebugLoc(DV->getDebugLoc());
+ DV->eraseFromParent();
+ }
+ DbgValue = DbgValueFragment = {NextNonDebugInst, NewDV};
+ continue;
}
- DbgValue = DbgValueFragment = {NextNonDebugInst, NewDV};
- continue;
}
- }
- // If this is the entry block, if the first value we see for each debug
- // value is undef, it is redundant.
- if (IsEntryBlock) {
- DenseSet<DILocalVariable *> Seen;
- for (Instruction &I : make_early_inc_range(BB)) {
- auto *DV = dyn_cast<DbgValueInst>(&I);
- if (!DV || Seen.contains(DV->getVariable()))
- continue;
- if (isa<UndefValue>(DV->getValue())) {
- DV->eraseFromParent();
- continue;
+ // If this is the entry block, if the first value we see for each debug
+ // value is undef, it is redundant.
+ if (IsEntryBlock) {
+ DenseSet<DILocalVariable *> Seen;
+ for (Instruction &I : make_early_inc_range(BB)) {
+ auto *DV = dyn_cast<DbgValueInst>(&I);
+ if (!DV || Seen.contains(DV->getVariable()))
+ continue;
+ if (isa<UndefValue>(DV->getValue())) {
+ DV->eraseFromParent();
+ continue;
+ }
+ Seen.insert(DV->getVariable());
}
- Seen.insert(DV->getVariable());
}
+ IsEntryBlock = false;
}
- IsEntryBlock = false;
}
}
>From e68eff88a068ace9189c24966b62d61c2574aa14 Mon Sep 17 00:00:00 2001
From: Harald van Dijk <hdijk at accesssoftek.com>
Date: Mon, 8 Jun 2026 14:27:12 +0100
Subject: [PATCH 4/4] Same for (DbgVariables)Seen
---
.../lib/Target/DirectX/DirectXIRPasses/DXILDebugInfo.cpp | 9 ++++++---
1 file changed, 6 insertions(+), 3 deletions(-)
diff --git a/llvm/lib/Target/DirectX/DirectXIRPasses/DXILDebugInfo.cpp b/llvm/lib/Target/DirectX/DirectXIRPasses/DXILDebugInfo.cpp
index 9fa5fc689dcdf..53f738c90c0da 100644
--- a/llvm/lib/Target/DirectX/DirectXIRPasses/DXILDebugInfo.cpp
+++ b/llvm/lib/Target/DirectX/DirectXIRPasses/DXILDebugInfo.cpp
@@ -82,9 +82,13 @@ DXILDebugInfoMap DXILDebugInfoPass::run(Module &M) {
DenseMap<std::pair<DILocalVariable *, DIExpression *>,
std::pair<Instruction *, DbgValueInst *>>
DbgValueFragments;
+ // Likewise, logically, this should be a variable in the
+ // for (Function &F : M) loop.
+ DenseSet<DILocalVariable *> DbgVariablesSeen;
for (Function &F : M) {
bool IsEntryBlock = true;
+ DbgVariablesSeen.clear();
for (BasicBlock &BB : F) {
Instruction *NextNonDebugInst = nullptr;
DbgValues.clear();
@@ -162,16 +166,15 @@ DXILDebugInfoMap DXILDebugInfoPass::run(Module &M) {
// If this is the entry block, if the first value we see for each debug
// value is undef, it is redundant.
if (IsEntryBlock) {
- DenseSet<DILocalVariable *> Seen;
for (Instruction &I : make_early_inc_range(BB)) {
auto *DV = dyn_cast<DbgValueInst>(&I);
- if (!DV || Seen.contains(DV->getVariable()))
+ if (!DV || DbgVariablesSeen.contains(DV->getVariable()))
continue;
if (isa<UndefValue>(DV->getValue())) {
DV->eraseFromParent();
continue;
}
- Seen.insert(DV->getVariable());
+ DbgVariablesSeen.insert(DV->getVariable());
}
}
IsEntryBlock = false;
More information about the llvm-commits
mailing list