Index: lib/CodeGen/LiveIntervalAnalysis.cpp =================================================================== --- lib/CodeGen/LiveIntervalAnalysis.cpp +++ lib/CodeGen/LiveIntervalAnalysis.cpp @@ -978,14 +978,49 @@ } dbgs() << ":\t" << LR << '\n'; }); + const SlotIndexes *Indexes = LIS.getSlotIndexes(); + const MachineBasicBlock *MBB = Indexes->getMBBFromIndex(NewIdx); + const VNInfo *OldLiveOut = LR.getVNInfoBefore(LIS.getMBBEndIdx(MBB)); + if (SlotIndex::isEarlierInstr(OldIdx, NewIdx)) handleMoveDown(LR); else handleMoveUp(LR, Reg, LaneMask); + + // Fix liveins to other blocks which may need to be changed to new liveouts. + if (OldLiveOut && LR.getNumValNums() > 1) { + const VNInfo *NewLiveOut = LR.getVNInfoBefore(LIS.getMBBEndIdx(MBB)); + if (OldLiveOut->id != NewLiveOut->id) + updateSuccessors(LR, MBB, NewLiveOut); + } + DEBUG(dbgs() << " -->\t" << LR << '\n'); LR.verify(); } + // Update value numbers in successor blocks in case if we have a new liveout + // replacing an old one. I.e. if we have swapped two instructions defining + // subregisters of a same register. Last one becomes a new liveout. + void updateSuccessors(LiveRange &LR, const MachineBasicBlock *MBB, + const VNInfo *Valno) { + VNInfo *Out = LR.getVNInfoBefore(LIS.getMBBEndIdx(MBB)); + if (!Out || Out != Valno) + return; + // This is a liveout. + // Find live-ins to other blocks which should connect to this live-out. + for (const auto &Succ : MBB->successors()) { + // Now set new value number in a successor. + auto *InSeg = LR.getSegmentContaining(LIS.getMBBStartIdx(Succ)); + if (InSeg && !InSeg->valno->isPHIDef() && InSeg->valno != Out) { + InSeg->valno = Out; + // Iterate next successors. No need to maintain visited list because + // when we update all possible segments loop will terminate. + if (InSeg->contains(LIS.getMBBEndIdx(Succ).getPrevSlot())) + updateSuccessors(LR, Succ, Out); + } + } + } + /// Update LR to reflect an instruction has been moved downwards from OldIdx /// to NewIdx (OldIdx < NewIdx). void handleMoveDown(LiveRange &LR) { Index: unittests/MI/LiveIntervalTest.cpp =================================================================== --- unittests/MI/LiveIntervalTest.cpp +++ unittests/MI/LiveIntervalTest.cpp @@ -382,6 +382,24 @@ }); } +TEST(LiveIntervalTest, SwapSubregDefs) { + // handleMoveUp had a bug not updating valno of segment incoming to bb.2 + // after swapping subreg definitions. + liveIntervalTest(R"MIR( + successors: %bb.1, %bb.2 + undef %0.sub0 = IMPLICIT_DEF + %0.sub1 = IMPLICIT_DEF + S_CBRANCH_VCCNZ %bb.2, implicit undef %vcc + S_BRANCH %bb.1 + bb.1: + S_NOP 0, implicit %0.sub1 + bb.2: + S_NOP 0, implicit %0.sub1 +)MIR", [](MachineFunction &MF, LiveIntervals &LIS) { + testHandleMove(MF, LIS, 1, 0); + }); +} + int main(int argc, char **argv) { ::testing::InitGoogleTest(&argc, argv); initLLVM();