[llvm] 5db9250 - Reapply D124184, [DebugInfo][InstrRef] Add a size operand to DBG_PHI

Jeremy Morse via llvm-commits llvm-commits at lists.llvm.org
Mon Apr 25 07:50:43 PDT 2022


Author: Jeremy Morse
Date: 2022-04-25T15:50:15+01:00
New Revision: 5db925023169f8a19419e68153682d1e518f8392

URL: https://github.com/llvm/llvm-project/commit/5db925023169f8a19419e68153682d1e518f8392
DIFF: https://github.com/llvm/llvm-project/commit/5db925023169f8a19419e68153682d1e518f8392.diff

LOG: Reapply D124184, [DebugInfo][InstrRef] Add a size operand to DBG_PHI

This was applied in fda4305e53784, reverted in 13815e8cbf8d49, the problem
was that fp80 X86 registers that were spilt to the stack aren't expected by
LiveDebugValues. It pre-allocates a position number for all register sizes
that can be spilt, and 80 bits isn't exactly common.

The solution is to scan the register classes to find any unrecognised
register sizes, adn pre-allocate those position numbers, avoiding a later
assertion.

Added: 
    llvm/test/DebugInfo/MIR/InstrRef/dbg-phis-in-ldv2.mir
    llvm/test/DebugInfo/MIR/InstrRef/phi-on-stack-coalesced.mir
    llvm/test/DebugInfo/MIR/InstrRef/phi-on-stack-coalesced2.mir

Modified: 
    llvm/lib/CodeGen/LiveDebugValues/InstrRefBasedImpl.cpp
    llvm/lib/CodeGen/LiveDebugVariables.cpp
    llvm/test/DebugInfo/MIR/InstrRef/phi-regallocd-to-stack.mir
    llvm/unittests/CodeGen/InstrRefLDVTest.cpp

Removed: 
    


################################################################################
diff  --git a/llvm/lib/CodeGen/LiveDebugValues/InstrRefBasedImpl.cpp b/llvm/lib/CodeGen/LiveDebugValues/InstrRefBasedImpl.cpp
index 74f6e6e8fbe7b..ab1fb3f743ea8 100644
--- a/llvm/lib/CodeGen/LiveDebugValues/InstrRefBasedImpl.cpp
+++ b/llvm/lib/CodeGen/LiveDebugValues/InstrRefBasedImpl.cpp
@@ -722,6 +722,20 @@ MLocTracker::MLocTracker(MachineFunction &MF, const TargetInstrInfo &TII,
     StackSlotIdxes.insert({{Size, Offs}, Idx});
   }
 
+  // There may also be strange register class sizes (think x86 fp80s).
+  for (const TargetRegisterClass *RC : TRI.regclasses()) {
+    unsigned Size = TRI.getRegSizeInBits(*RC);
+
+    // We might see special reserved values as sizes, and classes for other
+    // stuff the machine tries to model. If it's more than 512 bits, then it
+    // is very unlikely to be a register than can be spilt.
+    if (Size > 512)
+      continue;
+
+    unsigned Idx = StackSlotIdxes.size();
+    StackSlotIdxes.insert({{Size, 0}, Idx});
+  }
+
   for (auto &Idx : StackSlotIdxes)
     StackIdxesToPos[Idx.second] = Idx.first;
 
