| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,218 @@ | ||
| ; RUN: llc %s -stop-before finalize-isel -o - \ | ||
| ; RUN: -experimental-assignment-tracking \ | ||
| ; RUN: -experimental-debug-variable-locations=false \ | ||
| ; RUN: | FileCheck %s --check-prefixes=CHECK,DBGVALUE | ||
| ; RUN: llc %s -stop-before finalize-isel -o - \ | ||
| ; RUN: -experimental-assignment-tracking \ | ||
| ; RUN: -experimental-debug-variable-locations=true \ | ||
| ; RUN: | FileCheck %s --check-prefixes=CHECK,INSTRREF | ||
|
|
||
| ;-------------------------------------------------------------------- | ||
| ; Adapted from sdag-dangling-dbgvalue.ll to test dbg.assign intrinsics. This | ||
| ; ensures that dbg.assigns with no linked store are treated as dbg.values. For | ||
| ; ease of writing, all the dbg.assign intrinsics refer to the same DIAssignID | ||
| ; !54. There is no linked store in any case. | ||
| ; | ||
| ; This test case is basically generated from the following C code. | ||
| ; Compiled with "--target=x86_64-apple-darwin -S -g -O3" to get debug | ||
| ; info for optimized code. | ||
| ; | ||
| ; struct SS { | ||
| ; int a; | ||
| ; int b; | ||
| ; } S = { .a = 23, .b = -17 }; | ||
| ; | ||
| ; int test1() { | ||
| ; struct SS* foo1 = &S; | ||
| ; return (int)foo1; | ||
| ; } | ||
| ; | ||
| ; int test2() { | ||
| ; struct SS* foo2 = &S; | ||
| ; struct SS* bar2 = &S; | ||
| ; return (int)foo2 + (int)bar2; | ||
| ; } | ||
| ; | ||
| ; int test3() { | ||
| ; struct SS* bar3 = &S; | ||
| ; struct SS* foo3 = &S; | ||
| ; return (int)foo3 + (int)bar3; | ||
| ; } | ||
| ; | ||
| ; int test4() { | ||
| ; struct SS* foo4 = &S; | ||
| ; struct SS* bar4 = &S; | ||
| ; foo = 0; | ||
| ; return (int)foo4 + (int)bar4; | ||
| ; } | ||
| ; | ||
| ; int test5() { | ||
| ; struct SS* bar5 = &S; | ||
| ; struct SS* foo5 = &S; | ||
| ; foo5 = 0; | ||
| ; return (int)foo5 + (int)bar5; | ||
| ; } | ||
| ;-------------------------------------------------------------------- | ||
|
|
||
| ; CHECK: ![[FOO1:.*]] = !DILocalVariable(name: "foo1" | ||
| ; CHECK: ![[BAR1:.*]] = !DILocalVariable(name: "bar1" | ||
| ; CHECK: ![[FOO2:.*]] = !DILocalVariable(name: "foo2" | ||
| ; CHECK: ![[BAR2:.*]] = !DILocalVariable(name: "bar2" | ||
| ; CHECK: ![[FOO3:.*]] = !DILocalVariable(name: "bar3" | ||
| ; CHECK: ![[BAR3:.*]] = !DILocalVariable(name: "foo3" | ||
| ; CHECK: ![[FOO4:.*]] = !DILocalVariable(name: "foo4" | ||
| ; CHECK: ![[BAR4:.*]] = !DILocalVariable(name: "bar4" | ||
| ; CHECK: ![[BAR5:.*]] = !DILocalVariable(name: "bar5" | ||
| ; CHECK: ![[FOO5:.*]] = !DILocalVariable(name: "foo5" | ||
|
|
||
| source_filename = "sdag-dangling-dbgvalue.c" | ||
| target datalayout = "e-m:o-i64:64-f80:128-n8:16:32:64-S128" | ||
| target triple = "x86_64-apple-macosx10.4.0" | ||
|
|
||
| %struct.SS = type { i32, i32 } | ||
|
|
||
| @S = global %struct.SS { i32 23, i32 -17 }, align 4, !dbg !0 | ||
|
|
||
| ; Verify that the def comes before the for foo1. | ||
| define i32 @test1() local_unnamed_addr #0 !dbg !17 { | ||
| ; CHECK-LABEL: bb.0.entry1 | ||
| ; CHECK-NEXT: DBG_VALUE 0, $noreg, ![[BAR1]], !DIExpression() | ||
| ; CHECK-NEXT: [[REG1:%[0-9]+]]:gr64 = LEA64r | ||
| ; INSTRREF-SAME: debug-instr-number 1 | ||
| ; INSTRREF-NEXT: DBG_INSTR_REF 1, 0, ![[FOO1]], !DIExpression() | ||
| ; DBGVALUE-NEXT: DBG_VALUE [[REG1]], $noreg, ![[FOO1]], !DIExpression() | ||
| entry1: | ||
| call void @llvm.dbg.assign(metadata ptr @S, metadata !20, metadata !DIExpression(), metadata !54, metadata ptr undef, metadata !DIExpression()), !dbg !23 | ||
| call void @llvm.dbg.assign(metadata ptr null, metadata !22, metadata !DIExpression(), metadata !54, metadata ptr undef, metadata !DIExpression()), !dbg !24 | ||
| ret i32 ptrtoint (ptr @S to i32), !dbg !25 | ||
| } | ||
|
|
||
| ; Verify that the def comes before the for foo2 and bar2. | ||
| define i32 @test2() local_unnamed_addr #0 !dbg !26 { | ||
| ; CHECK-LABEL: bb.0.entry2 | ||
| ; CHECK-NEXT: [[REG2:%[0-9]+]]:gr64 = LEA64r | ||
| ; INSTRREF-SAME: debug-instr-number 1 | ||
| ; INSTRREF-NEXT: DBG_INSTR_REF 1, 0, ![[FOO2]], !DIExpression() | ||
| ; INSTRREF-NEXT: DBG_INSTR_REF 1, 0, ![[BAR2]], !DIExpression() | ||
| ; DBGVALUE-NEXT: DBG_VALUE [[REG2]], $noreg, ![[FOO2]], !DIExpression | ||
| ; DBGVALUE-NEXT: DBG_VALUE [[REG2]], $noreg, ![[BAR2]], !DIExpression | ||
| entry2: | ||
| call void @llvm.dbg.assign(metadata ptr @S, metadata !28, metadata !DIExpression(), metadata !54, metadata ptr undef, metadata !DIExpression()), !dbg !30 | ||
| call void @llvm.dbg.assign(metadata ptr @S, metadata !29, metadata !DIExpression(), metadata !54, metadata ptr undef, metadata !DIExpression()), !dbg !31 | ||
| ret i32 add (i32 ptrtoint (ptr @S to i32), i32 ptrtoint (ptr @S to i32)), !dbg !32 | ||
| } | ||
|
|
||
| ; Verify that the def comes before the for foo3 and bar3. | ||
| define i32 @test3() local_unnamed_addr #0 !dbg !33 { | ||
| ; CHECK-LABEL: bb.0.entry3 | ||
| ; CHECK-NEXT: [[REG3:%[0-9]+]]:gr64 = LEA64r | ||
| ; INSTRREF-SAME: debug-instr-number 1 | ||
| ; INSTRREF-NEXT: DBG_INSTR_REF 1, 0, ![[BAR3]], !DIExpression() | ||
| ; INSTRREF-NEXT: DBG_INSTR_REF 1, 0, ![[FOO3]], !DIExpression() | ||
| ; DBGVALUE-NEXT: DBG_VALUE [[REG3]], $noreg, ![[BAR3]], !DIExpression() | ||
| ; DBGVALUE-NEXT: DBG_VALUE [[REG3]], $noreg, ![[FOO3]], !DIExpression() | ||
| entry3: | ||
| call void @llvm.dbg.assign(metadata ptr @S, metadata !36, metadata !DIExpression(), metadata !54, metadata ptr undef, metadata !DIExpression()), !dbg !38 | ||
| call void @llvm.dbg.assign(metadata ptr @S, metadata !35, metadata !DIExpression(), metadata !54, metadata ptr undef, metadata !DIExpression()), !dbg !37 | ||
| ret i32 add (i32 ptrtoint (ptr @S to i32), i32 ptrtoint (ptr @S to i32)), !dbg !39 | ||
| } | ||
|
|
||
| ; Verify that the def comes before the for bar4. | ||
| define i32 @test4() local_unnamed_addr #0 !dbg !40 { | ||
| ; CHECK-LABEL: bb.0.entry4 | ||
| ;; NOTE: The check for `DBG_VALUE $noreg, $noreg, ![[FOO4]], !DIExpression()` | ||
| ;; has been removed because AT lowering removes redundant debug intrinsics. | ||
| ; CHECK-NEXT: DBG_VALUE 0, $noreg, ![[FOO4]], !DIExpression() | ||
| ; CHECK-NEXT: [[REG4:%[0-9]+]]:gr64 = LEA64r | ||
| ; INSTRREF-SAME: debug-instr-number 1 | ||
| ; INSTRREF-NEXT: DBG_INSTR_REF 1, 0, ![[BAR4]], !DIExpression() | ||
| ; DBGVALUE-NEXT: DBG_VALUE [[REG4]], $noreg, ![[BAR4]], !DIExpression() | ||
| entry4: | ||
| call void @llvm.dbg.assign(metadata ptr @S, metadata !42, metadata !DIExpression(), metadata !54, metadata ptr undef, metadata !DIExpression()), !dbg !44 | ||
| call void @llvm.dbg.assign(metadata ptr @S, metadata !43, metadata !DIExpression(), metadata !54, metadata ptr undef, metadata !DIExpression()), !dbg !45 | ||
| call void @llvm.dbg.assign(metadata ptr null, metadata !42, metadata !DIExpression(), metadata !54, metadata ptr undef, metadata !DIExpression()), !dbg !44 | ||
| ret i32 ptrtoint (ptr @S to i32), !dbg !46 | ||
| } | ||
|
|
||
| ; Verify that we do not get a DBG_VALUE that maps foo5 to @S here. | ||
| define i32 @test5() local_unnamed_addr #0 !dbg !47 { | ||
| ; CHECK-LABEL: bb.0.entry5: | ||
| ; cHECK-NEXT: DBG_VALUE $noreg, $noreg, ![[FOO5]], !DIExpression() | ||
| ; CHECK-NEXT: DBG_VALUE 0, $noreg, ![[FOO5]], !DIExpression() | ||
| ; CHECK-NEXT: [[REG5:%[0-9]+]]:gr64 = LEA64r | ||
| ; INSTRREF-SAME: debug-instr-number 1 | ||
| ; INSTRREF-NEXT: DBG_INSTR_REF 1, 0, ![[BAR5]], !DIExpression() | ||
| ; DBGVALUE-NEXT: DBG_VALUE [[REG5]], $noreg, ![[BAR5]], !DIExpression() | ||
| ; CHECK-NOT: DBG_{{.*}} ![[FOO5]], !DIExpression() | ||
| ; CHECK: RET | ||
| entry5: | ||
| call void @llvm.dbg.assign(metadata ptr @S, metadata !49, metadata !DIExpression(), metadata !54, metadata ptr undef, metadata !DIExpression()), !dbg !51 | ||
| call void @llvm.dbg.assign(metadata ptr @S, metadata !50, metadata !DIExpression(), metadata !54, metadata ptr undef, metadata !DIExpression()), !dbg !52 | ||
| call void @llvm.dbg.assign(metadata ptr null, metadata !50, metadata !DIExpression(), metadata !54, metadata ptr undef, metadata !DIExpression()), !dbg !52 | ||
| ret i32 ptrtoint (ptr @S to i32), !dbg !53 | ||
| } | ||
|
|
||
| declare void @llvm.dbg.assign(metadata, metadata, metadata, metadata, metadata, metadata) #1 | ||
|
|
||
| attributes #0 = { nounwind readnone uwtable } | ||
| attributes #1 = { nounwind readnone speculatable } | ||
|
|
||
| !llvm.dbg.cu = !{!2} | ||
| !llvm.module.flags = !{!12, !13, !14, !15} | ||
| !llvm.ident = !{!16} | ||
|
|
||
| !0 = !DIGlobalVariableExpression(var: !1, expr: !DIExpression()) | ||
| !1 = distinct !DIGlobalVariable(name: "S", scope: !2, file: !3, line: 4, type: !8, isLocal: false, isDefinition: true) | ||
| !2 = distinct !DICompileUnit(language: DW_LANG_C99, file: !3, producer: "clang version 7.0.0 (trunk 327229) (llvm/trunk 327239)", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, enums: !4, retainedTypes: !5, globals: !7) | ||
| !3 = !DIFile(filename: "sdag-dangling-dbgvalue.c", directory: "/repo/uabbpet/llvm-master") | ||
| !4 = !{} | ||
| !5 = !{!6} | ||
| !6 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed) | ||
| !7 = !{!0} | ||
| !8 = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "SS", file: !3, line: 1, size: 64, elements: !9) | ||
| !9 = !{!10, !11} | ||
| !10 = !DIDerivedType(tag: DW_TAG_member, name: "a", scope: !8, file: !3, line: 2, baseType: !6, size: 32) | ||
| !11 = !DIDerivedType(tag: DW_TAG_member, name: "b", scope: !8, file: !3, line: 3, baseType: !6, size: 32, offset: 32) | ||
| !12 = !{i32 2, !"Dwarf Version", i32 2} | ||
| !13 = !{i32 2, !"Debug Info Version", i32 3} | ||
| !14 = !{i32 1, !"wchar_size", i32 4} | ||
| !15 = !{i32 7, !"PIC Level", i32 2} | ||
| !16 = !{!"clang version 7.0.0 (trunk 327229) (llvm/trunk 327239)"} | ||
| !17 = distinct !DISubprogram(name: "test1", scope: !3, file: !3, line: 6, type: !18, isLocal: false, isDefinition: true, scopeLine: 6, isOptimized: true, unit: !2, retainedNodes: !19) | ||
| !18 = !DISubroutineType(types: !5) | ||
| !19 = !{!20, !22} | ||
| !20 = !DILocalVariable(name: "foo1", scope: !17, file: !3, line: 7, type: !21) | ||
| !21 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !8, size: 64) | ||
| !22 = !DILocalVariable(name: "bar1", scope: !17, file: !3, line: 8, type: !21) | ||
| !23 = !DILocation(line: 7, column: 14, scope: !17) | ||
| !24 = !DILocation(line: 8, column: 14, scope: !17) | ||
| !25 = !DILocation(line: 9, column: 3, scope: !17) | ||
| !26 = distinct !DISubprogram(name: "test2", scope: !3, file: !3, line: 12, type: !18, isLocal: false, isDefinition: true, scopeLine: 12, isOptimized: true, unit: !2, retainedNodes: !27) | ||
| !27 = !{!28, !29} | ||
| !28 = !DILocalVariable(name: "foo2", scope: !26, file: !3, line: 13, type: !21) | ||
| !29 = !DILocalVariable(name: "bar2", scope: !26, file: !3, line: 14, type: !21) | ||
| !30 = !DILocation(line: 13, column: 14, scope: !26) | ||
| !31 = !DILocation(line: 14, column: 14, scope: !26) | ||
| !32 = !DILocation(line: 15, column: 3, scope: !26) | ||
| !33 = distinct !DISubprogram(name: "test3", scope: !3, file: !3, line: 18, type: !18, isLocal: false, isDefinition: true, scopeLine: 18, isOptimized: true, unit: !2, retainedNodes: !34) | ||
| !34 = !{!35, !36} | ||
| !35 = !DILocalVariable(name: "bar3", scope: !33, file: !3, line: 19, type: !21) | ||
| !36 = !DILocalVariable(name: "foo3", scope: !33, file: !3, line: 20, type: !21) | ||
| !37 = !DILocation(line: 19, column: 14, scope: !33) | ||
| !38 = !DILocation(line: 20, column: 14, scope: !33) | ||
| !39 = !DILocation(line: 21, column: 3, scope: !33) | ||
| !40 = distinct !DISubprogram(name: "test4", scope: !3, file: !3, line: 24, type: !18, isLocal: false, isDefinition: true, scopeLine: 24, isOptimized: true, unit: !2, retainedNodes: !41) | ||
| !41 = !{!42, !43} | ||
| !42 = !DILocalVariable(name: "foo4", scope: !40, file: !3, line: 25, type: !21) | ||
| !43 = !DILocalVariable(name: "bar4", scope: !40, file: !3, line: 26, type: !21) | ||
| !44 = !DILocation(line: 25, column: 14, scope: !40) | ||
| !45 = !DILocation(line: 26, column: 14, scope: !40) | ||
| !46 = !DILocation(line: 28, column: 3, scope: !40) | ||
| !47 = distinct !DISubprogram(name: "test5", scope: !3, file: !3, line: 31, type: !18, isLocal: false, isDefinition: true, scopeLine: 31, isOptimized: true, unit: !2, retainedNodes: !48) | ||
| !48 = !{!49, !50} | ||
| !49 = !DILocalVariable(name: "bar5", scope: !47, file: !3, line: 32, type: !21) | ||
| !50 = !DILocalVariable(name: "foo5", scope: !47, file: !3, line: 33, type: !21) | ||
| !51 = !DILocation(line: 32, column: 14, scope: !47) | ||
| !52 = !DILocation(line: 33, column: 14, scope: !47) | ||
| !53 = !DILocation(line: 35, column: 3, scope: !47) | ||
| !54 = distinct !DIAssignID() |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,72 @@ | ||
| ; RUN: llc -mtriple=x86_64-unknown-unknown -start-after=codegenprepare \ | ||
| ; RUN: -experimental-assignment-tracking \ | ||
| ; RUN: -stop-before finalize-isel %s -o - \ | ||
| ; RUN: -experimental-debug-variable-locations=false \ | ||
| ; RUN: | FileCheck %s --check-prefixes=CHECK,DBGVALUE | ||
| ; RUN: llc -mtriple=x86_64-unknown-unknown -start-after=codegenprepare \ | ||
| ; RUN: -experimental-assignment-tracking \ | ||
| ; RUN: -stop-before finalize-isel %s -o - \ | ||
| ; RUN: -experimental-debug-variable-locations=true \ | ||
| ; RUN: | FileCheck %s --check-prefixes=CHECK,INSTRREF | ||
|
|
||
| ; Adapted from sdag-ir-salvage.ll to test dbg.assign intrinsics. This ensures | ||
| ; that dbg.assigns with no linked store are treated as dbg.values. | ||
|
|
||
| ; Test that the dbg.value for %baz, which doesn't exist in the 'next' bb, | ||
| ; can be salvaged back to the underlying argument vreg. | ||
|
|
||
| ; CHECK: ![[AAAVAR:.*]] = !DILocalVariable(name: "aaa", | ||
| ; CHECK-LABEL: bb.0.entry: | ||
| ; INSTRREF: DBG_PHI $rdi, 1 | ||
| ; CHECK-LABEL: bb.1.next: | ||
| ; INSTRREF: DBG_INSTR_REF 1, 0, ![[AAAVAR]] | ||
| ; DBGVALUE: DBG_VALUE %{{[0-9]+}}, $noreg, ![[AAAVAR]] | ||
|
|
||
| target datalayout = "e-m:o-i64:64-f80:128-n8:16:32:64-S128" | ||
| target triple = "x86_64-linux-gnu" | ||
|
|
||
| define i8 @f(ptr %foo) local_unnamed_addr !dbg !6 { | ||
| entry: | ||
| %bar = getelementptr i32, ptr %foo, i32 4 | ||
| %baz = bitcast ptr %bar to ptr | ||
| %quux = load i8, ptr %baz | ||
| br label %next | ||
|
|
||
| next: ; preds = %entry | ||
| tail call void @llvm.dbg.assign(metadata ptr %baz, metadata !15, metadata !DIExpression(), metadata !31, metadata ptr undef, metadata !DIExpression()), !dbg !30 | ||
| %xyzzy = add i8 %quux, 123 | ||
| br label %fin | ||
|
|
||
| fin: ; preds = %next | ||
| %trains = getelementptr i32, ptr %foo, i32 3 | ||
| %planes = bitcast ptr %trains to ptr | ||
| %cars = load i8, ptr %planes | ||
| %ret = add i8 %xyzzy, %cars | ||
| ret i8 %ret | ||
| } | ||
|
|
||
| ; Function Attrs: nounwind readnone speculatable | ||
| declare void @llvm.dbg.assign(metadata, metadata, metadata, metadata, metadata, metadata) #0 | ||
|
|
||
| attributes #0 = { nounwind readnone speculatable } | ||
|
|
||
| !llvm.dbg.cu = !{!0} | ||
| !llvm.module.flags = !{!25, !26, !27, !28} | ||
| !llvm.ident = !{!29} | ||
|
|
||
| !0 = distinct !DICompileUnit(language: DW_LANG_C99, file: !1, producer: "clang", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, enums: !2) | ||
| !1 = !DIFile(filename: "test.c", directory: ".") | ||
| !2 = !{} | ||
| !6 = distinct !DISubprogram(name: "f", scope: !1, file: !1, line: 18, type: !7, scopeLine: 19, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !0, retainedNodes: !14) | ||
| !7 = !DISubroutineType(types: !8) | ||
| !8 = !{!13} | ||
| !13 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_unsigned) | ||
| !14 = !{!15} | ||
| !15 = !DILocalVariable(name: "aaa", scope: !6, file: !1, line: 18, type: !13) | ||
| !25 = !{i32 2, !"Dwarf Version", i32 4} | ||
| !26 = !{i32 2, !"Debug Info Version", i32 3} | ||
| !27 = !{i32 1, !"wchar_size", i32 4} | ||
| !28 = !{i32 7, !"PIC Level", i32 2} | ||
| !29 = !{!"clang"} | ||
| !30 = !DILocation(line: 18, column: 14, scope: !6) | ||
| !31 = distinct !DIAssignID() |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,77 @@ | ||
| ; RUN: llc %s -start-after=codegenprepare -stop-before finalize-isel -o - \ | ||
| ; RUN: -experimental-assignment-tracking \ | ||
| ; RUN: -experimental-debug-variable-locations=false \ | ||
| ; RUN: | FileCheck %s --check-prefixes=CHECK,DBGVALUE | ||
| ; RUN: llc %s -start-after=codegenprepare -stop-before finalize-isel -o - \ | ||
| ; RUN: -experimental-assignment-tracking \ | ||
| ; RUN: -experimental-debug-variable-locations=true \ | ||
| ; RUN: | FileCheck %s --check-prefixes=CHECK,INSTRREF | ||
|
|
||
| ; Adapted from sdag-transfer-dbgvalue.ll to test dbg.assign intrinsics. This | ||
| ; ensures that dbg.assigns with no linked store are treated as dbg.values. | ||
|
|
||
| ; This tests that transferDbgValues() changes order of SDDbgValue transferred | ||
| ; to another node and debug info for 'ADD32ri' appears *after* the instruction. | ||
| ; | ||
| ; This test case was generated from the following program | ||
| ; using: clang -g -O3 -S -emit-llvm test.c | ||
| ; | ||
| ; int foo(int a, int *b) { | ||
| ; int c = a + 512; | ||
| ; if (c != 0) | ||
| ; *b = a; | ||
| ; return c; | ||
| ; } | ||
|
|
||
| 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" | ||
|
|
||
| ; CHECK-LABEL: bb.0.entry: | ||
| ; DBGVALUE: %[[REG:[0-9]+]]:gr32 = ADD32ri %1, 512 | ||
| ; DBGVALUE-NEXT: DBG_VALUE %[[REG]] | ||
| ; INSTRREF: ADD32ri %1, 512, {{.*}}debug-instr-number 1 | ||
| ; INSTRREF-NEXT: DBG_INSTR_REF 1, 0 | ||
|
|
||
| ; Function Attrs: nofree norecurse nounwind uwtable writeonly | ||
| define dso_local i32 @foo(i32 %a, ptr nocapture %b) local_unnamed_addr !dbg !7 { | ||
| entry: | ||
| %add = add nsw i32 %a, 512, !dbg !18 | ||
| call void @llvm.dbg.assign(metadata i32 %add, metadata !16, metadata !DIExpression(), metadata !19, metadata ptr undef, metadata !DIExpression()), !dbg !17 | ||
| %cmp = icmp eq i32 %add, 0, !dbg !18 | ||
| br i1 %cmp, label %if.end, label %if.then, !dbg !18 | ||
|
|
||
| if.then: ; preds = %entry | ||
| store i32 %a, ptr %b, align 4, !dbg !18 | ||
| br label %if.end, !dbg !18 | ||
|
|
||
| if.end: ; preds = %entry, %if.then | ||
| ret i32 %add, !dbg !18 | ||
| } | ||
|
|
||
| ; Function Attrs: nounwind readnone speculatable willreturn | ||
| declare void @llvm.dbg.assign(metadata, metadata, metadata, metadata, metadata, metadata) | ||
|
|
||
| !llvm.dbg.cu = !{!0} | ||
| !llvm.module.flags = !{!3, !4, !5} | ||
| !llvm.ident = !{!6} | ||
|
|
||
| !0 = distinct !DICompileUnit(language: DW_LANG_C99, file: !1, producer: "clang version 10.0.0", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, enums: !2, nameTableKind: None) | ||
| !1 = !DIFile(filename: "test.c", directory: "/") | ||
| !2 = !{} | ||
| !3 = !{i32 2, !"Dwarf Version", i32 4} | ||
| !4 = !{i32 2, !"Debug Info Version", i32 3} | ||
| !5 = !{i32 1, !"wchar_size", i32 4} | ||
| !6 = !{!"clang version 10.0.0"} | ||
| !7 = distinct !DISubprogram(name: "foo", scope: !8, file: !8, line: 1, type: !9, scopeLine: 1, flags: DIFlagPrototyped | DIFlagAllCallsDescribed, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !0, retainedNodes: !13) | ||
| !8 = !DIFile(filename: "test.c", directory: "/") | ||
| !9 = !DISubroutineType(types: !10) | ||
| !10 = !{!11, !11, !12} | ||
| !11 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed) | ||
| !12 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !11, size: 64) | ||
| !13 = !{!14, !15, !16} | ||
| !14 = !DILocalVariable(name: "a", arg: 1, scope: !7, file: !8, line: 1, type: !11) | ||
| !15 = !DILocalVariable(name: "b", arg: 2, scope: !7, file: !8, line: 1, type: !12) | ||
| !16 = !DILocalVariable(name: "c", scope: !7, file: !8, line: 2, type: !11) | ||
| !17 = !DILocation(line: 0, scope: !7) | ||
| !18 = !DILocation(line: 2, column: 13, scope: !7) | ||
| !19 = distinct !DIAssignID() |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,111 @@ | ||
| ; RUN: llc -stop-after=finalize-isel %s -o - \ | ||
| ; RUN: -experimental-assignment-tracking \ | ||
| ; RUN: | FileCheck %s | ||
|
|
||
| ;; Check that a dbg.assign for a fully stack-homed variable causes the variable | ||
| ;; location to appear in the Machine Function side table. Similar to | ||
| ;; single-memory-location.ll except this has slightly more complicated input | ||
| ;; (there's a loop and an assignment). | ||
| ;; | ||
| ;; $ cat test.cpp | ||
| ;; int get(); | ||
| ;; void esc(int*); | ||
| ;; void doSomething(int); | ||
| ;; void fun() { | ||
| ;; int local; | ||
| ;; esc(&local); | ||
| ;; while (local) { | ||
| ;; local = get(); | ||
| ;; doSomething(local); | ||
| ;; esc(&local); | ||
| ;; } | ||
| ;; } | ||
| ;; $ clang++ -O2 -g -emit-llvm -S -c -Xclang -fexperimental-assignment-tracking | ||
|
|
||
| ; CHECK: ![[VAR:[0-9]+]] = !DILocalVariable(name: "local", | ||
| ; CHECK: stack: | ||
| ; CHECK-NEXT: - { id: 0, name: local, type: default, offset: 0, size: 4, alignment: 4, | ||
| ; CHECK-NEXT: stack-id: default, callee-saved-register: '', callee-saved-restored: true, | ||
| ; CHECK-NEXT: debug-info-variable: '![[VAR]]', debug-info-expression: '!DIExpression()', | ||
| ; CHECK-NEXT: debug-info-location: '!{{.+}}' } | ||
|
|
||
| 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" | ||
|
|
||
| ; Function Attrs: uwtable mustprogress | ||
| define dso_local void @_Z3funv() local_unnamed_addr #0 !dbg !7 { | ||
| entry: | ||
| %local = alloca i32, align 4, !DIAssignID !13 | ||
| call void @llvm.dbg.assign(metadata i1 undef, metadata !11, metadata !DIExpression(), metadata !13, metadata ptr %local, metadata !DIExpression()), !dbg !14 | ||
| %0 = bitcast ptr %local to ptr, !dbg !15 | ||
| call void @llvm.lifetime.start.p0i8(i64 4, ptr nonnull %0) #4, !dbg !15 | ||
| call void @_Z3escPi(ptr nonnull %local), !dbg !16 | ||
| %1 = load i32, ptr %local, align 4, !dbg !17 | ||
| %tobool.not1 = icmp eq i32 %1, 0, !dbg !17 | ||
| br i1 %tobool.not1, label %while.end, label %while.body, !dbg !22 | ||
|
|
||
| while.body: ; preds = %entry, %while.body | ||
| %call = call i32 @_Z3getv(), !dbg !23 | ||
| store i32 %call, ptr %local, align 4, !dbg !25, !DIAssignID !26 | ||
| call void @llvm.dbg.assign(metadata i32 %call, metadata !11, metadata !DIExpression(), metadata !26, metadata ptr %local, metadata !DIExpression()), !dbg !14 | ||
| call void @_Z11doSomethingi(i32 %call), !dbg !27 | ||
| call void @_Z3escPi(ptr nonnull %local), !dbg !28 | ||
| %2 = load i32, ptr %local, align 4, !dbg !17 | ||
| %tobool.not = icmp eq i32 %2, 0, !dbg !17 | ||
| br i1 %tobool.not, label %while.end, label %while.body, !dbg !22, !llvm.loop !29 | ||
|
|
||
| while.end: ; preds = %while.body, %entry | ||
| call void @llvm.lifetime.end.p0i8(i64 4, ptr nonnull %0) #4, !dbg !32 | ||
| ret void, !dbg !32 | ||
| } | ||
|
|
||
| declare void @llvm.lifetime.start.p0i8(i64 immarg, ptr nocapture) | ||
| declare !dbg !33 dso_local void @_Z3escPi(ptr) local_unnamed_addr | ||
| declare !dbg !37 dso_local i32 @_Z3getv() local_unnamed_addr | ||
| declare !dbg !40 dso_local void @_Z11doSomethingi(i32) local_unnamed_addr | ||
| declare void @llvm.lifetime.end.p0i8(i64 immarg, ptr nocapture) | ||
| declare void @llvm.dbg.assign(metadata, metadata, metadata, metadata, metadata, metadata) | ||
|
|
||
| !llvm.dbg.cu = !{!0} | ||
| !llvm.module.flags = !{!3, !4, !5} | ||
| !llvm.ident = !{!6} | ||
|
|
||
| !0 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus_14, file: !1, producer: "clang version 12.0.0", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, enums: !2, splitDebugInlining: false, nameTableKind: None) | ||
| !1 = !DIFile(filename: "test.cpp", directory: "/") | ||
| !2 = !{} | ||
| !3 = !{i32 7, !"Dwarf Version", i32 4} | ||
| !4 = !{i32 2, !"Debug Info Version", i32 3} | ||
| !5 = !{i32 1, !"wchar_size", i32 4} | ||
| !6 = !{!"clang version 12.0.0"} | ||
| !7 = distinct !DISubprogram(name: "fun", linkageName: "_Z3funv", scope: !1, file: !1, line: 4, type: !8, scopeLine: 4, flags: DIFlagPrototyped | DIFlagAllCallsDescribed, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !0, retainedNodes: !10) | ||
| !8 = !DISubroutineType(types: !9) | ||
| !9 = !{null} | ||
| !10 = !{!11} | ||
| !11 = !DILocalVariable(name: "local", scope: !7, file: !1, line: 5, type: !12) | ||
| !12 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed) | ||
| !13 = distinct !DIAssignID() | ||
| !14 = !DILocation(line: 0, scope: !7) | ||
| !15 = !DILocation(line: 5, column: 3, scope: !7) | ||
| !16 = !DILocation(line: 6, column: 3, scope: !7) | ||
| !17 = !DILocation(line: 7, column: 10, scope: !7) | ||
| !22 = !DILocation(line: 7, column: 3, scope: !7) | ||
| !23 = !DILocation(line: 8, column: 13, scope: !24) | ||
| !24 = distinct !DILexicalBlock(scope: !7, file: !1, line: 7, column: 17) | ||
| !25 = !DILocation(line: 8, column: 11, scope: !24) | ||
| !26 = distinct !DIAssignID() | ||
| !27 = !DILocation(line: 9, column: 5, scope: !24) | ||
| !28 = !DILocation(line: 10, column: 5, scope: !24) | ||
| !29 = distinct !{!29, !22, !30, !31} | ||
| !30 = !DILocation(line: 11, column: 3, scope: !7) | ||
| !31 = !{!"llvm.loop.mustprogress"} | ||
| !32 = !DILocation(line: 12, column: 1, scope: !7) | ||
| !33 = !DISubprogram(name: "esc", linkageName: "_Z3escPi", scope: !1, file: !1, line: 2, type: !34, flags: DIFlagPrototyped, spFlags: DISPFlagOptimized, retainedNodes: !2) | ||
| !34 = !DISubroutineType(types: !35) | ||
| !35 = !{null, !36} | ||
| !36 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !12, size: 64) | ||
| !37 = !DISubprogram(name: "get", linkageName: "_Z3getv", scope: !1, file: !1, line: 1, type: !38, flags: DIFlagPrototyped, spFlags: DISPFlagOptimized, retainedNodes: !2) | ||
| !38 = !DISubroutineType(types: !39) | ||
| !39 = !{!12} | ||
| !40 = !DISubprogram(name: "doSomething", linkageName: "_Z11doSomethingi", scope: !1, file: !1, line: 3, type: !41, flags: DIFlagPrototyped, spFlags: DISPFlagOptimized, retainedNodes: !2) | ||
| !41 = !DISubroutineType(types: !42) | ||
| !42 = !{null, !12} |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,80 @@ | ||
| ; RUN: llc -stop-after=finalize-isel %s -o - \ | ||
| ; RUN: -experimental-assignment-tracking \ | ||
| ; RUN: | FileCheck %s | ||
|
|
||
| ;; Check that a dbg.assign for a fully stack-homed variable causes the variable | ||
| ;; location to appear in the Machine Function side table. | ||
| ;; | ||
| ;; $ cat test.cpp | ||
| ;; void maybe_writes(int*); | ||
| ;; void ext(int, int, int, int, int, int, int, int, int, int); | ||
| ;; int example() { | ||
| ;; int local; | ||
| ;; maybe_writes(&local); | ||
| ;; ext(0, 1, 2, 3, 4, 5, 6, 7, 8, 9); | ||
| ;; return local; | ||
| ;; } | ||
| ;; $ clang++ -O2 -g -emit-llvm -S -c -Xclang -fexperimental-assignment-tracking | ||
|
|
||
| ; CHECK: ![[VAR:[0-9]+]] = !DILocalVariable(name: "local", | ||
| ; CHECK: stack: | ||
| ; CHECK-NEXT: - { id: 0, name: local, type: default, offset: 0, size: 4, alignment: 4, | ||
| ; CHECK-NEXT: stack-id: default, callee-saved-register: '', callee-saved-restored: true, | ||
| ; CHECK-NEXT: debug-info-variable: '![[VAR]]', debug-info-expression: '!DIExpression()', | ||
| ; CHECK-NEXT: debug-info-location: '!{{.+}}' } | ||
|
|
||
| source_filename = "test.cpp" | ||
| 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" | ||
|
|
||
| define dso_local i32 @_Z7examplev() local_unnamed_addr !dbg !7 { | ||
| entry: | ||
| %local = alloca i32, align 4, !DIAssignID !13 | ||
| call void @llvm.dbg.assign(metadata i1 undef, metadata !12, metadata !DIExpression(), metadata !13, metadata ptr %local, metadata !DIExpression()), !dbg !14 | ||
| %0 = bitcast ptr %local to ptr, !dbg !15 | ||
| call void @llvm.lifetime.start.p0i8(i64 4, ptr nonnull %0), !dbg !15 | ||
| call void @_Z12maybe_writesPi(ptr nonnull %local), !dbg !16 | ||
| call void @_Z3extiiiiiiiiii(i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7, i32 8, i32 9), !dbg !17 | ||
| %1 = load i32, ptr %local, align 4, !dbg !18 | ||
| call void @llvm.lifetime.end.p0i8(i64 4, ptr nonnull %0), !dbg !23 | ||
| ret i32 %1, !dbg !24 | ||
| } | ||
|
|
||
| declare !dbg !25 dso_local void @_Z12maybe_writesPi(ptr) local_unnamed_addr | ||
| declare !dbg !29 dso_local void @_Z3extiiiiiiiiii(i32, i32, i32, i32, i32, i32, i32, i32, i32, i32) local_unnamed_addr | ||
| declare void @llvm.lifetime.start.p0i8(i64 immarg, ptr nocapture) | ||
| declare void @llvm.lifetime.end.p0i8(i64 immarg, ptr nocapture) | ||
| declare void @llvm.dbg.assign(metadata, metadata, metadata, metadata, metadata, metadata) | ||
|
|
||
| !llvm.dbg.cu = !{!0} | ||
| !llvm.module.flags = !{!3, !4, !5} | ||
| !llvm.ident = !{!6} | ||
|
|
||
| !0 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus_14, file: !1, producer: "clang version 12.0.0", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, enums: !2, splitDebugInlining: false, nameTableKind: None) | ||
| !1 = !DIFile(filename: "test.cpp", directory: "/") | ||
| !2 = !{} | ||
| !3 = !{i32 7, !"Dwarf Version", i32 4} | ||
| !4 = !{i32 2, !"Debug Info Version", i32 3} | ||
| !5 = !{i32 1, !"wchar_size", i32 4} | ||
| !6 = !{!"clang version 12.0.0"} | ||
| !7 = distinct !DISubprogram(name: "example", linkageName: "_Z7examplev", scope: !1, file: !1, line: 3, type: !8, scopeLine: 3, flags: DIFlagPrototyped | DIFlagAllCallsDescribed, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !0, retainedNodes: !11) | ||
| !8 = !DISubroutineType(types: !9) | ||
| !9 = !{!10} | ||
| !10 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed) | ||
| !11 = !{!12} | ||
| !12 = !DILocalVariable(name: "local", scope: !7, file: !1, line: 4, type: !10) | ||
| !13 = distinct !DIAssignID() | ||
| !14 = !DILocation(line: 0, scope: !7) | ||
| !15 = !DILocation(line: 4, column: 4, scope: !7) | ||
| !16 = !DILocation(line: 5, column: 4, scope: !7) | ||
| !17 = !DILocation(line: 6, column: 4, scope: !7) | ||
| !18 = !DILocation(line: 7, column: 11, scope: !7) | ||
| !23 = !DILocation(line: 8, column: 1, scope: !7) | ||
| !24 = !DILocation(line: 7, column: 4, scope: !7) | ||
| !25 = !DISubprogram(name: "maybe_writes", linkageName: "_Z12maybe_writesPi", scope: !1, file: !1, line: 1, type: !26, flags: DIFlagPrototyped, spFlags: DISPFlagOptimized, retainedNodes: !2) | ||
| !26 = !DISubroutineType(types: !27) | ||
| !27 = !{null, !28} | ||
| !28 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !10, size: 64) | ||
| !29 = !DISubprogram(name: "ext", linkageName: "_Z3extiiiiiiiiii", scope: !1, file: !1, line: 2, type: !30, flags: DIFlagPrototyped, spFlags: DISPFlagOptimized, retainedNodes: !2) | ||
| !30 = !DISubroutineType(types: !31) | ||
| !31 = !{null, !10, !10, !10, !10, !10, !10, !10, !10, !10, !10} |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,58 @@ | ||
| ; RUN: llc %s -o - -stop-after=finalize-isel \ | ||
| ; RUN: -experimental-assignment-tracking \ | ||
| ; RUN: | FileCheck %s --implicit-check-not=DBG | ||
|
|
||
| ;; Hand written. Check that we fall back to emitting a list of defs for | ||
| ;; variables with split allocas (i.e. we want to see DBG_VALUEs and no | ||
| ;; debug-info-variable entry in the stack slot table). | ||
|
|
||
| ; CHECK: stack: | ||
| ; CHECK: - { id: 0, name: a, type: default, offset: 0, size: 4, alignment: 4, | ||
| ; CHECK: stack-id: default, callee-saved-register: '', callee-saved-restored: true, | ||
| ; CHECK: debug-info-variable: '', debug-info-expression: '', debug-info-location: '' } | ||
| ; CHECK: - { id: 1, name: c, type: default, offset: 0, size: 4, alignment: 4, | ||
| ; CHECK: stack-id: default, callee-saved-register: '', callee-saved-restored: true, | ||
| ; CHECK: debug-info-variable: '', debug-info-expression: '', debug-info-location: '' } | ||
| ; CHECK: DBG_VALUE %stack.0.a, $noreg, !{{.*}}, !DIExpression(DW_OP_deref, DW_OP_LLVM_fragment, 0, 32) | ||
| ; CHECK: DBG_VALUE %stack.1.c, $noreg, !{{.*}}, !DIExpression(DW_OP_deref, DW_OP_LLVM_fragment, 64, 32) | ||
|
|
||
| target triple = "x86_64-unknown-linux-gnu" | ||
|
|
||
| define dso_local void @fun() !dbg !7 { | ||
| entry: | ||
| %a = alloca i32, align 4, !DIAssignID !16 | ||
| call void @llvm.dbg.assign(metadata i1 undef, metadata !11, metadata !DIExpression(DW_OP_LLVM_fragment, 0, 32), metadata !16, metadata ptr %a, metadata !DIExpression()), !dbg !17 | ||
| %c = alloca i32, align 4, !DIAssignID !20 | ||
| call void @llvm.dbg.assign(metadata i1 undef, metadata !11, metadata !DIExpression(DW_OP_LLVM_fragment, 64, 32), metadata !20, metadata ptr %c, metadata !DIExpression()), !dbg !17 | ||
| store i32 5, ptr %a, !DIAssignID !21 | ||
| ret void, !dbg !19 | ||
| } | ||
|
|
||
| declare void @llvm.dbg.assign(metadata, metadata, metadata, metadata, metadata, metadata) | ||
|
|
||
| !llvm.dbg.cu = !{!0} | ||
| !llvm.module.flags = !{!2, !3, !4, !5} | ||
| !llvm.ident = !{!6} | ||
|
|
||
| !0 = distinct !DICompileUnit(language: DW_LANG_C99, file: !1, producer: "clang version 14.0.0", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, splitDebugInlining: false, nameTableKind: None) | ||
| !1 = !DIFile(filename: "test.c", directory: "/") | ||
| !2 = !{i32 7, !"Dwarf Version", i32 5} | ||
| !3 = !{i32 2, !"Debug Info Version", i32 3} | ||
| !4 = !{i32 1, !"wchar_size", i32 4} | ||
| !5 = !{i32 7, !"uwtable", i32 1} | ||
| !6 = !{!"clang version 14.0.0"} | ||
| !7 = distinct !DISubprogram(name: "fun", scope: !1, file: !1, line: 1, type: !8, scopeLine: 1, flags: DIFlagAllCallsDescribed, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !0, retainedNodes: !10) | ||
| !8 = !DISubroutineType(types: !9) | ||
| !9 = !{null} | ||
| !10 = !{!11} | ||
| !11 = !DILocalVariable(name: "local", scope: !7, file: !1, line: 2, type: !12) | ||
| !12 = !DICompositeType(tag: DW_TAG_array_type, baseType: !13, size: 96, elements: !14) | ||
| !13 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed) | ||
| !14 = !{!15} | ||
| !15 = !DISubrange(count: 3) | ||
| !16 = distinct !DIAssignID() | ||
| !17 = !DILocation(line: 0, scope: !7) | ||
| !18 = !DILocation(line: 2, column: 3, scope: !7) | ||
| !19 = !DILocation(line: 3, column: 1, scope: !7) | ||
| !20 = distinct !DIAssignID() | ||
| !21 = distinct !DIAssignID() |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,82 @@ | ||
| ; RUN: llc %s -stop-after=finalize-isel -o - -experimental-assignment-tracking \ | ||
| ; RUN: | FileCheck %s --implicit-check-not=DBG_ | ||
|
|
||
| ;; Hand-written to test untagged store handling on a simple case. Here's what | ||
| ;; we're looking at in the IR: | ||
|
|
||
| ;; 1. mem(a): bits [0, 64) = !14 | ||
| ;; 2. dbg(a): bits [0, 64) = !14 ; Use memory loc | ||
| ;; 3. dbg(a): bits [0, 32) = <unique ID> ; Use implicit loc, dbg.value has no ID | ||
| ;; 4. dbg(a): bits [32, 64) = !16 ; These bits don't use mem loc. | ||
| ;; ; Linked to a def that comes later ---+ | ||
| ;; ... ; | | ||
| ;; 5. mem(a): bits [0, 32) = <unique ID> ; Untagged store ; | | ||
| ;; .. ; | | ||
| ;; 6. mem(a): bits [32, 64) = !16 ; <-----------------------------------+ | ||
|
|
||
| ;; Taking the '<number>.' above as the 'position', check we get defs that look | ||
| ;; like this: | ||
| ;; Position | bits [0, 32) | bits [32, 64) | ||
| ;; ---------+--------------+--------------- | ||
| ;; 2. | Mem | Mem | ||
| ;; 3. | Value | Mem | ||
| ;; 4. | Value | Value | ||
| ;; 5. | Mem | Value | ||
| ;; 6. | Mem | Mem | ||
|
|
||
| ; CHECK-DAG: ![[A:[0-9]+]] = !DILocalVariable(name: "a", | ||
|
|
||
| ; CHECK: DBG_VALUE %stack.0.a.addr, $noreg, ![[A]], !DIExpression(DW_OP_deref) | ||
| ; CHECK-NEXT: DBG_VALUE 5, $noreg, ![[A]], !DIExpression(DW_OP_LLVM_fragment, 0, 32) | ||
| ; CHECK-NEXT: DBG_VALUE $noreg, $noreg, ![[A]], !DIExpression(DW_OP_LLVM_fragment, 32, 32) | ||
| ; CHECK-NEXT: MOV32mi %stack.0.a.addr, 1, $noreg, 0, $noreg, 123 | ||
| ; CHECK-NEXT: DBG_VALUE %stack.0.a.addr, $noreg, ![[A]], !DIExpression(DW_OP_deref, DW_OP_LLVM_fragment, 0, 32) | ||
| ; CHECK-NEXT: MOV32mr %stack.0.a.addr, 1, $noreg, 4, $noreg, %1 :: (store (s32) into %ir.add.ptr, align 8) | ||
| ; CHECK-NEXT: DBG_VALUE %stack.0.a.addr, $noreg, ![[A]], !DIExpression(DW_OP_deref, DW_OP_LLVM_fragment, 32, 32) | ||
|
|
||
| ;; NOTE: The second and third DBG_VALUE combined make the first redundant. If | ||
| ;; removeRedundantDbgInstrs gets smarter, add an instruction between the first | ||
| ;; dbg.assign and the subsequent dbg.value. | ||
|
|
||
| target triple = "x86_64-unknown-linux-gnu" | ||
|
|
||
| define dso_local noundef i64 @_Z1fl(i64 noundef %a, i32 %b) #0 !dbg !8 { | ||
| entry: | ||
| %a.addr = alloca i64, align 8, !DIAssignID !13 | ||
| call void @llvm.dbg.assign(metadata i1 undef, metadata !14, metadata !DIExpression(), metadata !13, metadata ptr %a.addr, metadata !DIExpression()), !dbg !15 | ||
| call void @llvm.dbg.value(metadata i64 5, metadata !14, metadata !DIExpression(DW_OP_LLVM_fragment, 0, 32)), !dbg !15 | ||
| call void @llvm.dbg.assign(metadata i1 undef, metadata !14, metadata !DIExpression(DW_OP_LLVM_fragment, 32, 32), metadata !16, metadata ptr %a.addr, metadata !DIExpression()), !dbg !15 | ||
| %frag.addr = bitcast ptr %a.addr to ptr | ||
| store i32 123, ptr %frag.addr, align 8 | ||
| %0 = bitcast ptr %a.addr to ptr | ||
| %add.ptr = getelementptr inbounds i32, ptr %0, i64 1 | ||
| store i32 %b, ptr %add.ptr, align 8, !DIAssignID !16 | ||
| %1 = load i64, ptr %a.addr, align 8 | ||
| ret i64 %1 | ||
| } | ||
|
|
||
| declare void @llvm.dbg.value(metadata, metadata, metadata) #1 | ||
| declare void @llvm.dbg.assign(metadata, metadata, metadata, metadata, metadata, metadata) #1 | ||
|
|
||
| !llvm.dbg.cu = !{!0} | ||
| !llvm.module.flags = !{!2, !3, !4, !5, !6} | ||
| !llvm.ident = !{!7} | ||
|
|
||
| !0 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus_14, file: !1, producer: "clang version 14.0.0", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, splitDebugInlining: false, nameTableKind: None) | ||
| !1 = !DIFile(filename: "test.cpp", directory: "/") | ||
| !2 = !{i32 7, !"Dwarf Version", i32 5} | ||
| !3 = !{i32 2, !"Debug Info Version", i32 3} | ||
| !4 = !{i32 1, !"wchar_size", i32 4} | ||
| !5 = !{i32 7, !"uwtable", i32 1} | ||
| !6 = !{i32 7, !"frame-pointer", i32 2} | ||
| !7 = !{!"clang version 14.0.0"} | ||
| !8 = distinct !DISubprogram(name: "f", linkageName: "_Z1fl", scope: !1, file: !1, line: 1, type: !9, scopeLine: 1, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition, unit: !0, retainedNodes: !12) | ||
| !9 = !DISubroutineType(types: !10) | ||
| !10 = !{!11, !11} | ||
| !11 = !DIBasicType(name: "long", size: 64, encoding: DW_ATE_signed) | ||
| !12 = !{} | ||
| !13 = distinct !DIAssignID() | ||
| !14 = !DILocalVariable(name: "a", arg: 1, scope: !8, file: !1, line: 1, type: !11) | ||
| !15 = !DILocation(line: 0, scope: !8) | ||
| !16 = distinct !DIAssignID() | ||
| !17 = !DILocalVariable(name: "b", arg: 2, scope: !8, file: !1, line: 1, type: !11) |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,93 @@ | ||
| ; RUN: llc %s -stop-after=finalize-isel -o - \ | ||
| ; RUN: -experimental-assignment-tracking \ | ||
| ; RUN: | FileCheck %s --implicit-check-not=DBG_VALUE | ||
|
|
||
| ;; Check that sandwiching instructions between a linked store and dbg.assign | ||
| ;; results in a dbg.value(prev_value) being inserted at the store, and a | ||
| ;; dbg.value(deref) at the dbg.assign. | ||
| ;; Same as use-known-value-at-early-mem-def.ll except the "early mem def" is | ||
| ;; for a fragment of the variable rather than the whole. | ||
|
|
||
| ; CHECK: bb.0.entry: | ||
| ; CHECK-NEXT: DBG_VALUE %stack.0.c, $noreg, ![[var:[0-9]+]], !DIExpression(DW_OP_deref), debug-location | ||
| ; CHECK: MOV64mi32 %stack.0.c, 1, $noreg, 0, $noreg, 5 | ||
| ;; No DBG_VALUE required because the stack location is still valid. | ||
|
|
||
| ; CHECK: MOV32mi %stack.0.c, 1, $noreg, 0, $noreg, 1 | ||
| ; CHECK-NEXT: DBG_VALUE $noreg, $noreg, ![[var]], !DIExpression(DW_OP_LLVM_fragment, 0, 32), debug-location | ||
| ;; This DBG_VALUE is added by the frag-agg pass because bits [32, 64) are still | ||
| ;; live in memory. | ||
| ; CHECK-NEXT: DBG_VALUE %stack.0.c, $noreg, ![[var]], !DIExpression(DW_OP_plus_uconst, 4, DW_OP_deref, DW_OP_LLVM_fragment, 32, 32) | ||
|
|
||
| ; CHECK: CALL64pcrel32 @d | ||
| ; CHECK-NEXT: ADJCALLSTACKUP64 | ||
| ; CHECK-NEXT: DBG_VALUE %stack.0.c, $noreg, ![[var]], !DIExpression(DW_OP_deref, DW_OP_LLVM_fragment, 0, 32), debug-location | ||
|
|
||
| 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" | ||
|
|
||
| ; Function Attrs: nounwind uwtable | ||
| define dso_local void @b() local_unnamed_addr #0 !dbg !7 { | ||
| entry: | ||
| %c = alloca i64, align 1, !DIAssignID !13 | ||
| call void @llvm.dbg.assign(metadata i1 undef, metadata !11, metadata !DIExpression(), metadata !13, metadata i64* %c, metadata !DIExpression()), !dbg !14 | ||
| call void @llvm.lifetime.start.p0i64(i64 1, i64* nonnull %c) #4, !dbg !15 | ||
| store i64 5, i64* %c, align 1, !dbg !16, !DIAssignID !20 | ||
| call void @llvm.dbg.assign(metadata i64 5, metadata !11, metadata !DIExpression(), metadata !20, metadata i64* %c, metadata !DIExpression()), !dbg !14 | ||
| tail call void (...) @d() #4, !dbg !21 | ||
|
|
||
| ; --- VV Hand written VV --- ; | ||
| %bc = bitcast i64* %c to i32* | ||
| store i32 1, i32* %bc, align 1, !dbg !16, !DIAssignID !31 | ||
| ;; Check that a dbg.value(undef, frag(0, 32)) is inserted here. The value of | ||
| ;; the fragment is "unknown". TODO: In this case the value of the fragment is | ||
| ;; still obviously 5; a future improvement could be to be smarter and work | ||
| ;; this out. But that's a lot of work for an uncommon case. | ||
| tail call void (...) @d() #4, !dbg !21 | ||
| call void @llvm.dbg.assign(metadata i32 1, metadata !11, metadata !DIExpression(DW_OP_LLVM_fragment, 0, 32), metadata !31, metadata i32* %bc, metadata !DIExpression()), !dbg !14 | ||
| ; --- AA Hand written AA --- ; | ||
|
|
||
| call void @a(i64* nonnull %c) #4, !dbg !22 | ||
| call void @llvm.lifetime.end.p0i64(i64 1, i64* nonnull %c) #4, !dbg !23 | ||
| ret void, !dbg !23 | ||
| } | ||
|
|
||
| declare void @llvm.lifetime.start.p0i64(i64 immarg, i64* nocapture) #1 | ||
| declare !dbg !24 dso_local void @d(...) local_unnamed_addr #2 | ||
| declare !dbg !27 dso_local void @a(i64*) local_unnamed_addr #2 | ||
| declare void @llvm.lifetime.end.p0i64(i64 immarg, i64* nocapture) #1 | ||
| declare void @llvm.dbg.assign(metadata, metadata, metadata, metadata, metadata, metadata) #3 | ||
|
|
||
| !llvm.dbg.cu = !{!0} | ||
| !llvm.module.flags = !{!3, !4, !5} | ||
| !llvm.ident = !{!6} | ||
|
|
||
| !0 = distinct !DICompileUnit(language: DW_LANG_C99, file: !1, producer: "clang version 12.0.0", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, enums: !2, splitDebugInlining: false, nameTableKind: None) | ||
| !1 = !DIFile(filename: "reduce.c", directory: "/") | ||
| !2 = !{} | ||
| !3 = !{i32 7, !"Dwarf Version", i32 4} | ||
| !4 = !{i32 2, !"Debug Info Version", i32 3} | ||
| !5 = !{i32 1, !"wchar_size", i32 4} | ||
| !6 = !{!"clang version 12.0.0"} | ||
| !7 = distinct !DISubprogram(name: "b", scope: !1, file: !1, line: 3, type: !8, scopeLine: 3, flags: DIFlagAllCallsDescribed, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !0, retainedNodes: !10) | ||
| !8 = !DISubroutineType(types: !9) | ||
| !9 = !{null} | ||
| !10 = !{!11} | ||
| !11 = !DILocalVariable(name: "c", scope: !7, file: !1, line: 4, type: !12) | ||
| !12 = !DIBasicType(name: "char", size: 64, encoding: DW_ATE_unsigned) | ||
| !13 = distinct !DIAssignID() | ||
| !14 = !DILocation(line: 0, scope: !7) | ||
| !15 = !DILocation(line: 4, column: 3, scope: !7) | ||
| !16 = !DILocation(line: 4, column: 8, scope: !7) | ||
| !20 = distinct !DIAssignID() | ||
| !21 = !DILocation(line: 5, column: 3, scope: !7) | ||
| !22 = !DILocation(line: 6, column: 3, scope: !7) | ||
| !23 = !DILocation(line: 7, column: 1, scope: !7) | ||
| !24 = !DISubprogram(name: "d", scope: !1, file: !1, line: 2, type: !25, spFlags: DISPFlagOptimized, retainedNodes: !2) | ||
| !25 = !DISubroutineType(types: !26) | ||
| !26 = !{null, null} | ||
| !27 = !DISubprogram(name: "a", scope: !1, file: !1, line: 1, type: !28, flags: DIFlagPrototyped, spFlags: DISPFlagOptimized, retainedNodes: !2) | ||
| !28 = !DISubroutineType(types: !29) | ||
| !29 = !{null, !30} | ||
| !30 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !12, size: 64) | ||
| !31 = distinct !DIAssignID() |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,83 @@ | ||
| ; RUN: llc %s -stop-after=finalize-isel -o - \ | ||
| ; RUN: -experimental-assignment-tracking \ | ||
| ; RUN: | FileCheck %s --implicit-check-not=DBG_VALUE | ||
|
|
||
| ;; Check that sandwiching instructions between a linked store and dbg.assign | ||
| ;; results in a dbg.value(prev_value) being inserted at the store, and a | ||
| ;; dbg.value(deref) at the dbg.assign. | ||
|
|
||
| ; CHECK: bb.0.entry: | ||
| ; CHECK-NEXT: DBG_VALUE %stack.0.c, $noreg, ![[var:[0-9]+]], !DIExpression(DW_OP_deref), debug-location | ||
| ; CHECK: MOV8mi %stack.0.c, 1, $noreg, 0, $noreg, 0 | ||
| ;; No DBG_VALUE required because the stack location is still valid. | ||
|
|
||
| ; CHECK: MOV8mi %stack.0.c, 1, $noreg, 0, $noreg, 1 | ||
| ; CHECK-NEXT: DBG_VALUE 0, $noreg, ![[var]], !DIExpression(), debug-location | ||
| ; CHECK: CALL64pcrel32 @d | ||
| ; CHECK-NEXT: ADJCALLSTACKUP64 | ||
| ; CHECK-NEXT: DBG_VALUE %stack.0.c, $noreg, ![[var]], !DIExpression(DW_OP_deref), debug-location | ||
|
|
||
| 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" | ||
|
|
||
| ; Function Attrs: nounwind uwtable | ||
| define dso_local void @b() local_unnamed_addr #0 !dbg !7 { | ||
| entry: | ||
| %c = alloca i8, align 1, !DIAssignID !13 | ||
| call void @llvm.dbg.assign(metadata i1 undef, metadata !11, metadata !DIExpression(), metadata !13, metadata i8* %c, metadata !DIExpression()), !dbg !14 | ||
| call void @llvm.lifetime.start.p0i8(i64 1, i8* nonnull %c) #4, !dbg !15 | ||
| store i8 0, i8* %c, align 1, !dbg !16, !DIAssignID !20 | ||
| call void @llvm.dbg.assign(metadata i8 0, metadata !11, metadata !DIExpression(), metadata !20, metadata i8* %c, metadata !DIExpression()), !dbg !14 | ||
| tail call void (...) @d() #4, !dbg !21 | ||
|
|
||
| ; --- VV Hand written VV --- ; | ||
| store i8 1, i8* %c, align 1, !dbg !16, !DIAssignID !31 | ||
| ; Check that a dbg.value(0) is inserted here. | ||
| tail call void (...) @d() #4, !dbg !21 | ||
| call void @llvm.dbg.assign(metadata i8 1, metadata !11, metadata !DIExpression(), metadata !31, metadata i8* %c, metadata !DIExpression()), !dbg !14 | ||
| ; --- AA Hand written AA --- ; | ||
|
|
||
| call void @a(i8* nonnull %c) #4, !dbg !22 | ||
| call void @llvm.lifetime.end.p0i8(i64 1, i8* nonnull %c) #4, !dbg !23 | ||
| ret void, !dbg !23 | ||
| } | ||
|
|
||
| declare void @llvm.lifetime.start.p0i8(i64 immarg, i8* nocapture) #1 | ||
| declare !dbg !24 dso_local void @d(...) local_unnamed_addr #2 | ||
| declare !dbg !27 dso_local void @a(i8*) local_unnamed_addr #2 | ||
| declare void @llvm.lifetime.end.p0i8(i64 immarg, i8* nocapture) #1 | ||
| declare void @llvm.dbg.assign(metadata, metadata, metadata, metadata, metadata, metadata) #3 | ||
|
|
||
| !llvm.dbg.cu = !{!0} | ||
| !llvm.module.flags = !{!3, !4, !5} | ||
| !llvm.ident = !{!6} | ||
|
|
||
| !0 = distinct !DICompileUnit(language: DW_LANG_C99, file: !1, producer: "clang version 12.0.0", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, enums: !2, splitDebugInlining: false, nameTableKind: None) | ||
| !1 = !DIFile(filename: "reduce.c", directory: "/") | ||
| !2 = !{} | ||
| !3 = !{i32 7, !"Dwarf Version", i32 4} | ||
| !4 = !{i32 2, !"Debug Info Version", i32 3} | ||
| !5 = !{i32 1, !"wchar_size", i32 4} | ||
| !6 = !{!"clang version 12.0.0"} | ||
| !7 = distinct !DISubprogram(name: "b", scope: !1, file: !1, line: 3, type: !8, scopeLine: 3, flags: DIFlagAllCallsDescribed, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !0, retainedNodes: !10) | ||
| !8 = !DISubroutineType(types: !9) | ||
| !9 = !{null} | ||
| !10 = !{!11} | ||
| !11 = !DILocalVariable(name: "c", scope: !7, file: !1, line: 4, type: !12) | ||
| !12 = !DIBasicType(name: "char", size: 8, encoding: DW_ATE_signed_char) | ||
| !13 = distinct !DIAssignID() | ||
| !14 = !DILocation(line: 0, scope: !7) | ||
| !15 = !DILocation(line: 4, column: 3, scope: !7) | ||
| !16 = !DILocation(line: 4, column: 8, scope: !7) | ||
| !20 = distinct !DIAssignID() | ||
| !21 = !DILocation(line: 5, column: 3, scope: !7) | ||
| !22 = !DILocation(line: 6, column: 3, scope: !7) | ||
| !23 = !DILocation(line: 7, column: 1, scope: !7) | ||
| !24 = !DISubprogram(name: "d", scope: !1, file: !1, line: 2, type: !25, spFlags: DISPFlagOptimized, retainedNodes: !2) | ||
| !25 = !DISubroutineType(types: !26) | ||
| !26 = !{null, null} | ||
| !27 = !DISubprogram(name: "a", scope: !1, file: !1, line: 1, type: !28, flags: DIFlagPrototyped, spFlags: DISPFlagOptimized, retainedNodes: !2) | ||
| !28 = !DISubroutineType(types: !29) | ||
| !29 = !{null, !30} | ||
| !30 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !12, size: 64) | ||
| !31 = distinct !DIAssignID() |