[llvm] [LiveDebugVariables] Add tests for stale SlotIndexes (PR #225375)

Jay Foad via llvm-commits llvm-commits at lists.llvm.org
Thu Sep 24 04:06:02 PDT 2026


https://github.com/jayfoad updated https://github.com/llvm/llvm-project/pull/225375

>From a6644ec986ebeeade778c34e624e014010e091b1 Mon Sep 17 00:00:00 2001
From: Jay Foad <jay.foad at amd.com>
Date: Tue, 22 Sep 2026 11:26:56 +0100
Subject: [PATCH 1/2] [LiveDebugVariables] Add tests for stale SlotIndexes

Test various situations where LiveDebugVariables currently keeps
references to SlotIndexes for instructions that have been erased.
---
 .../AArch64/live-debug-vars-hoisted-spill.ll  | 70 ++++++++++++++++
 .../AArch64/live-debug-vars-trimmed-defs.ll   | 80 ++++++++++++++++++
 .../DebugInfo/X86/live-debug-vars-label.ll    | 69 +++++++++++++++
 .../X86/live-debug-vars-stashed-instr.ll      | 84 +++++++++++++++++++
 4 files changed, 303 insertions(+)
 create mode 100644 llvm/test/DebugInfo/AArch64/live-debug-vars-hoisted-spill.ll
 create mode 100644 llvm/test/DebugInfo/AArch64/live-debug-vars-trimmed-defs.ll
 create mode 100644 llvm/test/DebugInfo/X86/live-debug-vars-label.ll
 create mode 100644 llvm/test/DebugInfo/X86/live-debug-vars-stashed-instr.ll

diff --git a/llvm/test/DebugInfo/AArch64/live-debug-vars-hoisted-spill.ll b/llvm/test/DebugInfo/AArch64/live-debug-vars-hoisted-spill.ll
new file mode 100644
index 00000000000000..8e59ca13fa4ef7
--- /dev/null
+++ b/llvm/test/DebugInfo/AArch64/live-debug-vars-hoisted-spill.ll
@@ -0,0 +1,70 @@
+; RUN: llc -mtriple=aarch64-unknown-linux-gnu -O2 -stop-after=virtregrewriter %s -o - | FileCheck %s
+
+; LiveDebugVariables records SlotIndexes during register allocation and uses
+; them afterwards in emitDebugValues, but nothing tells it when an instruction
+; is erased in between, so a recorded index can be left naming an instruction
+; that no longer exists.
+;
+; Here HoistSpillHelper::hoistAllSpills removes a redundant spill, and the
+; interval bounds in UserValue::locInts are left naming it. The location still
+; comes out in the right place because findInsertLocation scans backwards from
+; the recorded index for a surviving instruction to insert after, so this test
+; pins down that currently correct output.
+;
+; Reduced from MultiSource/Benchmarks/7zip 7zUpdate.cpp built at -O2 -g.
+
+; CHECK-LABEL: name: update
+; CHECK: DBG_VALUE $x1, $noreg, ![[VAR:[0-9]+]], !DIExpression(DW_OP_plus_uconst, 72, DW_OP_stack_value)
+; CHECK: DBG_VALUE %stack.[[#]], 0, ![[VAR]], !DIExpression(DW_OP_plus_uconst, 72, DW_OP_stack_value)
+
+define i32 @update(ptr %db, ptr %mode, i1 %c1, ptr %p0, i1 %c2, ptr %p1, ptr %p2, ptr %p3, i1 %c3) !dbg !4 {
+entry:
+  %pw = getelementptr i8, ptr %mode, i64 72
+  br label %loop.outer
+
+loop.outer:                                       ; preds = %latch, %entry
+    #dbg_value(ptr %pw, !9, !DIExpression(), !17)
+  call void @llvm.memset.p0.i64(ptr %mode, i8 0, i64 1, i1 false)
+  br i1 %c3, label %for.cond, label %common.ret
+
+common.ret:                                       ; preds = %for.body, %loop.outer
+  ret i32 0
+
+for.cond:                                         ; preds = %for.end, %loop.outer
+  br i1 %c1, label %for.body, label %latch
+
+for.body:                                         ; preds = %for.cond
+  %v = load volatile ptr, ptr null, align 8
+  br i1 %c2, label %for.end, label %common.ret
+
+for.end:                                          ; preds = %for.body
+  %call = call ptr @allocate(i64 0)
+  store i64 4, ptr %p1, align 8
+  store ptr %p2, ptr %p0, align 8
+  store i64 1, ptr %p3, align 8
+  store volatile i32 0, ptr null, align 4
+  store i32 0, ptr %db, align 4
+  br label %for.cond
+
+latch:                                            ; preds = %for.cond
+  store volatile i32 0, ptr null, align 4
+  br label %loop.outer
+}
+
+declare ptr @allocate(i64)
+
+!llvm.dbg.cu = !{!0}
+!llvm.module.flags = !{!3}
+
+!0 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus_14, file: !1, producer: "clang", isOptimized: true, emissionKind: FullDebug)
+!1 = !DIFile(filename: "7zUpdate.cpp", directory: "/")
+!2 = !{}
+!3 = !{i32 2, !"Debug Info Version", i32 3}
+!4 = distinct !DISubprogram(name: "Update", scope: !1, file: !1, line: 714, type: !8, scopeLine: 728, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !0)
+!8 = distinct !DISubroutineType(types: !2)
+!9 = !DILocalVariable(name: "this", arg: 1, scope: !10, type: !16, flags: DIFlagArtificial | DIFlagObjectPointer)
+!10 = distinct !DISubprogram(name: "CStringBase", scope: !1, file: !1, line: 182, type: !8, scopeLine: 182, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !0)
+!16 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: null, size: 64)
+!17 = distinct !DILocation(line: 0, scope: !10, inlinedAt: !18)
+!18 = distinct !DILocation(line: 41, column: 3, scope: !19)
+!19 = distinct !DISubprogram(name: "CCompressionMethodMode", scope: !1, file: !1, line: 41, type: !8, scopeLine: 45, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !0)
diff --git a/llvm/test/DebugInfo/AArch64/live-debug-vars-trimmed-defs.ll b/llvm/test/DebugInfo/AArch64/live-debug-vars-trimmed-defs.ll
new file mode 100644
index 00000000000000..402f1f95681be4
--- /dev/null
+++ b/llvm/test/DebugInfo/AArch64/live-debug-vars-trimmed-defs.ll
@@ -0,0 +1,80 @@
+; RUN: llc -mtriple=aarch64-unknown-linux-gnu -O2 -stop-after=virtregrewriter %s -o - | FileCheck %s
+
+; UserValue::trimmedDefs records interval start indexes that computeIntervals
+; trimmed to a lexical scope, and emitDebugValues matches them against the
+; starts in locInts to decide whether to step a DBG_VALUE back one index.
+;
+; Nothing tells LiveDebugVariables when an instruction is erased during
+; register allocation, so here both a trimmed start and the locInts start it
+; belongs to are left naming an instruction that has been erased. The
+; locations still come out in the right place, so this test pins down that
+; currently correct output.
+;
+; Reduced from MultiSource/Benchmarks/DOE-ProxyApps-C++/PENNANT built at -O2 -g.
+
+; CHECK-LABEL: name: map_index
+; CHECK: DBG_VALUE $x0, $noreg, ![[VAR:[0-9]+]], !DIExpression()
+; CHECK: DBG_VALUE $x{{[0-9]+}}, $noreg, ![[VAR]], !DIExpression()
+
+target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128-Fn32"
+target triple = "aarch64-unknown-linux-gnu"
+
+define ptr @map_index(ptr %this, ptr %k, ptr %p0, ptr %x.addr.1, ptr %p1, i64 %n, i1 %cmp.i) !dbg !4 {
+entry:
+    #dbg_value(ptr %this, !10, !DIExpression(), !17)
+  %add.ptr = getelementptr i8, ptr %this, i64 8, !dbg !27
+  br label %while.body
+
+while.body:                                       ; preds = %while.body, %entry
+  %x.addr.011 = phi ptr [ null, %entry ], [ %x.addr.1, %while.body ]
+  %call = call i32 @memcmp(ptr %p1)
+  %sub = sub i64 0, %n
+  %spec.select = tail call i64 @llvm.smax.i64(i64 %sub, i64 1)
+  %retval.07 = tail call i64 @llvm.smin.i64(i64 %spec.select, i64 2147483647)
+  br i1 %cmp.i, label %lower_bound.exit, label %while.body
+
+lower_bound.exit:                                 ; preds = %while.body
+  %retval.0.i12 = trunc i64 %retval.07 to i32
+  %cmp.i3 = icmp slt i32 %retval.0.i12, 0
+  %y.addr.1 = select i1 %cmp.i3, ptr null, ptr %x.addr.011
+  %cmp = icmp eq ptr %y.addr.1, %add.ptr
+  br i1 %cmp, label %if.then, label %common.ret
+
+common.ret:                                       ; preds = %if.then, %lower_bound.exit
+  ret ptr null
+
+if.then:                                          ; preds = %lower_bound.exit
+  store ptr %k, ptr %p0, align 8
+  %call12 = load volatile ptr, ptr %this, align 8
+  br label %common.ret
+}
+
+declare i32 @memcmp(ptr)
+
+!llvm.dbg.cu = !{!0}
+!llvm.module.flags = !{!3}
+
+!0 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus_14, file: !1, producer: "clang", isOptimized: true, emissionKind: FullDebug)
+!1 = !DIFile(filename: "InputFile.cc", directory: "/")
+!2 = !{}
+!3 = !{i32 2, !"Debug Info Version", i32 3}
+!4 = distinct !DISubprogram(name: "operator[]", scope: !6, file: !5, line: 504, type: !8, scopeLine: 505, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !0)
+!5 = !DIFile(filename: "stl_map.h", directory: "/")
+!6 = distinct !DICompositeType(tag: DW_TAG_class_type, name: "map", scope: !7, file: !5, line: 102, size: 384, flags: DIFlagTypePassByReference | DIFlagNonTrivial, elements: !2)
+!7 = !DINamespace(name: "std", scope: null)
+!8 = distinct !DISubroutineType(types: !2)
+!10 = !DILocalVariable(name: "this", arg: 1, scope: !11, type: !16, flags: DIFlagArtificial | DIFlagObjectPointer)
+!11 = distinct !DISubprogram(name: "_M_end", scope: !13, file: !12, line: 747, type: !14, scopeLine: 748, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !0)
+!12 = !DIFile(filename: "stl_tree.h", directory: "/")
+!13 = distinct !DICompositeType(tag: DW_TAG_class_type, name: "_Rb_tree", scope: !7, file: !12, line: 423, size: 384, flags: DIFlagTypePassByReference | DIFlagNonTrivial, elements: !2)
+!14 = distinct !DISubroutineType(types: !2)
+!16 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !13, size: 64)
+!17 = distinct !DILocation(line: 0, scope: !11, inlinedAt: !18)
+!18 = distinct !DILocation(line: 1267, column: 43, scope: !19, inlinedAt: !22)
+!19 = distinct !DISubprogram(name: "lower_bound", scope: !13, file: !12, line: 1266, type: !20, scopeLine: 1267, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !0)
+!20 = distinct !DISubroutineType(types: !2)
+!22 = distinct !DILocation(line: 1308, column: 21, scope: !23, inlinedAt: !26)
+!23 = distinct !DISubprogram(name: "lower_bound", scope: !6, file: !5, line: 1307, type: !24, scopeLine: 1308, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !0)
+!24 = distinct !DISubroutineType(types: !2)
+!26 = distinct !DILocation(line: 509, column: 17, scope: !4)
+!27 = distinct !DILocation(line: 748, column: 17, scope: !11, inlinedAt: !18)
diff --git a/llvm/test/DebugInfo/X86/live-debug-vars-label.ll b/llvm/test/DebugInfo/X86/live-debug-vars-label.ll
new file mode 100644
index 00000000000000..dd308a1ac35038
--- /dev/null
+++ b/llvm/test/DebugInfo/X86/live-debug-vars-label.ll
@@ -0,0 +1,69 @@
+; RUN: llc -mtriple=x86_64-unknown-linux-gnu -O2 -stop-after=livedebugvalues %s -o - | FileCheck %s
+
+; LiveDebugVariables records the SlotIndex of a DBG_LABEL in UserLabel::loc and
+; re-inserts the label there after register allocation. Nothing tells it when
+; an instruction is erased in between, so here loc is left naming one that has
+; been erased. The label still comes out in the right place because
+; insertDebugLabel goes through findInsertLocation, which scans backwards from
+; the recorded index for a surviving instruction to insert after, so this test
+; pins down that currently correct output.
+;
+; Reduced from MultiSource/Benchmarks/Prolangs-C/cdecl built at -O2 -g.
+
+; CHECK-LABEL: name: yyparse
+; CHECK: DBG_LABEL !{{[0-9]+}}, debug-location !{{[0-9]+}}
+
+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 i32 @yyparse(ptr %add.ptr132, i16 %0, i16 %1, i1 %cmp.not, i1 %cmp8) !dbg !4 {
+entry:
+    #dbg_label(!7, !8)
+  br label %if.end
+
+if.then:                                          ; preds = %yystack.backedge
+  ret i32 0
+
+if.end:                                           ; preds = %yystack.backedge, %entry
+  %yystate.01028 = phi i16 [ 0, %entry ], [ %0, %yystack.backedge ]
+  store i16 %yystate.01028, ptr null, align 2
+  br i1 %cmp8, label %if.then10, label %if.end15
+
+if.then10:                                        ; preds = %if.end
+  %call = tail call i32 null()
+  br label %if.end15
+
+if.end15:                                         ; preds = %if.then10, %if.end
+  tail call void @llvm.memcpy.p0.p0.i64(ptr null, ptr %add.ptr132, i64 1, i1 false)
+  switch i16 %1, label %yystack.backedge [
+    i16 2, label %sw.bb162
+    i16 4, label %sw.bb164
+  ]
+
+yystack.backedge:                                 ; preds = %if.end15
+  br i1 %cmp.not, label %if.end, label %if.then
+
+sw.bb162:                                         ; preds = %if.end15
+  ret i32 0
+
+sw.bb164:                                         ; preds = %if.end15
+  ret i32 0
+}
+
+; Function Attrs: nocallback nofree nosync nounwind willreturn memory(argmem: readwrite)
+declare void @llvm.memcpy.p0.p0.i64(ptr noalias writeonly captures(none), ptr noalias readonly captures(none), i64, i1 immarg) #0
+
+attributes #0 = { nocallback nofree nosync nounwind willreturn memory(argmem: readwrite) }
+
+!llvm.dbg.cu = !{!0}
+!llvm.module.flags = !{!3}
+
+!0 = distinct !DICompileUnit(language: DW_LANG_C89, file: !1, producer: "clang", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, enums: !2, retainedTypes: !2, globals: !2, splitDebugInlining: false, nameTableKind: None)
+!1 = !DIFile(filename: "cdecl.c", directory: "/")
+!2 = !{}
+!3 = !{i32 2, !"Debug Info Version", i32 3}
+!4 = distinct !DISubprogram(name: "yyparse", scope: !5, file: !5, line: 1022, type: !6, scopeLine: 1022, flags: DIFlagAllCallsDescribed, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !0, retainedNodes: !2, keyInstructions: true)
+!5 = !DIFile(filename: "cdgram.y", directory: "/")
+!6 = !DISubroutineType(types: !2)
+!7 = !DILabel(scope: !4, name: "yystack", file: !5, line: 1038, column: 2)
+!8 = !DILocation(line: 1038, column: 2, scope: !4)
diff --git a/llvm/test/DebugInfo/X86/live-debug-vars-stashed-instr.ll b/llvm/test/DebugInfo/X86/live-debug-vars-stashed-instr.ll
new file mode 100644
index 00000000000000..93371f34aaeab5
--- /dev/null
+++ b/llvm/test/DebugInfo/X86/live-debug-vars-stashed-instr.ll
@@ -0,0 +1,84 @@
+; RUN: llc -mtriple=x86_64-unknown-linux-gnu -O2 -experimental-debug-variable-locations=true -stop-after=livedebugvalues %s -o - | FileCheck %s
+
+; In instruction referencing mode LiveDebugVariables unlinks debug instructions
+; during register allocation and records the SlotIndex to put them back at, in
+; StashedDebugInstrs. Nothing tells it when the instruction at that index is
+; erased in between, so here the recorded index is left naming one that has
+; been erased, and emitDebugValues takes its "insert position disappeared"
+; path, walking forwards through the slots for a new one. Note that this is
+; the opposite direction to findInsertLocation, which scans backwards.
+;
+; Reduced from MultiSource/Applications/oggenc built at -O2 -g.
+
+; CHECK-LABEL: name: accumulate_fit
+; CHECK: DBG_VALUE 0, $noreg, ![[VAR:[0-9]+]], !DIExpression(), debug-location ![[LOC:[0-9]+]]
+
+define fastcc i32 @accumulate_fit(ptr %flr, ptr %mdct, i32 %x0, i32 %x1, ptr %a, i32 %n, ptr %info, i64 %i.0141) !dbg !4 {
+entry:
+    #dbg_value(i64 0, !7, !DIExpression(), !9)
+  %conv = sext i32 %x0 to i64
+  br label %for.body
+
+for.body:                                         ; preds = %if.end37, %entry
+  %y2b.0151 = phi i64 [ 0, %entry ], [ %y2b.1, %if.end37 ]
+  %x2b.0150 = phi i64 [ 0, %entry ], [ %x2b.1, %if.end37 ]
+  %yb.0149 = phi i64 [ 0, %entry ], [ %yb.1, %if.end37 ]
+  %xb.0148 = phi i64 [ 0, %entry ], [ %xb.1, %if.end37 ]
+  %na.0147 = phi i64 [ 0, %entry ], [ %na.1, %if.end37 ]
+  %xya.0146 = phi i64 [ 0, %entry ], [ %xya.1, %if.end37 ]
+  %y2a.0145 = phi i64 [ 0, %entry ], [ %y2a.1, %if.end37 ]
+  %x2a.0144 = phi i64 [ 0, %entry ], [ %x2a.1, %if.end37 ]
+  %i.01412 = phi i64 [ %conv, %entry ], [ 0, %if.end37 ]
+  %add.ptr = getelementptr [4 x i8], ptr %flr, i64 %i.01412
+  %0 = load float, ptr %add.ptr, align 4
+  %conv.i = fptosi float %0 to i32
+  %arrayidx = getelementptr [4 x i8], ptr %mdct, i64 %i.01412
+  %1 = load float, ptr %arrayidx, align 4
+  %2 = load float, ptr %info, align 4
+  %add = fadd float %1, %2
+  %3 = tail call i32 @llvm.umin.i32(i32 %conv.i, i32 1)
+  %mul273 = mul i64 %i.0141, %i.0141
+  %cmp11 = fcmp ult float %add, 0.000000e+00
+  br i1 %cmp11, label %if.else, label %if.then13
+
+if.then13:                                        ; preds = %for.body
+  %add17 = or i64 %x2a.0144, %mul273
+  %add20 = or i64 %y2a.0145, 1
+  %add23 = or i64 1, %xya.0146
+  %inc = or i64 %na.0147, 1
+  br label %if.end37
+
+if.else:                                          ; preds = %for.body
+  %add24 = or i64 %xb.0148, %i.0141
+  %conv25 = zext i32 %3 to i64
+  %add26 = or i64 %yb.0149, %conv25
+  %add28 = or i64 %x2b.0150, 1
+  %add31 = or i64 %y2b.0151, %i.0141
+  br label %if.end37
+
+if.end37:                                         ; preds = %if.else, %if.then13
+  %x2a.1 = phi i64 [ %add17, %if.then13 ], [ %x2a.0144, %if.else ]
+  %y2a.1 = phi i64 [ %add20, %if.then13 ], [ %y2a.0145, %if.else ]
+  %xya.1 = phi i64 [ %add23, %if.then13 ], [ %xya.0146, %if.else ]
+  %na.1 = phi i64 [ %inc, %if.then13 ], [ %na.0147, %if.else ]
+  %xb.1 = phi i64 [ %xb.0148, %if.then13 ], [ %add24, %if.else ]
+  %yb.1 = phi i64 [ %yb.0149, %if.then13 ], [ %add26, %if.else ]
+  %x2b.1 = phi i64 [ %x2b.0150, %if.then13 ], [ %add28, %if.else ]
+  %y2b.1 = phi i64 [ %y2b.0151, %if.then13 ], [ %add31, %if.else ]
+  br label %for.body
+}
+
+declare i32 @llvm.umin.i32(i32, i32)
+
+!llvm.dbg.cu = !{!0}
+!llvm.module.flags = !{!3}
+
+!0 = distinct !DICompileUnit(language: DW_LANG_C11, file: !1, producer: "clang", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, splitDebugInlining: false, nameTableKind: None)
+!1 = !DIFile(filename: "oggenc.c", directory: "/")
+!3 = !{i32 2, !"Debug Info Version", i32 3}
+!4 = distinct !DISubprogram(name: "accumulate_fit", scope: !1, file: !1, line: 1, type: !6, scopeLine: 1, flags: DIFlagPrototyped | DIFlagAllCallsDescribed, spFlags: DISPFlagLocalToUnit | DISPFlagDefinition | DISPFlagOptimized, unit: !0)
+!6 = distinct !DISubroutineType(types: !2)
+!2 = !{}
+!7 = !DILocalVariable(name: "xa", scope: !4, file: !1, line: 2, type: !8)
+!8 = !DIBasicType(name: "long", size: 64, encoding: DW_ATE_signed)
+!9 = !DILocation(line: 0, scope: !4)

