1
0
mirror of https://github.com/RPCS3/llvm-mirror.git synced 2024-11-23 19:23:23 +01:00

[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
This commit is contained in:
Jeremy Morse 2021-06-03 16:43:49 +01:00
parent 7e79d4f8dc
commit 8e310e3825
3 changed files with 427 additions and 0 deletions

View File

@ -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 different 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 different 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 different 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
// different 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");

View File

@ -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@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@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
...

View File

@ -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 different 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
...