The "join" method in LiveDebugValues does not attempt to join unseen predecessor blocks if their out-locations aren't yet initialized, instead the block should be re-visited later to see if any locations have changed validity. However, because the set of blocks were all being "process"'d once before "join" saw them, that logic in "join" was actually ignoring legitimate out-locations on the first pass through. This meant that some invalidated locations were not removed from the head of loops, allowing illegal locations to persist. Fix this by removing the run of "process" before the main join/process loop in ExtendRanges. Now the unseen predecessors that "join" skips truly are uninitialized, and we come back to the block at a later time to re-run "join", see the @baz function added. This also fixes another fault where stack/register transfers in the entry block (or any other before-any-loop-block) had their tranfers initially ignored, and were then never revisited. The MIR test added tests for this behaviour. XFail a test that exposes another bug; a fix for this is coming in D66895. Differential Revision: https://reviews.llvm.org/D66663 llvm-svn: 370328
123 lines
4.0 KiB
YAML
123 lines
4.0 KiB
YAML
# RUN: llc %s -o - -run-pass=livedebugvalues -mtriple=x86_64-unknown-unknown | FileCheck %s
|
|
#
|
|
# In this lightly modified test case, the transfer in the entry block from
|
|
# geti32's return value in $eax to the non-volatile $ebx should be recognized,
|
|
# and propagated throughout the whole function.
|
|
#
|
|
# CHECK-LABEL: bb.0.entry
|
|
# CHECK: DBG_VALUE $eax
|
|
# CHECK: DBG_VALUE $ebx
|
|
# CHECK-LABEL: bb.1.loop2
|
|
# CHECK: DBG_VALUE $ebx
|
|
# CHECK-LABEL: bb.2.loop
|
|
# CHECK: DBG_VALUE $ebx
|
|
# CHECK-LABEL: bb.3.exit
|
|
# CHECK: DBG_VALUE $ebx
|
|
--- |
|
|
; ModuleID = 'asdf'
|
|
source_filename = "asdf.ll"
|
|
target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
|
|
target triple = "x86_64-unknown-unknown"
|
|
|
|
@glob = global i32 0
|
|
|
|
declare i1 @booler()
|
|
|
|
declare i32 @geti32()
|
|
|
|
declare void @escape(i32)
|
|
|
|
; Function Attrs: nounwind readnone speculatable willreturn
|
|
declare void @llvm.dbg.value(metadata, metadata, metadata)
|
|
|
|
define i32 @foo() !dbg !4 {
|
|
entry:
|
|
%bar = call i32 @geti32(), !dbg !10
|
|
call void @llvm.dbg.value(metadata i32 %bar, metadata !9, metadata !DIExpression()), !dbg !10
|
|
br label %loop
|
|
|
|
loop: ; preds = %loop2, %entry
|
|
call void @escape(i32 %bar)
|
|
%retval = call i1 @booler(), !dbg !10
|
|
br i1 %retval, label %loop2, label %exit
|
|
|
|
loop2: ; preds = %loop
|
|
store i32 %bar, i32* @glob
|
|
br label %loop
|
|
|
|
exit: ; preds = %loop
|
|
ret i32 %bar
|
|
}
|
|
|
|
; Function Attrs: nounwind
|
|
declare void @llvm.stackprotector(i8*, i8**)
|
|
|
|
!llvm.module.flags = !{!0, !1}
|
|
!llvm.dbg.cu = !{!2}
|
|
|
|
!0 = !{i32 2, !"Debug Info Version", i32 3}
|
|
!1 = !{i32 2, !"Dwarf Version", i32 4}
|
|
!2 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus, file: !3, producer: "beards", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug)
|
|
!3 = !DIFile(filename: "bees.cpp", directory: ".")
|
|
!4 = distinct !DISubprogram(name: "nope", scope: !3, file: !3, line: 1, type: !5, spFlags: DISPFlagDefinition, unit: !2, retainedNodes: !8)
|
|
!5 = !DISubroutineType(types: !6)
|
|
!6 = !{!7}
|
|
!7 = !DIBasicType(name: "int", size: 32, align: 32, encoding: DW_ATE_signed)
|
|
!8 = !{!9}
|
|
!9 = !DILocalVariable(name: "toast", scope: !4, file: !3, line: 1, type: !7)
|
|
!10 = !DILocation(line: 1, scope: !4)
|
|
|
|
...
|
|
---
|
|
name: foo
|
|
tracksRegLiveness: true
|
|
frameInfo:
|
|
stackSize: 8
|
|
offsetAdjustment: -8
|
|
adjustsStack: true
|
|
hasCalls: true
|
|
cvBytesOfCalleeSavedRegisters: 8
|
|
fixedStack:
|
|
- { id: 0, type: spill-slot, offset: -16, size: 8, alignment: 16, stack-id: default,
|
|
callee-saved-register: '$rbx', callee-saved-restored: true, debug-info-variable: '',
|
|
debug-info-expression: '', debug-info-location: '' }
|
|
stack: []
|
|
body: |
|
|
bb.0.entry:
|
|
successors: %bb.1(0x80000000)
|
|
liveins: $rbx
|
|
|
|
frame-setup PUSH64r killed $rbx, implicit-def $rsp, implicit $rsp, debug-location !10
|
|
CFI_INSTRUCTION def_cfa_offset 16
|
|
CFI_INSTRUCTION offset $rbx, -16
|
|
CALL64pcrel32 @geti32, csr_64, implicit $rsp, implicit $ssp, implicit-def $rsp, implicit-def $ssp, implicit-def $eax, debug-location !10
|
|
DBG_VALUE $eax, $noreg, !9, !DIExpression(), debug-location !10
|
|
$ebx = MOV32rr killed $eax, debug-location !10
|
|
JMP_1 %bb.1
|
|
|
|
bb.1.loop2:
|
|
successors: %bb.2
|
|
liveins: $ebx
|
|
|
|
MOV32mr $rip, 1, $noreg, @glob, $noreg, renamable $ebx :: (store 4 into @glob)
|
|
|
|
bb.2.loop:
|
|
successors: %bb.1, %bb.3
|
|
liveins: $ebx
|
|
|
|
$edi = MOV32rr $ebx
|
|
CALL64pcrel32 @escape, csr_64, implicit $rsp, implicit $ssp, implicit killed $edi, implicit-def $rsp, implicit-def $ssp
|
|
CALL64pcrel32 @booler, csr_64, implicit $rsp, implicit $ssp, implicit-def $rsp, implicit-def $ssp, implicit-def $al, debug-location !10
|
|
TEST8ri killed renamable $al, 1, implicit-def $eflags
|
|
JCC_1 %bb.1, 5, implicit $eflags
|
|
|
|
bb.3.exit:
|
|
liveins: $ebx
|
|
|
|
$eax = MOV32rr killed $ebx
|
|
$rbx = frame-destroy POP64r implicit-def $rsp, implicit $rsp
|
|
CFI_INSTRUCTION def_cfa_offset 8
|
|
RETQ $eax
|
|
|
|
...
|