>From 8988528f568574700f4a667f7e4554aa67cb6e21 Mon Sep 17 00:00:00 2001
From: Jay Foad <jay.foad at amd.com>
Date: Thu, 24 Sep 2026 12:05:18 +0100
Subject: [PATCH 2/2] Two tests per file. Name all IR values.

---
 .../AArch64/live-debug-vars-hoisted-spill.ll  |  70 ---------
 .../live-debug-vars-stale-slotindexes.ll      | 139 +++++++++++++++++
 .../AArch64/live-debug-vars-trimmed-defs.ll   |  80 ----------
 .../DebugInfo/X86/live-debug-vars-label.ll    |  69 ---------
 .../X86/live-debug-vars-stale-slotindexes.ll  | 141 ++++++++++++++++++
 .../X86/live-debug-vars-stashed-instr.ll      |  84 -----------
 6 files changed, 280 insertions(+), 303 deletions(-)
 delete mode 100644 llvm/test/DebugInfo/AArch64/live-debug-vars-hoisted-spill.ll
 create mode 100644 llvm/test/DebugInfo/AArch64/live-debug-vars-stale-slotindexes.ll
 delete mode 100644 llvm/test/DebugInfo/AArch64/live-debug-vars-trimmed-defs.ll
 delete mode 100644 llvm/test/DebugInfo/X86/live-debug-vars-label.ll
 create mode 100644 llvm/test/DebugInfo/X86/live-debug-vars-stale-slotindexes.ll
 delete mode 100644 llvm/test/DebugInfo/X86/live-debug-vars-stashed-instr.ll