@@ -1293,41 +1307,16 @@ bool InstrRefBasedLDV::transferDebugPHI(MachineInstr &MI) {
     if (!SpillNo)
       return EmitBadPHI();
 
-    // Problem: what value should we extract from the stack? LLVM does not
-    // record what size the last store to the slot was, and it would become
-    // sketchy after stack slot colouring anyway. Take a look at what values
-    // are stored on the stack, and pick the largest one that wasn't def'd
-    // by a spill (i.e., the value most likely to have been def'd in a register
-    // and then spilt.
-    std::array<unsigned, 4> CandidateSizes = {64, 32, 16, 8};
-    Optional<ValueIDNum> Result = None;
-    Optional<LocIdx> SpillLoc = None;
-    for (unsigned CS : CandidateSizes) {
-      unsigned SpillID = MTracker->getLocID(*SpillNo, {CS, 0});
-      SpillLoc = MTracker->getSpillMLoc(SpillID);
-      ValueIDNum Val = MTracker->readMLoc(*SpillLoc);
-      // If this value was defined in it's own position, then it was probably
-      // an aliasing index of a small value that was spilt.
-      if (Val.getLoc() != SpillLoc->asU64()) {
-        Result = Val;
-        break;
-      }
-    }
+    // Any stack location DBG_PHI should have an associate bit-size.
+    assert(MI.getNumOperands() == 3 && "Stack DBG_PHI with no size?");
+    unsigned slotBitSize = MI.getOperand(2).getImm();
 
-    // If we didn't find anything, we're probably looking at a PHI, or a memory
-    // store folded into an instruction. FIXME: Take a guess that's it's 64
-    // bits. This isn't ideal, but tracking the size that the spill is
-    // "supposed" to be is more complex, and benefits a small number of
-    // locations.
-    if (!Result) {
-      unsigned SpillID = MTracker->getLocID(*SpillNo, {64, 0});
-      SpillLoc = MTracker->getSpillMLoc(SpillID);
-      Result = MTracker->readMLoc(*SpillLoc);
-    }
+    unsigned SpillID = MTracker->getLocID(*SpillNo, {slotBitSize, 0});
+    LocIdx SpillLoc = MTracker->getSpillMLoc(SpillID);
+    ValueIDNum Result = MTracker->readMLoc(SpillLoc);
 
     // Record this DBG_PHI for later analysis.
-    auto DbgPHI =
-        DebugPHIRecord({InstrNum, MI.getParent(), *Result, *SpillLoc});
+    auto DbgPHI = DebugPHIRecord({InstrNum, MI.getParent(), Result, SpillLoc});
     DebugPHINumToValue.push_back(DbgPHI);
   } else {
     // Else: if the operand is neither a legal register or a stack slot, then

diff  --git a/llvm/lib/CodeGen/LiveDebugVariables.cpp b/llvm/lib/CodeGen/LiveDebugVariables.cpp
index ce350b78d7534..320e68241e4ef 100644
--- a/llvm/lib/CodeGen/LiveDebugVariables.cpp
+++ b/llvm/lib/CodeGen/LiveDebugVariables.cpp
@@ -1850,16 +1850,33 @@ void LDVImpl::emitDebugValues(VirtRegMap *VRM) {
       const TargetRegisterClass *TRC = MRI.getRegClass(Reg);
       unsigned SpillSize, SpillOffset;
 
-      // Test whether this location is legal with the given subreg.
+      unsigned regSizeInBits = TRI->getRegSizeInBits(*TRC);
+      if (SubReg)
+        regSizeInBits = TRI->getSubRegIdxSize(SubReg);
+
+      // Test whether this location is legal with the given subreg. If the
+      // subregister has a nonzero offset, drop this location, it's too complex
+      // to describe. (TODO: future work).
       bool Success =
           TII->getStackSlotRange(TRC, SubReg, SpillSize, SpillOffset, *MF);
 
-      if (Success) {
+      if (Success && SpillOffset == 0) {
         auto Builder = BuildMI(*OrigMBB, OrigMBB->begin(), DebugLoc(),
                                TII->get(TargetOpcode::DBG_PHI));
         Builder.addFrameIndex(VRM->getStackSlot(Reg));
         Builder.addImm(InstNum);
+        // Record how large the original value is. The stack slot might be
+        // merged and altered during optimisation, but we will want to know how
+        // large the value is, at this DBG_PHI.
+        Builder.addImm(regSizeInBits);
+      }
+
+      LLVM_DEBUG(
+      if (SpillOffset != 0) {
+        dbgs() << "DBG_PHI for Vreg " << Reg << " subreg " << SubReg <<
+                  " has nonzero offset\n";
       }
+      );
     }
     // If there was no mapping for a value ID, it's optimized out. Create no
     // DBG_PHI, and any variables using this value will become optimized out.

diff  --git a/llvm/test/DebugInfo/MIR/InstrRef/dbg-phis-in-ldv2.mir b/llvm/test/DebugInfo/MIR/InstrRef/dbg-phis-in-ldv2.mir
new file mode 100644
index 0000000000000..ac42364ae22f5
--- /dev/null
+++ b/llvm/test/DebugInfo/MIR/InstrRef/dbg-phis-in-ldv2.mir
@@ -0,0 +1,128 @@
+# RUN: llc %s -o - -mtriple=x86_64-unknown-unknown \
+# RUN:    -experimental-debug-variable-locations -run-pass=livedebugvalues\
+# RUN:    | FileCheck %s
+#
+# Test that a DBG_INSTR_REF that refers to a DBG_PHI, will be translated into a
+# DBG_VALUE of the value read at that DBG_PHI -- in this test, when the value
+# is on the stack.
+# 
+--- |
+  target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128"
+  target triple = "x86_64-unknown-linux-gnu"
+  
+  define dso_local i32 @foo(i64 %bar, i64 %baz) !dbg !7 {
+    ret i32 0
+  }
+  
+  declare dso_local void @ext(i64)
+  
+  declare dso_local i64 @getlong()
+  
+  !llvm.dbg.cu = !{!0}
+  !llvm.module.flags = !{!3, !4, !5}
+  !llvm.ident = !{!6}
+  
+  !0 = distinct !DICompileUnit(language: DW_LANG_C99, file: !1, isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, enums: !2, splitDebugInlining: false, nameTableKind: None)
+  !1 = !DIFile(filename: "test.c", directory: "/tmp/out.c")
+  !2 = !{}
+  !3 = !{i32 7, !"Dwarf Version", i32 4}
+  !4 = !{i32 2, !"Debug Info Version", i32 3}
+  !5 = !{i32 1, !"wchar_size", i32 4}
+  !6 = !{!""}
+  !7 = distinct !DISubprogram(name: "foo", scope: !1, file: !1, line: 3, type: !8, scopeLine: 3, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition, unit: !0, retainedNodes: !2)
+  !8 = !DISubroutineType(types: !9)
+  !9 = !{!10, !11, !11}
+  !10 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed)
+  !11 = !DIBasicType(name: "long int", size: 64, encoding: DW_ATE_signed)
+  !12 = !DILocalVariable(name: "bar", arg: 1, scope: !7, file: !1, line: 3, type: !11)
+  !13 = !DILocation(line: 0, scope: !7)
+  !14 = !DILocalVariable(name: "baz", arg: 2, scope: !7, file: !1, line: 3, type: !11)
+  !19 = distinct !DILexicalBlock(scope: !7, file: !1, line: 8, column: 7)
+  !26 = !DILocation(line: 13, column: 3, scope: !7)
+
+...
+---
+name:            foo
+alignment:       16
+tracksRegLiveness: true
+liveins:
+  - { reg: '$rdi' }
+  - { reg: '$rsi' }
+frameInfo:
+  stackSize:       24
+  offsetAdjustment: -24
+  maxAlignment:    1
+  adjustsStack:    true
+  hasCalls:        true
+  maxCallFrameSize: 0
+  cvBytesOfCalleeSavedRegisters: 16
+fixedStack:
+  - { id: 0, type: spill-slot, offset: -24, size: 8, alignment: 8, callee-saved-register: '$rbx' }
+  - { id: 1, type: spill-slot, offset: -16, size: 8, alignment: 16, callee-saved-register: '$r14' }
+machineFunctionInfo: {}
+stack:
+  - { id: 0, name: '', type: spill-slot, offset: 0, size: 8, alignment: 8,
+      stack-id: default, callee-saved-register: '', callee-saved-restored: true,
+      debug-info-variable: '', debug-info-expression: '', debug-info-location: '' }
+
+body:             |
+  bb.0:
+    liveins: $rdi, $rsi, $r14, $rbx
+    ; CHECK-LABEL: bb.0:
+  
+    $r14 = MOV64rr $rsi
+    $rbx = MOV64rr $rdi
+    $rax = MOV64ri 0
+    MOV64mr $rsp, 1, $noreg, 16, $noreg, $rax :: (store 8 into %stack.0)
+    $rax = MOV64ri 0
+
+    ;; A DBG_PHI of the stack should resolve to the stack location.
+    DBG_PHI %stack.0, 1, 64
+
+    ;; Reload value, clobber stack location.
+    $rcx = MOV64rm $rsp, 1, $noreg, 8, $noreg :: (load 8 from %stack.0)
+    MOV64mr $rsp, 1, $noreg, 16, $noreg, $rax :: (store 8 into %stack.0)
+
+    ;; This should resolve to the loaded register.
+    DBG_INSTR_REF 1, 0, !12, !DIExpression(), debug-location !13
+    ; CHECK:      DBG_INSTR_REF 1, 0,
+    ; CHECK-NEXT: DBG_VALUE $rcx
+
+    ;; And if we say it's a smaller size, we should be able to pick out smaller
+    ;; subregisters within the stack slot.
+    DBG_PHI %stack.0, 2, 32
+    $rax = MOV64ri 0
+    $rcx = MOV64rm $rsp, 1, $noreg, 8, $noreg :: (load 8 from %stack.0)
+    MOV64mr $rsp, 1, $noreg, 16, $noreg, $rax :: (store 8 into %stack.0)
+
+    ;; This should pick out the 32 bit value.
+    DBG_INSTR_REF 2, 0, !12, !DIExpression(), debug-location !13
+    ; CHECK:      DBG_INSTR_REF 2, 0,
+    ; CHECK-NEXT: DBG_VALUE $ecx
+
+    ;; Try all the other subregs.
+    DBG_PHI %stack.0, 3, 16
+    $rax = MOV64ri 0
+    $rcx = MOV64rm $rsp, 1, $noreg, 8, $noreg :: (load 8 from %stack.0)
+    MOV64mr $rsp, 1, $noreg, 16, $noreg, $rax :: (store 8 into %stack.0)
+
+    DBG_INSTR_REF 3, 0, !12, !DIExpression(), debug-location !13
+    ; CHECK:      DBG_INSTR_REF 3, 0,
+    ; CHECK-NEXT: DBG_VALUE $cx
+
+    DBG_PHI %stack.0, 4, 8
+    $rax = MOV64ri 0
+    $rcx = MOV64rm $rsp, 1, $noreg, 8, $noreg :: (load 8 from %stack.0)
+    MOV64mr $rsp, 1, $noreg, 16, $noreg, $rax :: (store 8 into %stack.0)
+
+    DBG_INSTR_REF 4, 0, !12, !DIExpression(), debug-location !13
+    ; CHECK:      DBG_INSTR_REF 4, 0,
+    ; CHECK-NEXT: DBG_VALUE $cl
+
+    ;; We can't, at this time, describe subregister fields with nonzero offset.
+    ;; It's easily achieved by attaching more data to stack DBG_PHIs, but it's
+    ;; not clear that LLVM will ever merge registers to generate such locations.
+
+    RET64 implicit $eax, debug-location !26
+
+...

diff  --git a/llvm/test/DebugInfo/MIR/InstrRef/phi-on-stack-coalesced.mir b/llvm/test/DebugInfo/MIR/InstrRef/phi-on-stack-coalesced.mir
new file mode 100644
index 0000000000000..a0b6d796ce64c
--- /dev/null
+++ b/llvm/test/DebugInfo/MIR/InstrRef/phi-on-stack-coalesced.mir
@@ -0,0 +1,156 @@
+# RUN: llc %s -o - -mtriple=x86_64-unknown-unknown \
+# RUN:    -experimental-debug-variable-locations \
+# RUN:    -start-before=phi-node-elimination -stop-after=virtregrewriter \
+# RUN:    | FileCheck %s
+#
+# Like phi-through-regalloc.mir, pass a PHI node into register allocation, and
+# test that it correctly comes out, in a stack slot. In this test the desired
+# value is a 16 bit copy of an argument, and the PHI register class is 16 bits.
+# It's subsequently coalesced into a larger vreg, which is then spilt as a 32
+# bit value.
+# Test that the coalescing happens (32 bits stored and loaded), but that we
+# record in the relevant DBG_PHI that the original value was 16 bits in size.
+# This avoids later ambiguity about how large the value on the stack is.
+
+--- |
+  ; ModuleID = 'promoted.ll'
+  source_filename = "test.c"
+  target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128"
+  target triple = "x86_64-unknown-linux-gnu"
+
+  define dso_local i32 @foo(i32 %bar, i32 %baz) !dbg !7 {
+  entry:
+    ret i32 0, !dbg !19
+  }
+
+  declare dso_local i32 @ext(i32)
+
+  ; Function Attrs: nounwind readnone speculatable willreturn
+  declare void @llvm.dbg.value(metadata, metadata, metadata)
+
+  !llvm.dbg.cu = !{!0}
+  !llvm.module.flags = !{!3, !4, !5}
+  !llvm.ident = !{!6}
+
+  !0 = distinct !DICompileUnit(language: DW_LANG_C99, file: !1, producer: "clang", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, enums: !2, splitDebugInlining: false, nameTableKind: None)
+  !1 = !DIFile(filename: "test.c", directory: ".")
+  !2 = !{}
+  !3 = !{i32 7, !"Dwarf Version", i32 4}
+  !4 = !{i32 2, !"Debug Info Version", i32 3}
+  !5 = !{i32 1, !"wchar_size", i32 4}
+  !6 = !{!"."}
+  !7 = distinct !DISubprogram(name: "foo", scope: !1, file: !1, line: 2, type: !8, scopeLine: 2, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition, unit: !0, retainedNodes: !2)
+  !8 = !DISubroutineType(types: !9)
+  !9 = !{!10, !10, !10}
+  !10 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed)
+  !11 = !DILocalVariable(name: "bar", arg: 1, scope: !7, file: !1, line: 2, type: !10)
+  !12 = !DILocation(line: 0, scope: !7)
+  !13 = !DILocalVariable(name: "baz", arg: 2, scope: !7, file: !1, line: 2, type: !10)
+  !14 = !DILocalVariable(name: "either", scope: !7, file: !1, line: 3, type: !10)
+  !15 = !DILocation(line: 4, column: 7, scope: !16)
+  !16 = distinct !DILexicalBlock(scope: !7, file: !1, line: 4, column: 7)
+  !17 = !DILocation(line: 4, column: 7, scope: !7)
+  !18 = !DILocation(line: 0, scope: !16)
+  !19 = !DILocation(line: 9, column: 3, scope: !7)
+
+...
+---
+name:            foo
+alignment:       16
+tracksRegLiveness: true
+registers:
+  - { id: 0, class: gr16 }
+  - { id: 1, class: gr32 }
+  - { id: 2, class: gr32 }
+  - { id: 3, class: gr32 }
+  - { id: 4, class: gr32 }
+liveins:
+  - { reg: '$edi', virtual-reg: '%1' }
+  - { reg: '$esi', virtual-reg: '%2' }
+frameInfo:
+  maxAlignment:    1
+  hasCalls:        true
+machineFunctionInfo: {}
+body:             |
+  ; CHECK-LABEL: bb.0:
+  ; CHECK:       MOV32mr %stack.0, 1, $noreg, 0, $noreg, $edi
+  bb.0:
+    successors: %bb.2(0x50000000), %bb.1(0x30000000)
+    liveins: $edi, $esi
+
+    DBG_VALUE $edi, $noreg, !11, !DIExpression(), debug-location !12
+    DBG_VALUE $esi, $noreg, !13, !DIExpression(), debug-location !12
+    %2:gr32 = COPY killed $esi
+    %1:gr32 = COPY killed $edi
+    %5:gr16 = COPY %1.sub_16bit
+    %6:gr16 = COPY %1.sub_16bit
+    ADJCALLSTACKDOWN64 0, 0, 0, implicit-def dead $rsp, implicit-def dead $eflags, implicit-def dead $ssp, implicit $rsp, implicit $ssp, debug-location !15
+    %3:gr32 = MOV32r0 implicit-def dead $eflags
+    $edi = COPY killed %3, debug-location !15
+    CALL64pcrel32 @ext, csr_64, implicit $rsp, implicit $ssp, implicit killed $edi, implicit-def $rsp, implicit-def $ssp, implicit-def $eax, debug-location !15
+    ADJCALLSTACKUP64 0, 0, implicit-def dead $rsp, implicit-def dead $eflags, implicit-def dead $ssp, implicit $rsp, implicit $ssp, debug-location !15
+    %4:gr32 = COPY killed $eax, debug-location !15
+    %10:gr32 = MOV32ri 0
+    %11:gr32 = MOV32ri 1
+    %12:gr32 = MOV32ri 2
+    %13:gr32 = MOV32ri 3
+    %14:gr32 = MOV32ri 4
+    %15:gr32 = MOV32ri 5
+    %16:gr32 = MOV32ri 6
+    %17:gr32 = MOV32ri 7
+    %18:gr32 = MOV32ri 8
+    %19:gr32 = MOV32ri 9
+    %20:gr32 = MOV32ri 10
+    %21:gr32 = MOV32ri 11
+    %22:gr32 = MOV32ri 12
+    %23:gr32 = MOV32ri 13
+    %24:gr32 = MOV32ri 14
+    TEST32rr killed %4, %4, implicit-def $eflags, debug-location !15
+    JCC_1 %bb.2, 5, implicit killed $eflags, debug-location !17
+    JMP_1 %bb.1, debug-location !17
+
+  bb.1:
+    %30:gr32 = MOV32ri 0
+    %31:gr32 = MOV32ri 1
+    %32:gr32 = MOV32ri 2
+    %33:gr32 = MOV32ri 3
+    %34:gr32 = MOV32ri 4
+    %35:gr32 = MOV32ri 5
+    %36:gr32 = MOV32ri 6
+    %37:gr32 = MOV32ri 7
+    %38:gr32 = MOV32ri 8
+    %39:gr32 = MOV32ri 9
+    %40:gr32 = MOV32ri 10
+    %41:gr32 = MOV32ri 11
+    %42:gr32 = MOV32ri 12
+    %43:gr32 = MOV32ri 13
+    %44:gr32 = MOV32ri 14
+
+    ; CHECK-LABEL: bb.2:
+  bb.2:
+    %0:gr16 = PHI %5, %bb.0, %6, %bb.1, debug-instr-number 1, debug-location !18
+    %50:gr32 = PHI %10, %bb.0, %30, %bb.1, debug-location !18
+    %51:gr32 = PHI %11, %bb.0, %31, %bb.1, debug-location !18
+    %52:gr32 = PHI %12, %bb.0, %32, %bb.1, debug-location !18
+    %53:gr32 = PHI %13, %bb.0, %33, %bb.1, debug-location !18
+    %54:gr32 = PHI %14, %bb.0, %34, %bb.1, debug-location !18
+    %55:gr32 = PHI %15, %bb.0, %35, %bb.1, debug-location !18
+    %56:gr32 = PHI %16, %bb.0, %36, %bb.1, debug-location !18
+    %57:gr32 = PHI %17, %bb.0, %37, %bb.1, debug-location !18
+    %58:gr32 = PHI %18, %bb.0, %38, %bb.1, debug-location !18
+    %59:gr32 = PHI %19, %bb.0, %39, %bb.1, debug-location !18
+    %60:gr32 = PHI %20, %bb.0, %40, %bb.1, debug-location !18
+    %61:gr32 = PHI %21, %bb.0, %41, %bb.1, debug-location !18
+    %62:gr32 = PHI %22, %bb.0, %42, %bb.1, debug-location !18
+    %63:gr32 = PHI %23, %bb.0, %43, %bb.1, debug-location !18
+    %64:gr32 = PHI %24, %bb.0, %44, %bb.1, debug-location !18
+
+    INLINEASM &"", 1, 12, %50, 12, %51, 12, %52, 12, %53, 12, %54, 12, %55, 12, %56, 12, %57, 12, %58, 12, %59, 12, %60, 12, %61, 12, %62, 12, %63, 12, %64
+    DBG_INSTR_REF 1, 0, !14, !DIExpression(), debug-location !12
+    ; CHECK:      DBG_PHI %stack.0, 1, 16
+    ; CHECK:      DBG_INSTR_REF 1, 0
+    ; CHECK:      renamable $eax = MOV32rm %stack.0,
+    $eax = COPY killed %0, debug-location !19
+    RET 0, killed $eax, debug-location !19
+
+...

