From d15319f75f537a806f85f616a84423d63fa1b3d1 Mon Sep 17 00:00:00 2001 From: Quentin Colombet Date: Wed, 6 May 2015 22:41:50 +0000 Subject: [PATCH] [RegisterCoalescer] Make sure each live-range has only one component, as demanded by the machine verifier. After shrinking a live-range to its uses, it is possible to create several smaller live-ranges. When this happens, shrinkToUses returns true and we need to split the different components into their own live-ranges. The problem does not reproduce on any in-tree target but Jonas Paulsson , who reported the problem, checked that this patch fixes the issue. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@236658 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/CodeGen/RegisterCoalescer.cpp | 34 +++++++++++++++++++++++++++---- 1 file changed, 30 insertions(+), 4 deletions(-) diff --git a/lib/CodeGen/RegisterCoalescer.cpp b/lib/CodeGen/RegisterCoalescer.cpp index f3fb2b763b2..c2d1620c552 100644 --- a/lib/CodeGen/RegisterCoalescer.cpp +++ b/lib/CodeGen/RegisterCoalescer.cpp @@ -224,6 +224,32 @@ namespace { /// Dst, we can drop \p Copy. bool applyTerminalRule(const MachineInstr &Copy) const; + /// Check whether or not \p LI is composed by multiple connected + /// components and if that is the case, fix that. + void splitNewRanges(LiveInterval *LI) { + ConnectedVNInfoEqClasses ConEQ(*LIS); + unsigned NumComps = ConEQ.Classify(LI); + if (NumComps <= 1) + return; + SmallVector NewComps(1, LI); + for (unsigned i = 1; i != NumComps; ++i) { + unsigned VReg = MRI->createVirtualRegister(MRI->getRegClass(LI->reg)); + NewComps.push_back(&LIS->createEmptyInterval(VReg)); + } + + ConEQ.Distribute(&NewComps[0], *MRI); + } + + /// Wrapper method for \see LiveIntervals::shrinkToUses. + /// This method does the proper fixing of the live-ranges when the afore + /// mentioned method returns true. + void shrinkToUses(LiveInterval *LI, + SmallVectorImpl *Dead = nullptr) { + if (LIS->shrinkToUses(LI, Dead)) + // We may have created multiple connected components, split them. + splitNewRanges(LI); + } + public: static char ID; ///< Class identification, replacement for typeinfo RegisterCoalescer() : MachineFunctionPass(ID) { @@ -556,7 +582,7 @@ bool RegisterCoalescer::adjustCopiesBackFrom(const CoalescerPair &CP, // will also add the isKill marker. CopyMI->substituteRegister(IntA.reg, IntB.reg, 0, *TRI); if (AS->end == CopyIdx) - LIS->shrinkToUses(&IntA); + shrinkToUses(&IntA); ++numExtends; return true; @@ -1046,7 +1072,7 @@ bool RegisterCoalescer::reMaterializeTrivialDef(const CoalescerPair &CP, ++NumReMats; // The source interval can become smaller because we removed a use. - LIS->shrinkToUses(&SrcInt, &DeadDefs); + shrinkToUses(&SrcInt, &DeadDefs); if (!DeadDefs.empty()) { // If the virtual SrcReg is completely eliminated, update all DBG_VALUEs // to describe DstReg instead. @@ -1427,7 +1453,7 @@ bool RegisterCoalescer::joinCopy(MachineInstr *CopyMI, bool &Again) { } if (ShrinkMainRange) { LiveInterval &LI = LIS->getInterval(CP.getDstReg()); - LIS->shrinkToUses(&LI); + shrinkToUses(&LI); } // SrcReg is guaranteed to be the register whose live interval that is @@ -2635,7 +2661,7 @@ bool RegisterCoalescer::joinVirtRegs(CoalescerPair &CP) { LHSVals.eraseInstrs(ErasedInstrs, ShrinkRegs); RHSVals.eraseInstrs(ErasedInstrs, ShrinkRegs); while (!ShrinkRegs.empty()) - LIS->shrinkToUses(&LIS->getInterval(ShrinkRegs.pop_back_val())); + shrinkToUses(&LIS->getInterval(ShrinkRegs.pop_back_val())); // Join RHS into LHS. LHS.join(RHS, LHSVals.getAssignments(), RHSVals.getAssignments(), NewVNInfo); -- 2.34.1