| # RUN: llc -mtriple=x86_64-unknown-unknown %s -o - -run-pass=simple-register-coalescing | FileCheck %s |
| # PR40010: DBG_VALUEs do not contribute to the liveness of virtual registers, |
| # and the register coalescer would merge new live values on top of DBG_VALUEs, |
| # leading to them presenting new (wrong) values to the debugger. Test that |
| # when out of liveness, coalescing will mark DBG_VALUEs in non-live locations |
| # as undef. |
| --- | |
| ; ModuleID = './test.ll' |
| source_filename = "./test.ll" |
| target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" |
| |
| ; Function Attrs: nounwind readnone speculatable |
| declare void @llvm.dbg.value(metadata, metadata, metadata) #0 |
| |
| ; Original IR source here: |
| define i32 @test(i32* %pin) { |
| entry: |
| br label %start.test1 |
| |
| start.test1: ; preds = %start, %entry |
| %foo = phi i32 [ 0, %entry ], [ %bar, %start.test1 ] |
| %baz = load i32, i32* %pin, align 1 |
| %qux = xor i32 %baz, 1234 |
| %bar = add i32 %qux, %foo |
| call void @llvm.dbg.value(metadata i32 %foo, metadata !3, metadata !DIExpression()), !dbg !5 |
| %cmp = icmp ugt i32 %bar, 1000000 |
| br i1 %cmp, label %leave, label %start.test1 |
| |
| leave: ; preds = %start |
| ret i32 %bar |
| } |
| |
| ; Stubs to appease the MIR parser |
| define i32 @test2(i32* %pin) { |
| entry: |
| ret i32 0 |
| start.test2: |
| ret i32 0 |
| leave: |
| ret i32 0 |
| } |
| |
| ; Function Attrs: nounwind |
| declare void @llvm.stackprotector(i8*, i8**) #1 |
| |
| attributes #0 = { nounwind readnone speculatable } |
| attributes #1 = { nounwind } |
| |
| !llvm.module.flags = !{!0} |
| !llvm.dbg.cu = !{!1} |
| |
| !0 = !{i32 2, !"Debug Info Version", i32 3} |
| !1 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus, file: !2, producer: "beards", isOptimized: true, runtimeVersion: 4, emissionKind: FullDebug) |
| !2 = !DIFile(filename: "bees.cpp", directory: "") |
| !3 = !DILocalVariable(name: "bees", scope: !4) |
| !4 = distinct !DISubprogram(name: "nope", scope: !1, file: !2, line: 1, spFlags: DISPFlagDefinition, unit: !1) |
| !5 = !DILocation(line: 0, scope: !4) |
| |
| ... |
| --- |
| name: test |
| tracksRegLiveness: true |
| body: | |
| bb.0.entry: |
| successors: %bb.1(0x80000000) |
| liveins: $rdi |
| |
| %2:gr64 = COPY killed $rdi |
| %3:gr32 = MOV32r0 implicit-def dead $eflags |
| %4:gr32 = MOV32ri 1234 |
| %7:gr32 = COPY killed %3 |
| |
| bb.1.start.test1: |
| successors: %bb.2(0x04000000), %bb.1(0x7c000000) |
| |
| ; CHECK-LABEL: name: test |
| ; |
| ; We currently expect %1 and %0 to merge into %7 |
| ; |
| ; CHECK: %[[REG1:[0-9]+]]:gr32 = MOV32rm |
| ; CHECK-NEXT: %[[REG2:[0-9]+]]:gr32 = XOR32rr %[[REG1]] |
| ; CHECK-NEXT: %[[REG3:[0-9]+]]:gr32 = ADD32rr %[[REG3]], %[[REG2]] |
| ; CHECK-NEXT: DBG_VALUE $noreg |
| |
| %0:gr32 = COPY killed %7 |
| %8:gr32 = MOV32rm %2, 1, $noreg, 0, $noreg :: (load 4 from %ir.pin, align 1) |
| %5:gr32 = COPY killed %8 |
| %5:gr32 = XOR32rr %5, %4, implicit-def dead $eflags |
| %1:gr32 = COPY killed %0 |
| %1:gr32 = ADD32rr %1, killed %5, implicit-def dead $eflags |
| DBG_VALUE %0, $noreg, !3, !DIExpression(), debug-location !5 |
| CMP32ri %1, 1000001, implicit-def $eflags |
| %7:gr32 = COPY %1 |
| JCC_1 %bb.1, 2, implicit killed $eflags |
| JMP_1 %bb.2 |
| |
| bb.2.leave: |
| $eax = COPY killed %1 |
| RET 0, killed $eax |
| |
| ... |
| --- |
| name: test2 |
| tracksRegLiveness: true |
| body: | |
| bb.0.entry: |
| successors: %bb.1(0x80000000) |
| liveins: $rdi |
| |
| %2:gr64 = COPY killed $rdi |
| %3:gr32 = MOV32r0 implicit-def dead $eflags |
| %4:gr32 = MOV32ri 1234 |
| %7:gr32 = COPY killed %3 |
| |
| bb.1.start.test2: |
| successors: %bb.2(0x04000000), %bb.1(0x7c000000) |
| |
| ; CHECK-LABEL: name: test2 |
| ; |
| ; %0 should be merged into %7, but as %0 is live at this location the |
| ; DBG_VALUE should be preserved and point at the operand of ADD32rr. |
| ; RegisterCoalescer resolves %0 as CR_Erase: %0 is a redundant copy and |
| ; can be erased. |
| ; |
| ; CHECK: %[[REG11:[0-9]+]]:gr32 = MOV32rm |
| ; CHECK-NEXT: %[[REG12:[0-9]+]]:gr32 = XOR32rr %[[REG11]] |
| ; CHECK-NEXT: DBG_VALUE %[[REG13:[0-9]+]] |
| ; CHECK-NEXT: %[[REG13]]:gr32 = ADD32rr %[[REG13]], %[[REG12]] |
| |
| %0:gr32 = COPY killed %7 |
| %8:gr32 = MOV32rm %2, 1, $noreg, 0, $noreg :: (load 4 from %ir.pin, align 1) |
| %8:gr32 = XOR32rr %8, %4, implicit-def dead $eflags |
| DBG_VALUE %0, $noreg, !3, !DIExpression(), debug-location !5 |
| %0:gr32 = ADD32rr %0, killed %8, implicit-def dead $eflags |
| CMP32ri %0, 1000001, implicit-def $eflags |
| %7:gr32 = COPY %0 |
| JCC_1 %bb.1, 2, implicit killed $eflags |
| JMP_1 %bb.2 |
| |
| bb.2.leave: |
| $eax = COPY killed %7 |
| RET 0, killed $eax |
| |
| ... |
| |