Index: lib/CodeGen/RegisterCoalescer.cpp =================================================================== --- lib/CodeGen/RegisterCoalescer.cpp +++ lib/CodeGen/RegisterCoalescer.cpp @@ -1922,6 +1922,28 @@ // Update regalloc hint. TRI->updateRegAllocHint(CP.getSrcReg(), CP.getDstReg(), *MF); + if (!CP.isPhys()) { + // Fix up the case that some subreg was undefined at a use, and thus the + // use was not in the live range, but due to merging it has now become + // defined. + LiveInterval &LI = LIS->getInterval(CP.getDstReg()); + LLVM_DEBUG(dbgs() << "\tBefore extending subranges: " << LI << '\n'); + for (auto &S : LI.subranges()) { + SmallVector Uses; + for (auto &MO : MRI->reg_operands(CP.getDstReg())) { + if (!MO.isUse() || MO.isUndef() || MO.isDebug()) + continue; + auto OperandMask = TRI->getSubRegIndexLaneMask(MO.getSubReg()); + if ((OperandMask & S.LaneMask).none()) + continue; + Uses.push_back(LIS->getInstructionIndex(*MO.getParent()).getRegSlot()); + } + SmallVector Undefs; + LI.computeSubRangeUndefs(Undefs, S.LaneMask, *MRI, *LIS->getSlotIndexes()); + LIS->extendToIndices(S, Uses, Undefs); + } + } + LLVM_DEBUG({ dbgs() << "\tSuccess: " << printReg(CP.getSrcReg(), TRI, CP.getSrcIdx()) << " -> " << printReg(CP.getDstReg(), TRI, CP.getDstIdx()) << '\n'; Index: test/CodeGen/AMDGPU/coalescing-subreg-was-undef-but-became-def.mir =================================================================== --- /dev/null +++ test/CodeGen/AMDGPU/coalescing-subreg-was-undef-but-became-def.mir @@ -0,0 +1,37 @@ +# RUN: llc -march=amdgcn -mcpu=gfx803 -run-pass simple-register-coalescing -verify-machineinstrs -o - %s +# +# This is another example of a test giving "Couldn't join subrange!" +# +# This shows a case where a whole reg use point of the whole register was +# undefined in one subreg, but after coalescing it became defined but the +# subrange was not updated to reflect that. +# + +--- +name: coalescing_makes_lane_defined +tracksRegLiveness: true +body: | + bb.0: + successors: %bb.1, %bb.2 + + %0:sreg_32_xm0 = S_MOV_B32 0 + undef %1.sub2:sreg_128 = COPY %0 + undef %2.sub0:sreg_128 = S_MOV_B32 0 + undef %3.sub2:sreg_128 = COPY %0 + S_CBRANCH_SCC0 %bb.2, implicit undef $scc + + bb.1: + successors: %bb.2 + + undef %4.sub0:sreg_128 = S_MOV_B32 -1 + %4.sub2:sreg_128 = COPY killed %0 + %5:sreg_128 = COPY killed %4 + %6:sreg_128 = COPY killed %1 + %3:sreg_128 = COPY killed %6 + %2:sreg_128 = COPY killed %5 + + bb.2: + S_NOP 0, implicit killed %3 + S_ENDPGM implicit %2 + +...