[llvm] [MergeICmps][DebugInfo] Preserve debug locations in mergeComparisons (PR #205796)

Stephen Tozer via llvm-commits llvm-commits at lists.llvm.org
Mon Jul 6 02:29:28 PDT 2026


https://github.com/SLTozer updated https://github.com/llvm/llvm-project/pull/205796

>From 5adfd3a8b133e6c38c07bf0039187dd4422a6866 Mon Sep 17 00:00:00 2001
From: Stephen Tozer <stephen.tozer at sony.com>
Date: Thu, 25 Jun 2026 13:04:46 +0100
Subject: [PATCH 1/2] [MergeICmps][DebugInfo] Preserve debug locations in
 mergeComparisons

The mergeComparisons function in MergeICmps merges a chain of comparison
blocks, generating new instructions inside of the merged block(s) to memcmp
the contiguous blocks of memory being compared and perform a single branch
based on the result. Some of the generated instructions take their debug
locations directly from the first block in the comparison chain, but the
icmp/memcmp and branch instructions generated are not assigned any debug
location.

This patch assigns a debug location to the comparison instructions from the
merged location of all merged comparison instructions, and similarly assigns
the branch instruction from the merged branch instructions.
---
 llvm/lib/Transforms/Scalar/MergeICmps.cpp     |  20 +++
 .../MergeICmps/X86/dbgloc-branches.ll         | 117 ++++++++++++++++++
 2 files changed, 137 insertions(+)
 create mode 100644 llvm/test/Transforms/MergeICmps/X86/dbgloc-branches.ll

diff --git a/llvm/lib/Transforms/Scalar/MergeICmps.cpp b/llvm/lib/Transforms/Scalar/MergeICmps.cpp
index fbcbf537faf54..9b4285f03b33a 100644
--- a/llvm/lib/Transforms/Scalar/MergeICmps.cpp
+++ b/llvm/lib/Transforms/Scalar/MergeICmps.cpp
@@ -213,6 +213,8 @@ class BCECmpBlock {
   const BCEAtom &Rhs() const { return Cmp.Rhs; }
   int SizeBits() const { return Cmp.SizeBits; }
 
+  DebugLoc getCmpDebugLoc() const { return Cmp.CmpI->getDebugLoc(); }
+
   // Returns true if the block does other works besides comparison.
   bool doesOtherWork() const;
 
@@ -698,12 +700,21 @@ static BasicBlock *mergeComparisons(ArrayRef<BCECmpBlock> Comparisons,
     RhsLoad->replaceUsesOfWith(RhsLoad->getOperand(0), Rhs);
     // There are no blocks to merge, just do the comparison.
     // If we condition on this IsEqual, we already have its probabilities.
+    Builder.SetCurrentDebugLocation(Comparisons[0].getCmpDebugLoc());
     IsEqual = Builder.CreateICmpEQ(LhsLoad, RhsLoad);
   } else {
     const unsigned TotalSizeBits = std::accumulate(
         Comparisons.begin(), Comparisons.end(), 0u,
         [](int Size, const BCECmpBlock &C) { return Size + C.SizeBits(); });
 
+    // Find the merged debug location for our generated comparison instructions.
+    SmallVector<DebugLoc> OrigCmpDebugLocs;
+    OrigCmpDebugLocs.reserve(Comparisons.size());
+    for (auto &Comparison : Comparisons)
+      OrigCmpDebugLocs.push_back(Comparison.getCmpDebugLoc());
+    DebugLoc CmpDebugLoc = DebugLoc::getMergedLocations(OrigCmpDebugLocs);
+    Builder.SetCurrentDebugLocation(CmpDebugLoc);
+
     // memcmp expects a 'size_t' argument and returns 'int'.
     unsigned SizeTBits = TLI.getSizeTSize(*Phi.getModule());
     unsigned IntBits = TLI.getIntSize();
@@ -718,6 +729,15 @@ static BasicBlock *mergeComparisons(ArrayRef<BCECmpBlock> Comparisons,
         MemCmpCall, ConstantInt::get(Builder.getIntNTy(IntBits), 0));
   }
 
+  // Find the merged debug location for our generated branches.
+  SmallVector<DebugLoc> OrigBranchDebugLocs;
+  OrigBranchDebugLocs.reserve(Comparisons.size());
+  for (auto &Comparison : Comparisons)
+    OrigBranchDebugLocs.push_back(
+        Comparison.BB->getTerminator()->getDebugLoc());
+  DebugLoc BranchDebugLoc = DebugLoc::getMergedLocations(OrigBranchDebugLocs);
+  Builder.SetCurrentDebugLocation(BranchDebugLoc);
+
   BasicBlock *const PhiBB = Phi.getParent();
   // Add a branch to the next basic block in the chain.
   if (NextCmpBlock == PhiBB) {
diff --git a/llvm/test/Transforms/MergeICmps/X86/dbgloc-branches.ll b/llvm/test/Transforms/MergeICmps/X86/dbgloc-branches.ll
new file mode 100644
index 0000000000000..94a3addd0e0e9
--- /dev/null
+++ b/llvm/test/Transforms/MergeICmps/X86/dbgloc-branches.ll
@@ -0,0 +1,117 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 6
+; RUN: opt -S -passes=mergeicmps < %s | FileCheck %s
+
+;; Tests that we correctly set debug locations on the instructions generated
+;; while merging comparison blocks.
+;; The GEP and Load instructions take their debug locations from the
+;; corresponding GEP+Load insts in the first comparison block.
+;; The icmp/memcmp insts take their debug locations from all of the icmp insts
+;; being merged in the comparison block chain.
+;; The branch insts similarly take their debug locations from all of the branch
+;; insts being merged in the comparison block chain.
+
+
+source_filename = "reduced.ll"
+target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128"
+target triple = "x86_64-unknown-linux-gnu"
+
+define i1 @wibble(ptr dereferenceable(600) %arg) !dbg !5 {
+; CHECK-LABEL: define i1 @wibble(
+; CHECK-SAME: ptr dereferenceable(600) [[ARG:%.*]]) !dbg [[DBG5:![0-9]+]] {
+; CHECK-NEXT:  "bb+bb5":
+; CHECK-NEXT:    [[TMP0:%.*]] = getelementptr i8, ptr [[ARG]], i64 44, !dbg [[DBG8:![0-9]+]]
+; CHECK-NEXT:    [[TMP1:%.*]] = getelementptr i8, ptr [[ARG]], i64 280, !dbg [[DBG9:![0-9]+]]
+; CHECK-NEXT:    [[MEMCMP:%.*]] = call i32 @memcmp(ptr [[TMP0]], ptr [[TMP1]], i64 2), !dbg [[DBG10:![0-9]+]]
+; CHECK-NEXT:    [[TMP2:%.*]] = icmp eq i32 [[MEMCMP]], 0, !dbg [[DBG10]]
+; CHECK-NEXT:    br i1 [[TMP2]], label %[[BB121:.*]], label %[[BB18:.*]], !dbg [[DBG11:![0-9]+]]
+; CHECK:       [[BB121]]:
+; CHECK-NEXT:    [[TMP3:%.*]] = getelementptr i8, ptr [[ARG]], i64 47, !dbg [[DBG12:![0-9]+]]
+; CHECK-NEXT:    [[TMP4:%.*]] = getelementptr i8, ptr [[ARG]], i64 283, !dbg [[DBG13:![0-9]+]]
+; CHECK-NEXT:    [[TMP5:%.*]] = load i8, ptr [[TMP3]], align 1, !dbg [[DBG14:![0-9]+]]
+; CHECK-NEXT:    [[TMP6:%.*]] = load i8, ptr [[TMP4]], align 1, !dbg [[DBG15:![0-9]+]]
+; CHECK-NEXT:    [[TMP7:%.*]] = icmp eq i8 [[TMP5]], [[TMP6]], !dbg [[DBG16:![0-9]+]]
+; CHECK-NEXT:    br label %[[BB18]], !dbg [[DBG17:![0-9]+]]
+; CHECK:       [[BB18]]:
+; CHECK-NEXT:    [[PHI:%.*]] = phi i1 [ false, %"bb+bb5" ], [ [[TMP7]], %[[BB121]] ], !dbg [[DBG18:![0-9]+]]
+; CHECK-NEXT:    ret i1 [[PHI]], !dbg [[DBG19:![0-9]+]]
+;
+bb:
+  %getelementptr = getelementptr i8, ptr %arg, i64 44, !dbg !8
+  %load = load i8, ptr %getelementptr, align 4, !dbg !9
+  %getelementptr2 = getelementptr i8, ptr %arg, i64 280, !dbg !10
+  %load3 = load i8, ptr %getelementptr2, align 8, !dbg !11
+  %icmp = icmp eq i8 %load, %load3, !dbg !12
+  br i1 %icmp, label %bb5, label %bb18, !dbg !13
+
+bb5:                                              ; preds = %bb
+  %getelementptr7 = getelementptr i8, ptr %arg, i64 45, !dbg !14
+  %load8 = load i8, ptr %getelementptr7, align 1, !dbg !15
+  %getelementptr9 = getelementptr i8, ptr %arg, i64 281, !dbg !16
+  %load10 = load i8, ptr %getelementptr9, align 1, !dbg !17
+  %icmp11 = icmp eq i8 %load8, %load10, !dbg !18
+  br i1 %icmp11, label %bb12, label %bb18, !dbg !19
+
+bb12:                                             ; preds = %bb5
+  %getelementptr13 = getelementptr i8, ptr %arg, i64 47, !dbg !20
+  %load14 = load i8, ptr %getelementptr13, align 1, !dbg !21
+  %getelementptr15 = getelementptr i8, ptr %arg, i64 283, !dbg !22
+  %load16 = load i8, ptr %getelementptr15, align 1, !dbg !23
+  %icmp17 = icmp eq i8 %load14, %load16, !dbg !24
+  br label %bb18, !dbg !25
+
+bb18:                                             ; preds = %bb12, %bb5, %bb
+  %phi = phi i1 [ false, %bb ], [ false, %bb5 ], [ %icmp17, %bb12 ], !dbg !26
+  ret i1 %phi, !dbg !27
+}
+
+!llvm.dbg.cu = !{!0}
+!llvm.debugify = !{!2, !3}
+!llvm.module.flags = !{!4}
+
+!0 = distinct !DICompileUnit(language: DW_LANG_C, file: !1, producer: "debugify", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug)
+!1 = !DIFile(filename: "reduced.ll", directory: "/")
+!2 = !{i32 20}
+!3 = !{i32 0}
+!4 = !{i32 2, !"Debug Info Version", i32 3}
+!5 = distinct !DISubprogram(name: "wibble", linkageName: "wibble", scope: null, file: !1, line: 1, type: !6, scopeLine: 1, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !0)
+!6 = !DISubroutineType(types: !7)
+!7 = !{}
+!8 = !DILocation(line: 1, column: 1, scope: !5)
+!9 = !DILocation(line: 2, column: 1, scope: !5)
+!10 = !DILocation(line: 3, column: 1, scope: !5)
+!11 = !DILocation(line: 4, column: 1, scope: !5)
+!12 = !DILocation(line: 5, column: 1, scope: !5)
+!13 = !DILocation(line: 6, column: 1, scope: !5)
+!14 = !DILocation(line: 7, column: 1, scope: !5)
+!15 = !DILocation(line: 8, column: 1, scope: !5)
+!16 = !DILocation(line: 9, column: 1, scope: !5)
+!17 = !DILocation(line: 10, column: 1, scope: !5)
+!18 = !DILocation(line: 5, column: 10, scope: !5)
+!19 = !DILocation(line: 6, column: 10, scope: !5)
+!20 = !DILocation(line: 13, column: 1, scope: !5)
+!21 = !DILocation(line: 14, column: 1, scope: !5)
+!22 = !DILocation(line: 15, column: 1, scope: !5)
+!23 = !DILocation(line: 16, column: 1, scope: !5)
+!24 = !DILocation(line: 17, column: 1, scope: !5)
+!25 = !DILocation(line: 18, column: 1, scope: !5)
+!26 = !DILocation(line: 19, column: 1, scope: !5)
+!27 = !DILocation(line: 20, column: 1, scope: !5)
+;.
+; CHECK: [[META0:![0-9]+]] = distinct !DICompileUnit(language: DW_LANG_C, file: [[META1:![0-9]+]], producer: "debugify", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug)
+; CHECK: [[META1]] = !DIFile(filename: "{{.*}}reduced.ll", directory: {{.*}})
+; CHECK: [[DBG5]] = distinct !DISubprogram(name: "wibble", linkageName: "wibble", scope: null, file: [[META1]], line: 1, type: [[META6:![0-9]+]], scopeLine: 1, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: [[META0]])
+; CHECK: [[META6]] = !DISubroutineType(types: [[META7:![0-9]+]])
+; CHECK: [[META7]] = !{}
+; CHECK: [[DBG8]] = !DILocation(line: 1, column: 1, scope: [[DBG5]])
+; CHECK: [[DBG9]] = !DILocation(line: 3, column: 1, scope: [[DBG5]])
+; CHECK: [[DBG10]] = !DILocation(line: 5, scope: [[DBG5]])
+; CHECK: [[DBG11]] = !DILocation(line: 6, scope: [[DBG5]])
+; CHECK: [[DBG12]] = !DILocation(line: 13, column: 1, scope: [[DBG5]])
+; CHECK: [[DBG13]] = !DILocation(line: 15, column: 1, scope: [[DBG5]])
+; CHECK: [[DBG14]] = !DILocation(line: 14, column: 1, scope: [[DBG5]])
+; CHECK: [[DBG15]] = !DILocation(line: 16, column: 1, scope: [[DBG5]])
+; CHECK: [[DBG16]] = !DILocation(line: 17, column: 1, scope: [[DBG5]])
+; CHECK: [[DBG17]] = !DILocation(line: 18, column: 1, scope: [[DBG5]])
+; CHECK: [[DBG18]] = !DILocation(line: 19, column: 1, scope: [[DBG5]])
+; CHECK: [[DBG19]] = !DILocation(line: 20, column: 1, scope: [[DBG5]])
+;.

>From 3cb97451b9c16e4f7e5642bbc1f5d50a17f4df34 Mon Sep 17 00:00:00 2001
From: Stephen Tozer <stephen.tozer at sony.com>
Date: Mon, 6 Jul 2026 10:29:17 +0100
Subject: [PATCH 2/2] Fixup header

---
 llvm/test/Transforms/MergeICmps/X86/dbgloc-branches.ll | 7 +------
 1 file changed, 1 insertion(+), 6 deletions(-)

diff --git a/llvm/test/Transforms/MergeICmps/X86/dbgloc-branches.ll b/llvm/test/Transforms/MergeICmps/X86/dbgloc-branches.ll
index 94a3addd0e0e9..8a3392977e68e 100644
--- a/llvm/test/Transforms/MergeICmps/X86/dbgloc-branches.ll
+++ b/llvm/test/Transforms/MergeICmps/X86/dbgloc-branches.ll
@@ -1,5 +1,5 @@
 ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 6
-; RUN: opt -S -passes=mergeicmps < %s | FileCheck %s
+; RUN: opt -S -passes=mergeicmps -mtriple=x86_64-unknown-unknown < %s | FileCheck %s
 
 ;; Tests that we correctly set debug locations on the instructions generated
 ;; while merging comparison blocks.
@@ -10,11 +10,6 @@
 ;; The branch insts similarly take their debug locations from all of the branch
 ;; insts being merged in the comparison block chain.
 
-
-source_filename = "reduced.ll"
-target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128"
-target triple = "x86_64-unknown-linux-gnu"
-
 define i1 @wibble(ptr dereferenceable(600) %arg) !dbg !5 {
 ; CHECK-LABEL: define i1 @wibble(
 ; CHECK-SAME: ptr dereferenceable(600) [[ARG:%.*]]) !dbg [[DBG5:![0-9]+]] {



More information about the llvm-commits mailing list