<html xmlns:v="urn:schemas-microsoft-com:vml" xmlns:o="urn:schemas-microsoft-com:office:office" xmlns:w="urn:schemas-microsoft-com:office:word" xmlns:m="http://schemas.microsoft.com/office/2004/12/omml" xmlns="http://www.w3.org/TR/REC-html40">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<meta name="Generator" content="Microsoft Word 14 (filtered medium)">
<style><!--
/* Font Definitions */
@font-face
        {font-family:Calibri;
        panose-1:2 15 5 2 2 2 4 3 2 4;}
@font-face
        {font-family:Tahoma;
        panose-1:2 11 6 4 3 5 4 4 2 4;}
/* Style Definitions */
p.MsoNormal, li.MsoNormal, div.MsoNormal
        {margin:0in;
        margin-bottom:.0001pt;
        font-size:12.0pt;
        font-family:"Times New Roman","serif";}
a:link, span.MsoHyperlink
        {mso-style-priority:99;
        color:blue;
        text-decoration:underline;}
a:visited, span.MsoHyperlinkFollowed
        {mso-style-priority:99;
        color:purple;
        text-decoration:underline;}
span.EmailStyle17
        {mso-style-type:personal-reply;
        font-family:"Calibri","sans-serif";
        color:#1F497D;}
.MsoChpDefault
        {mso-style-type:export-only;
        font-family:"Calibri","sans-serif";}
@page WordSection1
        {size:8.5in 11.0in;
        margin:1.0in 1.0in 1.0in 1.0in;}
div.WordSection1
        {page:WordSection1;}
--></style><!--[if gte mso 9]><xml>
<o:shapedefaults v:ext="edit" spidmax="1026" />
</xml><![endif]--><!--[if gte mso 9]><xml>
<o:shapelayout v:ext="edit">
<o:idmap v:ext="edit" data="1" />
</o:shapelayout></xml><![endif]-->
</head>
<body lang="EN-US" link="blue" vlink="purple">
<div class="WordSection1">
<p class="MsoNormal"><span style="font-size:11.0pt;font-family:"Calibri","sans-serif";color:#1F497D">Hi Jordan, Jeremy is in the UK so if you want to revert now I think that would be fine. Or you can wait until he's in tomorrow.<o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size:11.0pt;font-family:"Calibri","sans-serif";color:#1F497D">--paulr<o:p></o:p></span></p>
<p class="MsoNormal"><a name="_MailEndCompose"><span style="font-size:11.0pt;font-family:"Calibri","sans-serif";color:#1F497D"><o:p> </o:p></span></a></p>
<div style="border:none;border-left:solid blue 1.5pt;padding:0in 0in 0in 4.0pt">
<div>
<div style="border:none;border-top:solid #B5C4DF 1.0pt;padding:3.0pt 0in 0in 0in">
<p class="MsoNormal"><b><span style="font-size:10.0pt;font-family:"Tahoma","sans-serif"">From:</span></b><span style="font-size:10.0pt;font-family:"Tahoma","sans-serif""> llvm-commits [mailto:llvm-commits-bounces@lists.llvm.org]
<b>On Behalf Of </b>Jordan Rupprecht via llvm-commits<br>
<b>Sent:</b> Monday, July 08, 2019 6:09 PM<br>
<b>To:</b> Jeremy Morse<br>
<b>Cc:</b> llvm-commits<br>
<b>Subject:</b> Re: [llvm] r364515 - [DebugInfo] Avoid register coalesing unsoundly changing DBG_VALUE locations<o:p></o:p></span></p>
</div>
</div>
<p class="MsoNormal"><o:p> </o:p></p>
<div>
<p class="MsoNormal">Forgot to mention, we don't have specific timings yet, but we're seeing files take >15min to compile that were previously taking a minute or two -- so it's a pretty large increase.<o:p></o:p></p>
</div>
<p class="MsoNormal"><o:p> </o:p></p>
<div>
<div>
<p class="MsoNormal">On Mon, Jul 8, 2019 at 4:24 PM Jordan Rupprecht <<a href="mailto:rupprecht@google.com">rupprecht@google.com</a>> wrote:<o:p></o:p></p>
</div>
<blockquote style="border:none;border-left:solid #CCCCCC 1.0pt;padding:0in 0in 0in 6.0pt;margin-left:4.8pt;margin-right:0in">
<div>
<p class="MsoNormal">Hi Jeremy,<o:p></o:p></p>
<div>
<p class="MsoNormal">We're seeing some compilation timeouts as a result of this patch. Mind if we revert this until we can get a public reproducer w/ timings showing the regression?<o:p></o:p></p>
</div>
</div>
<p class="MsoNormal"><o:p> </o:p></p>
<div>
<div>
<p class="MsoNormal">On Thu, Jun 27, 2019 at 3:20 AM Jeremy Morse via llvm-commits <<a href="mailto:llvm-commits@lists.llvm.org" target="_blank">llvm-commits@lists.llvm.org</a>> wrote:<o:p></o:p></p>
</div>
<blockquote style="border:none;border-left:solid #CCCCCC 1.0pt;padding:0in 0in 0in 6.0pt;margin-left:4.8pt;margin-right:0in">
<p class="MsoNormal">Author: jmorse<br>
Date: Thu Jun 27 03:20:27 2019<br>
New Revision: 364515<br>
<br>
URL: <a href="http://llvm.org/viewvc/llvm-project?rev=364515&view=rev" target="_blank">
http://llvm.org/viewvc/llvm-project?rev=364515&view=rev</a><br>
Log:<br>
[DebugInfo] Avoid register coalesing unsoundly changing DBG_VALUE locations<br>
<br>
Once MIR code leaves SSA form and the liveness of a vreg is considered,<br>
DBG_VALUE insts are able to refer to non-live vregs, because their<br>
debug-uses do not contribute to liveness. This non-liveness becomes<br>
problematic for optimizations like register coalescing, as they can't<br>
``see'' the debug uses in the liveness analyses.<br>
<br>
As a result registers get coalesced regardless of debug uses, and that can<br>
lead to invalid variable locations containing unexpected values. In the<br>
added test case, the first vreg operand of ADD32rr is merged with various<br>
copies of the vreg (great for performance), but a DBG_VALUE of the<br>
unmodified operand is blindly updated to the modified operand. This changes<br>
what value the variable will appear to have in a debugger.<br>
<br>
Fix this by changing any DBG_VALUE whose operand will be resurrected by<br>
register coalescing to be a $noreg DBG_VALUE, i.e. give the variable no<br>
location. This is an overapproximation as some coalesced locations are<br>
safe (others are not) -- an extra domination analysis would be required to<br>
work out which, and it would be better if we just don't generate non-live<br>
DBG_VALUEs.<br>
<br>
This fixes PR40010.<br>
<br>
Differential Revision: <a href="https://reviews.llvm.org/D56151" target="_blank">
https://reviews.llvm.org/D56151</a><br>
<br>
Added:<br>
    llvm/trunk/test/DebugInfo/MIR/X86/regcoalescing-clears-dead-dbgvals.mir<br>
Modified:<br>
    llvm/trunk/lib/CodeGen/RegisterCoalescer.cpp<br>
<br>
Modified: llvm/trunk/lib/CodeGen/RegisterCoalescer.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/RegisterCoalescer.cpp?rev=364515&r1=364514&r2=364515&view=diff" target="_blank">
http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/RegisterCoalescer.cpp?rev=364515&r1=364514&r2=364515&view=diff</a><br>
==============================================================================<br>
--- llvm/trunk/lib/CodeGen/RegisterCoalescer.cpp (original)<br>
+++ llvm/trunk/lib/CodeGen/RegisterCoalescer.cpp Thu Jun 27 03:20:27 2019<br>
@@ -265,6 +265,14 @@ namespace {<br>
     /// Return true if a copy involving a physreg should be joined.<br>
     bool canJoinPhys(const CoalescerPair &CP);<br>
<br>
+    /// When merging SrcReg and DstReg together, and the operand of the<br>
+    /// specified DBG_VALUE refers to one of them, would the def that a<br>
+    /// DBG_VALUE refers to change? This can happen when the DBG_VALUEs<br>
+    /// operand is dead and it's merged into a different live value,<br>
+    /// meaning the DBG_VALUE operands must be updated.<br>
+    bool mergingChangesDbgValue(MachineInstr *DbgV, unsigned SrcReg,<br>
+                                unsigned DstReg) const;<br>
+<br>
     /// Replace all defs and uses of SrcReg to DstReg and update the subregister<br>
     /// number if it is not zero. If DstReg is a physical register and the<br>
     /// existing subregister number of the def / use being updated is not zero,<br>
@@ -1641,8 +1649,59 @@ void RegisterCoalescer::addUndefFlag(con<br>
   }<br>
 }<br>
<br>
-void RegisterCoalescer::updateRegDefsUses(unsigned SrcReg,<br>
-                                          unsigned DstReg,<br>
+bool RegisterCoalescer::mergingChangesDbgValue(MachineInstr *DbgV,<br>
+                                               unsigned SrcReg,<br>
+                                               unsigned DstReg) const {<br>
+  assert(DbgV->isDebugValue());<br>
+  assert(DbgV->getParent() && "DbgValue with no parent");<br>
+  assert(DbgV->getOperand(0).isReg());<br>
+  unsigned DbgReg = DbgV->getOperand(0).getReg();<br>
+<br>
+  SlotIndex MIIdx = LIS->getSlotIndexes()->getIndexAfter(*DbgV);<br>
+  const LiveInterval &SrcLI = LIS->getInterval(SrcReg);<br>
+<br>
+  // Is the source register live across the DBG_VALUE?<br>
+  bool SrcLive = false;<br>
+  auto LII = SrcLI.find(MIIdx);<br>
+  if (LII != SrcLI.end() && LII->contains(MIIdx))<br>
+    SrcLive = true;<br>
+<br>
+  bool DstLive = false;<br>
+  // Destination register can be physical or virtual.<br>
+  if (TargetRegisterInfo::isVirtualRegister(DstReg)) {<br>
+    // Is DstReg live across the DBG_VALUE?<br>
+    const LiveInterval &DstLI = LIS->getInterval(DstReg);<br>
+    LII = DstLI.find(MIIdx);<br>
+    DstLive = (LII != DstLI.end() && LII->contains(MIIdx));<br>
+  } else if (MRI->isConstantPhysReg(DstReg)) {<br>
+    // Constant physical registers are always live.<br>
+    DstLive = true;<br>
+  } else {<br>
+    // For physical registers, see if any register unit containing DstReg<br>
+    // is live across the DBG_VALUE.<br>
+    for (MCRegUnitIterator UI(DstReg, TRI); UI.isValid(); ++UI) {<br>
+      const LiveRange &DstLI = LIS->getRegUnit(*UI);<br>
+      auto DstLII = DstLI.find(MIIdx);<br>
+      if (DstLII != DstLI.end() && DstLII->contains(MIIdx)) {<br>
+        DstLive = true;<br>
+        break;<br>
+      }<br>
+    }<br>
+  }<br>
+<br>
+  // We now know whether src and dst are live. Best case: we have a DBG_VALUE<br>
+  // of a live register, coalesing won't change its value.<br>
+  if ((DstLive && DbgReg == DstReg) || (SrcLive && DbgReg == SrcReg))<br>
+    return false;<br>
+  // If neither register are live, no damage done.<br>
+  if (!DstLive && !SrcLive)<br>
+    return false;<br>
+  // Otherwise, we will end up resurrecting the DBG_VALUE with a different<br>
+  // register, which is unsafe.<br>
+  return true;<br>
+}<br>
+<br>
+void RegisterCoalescer::updateRegDefsUses(unsigned SrcReg, unsigned DstReg,<br>
                                           unsigned SubIdx) {<br>
   bool DstIsPhys = TargetRegisterInfo::isPhysicalRegister(DstReg);<br>
   LiveInterval *DstInt = DstIsPhys ? nullptr : &LIS->getInterval(DstReg);<br>
@@ -1854,6 +1913,20 @@ bool RegisterCoalescer::joinCopy(Machine<br>
   ShrinkMask = LaneBitmask::getNone();<br>
   ShrinkMainRange = false;<br>
<br>
+  // Although we can update the DBG_VALUEs to the merged register, as debug uses<br>
+  // do not contribute to liveness it might not be a sound update. Collect<br>
+  // DBG_VALUEs that would change value were this interval merging to succeed.<br>
+  SmallVector<MachineInstr *, 4> DbgValuesToChange;<br>
+  auto CheckForDbgUser = [this, &CP, &DbgValuesToChange](MachineInstr &MI) {<br>
+    if (MI.isDebugValue() && MI.getOperand(0).isReg() &&<br>
+        mergingChangesDbgValue(&MI, CP.getSrcReg(), CP.getDstReg()))<br>
+      DbgValuesToChange.push_back(&MI);<br>
+  };<br>
+  for (auto &RegIt : MRI->reg_instructions(CP.getSrcReg()))<br>
+    CheckForDbgUser(RegIt);<br>
+  for (auto &RegIt : MRI->reg_instructions(CP.getDstReg()))<br>
+    CheckForDbgUser(RegIt);<br>
+<br>
   // Okay, attempt to join these two intervals.  On failure, this returns false.<br>
   // Otherwise, if one of the intervals being joined is a physreg, this method<br>
   // always canonicalizes DstInt to be it.  The output "SrcInt" will not have<br>
@@ -1922,6 +1995,16 @@ bool RegisterCoalescer::joinCopy(Machine<br>
     updateRegDefsUses(CP.getDstReg(), CP.getDstReg(), CP.getDstIdx());<br>
   updateRegDefsUses(CP.getSrcReg(), CP.getDstReg(), CP.getSrcIdx());<br>
<br>
+  // The updates to these DBG_VALUEs are not sound -- mark them undef.<br>
+  // FIXME: further analysis might recover them, this is the minimal sound<br>
+  // solution.<br>
+  for (MachineInstr *MI : DbgValuesToChange) {<br>
+    assert(MI->getOperand(0).isReg());<br>
+    LLVM_DEBUG(dbgs() << "Update of " << MI->getOperand(0) << " would be "<br>
+                      << "unsound, setting undef\n");<br>
+    MI->getOperand(0).setReg(0);<br>
+  }<br>
+<br>
   // Shrink subregister ranges if necessary.<br>
   if (ShrinkMask.any()) {<br>
     LiveInterval &LI = LIS->getInterval(CP.getDstReg());<br>
<br>
Added: llvm/trunk/test/DebugInfo/MIR/X86/regcoalescing-clears-dead-dbgvals.mir<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/test/DebugInfo/MIR/X86/regcoalescing-clears-dead-dbgvals.mir?rev=364515&view=auto" target="_blank">
http://llvm.org/viewvc/llvm-project/llvm/trunk/test/DebugInfo/MIR/X86/regcoalescing-clears-dead-dbgvals.mir?rev=364515&view=auto</a><br>
==============================================================================<br>
--- llvm/trunk/test/DebugInfo/MIR/X86/regcoalescing-clears-dead-dbgvals.mir (added)<br>
+++ llvm/trunk/test/DebugInfo/MIR/X86/regcoalescing-clears-dead-dbgvals.mir Thu Jun 27 03:20:27 2019<br>
@@ -0,0 +1,243 @@<br>
+# RUN: llc %s -o - -run-pass=simple-register-coalescing | FileCheck %s<br>
+# PR40010: DBG_VALUEs do not contribute to the liveness of virtual registers,<br>
+# and the register coalescer would merge new live values on top of DBG_VALUEs,<br>
+# leading to them presenting new (wrong) values to the debugger. Test that<br>
+# when out of liveness, coalescing will mark DBG_VALUEs in non-live locations<br>
+# as undef.<br>
+--- |<br>
+  ; ModuleID = './test.ll'<br>
+  source_filename = "./test.ll"<br>
+  target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"<br>
+<br>
+  ; Function Attrs: nounwind readnone speculatable<br>
+  declare void @llvm.dbg.value(metadata, metadata, metadata) #0<br>
+<br>
+  ; Original IR source here:<br>
+  define i32 @test(i32* %pin) {<br>
+  entry:<br>
+    br label %start.test1<br>
+<br>
+  start.test1:                                       ; preds = %start, %entry<br>
+    %foo = phi i32 [ 0, %entry ], [ %bar, %start.test1 ]<br>
+    %baz = load i32, i32* %pin, align 1<br>
+    %qux = xor i32 %baz, 1234<br>
+    %bar = add i32 %qux, %foo<br>
+    call void @llvm.dbg.value(metadata i32 %foo, metadata !3, metadata !DIExpression()), !dbg !5<br>
+    %cmp = icmp ugt i32 %bar, 1000000<br>
+    br i1 %cmp, label %leave, label %start.test1<br>
+<br>
+  leave:                                            ; preds = %start<br>
+    ret i32 %bar<br>
+  }<br>
+<br>
+  ; Stubs to appease the MIR parser<br>
+  define i32 @test2(i32* %pin) {<br>
+  entry:<br>
+    ret i32 0<br>
+  start.test2:<br>
+    ret i32 0<br>
+  leave:<br>
+    ret i32 0<br>
+  }<br>
+<br>
+  define i32 @test3(i32* %pin) {<br>
+  entry:<br>
+    ret i32 0<br>
+  start.test3:<br>
+    ret i32 0<br>
+  leave:<br>
+    ret i32 0<br>
+  }<br>
+<br>
+  define i32 @test4(i32* %pin) {<br>
+  entry:<br>
+    ret i32 0<br>
+  start.test4:<br>
+    ret i32 0<br>
+  leave:<br>
+    ret i32 0<br>
+  }<br>
+<br>
+  ; Function Attrs: nounwind<br>
+  declare void @llvm.stackprotector(i8*, i8**) #1<br>
+<br>
+  attributes #0 = { nounwind readnone speculatable }<br>
+  attributes #1 = { nounwind }<br>
+<br>
+  !llvm.module.flags = !{!0}<br>
+  !<a href="http://llvm.dbg.cu" target="_blank">llvm.dbg.cu</a> = !{!1}<br>
+<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: 4, emissionKind: FullDebug)<br>
+  !2 = !DIFile(filename: "bees.cpp", directory: "")<br>
+  !3 = !DILocalVariable(name: "bees", scope: !4)<br>
+  !4 = distinct !DISubprogram(name: "nope", scope: !1, file: !2, line: 1, spFlags: DISPFlagDefinition, unit: !1)<br>
+  !5 = !DILocation(line: 0, scope: !4)<br>
+<br>
+...<br>
+---<br>
+name:            test<br>
+tracksRegLiveness: true<br>
+body:             |<br>
+  bb.0.entry:<br>
+    successors: %bb.1(0x80000000)<br>
+    liveins: $rdi<br>
+<br>
+    %2:gr64 = COPY killed $rdi<br>
+    %3:gr32 = MOV32r0 implicit-def dead $eflags<br>
+    %4:gr32 = MOV32ri 1234<br>
+    %7:gr32 = COPY killed %3<br>
+<br>
+  bb.1.start.test1:<br>
+    successors: %bb.2(0x04000000), %bb.1(0x7c000000)<br>
+<br>
+    ; CHECK-LABEL: name: test<br>
+    ;<br>
+    ; We currently expect %1 and %0 to merge into %7<br>
+    ;<br>
+    ; CHECK: %[[REG1:[0-9]+]]:gr32 = MOV32rm<br>
+    ; CHECK-NEXT: %[[REG2:[0-9]+]]:gr32 = XOR32rr %[[REG1]]<br>
+    ; CHECK-NEXT: %[[REG3:[0-9]+]]:gr32 = ADD32rr %[[REG3]], %[[REG2]]<br>
+    ; CHECK-NEXT: DBG_VALUE $noreg<br>
+<br>
+    %0:gr32 = COPY killed %7<br>
+    %8:gr32 = MOV32rm %2, 1, $noreg, 0, $noreg :: (load 4 from %ir.pin, align 1)<br>
+    %5:gr32 = COPY killed %8<br>
+    %5:gr32 = XOR32rr %5, %4, implicit-def dead $eflags<br>
+    %1:gr32 = COPY killed %0<br>
+    %1:gr32 = ADD32rr %1, killed %5, implicit-def dead $eflags<br>
+    DBG_VALUE %0, $noreg, !3, !DIExpression(), debug-location !5<br>
+    CMP32ri %1, 1000001, implicit-def $eflags<br>
+    %7:gr32 = COPY %1<br>
+    JCC_1 %bb.1, 2, implicit killed $eflags<br>
+    JMP_1 %bb.2<br>
+<br>
+  bb.2.leave:<br>
+    $eax = COPY killed %1<br>
+    RET 0, killed $eax<br>
+<br>
+...<br>
+---<br>
+name:            test2<br>
+tracksRegLiveness: true<br>
+body:             |<br>
+  bb.0.entry:<br>
+    successors: %bb.1(0x80000000)<br>
+    liveins: $rdi<br>
+<br>
+    %2:gr64 = COPY killed $rdi<br>
+    %3:gr32 = MOV32r0 implicit-def dead $eflags<br>
+    %4:gr32 = MOV32ri 1234<br>
+    %7:gr32 = COPY killed %3<br>
+<br>
+  bb.1.start.test2:<br>
+    successors: %bb.2(0x04000000), %bb.1(0x7c000000)<br>
+<br>
+    ; CHECK-LABEL: name: test2<br>
+    ;<br>
+    ; %0 should be merged into %7, but as %0 is live at this location the<br>
+    ; DBG_VALUE should be preserved and point at the operand of ADD32rr.<br>
+    ;<br>
+    ; CHECK: %[[REG11:[0-9]+]]:gr32 = MOV32rm<br>
+    ; CHECK-NEXT: %[[REG12:[0-9]+]]:gr32 = XOR32rr %[[REG11]]<br>
+    ; CHECK-NEXT: DBG_VALUE %[[REG13:[0-9]+]]<br>
+    ; CHECK-NEXT: %[[REG13]]:gr32 = ADD32rr %[[REG13]], %[[REG12]]<br>
+<br>
+    %0:gr32 = COPY killed %7<br>
+    %8:gr32 = MOV32rm %2, 1, $noreg, 0, $noreg :: (load 4 from %ir.pin, align 1)<br>
+    %5:gr32 = COPY killed %8<br>
+    %5:gr32 = XOR32rr %5, %4, implicit-def dead $eflags<br>
+    DBG_VALUE %0, $noreg, !3, !DIExpression(), debug-location !5<br>
+    %1:gr32 = COPY killed %0<br>
+    %1:gr32 = ADD32rr %1, killed %5, implicit-def dead $eflags<br>
+    CMP32ri %1, 1000001, implicit-def $eflags<br>
+    %7:gr32 = COPY %1<br>
+    JCC_1 %bb.1, 2, implicit killed $eflags<br>
+    JMP_1 %bb.2<br>
+<br>
+  bb.2.leave:<br>
+    $eax = COPY killed %1<br>
+    RET 0, killed $eax<br>
+<br>
+...<br>
+---<br>
+name:            test3<br>
+tracksRegLiveness: true<br>
+body:             |<br>
+  bb.0.entry:<br>
+    successors: %bb.1(0x80000000)<br>
+    liveins: $rdi<br>
+<br>
+    %2:gr64 = COPY killed $rdi<br>
+    %3:gr32 = MOV32r0 implicit-def dead $eflags<br>
+    %4:gr32 = MOV32ri 1234<br>
+    %7:gr32 = COPY killed %3<br>
+<br>
+  bb.1.start.test3:<br>
+    successors: %bb.2(0x04000000), %bb.1(0x7c000000)<br>
+<br>
+    ; CHECK-LABEL: name: test3<br>
+    ;<br>
+    ; This is a use-before-def, merging new registers into %0 could unsoundly<br>
+    ; make it live again, on merge mark it undef.<br>
+    ;<br>
+    ; CHECK: DBG_VALUE $noreg<br>
+<br>
+    DBG_VALUE %0, $noreg, !3, !DIExpression(), debug-location !5<br>
+    %0:gr32 = COPY killed %7<br>
+    %8:gr32 = MOV32rm %2, 1, $noreg, 0, $noreg :: (load 4 from %ir.pin, align 1)<br>
+    %5:gr32 = COPY killed %8<br>
+    %5:gr32 = XOR32rr %5, %4, implicit-def dead $eflags<br>
+    %1:gr32 = COPY killed %0<br>
+    %1:gr32 = ADD32rr %1, killed %5, implicit-def dead $eflags<br>
+    CMP32ri %1, 1000001, implicit-def $eflags<br>
+    %7:gr32 = COPY %1<br>
+    JCC_1 %bb.1, 2, implicit killed $eflags<br>
+    JMP_1 %bb.2<br>
+<br>
+  bb.2.leave:<br>
+    $eax = COPY killed %1<br>
+    RET 0, killed $eax<br>
+<br>
+...<br>
+---<br>
+name:            test4<br>
+tracksRegLiveness: true<br>
+body:             |<br>
+  bb.0.entry:<br>
+    successors: %bb.1(0x80000000)<br>
+    liveins: $rdi<br>
+<br>
+    %2:gr64 = COPY killed $rdi<br>
+    %3:gr32 = MOV32r0 implicit-def dead $eflags<br>
+    %4:gr32 = MOV32ri 1234<br>
+    %7:gr32 = COPY killed %3<br>
+<br>
+  bb.1.start.test4:<br>
+    successors: %bb.2(0x04000000), %bb.1(0x7c000000)<br>
+<br>
+    ; CHECK-LABEL: name: test4<br>
+    ;<br>
+    ; Using a dead register, even if we coalesce it to the right value, should<br>
+    ; be marked undef. The coalescer can't prove it's correct without<br>
+    ; considering control flow in the general case.<br>
+    ;<br>
+    ; CHECK: DBG_VALUE $noreg<br>
+<br>
+    %0:gr32 = COPY killed %7<br>
+    DBG_VALUE %7, $noreg, !3, !DIExpression(), debug-location !5<br>
+    %8:gr32 = MOV32rm %2, 1, $noreg, 0, $noreg :: (load 4 from %ir.pin, align 1)<br>
+    %5:gr32 = COPY killed %8<br>
+    %5:gr32 = XOR32rr %5, %4, implicit-def dead $eflags<br>
+    %1:gr32 = COPY killed %0<br>
+    %1:gr32 = ADD32rr %1, killed %5, implicit-def dead $eflags<br>
+    CMP32ri %1, 1000001, implicit-def $eflags<br>
+    %7:gr32 = COPY %1<br>
+    JCC_1 %bb.1, 2, implicit killed $eflags<br>
+    JMP_1 %bb.2<br>
+<br>
+  bb.2.leave:<br>
+    $eax = COPY killed %1<br>
+    RET 0, killed $eax<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" target="_blank">https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-commits</a><o:p></o:p></p>
</blockquote>
</div>
</blockquote>
</div>
</div>
</div>
</body>
</html>