[llvm] ae4303b - [DebugInstrRef][2/3] Track PHI values through register coalescing

Jeremy Morse via llvm-commits llvm-commits at lists.llvm.org
Thu Jun 3 09:07:16 PDT 2021


Author: Jeremy Morse
Date: 2021-06-03T17:06:51+01:00
New Revision: ae4303b42cfa5c8c14e3fff67d73af2f154aea9a

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

LOG: [DebugInstrRef][2/3] Track PHI values through register coalescing

In the instruction referencing variable location model, we store variable
locations that point at PHIs in MachineFunction during register
allocation. Unfortunately, register coalescing can substantially change
the locations of registers, and so that PHI-variable-location side table
needs maintenence during the pass.

This patch builds an index from the side table, and whenever a vreg gets
coalesced into another vreg, update the index to record the new vreg that
the PHI happens in. It also accepts a limited range of subregister
coalescing, for example merging a subregister into a larger class.

Differential Revision: https://reviews.llvm.org/D86813

Added: 
    llvm/test/DebugInfo/MIR/InstrRef/phi-coalesce-subreg.mir
    llvm/test/DebugInfo/MIR/InstrRef/phi-coalescing.mir

Modified: 
    llvm/lib/CodeGen/RegisterCoalescer.cpp

Removed: 
    


