[llvm] [FastISel] Ignore debug uses when folding a load (PR #228719)

Aochang Liu via llvm-commits llvm-commits at lists.llvm.org
Sat Oct 3 08:53:49 PDT 2026


https://github.com/HelloWorldU updated https://github.com/llvm/llvm-project/pull/228719

>From d1e636e7c84cf684b4609cc6ccd3978d335fc7da Mon Sep 17 00:00:00 2001
From: HelloWorldU <asd001liu at gmail.com>
Date: Sat, 3 Oct 2026 22:50:13 +0800
Subject: [PATCH 1/2] [FastISel] Ignore debug uses when folding a load

tryToFoldLoad counted DBG_VALUE as a use of the loaded vreg, so the load was
folded only without -g. Check for a single non-debug use, and mark debug
values of the vreg undef once the load is folded, as PeepholeOptimizer does.

Fixes #228711

Assisted-by: Claude Opus 5.5
---
 llvm/lib/CodeGen/SelectionDAG/FastISel.cpp    | 17 ++++++----
 .../CodeGen/X86/fast-isel-fold-load-dbg.ll    | 33 +++++++++++++++++++
 2 files changed, 44 insertions(+), 6 deletions(-)
 create mode 100644 llvm/test/CodeGen/X86/fast-isel-fold-load-dbg.ll

diff --git a/llvm/lib/CodeGen/SelectionDAG/FastISel.cpp b/llvm/lib/CodeGen/SelectionDAG/FastISel.cpp
index 4f391390705081..3dd81d54773b41 100644
--- a/llvm/lib/CodeGen/SelectionDAG/FastISel.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/FastISel.cpp
@@ -2240,10 +2240,10 @@ bool FastISel::tryToFoldLoad(const LoadInst *LI, const Instruction *FoldInst) {
   if (!LoadReg)
     return false;
 
-  // We can't fold if this vreg has no uses or more than one use.  Multiple uses
-  // may mean that the instruction got lowered to multiple MIs, or the use of
-  // the loaded value ended up being multiple operands of the result.
-  if (!MRI.hasOneUse(LoadReg))
+  // We can't fold if this vreg has no uses or more than one non-debug use.
+  // Multiple uses may mean that the instruction got lowered to multiple MIs, or
+  // the use of the loaded value ended up being multiple operands of the result.
+  if (!MRI.hasOneNonDBGUse(LoadReg))
     return false;
 
   // If the register has fixups, there may be additional uses through a
@@ -2251,7 +2251,7 @@ bool FastISel::tryToFoldLoad(const LoadInst *LI, const Instruction *FoldInst) {
   if (FuncInfo.RegsWithFixups.contains(LoadReg))
     return false;
 
-  MachineRegisterInfo::reg_iterator RI = MRI.reg_begin(LoadReg);
+  MachineRegisterInfo::use_nodbg_iterator RI = MRI.use_nodbg_begin(LoadReg);
   MachineInstr *User = RI->getParent();
 
   // Set the insertion point properly.  Folding the load can cause generation of
@@ -2261,7 +2261,12 @@ bool FastISel::tryToFoldLoad(const LoadInst *LI, const Instruction *FoldInst) {
   FuncInfo.MBB = User->getParent();
 
   // Ask the target to try folding the load.
-  return tryToFoldLoadIntoMI(User, RI.getOperandNo(), LI);
+  if (!tryToFoldLoadIntoMI(User, RI.getOperandNo(), LI))
+    return false;
+
+  // The loaded value no longer lives in LoadReg.
+  MRI.markUsesInDebugValueAsUndef(LoadReg);
+  return true;
 }
 
 bool FastISel::canFoldAddIntoGEP(const User *GEP, const Value *Add) {
diff --git a/llvm/test/CodeGen/X86/fast-isel-fold-load-dbg.ll b/llvm/test/CodeGen/X86/fast-isel-fold-load-dbg.ll
new file mode 100644
index 00000000000000..a154c045b93f2e
--- /dev/null
+++ b/llvm/test/CodeGen/X86/fast-isel-fold-load-dbg.ll
@@ -0,0 +1,33 @@
+; RUN: llc -O0 -mtriple=x86_64-unknown-unknown -stop-after=finalize-isel %s -o - | \
+; RUN:    FileCheck %s --check-prefixes=CHECK,O0
+; RUN: llc -fast-isel -fast-isel-abort=1 -mtriple=x86_64-unknown-unknown -stop-after=finalize-isel %s -o - | \
+; RUN:    FileCheck %s --check-prefixes=CHECK,IREF
+
+; A debug use of the loaded value must not prevent folding the load, and the
+; debug value must not refer to the now undefined vreg. At -O0 this is a
+; DBG_VALUE; with instruction referencing it is a DBG_INSTR_REF that becomes an
+; undef DBG_VALUE_LIST.
+
+; CHECK-LABEL: name: fold_load_dbg
+; CHECK-NOT:   MOV64rm
+; O0:          DBG_VALUE $noreg, $noreg,
+; IREF:        DBG_VALUE_LIST {{.*}}, $noreg,
+; CHECK-NEXT:  ADD64rm
+define i64 @fold_load_dbg(ptr %a, i64 %b) !dbg !4 {
+  %1 = load i64, ptr %a, align 8
+    #dbg_value(i64 %1, !6, !DIExpression(), !7)
+  %2 = add i64 %1, %b
+  ret i64 %2
+}
+
+!llvm.dbg.cu = !{!0}
+!llvm.module.flags = !{!2}
+
+!0 = distinct !DICompileUnit(language: DW_LANG_C, file: !1, emissionKind: FullDebug)
+!1 = !DIFile(filename: "t.c", directory: "/")
+!2 = !{i32 2, !"Debug Info Version", i32 3}
+!3 = !DISubroutineType(types: !{})
+!4 = distinct !DISubprogram(name: "fold_load_dbg", scope: !1, file: !1, type: !3, spFlags: DISPFlagDefinition, unit: !0)
+!5 = !DIBasicType(name: "long", size: 64, encoding: DW_ATE_signed)
+!6 = !DILocalVariable(name: "x", scope: !4, file: !1, type: !5)
+!7 = !DILocation(line: 1, scope: !4)

>From d33df4043b715f647a9014717ec208fc688dd4b3 Mon Sep 17 00:00:00 2001
From: HelloWorldU <asd001liu at gmail.com>
Date: Sat, 3 Oct 2026 23:53:22 +0800
Subject: [PATCH 2/2] Update LTO_CCU_zero_loc_cov.ll

The inlined parameter "a" in the optnone main is described by a loaded value
that is now folded, so its DBG_VALUE becomes undef and it loses its location.

Assisted-by: Claude Opus 5.5
---
 llvm/test/tools/llvm-dwarfdump/X86/LTO_CCU_zero_loc_cov.ll | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/llvm/test/tools/llvm-dwarfdump/X86/LTO_CCU_zero_loc_cov.ll b/llvm/test/tools/llvm-dwarfdump/X86/LTO_CCU_zero_loc_cov.ll
index fa32b35658047a..27ac88398dae35 100644
--- a/llvm/test/tools/llvm-dwarfdump/X86/LTO_CCU_zero_loc_cov.ll
+++ b/llvm/test/tools/llvm-dwarfdump/X86/LTO_CCU_zero_loc_cov.ll
@@ -28,9 +28,9 @@
 ;;	return result;
 ;;}
 
-; CHECK:      "#source variables with location": 10,
-; CHECK:      "#variables with 0% of parent scope covered by DW_AT_location": 1,
-; CHECK:      "#params with 0% of parent scope covered by DW_AT_location": 1,
+; CHECK:      "#source variables with location": 9,
+; CHECK:      "#variables with 0% of parent scope covered by DW_AT_location": 2,
+; CHECK:      "#params with 0% of parent scope covered by DW_AT_location": 2,
 
 ; ModuleID = 'linked.ll'
 source_filename = "llvm-link"



More information about the llvm-commits mailing list