llvm.org GIT mirror llvm / 27467f8
[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 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@326087 91177308-0d34-0410-b5e6-96231b3b80d8 Tim Renouf 2 years ago
2 changed file(s) with 55 addition(s) and 0 deletion(s). Raw diff Collapse all Expand all
12901290 if (OldIdxIn != E && SlotIndex::isEarlierInstr(NewIdx, OldIdxIn->end))
12911291 OldIdxIn->end = NewIdx.getRegSlot();
12921292 }
1293 } else if (OldIdxIn != E
1294 && SlotIndex::isEarlierInstr(NewIdxOut->start, NewIdx)
1295 && SlotIndex::isEarlierInstr(NewIdx, NewIdxOut->end)) {
1296 // OldIdxVNI is a dead def that has been moved into the middle of
1297 // another value in LR. That can happen when LR is a whole register,
1298 // but the dead def is a write to a subreg that is dead at NewIdx.
1299 // The dead def may have been moved across other values
1300 // in LR, so move OldIdxOut up to NewIdxOut. Slide [NewIdxOut;OldIdxOut)
1301 // down one position.
1302 // |- X0/NewIdxOut -| ... |- Xn-1 -| |- Xn/OldIdxOut -| |- next - |
1303 // => |- X0/NewIdxOut -| |- X0 -| ... |- Xn-1 -| |- next -|
1304 std::copy_backward(NewIdxOut, OldIdxOut, std::next(OldIdxOut));
1305 // Modify the segment at NewIdxOut and the following segment to meet at
1306 // the point of the dead def, with the following segment getting
1307 // OldIdxVNI as its value number.
1308 *NewIdxOut = LiveRange::Segment(
1309 NewIdxOut->start, NewIdxDef.getRegSlot(), NewIdxOut->valno);
1310 *(NewIdxOut + 1) = LiveRange::Segment(
1311 NewIdxDef.getRegSlot(), (NewIdxOut + 1)->end, OldIdxVNI);
1312 OldIdxVNI->def = NewIdxDef;
1313 // Modify subsequent segments to be defined by the moved def OldIdxVNI.
1314 for (auto Idx = NewIdxOut + 2; Idx <= OldIdxOut; ++Idx)
1315 Idx->valno = OldIdxVNI;
1316 // Aggressively remove all dead flags from the former dead definition.
1317 // Kill/dead flags shouldn't be used while live intervals exist; they
1318 // will be reinserted by VirtRegRewriter.
1319 if (MachineInstr *KillMI = LIS.getInstructionFromIndex(NewIdx))
1320 for (MIBundleOperands MO(*KillMI); MO.isValid(); ++MO)
1321 if (MO->isReg() && !MO->isUse())
1322 MO->setIsDead(false);
12931323 } else {
12941324 // OldIdxVNI is a dead def. It may have been moved across other values
12951325 // in LR, so move OldIdxOut up to NewIdxOut. Slide [NewIdxOut;OldIdxOut)
394394 });
395395 }
396396
397 TEST(LiveIntervalTest, DeadSubRegMoveUp) {
398 // handleMoveUp had a bug where moving a dead subreg def into the middle of
399 // an earlier segment resulted in an invalid live range.
400 liveIntervalTest(R"MIR(
401 undef %125.sub0:vreg_128 = V_MOV_B32_e32 0, implicit $exec
402 %125.sub1:vreg_128 = COPY %125.sub0
403 %125.sub2:vreg_128 = COPY %125.sub0
404 undef %51.sub0:vreg_128 = V_MOV_B32_e32 898625526, implicit $exec
405 %51.sub1:vreg_128 = COPY %51.sub0
406 %51.sub2:vreg_128 = COPY %51.sub0
407 %52:vgpr_32 = V_MOV_B32_e32 986714345, implicit $exec
408 %54:vgpr_32 = V_MOV_B32_e32 1742342378, implicit $exec
409 %57:vgpr_32 = V_MOV_B32_e32 3168768712, implicit $exec
410 %59:vgpr_32 = V_MOV_B32_e32 1039972644, implicit $exec
411 %60:vgpr_32 = V_MAD_F32 0, %52, 0, undef %61:vgpr_32, 0, %59, 0, 0, implicit $exec
412 %63:vgpr_32 = V_ADD_F32_e32 %51.sub3, undef %64:vgpr_32, implicit $exec
413 dead %66:vgpr_32 = V_MAD_F32 0, %60, 0, undef %67:vgpr_32, 0, %125.sub2, 0, 0, implicit $exec
414 undef %124.sub1:vreg_128 = V_MAD_F32 0, %57, 0, undef %70:vgpr_32, 0, %125.sub1, 0, 0, implicit $exec
415 %124.sub0:vreg_128 = V_MAD_F32 0, %54, 0, undef %73:vgpr_32, 0, %125.sub0, 0, 0, implicit $exec
416 dead undef %125.sub3:vreg_128 = V_MAC_F32_e32 %63, undef %76:vgpr_32, %125.sub3, implicit $exec
417 )MIR", [](MachineFunction &MF, LiveIntervals &LIS) {
418 testHandleMove(MF, LIS, 15, 12);
419 });
420 }
421
397422 int main(int argc, char **argv) {
398423 ::testing::InitGoogleTest(&argc, argv);
399424 initLLVM();