################################################################################
diff  --git a/llvm/lib/CodeGen/RegisterCoalescer.cpp b/llvm/lib/CodeGen/RegisterCoalescer.cpp
index f535688320b35..dd5e490dbea56 100644
--- a/llvm/lib/CodeGen/RegisterCoalescer.cpp
+++ b/llvm/lib/CodeGen/RegisterCoalescer.cpp
@@ -133,6 +133,20 @@ namespace {
     AliasAnalysis *AA = nullptr;
     RegisterClassInfo RegClassInfo;
 
+    /// Position and VReg of a PHI instruction during coalescing.
+    struct PHIValPos {
+      SlotIndex SI;    ///< Slot where this PHI occurs.
+      Register Reg;    ///< VReg the PHI occurs in.
+      unsigned SubReg; ///< Qualifying subregister for Reg.
+    };
+
+    /// Map from debug instruction number to PHI position during coalescing.
+    DenseMap<unsigned, PHIValPos> PHIValToPos;
+    /// Index of, for each VReg, which debug instruction numbers and
+    /// corresponding PHIs are sensitive to coalescing. Each VReg may have
+    /// multiple PHI defs, at 
diff erent positions.
+    DenseMap<Register, SmallVector<unsigned, 2>> RegToPHIIdx;
+
     /// Debug variable location tracking -- for each VReg, maintain an
     /// ordered-by-slot-index set of DBG_VALUEs, to help quick
     /// identification of whether coalescing may change location validity.
@@ -3546,6 +3560,64 @@ bool RegisterCoalescer::joinVirtRegs(CoalescerPair &CP) {
   // Scan and mark undef any DBG_VALUEs that would refer to a 
diff erent value.
   checkMergingChangesDbgValues(CP, LHS, LHSVals, RHS, RHSVals);
 
+  // If the RHS covers any PHI locations that were tracked for debug-info, we
+  // must update tracking information to reflect the join.
+  auto RegIt = RegToPHIIdx.find(CP.getSrcReg());
+  if (RegIt != RegToPHIIdx.end()) {
+    // Iterate over all the debug instruction numbers assigned this register.
+    for (unsigned InstID : RegIt->second) {
+      auto PHIIt = PHIValToPos.find(InstID);
+      assert(PHIIt != PHIValToPos.end());
+      const SlotIndex &SI = PHIIt->second.SI;
+
+      // Does the RHS cover the position of this PHI?
+      auto LII = RHS.find(SI);
+      if (LII == RHS.end() || LII->start > SI)
+        continue;
+
+      // Accept two kinds of subregister movement:
+      //  * When we merge from one register class into a larger register:
+      //        %1:gr16 = some-inst
+      //                ->
+      //        %2:gr32.sub_16bit = some-inst
+      //  * When the PHI is already in a subregister, and the larger class
+      //    is coalesced:
+      //        %2:gr32.sub_16bit = some-inst
+      //        %3:gr32 = COPY %2
+      //                ->
+      //        %3:gr32.sub_16bit = some-inst
+      // Test for subregister move:
+      if (CP.getSrcIdx() != 0 || CP.getDstIdx() != 0)
+        // If we're moving between 
diff erent subregisters, ignore this join.
+        // The PHI will not get a location, dropping variable locations.
+        if (PHIIt->second.SubReg && PHIIt->second.SubReg != CP.getSrcIdx())
+          continue;
+
+      // Update our tracking of where the PHI is.
+      PHIIt->second.Reg = CP.getDstReg();
+
+      // If we merge into a sub-register of a larger class (test above),
+      // update SubReg.
+      if (CP.getSrcIdx() != 0)
+        PHIIt->second.SubReg = CP.getSrcIdx();
+    }
+
+    // Rebuild the register index in RegToPHIIdx to account for PHIs tracking
+    // 
diff erent VRegs now. Copy old collection of debug instruction numbers and
+    // erase the old one:
+    auto InstrNums = RegIt->second;
+    RegToPHIIdx.erase(RegIt);
+
+    // There might already be PHIs being tracked in the destination VReg. Insert
+    // into an existing tracking collection, or insert a new one.
+    RegIt = RegToPHIIdx.find(CP.getDstReg());
+    if (RegIt != RegToPHIIdx.end())
+      RegIt->second.insert(RegIt->second.end(), InstrNums.begin(),
+                           InstrNums.end());
+    else
+      RegToPHIIdx.insert({CP.getDstReg(), InstrNums});
+  }
+
   // Join RHS into LHS.
   LHS.join(RHS, LHSVals.getAssignments(), RHSVals.getAssignments(), NewVNInfo);
 
@@ -4007,6 +4079,19 @@ bool RegisterCoalescer::runOnMachineFunction(MachineFunction &fn) {
   else
     JoinGlobalCopies = (EnableGlobalCopies == cl::BOU_TRUE);
 
+  // If there are PHIs tracked by debug-info, they will need updating during
+  // coalescing. Build an index of those PHIs to ease updating.
+  SlotIndexes *Slots = LIS->getSlotIndexes();
+  for (const auto &DebugPHI : MF->DebugPHIPositions) {
+    MachineBasicBlock *MBB = DebugPHI.second.MBB;
+    Register Reg = DebugPHI.second.Reg;
+    unsigned SubReg = DebugPHI.second.SubReg;
+    SlotIndex SI = Slots->getMBBStartIdx(MBB);
+    PHIValPos P = {SI, Reg, SubReg};
+    PHIValToPos.insert(std::make_pair(DebugPHI.first, P));
+    RegToPHIIdx[Reg].push_back(DebugPHI.first);
+  }
+
   // The MachineScheduler does not currently require JoinSplitEdges. This will
   // either be enabled unconditionally or replaced by a more general live range
   // splitting optimization.
@@ -4062,6 +4147,18 @@ bool RegisterCoalescer::runOnMachineFunction(MachineFunction &fn) {
     }
   }
 
+  // After coalescing, update any PHIs that are being tracked by debug-info
+  // with their new VReg locations.
+  for (auto &p : MF->DebugPHIPositions) {
+    auto it = PHIValToPos.find(p.first);
+    assert(it != PHIValToPos.end());
+    p.second.Reg = it->second.Reg;
+    p.second.SubReg = it->second.SubReg;
+  }
+
+  PHIValToPos.clear();
+  RegToPHIIdx.clear();
+
   LLVM_DEBUG(dump());
   if (VerifyCoalescing)
     MF->verify(this, "After register coalescing");

diff  --git a/llvm/test/DebugInfo/MIR/InstrRef/phi-coalesce-subreg.mir b/llvm/test/DebugInfo/MIR/InstrRef/phi-coalesce-subreg.mir
new file mode 100644
index 0000000000000..b337fd6ccc585
--- /dev/null
+++ b/llvm/test/DebugInfo/MIR/InstrRef/phi-coalesce-subreg.mir
@@ -0,0 +1,165 @@
+# RUN: llc %s -o - -mtriple=x86_64-unknown-unknown \
+# RUN:    -experimental-debug-variable-locations \
+# RUN:    -run-pass=phi-node-elimination,simple-register-coalescing \
+# RUN:    | FileCheck %s --check-prefix=DOESCOALESCE
+# RUN: llc %s -o - -mtriple=x86_64-unknown-unknown \
+# RUN:    -experimental-debug-variable-locations \
+# RUN:    -run-pass=phi-node-elimination,simple-register-coalescing,livedebugvars,greedy,virtregrewriter \
+# RUN:    | FileCheck %s --check-prefix=CHECK
+#
+# This is a sibling-test for phi-coalescing.mir, using similar code but where
+# registers are coalesced across subregisters. Specifically, vreg %2 below is
+# a 16-bit register, but will be coalesced into the lower 16 bits of a 32 bit
+# vreg during coalescing. We should survive this transformation, and emit a
+# DBG_PHI for $bx where the PHI was.
+--- |
+  ; 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"
+  
+  ; Function Attrs: noinline nounwind uwtable
+  define dso_local i32 @foo(i16 signext %bar, i16 signext %baz) !dbg !7 {
+  entry:
+    call void @llvm.dbg.value(metadata i16 %bar, metadata !12, metadata !DIExpression()), !dbg !13
+    call void @llvm.dbg.value(metadata i16 %baz, metadata !14, metadata !DIExpression()), !dbg !13
+    call void @ext(i16 signext %bar), !dbg !13
+    %conv = sext i16 %bar to i32, !dbg !13
+    %add = add nsw i32 %conv, 12, !dbg !13
+    %conv1 = trunc i32 %add to i16, !dbg !13
+    call void @llvm.dbg.value(metadata i16 %conv1, metadata !12, metadata !DIExpression()), !dbg !13
+    call void @ext(i16 signext %conv1), !dbg !13
+    %call = call signext i16 @getlong(), !dbg !13
+    %tobool = icmp ne i16 %call, 0, !dbg !13
+    br i1 %tobool, label %if.then, label %if.end, !dbg !13
+  
+  if.then:                                          ; preds = %entry
+    %conv2 = sext i16 %conv1 to i32, !dbg !13
+    %add3 = add nsw i32 %conv2, 1, !dbg !13
+    %conv4 = trunc i32 %add3 to i16, !dbg !13
+    call void @llvm.dbg.value(metadata i16 %conv4, metadata !12, metadata !DIExpression()), !dbg !13
+    br label %if.end, !dbg !13
+  
+  if.end:                                           ; preds = %if.then, %entry
+    %bar.addr.0 = phi i16 [ %conv4, %if.then ], [ %conv1, %entry ], !dbg !13
+    call void @llvm.dbg.value(metadata i16 %bar.addr.0, metadata !12, metadata !DIExpression()), !dbg !13
+    %conv5 = sext i16 %baz to i32, !dbg !13
+    %conv6 = sext i16 %bar.addr.0 to i32, !dbg !13
+    %add7 = add nsw i32 %conv6, %conv5, !dbg !13
+    %conv8 = trunc i32 %add7 to i16, !dbg !13
+    call void @llvm.dbg.value(metadata i16 %conv8, metadata !12, metadata !DIExpression()), !dbg !13
+    call void @ext(i16 signext %conv8), !dbg !13
+    %conv9 = sext i16 %conv8 to i32, !dbg !13
+    ret i32 %conv9, !dbg !13
+  }
+  
+  ; Function Attrs: nounwind readnone speculatable willreturn
+  declare void @llvm.dbg.declare(metadata, metadata, metadata)
+  
+  declare dso_local void @ext(i16 signext)
+  
+  declare dso_local signext i16 @getlong()
+  
+  ; 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 version 12.0.0 (git at github.com:llvm/llvm-project 79a35789efdf2378f97642ae4a5f3099b9087a11)", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, enums: !2, splitDebugInlining: false, nameTableKind: None)
+  !1 = !DIFile(filename: "test.c", directory: "/fast/fs/llvm3/llvm/test/DebugInfo/MIR/InstrRef")
+  !2 = !{}
+  !3 = !{i32 7, !"Dwarf Version", i32 4}
+  !4 = !{i32 2, !"Debug Info Version", i32 3}
+  !5 = !{i32 1, !"wchar_size", i32 4}
+  !6 = !{!"clang version 12.0.0 (git at github.com:llvm/llvm-project 79a35789efdf2378f97642ae4a5f3099b9087a11)"}
+  !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: "short", size: 16, 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)
+  !15 = distinct !DILexicalBlock(scope: !7, file: !1, line: 8, column: 7)
+
+...
+---
+name:            foo
+alignment:       16
+tracksRegLiveness: true
+liveins:
+  - { reg: '$edi', virtual-reg: '%3' }
+  - { reg: '$esi', virtual-reg: '%4' }
+frameInfo:
+  maxAlignment:    1
+  hasCalls:        true
+machineFunctionInfo: {}
+body:             |
+  bb.0.entry:
+    liveins: $edi, $esi
+  
+    %4:gr32 = COPY $esi
+    %3:gr32 = COPY $edi
+    %6:gr16 = COPY %4.sub_16bit
+    %5:gr16 = COPY %3.sub_16bit
+    DBG_VALUE %5, $noreg, !12, !DIExpression(), debug-location !13
+    DBG_VALUE %6, $noreg, !14, !DIExpression(), debug-location !13
+    ADJCALLSTACKDOWN64 0, 0, 0, implicit-def $rsp, implicit-def $eflags, implicit-def $ssp, implicit $rsp, implicit $ssp, debug-location !13
+    %15:gr32 = MOVSX32rr16 %5, debug-location !13
+    $edi = COPY %15, debug-location !13
+    CALL64pcrel32 @ext, csr_64, implicit $rsp, implicit $ssp, implicit $edi, debug-location !13
+    ADJCALLSTACKUP64 0, 0, implicit-def $rsp, implicit-def $eflags, implicit-def $ssp, implicit $rsp, implicit $ssp, debug-location !13
+    %14:gr32 = MOVSX32rr16 %5, debug-location !13
+    %13:gr32 = ADD32ri8 killed %14, 12, implicit-def $eflags, debug-location !13
+    %11:gr16 = COPY killed %13.sub_16bit, debug-location !13
+    DBG_VALUE %11, $noreg, !12, !DIExpression(), debug-location !13
+    ADJCALLSTACKDOWN64 0, 0, 0, implicit-def $rsp, implicit-def $eflags, implicit-def $ssp, implicit $rsp, implicit $ssp, debug-location !13
+    %9:gr32 = MOVSX32rr16 %11, debug-location !13
+    $edi = COPY %9, debug-location !13
+    CALL64pcrel32 @ext, csr_64, implicit $rsp, implicit $ssp, implicit $edi, debug-location !13
+    ADJCALLSTACKUP64 0, 0, implicit-def $rsp, implicit-def $eflags, implicit-def $ssp, implicit $rsp, implicit $ssp, debug-location !13
+    ADJCALLSTACKDOWN64 0, 0, 0, implicit-def $rsp, implicit-def $eflags, implicit-def $ssp, implicit $rsp, implicit $ssp, debug-location !13
+    CALL64pcrel32 @getlong, csr_64, implicit $rsp, implicit $ssp, implicit-def $ax, debug-location !13
+    ADJCALLSTACKUP64 0, 0, implicit-def $rsp, implicit-def $eflags, implicit-def $ssp, implicit $rsp, implicit $ssp, debug-location !13
+    %8:gr16 = COPY $ax, debug-location !13
+    CMP16ri8 %8, 0, implicit-def $eflags, debug-location !13
+    JCC_1 %bb.2, 4, implicit $eflags, debug-location !13
+  
+  ; DOESCOALESCE-LABEL: bb.1.if.then:
+  ; CHECK-LABEL:        bb.1.if.then:
+  bb.1.if.then:
+    %20:gr32 = MOVSX32rr16 %11, debug-location !13
+    %19:gr32 = ADD32ri8 killed %20, 1, implicit-def $eflags, debug-location !13
+    %17:gr16 = COPY killed %19.sub_16bit, debug-location !13
+    DBG_VALUE %17, $noreg, !12, !DIExpression(), debug-location !13
+
+  ; Verify that vreg 17 is coalesced into gr32.
+  ; DOESCOALESCE:       %{{[0-9]+}}:gr32 = ADD32ri8
+  ; DOESCOALESCE-NEXT:  DBG_VALUE %{{[0-9]+}}.sub_16bit,
+  ; Verify those registers land in $bx
+  ; CHECK:              renamable $ebp = ADD32ri8
+  ; CHECK-NEXT:         DBG_VALUE $bp
+
+  ; DOESCOALESCE-LABEL: bb.2.if.end:
+  ; CHECK-LABEL:        bb.2.if.end:
+  bb.2.if.end:
+    %2:gr16 = PHI %11, %bb.0, %17, %bb.1, debug-instr-number 1, debug-location !13
+  ; CHECK:              DBG_PHI $bp, 1
+    DBG_INSTR_REF 1, 0, !12, !DIExpression(), debug-location !13
+    %31:gr32 = MOVSX32rr16 %6, debug-location !13
+    %30:gr32 = MOVSX32rr16 killed %2, debug-location !13
+    %29:gr32 = ADD32rr killed %30, killed %31, implicit-def $eflags, debug-location !13
+    %26:gr16 = COPY killed %29.sub_16bit, debug-location !13
+    DBG_VALUE %26, $noreg, !12, !DIExpression(), debug-location !13
+    ADJCALLSTACKDOWN64 0, 0, 0, implicit-def $rsp, implicit-def $eflags, implicit-def $ssp, implicit $rsp, implicit $ssp, debug-location !13
+    %24:gr32 = MOVSX32rr16 %26, debug-location !13
+    $edi = COPY %24, debug-location !13
+    CALL64pcrel32 @ext, csr_64, implicit $rsp, implicit $ssp, implicit $edi, debug-location !13
+    ADJCALLSTACKUP64 0, 0, implicit-def $rsp, implicit-def $eflags, implicit-def $ssp, implicit $rsp, implicit $ssp, debug-location !13
+    %23:gr32 = MOVSX32rr16 %26, debug-location !13
+    $eax = COPY %23, debug-location !13
+    RETQ implicit $eax, debug-location !13
+
+...

diff  --git a/llvm/test/DebugInfo/MIR/InstrRef/phi-coalescing.mir b/llvm/test/DebugInfo/MIR/InstrRef/phi-coalescing.mir
new file mode 100644
index 0000000000000..ae4b68b8c2654
--- /dev/null
+++ b/llvm/test/DebugInfo/MIR/InstrRef/phi-coalescing.mir
@@ -0,0 +1,165 @@
+# RUN: llc %s -o - -mtriple=x86_64-unknown-unknown \
+# RUN:    -experimental-debug-variable-locations \
+# RUN:    -run-pass=phi-node-elimination,simple-register-coalescing \
+# RUN:    | FileCheck %s --check-prefix=DOESCOALESCE
+# RUN: llc %s -o - -mtriple=x86_64-unknown-unknown \
+# RUN:    -experimental-debug-variable-locations \
+# RUN:    -run-pass=phi-node-elimination,simple-register-coalescing,livedebugvars,greedy,virtregrewriter \
+# RUN:    | FileCheck %s --check-prefix=CHECK
+#
+# Test that a PHI with a debug instruction number attached survives register
+# coalescing, when its vreg gets coalesced. This test comes in two parts, first
+# that coalescing actually happens, second that a DBG_PHI is still produced
+# afterwards.
+#
+# Original C code, the PHI is of the value of 'bar' after the control flow.
+# Compiled at -O0, applied -mem2reg, llc -O0, then manually added the PHI
+# instruction label.
+#
+#    void ext(long);
+#    long getlong(void);
+#    int foo(long bar, long baz) {
+#      ext(bar);
+#      bar += 12;
+#      ext(bar);
+#    
+#      if (getlong())
+#        bar += 1;
+#    
+#      bar += baz;
+#      ext(bar);
+#      return bar;
+#    }
+#
+--- |
+  ; 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(i64 %bar, i64 %baz) !dbg !7 {
+  entry:
+    call void @llvm.dbg.value(metadata i64 %bar, metadata !12, metadata !DIExpression()), !dbg !13
+    call void @llvm.dbg.value(metadata i64 %baz, metadata !14, metadata !DIExpression()), !dbg !13
+    call void @ext(i64 %bar), !dbg !13
+    %add = add nsw i64 %bar, 12, !dbg !13
+    call void @llvm.dbg.value(metadata i64 %add, metadata !12, metadata !DIExpression()), !dbg !13
+    call void @ext(i64 %add), !dbg !13
+    %call = call i64 @getlong(), !dbg !13
+    %tobool = icmp ne i64 %call, 0, !dbg !13
+    br i1 %tobool, label %if.then, label %if.end, !dbg !13
+  
+  if.then:                                          ; preds = %entry
+    %add1 = add nsw i64 %add, 1, !dbg !13
+    call void @llvm.dbg.value(metadata i64 %add1, metadata !12, metadata !DIExpression()), !dbg !13
+    br label %if.end, !dbg !13
+  
+  if.end:                                           ; preds = %if.then, %entry
+    %bar.addr.0 = phi i64 [ %add1, %if.then ], [ %add, %entry ], !dbg !13
+    call void @llvm.dbg.value(metadata i64 %bar.addr.0, metadata !12, metadata !DIExpression()), !dbg !13
+    %add2 = add nsw i64 %bar.addr.0, %baz, !dbg !13
+    call void @llvm.dbg.value(metadata i64 %add2, metadata !12, metadata !DIExpression()), !dbg !13
+    call void @ext(i64 %add2), !dbg !13
+    %conv = trunc i64 %add2 to i32, !dbg !13
+    ret i32 %conv, !dbg !13
+  }
+  
+  ; Function Attrs: nounwind readnone speculatable willreturn
+  declare void @llvm.dbg.declare(metadata, metadata, metadata)
+  
+  declare dso_local void @ext(i64)
+  
+  declare dso_local i64 @getlong()
+  
+  ; 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, 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)
+  !15 = distinct !DILexicalBlock(scope: !7, file: !1, line: 8, column: 7)
+
+...
+---
+name:            foo
+alignment:       16
+tracksRegLiveness: true
+liveins:
+  - { reg: '$rdi', virtual-reg: '%3' }
+  - { reg: '$rsi', virtual-reg: '%5' }
+frameInfo:
+  maxAlignment:    1
+  hasCalls:        true
+machineFunctionInfo: {}
+body:             |
+  bb.0.entry:
+    liveins: $rdi, $rsi
+  
+    %5:gr64 = COPY $rsi
+    %3:gr64 = COPY $rdi
+    %4:gr64 = COPY killed %3
+    %6:gr64 = COPY killed %5
+    DBG_VALUE %4, $noreg, !12, !DIExpression(), debug-location !13
+    DBG_VALUE %6, $noreg, !14, !DIExpression(), debug-location !13
+    ADJCALLSTACKDOWN64 0, 0, 0, implicit-def $rsp, implicit-def $eflags, implicit-def $ssp, implicit $rsp, implicit $ssp, debug-location !13
+    $rdi = COPY %4, debug-location !13
+    CALL64pcrel32 @ext, csr_64, implicit $rsp, implicit $ssp, implicit $rdi, debug-location !13
+    ADJCALLSTACKUP64 0, 0, implicit-def $rsp, implicit-def $eflags, implicit-def $ssp, implicit $rsp, implicit $ssp, debug-location !13
+    %9:gr64 = ADD64ri32 %4, 12, implicit-def $eflags, debug-location !13
+    DBG_VALUE %9, $noreg, !12, !DIExpression(), debug-location !13
+    ADJCALLSTACKDOWN64 0, 0, 0, implicit-def $rsp, implicit-def $eflags, implicit-def $ssp, implicit $rsp, implicit $ssp, debug-location !13
+    $rdi = COPY %9, debug-location !13
+    CALL64pcrel32 @ext, csr_64, implicit $rsp, implicit $ssp, implicit $rdi, debug-location !13
+    ADJCALLSTACKUP64 0, 0, implicit-def $rsp, implicit-def $eflags, implicit-def $ssp, implicit $rsp, implicit $ssp, debug-location !13
+    ADJCALLSTACKDOWN64 0, 0, 0, implicit-def $rsp, implicit-def $eflags, implicit-def $ssp, implicit $rsp, implicit $ssp, debug-location !13
+    CALL64pcrel32 @getlong, csr_64, implicit $rsp, implicit $ssp, implicit-def $rax, debug-location !13
+    ADJCALLSTACKUP64 0, 0, implicit-def $rsp, implicit-def $eflags, implicit-def $ssp, implicit $rsp, implicit $ssp, debug-location !13
+    %8:gr64 = COPY $rax, debug-location !13
+    CMP64ri8 %8, 0, implicit-def $eflags, debug-location !13
+    JCC_1 %bb.2, 4, implicit $eflags, debug-location !13
+  
+  ; DOESCOALESCE-LABEL: bb.1.if.then:
+  ; CHECK-LABEL:        bb.1.if.then:
+  bb.1.if.then:
+    %10:gr64 = ADD64ri32 %9, 1, implicit-def $eflags, debug-location !13
+    DBG_VALUE %10, $noreg, !12, !DIExpression(), debug-location !13
+
+  ; Verify that the vreg is 
diff erent immediately after register coalescing.
+  ; DOESCOALESCE-NOT:   %10:gr64 ADD64ri32
+  ; DOESCOALESCE:       %{{[0-9]+}}:gr64 = ADD64ri32
+  ; Verify that all these registers land in rbx.
+  ; CHECK:              renamable $rbx = ADD64ri32 killed renamable $rbx
+  
+  ; DOESCOALESCE-LABEL: bb.2.if.end:
+  ; CHECK-LABEL:        bb.2.if.end:
+  bb.2.if.end:
+    %2:gr64 = PHI %9, %bb.0, %10, %bb.1, debug-instr-number 1, debug-location !13
+  ; CHECK:              DBG_PHI $rbx, 1
+    DBG_INSTR_REF 1, 0, !12, !DIExpression(), debug-location !13
+    %14:gr64 = ADD64rr killed %2, %6, implicit-def $eflags, debug-location !13
+    DBG_VALUE %14, $noreg, !12, !DIExpression(), debug-location !13
+    ADJCALLSTACKDOWN64 0, 0, 0, implicit-def $rsp, implicit-def $eflags, implicit-def $ssp, implicit $rsp, implicit $ssp, debug-location !13
+    $rdi = COPY %14, debug-location !13
+    CALL64pcrel32 @ext, csr_64, implicit $rsp, implicit $ssp, implicit $rdi, debug-location !13
+    ADJCALLSTACKUP64 0, 0, implicit-def $rsp, implicit-def $eflags, implicit-def $ssp, implicit $rsp, implicit $ssp, debug-location !13
+    %13:gr32 = COPY %14.sub_32bit, debug-location !13
+    $eax = COPY %13, debug-location !13
+    RETQ implicit $eax, debug-location !13
+
+...


        


More information about the llvm-commits mailing list