<div dir="ltr">We're seeing a pretty serious compile-time regression that bisects cleanly to this patch, e.g. large files that previously took a minute or two to compile are now taking > 15 minutes (and timing out).<div><br><div>Is it ok to temporarily revert this patch until we can provide a repro?</div></div></div><br><div class="gmail_quote"><div dir="ltr" class="gmail_attr">On Mon, Apr 29, 2019 at 2:11 AM Jeremy Morse via llvm-commits <<a href="mailto:llvm-commits@lists.llvm.org">llvm-commits@lists.llvm.org</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">Author: jmorse<br>
Date: Mon Apr 29 02:13:16 2019<br>
New Revision: 359426<br>
<br>
URL: <a href="http://llvm.org/viewvc/llvm-project?rev=359426&view=rev" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project?rev=359426&view=rev</a><br>
Log:<br>
[DebugInfo] Terminate more location-list ranges at the end of blocks<br>
<br>
This patch fixes PR40795, where constant-valued variable locations can<br>
"leak" into blocks placed at higher addresses. The root of this is that<br>
DbgEntityHistoryCalculator terminates all register variable locations at<br>
the end of each block, but not constant-value variable locations.<br>
<br>
Fixing this requires constant-valued DBG_VALUE instructions to be<br>
broadcast into all blocks where the variable location remains valid, as<br>
documented in the LiveDebugValues section of SourceLevelDebugging.rst,<br>
and correct termination in DbgEntityHistoryCalculator.<br>
<br>
Differential Revision: <a href="https://reviews.llvm.org/D59431" rel="noreferrer" target="_blank">https://reviews.llvm.org/D59431</a><br>
<br>
Added:<br>
    llvm/trunk/test/DebugInfo/X86/live-debug-values-constprop.mir<br>
Modified:<br>
    llvm/trunk/lib/CodeGen/AsmPrinter/DbgEntityHistoryCalculator.cpp<br>
    llvm/trunk/lib/CodeGen/LiveDebugValues.cpp<br>
    llvm/trunk/test/DebugInfo/COFF/pieces.ll<br>
    llvm/trunk/test/DebugInfo/MIR/AArch64/implicit-def-dead-scope.mir<br>
    llvm/trunk/test/DebugInfo/X86/fission-ranges.ll<br>
<br>
Modified: llvm/trunk/lib/CodeGen/AsmPrinter/DbgEntityHistoryCalculator.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/AsmPrinter/DbgEntityHistoryCalculator.cpp?rev=359426&r1=359425&r2=359426&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/AsmPrinter/DbgEntityHistoryCalculator.cpp?rev=359426&r1=359425&r2=359426&view=diff</a><br>
==============================================================================<br>
--- llvm/trunk/lib/CodeGen/AsmPrinter/DbgEntityHistoryCalculator.cpp (original)<br>
+++ llvm/trunk/lib/CodeGen/AsmPrinter/DbgEntityHistoryCalculator.cpp Mon Apr 29 02:13:16 2019<br>
@@ -352,17 +352,43 @@ void llvm::calculateDbgEntityHistory(con<br>
       }<br>
     }<br>
<br>
-    // Make sure locations for register-described variables are valid only<br>
-    // until the end of the basic block (unless it's the last basic block, in<br>
-    // which case let their liveness run off to the end of the function).<br>
+    // Make sure locations for all variables are valid only until the end of<br>
+    // the basic block (unless it's the last basic block, in which case let<br>
+    // their liveness run off to the end of the function).<br>
     if (!MBB.empty() && &MBB != &MF->back()) {<br>
-      for (auto I = RegVars.begin(), E = RegVars.end(); I != E;) {<br>
-        auto CurElem = I++; // CurElem can be erased below.<br>
-        if (TRI->isVirtualRegister(CurElem->first) ||<br>
-            ChangingRegs.test(CurElem->first))<br>
-          clobberRegisterUses(RegVars, CurElem, DbgValues, LiveEntries,<br>
-                              MBB.back());<br>
+      // Iterate over all variables that have open debug values.<br>
+      SmallSet<unsigned, 8> RegsToClobber;<br>
+      for (auto &Pair : LiveEntries) {<br>
+        // Iterate over history entries for all open fragments.<br>
+        SmallVector<EntryIndex, 8> IdxesToRemove;<br>
+        for (EntryIndex Idx : Pair.second) {<br>
+          DbgValueHistoryMap::Entry &Ent = DbgValues.getEntry(Pair.first, Idx);<br>
+          assert(Ent.isDbgValue() && !Ent.isClosed());<br>
+          const MachineInstr *DbgValue = Ent.getInstr();<br>
+<br>
+          // If this is a register or indirect DBG_VALUE, apply some futher<br>
+          // tests to see if we should clobber it. Perform the clobbering<br>
+          // later though, to keep LiveEntries iteration stable.<br>
+          if (DbgValue->getOperand(0).isReg()) {<br>
+            unsigned RegNo = DbgValue->getOperand(0).getReg();<br>
+            if (TRI->isVirtualRegister(RegNo) || ChangingRegs.test(RegNo))<br>
+              RegsToClobber.insert(RegNo);<br>
+          } else {<br>
+            // This is a constant, terminate it at end of the block. Store<br>
+            // eliminated EntryIdx and delete later, for iteration stability.<br>
+            EntryIndex ClobIdx = DbgValues.startClobber(Pair.first, MBB.back());<br>
+            DbgValues.getEntry(Pair.first, Idx).endEntry(ClobIdx);<br>
+            IdxesToRemove.push_back(Idx);<br>
+          }<br>
+        }<br>
+<br>
+        for (EntryIndex Idx : IdxesToRemove)<br>
+          Pair.second.erase(Idx);<br>
       }<br>
+<br>
+      // Implement clobbering of registers at the end of BB.<br>
+      for (unsigned Reg : RegsToClobber)<br>
+        clobberRegisterUses(RegVars, Reg, DbgValues, LiveEntries, MBB.back());<br>
     }<br>
   }<br>
 }<br>
