diff --git a/llvm/test/CodeGen/X86/dbg-value-superreg-copy2.mir b/llvm/test/CodeGen/X86/dbg-value-superreg-copy2.mir new file mode 100644 --- /dev/null +++ b/llvm/test/CodeGen/X86/dbg-value-superreg-copy2.mir @@ -0,0 +1,67 @@ +# RUN: llc -O1 -start-after simple-register-coalescing -o - %s -experimental-debug-variable-locations=true | FileCheck %s + +--- | + target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" + target triple = "x86_64-pc-linux-gnu" + + define i16 @foo(i8 %zzz) !dbg !4 { + entry: + ret i16 1 + } + + ; Function Attrs: nounwind readnone speculatable + declare void @llvm.dbg.value(metadata, metadata, metadata) + + !llvm.dbg.cu = !{!0} + !llvm.module.flags = !{!3} + + !0 = distinct !DICompileUnit(language: DW_LANG_C99, file: !1, producer: "clang", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, enums: !2, retainedTypes: !2) + !1 = !DIFile(filename: "test.c", directory: "") + !2 = !{} + !3 = !{i32 1, !"Debug Info Version", i32 3} + !4 = distinct !DISubprogram(name: "foo", scope: !1, file: !1, line: 3, type: !5, isLocal: false, isDefinition: true, scopeLine: 3, virtualIndex: 6, flags: DIFlagPrototyped, isOptimized: false, unit: !0) + !5 = !DISubroutineType(types: !6) + !6 = !{null} + !7 = !DILocalVariable(name: "zzz", arg: 1, scope: !4, file: !1, line: 3, type: !8) + !8 = !DIBasicType(name: "char", size: 8, align: 8, encoding: DW_ATE_signed) + !9 = !DILocation(line: 0, scope: !4) + !10 = !DILocation(line: 4, column: 22, scope: !11) + !11 = distinct !DILexicalBlock(scope: !4, file: !1, line: 3, column: 19) + +... +--- +name: foo +tracksRegLiveness: true +debugValueSubstitutions: + - { srcinst: 2, srcop: 0, dstinst: 1, dstop: 0, subreg: 2 } +body: | + bb.0: + %0:gr16_abcd = MOV16ri 1, debug-instr-number 1, debug-location !9 + + bb.1: + DBG_INSTR_REF 2, 0, !7, !DIExpression(), debug-location !9 + %1:gr16 = COPY %0, debug-location !9 + %2:gr16 = COPY %0 + + bb.2: + $ax = COPY %1, debug-location !9 + $dx = COPY %2 + RET64 killed $ax, killed $dx, debug-location !9 +... + +# This test is an instruction-referencing flavour of the +# dbg-value-superreg-copy.mir test. Over there, we ran into difficulties where +# register coalescing would transform DBG_VALUEs of subregisters such as: +# +# DBG_VALUE %0.sub_8bit_hi, $noreg, +# +# Into references to larger registers, potentially with the wrong offset. We +# can't refer to vregs in instruction referencing mode, so this test replicates +# the same scenario in a new test. The defining storing load gets an instruction +# number, and we encode which subregister we want through a substitution. Check +# that it comes out the other end of regalloc through coalescing still in a +# high register. +# +# CHECK-NOT: #DEBUG_VALUE: +# CHECK: #DEBUG_VALUE: foo:zzz <- ${{[abcd]+}}h +# CHECK-NOT: #DEBUG_VALUE: diff --git a/llvm/test/DebugInfo/X86/dbg-value-arg-movement.ll b/llvm/test/DebugInfo/X86/dbg-value-arg-movement.ll --- a/llvm/test/DebugInfo/X86/dbg-value-arg-movement.ll +++ b/llvm/test/DebugInfo/X86/dbg-value-arg-movement.ll @@ -1,4 +1,5 @@ -; RUN: llc -mtriple=x86_64-unknown-unknown -start-after=codegenprepare -stop-before=finalize-isel %s -o - -experimental-debug-variable-locations=false | FileCheck %s +; RUN: llc -mtriple=x86_64-unknown-unknown -start-after=codegenprepare -stop-before=finalize-isel %s -o - -experimental-debug-variable-locations=false | FileCheck %s --check-prefixes=COMMON,CHECK +; RUN: llc -mtriple=x86_64-unknown-unknown -start-after=codegenprepare -stop-before=finalize-isel %s -o - -experimental-debug-variable-locations=true | FileCheck %s --check-prefixes=COMMON,INSTRREF ; Test the movement of dbg.values of arguments. SelectionDAG tries to be ; helpful and places DBG_VALUEs of Arguments at the start of functions. @@ -10,6 +11,9 @@ ; function. In the test below, 'xyzzy' is a parameter to an inlined function, ; but should not be hoisted to the start of the function. ; +; With instruction referencing, accuracy becomes more important than coverage, +; so debug instructions are placed wherever they were in the IR. +; ; Original test case, in which 'xyzzy' became unavailable because its DBG_VALUE ; landed far from any uses, compiled "clang -O2 -g" with inlining, ; @@ -39,8 +43,8 @@ ; return qux; ; } -; CHECK: [[BAZVAR:![0-9]+]] = !DILocalVariable(name: "baz", -; CHECK: [[XYZVAR:![0-9]+]] = !DILocalVariable(name: "xyzzy", +; COMMON: [[BAZVAR:![0-9]+]] = !DILocalVariable(name: "baz", +; COMMON: [[XYZVAR:![0-9]+]] = !DILocalVariable(name: "xyzzy", ; Start of MIR function block, ; CHECK-LABEL: body @@ -53,6 +57,12 @@ ; Correctly place dbg.value in the 'next' block. ; CHECK: DBG_VALUE [[ARGREG]], $noreg, [[XYZVAR]] +; INSTRREF-LABEL: body +; INSTRREF: DBG_PHI $edi, 1 +; INSTRREF: DBG_VALUE $edi, $noreg, [[BAZVAR]] +; INSTRREF-LABEL: bb.1.next +; INSTRREF: DBG_INSTR_REF 1, 0, [[XYZVAR]], + target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" target triple = "x86_64-unknown-linux-gnu" diff --git a/llvm/test/DebugInfo/X86/dbg-value-funcarg.ll b/llvm/test/DebugInfo/X86/dbg-value-funcarg.ll --- a/llvm/test/DebugInfo/X86/dbg-value-funcarg.ll +++ b/llvm/test/DebugInfo/X86/dbg-value-funcarg.ll @@ -1,4 +1,5 @@ -; RUN: llc -mtriple=x86_64-unknown-linux-gnu -start-after=codegenprepare -stop-before=finalize-isel -o - %s -experimental-debug-variable-locations=false | FileCheck %s +; RUN: llc -mtriple=x86_64-unknown-linux-gnu -start-after=codegenprepare -stop-before=finalize-isel -o - %s -experimental-debug-variable-locations=false | FileCheck %s --check-prefixes=COMMON,CHECK +; RUN: llc -mtriple=x86_64-unknown-linux-gnu -start-after=codegenprepare -stop-before=finalize-isel -o - %s -experimental-debug-variable-locations=true | FileCheck %s --check-prefixes=COMMON,INSTRREF ; Input to this test looked like this and was compiled using: clang -g -O1 -mllvm -stop-after=codegenprepare -S ; @@ -31,12 +32,12 @@ ; Catch metadata references for involved variables. ; -; CHECK-DAG: ![[T1A:.*]] = !DILocalVariable(name: "t1a" -; CHECK-DAG: ![[LOCAL:.*]] = !DILocalVariable(name: "local" -; CHECK-DAG: ![[T2A:.*]] = !DILocalVariable(name: "t2a" -; CHECK-DAG: ![[T2B:.*]] = !DILocalVariable(name: "t2b" -; CHECK-DAG: ![[T3A:.*]] = !DILocalVariable(name: "t3a" -; CHECK-DAG: ![[TMP:.*]] = !DILocalVariable(name: "tmp" +; COMMON-DAG: ![[T1A:.*]] = !DILocalVariable(name: "t1a" +; COMMON-DAG: ![[LOCAL:.*]] = !DILocalVariable(name: "local" +; COMMON-DAG: ![[T2A:.*]] = !DILocalVariable(name: "t2a" +; COMMON-DAG: ![[T2B:.*]] = !DILocalVariable(name: "t2b" +; COMMON-DAG: ![[T3A:.*]] = !DILocalVariable(name: "t3a" +; COMMON-DAG: ![[TMP:.*]] = !DILocalVariable(name: "tmp" define dso_local void @foo_local(i32 %t1a) local_unnamed_addr #0 !dbg !7 { @@ -52,6 +53,18 @@ ; CHECK: DBG_VALUE $edi, $noreg, ![[T1A]], !DIExpression(), ; CHECK-NOT: DBG_VALUE ; CHECK: TCRETURNdi64 @bar, +; INSTRREF-LABEL: name: foo_local +; INSTRREF-NOT: DBG_ +; INSTRREF: DBG_PHI $edi, 1 +; INSTRREF: DBG_VALUE $edi, $noreg, ![[T1A]], !DIExpression(), +; INSTRREF-NEXT: %0:gr32 = COPY $edi +; INSTRREF-NEXT: DBG_VALUE 123, $noreg, ![[LOCAL]], !DIExpression(), +; INSTRREF: CALL64pcrel32 @bar, +; INSTRREF-NEXT: ADJCALLSTACKUP64 +; INSTRREF: DBG_INSTR_REF 1, 0, ![[LOCAL]], !DIExpression(), +; INSTRREF-NOT: DBG_ +; INSTRREF: TCRETURNdi64 @bar, + entry: call void @llvm.dbg.value(metadata i32 %t1a, metadata !12, metadata !DIExpression()), !dbg !14 call void @llvm.dbg.value(metadata i32 123, metadata !13, metadata !DIExpression()), !dbg !15 @@ -76,6 +89,15 @@ ; CHECK: DBG_VALUE %0, $noreg, ![[T2B]], !DIExpression(), ; CHECK: DBG_VALUE $edi, $noreg, ![[T2A]], !DIExpression(), ; CHECK: TCRETURNdi64 @bar, +; INSTRREF-LABEL: name: foo_other_param +; INSTRREF: DBG_PHI $edi, 1 +; INSTRREF: DBG_VALUE $edi, $noreg, ![[T2A]], !DIExpression(), +; INSTRREF: DBG_VALUE $esi, $noreg, ![[T2B]], !DIExpression(), +; INSTRREF: CALL64pcrel32 @bar, +; INSTRREF: DBG_VALUE 123, $noreg, ![[T2B]], !DIExpression(), +; INSTRREF: CALL64pcrel32 @bar, +; INSTRREF: DBG_INSTR_REF 1, 0, ![[T2B]], !DIExpression(), +; INSTRREF: TCRETURNdi64 @bar, entry: call void @llvm.dbg.value(metadata i32 %t2a, metadata !23, metadata !DIExpression()), !dbg !25 @@ -99,6 +121,16 @@ ; CHECK: CALL64pcrel32 @bar, ; CHECK: DBG_VALUE %0, $noreg, ![[T3A]], !DIExpression(), ; CHECK: TCRETURNdi64 @bar, +; INSTRREF-LABEL: name: foo_same_param +; INSTRREF: DBG_PHI $edi, 2 +; INSTRREF: DBG_PHI $edi, 1 +; INSTRREF: DBG_VALUE $edi, $noreg, ![[T3A]], !DIExpression(), +; INSTRREF: CALL64pcrel32 @bar, +; INSTRREF: DBG_INSTR_REF 1, 0, ![[TMP]], !DIExpression(), +; INSTRREF: DBG_VALUE 123, $noreg, ![[T3A]], !DIExpression(), +; INSTRREF: CALL64pcrel32 @bar, +; INSTRREF: DBG_INSTR_REF 2, 0, ![[T3A]], !DIExpression(), +; INSTRREF: TCRETURNdi64 @bar, entry: call void @llvm.dbg.value(metadata i32 %t3a, metadata !33, metadata !DIExpression()), !dbg !35 tail call void @bar(i32 %t3a) #3, !dbg !36 diff --git a/llvm/test/DebugInfo/X86/dbg-value-funcarg2.ll b/llvm/test/DebugInfo/X86/dbg-value-funcarg2.ll --- a/llvm/test/DebugInfo/X86/dbg-value-funcarg2.ll +++ b/llvm/test/DebugInfo/X86/dbg-value-funcarg2.ll @@ -1,4 +1,5 @@ -; RUN: llc -mtriple=x86_64-unknown-linux-gnu -start-after=codegenprepare -stop-before=finalize-isel -o - %s -experimental-debug-variable-locations=false | FileCheck %s +; RUN: llc -mtriple=x86_64-unknown-linux-gnu -start-after=codegenprepare -stop-before=finalize-isel -o - %s -experimental-debug-variable-locations=false | FileCheck %s --check-prefixes=CHECK,COMMON +; RUN: llc -mtriple=x86_64-unknown-linux-gnu -start-after=codegenprepare -stop-before=finalize-isel -o - %s -experimental-debug-variable-locations=true | FileCheck %s --check-prefixes=INSTRREF,COMMON ; Test case was generated from the following C code, ; using: clang -g -O1 -S -emit-llvm s.c -o s.ll @@ -17,18 +18,21 @@ ; Catch metadata references for involved variables. ; -; CHECK-DAG: ![[S1:.*]] = !DILocalVariable(name: "s1" -; CHECK-DAG: ![[S2:.*]] = !DILocalVariable(name: "s2" +; COMMON-DAG: ![[S1:.*]] = !DILocalVariable(name: "s1" +; COMMON-DAG: ![[S2:.*]] = !DILocalVariable(name: "s2" define dso_local i32 @f(i64 %s1.coerce0, i64 %s1.coerce1, i64 %s2.coerce0, i64 %s2.coerce1) local_unnamed_addr #0 !dbg !7 { ; We expect DBG_VALUE instructions for the arguments at the entry. -; CHECK-LABEL: name: f -; CHECK-NOT: DBG_VALUE -; CHECK-DAG: DBG_VALUE $rdi, $noreg, ![[S1]], !DIExpression(DW_OP_LLVM_fragment, 0, 64) -; CHECK-DAG: DBG_VALUE $rsi, $noreg, ![[S1]], !DIExpression(DW_OP_LLVM_fragment, 64, 64) -; CHECK-DAG: DBG_VALUE $rdx, $noreg, ![[S2]], !DIExpression(DW_OP_LLVM_fragment, 0, 64) -; CHECK-DAG: DBG_VALUE $rcx, $noreg, ![[S2]], !DIExpression(DW_OP_LLVM_fragment, 64, 64) -; CHECK-NOT: DBG_VALUE +; In instr-ref mode, there'll be some DBG_PHIs in there too. +; COMMON-LABEL: name: f +; COMMON-NOT: DBG_VALUE +; INSTRREF-DAG: DBG_PHI $rcx, 2 +; INSTRREF-DAG: DBG_PHI $rdx, 1 +; COMMON-DAG: DBG_VALUE $rdi, $noreg, ![[S1]], !DIExpression(DW_OP_LLVM_fragment, 0, 64) +; COMMON-DAG: DBG_VALUE $rsi, $noreg, ![[S1]], !DIExpression(DW_OP_LLVM_fragment, 64, 64) +; COMMON-DAG: DBG_VALUE $rdx, $noreg, ![[S2]], !DIExpression(DW_OP_LLVM_fragment, 0, 64) +; COMMON-DAG: DBG_VALUE $rcx, $noreg, ![[S2]], !DIExpression(DW_OP_LLVM_fragment, 64, 64) +; COMMON-NOT: DBG_ ; Then arguments are copied to virtual registers. ; CHECK-NOT: DBG_VALUE @@ -43,8 +47,8 @@ ; CHECK-NOT: DBG_VALUE ; We have the call to bar. -; CHECK: ADJCALLSTACKDOWN -; CHECK: CALL64pcrel32 @bar +; COMMON: ADJCALLSTACKDOWN +; COMMON: CALL64pcrel32 @bar ; After the call we expect to find new DBG_VALUE instructions for "s1". ; CHECK: ADJCALLSTACKUP @@ -52,9 +56,16 @@ ; CHECK-DAG: DBG_VALUE %[[R2]], $noreg, ![[S1]], !DIExpression(DW_OP_LLVM_fragment, 0, 64) ; CHECK-DAG: DBG_VALUE %[[R1]], $noreg, ![[S1]], !DIExpression(DW_OP_LLVM_fragment, 64, 64) -; And then no more DBG_VALUE instructions before the add. -; CHECK-NOT: DBG_VALUE -; CHECK: ADD32rr +;; In instruction referencing mode, we should refer to the instruction number +;; of the earlier DBG_PHIs. +; INSTRREF: ADJCALLSTACKUP +; INSTRREF-NOT: DBG_ +; INSTRREF-DAG: DBG_INSTR_REF 1, 0, ![[S1]], !DIExpression(DW_OP_LLVM_fragment, 0, 64) +; INSTRREF-DAG: DBG_INSTR_REF 2, 0, ![[S1]], !DIExpression(DW_OP_LLVM_fragment, 64, 64) + +; And then no more DBG_ instructions before the add. +; COMMON-NOT: DBG_ +; COMMON: ADD32rr entry: %tmp.sroa.0 = alloca i64, align 8 diff --git a/llvm/test/DebugInfo/X86/dbg-value-funcarg3.ll b/llvm/test/DebugInfo/X86/dbg-value-funcarg3.ll --- a/llvm/test/DebugInfo/X86/dbg-value-funcarg3.ll +++ b/llvm/test/DebugInfo/X86/dbg-value-funcarg3.ll @@ -1,4 +1,5 @@ ; RUN: llc -mtriple=x86_64-unknown-linux-gnu -start-after=codegenprepare -stop-before=finalize-isel -o - %s -experimental-debug-variable-locations=false | FileCheck %s +; RUN: llc -mtriple=x86_64-unknown-linux-gnu -start-after=codegenprepare -stop-before=finalize-isel -o - %s -experimental-debug-variable-locations=true | FileCheck %s --check-prefixes=INSTRREF ; Input to this test looked like this and was compiled using: clang -g -O1 -mllvm -stop-after=codegenprepare -S ; @@ -10,6 +11,7 @@ ; Catch metadata references for involved variables. ; ; CHECK-DAG: ![[T1:.*]] = !DILocalVariable(name: "t1" +; INSTRREF-DAG: ![[T1:.*]] = !DILocalVariable(name: "t1" define dso_local i32 @fn1(i64 %t1) local_unnamed_addr #0 !dbg !7 { @@ -23,6 +25,17 @@ ; CHECK-NEXT: %1:gr32 = COPY %0.sub_32bit ; CHECK-NEXT: COPY ; CHECK-NEXT: RET +; +;; For instr-ref, no copies should be considered. Because argumenst are +;; Special, we don't label them in the same way, and currently emit a +;; DBG_VALUE for the physreg. +; INSTRREF-LABEL: name: fn1 +; INSTRREF: DBG_VALUE $rdi, $noreg, ![[T1]], !DIExpression(), +; INSTRREF-NEXT: %0:gr64 = COPY $rdi +; INSTRREF-NEXT: %1:gr32 = COPY %0.sub_32bit +; INSTRREF-NEXT: COPY +; INSTRREF-NEXT: RET + entry: call void @llvm.dbg.value(metadata i64 %t1, metadata !13, metadata !DIExpression()), !dbg !14 %0 = trunc i64 %t1 to i32, !dbg !15