diff --git a/llvm/lib/CodeGen/TwoAddressInstructionPass.cpp b/llvm/lib/CodeGen/TwoAddressInstructionPass.cpp --- a/llvm/lib/CodeGen/TwoAddressInstructionPass.cpp +++ b/llvm/lib/CodeGen/TwoAddressInstructionPass.cpp @@ -1757,6 +1757,34 @@ mi->RemoveOperand(1); mi->setDesc(TII->get(TargetOpcode::COPY)); LLVM_DEBUG(dbgs() << "\t\tconvert to:\t" << *mi); + + // Update LiveIntervals. + if (LIS) { + Register Reg = mi->getOperand(0).getReg(); + LiveInterval &LI = LIS->getInterval(Reg); + if (LI.hasSubRanges()) { + // The COPY no longer defines subregs of %reg except for + // %reg.subidx. + LaneBitmask LaneMask = + TRI->getSubRegIndexLaneMask(mi->getOperand(0).getSubReg()); + SlotIndex Idx = LIS->getInstructionIndex(*mi); + for (auto &S : LI.subranges()) { + if ((S.LaneMask & LaneMask).none()) { + LiveRange::iterator UseSeg = S.FindSegmentContaining(Idx); + LiveRange::iterator DefSeg = std::next(UseSeg); + S.MergeValueNumberInto(DefSeg->valno, UseSeg->valno); + } + } + + // The COPY no longer has a use of %reg. + LIS->shrinkToUses(&LI); + } else { + // The live interval for Reg did not have subranges but now it needs + // them because we have introduced a subreg def. Recompute it. + LIS->removeInterval(Reg); + LIS->createAndComputeVirtRegInterval(Reg); + } + } } // Clear TiedOperands here instead of at the top of the loop diff --git a/llvm/test/CodeGen/AMDGPU/undefined-subreg-liverange.ll b/llvm/test/CodeGen/AMDGPU/undefined-subreg-liverange.ll --- a/llvm/test/CodeGen/AMDGPU/undefined-subreg-liverange.ll +++ b/llvm/test/CodeGen/AMDGPU/undefined-subreg-liverange.ll @@ -1,5 +1,6 @@ ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py ; RUN: llc -march=amdgcn -verify-machineinstrs < %s | FileCheck %s +; RUN: llc -march=amdgcn -verify-machineinstrs -early-live-intervals < %s | FileCheck %s ; We may have subregister live ranges that are undefined on some paths. The ; verifier should not complain about this.