<br>
Modified: llvm/trunk/lib/CodeGen/LiveDebugValues.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/LiveDebugValues.cpp?rev=359426&r1=359425&r2=359426&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/LiveDebugValues.cpp?rev=359426&r1=359425&r2=359426&view=diff</a><br>
==============================================================================<br>
--- llvm/trunk/lib/CodeGen/LiveDebugValues.cpp (original)<br>
+++ llvm/trunk/lib/CodeGen/LiveDebugValues.cpp Mon Apr 29 02:13:16 2019<br>
@@ -143,7 +143,8 @@ private:<br>
     enum VarLocKind {<br>
       InvalidKind = 0,<br>
       RegisterKind,<br>
-      SpillLocKind<br>
+      SpillLocKind,<br>
+      ImmediateKind<br>
     } Kind = InvalidKind;<br>
<br>
     /// The value location. Stored separately to avoid repeatedly<br>
@@ -152,6 +153,9 @@ private:<br>
       uint64_t RegNo;<br>
       SpillLoc SpillLocation;<br>
       uint64_t Hash;<br>
+      int64_t Immediate;<br>
+      const ConstantFP *FPImm;<br>
+      const ConstantInt *CImm;<br>
     } Loc;<br>
<br>
     VarLoc(const MachineInstr &MI, LexicalScopes &LS)<br>
@@ -164,6 +168,15 @@ private:<br>
       if (int RegNo = isDbgValueDescribedByReg(MI)) {<br>
         Kind = RegisterKind;<br>
         Loc.RegNo = RegNo;<br>
+      } else if (MI.getOperand(0).isImm()) {<br>
+        Kind = ImmediateKind;<br>
+        Loc.Immediate = MI.getOperand(0).getImm();<br>
+      } else if (MI.getOperand(0).isFPImm()) {<br>
+        Kind = ImmediateKind;<br>
+        Loc.FPImm = MI.getOperand(0).getFPImm();<br>
+      } else if (MI.getOperand(0).isCImm()) {<br>
+        Kind = ImmediateKind;<br>
+        Loc.CImm = MI.getOperand(0).getCImm();<br>
       }<br>
     }<br>
<br>
@@ -178,6 +191,9 @@ private:<br>
       Loc.SpillLocation = {SpillBase, SpillOffset};<br>
     }<br>