diff --git a/llvm/test/DebugInfo/AArch64/live-debug-vars-hoisted-spill.ll b/llvm/test/DebugInfo/AArch64/live-debug-vars-hoisted-spill.ll
deleted file mode 100644
index 8e59ca13fa4ef7..00000000000000
--- a/llvm/test/DebugInfo/AArch64/live-debug-vars-hoisted-spill.ll
+++ /dev/null
@@ -1,70 +0,0 @@
-; RUN: llc -mtriple=aarch64-unknown-linux-gnu -O2 -stop-after=virtregrewriter %s -o - | FileCheck %s
-
-; LiveDebugVariables records SlotIndexes during register allocation and uses
-; them afterwards in emitDebugValues, but nothing tells it when an instruction
-; is erased in between, so a recorded index can be left naming an instruction
-; that no longer exists.
-;
-; Here HoistSpillHelper::hoistAllSpills removes a redundant spill, and the
-; interval bounds in UserValue::locInts are left naming it. The location still
-; comes out in the right place because findInsertLocation scans backwards from
-; the recorded index for a surviving instruction to insert after, so this test
-; pins down that currently correct output.
-;
-; Reduced from MultiSource/Benchmarks/7zip 7zUpdate.cpp built at -O2 -g.
-
-; CHECK-LABEL: name: update
-; CHECK: DBG_VALUE $x1, $noreg, ![[VAR:[0-9]+]], !DIExpression(DW_OP_plus_uconst, 72, DW_OP_stack_value)
-; CHECK: DBG_VALUE %stack.[[#]], 0, ![[VAR]], !DIExpression(DW_OP_plus_uconst, 72, DW_OP_stack_value)
-
-define i32 @update(ptr %db, ptr %mode, i1 %c1, ptr %p0, i1 %c2, ptr %p1, ptr %p2, ptr %p3, i1 %c3) !dbg !4 {
-entry:
-  %pw = getelementptr i8, ptr %mode, i64 72
-  br label %loop.outer
-
-loop.outer:                                       ; preds = %latch, %entry
-    #dbg_value(ptr %pw, !9, !DIExpression(), !17)
-  call void @llvm.memset.p0.i64(ptr %mode, i8 0, i64 1, i1 false)
-  br i1 %c3, label %for.cond, label %common.ret
-
-common.ret:                                       ; preds = %for.body, %loop.outer
-  ret i32 0
-
-for.cond:                                         ; preds = %for.end, %loop.outer
-  br i1 %c1, label %for.body, label %latch
-
-for.body:                                         ; preds = %for.cond
-  %v = load volatile ptr, ptr null, align 8
-  br i1 %c2, label %for.end, label %common.ret
-
-for.end:                                          ; preds = %for.body
-  %call = call ptr @allocate(i64 0)
-  store i64 4, ptr %p1, align 8
-  store ptr %p2, ptr %p0, align 8
-  store i64 1, ptr %p3, align 8
-  store volatile i32 0, ptr null, align 4
-  store i32 0, ptr %db, align 4
-  br label %for.cond
-
-latch:                                            ; preds = %for.cond
-  store volatile i32 0, ptr null, align 4
-  br label %loop.outer
-}
-
-declare ptr @allocate(i64)
-
-!llvm.dbg.cu = !{!0}
-!llvm.module.flags = !{!3}
-
-!0 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus_14, file: !1, producer: "clang", isOptimized: true, emissionKind: FullDebug)
-!1 = !DIFile(filename: "7zUpdate.cpp", directory: "/")
-!2 = !{}
-!3 = !{i32 2, !"Debug Info Version", i32 3}
-!4 = distinct !DISubprogram(name: "Update", scope: !1, file: !1, line: 714, type: !8, scopeLine: 728, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !0)
-!8 = distinct !DISubroutineType(types: !2)
-!9 = !DILocalVariable(name: "this", arg: 1, scope: !10, type: !16, flags: DIFlagArtificial | DIFlagObjectPointer)
-!10 = distinct !DISubprogram(name: "CStringBase", scope: !1, file: !1, line: 182, type: !8, scopeLine: 182, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !0)
-!16 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: null, size: 64)
-!17 = distinct !DILocation(line: 0, scope: !10, inlinedAt: !18)
-!18 = distinct !DILocation(line: 41, column: 3, scope: !19)
-!19 = distinct !DISubprogram(name: "CCompressionMethodMode", scope: !1, file: !1, line: 41, type: !8, scopeLine: 45, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !0)
diff --git a/llvm/test/DebugInfo/AArch64/live-debug-vars-stale-slotindexes.ll b/llvm/test/DebugInfo/AArch64/live-debug-vars-stale-slotindexes.ll
new file mode 100644
index 00000000000000..43f67c3a0c3e22
--- /dev/null
+++ b/llvm/test/DebugInfo/AArch64/live-debug-vars-stale-slotindexes.ll
@@ -0,0 +1,139 @@
+; RUN: llc -mtriple=aarch64-unknown-linux-gnu -O2 -stop-after=virtregrewriter %s -o - | FileCheck %s
+
+; LiveDebugVariables records SlotIndexes during register allocation and uses
+; them afterwards to re-insert debug instructions, but nothing tells it when an
+; instruction is erased in between, so a recorded index can be left naming an
+; instruction that no longer exists. Each function below reaches one such case.
+; The debug instructions still come out in the right place, so these tests pin
+; down that currently correct output.
+;
+; See also DebugInfo/X86/live-debug-vars-stale-slotindexes.ll.
+
+; HoistSpillHelper::hoistAllSpills removes a redundant spill, and the interval
+; bounds in UserValue::locInts are left naming it. findInsertLocation scans
+; backwards from the recorded index for a surviving instruction to insert
+; after.
+;
+; Reduced from MultiSource/Benchmarks/7zip 7zUpdate.cpp built at -O2 -g.
+
+; CHECK-LABEL: name: update
+; CHECK: DBG_VALUE $x1, $noreg, ![[VAR:[0-9]+]], !DIExpression(DW_OP_plus_uconst, 72, DW_OP_stack_value)
+; CHECK: DBG_VALUE %stack.[[#]], 0, ![[VAR]], !DIExpression(DW_OP_plus_uconst, 72, DW_OP_stack_value)
+
+define i32 @update(ptr %db, ptr %mode, i1 %c1, ptr %p0, i1 %c2, ptr %p1, ptr %p2, ptr %p3, i1 %c3) !dbg !4 {
+entry:
+  %pw = getelementptr i8, ptr %mode, i64 72
+  br label %loop.outer
+
+loop.outer:                                       ; preds = %latch, %entry
+    #dbg_value(ptr %pw, !9, !DIExpression(), !17)
+  call void @llvm.memset.p0.i64(ptr %mode, i8 0, i64 1, i1 false)
+  br i1 %c3, label %for.cond, label %common.ret
+
+common.ret:                                       ; preds = %for.body, %loop.outer
+  ret i32 0
+
+for.cond:                                         ; preds = %for.end, %loop.outer
+  br i1 %c1, label %for.body, label %latch
+
+for.body:                                         ; preds = %for.cond
+  %v = load volatile ptr, ptr null, align 8
+  br i1 %c2, label %for.end, label %common.ret
+
+for.end:                                          ; preds = %for.body
+  %call = call ptr @allocate(i64 0)
+  store i64 4, ptr %p1, align 8
+  store ptr %p2, ptr %p0, align 8
+  store i64 1, ptr %p3, align 8
+  store volatile i32 0, ptr null, align 4
+  store i32 0, ptr %db, align 4
+  br label %for.cond
+
+latch:                                            ; preds = %for.cond
+  store volatile i32 0, ptr null, align 4
+  br label %loop.outer
+}
+
+declare ptr @allocate(i64)
+
+; UserValue::trimmedDefs records interval start indexes that computeIntervals
+; trimmed to a lexical scope, and emitDebugValues matches them against the
+; starts in locInts to decide whether to step a DBG_VALUE back one index. Here
+; both a trimmed start and the locInts start it belongs to are left naming an
+; erased instruction.
+;
+; Reduced from MultiSource/Benchmarks/DOE-ProxyApps-C++/PENNANT built at -O2 -g.
+
+; CHECK-LABEL: name: map_index
+; CHECK: DBG_VALUE $x0, $noreg, ![[VAR:[0-9]+]], !DIExpression()
+; CHECK: DBG_VALUE $x{{[0-9]+}}, $noreg, ![[VAR]], !DIExpression()
+
+define ptr @map_index(ptr %this, ptr %k, ptr %p0, ptr %x.addr.1, ptr %p1, i64 %n, i1 %cmp.i) !dbg !24 {
+entry:
+    #dbg_value(ptr %this, !30, !DIExpression(), !37)
+  %add.ptr = getelementptr i8, ptr %this, i64 8, !dbg !47
+  br label %while.body
+
+while.body:                                       ; preds = %while.body, %entry
+  %x.addr.011 = phi ptr [ null, %entry ], [ %x.addr.1, %while.body ]
+  %call = call i32 @memcmp(ptr %p1)
+  %sub = sub i64 0, %n
+  %spec.select = tail call i64 @llvm.smax.i64(i64 %sub, i64 1)
+  %retval.07 = tail call i64 @llvm.smin.i64(i64 %spec.select, i64 2147483647)
+  br i1 %cmp.i, label %lower_bound.exit, label %while.body
+
+lower_bound.exit:                                 ; preds = %while.body
+  %retval.0.i12 = trunc i64 %retval.07 to i32
+  %cmp.i3 = icmp slt i32 %retval.0.i12, 0
+  %y.addr.1 = select i1 %cmp.i3, ptr null, ptr %x.addr.011
+  %cmp = icmp eq ptr %y.addr.1, %add.ptr
+  br i1 %cmp, label %if.then, label %common.ret
+
+common.ret:                                       ; preds = %if.then, %lower_bound.exit
+  ret ptr null
+
+if.then:                                          ; preds = %lower_bound.exit
+  store ptr %k, ptr %p0, align 8
+  %call12 = load volatile ptr, ptr %this, align 8
+  br label %common.ret
+}
+
+declare i32 @memcmp(ptr)
+
+!llvm.dbg.cu = !{!0, !20}
+!llvm.module.flags = !{!3}
+!0 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus_14, file: !1, producer: "clang", isOptimized: true, emissionKind: FullDebug)
+!1 = !DIFile(filename: "7zUpdate.cpp", directory: "/")
+!2 = !{}
+!3 = !{i32 2, !"Debug Info Version", i32 3}
+!4 = distinct !DISubprogram(name: "Update", scope: !1, file: !1, line: 714, type: !8, scopeLine: 728, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !0)
+!8 = distinct !DISubroutineType(types: !2)
+!9 = !DILocalVariable(name: "this", arg: 1, scope: !10, type: !16, flags: DIFlagArtificial | DIFlagObjectPointer)
+!10 = distinct !DISubprogram(name: "CStringBase", scope: !1, file: !1, line: 182, type: !8, scopeLine: 182, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !0)
+!16 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: null, size: 64)
+!17 = distinct !DILocation(line: 0, scope: !10, inlinedAt: !18)
+!18 = distinct !DILocation(line: 41, column: 3, scope: !19)
+!19 = distinct !DISubprogram(name: "CCompressionMethodMode", scope: !1, file: !1, line: 41, type: !8, scopeLine: 45, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !0)
+!20 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus_14, file: !21, producer: "clang", isOptimized: true, emissionKind: FullDebug)
+!21 = !DIFile(filename: "InputFile.cc", directory: "/")
+!22 = !{}
+!24 = distinct !DISubprogram(name: "operator[]", scope: !26, file: !25, line: 504, type: !28, scopeLine: 505, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !20)
+!25 = !DIFile(filename: "stl_map.h", directory: "/")
+!26 = distinct !DICompositeType(tag: DW_TAG_class_type, name: "map", scope: !27, file: !25, line: 102, size: 384, flags: DIFlagTypePassByReference | DIFlagNonTrivial, elements: !22)
+!27 = !DINamespace(name: "std", scope: null)
+!28 = distinct !DISubroutineType(types: !22)
+!30 = !DILocalVariable(name: "this", arg: 1, scope: !31, type: !36, flags: DIFlagArtificial | DIFlagObjectPointer)
+!31 = distinct !DISubprogram(name: "_M_end", scope: !33, file: !32, line: 747, type: !34, scopeLine: 748, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !20)
+!32 = !DIFile(filename: "stl_tree.h", directory: "/")
+!33 = distinct !DICompositeType(tag: DW_TAG_class_type, name: "_Rb_tree", scope: !27, file: !32, line: 423, size: 384, flags: DIFlagTypePassByReference | DIFlagNonTrivial, elements: !22)
+!34 = distinct !DISubroutineType(types: !22)
+!36 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !33, size: 64)
+!37 = distinct !DILocation(line: 0, scope: !31, inlinedAt: !38)
+!38 = distinct !DILocation(line: 1267, column: 43, scope: !39, inlinedAt: !42)
+!39 = distinct !DISubprogram(name: "lower_bound", scope: !33, file: !32, line: 1266, type: !40, scopeLine: 1267, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !20)
+!40 = distinct !DISubroutineType(types: !22)
+!42 = distinct !DILocation(line: 1308, column: 21, scope: !43, inlinedAt: !46)
+!43 = distinct !DISubprogram(name: "lower_bound", scope: !26, file: !25, line: 1307, type: !44, scopeLine: 1308, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !20)
+!44 = distinct !DISubroutineType(types: !22)
+!46 = distinct !DILocation(line: 509, column: 17, scope: !24)
+!47 = distinct !DILocation(line: 748, column: 17, scope: !31, inlinedAt: !38)
diff --git a/llvm/test/DebugInfo/AArch64/live-debug-vars-trimmed-defs.ll b/llvm/test/DebugInfo/AArch64/live-debug-vars-trimmed-defs.ll
deleted file mode 100644
index 402f1f95681be4..00000000000000
--- a/llvm/test/DebugInfo/AArch64/live-debug-vars-trimmed-defs.ll
+++ /dev/null
@@ -1,80 +0,0 @@
-; RUN: llc -mtriple=aarch64-unknown-linux-gnu -O2 -stop-after=virtregrewriter %s -o - | FileCheck %s
-
-; UserValue::trimmedDefs records interval start indexes that computeIntervals
-; trimmed to a lexical scope, and emitDebugValues matches them against the
-; starts in locInts to decide whether to step a DBG_VALUE back one index.
-;
-; Nothing tells LiveDebugVariables when an instruction is erased during
-; register allocation, so here both a trimmed start and the locInts start it
-; belongs to are left naming an instruction that has been erased. The
-; locations still come out in the right place, so this test pins down that
-; currently correct output.
-;
-; Reduced from MultiSource/Benchmarks/DOE-ProxyApps-C++/PENNANT built at -O2 -g.
-
-; CHECK-LABEL: name: map_index
-; CHECK: DBG_VALUE $x0, $noreg, ![[VAR:[0-9]+]], !DIExpression()
-; CHECK: DBG_VALUE $x{{[0-9]+}}, $noreg, ![[VAR]], !DIExpression()
-
-target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128-Fn32"
-target triple = "aarch64-unknown-linux-gnu"
-
-define ptr @map_index(ptr %this, ptr %k, ptr %p0, ptr %x.addr.1, ptr %p1, i64 %n, i1 %cmp.i) !dbg !4 {
-entry:
-    #dbg_value(ptr %this, !10, !DIExpression(), !17)
-  %add.ptr = getelementptr i8, ptr %this, i64 8, !dbg !27
-  br label %while.body
-
-while.body:                                       ; preds = %while.body, %entry
-  %x.addr.011 = phi ptr [ null, %entry ], [ %x.addr.1, %while.body ]
-  %call = call i32 @memcmp(ptr %p1)
-  %sub = sub i64 0, %n
-  %spec.select = tail call i64 @llvm.smax.i64(i64 %sub, i64 1)
-  %retval.07 = tail call i64 @llvm.smin.i64(i64 %spec.select, i64 2147483647)
-  br i1 %cmp.i, label %lower_bound.exit, label %while.body
-
-lower_bound.exit:                                 ; preds = %while.body
-  %retval.0.i12 = trunc i64 %retval.07 to i32
-  %cmp.i3 = icmp slt i32 %retval.0.i12, 0
-  %y.addr.1 = select i1 %cmp.i3, ptr null, ptr %x.addr.011
-  %cmp = icmp eq ptr %y.addr.1, %add.ptr
-  br i1 %cmp, label %if.then, label %common.ret
-
-common.ret:                                       ; preds = %if.then, %lower_bound.exit
-  ret ptr null
-
-if.then:                                          ; preds = %lower_bound.exit
-  store ptr %k, ptr %p0, align 8
-  %call12 = load volatile ptr, ptr %this, align 8
-  br label %common.ret
-}
-
-declare i32 @memcmp(ptr)
-
-!llvm.dbg.cu = !{!0}
-!llvm.module.flags = !{!3}
-
-!0 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus_14, file: !1, producer: "clang", isOptimized: true, emissionKind: FullDebug)
-!1 = !DIFile(filename: "InputFile.cc", directory: "/")
-!2 = !{}
-!3 = !{i32 2, !"Debug Info Version", i32 3}
-!4 = distinct !DISubprogram(name: "operator[]", scope: !6, file: !5, line: 504, type: !8, scopeLine: 505, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !0)
-!5 = !DIFile(filename: "stl_map.h", directory: "/")
-!6 = distinct !DICompositeType(tag: DW_TAG_class_type, name: "map", scope: !7, file: !5, line: 102, size: 384, flags: DIFlagTypePassByReference | DIFlagNonTrivial, elements: !2)
-!7 = !DINamespace(name: "std", scope: null)
-!8 = distinct !DISubroutineType(types: !2)
-!10 = !DILocalVariable(name: "this", arg: 1, scope: !11, type: !16, flags: DIFlagArtificial | DIFlagObjectPointer)
-!11 = distinct !DISubprogram(name: "_M_end", scope: !13, file: !12, line: 747, type: !14, scopeLine: 748, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !0)
-!12 = !DIFile(filename: "stl_tree.h", directory: "/")
-!13 = distinct !DICompositeType(tag: DW_TAG_class_type, name: "_Rb_tree", scope: !7, file: !12, line: 423, size: 384, flags: DIFlagTypePassByReference | DIFlagNonTrivial, elements: !2)
-!14 = distinct !DISubroutineType(types: !2)
-!16 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !13, size: 64)
-!17 = distinct !DILocation(line: 0, scope: !11, inlinedAt: !18)
-!18 = distinct !DILocation(line: 1267, column: 43, scope: !19, inlinedAt: !22)
-!19 = distinct !DISubprogram(name: "lower_bound", scope: !13, file: !12, line: 1266, type: !20, scopeLine: 1267, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !0)
-!20 = distinct !DISubroutineType(types: !2)
-!22 = distinct !DILocation(line: 1308, column: 21, scope: !23, inlinedAt: !26)
-!23 = distinct !DISubprogram(name: "lower_bound", scope: !6, file: !5, line: 1307, type: !24, scopeLine: 1308, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !0)
-!24 = distinct !DISubroutineType(types: !2)
-!26 = distinct !DILocation(line: 509, column: 17, scope: !4)
-!27 = distinct !DILocation(line: 748, column: 17, scope: !11, inlinedAt: !18)
diff --git a/llvm/test/DebugInfo/X86/live-debug-vars-label.ll b/llvm/test/DebugInfo/X86/live-debug-vars-label.ll
deleted file mode 100644
index dd308a1ac35038..00000000000000
--- a/llvm/test/DebugInfo/X86/live-debug-vars-label.ll
+++ /dev/null
@@ -1,69 +0,0 @@
-; RUN: llc -mtriple=x86_64-unknown-linux-gnu -O2 -stop-after=livedebugvalues %s -o - | FileCheck %s
-
-; LiveDebugVariables records the SlotIndex of a DBG_LABEL in UserLabel::loc and
-; re-inserts the label there after register allocation. Nothing tells it when
-; an instruction is erased in between, so here loc is left naming one that has
-; been erased. The label still comes out in the right place because
-; insertDebugLabel goes through findInsertLocation, which scans backwards from
-; the recorded index for a surviving instruction to insert after, so this test
-; pins down that currently correct output.
-;
-; Reduced from MultiSource/Benchmarks/Prolangs-C/cdecl built at -O2 -g.
-
-; CHECK-LABEL: name: yyparse
-; CHECK: DBG_LABEL !{{[0-9]+}}, debug-location !{{[0-9]+}}
-
-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 i32 @yyparse(ptr %add.ptr132, i16 %0, i16 %1, i1 %cmp.not, i1 %cmp8) !dbg !4 {
-entry:
-    #dbg_label(!7, !8)
-  br label %if.end
-
-if.then:                                          ; preds = %yystack.backedge
-  ret i32 0
-
-if.end:                                           ; preds = %yystack.backedge, %entry
-  %yystate.01028 = phi i16 [ 0, %entry ], [ %0, %yystack.backedge ]
-  store i16 %yystate.01028, ptr null, align 2
-  br i1 %cmp8, label %if.then10, label %if.end15
-
-if.then10:                                        ; preds = %if.end
-  %call = tail call i32 null()
-  br label %if.end15
-
-if.end15:                                         ; preds = %if.then10, %if.end
-  tail call void @llvm.memcpy.p0.p0.i64(ptr null, ptr %add.ptr132, i64 1, i1 false)
-  switch i16 %1, label %yystack.backedge [
-    i16 2, label %sw.bb162
-    i16 4, label %sw.bb164
-  ]
-
-yystack.backedge:                                 ; preds = %if.end15
-  br i1 %cmp.not, label %if.end, label %if.then
-
-sw.bb162:                                         ; preds = %if.end15
-  ret i32 0
-
-sw.bb164:                                         ; preds = %if.end15
-  ret i32 0
-}
-
-; Function Attrs: nocallback nofree nosync nounwind willreturn memory(argmem: readwrite)
-declare void @llvm.memcpy.p0.p0.i64(ptr noalias writeonly captures(none), ptr noalias readonly captures(none), i64, i1 immarg) #0
-
-attributes #0 = { nocallback nofree nosync nounwind willreturn memory(argmem: readwrite) }
-
-!llvm.dbg.cu = !{!0}
-!llvm.module.flags = !{!3}
-
-!0 = distinct !DICompileUnit(language: DW_LANG_C89, file: !1, producer: "clang", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, enums: !2, retainedTypes: !2, globals: !2, splitDebugInlining: false, nameTableKind: None)
-!1 = !DIFile(filename: "cdecl.c", directory: "/")
-!2 = !{}
-!3 = !{i32 2, !"Debug Info Version", i32 3}
-!4 = distinct !DISubprogram(name: "yyparse", scope: !5, file: !5, line: 1022, type: !6, scopeLine: 1022, flags: DIFlagAllCallsDescribed, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !0, retainedNodes: !2, keyInstructions: true)
-!5 = !DIFile(filename: "cdgram.y", directory: "/")
-!6 = !DISubroutineType(types: !2)
-!7 = !DILabel(scope: !4, name: "yystack", file: !5, line: 1038, column: 2)
-!8 = !DILocation(line: 1038, column: 2, scope: !4)
diff --git a/llvm/test/DebugInfo/X86/live-debug-vars-stale-slotindexes.ll b/llvm/test/DebugInfo/X86/live-debug-vars-stale-slotindexes.ll
new file mode 100644
index 00000000000000..776ac6faa27f63
--- /dev/null
+++ b/llvm/test/DebugInfo/X86/live-debug-vars-stale-slotindexes.ll
@@ -0,0 +1,141 @@
+; RUN: llc -mtriple=x86_64-unknown-linux-gnu -O2 -experimental-debug-variable-locations=true -stop-after=livedebugvalues %s -o - | FileCheck %s
+
+; LiveDebugVariables records SlotIndexes during register allocation and uses
+; them afterwards to re-insert debug instructions, but nothing tells it when an
+; instruction is erased in between, so a recorded index can be left naming an
+; instruction that no longer exists. Each function below reaches one such case.
+; The debug instructions still come out in the right place, so these tests pin
+; down that currently correct output.
+;
+; See also DebugInfo/AArch64/live-debug-vars-stale-slotindexes.ll.
+
+; The SlotIndex of a DBG_LABEL is recorded in UserLabel::loc, and loc is left
+; naming an erased instruction. insertDebugLabel goes through
+; findInsertLocation, which scans backwards from the recorded index for a
+; surviving instruction to insert after.
+;
+; Reduced from MultiSource/Benchmarks/Prolangs-C/cdecl built at -O2 -g.
+
+; CHECK-LABEL: name: yyparse
+; CHECK: DBG_LABEL !{{[0-9]+}}, debug-location !{{[0-9]+}}
+
+define i32 @yyparse(ptr %add.ptr132, i16 %arg, i16 %arg1, i1 %cmp.not, i1 %cmp8) !dbg !4 {
+entry:
+    #dbg_label(!7, !8)
+  br label %if.end
+
+if.then:                                          ; preds = %yystack.backedge
+  ret i32 0
+
+if.end:                                           ; preds = %yystack.backedge, %entry
+  %yystate.01028 = phi i16 [ 0, %entry ], [ %arg, %yystack.backedge ]
+  store i16 %yystate.01028, ptr null, align 2
+  br i1 %cmp8, label %if.then10, label %if.end15
+
+if.then10:                                        ; preds = %if.end
+  %call = tail call i32 null()
+  br label %if.end15
+
+if.end15:                                         ; preds = %if.then10, %if.end
+  tail call void @llvm.memcpy.p0.p0.i64(ptr null, ptr %add.ptr132, i64 1, i1 false)
+  switch i16 %arg1, label %yystack.backedge [
+    i16 2, label %sw.bb162
+    i16 4, label %sw.bb164
+  ]
+
+yystack.backedge:                                 ; preds = %if.end15
+  br i1 %cmp.not, label %if.end, label %if.then
+
+sw.bb162:                                         ; preds = %if.end15
+  ret i32 0
+
+sw.bb164:                                         ; preds = %if.end15
+  ret i32 0
+}
+
+; In instruction referencing mode, debug instructions are unlinked during
+; register allocation and the SlotIndex to put them back at is recorded in
+; StashedDebugInstrs. Here that index is left naming an erased instruction, and
+; emitDebugValues takes its "insert position disappeared" path, walking
+; forwards through the slots for a new one. Note that this is the opposite
+; direction to findInsertLocation, which scans backwards.
+;
+; Reduced from MultiSource/Applications/oggenc built at -O2 -g.
+
+; CHECK-LABEL: name: accumulate_fit
+; CHECK: DBG_VALUE 0, $noreg, !{{[0-9]+}}, !DIExpression(), debug-location !{{[0-9]+}}
+
+define fastcc i32 @accumulate_fit(ptr %flr, ptr %mdct, i32 %x0, i32 %x1, ptr %a, i32 %n, ptr %info, i64 %i.0141) !dbg !13 {
+entry:
+    #dbg_value(i64 0, !16, !DIExpression(), !18)
+  %conv = sext i32 %x0 to i64
+  br label %for.body
+
+for.body:                                         ; preds = %if.end37, %entry
+  %y2b.0151 = phi i64 [ 0, %entry ], [ %y2b.1, %if.end37 ]
+  %x2b.0150 = phi i64 [ 0, %entry ], [ %x2b.1, %if.end37 ]
+  %yb.0149 = phi i64 [ 0, %entry ], [ %yb.1, %if.end37 ]
+  %xb.0148 = phi i64 [ 0, %entry ], [ %xb.1, %if.end37 ]
+  %na.0147 = phi i64 [ 0, %entry ], [ %na.1, %if.end37 ]
+  %xya.0146 = phi i64 [ 0, %entry ], [ %xya.1, %if.end37 ]
+  %y2a.0145 = phi i64 [ 0, %entry ], [ %y2a.1, %if.end37 ]
+  %x2a.0144 = phi i64 [ 0, %entry ], [ %x2a.1, %if.end37 ]
+  %i.01412 = phi i64 [ %conv, %entry ], [ 0, %if.end37 ]
+  %add.ptr = getelementptr [4 x i8], ptr %flr, i64 %i.01412
+  %i = load float, ptr %add.ptr, align 4
+  %conv.i = fptosi float %i to i32
+  %arrayidx = getelementptr [4 x i8], ptr %mdct, i64 %i.01412
+  %i1 = load float, ptr %arrayidx, align 4
+  %i2 = load float, ptr %info, align 4
+  %add = fadd float %i1, %i2
+  %i3 = tail call i32 @llvm.umin.i32(i32 %conv.i, i32 1)
+  %mul273 = mul i64 %i.0141, %i.0141
+  %cmp11 = fcmp ult float %add, 0.000000e+00
+  br i1 %cmp11, label %if.else, label %if.then13
+
+if.then13:                                        ; preds = %for.body
+  %add17 = or i64 %x2a.0144, %mul273
+  %add20 = or i64 %y2a.0145, 1
+  %add23 = or i64 1, %xya.0146
+  %inc = or i64 %na.0147, 1
+  br label %if.end37
+
+if.else:                                          ; preds = %for.body
+  %add24 = or i64 %xb.0148, %i.0141
+  %conv25 = zext i32 %i3 to i64
+  %add26 = or i64 %yb.0149, %conv25
+  %add28 = or i64 %x2b.0150, 1
+  %add31 = or i64 %y2b.0151, %i.0141
+  br label %if.end37
+
+if.end37:                                         ; preds = %if.else, %if.then13
+  %x2a.1 = phi i64 [ %add17, %if.then13 ], [ %x2a.0144, %if.else ]
+  %y2a.1 = phi i64 [ %add20, %if.then13 ], [ %y2a.0145, %if.else ]
+  %xya.1 = phi i64 [ %add23, %if.then13 ], [ %xya.0146, %if.else ]
+  %na.1 = phi i64 [ %inc, %if.then13 ], [ %na.0147, %if.else ]
+  %xb.1 = phi i64 [ %xb.0148, %if.then13 ], [ %add24, %if.else ]
+  %yb.1 = phi i64 [ %yb.0149, %if.then13 ], [ %add26, %if.else ]
+  %x2b.1 = phi i64 [ %x2b.0150, %if.then13 ], [ %add28, %if.else ]
+  %y2b.1 = phi i64 [ %y2b.0151, %if.then13 ], [ %add31, %if.else ]
+  br label %for.body
+}
+
+!llvm.dbg.cu = !{!0, !9}
+!llvm.module.flags = !{!3}
+!0 = distinct !DICompileUnit(language: DW_LANG_C89, file: !1, producer: "clang", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, enums: !2, retainedTypes: !2, globals: !2, splitDebugInlining: false, nameTableKind: None)
+!1 = !DIFile(filename: "cdecl.c", directory: "/")
+!2 = !{}
+!3 = !{i32 2, !"Debug Info Version", i32 3}
+!4 = distinct !DISubprogram(name: "yyparse", scope: !5, file: !5, line: 1022, type: !6, scopeLine: 1022, flags: DIFlagAllCallsDescribed, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !0, retainedNodes: !2, keyInstructions: true)
+!5 = !DIFile(filename: "cdgram.y", directory: "/")
+!6 = !DISubroutineType(types: !2)
+!7 = !DILabel(scope: !4, name: "yystack", file: !5, line: 1038, column: 2)
+!8 = !DILocation(line: 1038, column: 2, scope: !4)
+!9 = distinct !DICompileUnit(language: DW_LANG_C11, file: !10, producer: "clang", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, splitDebugInlining: false, nameTableKind: None)
+!10 = !DIFile(filename: "oggenc.c", directory: "/")
+!13 = distinct !DISubprogram(name: "accumulate_fit", scope: !10, file: !10, line: 1, type: !15, scopeLine: 1, flags: DIFlagPrototyped | DIFlagAllCallsDescribed, spFlags: DISPFlagLocalToUnit | DISPFlagDefinition | DISPFlagOptimized, unit: !9)
+!15 = distinct !DISubroutineType(types: !11)
+!11 = !{}
+!16 = !DILocalVariable(name: "xa", scope: !13, file: !10, line: 2, type: !17)
+!17 = !DIBasicType(name: "long", size: 64, encoding: DW_ATE_signed)
+!18 = !DILocation(line: 0, scope: !13)
diff --git a/llvm/test/DebugInfo/X86/live-debug-vars-stashed-instr.ll b/llvm/test/DebugInfo/X86/live-debug-vars-stashed-instr.ll
deleted file mode 100644
index 93371f34aaeab5..00000000000000
--- a/llvm/test/DebugInfo/X86/live-debug-vars-stashed-instr.ll
+++ /dev/null
@@ -1,84 +0,0 @@
-; RUN: llc -mtriple=x86_64-unknown-linux-gnu -O2 -experimental-debug-variable-locations=true -stop-after=livedebugvalues %s -o - | FileCheck %s
-
-; In instruction referencing mode LiveDebugVariables unlinks debug instructions
-; during register allocation and records the SlotIndex to put them back at, in
-; StashedDebugInstrs. Nothing tells it when the instruction at that index is
-; erased in between, so here the recorded index is left naming one that has
-; been erased, and emitDebugValues takes its "insert position disappeared"
-; path, walking forwards through the slots for a new one. Note that this is
-; the opposite direction to findInsertLocation, which scans backwards.
-;
-; Reduced from MultiSource/Applications/oggenc built at -O2 -g.
-
-; CHECK-LABEL: name: accumulate_fit
-; CHECK: DBG_VALUE 0, $noreg, ![[VAR:[0-9]+]], !DIExpression(), debug-location ![[LOC:[0-9]+]]
-
-define fastcc i32 @accumulate_fit(ptr %flr, ptr %mdct, i32 %x0, i32 %x1, ptr %a, i32 %n, ptr %info, i64 %i.0141) !dbg !4 {
-entry:
-    #dbg_value(i64 0, !7, !DIExpression(), !9)
-  %conv = sext i32 %x0 to i64
-  br label %for.body
-
-for.body:                                         ; preds = %if.end37, %entry
-  %y2b.0151 = phi i64 [ 0, %entry ], [ %y2b.1, %if.end37 ]
-  %x2b.0150 = phi i64 [ 0, %entry ], [ %x2b.1, %if.end37 ]
-  %yb.0149 = phi i64 [ 0, %entry ], [ %yb.1, %if.end37 ]
-  %xb.0148 = phi i64 [ 0, %entry ], [ %xb.1, %if.end37 ]
-  %na.0147 = phi i64 [ 0, %entry ], [ %na.1, %if.end37 ]
-  %xya.0146 = phi i64 [ 0, %entry ], [ %xya.1, %if.end37 ]
-  %y2a.0145 = phi i64 [ 0, %entry ], [ %y2a.1, %if.end37 ]
-  %x2a.0144 = phi i64 [ 0, %entry ], [ %x2a.1, %if.end37 ]
-  %i.01412 = phi i64 [ %conv, %entry ], [ 0, %if.end37 ]
-  %add.ptr = getelementptr [4 x i8], ptr %flr, i64 %i.01412
-  %0 = load float, ptr %add.ptr, align 4
-  %conv.i = fptosi float %0 to i32
-  %arrayidx = getelementptr [4 x i8], ptr %mdct, i64 %i.01412
-  %1 = load float, ptr %arrayidx, align 4
-  %2 = load float, ptr %info, align 4
-  %add = fadd float %1, %2
-  %3 = tail call i32 @llvm.umin.i32(i32 %conv.i, i32 1)
-  %mul273 = mul i64 %i.0141, %i.0141
-  %cmp11 = fcmp ult float %add, 0.000000e+00
-  br i1 %cmp11, label %if.else, label %if.then13
-
-if.then13:                                        ; preds = %for.body
-  %add17 = or i64 %x2a.0144, %mul273
-  %add20 = or i64 %y2a.0145, 1
-  %add23 = or i64 1, %xya.0146
-  %inc = or i64 %na.0147, 1
-  br label %if.end37
-
-if.else:                                          ; preds = %for.body
-  %add24 = or i64 %xb.0148, %i.0141
-  %conv25 = zext i32 %3 to i64
-  %add26 = or i64 %yb.0149, %conv25
-  %add28 = or i64 %x2b.0150, 1
-  %add31 = or i64 %y2b.0151, %i.0141
-  br label %if.end37
-
-if.end37:                                         ; preds = %if.else, %if.then13
-  %x2a.1 = phi i64 [ %add17, %if.then13 ], [ %x2a.0144, %if.else ]
-  %y2a.1 = phi i64 [ %add20, %if.then13 ], [ %y2a.0145, %if.else ]
-  %xya.1 = phi i64 [ %add23, %if.then13 ], [ %xya.0146, %if.else ]
-  %na.1 = phi i64 [ %inc, %if.then13 ], [ %na.0147, %if.else ]
-  %xb.1 = phi i64 [ %xb.0148, %if.then13 ], [ %add24, %if.else ]
-  %yb.1 = phi i64 [ %yb.0149, %if.then13 ], [ %add26, %if.else ]
-  %x2b.1 = phi i64 [ %x2b.0150, %if.then13 ], [ %add28, %if.else ]
-  %y2b.1 = phi i64 [ %y2b.0151, %if.then13 ], [ %add31, %if.else ]
-  br label %for.body
-}
-
-declare i32 @llvm.umin.i32(i32, i32)
-
-!llvm.dbg.cu = !{!0}
-!llvm.module.flags = !{!3}
-
-!0 = distinct !DICompileUnit(language: DW_LANG_C11, file: !1, producer: "clang", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, splitDebugInlining: false, nameTableKind: None)
-!1 = !DIFile(filename: "oggenc.c", directory: "/")
-!3 = !{i32 2, !"Debug Info Version", i32 3}
-!4 = distinct !DISubprogram(name: "accumulate_fit", scope: !1, file: !1, line: 1, type: !6, scopeLine: 1, flags: DIFlagPrototyped | DIFlagAllCallsDescribed, spFlags: DISPFlagLocalToUnit | DISPFlagDefinition | DISPFlagOptimized, unit: !0)
-!6 = distinct !DISubroutineType(types: !2)
-!2 = !{}
-!7 = !DILocalVariable(name: "xa", scope: !4, file: !1, line: 2, type: !8)
-!8 = !DIBasicType(name: "long", size: 64, encoding: DW_ATE_signed)
-!9 = !DILocation(line: 0, scope: !4)



More information about the llvm-commits mailing list