[DebugInfo] Nerf placeDbgValues, with prejudice
authorJeremy Morse <jeremy.morse@sony.com>
Mon, 9 Dec 2019 11:26:44 +0000 (11:26 +0000)
committerJeremy Morse <jeremy.morse@sony.com>
Mon, 9 Dec 2019 12:52:10 +0000 (12:52 +0000)
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

llvm/include/llvm/CodeGen/MachineInstr.h
llvm/lib/CodeGen/CodeGenPrepare.cpp
llvm/test/DebugInfo/COFF/register-variables.ll
llvm/test/DebugInfo/NVPTX/debug-info.ll
llvm/test/DebugInfo/X86/DW_AT_location-reference.ll
llvm/test/DebugInfo/X86/PR37234.ll
llvm/test/DebugInfo/X86/codegenprep-addrsink.ll
llvm/test/tools/llvm-locstats/locstats.ll

index 55457aa..a602445 100644 (file)
@@ -1651,7 +1651,8 @@ public:
   /// 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
index a041808..a683fcf 100644 (file)
@@ -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;
index e67c62a..fe73f91 100644 (file)
@@ -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.*]]:
 ; 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    [[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
 ; 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 {
 ; 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 {
 ; 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 {
index 9a572ff..d6cb809 100644 (file)
@@ -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 Ltmp                          // 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
index 43fde0b..74b0afb 100644 (file)
@@ -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"
index a0c8b91..04005ca 100644 (file)
@@ -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]]
index a3a80e1..137316d 100644 (file)
@@ -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
@@ -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
index 394d512..911abf5 100644 (file)
@@ -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%
 ;