<br>
+    // Is the Loc field a constant or constant object?<br>
+    bool isConstant() const { return Kind == ImmediateKind; }<br>
+<br>
     /// If this variable is described by a register, return it,<br>
     /// otherwise return 0.<br>
     unsigned isDescribedByReg() const {<br>
@@ -195,7 +211,8 @@ private:<br>
 #endif<br>
<br>
     bool operator==(const VarLoc &Other) const {<br>
-      return Var == Other.Var && Loc.Hash == Other.Loc.Hash;<br>
+      return Kind == Other.Kind && Var == Other.Var &&<br>
+             Loc.Hash == Other.Loc.Hash;<br>
     }<br>
<br>
     /// This operator guarantees that VarLocs are sorted by Variable first.<br>
@@ -408,11 +425,23 @@ void LiveDebugValues::transferDebugValue<br>
   OpenRanges.erase(V);<br>
<br>
   // Add the VarLoc to OpenRanges from this DBG_VALUE.<br>
-  // TODO: Currently handles DBG_VALUE which has only reg as location.<br>
-  if (isDbgValueDescribedByReg(MI)) {<br>
+  unsigned ID;<br>
+  if (isDbgValueDescribedByReg(MI) || MI.getOperand(0).isImm() ||<br>
+      MI.getOperand(0).isFPImm() || MI.getOperand(0).isCImm()) {<br>
+    // Use normal VarLoc constructor for registers and immediates.<br>
     VarLoc VL(MI, LS);<br>
-    unsigned ID = VarLocIDs.insert(VL);<br>
+    ID = VarLocIDs.insert(VL);<br>
+    OpenRanges.insert(ID, VL.Var);<br>
+  } else if (MI.hasOneMemOperand()) {<br>
+    // It's a stack spill -- fetch spill base and offset.<br>
+    VarLoc::SpillLoc SpillLocation = extractSpillBaseRegAndOffset(MI);<br>
+    VarLoc VL(MI, SpillLocation.SpillBase, SpillLocation.SpillOffset, LS);<br>
+    ID = VarLocIDs.insert(VL);<br>
     OpenRanges.insert(ID, VL.Var);<br>
+  } else {<br>
+    // This must be an undefined location. We should leave OpenRanges closed.<br>
+    assert(MI.getOperand(0).isReg() && MI.getOperand(0).getReg() == 0 &&<br>
+           "Unexpected non-undef DBG_VALUE encountered");<br>
   }<br>
 }<br>
<br>
@@ -806,12 +835,19 @@ bool LiveDebugValues::join(<br>
     // a new DBG_VALUE. process() will end this range however appropriate.<br>
     const VarLoc &DiffIt = VarLocIDs[ID];<br>
     const MachineInstr *DMI = &DiffIt.MI;<br>
-    MachineInstr *MI =<br>
-        BuildMI(MBB, MBB.instr_begin(), DMI->getDebugLoc(), DMI->getDesc(),<br>
-                DMI->isIndirectDebugValue(), DMI->getOperand(0).getReg(),<br>
-                DMI->getDebugVariable(), DMI->getDebugExpression());<br>
-    if (DMI->isIndirectDebugValue())<br>
-      MI->getOperand(1).setImm(DMI->getOperand(1).getImm());<br>
+    MachineInstr *MI = nullptr;<br>
+    if (DiffIt.isConstant()) {<br>
+      MachineOperand MO(DMI->getOperand(0));<br>
+      MI = BuildMI(MBB, MBB.instr_begin(), DMI->getDebugLoc(), DMI->getDesc(),<br>
+                   false, MO, DMI->getDebugVariable(),<br>
+                   DMI->getDebugExpression());<br>
+    } else {<br>
+      MI = BuildMI(MBB, MBB.instr_begin(), DMI->getDebugLoc(), DMI->getDesc(),<br>
+                   DMI->isIndirectDebugValue(), DMI->getOperand(0).getReg(),<br>
+                   DMI->getDebugVariable(), DMI->getDebugExpression());<br>
+      if (DMI->isIndirectDebugValue())<br>
+        MI->getOperand(1).setImm(DMI->getOperand(1).getImm());<br>
+    }<br>
     LLVM_DEBUG(dbgs() << "Inserted: "; MI->dump(););<br>
     ILS.set(ID);<br>
     ++NumInserted;<br>
<br>
Modified: llvm/trunk/test/DebugInfo/COFF/pieces.ll<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/test/DebugInfo/COFF/pieces.ll?rev=359426&r1=359425&r2=359426&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/test/DebugInfo/COFF/pieces.ll?rev=359426&r1=359425&r2=359426&view=diff</a><br>
==============================================================================<br>
--- llvm/trunk/test/DebugInfo/COFF/pieces.ll (original)<br>
+++ llvm/trunk/test/DebugInfo/COFF/pieces.ll Mon Apr 29 02:13:16 2019<br>
@@ -40,9 +40,10 @@<br>
 ; ASM: # %bb.2:                                 # %for.body.preheader<br>
 ; ASM:         xorl    %edi, %edi<br>
 ; ASM:         xorl    %esi, %esi<br>
+; ASM: [[oy_ox_start:\.Ltmp[0-9]+]]:<br>
 ; ASM:         .p2align        4, 0x90<br>
 ; ASM: .LBB0_3:                                # %for.body<br>
-; ASM: [[oy_ox_start:\.Ltmp[0-9]+]]:<br>
+; ASM:        #DEBUG_VALUE: loop_csr:o <- [DW_OP_LLVM_fragment 0 32] 0<br>
 ; ASM:        #DEBUG_VALUE: loop_csr:o <- [DW_OP_LLVM_fragment 0 32] $edi<br>
 ; ASM:        #DEBUG_VALUE: loop_csr:o <- [DW_OP_LLVM_fragment 32 32] $esi<br>
 ; ASM:        .cv_loc 0 1 13 11               # t.c:13:11<br>
@@ -59,13 +60,21 @@<br>
 ; ASM:         #DEBUG_VALUE: loop_csr:o <- [DW_OP_LLVM_fragment 32 32] $esi<br>
 ; ASM:         cmpl    n(%rip), %eax<br>
 ; ASM:         jl      .LBB0_3<br>
+; ASM: [[loopskip_start:\.Ltmp[0-9]+]]:<br>
+; ASM:         #DEBUG_VALUE: loop_csr:o <- [DW_OP_LLVM_fragment 0 32] 0<br>
+; ASM:         xorl    %esi, %esi<br>
+; ASM:         xorl    %edi, %edi<br>
 ; ASM: [[oy_end:\.Ltmp[0-9]+]]:<br>
 ; ASM:         addl    %edi, %esi<br>
 ; ASM:         movl    %esi, %eax<br>
<br>
+; XXX FIXME: the debug value line after loopskip_start should be repeated<br>
+; because both fields of 'o' are zero flowing into this block. However, it<br>
+; appears livedebugvalues doesn't account for fragments.<br>
<br>
 ; ASM-LABEL: pad_right: # @pad_right<br>
 ; ASM:         movq    %rcx, %rax<br>
+; ASM: [[pad_right_tmp:\.Ltmp[0-9]+]]:<br>
 ; ASM:         #DEBUG_VALUE: pad_right:o <- [DW_OP_LLVM_fragment 32 32] $eax<br>
 ; ASM:         retq<br>
<br>
@@ -73,6 +82,7 @@<br>
 ; ASM-LABEL: pad_left: # @pad_left<br>
 ; ASM:         .cv_loc 2 1 24 3                # t.c:24:3<br>
 ; ASM:         movq    %rcx, %rax<br>
+; ASM: [[pad_left_tmp:\.Ltmp[0-9]+]]:<br>
 ; ASM:         #DEBUG_VALUE: pad_left:o <- [DW_OP_LLVM_fragment 0 32] $eax<br>
 ; ASM:         retq<br>
<br>
@@ -104,8 +114,8 @@<br>
 ; ASM:        .asciz  "o"<br>
 ; ASM:        .cv_def_range    [[oy_ox_start]] [[ox_start]], "C\021\030\000\000\000\000\000\000\000"<br>
 ; ASM:        .cv_def_range    [[oy_ox_start]] [[oy_start]], "C\021\027\000\000\000\004\000\000\000"<br>
-; ASM:        .cv_def_range    [[ox_start]] [[oy_end]], "C\021\030\000\000\000\000\000\000\000"<br>
-; ASM:        .cv_def_range    [[oy_start]] [[oy_end]], "C\021\027\000\000\000\004\000\000\000"<br>
+; ASM:        .cv_def_range    [[ox_start]] [[loopskip_start]], "C\021\030\000\000\000\000\000\000\000"<br>
+; ASM:        .cv_def_range    [[oy_start]] [[loopskip_start]], "C\021\027\000\000\000\004\000\000\000"<br>
<br>
<br>
 ; OBJ-LABEL: GlobalProcIdSym {<br>
@@ -136,7 +146,7 @@<br>
 ; ASM:        .asciz  "pad_right"             # Function name<br>
 ; ASM:        .short  4414                    # Record kind: S_LOCAL<br>
 ; ASM:        .asciz  "o"<br>
-; ASM:        .cv_def_range    .Ltmp8 .Ltmp8, "C\021\021\000\000\000\004\000\000\000"<br>
+; ASM:        .cv_def_range    [[pad_right_tmp]] [[pad_right_tmp]], "C\021\021\000\000\000\004\000\000\000"<br>
<br>
 ; OBJ-LABEL: GlobalProcIdSym {<br>
 ; OBJ:         Kind: S_GPROC32_ID (0x1147)<br>
@@ -159,7 +169,7 @@<br>
 ; ASM:        .asciz  "pad_left"              # Function name<br>
 ; ASM:        .short  4414                    # Record kind: S_LOCAL<br>
 ; ASM:        .asciz  "o"<br>
-; ASM:        .cv_def_range    .Ltmp10 .Ltmp10, "C\021\021\000\000\000\000\000\000\000"<br>
+; ASM:        .cv_def_range    [[pad_left_tmp]] [[pad_left_tmp]], "C\021\021\000\000\000\000\000\000\000"<br>
<br>
 ; OBJ-LABEL: GlobalProcIdSym {<br>
 ; OBJ:         Kind: S_GPROC32_ID (0x1147)<br>
<br>
Modified: llvm/trunk/test/DebugInfo/MIR/AArch64/implicit-def-dead-scope.mir<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/test/DebugInfo/MIR/AArch64/implicit-def-dead-scope.mir?rev=359426&r1=359425&r2=359426&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/test/DebugInfo/MIR/AArch64/implicit-def-dead-scope.mir?rev=359426&r1=359425&r2=359426&view=diff</a><br>
==============================================================================<br>
--- llvm/trunk/test/DebugInfo/MIR/AArch64/implicit-def-dead-scope.mir (original)<br>
+++ llvm/trunk/test/DebugInfo/MIR/AArch64/implicit-def-dead-scope.mir Mon Apr 29 02:13:16 2019<br>
@@ -5,8 +5,10 @@<br>
 #  encountering an IMPLICIT_DEF in its own lexical scope.<br>
<br>
 # CHECK: .debug_info contents:<br>
-# CHECK: DW_TAG_formal_parameter<br>
-# CHECK:   DW_AT_const_value [DW_FORM_udata]   (0)<br>
+# CHECK:       DW_TAG_formal_parameter<br>
+# CHECK:       DW_AT_location [DW_FORM_sec_offset]<br>
+# CHECK-NEXT:                 DW_OP_lit0, DW_OP_stack_value<br>
+# CHECK-NEXT:  DW_AT_abstract_origin {{.*}} "name"<br>
 --- |<br>
   ; ModuleID = 't.ll'<br>
   source_filename = "t.ll"<br>
@@ -103,7 +105,7 @@<br>
   !15 = distinct !DICompositeType(tag: DW_TAG_class_type, name: "v", file: !5, line: 97, size: 64, elements: !2, identifier: "_ZTS1v")<br>
   !16 = !DISubroutineType(types: !2)<br>
   !17 = !DISubprogram(name: "bv", linkageName: "_ZN1v2bvEv", scope: !15, file: !5, line: 98, type: !16, isLocal: false, isDefinition: false, scopeLine: 98, flags: DIFlagPrototyped, isOptimized: true)<br>
-  !18 = !DILocalVariable(arg: 2, scope: !19, file: !5, line: 22, type: !21)<br>
+  !18 = !DILocalVariable(name: "name", arg: 2, scope: !19, file: !5, line: 22, type: !21)<br>
   !19 = distinct !DISubprogram(name: "m", linkageName: "_ZN1jILi6EN1a1fEE1mEj", scope: !11, file: !5, line: 22, type: !16, isLocal: false, isDefinition: true, scopeLine: 22, flags: DIFlagPrototyped, isOptimized: true, unit: !0, declaration: !20, retainedNodes: !2)<br>
   !20 = !DISubprogram(name: "m", linkageName: "_ZN1jILi6EN1a1fEE1mEj", scope: !11, file: !5, line: 22, type: !16, isLocal: false, isDefinition: false, scopeLine: 22, flags: DIFlagPublic | DIFlagPrototyped, isOptimized: true)<br>
   !21 = !DIDerivedType(tag: DW_TAG_typedef, name: "h", file: !5, line: 10, baseType: !22)<br>
<br>
Modified: llvm/trunk/test/DebugInfo/X86/fission-ranges.ll<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/test/DebugInfo/X86/fission-ranges.ll?rev=359426&r1=359425&r2=359426&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/test/DebugInfo/X86/fission-ranges.ll?rev=359426&r1=359425&r2=359426&view=diff</a><br>
==============================================================================<br>
--- llvm/trunk/test/DebugInfo/X86/fission-ranges.ll (original)<br>
+++ llvm/trunk/test/DebugInfo/X86/fission-ranges.ll Mon Apr 29 02:13:16 2019<br>
@@ -15,6 +15,7 @@<br>
 ; CHECK-NEXT: DW_AT_GNU_addr_base [DW_FORM_sec_offset]                   (0x00000000)<br>
<br>
 ; CHECK: .debug_info.dwo contents:<br>
+; CHECK: DW_AT_location [DW_FORM_sec_offset]   ([[P:0x[0-9a-z]*]]<br>
 ; CHECK: DW_AT_location [DW_FORM_sec_offset]   ([[A:0x[0-9a-z]*]]<br>
 ; CHECK: DW_AT_location [DW_FORM_sec_offset]   ([[E:0x[0-9a-z]*]]<br>
 ; CHECK: DW_AT_location [DW_FORM_sec_offset]   ([[B:0x[0-9a-z]*]]<br>
@@ -27,24 +28,31 @@<br>
 ; Don't assume these locations are entirely correct - feel free to update them<br>
 ; if they've changed due to a bugfix, change in register allocation, etc.<br>
<br>
+; CHECK:      [[P]]:<br>
+; CHECK-NEXT:   Addr idx 1 (w/ length 204): DW_OP_consts +1, DW_OP_stack_value<br>
 ; CHECK:      [[A]]:<br>
 ; CHECK-NEXT:   Addr idx 2 (w/ length 169): DW_OP_consts +0, DW_OP_stack_value<br>
-; CHECK-NEXT:   Addr idx 3 (w/ length 25): DW_OP_reg0 RAX<br>
+; CHECK-NEXT:   Addr idx 3 (w/ length 15): DW_OP_reg0 RAX<br>
+; CHECK-NEXT:   Addr idx 4 (w/ length 6): DW_OP_breg7 RSP-8<br>
+; CHECK-NEXT:   Addr idx 5 (w/ length 4): DW_OP_reg0 RAX<br>
 ; CHECK:      [[E]]:<br>
-; CHECK-NEXT:   Addr idx 4 (w/ length 19): DW_OP_reg0 RAX<br>
+; CHECK-NEXT:   Addr idx 6 (w/ length 9): DW_OP_reg0 RAX<br>
+; CHECK-NEXT:   Addr idx 7 (w/ length 98): DW_OP_breg7 RSP-44<br>
 ; CHECK:      [[B]]:<br>
-; CHECK-NEXT:   Addr idx 5 (w/ length 17): DW_OP_reg0 RAX<br>
+; CHECK-NEXT:   Addr idx 8 (w/ length 15): DW_OP_reg0 RAX<br>
+; CHECK-NEXT:   Addr idx 9 (w/ length 66): DW_OP_breg7 RSP-32<br>
 ; CHECK:      [[D]]:<br>
-; CHECK-NEXT:   Addr idx 6 (w/ length 17): DW_OP_reg0 RAX<br>
+; CHECK-NEXT:   Addr idx 10 (w/ length 15): DW_OP_reg0 RAX<br>
+; CHECK-NEXT:   Addr idx 11 (w/ length 42): DW_OP_breg7 RSP-20<br>
<br>
 ; Make sure we don't produce any relocations in any .dwo section (though in particular, debug_info.dwo)<br>
 ; HDR-NOT: .rela.{{.*}}.dwo<br>
<br>
 ; Make sure we have enough stuff in the debug_addr to cover the address indexes<br>
-; (6 is the last index in debug_loc.dwo, making 7 entries of 8 bytes each, 7 * 8<br>
-; == 56 base 10 == 38 base 16)<br>
+; (11 is the last index in debug_loc.dwo, making 12 entries of 8 bytes each,<br>
+; 12 * 8 == 96 base 10 == 60 base 16)<br>
<br>
-; HDR: .debug_addr 00000038<br>
+; HDR: .debug_addr 00000060<br>
 ; HDR-NOT: .rela.{{.*}}.dwo<br>
<br>
 ; Check for the existence of a DWARF v5-style range list table in the .debug_rnglists<br>
<br>
Added: llvm/trunk/test/DebugInfo/X86/live-debug-values-constprop.mir<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/test/DebugInfo/X86/live-debug-values-constprop.mir?rev=359426&view=auto" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/test/DebugInfo/X86/live-debug-values-constprop.mir?rev=359426&view=auto</a><br>
==============================================================================<br>
--- llvm/trunk/test/DebugInfo/X86/live-debug-values-constprop.mir (added)<br>
+++ llvm/trunk/test/DebugInfo/X86/live-debug-values-constprop.mir Mon Apr 29 02:13:16 2019<br>
@@ -0,0 +1,347 @@<br>
+# RUN: llc %s -o - -run-pass=livedebugvalues -mtriple=x86_64-unknown-unknown | FileCheck %s --check-prefix=CHECK<br>
+# RUN: llc %s -o - -start-before=livedebugvalues -filetype=obj -mtriple=x86_64-unknown-unknown | llvm-dwarfdump - | FileCheck %s --check-prefix=RANGES<br>
+# Check that livedebugvalues does the right thing when register and constant<br>
+# DBG_VALUEs interact, and that their ranges are correctly terminated by the<br>
+# debug printing backend.<br>
+--- |<br>
+  ; All these IR functions are duds, see the MIR below.<br>
+  source_filename = "<stdin>"<br>
+  target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"<br>
+  <br>
+  define i32 @foo(i32* %bees, i32* %output) !dbg !4 {<br>
+  entry:<br>
+    br i1 undef, label %bb1, label %bb1<br>
+  bb1:<br>
+    br label %bb3<br>
+  bb2:<br>
+    br label %bb3<br>
+  bb3:<br>
+    ret i32 0<br>
+  }<br>
+<br>
+  define i32 @bar(i32* %bees, i32* %output) !dbg !40 {<br>
+  entry:<br>
+    br i1 undef, label %bb1, label %bb1<br>
+  bb1:<br>
+    br label %bb3<br>
+  bb2:<br>
+    br label %bb3<br>
+  bb3:<br>
+    ret i32 0<br>
+  }<br>
+<br>
+  define i32 @baz(i32* %bees, i32* %output) !dbg !80 {<br>
+  entry:<br>
+    br i1 undef, label %bb1, label %bb1<br>
+  bb1:<br>
+    br label %bb3<br>
+  bb2:<br>
+    br label %bb3<br>
+  bb3:<br>
+    ret i32 0<br>
+  }<br>
+<br>
+  define i32 @qux(i32* %bees, i32* %output) !dbg !120 {<br>
+  entry:<br>
+    br i1 undef, label %bb1, label %bb1<br>
+  bb1:<br>
+    br label %bb3<br>
+  bb2:<br>
+    br label %bb3<br>
+  bb3:<br>
+    ret i32 0<br>
+  }<br>
+<br>
+  ; Function Attrs: nounwind readnone speculatable<br>
+  declare void @llvm.dbg.value(metadata, metadata, metadata)<br>
+  <br>
+  ; Function Attrs: nounwind readnone speculatable<br>
+  declare void @llvm.dbg.declare(metadata, metadata, metadata)<br>
+  <br>
+  ; Function Attrs: nounwind<br>
+  declare void @llvm.stackprotector(i8*, i8**)<br>
+  <br>
+  !llvm.module.flags = !{!0, !100}<br>
+  !<a href="http://llvm.dbg.cu" rel="noreferrer" target="_blank">llvm.dbg.cu</a> = !{!1}<br>
+  <br>
+  !100 = !{i32 2, !"Dwarf Version", i32 4}<br>
+  !0 = !{i32 2, !"Debug Info Version", i32 3}<br>
+  !1 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus, file: !2, producer: "beards", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug)<br>
+  !2 = !DIFile(filename: "bees.cpp", directory: ".")<br>
+  !3 = !DILocalVariable(name: "flannel", scope: !4, file: !2, line: 1, type: !16)<br>
+  !4 = distinct !DISubprogram(name: "nope", scope: !2, file: !2, line: 1, spFlags: DISPFlagDefinition, unit: !1, retainedNodes: !13, type: !14, isDefinition: true)<br>
+  !5 = !DILocation(line: 0, scope: !4)<br>
+  !6 = !DILocation(line: 1, scope: !4)<br>
+  !7 = !DILocation(line: 2, scope: !4)<br>
+  !8 = !DILocation(line: 4, scope: !4)<br>
+  !9 = !DILocation(line: 5, scope: !4)<br>
+  !10 = !DILocation(line: 6, scope: !4)<br>
+  !11 = !DILocation(line: 7, scope: !4)<br>
+  !12 = !DILocation(line: 8, scope: !4)<br>
+  !13 = !{!3}<br>
+  !14 = !DISubroutineType(types: !15)<br>
+  !15 = !{!16}<br>
+  !16 = !DIBasicType(name: "int", size: 32, align: 32, encoding: DW_ATE_signed)<br>
+  !40 = distinct !DISubprogram(name: "bar", scope: !2, file: !2, line: 1, spFlags: DISPFlagDefinition, unit: !1, retainedNodes: !13, type: !14, isDefinition: true)<br>
+  !41 = !DILocalVariable(name: "towel", scope: !40, file: !2, line: 1, type: !16)<br>
+  !42 = !DILocation(line: 40, scope: !40)<br>
+  !80 = distinct !DISubprogram(name: "baz", scope: !2, file: !2, line: 1, spFlags: DISPFlagDefinition, unit: !1, retainedNodes: !13, type: !14, isDefinition: true)<br>
+  !81 = !DILocalVariable(name: "socks", scope: !80, file: !2, line: 1, type: !16)<br>
+  !82 = !DILocation(line: 40, scope: !80)<br>
+  !120 = distinct !DISubprogram(name: "qux", scope: !2, file: !2, line: 1, spFlags: DISPFlagDefinition, unit: !1, retainedNodes: !13, type: !14, isDefinition: true)<br>
+  !121 = !DILocalVariable(name: "shoes", scope: !120, file: !2, line: 1, type: !16)<br>
+  !122 = !DILocation(line: 40, scope: !120)<br>
+<br>
+...<br>
+---<br>
+name:            foo<br>
+alignment:       4<br>
+tracksRegLiveness: true<br>
+registers:       []<br>
+liveins:         <br>
+  - { reg: '$rdi', virtual-reg: '' }<br>
+body:             |<br>
+<br>
+  ; Two DBG_VALUEs for eax merge into bb3, check that livedebugvalues propagates<br>
+  ; the location.<br>
+  ; CHECK-LABEL: name: foo<br>
+  ; CHECK-LABEL: bb.1.bb1<br>
+  ; CHECK:       $eax = MOV32rr<br>
+  ; CHECK-NEXT:  DBG_VALUE $eax<br>
+  ; CHECK-NEXT:  JMP_1 %bb.3<br>
+  ; CHECK-LABEL: bb.2.bb2<br>
+  ; CHECK:       $eax = ADD32ri8<br>
+  ; CHECK-NEXT:  DBG_VALUE $eax<br>
+  ; CHECK-NEXT:  JMP_1 %bb.3<br>
+  ; CHECK-LABEL: bb.3.bb3<br>
+  ; CHECK:       DBG_VALUE $eax<br>
+  ; Test for there being a location-list gap between bb1 and bb2, as the<br>
+  ; variable does not have a location over the ADD32ri. The range should also<br>
+  ; extend over the final bb.<br>
+  ; RANGES-LABEL: DW_TAG_subprogram<br>
+  ; RANGES:       DW_AT_high_pc (0x[[NOPEHIGHPC:[0-9a-f]+]])<br>
+  ; RANGES-LABEL: DW_AT_name ("nope")<br>
+  ; RANGES:       DW_AT_location (0x{{[0-9a-f]+}}<br>
+  ; RANGES-NEXT:   [0x{{[0-9a-f]+}}, 0x[[NOPEADDR:[0-9a-f]+]]): DW_OP_reg0 RAX<br>
+  ; RANGES-NEXT:   [<br>
+  ; RANGES-NOT:    0x[[NOPEADDR]]<br>
+  ; RANGES-SAME:   , 0x[[NOPEHIGHPC]]): DW_OP_reg0 RAX<br>
+<br>
+  bb.0.entry:<br>
+    successors: %bb.1, %bb.2<br>
+    liveins: $rdi<br>
+  <br>
+    $ecx = XOR32rr undef $ecx, undef $ecx, implicit-def $eflags<br>
+    JCC_1 %bb.1, 2, implicit killed $eflags<br>
+    JMP_1 %bb.2<br>
+  <br>
+  bb.1.bb1 (align 4):<br>
+    successors: %bb.3<br>
+    liveins: $ecx, $rdi<br>
+  <br>
+    $eax = MOV32rr killed $ecx, implicit-def $rax<br>
+    DBG_VALUE $eax, $noreg, !3, !DIExpression(), debug-location !8<br>
+    JMP_1 %bb.3<br>
+  <br>
+  bb.2.bb2:<br>
+    successors: %bb.3<br>
+    liveins: $rax<br>
+  <br>
+    $eax = ADD32ri8 $eax, 3, implicit-def dead $eflags, implicit killed $rax, implicit-def $rax<br>
+    DBG_VALUE $eax, $noreg, !3, !DIExpression(), debug-location !8<br>
+    JMP_1 %bb.3<br>
+<br>
+  bb.3.bb3:<br>
+    liveins: $rax<br>
+    RETQ $eax, debug-location !9<br>
+<br>
+...<br>
+---<br>
+name:            bar<br>
+alignment:       4<br>
+tracksRegLiveness: true<br>
+registers:       []<br>
+liveins:         <br>
+  - { reg: '$rdi', virtual-reg: '' }<br>
+body:             |<br>
+  ; Two DBG_VALUEs, one for eax, the other for zero, merge into bb3. Check that<br>
+  ; livedebugvalues does not propagate anything.<br>
+  ; the location.<br>
+  ; CHECK-LABEL: name: bar<br>
+  ; CHECK-LABEL: bb.1.bb1<br>
+  ; CHECK:       $eax = MOV32rr<br>
+  ; CHECK-NEXT:  DBG_VALUE 0<br>
+  ; CHECK-NEXT:  JMP_1 %bb.3<br>
+  ; CHECK-LABEL: bb.2.bb2<br>
+  ; CHECK:       $eax = ADD32ri8<br>
+  ; CHECK-NEXT:  DBG_VALUE $eax<br>
+  ; CHECK-NEXT:  JMP_1 %bb.3<br>
+  ; CHECK-LABEL: bb.3.bb3<br>
+  ; CHECK-NOT:   DBG_VALUE<br>
+  ; Test for there being a location-list gap between bb1 and bb2, the variable<br>
+  ; should not have a location over the ADD32ri. The range of the last entry<br>
+  ; should not cover the last block.<br>
+  ; RANGES-LABEL: DW_TAG_subprogram<br>
+  ; RANGES:       DW_AT_high_pc (0x[[BARHIGHPC:[0-9a-f]+]])<br>
+  ; RANGES-LABEL: DW_AT_name ("bar")<br>
+  ; RANGES:       DW_AT_location (0x{{[0-9a-f]+}}<br>
+  ; RANGES-NEXT:   [0x{{[0-9a-f]+}}, 0x[[BARADDR:[0-9a-f]+]]): DW_OP_consts +0, DW_OP_stack_value<br>
+  ; RANGES-NEXT:   [<br>
+  ; RANGES-NOT:    0x[[BARADDR]]<br>
+  ; RANGES-NOT:    0x[[BARHIGHPC]]<br>
+  ; RANGES-SAME:   ): DW_OP_reg0 RAX<br>
+<br>
+  bb.0.entry:<br>
+    successors: %bb.1, %bb.2<br>
+    liveins: $rdi<br>
+  <br>
+    $ecx = XOR32rr undef $ecx, undef $ecx, implicit-def $eflags<br>
+    JCC_1 %bb.1, 2, implicit killed $eflags<br>
+    JMP_1 %bb.2<br>
+  <br>
+  bb.1.bb1 (align 4):<br>
+    successors: %bb.3<br>
+    liveins: $ecx, $rdi<br>
+  <br>
+    $eax = MOV32rr killed $ecx, implicit-def $rax<br>
+    DBG_VALUE 0, $noreg, !41, !DIExpression(), debug-location !42<br>
+    JMP_1 %bb.3<br>
+  <br>
+  bb.2.bb2:<br>
+    successors: %bb.3<br>
+    liveins: $rax<br>
+  <br>
+    $eax = ADD32ri8 $eax, 3, implicit-def dead $eflags, implicit killed $rax, implicit-def $rax<br>
+    DBG_VALUE $eax, $noreg, !41, !DIExpression(), debug-location !42<br>
+    JMP_1 %bb.3<br>
+<br>
+  bb.3.bb3:<br>
+    liveins: $rax<br>
+    RETQ $eax, debug-location !42<br>
+<br>
+...<br>
+---<br>
+name:            baz<br>
+alignment:       4<br>
+tracksRegLiveness: true<br>
+registers:       []<br>
+liveins:         <br>
+  - { reg: '$rdi', virtual-reg: '' }<br>
+body:             |<br>
+  ; Two DBG_VALUEs, one for zero, the other for eax, merge into bb3. Check that<br>
+  ; livedebugvalues does not propagate anything.<br>
+  ; the location.<br>
+  ; CHECK-LABEL: name: baz<br>
+  ; CHECK-LABEL: bb.1.bb1<br>
+  ; CHECK:       $eax = MOV32rr<br>
+  ; CHECK-NEXT:  DBG_VALUE $eax<br>
+  ; CHECK-NEXT:  JMP_1 %bb.3<br>
+  ; CHECK-LABEL: bb.2.bb2<br>
+  ; CHECK:       $eax = ADD32ri8<br>
+  ; CHECK-NEXT:  DBG_VALUE 0<br>
+  ; CHECK-NEXT:  JMP_1 %bb.3<br>
+  ; CHECK-LABEL: bb.3.bb3<br>
+  ; CHECK-NOT:   DBG_VALUE<br>
+  ; Test for there being a location-list gap between bb1 and bb2, the variable<br>
+  ; should not have a location over the ADD32ri. The range of the last item<br>
+  ; should not cover the last block.<br>
+  ; RANGES-LABEL: DW_TAG_subprogram<br>
+  ; RANGES:       DW_AT_high_pc (0x[[BAZHIGHPC:[0-9a-f]+]])<br>
+  ; RANGES-LABEL: DW_AT_name ("baz")<br>
+  ; RANGES:       DW_AT_location (0x{{[0-9a-f]+}}<br>
+  ; RANGES-NEXT:   [0x{{[0-9a-f]+}}, 0x[[BAZADDR:[0-9a-f]+]]): DW_OP_reg0 RAX<br>
+  ; RANGES-NEXT:   [<br>
+  ; RANGES-NOT:    0x[[BAZADDR]]<br>
+  ; RANGES-NOT:    0x[[BAZHIGHPC]]<br>
+  ; RANGES-SAME:   ): DW_OP_consts +0, DW_OP_stack_value<br>
+<br>
+  bb.0.entry:<br>
+    successors: %bb.1, %bb.2<br>
+    liveins: $rdi<br>
+  <br>
+    $ecx = XOR32rr undef $ecx, undef $ecx, implicit-def $eflags<br>
+    JCC_1 %bb.1, 2, implicit killed $eflags<br>
+    JMP_1 %bb.2<br>
+  <br>
+  bb.1.bb1 (align 4):<br>
+    successors: %bb.3<br>
+    liveins: $ecx, $rdi<br>
+  <br>
+    $eax = MOV32rr killed $ecx, implicit-def $rax<br>
+    DBG_VALUE $eax, $noreg, !81, !DIExpression(), debug-location !82<br>
+    JMP_1 %bb.3<br>
+  <br>
+  bb.2.bb2:<br>
+    successors: %bb.3<br>
+    liveins: $rax<br>
+  <br>
+    $eax = ADD32ri8 $eax, 3, implicit-def dead $eflags, implicit killed $rax, implicit-def $rax<br>
+    DBG_VALUE 0, $noreg, !81, !DIExpression(), debug-location !82<br>
+    JMP_1 %bb.3<br>
+<br>
+  bb.3.bb3:<br>
+    liveins: $rax<br>
+    RETQ $eax, debug-location !82<br>
+<br>
+...<br>
+---<br>
+name:            qux<br>
+alignment:       4<br>
+tracksRegLiveness: true<br>
+registers:       []<br>
+liveins:         <br>
+  - { reg: '$rdi', virtual-reg: '' }<br>
+body:             |<br>
+  ; Two DBG_VALUEs for zero merging into bb3, Check that livedebugvalues does<br>
+  ; propagate the zero into the merging block.<br>
+  ; CHECK-LABEL: name: qux<br>
+  ; CHECK-LABEL: bb.1.bb1<br>
+  ; CHECK:       $eax = MOV32rr<br>
+  ; CHECK-NEXT:  DBG_VALUE 0<br>
+  ; CHECK-NEXT:  JMP_1 %bb.3<br>
+  ; CHECK-LABEL: bb.2.bb2<br>
+  ; CHECK:       $eax = ADD32ri8<br>
+  ; CHECK-NEXT:  DBG_VALUE 0<br>
+  ; CHECK-NEXT:  JMP_1 %bb.3<br>
+  ; CHECK-LABEL: bb.3.bb3<br>
+  ; CHECK:       DBG_VALUE 0<br>
+  ; Test for there being a location-list gap between bb1 and bb2, the variable<br>
+  ; should not have a location over the ADD32ri. The final entry should cover<br>
+  ; the final block.<br>
+  ; RANGES-LABEL: DW_TAG_subprogram<br>
+  ; RANGES:       DW_AT_high_pc (0x[[QUXHIGHPC:[0-9a-f]+]])<br>
+  ; RANGES-LABEL: DW_AT_name ("qux")<br>
+  ; RANGES:       DW_AT_location (0x{{[0-9a-f]+}}<br>
+  ; RANGES-NEXT:   [0x{{[0-9a-f]+}}, 0x[[QUXADDR:[0-9a-f]+]]): DW_OP_consts +0, DW_OP_stack_value<br>
+  ; RANGES-NOT:    0x[[QUXADDR]]<br>
+  ; RANGES-NEXT:   [0x{{[0-9a-f]+}}, 0x[[QUXHIGHPC]]): DW_OP_consts +0, DW_OP_stack_value<br>
+<br>
+  bb.0.entry:<br>
+    successors: %bb.1, %bb.2<br>
+    liveins: $rdi<br>
+  <br>
+    $ecx = XOR32rr undef $ecx, undef $ecx, implicit-def $eflags<br>
+    JCC_1 %bb.1, 2, implicit killed $eflags<br>
+    JMP_1 %bb.2<br>
+  <br>
+  bb.1.bb1 (align 4):<br>
+    successors: %bb.3<br>
+    liveins: $ecx, $rdi<br>
+  <br>
+    $eax = MOV32rr killed $ecx, implicit-def $rax<br>
+    DBG_VALUE 0, $noreg, !121, !DIExpression(), debug-location !122<br>
+    JMP_1 %bb.3<br>
+  <br>
+  bb.2.bb2:<br>
+    successors: %bb.3<br>
+    liveins: $rax<br>
+  <br>
+    $eax = ADD32ri8 $eax, 3, implicit-def dead $eflags, implicit killed $rax, implicit-def $rax<br>
+    DBG_VALUE 0, $noreg, !121, !DIExpression(), debug-location !122<br>
+    JMP_1 %bb.3<br>
+<br>
+  bb.3.bb3:<br>
+    liveins: $rax<br>
+    RETQ $eax, debug-location !122<br>
+<br>
+...<br>
<br>
<br>
_______________________________________________<br>
llvm-commits mailing list<br>
<a href="mailto:llvm-commits@lists.llvm.org" target="_blank">llvm-commits@lists.llvm.org</a><br>
<a href="https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-commits" rel="noreferrer" target="_blank">https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-commits</a><br>
</blockquote></div>