[llvm] r326087 - [LiveIntervals] Handle moving up dead partial write

Tim Renouf via llvm-commits llvm-commits at lists.llvm.org
Mon Feb 26 06:42:13 PST 2018


Author: tpr
Date: Mon Feb 26 06:42:13 2018
New Revision: 326087

URL: http://llvm.org/viewvc/llvm-project?rev=326087&view=rev
Log:
[LiveIntervals] Handle moving up dead partial write

Summary:
In the test case, the machine scheduler moves a dead write to a subreg
up into the middle of a segment of the overall reg's live range, where
the segment had liveness only for other subregs in the reg.
handleMoveUp created an invalid live range, causing an assert a bit
later.

This commit fixes it to handle that situation. The segment is split in
two at the insertion point, and the part after the split, and any
subsequent segments up to the old position, are changed to be defined by
the moved def.

V2: Better test.

Subscribers: MatzeB, nhaehnle, llvm-commits

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

Change-Id: Ibc42445ddca84e79ad1f616401015d22bc63832e

Modified:
    llvm/trunk/lib/CodeGen/LiveIntervals.cpp
    llvm/trunk/unittests/MI/LiveIntervalTest.cpp

Modified: llvm/trunk/lib/CodeGen/LiveIntervals.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/LiveIntervals.cpp?rev=326087&r1=326086&r2=326087&view=diff
==============================================================================
--- llvm/trunk/lib/CodeGen/LiveIntervals.cpp (original)
+++ llvm/trunk/lib/CodeGen/LiveIntervals.cpp Mon Feb 26 06:42:13 2018
@@ -1291,6 +1291,36 @@ private:
           if (OldIdxIn != E && SlotIndex::isEarlierInstr(NewIdx, OldIdxIn->end))
             OldIdxIn->end = NewIdx.getRegSlot();
         }
+      } else if (OldIdxIn != E
+          && SlotIndex::isEarlierInstr(NewIdxOut->start, NewIdx)
+          && SlotIndex::isEarlierInstr(NewIdx, NewIdxOut->end)) {
+        // OldIdxVNI is a dead def that has been moved into the middle of
+        // another value in LR. That can happen when LR is a whole register,
+        // but the dead def is a write to a subreg that is dead at NewIdx.
+        // The dead def may have been moved across other values
+        // in LR, so move OldIdxOut up to NewIdxOut. Slide [NewIdxOut;OldIdxOut)
+        // down one position.
+        //    |- X0/NewIdxOut -| ... |- Xn-1 -| |- Xn/OldIdxOut -| |- next - |
+        // => |- X0/NewIdxOut -| |- X0 -| ... |- Xn-1 -| |- next -|
+        std::copy_backward(NewIdxOut, OldIdxOut, std::next(OldIdxOut));
+        // Modify the segment at NewIdxOut and the following segment to meet at
+        // the point of the dead def, with the following segment getting
+        // OldIdxVNI as its value number.
+        *NewIdxOut = LiveRange::Segment(
+            NewIdxOut->start, NewIdxDef.getRegSlot(), NewIdxOut->valno);
+        *(NewIdxOut + 1) = LiveRange::Segment(
+            NewIdxDef.getRegSlot(), (NewIdxOut + 1)->end, OldIdxVNI);
+        OldIdxVNI->def = NewIdxDef;
+        // Modify subsequent segments to be defined by the moved def OldIdxVNI.
+        for (auto Idx = NewIdxOut + 2; Idx <= OldIdxOut; ++Idx)
+          Idx->valno = OldIdxVNI;
+        // Aggressively remove all dead flags from the former dead definition.
+        // Kill/dead flags shouldn't be used while live intervals exist; they
+        // will be reinserted by VirtRegRewriter.
+        if (MachineInstr *KillMI = LIS.getInstructionFromIndex(NewIdx))
+          for (MIBundleOperands MO(*KillMI); MO.isValid(); ++MO)
+            if (MO->isReg() && !MO->isUse())
+              MO->setIsDead(false);
       } else {
         // OldIdxVNI is a dead def. It may have been moved across other values
         // in LR, so move OldIdxOut up to NewIdxOut. Slide [NewIdxOut;OldIdxOut)

Modified: llvm/trunk/unittests/MI/LiveIntervalTest.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/unittests/MI/LiveIntervalTest.cpp?rev=326087&r1=326086&r2=326087&view=diff
==============================================================================
--- llvm/trunk/unittests/MI/LiveIntervalTest.cpp (original)
+++ llvm/trunk/unittests/MI/LiveIntervalTest.cpp Mon Feb 26 06:42:13 2018
@@ -395,6 +395,31 @@ TEST(LiveIntervalTest, SubRegMoveUp) {
   });
 }
 
+TEST(LiveIntervalTest, DeadSubRegMoveUp) {
+  // handleMoveUp had a bug where moving a dead subreg def into the middle of
+  // an earlier segment resulted in an invalid live range.
+  liveIntervalTest(R"MIR(
+    undef %125.sub0:vreg_128 = V_MOV_B32_e32 0, implicit $exec
+    %125.sub1:vreg_128 = COPY %125.sub0
+    %125.sub2:vreg_128 = COPY %125.sub0
+    undef %51.sub0:vreg_128 = V_MOV_B32_e32 898625526, implicit $exec
+    %51.sub1:vreg_128 = COPY %51.sub0
+    %51.sub2:vreg_128 = COPY %51.sub0
+    %52:vgpr_32 = V_MOV_B32_e32 986714345, implicit $exec
+    %54:vgpr_32 = V_MOV_B32_e32 1742342378, implicit $exec
+    %57:vgpr_32 = V_MOV_B32_e32 3168768712, implicit $exec
+    %59:vgpr_32 = V_MOV_B32_e32 1039972644, implicit $exec
+    %60:vgpr_32 = V_MAD_F32 0, %52, 0, undef %61:vgpr_32, 0, %59, 0, 0, implicit $exec
+    %63:vgpr_32 = V_ADD_F32_e32 %51.sub3, undef %64:vgpr_32, implicit $exec
+    dead %66:vgpr_32 = V_MAD_F32 0, %60, 0, undef %67:vgpr_32, 0, %125.sub2, 0, 0, implicit $exec
+    undef %124.sub1:vreg_128 = V_MAD_F32 0, %57, 0, undef %70:vgpr_32, 0, %125.sub1, 0, 0, implicit $exec
+    %124.sub0:vreg_128 = V_MAD_F32 0, %54, 0, undef %73:vgpr_32, 0, %125.sub0, 0, 0, implicit $exec
+    dead undef %125.sub3:vreg_128 = V_MAC_F32_e32 %63, undef %76:vgpr_32, %125.sub3, implicit $exec
+)MIR", [](MachineFunction &MF, LiveIntervals &LIS) {
+    testHandleMove(MF, LIS, 15, 12);
+  });
+}
+
 int main(int argc, char **argv) {
   ::testing::InitGoogleTest(&argc, argv);
   initLLVM();




More information about the llvm-commits mailing list