diff  --git a/llvm/test/DebugInfo/MIR/InstrRef/phi-on-stack-coalesced2.mir b/llvm/test/DebugInfo/MIR/InstrRef/phi-on-stack-coalesced2.mir
new file mode 100644
index 0000000000000..1047c005a5ad6
--- /dev/null
+++ b/llvm/test/DebugInfo/MIR/InstrRef/phi-on-stack-coalesced2.mir
@@ -0,0 +1,155 @@
+# RUN: llc %s -o - -mtriple=x86_64-unknown-unknown \
+# RUN:    -experimental-debug-variable-locations \
+# RUN:    -start-before=phi-node-elimination -stop-after=virtregrewriter \
+# RUN:    | FileCheck %s
+#
+# Pass a PHI node into register allocation, and test that it is correctly
+# dropped.  In this test the desired value is an 8 bit copy of an argument,
+# but it's located in an upper subregister field. That coalesces back to the
+# whole argument, which is spilt to the stack.
+#
+# Currently, DBG_PHIs can't describe non-zero offsets in stack slots, therefore
+# no DBG_PHI should be emitted. (This means there is no value for that
+# instruction/operand number, and any DBG_INSTR_REF will become a
+# DBG_VALUE $noreg.
+
+--- |
+  ; ModuleID = 'promoted.ll'
+  source_filename = "test.c"
+  target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128"
+  target triple = "x86_64-unknown-linux-gnu"
+
+  define dso_local i32 @foo(i32 %bar, i32 %baz) !dbg !7 {
+  entry:
+    ret i32 0, !dbg !19
+  }
+
+  declare dso_local i32 @ext(i32)
+
+  ; Function Attrs: nounwind readnone speculatable willreturn
+  declare void @llvm.dbg.value(metadata, metadata, metadata)
+
+  !llvm.dbg.cu = !{!0}
+  !llvm.module.flags = !{!3, !4, !5}
+  !llvm.ident = !{!6}
+
+  !0 = distinct !DICompileUnit(language: DW_LANG_C99, file: !1, producer: "clang", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, enums: !2, splitDebugInlining: false, nameTableKind: None)
+  !1 = !DIFile(filename: "test.c", directory: ".")
+  !2 = !{}
+  !3 = !{i32 7, !"Dwarf Version", i32 4}
+  !4 = !{i32 2, !"Debug Info Version", i32 3}
+  !5 = !{i32 1, !"wchar_size", i32 4}
+  !6 = !{!"."}
+  !7 = distinct !DISubprogram(name: "foo", scope: !1, file: !1, line: 2, type: !8, scopeLine: 2, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition, unit: !0, retainedNodes: !2)
+  !8 = !DISubroutineType(types: !9)
+  !9 = !{!10, !10, !10}
+  !10 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed)
+  !11 = !DILocalVariable(name: "bar", arg: 1, scope: !7, file: !1, line: 2, type: !10)
+  !12 = !DILocation(line: 0, scope: !7)
+  !13 = !DILocalVariable(name: "baz", arg: 2, scope: !7, file: !1, line: 2, type: !10)
+  !14 = !DILocalVariable(name: "either", scope: !7, file: !1, line: 3, type: !10)
+  !15 = !DILocation(line: 4, column: 7, scope: !16)
+  !16 = distinct !DILexicalBlock(scope: !7, file: !1, line: 4, column: 7)
+  !17 = !DILocation(line: 4, column: 7, scope: !7)
+  !18 = !DILocation(line: 0, scope: !16)
+  !19 = !DILocation(line: 9, column: 3, scope: !7)
+
+...
+---
+name:            foo
+alignment:       16
+tracksRegLiveness: true
+registers:
+  - { id: 0, class: gr8 }
+  - { id: 1, class: gr32_abcd }
+  - { id: 2, class: gr32_abcd }
+  - { id: 3, class: gr32 }
+  - { id: 4, class: gr32 }
+liveins:
+  - { reg: '$edi', virtual-reg: '%1' }
+  - { reg: '$esi', virtual-reg: '%2' }
+frameInfo:
+  maxAlignment:    1
+  hasCalls:        true
+machineFunctionInfo: {}
+body:             |
+  bb.0:
+    successors: %bb.2(0x50000000), %bb.1(0x30000000)
+    liveins: $edi, $esi
+
+    DBG_VALUE $edi, $noreg, !11, !DIExpression(), debug-location !12
+    DBG_VALUE $esi, $noreg, !13, !DIExpression(), debug-location !12
+    %2:gr32_abcd = COPY killed $esi
+    %1:gr32_abcd = COPY killed $edi
+    %5:gr8 = COPY %1.sub_8bit_hi
+    %6:gr8 = COPY %1.sub_8bit_hi
+    ADJCALLSTACKDOWN64 0, 0, 0, implicit-def dead $rsp, implicit-def dead $eflags, implicit-def dead $ssp, implicit $rsp, implicit $ssp, debug-location !15
+    %3:gr32 = MOV32r0 implicit-def dead $eflags
+    $edi = COPY killed %3, debug-location !15
+    CALL64pcrel32 @ext, csr_64, implicit $rsp, implicit $ssp, implicit killed $edi, implicit-def $rsp, implicit-def $ssp, implicit-def $eax, debug-location !15
+    ADJCALLSTACKUP64 0, 0, implicit-def dead $rsp, implicit-def dead $eflags, implicit-def dead $ssp, implicit $rsp, implicit $ssp, debug-location !15
+    %4:gr32 = COPY killed $eax, debug-location !15
+    %10:gr32 = MOV32ri 0
+    %11:gr32 = MOV32ri 1
+    %12:gr32 = MOV32ri 2
+    %13:gr32 = MOV32ri 3
+    %14:gr32 = MOV32ri 4
+    %15:gr32 = MOV32ri 5
+    %16:gr32 = MOV32ri 6
+    %17:gr32 = MOV32ri 7
+    %18:gr32 = MOV32ri 8
+    %19:gr32 = MOV32ri 9
+    %20:gr32 = MOV32ri 10
+    %21:gr32 = MOV32ri 11
+    %22:gr32 = MOV32ri 12
+    %23:gr32 = MOV32ri 13
+    %24:gr32 = MOV32ri 14
+    TEST32rr killed %4, %4, implicit-def $eflags, debug-location !15
+    JCC_1 %bb.2, 5, implicit killed $eflags, debug-location !17
+    JMP_1 %bb.1, debug-location !17
+
+  bb.1:
+    %30:gr32 = MOV32ri 0
+    %31:gr32 = MOV32ri 1
+    %32:gr32 = MOV32ri 2
+    %33:gr32 = MOV32ri 3
+    %34:gr32 = MOV32ri 4
+    %35:gr32 = MOV32ri 5
+    %36:gr32 = MOV32ri 6
+    %37:gr32 = MOV32ri 7
+    %38:gr32 = MOV32ri 8
+    %39:gr32 = MOV32ri 9
+    %40:gr32 = MOV32ri 10
+    %41:gr32 = MOV32ri 11
+    %42:gr32 = MOV32ri 12
+    %43:gr32 = MOV32ri 13
+    %44:gr32 = MOV32ri 14
+
+    ; CHECK-LABEL: bb.2:
+  bb.2:
+    %0:gr8 = PHI %5, %bb.0, %6, %bb.1, debug-instr-number 1, debug-location !18
+    %50:gr32 = PHI %10, %bb.0, %30, %bb.1, debug-location !18
+    %51:gr32 = PHI %11, %bb.0, %31, %bb.1, debug-location !18
+    %52:gr32 = PHI %12, %bb.0, %32, %bb.1, debug-location !18
+    %53:gr32 = PHI %13, %bb.0, %33, %bb.1, debug-location !18
+    %54:gr32 = PHI %14, %bb.0, %34, %bb.1, debug-location !18
+    %55:gr32 = PHI %15, %bb.0, %35, %bb.1, debug-location !18
+    %56:gr32 = PHI %16, %bb.0, %36, %bb.1, debug-location !18
+    %57:gr32 = PHI %17, %bb.0, %37, %bb.1, debug-location !18
+    %58:gr32 = PHI %18, %bb.0, %38, %bb.1, debug-location !18
+    %59:gr32 = PHI %19, %bb.0, %39, %bb.1, debug-location !18
+    %60:gr32 = PHI %20, %bb.0, %40, %bb.1, debug-location !18
+    %61:gr32 = PHI %21, %bb.0, %41, %bb.1, debug-location !18
+    %62:gr32 = PHI %22, %bb.0, %42, %bb.1, debug-location !18
+    %63:gr32 = PHI %23, %bb.0, %43, %bb.1, debug-location !18
+    %64:gr32 = PHI %24, %bb.0, %44, %bb.1, debug-location !18
+
+    INLINEASM &"", 1, 12, %50, 12, %51, 12, %52, 12, %53, 12, %54, 12, %55, 12, %56, 12, %57, 12, %58, 12, %59, 12, %60, 12, %61, 12, %62, 12, %63, 12, %64
+    DBG_INSTR_REF 1, 0, !14, !DIExpression(), debug-location !12
+    ; CHECK-NOT:  DBG_PHI
+    ; CHECK:      DBG_INSTR_REF 1, 0
+    ; CHECK-NOT:  DBG_PHI
+    $eax = COPY killed %0, debug-location !19
+    RET 0, killed $eax, debug-location !19
+
+...

