Index: include/llvm/CodeGen/LiveIntervalAnalysis.h =================================================================== --- include/llvm/CodeGen/LiveIntervalAnalysis.h +++ include/llvm/CodeGen/LiveIntervalAnalysis.h @@ -406,6 +406,9 @@ void splitSeparateComponents(LiveInterval &LI, SmallVectorImpl &SplitLIs); + /// Assure dead subregister definitions have their own vreg assigned. + void renameDeadSubRegDefs(); + private: /// Compute live intervals for all virtual registers. void computeVirtRegs(); Index: lib/CodeGen/LiveIntervalAnalysis.cpp =================================================================== --- lib/CodeGen/LiveIntervalAnalysis.cpp +++ lib/CodeGen/LiveIntervalAnalysis.cpp @@ -1459,3 +1459,84 @@ } ConEQ.Distribute(LI, SplitLIs.data(), *MRI); } + +/// Remove the definition at \p Def from LiveRange \p LR. If there is an +/// adjacent previous segment merge with that. If there is no Def at the +/// specified position do nothing. +static void removeDefFrom(LiveRange &LR, SlotIndex Def) { + LiveRange::iterator I = LR.find(Def); + if (I->start != Def) + return; + + // Merge with previous segment if possible. + if (I != LR.begin()) { + LiveRange::iterator Prev = std::prev(I); + if (SlotIndex::isSameInstr(Prev->end, I->start)) + Prev->end = I->end; + } + I->valno->markUnused(); + LR.removeSegment(I); +} + +void LiveIntervals::renameDeadSubRegDefs() { + for (size_t I = 0, E = MRI->getNumVirtRegs(); I < E; ++I) { + unsigned Reg = TargetRegisterInfo::index2VirtReg(I); + LiveInterval *LI = VirtRegIntervals[Reg]; + if (LI == nullptr || !LI->hasSubRanges()) + continue; + + // Only look for vregs with multiple definition to find candidates of dead + // subregister defs that do not write into an own register. + if (LI->valnos.size() < 2) + continue; + + for (const VNInfo *VNI : LI->valnos) { + if (VNI->isUnused()) + continue; + + SlotIndex Def = VNI->def; + unsigned Reg = LI->reg; + // Do we only have dead (subregister) defs at VNI->def? + bool OnlyDeadDefs = true; + for (const LiveInterval::SubRange &SR : LI->subranges()) { + LiveRange::const_iterator SI = SR.find(Def); + if (SI != SR.end() && SI->start == Def && + !SlotIndex::isSameInstr(SI->start, SI->end)) { + OnlyDeadDefs = false; + break; + } + } + if (!OnlyDeadDefs) + continue; + + MachineInstr *MI = getInstructionFromIndex(Def); + if (MI == nullptr) + continue; + const TargetRegisterClass *RegClass = MRI->getRegClass(Reg); + unsigned NewVReg = MRI->createVirtualRegister(RegClass); + LiveInterval &NewLI = createEmptyInterval(NewVReg); + NewLI.createDeadDef(Def, getVNInfoAllocator()); + LaneBitmask LaneMask = 0; + for (MachineOperand &MO : MI->operands()) { + if (!MO.isReg() || !MO.isDef() || MO.getReg() != Reg) + continue; + unsigned SubRegIndex = MO.getSubReg(); + assert(SubRegIndex != 0 && !MO.isUndef() && + "Should find proper subreg def"); + LaneMask |= TRI->getSubRegIndexLaneMask(SubRegIndex); + MO.setReg(NewVReg); + MO.setIsUndef(); + MO.setIsDead(); + } + assert(LaneMask != 0); + + NewLI.createSubRangeFrom(getVNInfoAllocator(), LaneMask, NewLI); + + // Remove Def from LI. + for (LiveInterval::SubRange &SR : LI->subranges()) + removeDefFrom(SR, Def); + LI->removeEmptySubRanges(); + removeDefFrom(*LI, Def); + } + } +}