diff --git a/llvm/lib/CodeGen/LiveDebugValues/InstrRefBasedImpl.cpp b/llvm/lib/CodeGen/LiveDebugValues/InstrRefBasedImpl.cpp --- a/llvm/lib/CodeGen/LiveDebugValues/InstrRefBasedImpl.cpp +++ b/llvm/lib/CodeGen/LiveDebugValues/InstrRefBasedImpl.cpp @@ -3716,7 +3716,12 @@ unsigned BlockNo = Num.getBlock(); LocIdx LocNo = Num.getLoc(); - Num = MInLocs[BlockNo][LocNo.asU64()]; + ValueIDNum ResolvedValue = MInLocs[BlockNo][LocNo.asU64()]; + // If there is no resolved value for this live-in then it is not directly + // reachable from the entry block -- model it as a PHI on entry to this + // block, which means we leave the ValueIDNum unchanged. + if (ResolvedValue != ValueIDNum::EmptyValue) + Num = ResolvedValue; } // Later, we'll be looking up ranges of instruction numbers. llvm::sort(DebugPHINumToValue); diff --git a/llvm/test/DebugInfo/X86/instr-ref-unreachable.mir b/llvm/test/DebugInfo/X86/instr-ref-unreachable.mir new file mode 100644 --- /dev/null +++ b/llvm/test/DebugInfo/X86/instr-ref-unreachable.mir @@ -0,0 +1,110 @@ +# RUN: llc --run-pass=livedebugvalues %s -o - -experimental-debug-variable-locations | FileCheck %s + +## Tests that when a block that is not directly reachable from the entry block +## contains a DBG_PHI, we treat those DBG_PHIs as referring to live-in values, +## and resolve them for users as normal. +## FIXME: "def" currently does not have a value due to blocks that are not +## directly reachable from the entry block not being fully covered by the +## LiveDebugValues analysis. + +# CHECK-DAG: ![[UNDEFVAR:[0-9]+]] = !DILocalVariable(name: "undef" +# CHECK-DAG: ![[DEFVAR:[0-9]+]] = !DILocalVariable(name: "def" + +# CHECK-LABEL: bb.1.bb1 +# CHECK: DBG_VALUE_LIST ![[UNDEFVAR]], {{.+}}, $noreg +# CHECK-LABEL: bb.4.bb3 +# CHECK: DBG_VALUE_LIST ![[DEFVAR]], {{.+}}, $noreg + +--- | + ; ModuleID = 'llvm/test/DebugInfo/X86/instr-ref-unreachable.mir' + source_filename = "/tmp/b.ll" + target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128" + target triple = "x86_64-unknown-linux-gnu" + + @global = private constant [2 x ptr] [ptr blockaddress(@foo, %bb3), ptr blockaddress(@foo, %bb1)] + + define ptr @foo() !dbg !4 { + bb: + br label %bb3 + + bb1: ; preds = %bb3 + call void @llvm.dbg.value(metadata i64 %phi, metadata !6, metadata !DIExpression()), !dbg !8 + call void @llvm.dbg.value(metadata i64 %phi, metadata !9, metadata !DIExpression()), !dbg !8 + store i32 0, ptr null, align 4, !dbg !10 + %getelementptr = getelementptr i32, ptr null, i64 %phi + store i32 0, ptr %getelementptr, align 4 + br label %bb2 + + bb2: ; preds = %bb2, %bb1 + %select = select i1 false, i1 false, i1 false + br i1 %select, label %bb3, label %bb2 + + bb3: ; preds = %bb2, %bb + %phi = phi i64 [ 1, %bb ], [ 0, %bb2 ] + br label %bb1 + } + + declare void @llvm.dbg.value(metadata, metadata, metadata) + + !llvm.dbg.cu = !{!0} + !llvm.module.flags = !{!3} + + !0 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus_14, file: !1, isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, enums: !2, retainedTypes: !2, globals: !2, imports: !2, splitDebugInlining: false, nameTableKind: GNU) + !1 = !DIFile(filename: "test.cpp", directory: ".") + !2 = !{} + !3 = !{i32 2, !"Debug Info Version", i32 3} + !4 = distinct !DISubprogram(name: "GetNumericFormat", linkageName: "f", scope: null, file: !1, line: 980, type: !5, scopeLine: 984, flags: DIFlagPrototyped | DIFlagAllCallsDescribed, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !0, retainedNodes: !2) + !5 = distinct !DISubroutineType(types: !2) + !6 = !DILocalVariable(name: "undef", scope: !4, file: !1, line: 263, type: !7) + !7 = !DIBasicType(name: "unsigned long", size: 64, encoding: DW_ATE_unsigned) + !8 = !DILocation(line: 0, scope: !4) + !9 = !DILocalVariable(name: "def", scope: !4, file: !1, line: 263, type: !7) + !10 = !DILocation(line: 151, column: 41, scope: !4) + +... +--- +name: foo +alignment: 16 +tracksRegLiveness: true +debugInstrRef: true +tracksDebugUserValues: true +frameInfo: + maxAlignment: 1 +body: | + bb.0.bb: + successors: %bb.1(0x80000000) + + $ecx = MOV32ri 1, implicit-def $rcx + renamable $al = MOV8ri 1 + + bb.1.bb1 (ir-block-address-taken %ir-block.bb1, align 16): + successors: %bb.2(0x80000000) + liveins: $al, $rcx + + DBG_INSTR_REF !6, !DIExpression(DW_OP_LLVM_arg, 0), dbg-instr-ref(1, 0), debug-location !8 + MOV32mi $noreg, 1, $noreg, 0, $noreg, 0, debug-location !10 :: (store (s32) into `ptr null`) + MOV32mi $noreg, 4, killed renamable $rcx, 0, $noreg, 0 :: (store (s32) into %ir.getelementptr) + + bb.2.bb2 (align 16): + successors: %bb.3(0x04000000), %bb.2(0x7c000000) + liveins: $al + + TEST8rr renamable $al, renamable $al, implicit-def $eflags + JCC_1 %bb.2, 5, implicit killed $eflags + + bb.3: + successors: %bb.1(0x80000000) + liveins: $al + + renamable $ecx = XOR32rr undef $ecx, undef $ecx, implicit-def dead $eflags, implicit-def $rcx + JMP_1 %bb.1 + + bb.4.bb3 (ir-block-address-taken %ir-block.bb3): + successors: %bb.1(0x80000000) + liveins: $al, $rcx + + DBG_PHI $rcx, 1 + DBG_INSTR_REF !9, !DIExpression(DW_OP_LLVM_arg, 0), dbg-instr-ref(1, 0), debug-location !8 + JMP_1 %bb.1 + +...