diff  --git a/llvm/test/DebugInfo/MIR/InstrRef/phi-regallocd-to-stack.mir b/llvm/test/DebugInfo/MIR/InstrRef/phi-regallocd-to-stack.mir
index b40f2ae9cb6d0..f8733e1128f95 100644
--- a/llvm/test/DebugInfo/MIR/InstrRef/phi-regallocd-to-stack.mir
+++ b/llvm/test/DebugInfo/MIR/InstrRef/phi-regallocd-to-stack.mir
@@ -140,7 +140,7 @@ body:             |
     %64:gr32 = PHI %24, %bb.0, %44, %bb.1, debug-location !18
 
     DBG_INSTR_REF 1, 0, !14, !DIExpression(), debug-location !12
-    ; CHECK:      DBG_PHI %stack.1, 1
+    ; CHECK:      DBG_PHI %stack.1, 1, 32
     ; CHECK:      renamable $eax = MOV32rm %stack.1,
     ; CHECK:      DBG_INSTR_REF 1, 0
     $eax = COPY killed %0, debug-location !19

diff  --git a/llvm/unittests/CodeGen/InstrRefLDVTest.cpp b/llvm/unittests/CodeGen/InstrRefLDVTest.cpp
index c47c83ad65162..db9107b9b5bcd 100644
--- a/llvm/unittests/CodeGen/InstrRefLDVTest.cpp
+++ b/llvm/unittests/CodeGen/InstrRefLDVTest.cpp
@@ -1113,9 +1113,10 @@ TEST_F(InstrRefLDVTest, MLocDiamondSpills) {
   // Create a stack location and ensure it's tracked.
   SpillLoc SL = {getRegByName("RSP"), StackOffset::getFixed(-8)};
   SpillLocationNo SpillNo = *MTracker->getOrTrackSpillLoc(SL);
-  ASSERT_EQ(MTracker->getNumLocs(), 10u); // Tracks all possible stack locs.
+  ASSERT_EQ(MTracker->getNumLocs(), 11u); // Tracks all possible stack locs.
   // Locations are: RSP, stack slots from 2^3 bits wide up to 2^9 for zmm regs,
   // then slots for sub_8bit_hi and sub_16bit_hi ({8, 8} and {16, 16}).
+  // Finally, one for spilt fp80 registers.
 
   // Pick out the locations on the stack that various x86 regs would be written
   // to. HAX is the upper 16 bits of EAX.


        


More information about the llvm-commits mailing list