summaryrefslogtreecommitdiffstats
path: root/llvm/lib/CodeGen/LiveIntervals.cpp
diff options
context:
space:
mode:
authorTim Renouf <tpr.llvm@botech.co.uk>2018-02-26 14:42:13 +0000
committerTim Renouf <tpr.llvm@botech.co.uk>2018-02-26 14:42:13 +0000
commitf40707a2db3b7abd26ac87191cb792e648f0ccb4 (patch)
treeb86e3c7faec417aec76fc16ae2f7c85ae08fa53e /llvm/lib/CodeGen/LiveIntervals.cpp
parent0b2f774be69dcfbccb70c77b70264f93a661a590 (diff)
downloadbcm5719-llvm-f40707a2db3b7abd26ac87191cb792e648f0ccb4.tar.gz
bcm5719-llvm-f40707a2db3b7abd26ac87191cb792e648f0ccb4.zip
[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 llvm-svn: 326087
Diffstat (limited to 'llvm/lib/CodeGen/LiveIntervals.cpp')
-rw-r--r--llvm/lib/CodeGen/LiveIntervals.cpp30
1 files changed, 30 insertions, 0 deletions
diff --git a/llvm/lib/CodeGen/LiveIntervals.cpp b/llvm/lib/CodeGen/LiveIntervals.cpp
index 79fdba7e062..13fe77e4866 100644
--- a/llvm/lib/CodeGen/LiveIntervals.cpp
+++ b/llvm/lib/CodeGen/LiveIntervals.cpp
@@ -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)
OpenPOWER on IntegriCloud