Skip to content

Commit

Permalink
[DebugInfo] Nerf placeDbgValues, with prejudice
Browse files Browse the repository at this point in the history
CodeGenPrepare::placeDebugValues moves variable location intrinsics to be
immediately after the Value they refer to. This makes tracking of locations
very easy; but it changes the order in which assignments appear to the
debugger, from the source programs order to the order in which the
optimised program computes values. This then leads to PR43986 and PR38754,
where variable locations that were in a conditional block are made
unconditional, which is highly misleading.

This patch adjusts placeDbgValues to only re-order variable location
intrinsics if they use a Value before it is defined, significantly reducing
the damage that it does. This is still not 100% safe, but the rest of
CodeGenPrepare needs polishing to correctly update debug info when
optimisations are performed to fully fix this.

This will probably break downstream debuginfo tests -- if the
instruction-stream position of variable location changes isn't the focus of
the test, an easy fix should be to manually apply placeDbgValues' behaviour
to the failing tests, moving dbg.value intrinsics next to SSA variable
definitions thus:

  %foo = inst1
  %bar = ...
  %baz = ...
  void call @llvm.dbg.value(metadata i32 %foo, ...

to

  %foo = inst1
  void call @llvm.dbg.value(metadata i32 %foo, ...
  %bar = ...
  %baz = ...

This should return your test to exercising whatever it was testing before.

Differential Revision: https://reviews.llvm.org/D58453
  • Loading branch information
jmorse committed Dec 9, 2019
1 parent f7e7a5f commit 00e2388
Show file tree
Hide file tree
Showing 8 changed files with 61 additions and 72 deletions.
3 changes: 2 additions & 1 deletion llvm/include/llvm/CodeGen/MachineInstr.h
Original file line number Diff line number Diff line change
Expand Up @@ -1651,7 +1651,8 @@ class MachineInstr
/// Add all implicit def and use operands to this instruction.
void addImplicitDefUseOperands(MachineFunction &MF);

/// Scan instructions following MI and collect any matching DBG_VALUEs.
/// Scan instructions immediately following MI and collect any matching
/// DBG_VALUEs.
void collectDebugValues(SmallVectorImpl<MachineInstr *> &DbgValues);

/// Find all DBG_VALUEs that point to the register def in this instruction
Expand Down
58 changes: 31 additions & 27 deletions llvm/lib/CodeGen/CodeGenPrepare.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7230,42 +7230,46 @@ bool CodeGenPrepare::fixupDbgValue(Instruction *I) {
return false;
}

// llvm.dbg.value is far away from the value then iSel may not be able
// handle it properly. iSel will drop llvm.dbg.value if it can not
// find a node corresponding to the value.
// A llvm.dbg.value may be using a value before its definition, due to
// optimizations in this pass and others. Scan for such dbg.values, and rescue
// them by moving the dbg.value to immediately after the value definition.
// FIXME: Ideally this should never be necessary, and this has the potential
// to re-order dbg.value intrinsics.
bool CodeGenPrepare::placeDbgValues(Function &F) {
bool MadeChange = false;
DominatorTree DT(F);

for (BasicBlock &BB : F) {
Instruction *PrevNonDbgInst = nullptr;
for (BasicBlock::iterator BI = BB.begin(), BE = BB.end(); BI != BE;) {
Instruction *Insn = &*BI++;
DbgValueInst *DVI = dyn_cast<DbgValueInst>(Insn);
// Leave dbg.values that refer to an alloca alone. These
// intrinsics describe the address of a variable (= the alloca)
// being taken. They should not be moved next to the alloca
// (and to the beginning of the scope), but rather stay close to
// where said address is used.
if (!DVI || (DVI->getValue() && isa<AllocaInst>(DVI->getValue()))) {
PrevNonDbgInst = Insn;
if (!DVI)
continue;
}

Instruction *VI = dyn_cast_or_null<Instruction>(DVI->getValue());
if (VI && VI != PrevNonDbgInst && !VI->isTerminator()) {
// If VI is a phi in a block with an EHPad terminator, we can't insert
// after it.
if (isa<PHINode>(VI) && VI->getParent()->getTerminator()->isEHPad())
continue;
LLVM_DEBUG(dbgs() << "Moving Debug Value before :\n"
<< *DVI << ' ' << *VI);
DVI->removeFromParent();
if (isa<PHINode>(VI))
DVI->insertBefore(&*VI->getParent()->getFirstInsertionPt());
else
DVI->insertAfter(VI);
MadeChange = true;
++NumDbgValueMoved;
}

if (!VI || VI->isTerminator())
continue;

// If VI is a phi in a block with an EHPad terminator, we can't insert
// after it.
if (isa<PHINode>(VI) && VI->getParent()->getTerminator()->isEHPad())
continue;

// If the defining instruction dominates the dbg.value, we do not need
// to move the dbg.value.
if (DT.dominates(VI, DVI))
continue;

LLVM_DEBUG(dbgs() << "Moving Debug Value before :\n"
<< *DVI << ' ' << *VI);
DVI->removeFromParent();
if (isa<PHINode>(VI))
DVI->insertBefore(&*VI->getParent()->getFirstInsertionPt());
else
DVI->insertAfter(VI);
MadeChange = true;
++NumDbgValueMoved;
}
}
return MadeChange;
Expand Down
42 changes: 14 additions & 28 deletions llvm/test/DebugInfo/COFF/register-variables.ll
Original file line number Diff line number Diff line change
Expand Up @@ -32,9 +32,6 @@
; ASM: #DEBUG_VALUE: f:p <- $esi
; ASM: callq getint
; ASM: [[after_getint:\.Ltmp.*]]:
; ASM: #DEBUG_VALUE: a <- $eax
; ASM: #DEBUG_VALUE: inlineinc:a <- $eax
; ASM: #DEBUG_VALUE: c <- $eax
; ASM: testl %esi, %esi
; ASM: je .LBB0_2
; ASM: [[after_je:\.Ltmp.*]]:
Expand All @@ -45,35 +42,38 @@
; ASM: addl $1, %eax
; ASM: [[after_inc_eax:\.Ltmp.*]]:
; ASM: #DEBUG_VALUE: inlineinc:b <- $eax
; ASM: #DEBUG_VALUE: b <- $eax
; ASM: addl $1, x(%rip)
; ASM: [[after_if:\.Ltmp.*]]:
; ASM: .LBB0_2: # %if.else
; ASM: #DEBUG_VALUE: f:p <- $esi
; ASM: #DEBUG_VALUE: c <- $eax
; ASM: movl %eax, %ecx
; ASM: addq $32, %rsp
; ASM: popq %rsi
; ASM: [[func_end:\.Ltmp.*]]:
; ASM: jmp putint # TAILCALL
; ASM: [[func_finished:\.Ltmp.*]]:

; ASM: .short 4414 # Record kind: S_LOCAL
; ASM: .asciz "p"
; ASM: .cv_def_range .Lfunc_begin0 [[p_ecx_esi]], reg, 18
; ASM: .cv_def_range [[p_ecx_esi]] [[func_end]], reg, 23
; ASM: .short 4414 # Record kind: S_LOCAL
; ASM: .asciz "c"
; ASM: .cv_def_range [[after_getint]] [[after_je]], reg, 17
; ASM: .cv_def_range [[after_if]] [[func_finished]], reg, 17
; ASM: .short 4414 # Record kind: S_LOCAL
; ASM: .asciz "a"
; ASM: .cv_def_range [[after_getint]] [[after_inc_eax]], reg, 17
; ASM: .cv_def_range [[after_je]] [[after_inc_eax]], reg, 17
; ASM: .short 4414 # Record kind: S_LOCAL
; ASM: .asciz "b"
; ASM: .cv_def_range [[after_inc_eax]] [[after_if]], reg, 17
; ASM: .cv_def_range [[after_if]] [[after_if]], reg, 17

; Note: "b" is a victim of tail de-duplication / branch folding.

; ASM: .short 4429 # Record kind: S_INLINESITE
; ASM: .short 4414 # Record kind: S_LOCAL
; ASM: .asciz "a"
; ASM: .cv_def_range [[after_getint]] [[after_inc_eax]], reg, 17
; ASM: .cv_def_range [[after_je]] [[after_inc_eax]], reg, 17
; ASM: .short 4414 # Record kind: S_LOCAL
; ASM: .asciz "b"
; ASM: .cv_def_range [[after_inc_eax]] [[after_if]], reg, 17
Expand Down Expand Up @@ -116,9 +116,9 @@
; OBJ: DefRangeRegisterSym {
; OBJ: Register: EAX (0x11)
; OBJ: LocalVariableAddrRange {
; OBJ: OffsetStart: .text+0xC
; OBJ: OffsetStart: .text+0x1A
; OBJ: ISectStart: 0x0
; OBJ: Range: 0x4
; OBJ: Range: 0xC
; OBJ: }
; OBJ: }
; OBJ: LocalSym {
Expand All @@ -130,23 +130,9 @@
; OBJ: DefRangeRegisterSym {
; OBJ: Register: EAX (0x11)
; OBJ: LocalVariableAddrRange {
; OBJ: OffsetStart: .text+0xC
; OBJ: OffsetStart: .text+0x10
; OBJ: ISectStart: 0x0
; OBJ: Range: 0x7
; OBJ: }
; OBJ: }
; OBJ: LocalSym {
; OBJ: Type: int (0x74)
; OBJ: Flags [ (0x0)
; OBJ: ]
; OBJ: VarName: b
; OBJ: }
; OBJ: DefRangeRegisterSym {
; OBJ: Register: EAX (0x11)
; OBJ: MayHaveNoName: 0
; OBJ: OffsetStart: .text+0x13
; OBJ: ISectStart: 0x0
; OBJ: Range: 0x7
; OBJ: Range: 0x3
; OBJ: }
; OBJ: }
; OBJ: InlineSiteSym {
Expand All @@ -164,9 +150,9 @@
; OBJ: DefRangeRegisterSym {
; OBJ: Register: EAX (0x11)
; OBJ: LocalVariableAddrRange {
; OBJ: OffsetStart: .text+0xC
; OBJ: OffsetStart: .text+0x10
; OBJ: ISectStart: 0x0
; OBJ: Range: 0x7
; OBJ: Range: 0x3
; OBJ: }
; OBJ: }
; OBJ: LocalSym {
Expand Down
4 changes: 2 additions & 2 deletions llvm/test/DebugInfo/NVPTX/debug-info.ll
Original file line number Diff line number Diff line change
Expand Up @@ -8388,8 +8388,8 @@ if.end: ; preds = %if.then, %entry
; CHECK-NEXT: .b8 37 // DW_AT_call_column
; CHECK-NEXT: .b8 43 // Abbrev [43] 0x2711:0x23 DW_TAG_inlined_subroutine
; CHECK-NEXT: .b32 9791 // DW_AT_abstract_origin
; CHECK-NEXT: .b64 Ltmp10 // DW_AT_low_pc
; CHECK-NEXT: .b64 Ltmp11 // DW_AT_high_pc
; CHECK-NEXT: .b64 Ltmp9 // DW_AT_low_pc
; CHECK-NEXT: .b64 Ltmp10 // DW_AT_high_pc
; CHECK-NEXT: .b8 12 // DW_AT_call_file
; CHECK-NEXT: .b8 8 // DW_AT_call_line
; CHECK-NEXT: .b8 5 // DW_AT_call_column
Expand Down
4 changes: 3 additions & 1 deletion llvm/test/DebugInfo/X86/DW_AT_location-reference.ll
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,9 @@
; CHECK: .debug_info contents:
; CHECK: DW_TAG_variable
; CHECK-NEXT: DW_AT_location [DW_FORM_sec_offset] (0x00000000
; Check that the location contains only 2 ranges.
; Check that the location contains only 4 ranges.
; CHECK-NEXT: [0x{{[0-9a-f]*}}, 0x{{[0-9a-f]*}})
; CHECK-NEXT: [0x{{[0-9a-f]*}}, 0x{{[0-9a-f]*}})
; CHECK-NEXT: [0x{{[0-9a-f]*}}, 0x{{[0-9a-f]*}})
; CHECK-NEXT: [0x{{[0-9a-f]*}}, 0x{{[0-9a-f]*}}){{.*}})
; CHECK-NEXT: DW_AT_name {{.*}} "x"
Expand Down
3 changes: 1 addition & 2 deletions llvm/test/DebugInfo/X86/PR37234.ll
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,8 @@

; CHECK-LABEL: # %bb.{{.*}}:
; CHECK: #DEBUG_VALUE: main:aa <- 0
; CHECK: #DEBUG_VALUE: main:aa <- $[[REG:[0-9a-z]+]]
; CHECK: .LBB0_1:
; CHECK: #DEBUG_VALUE: main:aa <- $[[REG]]
; CHECK: #DEBUG_VALUE: main:aa <- $[[REG:[0-9a-z]+]]
; CHECK: je .LBB0_4
; CHECK: # %bb.{{.*}}:
; CHECK: #DEBUG_VALUE: main:aa <- $[[REG]]
Expand Down
15 changes: 6 additions & 9 deletions llvm/test/DebugInfo/X86/codegenprep-addrsink.ll
Original file line number Diff line number Diff line change
Expand Up @@ -9,17 +9,12 @@
; memory instruction. Test that the one before does _not_ get updated (as that
; would either make it use-before-def or shift when the variable appears), and
; that the dbg.value after the memory instruction does get updated.
;
; Due to placeDbgValues, the dbg.values currently get shifted up a few
; instructions.

define dso_local i8 @foo(i32 *%p, i32 %cond) !dbg !7 {
entry:
; The first dbg.value of %arith, in the 'next' block, will be moved up here
; by placeDbgValues,
; There should be no dbg.values in this block.
; CHECK-LABEL: entry:
; CHECK: dbg.value(metadata i8* %arith, metadata ![[DIVAR:[0-9]+]],
; CHECK-SAME: metadata !DIExpression()
; CHECK-NOT: dbg.value
%casted = bitcast i32 *%p to i8*
%arith = getelementptr i8, i8 *%casted, i32 3
%load1 = load i8, i8 *%arith
Expand All @@ -30,12 +25,14 @@ next:
; Address calcs should be duplicated into this block. One dbg.value should be
; updated, and the other should not.
; CHECK-LABEL: next:
; CHECK: %[[CASTVAR:[0-9a-zA-Z]+]] = bitcast i32* %p to i8*
; CHECK: dbg.value(metadata i8* %arith, metadata ![[DIVAR:[0-9]+]],
; CHECK-SAME: metadata !DIExpression()
; CHECK-NEXT: %[[CASTVAR:[0-9a-zA-Z]+]] = bitcast i32* %p to i8*
; CHECK-NEXT: %[[GEPVAR:[0-9a-zA-Z]+]] = getelementptr i8, i8* %[[CASTVAR]],
; CHECK-SAME: i64 3
; CHECK-NEXT: %loaded = load i8, i8* %[[GEPVAR]]
; CHECK-NEXT: call void @llvm.dbg.value(metadata i8* %[[GEPVAR]],
; CHECK-SAME: metadata ![[DIVAR]],
; CHECK-NEXT: %loaded = load i8, i8* %[[GEPVAR]]
call void @llvm.dbg.value(metadata i8 *%arith, metadata !12, metadata !DIExpression()), !dbg !14
%loaded = load i8, i8 *%arith
call void @llvm.dbg.value(metadata i8 *%arith, metadata !12, metadata !DIExpression()), !dbg !14
Expand Down
4 changes: 2 additions & 2 deletions llvm/test/tools/llvm-locstats/locstats.ll
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,9 @@
; LOCSTATS: 30-39% 0 0%
; LOCSTATS: 40-49% 1 11%
; LOCSTATS: 50-59% 1 11%
; LOCSTATS: 60-69% 1 11%
; LOCSTATS: 60-69% 0 0%
; LOCSTATS: 70-79% 0 0%
; LOCSTATS: 80-89% 2 22%
; LOCSTATS: 80-89% 3 33%
; LOCSTATS: 90-99% 1 11%
; LOCSTATS: 100% 2 22%
;
Expand Down

0 comments on commit 00e2388

Please sign in to comment.