Index: include/llvm/CodeGen/LiveIntervalAnalysis.h =================================================================== --- include/llvm/CodeGen/LiveIntervalAnalysis.h +++ include/llvm/CodeGen/LiveIntervalAnalysis.h @@ -153,6 +153,8 @@ /// Dead PHIDef values are marked as unused. New dead machine instructions /// are added to the dead vector. Returns true if the interval may have been /// separated into multiple connected components. + /// May create new VRegs/LiveIntervals with a single dead def to break apart + /// separated dead subregister defs. bool shrinkToUses(LiveInterval *li, SmallVectorImpl *dead = nullptr); @@ -416,6 +418,8 @@ /// if it is not nullptr. /// Returns true if any PHI value numbers have been removed which may /// have separated the interval into multiple connected components. + /// May create new VRegs/LiveIntervals with a single dead def to break apart + /// separated dead subregister defs. bool computeDeadValues(LiveInterval &LI, SmallVectorImpl *dead); Index: lib/CodeGen/LiveIntervalAnalysis.cpp =================================================================== --- lib/CodeGen/LiveIntervalAnalysis.cpp +++ lib/CodeGen/LiveIntervalAnalysis.cpp @@ -455,6 +455,24 @@ return CanSeparate; } +static void removeDeadDef(LiveInterval &LI, LiveRange::iterator I) { + assert(SlotIndex::isSameInstr(I->start, I->end)); + + SlotIndex Def = I->start; + for (LiveInterval::SubRange &SR : LI.subranges()) { + LiveRange::iterator SRI = SR.FindSegmentContaining(Def); + if (SRI != SR.end()) { + assert(SlotIndex::isSameInstr(SRI->start, SRI->end)); + SRI->valno->markUnused(); + SR.removeSegment(SRI); + } + } + LI.removeEmptySubRanges(); + + I->valno->markUnused(); + LI.removeSegment(I); +} + bool LiveIntervals::computeDeadValues(LiveInterval &LI, SmallVectorImpl *dead) { bool PHIRemoved = false; @@ -467,10 +485,13 @@ // Is the register live before? Otherwise we may have to add a read-undef // flag for subregister defs. - if (MRI->shouldTrackSubRegLiveness(LI.reg)) { + bool DeadBeforeDef = false; + unsigned VReg = LI.reg; + if (MRI->shouldTrackSubRegLiveness(VReg)) { if ((I == LI.begin() || std::prev(I)->end < Def) && !VNI->isPHIDef()) { MachineInstr *MI = getInstructionFromIndex(Def); - MI->addRegisterDefReadUndef(LI.reg); + MI->addRegisterDefReadUndef(VReg); + DeadBeforeDef = true; } } @@ -478,15 +499,33 @@ continue; if (VNI->isPHIDef()) { // This is a dead PHI. Remove it. - VNI->markUnused(); - LI.removeSegment(I); + removeDeadDef(LI, I); DEBUG(dbgs() << "Dead PHI at " << Def << " may separate interval\n"); PHIRemoved = true; } else { // This is a dead def. Make sure the instruction knows. MachineInstr *MI = getInstructionFromIndex(Def); assert(MI && "No instruction defining live value"); - MI->addRegisterDead(LI.reg, TRI); + MI->addRegisterDead(VReg, TRI); + + // If we have a dead def that is completely separate from the rest of + // the liverange then we rewrite it to use a different VReg to not violate + // the rule that the liveness of a virtual register forms a connected + // component. This should only happen if subregister liveness is tracked. + if (DeadBeforeDef) { + // Create a fresh vreg and rewrite MI. + const TargetRegisterClass *RegClass = MRI->getRegClass(VReg); + unsigned NewVReg = MRI->createVirtualRegister(RegClass); + LiveInterval &NewLI = createEmptyInterval(NewVReg); + NewLI.createDeadDef(Def, VNInfoAllocator); + for (MachineOperand &MO : MI->operands()) { + if (MO.isReg() && MO.getReg() == VReg) + MO.setReg(NewVReg); + } + // Remove the dead segments from the old register liveness info. + removeDeadDef(LI, I); + } + if (dead && MI->allDefsAreDead()) { DEBUG(dbgs() << "All defs dead: " << Def << '\t' << *MI); dead->push_back(MI); Index: test/CodeGen/AMDGPU/partially-dead-super-register-immediate.ll =================================================================== --- test/CodeGen/AMDGPU/partially-dead-super-register-immediate.ll +++ test/CodeGen/AMDGPU/partially-dead-super-register-immediate.ll @@ -1,4 +1,3 @@ -; XFAIL: * ; RUN: llc -march=amdgcn -verify-machineinstrs -verify-coalescing < %s ; The original and requires materializing a 64-bit immediate for