[llvm] [WebAssembly] Avoid scanning unrelated debug values (NFCI) (PR #218378)
Frank Denis via llvm-commits
llvm-commits at lists.llvm.org
Tue Aug 25 03:29:44 PDT 2026
https://github.com/jedisct1 updated https://github.com/llvm/llvm-project/pull/218378
>From e0452def3e735d671048e00490847811d4e71374 Mon Sep 17 00:00:00 2001
From: Frank Denis <github at pureftpd.org>
Date: Mon, 24 Aug 2026 13:12:57 +0200
Subject: [PATCH 1/4] [WebAssembly] Avoid scanning unrelated debug values
(NFCI)
RegStackify looks for debug values when moving an instruction.
But when a debug use comes before the definition, it may collect
values for a lot of unrelated variables until the end of the
block.
Stop early once all relevant values have been found instead.
---
.../WebAssemblyDebugValueManager.cpp | 92 ++++++++++++-------
1 file changed, 61 insertions(+), 31 deletions(-)
diff --git a/llvm/lib/Target/WebAssembly/WebAssemblyDebugValueManager.cpp b/llvm/lib/Target/WebAssembly/WebAssemblyDebugValueManager.cpp
index abc022c18f275..55434359837e0 100644
--- a/llvm/lib/Target/WebAssembly/WebAssemblyDebugValueManager.cpp
+++ b/llvm/lib/Target/WebAssembly/WebAssemblyDebugValueManager.cpp
@@ -15,7 +15,9 @@
#include "MCTargetDesc/WebAssemblyMCTargetDesc.h"
#include "WebAssembly.h"
#include "WebAssemblyMachineFunctionInfo.h"
+#include "llvm/ADT/DenseSet.h"
#include "llvm/CodeGen/MachineInstr.h"
+#include "llvm/CodeGen/MachineRegisterInfo.h"
#include "llvm/IR/DebugInfoMetadata.h"
#include "llvm/IR/Function.h"
@@ -35,26 +37,33 @@ WebAssemblyDebugValueManager::WebAssemblyDebugValueManager(MachineInstr *Def)
// Collect all the uses of this def.
MachineRegisterInfo &MRI = Def->getMF()->getRegInfo();
- SmallVector<MachineInstr *, 2> Candidates;
- for (MachineInstr &MI : MRI.use_instructions(CurrentReg)) {
- if (MI.isDebugValue() && MI.getParent() == Def->getParent())
- Candidates.push_back(&MI);
- }
- if (Candidates.empty())
+ MachineBasicBlock *MBB = Def->getParent();
+ unsigned RemainingUses = 0;
+ for (MachineInstr &MI : MRI.use_instructions(CurrentReg))
+ if (MI.isDebugValue() && MI.getParent() == MBB)
+ ++RemainingUses;
+ if (RemainingUses == 0)
return;
// To preserve the order of DBG_VALUEs and correctly handle non-SSA cases,
// we scan the BB as far as needed to find all candidates.
- for (MachineBasicBlock::iterator MI = std::next(Def->getIterator()),
- ME = Def->getParent()->end();
- MI != ME; ++MI) {
- // If another definition appears, stop
- if (MI->definesRegister(CurrentReg, /*TRI=*/nullptr))
+ MachineBasicBlock::iterator Down = std::next(Def->getIterator()),
+ DownEnd = MBB->end(), Up = Def->getIterator(),
+ UpBegin = MBB->begin();
+ while (RemainingUses > 0 && Down != DownEnd) {
+ if (Down->isDebugValue()) {
+ if (Down->hasDebugOperandForReg(CurrentReg)) {
+ DbgValues.push_back(&*Down);
+ --RemainingUses;
+ }
+ } else if (Down->definesRegister(CurrentReg, /*TRI=*/nullptr)) {
break;
- if (MI->isDebugValue() && MI->hasDebugOperandForReg(CurrentReg)) {
- DbgValues.push_back(&*MI);
- if (DbgValues.size() == Candidates.size())
- break;
+ }
+ ++Down;
+ if (Up != UpBegin) {
+ --Up;
+ if (Up->isDebugValue() && Up->hasDebugOperandForReg(CurrentReg))
+ --RemainingUses;
}
}
}
@@ -79,44 +88,65 @@ WebAssemblyDebugValueManager::getSinkableDebugValues(
MachineInstr *Insert) const {
if (DbgValues.empty())
return {};
- // DBG_VALUEs between Def and Insert
+
+ // If Def and Insert are in different BBs, we only handle a simple case in
+ // which Insert's BB is a successor of Def's BB.
+ if (Def->getParent() != Insert->getParent() &&
+ !Def->getParent()->isSuccessor(Insert->getParent()))
+ return {};
+
+ SmallDenseSet<std::pair<const DILocalVariable *, const DILocation *>, 4>
+ OurVars;
+ for (MachineInstr *DV : DbgValues)
+ OurVars.insert({DV->getDebugVariable(), DV->getDebugLoc()->getInlinedAt()});
+ auto IsRelevantDbgValue = [&](const MachineInstr &MI) {
+ return MI.isDebugValue() &&
+ OurVars.count(
+ {MI.getDebugVariable(), MI.getDebugLoc()->getInlinedAt()});
+ };
+
SmallVector<MachineInstr *, 8> DbgValuesInBetween;
if (Def->getParent() == Insert->getParent()) {
// When Def and Insert are within the same BB, check if Insert comes after
// Def, because we only support sinking.
+ MachineBasicBlock::iterator Down = std::next(Def->getIterator()),
+ DownEnd = Def->getParent()->end(),
+ Up = Def->getIterator(),
+ UpBegin = Def->getParent()->begin();
bool DefFirst = false;
- for (MachineBasicBlock::iterator MI = std::next(Def->getIterator()),
- ME = Def->getParent()->end();
- MI != ME; ++MI) {
- if (&*MI == Insert) {
- DefFirst = true;
- break;
+ while (Down != DownEnd || Up != UpBegin) {
+ if (Down != DownEnd) {
+ if (&*Down == Insert) {
+ DefFirst = true;
+ break;
+ }
+ if (IsRelevantDbgValue(*Down))
+ DbgValuesInBetween.push_back(&*Down);
+ ++Down;
+ }
+ if (Up != UpBegin) {
+ --Up;
+ if (&*Up == Insert)
+ break;
}
- if (MI->isDebugValue())
- DbgValuesInBetween.push_back(&*MI);
}
if (!DefFirst) // Not a sink
return {};
} else { // Def and Insert are in different BBs
- // If Def and Insert are in different BBs, we only handle a simple case in
- // which Insert's BB is a successor of Def's BB.
- if (!Def->getParent()->isSuccessor(Insert->getParent()))
- return {};
-
// Gather DBG_VALUEs between 'Def~Def BB's end' and
// 'Insert BB's begin~Insert'
for (MachineBasicBlock::iterator MI = std::next(Def->getIterator()),
ME = Def->getParent()->end();
MI != ME; ++MI) {
- if (MI->isDebugValue())
+ if (IsRelevantDbgValue(*MI))
DbgValuesInBetween.push_back(&*MI);
}
for (MachineBasicBlock::iterator MI = Insert->getParent()->begin(),
ME = Insert->getIterator();
MI != ME; ++MI) {
- if (MI->isDebugValue())
+ if (IsRelevantDbgValue(*MI))
DbgValuesInBetween.push_back(&*MI);
}
}
>From 048eaaca04ce45caddff7c0dc26a5443396ab60f Mon Sep 17 00:00:00 2001
From: Frank Denis <github at pureftpd.org>
Date: Tue, 25 Aug 2026 09:24:51 +0200
Subject: [PATCH 2/4] Add comment to explain the scan in both directions
And clarify that only the forward scan collects debug values.
---
.../lib/Target/WebAssembly/WebAssemblyDebugValueManager.cpp | 6 ++++--
1 file changed, 4 insertions(+), 2 deletions(-)
diff --git a/llvm/lib/Target/WebAssembly/WebAssemblyDebugValueManager.cpp b/llvm/lib/Target/WebAssembly/WebAssemblyDebugValueManager.cpp
index 55434359837e0..ff7de9459628a 100644
--- a/llvm/lib/Target/WebAssembly/WebAssemblyDebugValueManager.cpp
+++ b/llvm/lib/Target/WebAssembly/WebAssemblyDebugValueManager.cpp
@@ -45,8 +45,10 @@ WebAssemblyDebugValueManager::WebAssemblyDebugValueManager(MachineInstr *Def)
if (RemainingUses == 0)
return;
- // To preserve the order of DBG_VALUEs and correctly handle non-SSA cases,
- // we scan the BB as far as needed to find all candidates.
+ // Scan forward to collect DBG_VALUEs in block order.
+ // Scan backward at the same pace to account for earlier uses and stop once
+ // all possible matches have been found.
+ // Only the forward scan collects DBG_VALUEs.
MachineBasicBlock::iterator Down = std::next(Def->getIterator()),
DownEnd = MBB->end(), Up = Def->getIterator(),
UpBegin = MBB->begin();
>From e1158f8aec36da0878f9ae1fdc66317a7c741bba Mon Sep 17 00:00:00 2001
From: Frank Denis <github at pureftpd.org>
Date: Tue, 25 Aug 2026 09:28:57 +0200
Subject: [PATCH 3/4] Explain why the insertion point is searched for in both
directions
---
llvm/lib/Target/WebAssembly/WebAssemblyDebugValueManager.cpp | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/llvm/lib/Target/WebAssembly/WebAssemblyDebugValueManager.cpp b/llvm/lib/Target/WebAssembly/WebAssemblyDebugValueManager.cpp
index ff7de9459628a..0d18e21663891 100644
--- a/llvm/lib/Target/WebAssembly/WebAssemblyDebugValueManager.cpp
+++ b/llvm/lib/Target/WebAssembly/WebAssemblyDebugValueManager.cpp
@@ -110,8 +110,8 @@ WebAssemblyDebugValueManager::getSinkableDebugValues(
SmallVector<MachineInstr *, 8> DbgValuesInBetween;
if (Def->getParent() == Insert->getParent()) {
- // When Def and Insert are within the same BB, check if Insert comes after
- // Def, because we only support sinking.
+ // Search both ways to quickly determine whether Insert follows Def.
+ // Only the forward scan collects DBG_VALUEs.
MachineBasicBlock::iterator Down = std::next(Def->getIterator()),
DownEnd = Def->getParent()->end(),
Up = Def->getIterator(),
>From 5492e12a1b2d25332a7c78cfd3e1e20bf1821f4c Mon Sep 17 00:00:00 2001
From: Frank Denis <github at pureftpd.org>
Date: Tue, 25 Aug 2026 09:36:23 +0200
Subject: [PATCH 4/4] Simplify debug value filtering
Use DebugVariable consistently to find assignments between an
instruction and its new position.
And record matches directly instead of collecting them in a
temporary list.
Suggested by @aheejin
---
.../WebAssemblyDebugValueManager.cpp | 50 +++++++------------
1 file changed, 19 insertions(+), 31 deletions(-)
diff --git a/llvm/lib/Target/WebAssembly/WebAssemblyDebugValueManager.cpp b/llvm/lib/Target/WebAssembly/WebAssemblyDebugValueManager.cpp
index 0d18e21663891..5e25b13464e9b 100644
--- a/llvm/lib/Target/WebAssembly/WebAssemblyDebugValueManager.cpp
+++ b/llvm/lib/Target/WebAssembly/WebAssemblyDebugValueManager.cpp
@@ -97,17 +97,22 @@ WebAssemblyDebugValueManager::getSinkableDebugValues(
!Def->getParent()->isSuccessor(Insert->getParent()))
return {};
- SmallDenseSet<std::pair<const DILocalVariable *, const DILocation *>, 4>
- OurVars;
+ SmallDenseSet<DebugVariable, 4> OurVars;
for (MachineInstr *DV : DbgValues)
- OurVars.insert({DV->getDebugVariable(), DV->getDebugLoc()->getInlinedAt()});
- auto IsRelevantDbgValue = [&](const MachineInstr &MI) {
- return MI.isDebugValue() &&
- OurVars.count(
- {MI.getDebugVariable(), MI.getDebugLoc()->getInlinedAt()});
- };
+ OurVars.insert(DebugVariable(DV->getDebugVariable(),
+ DV->getDebugExpression(),
+ DV->getDebugLoc()->getInlinedAt()));
- SmallVector<MachineInstr *, 8> DbgValuesInBetween;
+ SmallDenseMap<DebugVariable, SmallVector<MachineInstr *, 2>>
+ SeenDbgVarToDbgValues;
+ auto RecordDbgValue = [&](MachineInstr &MI) {
+ if (!MI.isDebugValue())
+ return;
+ DebugVariable Var(MI.getDebugVariable(), MI.getDebugExpression(),
+ MI.getDebugLoc()->getInlinedAt());
+ if (OurVars.count(Var) && !llvm::is_contained(DbgValues, &MI))
+ SeenDbgVarToDbgValues[Var].push_back(&MI);
+ };
if (Def->getParent() == Insert->getParent()) {
// Search both ways to quickly determine whether Insert follows Def.
@@ -123,8 +128,7 @@ WebAssemblyDebugValueManager::getSinkableDebugValues(
DefFirst = true;
break;
}
- if (IsRelevantDbgValue(*Down))
- DbgValuesInBetween.push_back(&*Down);
+ RecordDbgValue(*Down);
++Down;
}
if (Up != UpBegin) {
@@ -141,28 +145,12 @@ WebAssemblyDebugValueManager::getSinkableDebugValues(
// 'Insert BB's begin~Insert'
for (MachineBasicBlock::iterator MI = std::next(Def->getIterator()),
ME = Def->getParent()->end();
- MI != ME; ++MI) {
- if (IsRelevantDbgValue(*MI))
- DbgValuesInBetween.push_back(&*MI);
- }
+ MI != ME; ++MI)
+ RecordDbgValue(*MI);
for (MachineBasicBlock::iterator MI = Insert->getParent()->begin(),
ME = Insert->getIterator();
- MI != ME; ++MI) {
- if (IsRelevantDbgValue(*MI))
- DbgValuesInBetween.push_back(&*MI);
- }
- }
-
- // Gather DebugVariables that are seen between Def and Insert, excluding our
- // own DBG_VALUEs in DbgValues.
- SmallDenseMap<DebugVariable, SmallVector<MachineInstr *, 2>>
- SeenDbgVarToDbgValues;
- for (auto *DV : DbgValuesInBetween) {
- if (!llvm::is_contained(DbgValues, DV)) {
- DebugVariable Var(DV->getDebugVariable(), DV->getDebugExpression(),
- DV->getDebugLoc()->getInlinedAt());
- SeenDbgVarToDbgValues[Var].push_back(DV);
- }
+ MI != ME; ++MI)
+ RecordDbgValue(*MI);
}
// Gather sinkable DBG_VALUEs. We should not sink a DBG_VALUE if there is
More information about the llvm-commits
mailing list