RegisterCoalescer: Fix stripCopies() picking up main range instead of subregister range

This fixes a problem where stripCopies() would switch to values in the
main liverange when it crossed a copy instruction. However when joining
subranges we need to stay in the respective subregister ranges.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@224461 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Matthias Braun
2014-12-17 21:25:20 +00:00
parent aa14ffddcf
commit a1a68905b5

View File

@ -159,12 +159,16 @@ namespace {
/// Add the LiveRange @p ToMerge as a subregister liverange of @p LI. /// Add the LiveRange @p ToMerge as a subregister liverange of @p LI.
/// Subranges in @p LI which only partially interfere with the desired /// Subranges in @p LI which only partially interfere with the desired
/// LaneMask are split as necessary. /// LaneMask are split as necessary.
/// @p DestLaneMask are the lanes that @p ToMerge will end up in after the
/// merge, @p PrevLaneMask the ones it currently occupies.
void mergeSubRangeInto(LiveInterval &LI, const LiveRange &ToMerge, void mergeSubRangeInto(LiveInterval &LI, const LiveRange &ToMerge,
unsigned LaneMask, CoalescerPair &CP); unsigned DstLaneMask, unsigned PrevLaneMask,
CoalescerPair &CP);
/// Join the liveranges of two subregisters. Joins @p RRange into /// Join the liveranges of two subregisters. Joins @p RRange into
/// @p LRange, @p RRange may be invalid afterwards. /// @p LRange, @p RRange may be invalid afterwards.
void joinSubRegRanges(LiveRange &LRange, LiveRange &RRange, void joinSubRegRanges(LiveRange &LRange, unsigned LMask,
LiveRange &RRange, unsigned RMask,
const CoalescerPair &CP); const CoalescerPair &CP);
/// We found a non-trivially-coalescable copy. If /// We found a non-trivially-coalescable copy. If
@ -1503,6 +1507,8 @@ class JoinVals {
/// (Main) register we work on. /// (Main) register we work on.
const unsigned Reg; const unsigned Reg;
/// When coalescing a subregister range this is the LaneMask in Reg.
unsigned SubRegMask;
/// This is true when joining sub register ranges, false when joining main /// This is true when joining sub register ranges, false when joining main
/// ranges. /// ranges.
const bool SubRangeJoin; const bool SubRangeJoin;
@ -1603,7 +1609,8 @@ class JoinVals {
SmallVector<Val, 8> Vals; SmallVector<Val, 8> Vals;
unsigned computeWriteLanes(const MachineInstr *DefMI, bool &Redef) const; unsigned computeWriteLanes(const MachineInstr *DefMI, bool &Redef) const;
VNInfo *stripCopies(VNInfo *VNI) const; VNInfo *stripCopies(VNInfo *VNI, unsigned LaneMask, unsigned &Reg) const;
bool valuesIdentical(VNInfo *Val0, VNInfo *Val1, const JoinVals &Other) const;
ConflictResolution analyzeValue(unsigned ValNo, JoinVals &Other); ConflictResolution analyzeValue(unsigned ValNo, JoinVals &Other);
void computeAssignment(unsigned ValNo, JoinVals &Other); void computeAssignment(unsigned ValNo, JoinVals &Other);
bool taintExtent(unsigned, unsigned, JoinVals&, bool taintExtent(unsigned, unsigned, JoinVals&,
@ -1615,9 +1622,9 @@ public:
JoinVals(LiveRange &LR, unsigned Reg, unsigned subIdx, JoinVals(LiveRange &LR, unsigned Reg, unsigned subIdx,
SmallVectorImpl<VNInfo*> &newVNInfo, SmallVectorImpl<VNInfo*> &newVNInfo,
const CoalescerPair &cp, LiveIntervals *lis, const CoalescerPair &cp, LiveIntervals *lis,
const TargetRegisterInfo *tri, bool SubRangeJoin, const TargetRegisterInfo *tri, unsigned SubRegMask,
bool TrackSubRegLiveness) bool SubRangeJoin, bool TrackSubRegLiveness)
: LR(LR), Reg(Reg), SubRangeJoin(SubRangeJoin), : LR(LR), Reg(Reg), SubRegMask(SubRegMask), SubRangeJoin(SubRangeJoin),
TrackSubRegLiveness(TrackSubRegLiveness), SubIdx(subIdx), TrackSubRegLiveness(TrackSubRegLiveness), SubIdx(subIdx),
NewVNInfo(newVNInfo), CP(cp), LIS(lis), Indexes(LIS->getSlotIndexes()), NewVNInfo(newVNInfo), CP(cp), LIS(lis), Indexes(LIS->getSlotIndexes()),
TRI(tri), Assignments(LR.getNumValNums(), -1), TRI(tri), Assignments(LR.getNumValNums(), -1),
@ -1673,23 +1680,58 @@ unsigned JoinVals::computeWriteLanes(const MachineInstr *DefMI, bool &Redef)
} }
/// Find the ultimate value that VNI was copied from. /// Find the ultimate value that VNI was copied from.
VNInfo *JoinVals::stripCopies(VNInfo *VNI) const { VNInfo *JoinVals::stripCopies(VNInfo *VNI, unsigned LaneMask, unsigned &Reg)
const {
while (!VNI->isPHIDef()) { while (!VNI->isPHIDef()) {
MachineInstr *MI = Indexes->getInstructionFromIndex(VNI->def); SlotIndex Def = VNI->def;
MachineInstr *MI = Indexes->getInstructionFromIndex(Def);
assert(MI && "No defining instruction"); assert(MI && "No defining instruction");
if (!MI->isFullCopy()) if (!MI->isFullCopy())
return VNI;
unsigned SrcReg = MI->getOperand(1).getReg();
if (!TargetRegisterInfo::isVirtualRegister(SrcReg))
return VNI;
const LiveInterval &LI = LIS->getInterval(SrcReg);
VNInfo *ValueIn;
// No subrange involved.
if (LaneMask == 0 || !LI.hasSubRanges()) {
LiveQueryResult LRQ = LI.Query(Def);
ValueIn = LRQ.valueIn();
} else {
// Query subranges. Pick the first matching one.
ValueIn = nullptr;
for (const LiveInterval::SubRange &S : LI.subranges()) {
if ((S.LaneMask & LaneMask) == 0)
continue;
LiveQueryResult LRQ = S.Query(Def);
ValueIn = LRQ.valueIn();
break; break;
unsigned Reg = MI->getOperand(1).getReg(); }
if (!TargetRegisterInfo::isVirtualRegister(Reg)) }
if (ValueIn == nullptr)
break; break;
LiveQueryResult LRQ = LIS->getInterval(Reg).Query(VNI->def); VNI = ValueIn;
if (!LRQ.valueIn()) Reg = SrcReg;
break;
VNI = LRQ.valueIn();
} }
return VNI; return VNI;
} }
bool JoinVals::valuesIdentical(VNInfo *Value0, VNInfo *Value1,
const JoinVals &Other) const {
unsigned Reg0 = Reg;
VNInfo *Stripped0 = stripCopies(Value0, SubRegMask, Reg0);
unsigned Reg1 = Other.Reg;
VNInfo *Stripped1 = stripCopies(Value1, Other.SubRegMask, Reg1);
if (Stripped0 == Stripped1)
return true;
// Special case: when merging subranges one of the ranges is actually a copy,
// so we can't simply compare VNInfos but have to resort to comparing
// position and register of the Def.
return Stripped0->def == Stripped1->def && Reg0 == Reg1;
}
/// Analyze ValNo in this live range, and set all fields of Vals[ValNo]. /// Analyze ValNo in this live range, and set all fields of Vals[ValNo].
/// Return a conflict resolution when possible, but leave the hard cases as /// Return a conflict resolution when possible, but leave the hard cases as
/// CR_Unresolved. /// CR_Unresolved.
@ -1849,26 +1891,9 @@ JoinVals::analyzeValue(unsigned ValNo, JoinVals &Other) {
// %other = COPY %ext // %other = COPY %ext
// %this = COPY %ext <-- Erase this copy // %this = COPY %ext <-- Erase this copy
// //
if (DefMI->isFullCopy() && !CP.isPartial()) { if (DefMI->isFullCopy() && !CP.isPartial()
VNInfo *TVNI = stripCopies(VNI); && valuesIdentical(VNI, V.OtherVNI, Other))
VNInfo *OVNI = stripCopies(V.OtherVNI);
// Map our subrange values to main range as stripCopies() follows the main
// ranges.
if (SubRangeJoin && TVNI != OVNI) {
if (TVNI == VNI) {
LiveInterval &LI = LIS->getInterval(Reg);
TVNI = LI.getVNInfoAt(TVNI->def);
}
if (OVNI == V.OtherVNI) {
LiveInterval &LI = LIS->getInterval(Other.Reg);
OVNI = LI.getVNInfoAt(OVNI->def);
}
}
if (TVNI == OVNI)
return CR_Erase; return CR_Erase;
}
// If the lanes written by this instruction were all undef in OtherVNI, it is // If the lanes written by this instruction were all undef in OtherVNI, it is
// still safe to join the live ranges. This can't be done with a simple value // still safe to join the live ranges. This can't be done with a simple value
@ -2277,13 +2302,14 @@ void JoinVals::eraseInstrs(SmallPtrSetImpl<MachineInstr*> &ErasedInstrs,
} }
} }
void RegisterCoalescer::joinSubRegRanges(LiveRange &LRange, LiveRange &RRange, void RegisterCoalescer::joinSubRegRanges(LiveRange &LRange, unsigned LMask,
LiveRange &RRange, unsigned RMask,
const CoalescerPair &CP) { const CoalescerPair &CP) {
SmallVector<VNInfo*, 16> NewVNInfo; SmallVector<VNInfo*, 16> NewVNInfo;
JoinVals RHSVals(RRange, CP.getSrcReg(), CP.getSrcIdx(), JoinVals RHSVals(RRange, CP.getSrcReg(), CP.getSrcIdx(),
NewVNInfo, CP, LIS, TRI, true, true); NewVNInfo, CP, LIS, TRI, LMask, true, true);
JoinVals LHSVals(LRange, CP.getDstReg(), CP.getDstIdx(), JoinVals LHSVals(LRange, CP.getDstReg(), CP.getDstIdx(),
NewVNInfo, CP, LIS, TRI, true, true); NewVNInfo, CP, LIS, TRI, RMask, true, true);
/// Compute NewVNInfo and resolve conflicts (see also joinVirtRegs()) /// Compute NewVNInfo and resolve conflicts (see also joinVirtRegs())
/// Conflicts should already be resolved so the mapping/resolution should /// Conflicts should already be resolved so the mapping/resolution should
@ -2321,13 +2347,14 @@ void RegisterCoalescer::joinSubRegRanges(LiveRange &LRange, LiveRange &RRange,
void RegisterCoalescer::mergeSubRangeInto(LiveInterval &LI, void RegisterCoalescer::mergeSubRangeInto(LiveInterval &LI,
const LiveRange &ToMerge, const LiveRange &ToMerge,
unsigned LaneMask, unsigned DstLaneMask,
unsigned PrevLaneMask,
CoalescerPair &CP) { CoalescerPair &CP) {
BumpPtrAllocator &Allocator = LIS->getVNInfoAllocator(); BumpPtrAllocator &Allocator = LIS->getVNInfoAllocator();
for (LiveInterval::SubRange &R : LI.subranges()) { for (LiveInterval::SubRange &R : LI.subranges()) {
unsigned RMask = R.LaneMask; unsigned RMask = R.LaneMask;
// LaneMask of subregisters common to subrange R and ToMerge. // LaneMask of subregisters common to subrange R and ToMerge.
unsigned Common = RMask & LaneMask; unsigned Common = RMask & DstLaneMask;
// There is nothing to do without common subregs. // There is nothing to do without common subregs.
if (Common == 0) if (Common == 0)
continue; continue;
@ -2335,7 +2362,7 @@ void RegisterCoalescer::mergeSubRangeInto(LiveInterval &LI,
DEBUG(dbgs() << format("\t\tCopy+Merge %04X into %04X\n", RMask, Common)); DEBUG(dbgs() << format("\t\tCopy+Merge %04X into %04X\n", RMask, Common));
// LaneMask of subregisters contained in the R range but not in ToMerge, // LaneMask of subregisters contained in the R range but not in ToMerge,
// they have to split into their own subrange. // they have to split into their own subrange.
unsigned LRest = RMask & ~LaneMask; unsigned LRest = RMask & ~DstLaneMask;
LiveInterval::SubRange *CommonRange; LiveInterval::SubRange *CommonRange;
if (LRest != 0) { if (LRest != 0) {
R.LaneMask = LRest; R.LaneMask = LRest;
@ -2348,13 +2375,14 @@ void RegisterCoalescer::mergeSubRangeInto(LiveInterval &LI,
CommonRange = &R; CommonRange = &R;
} }
LiveRange RangeCopy(ToMerge, Allocator); LiveRange RangeCopy(ToMerge, Allocator);
joinSubRegRanges(*CommonRange, RangeCopy, CP); joinSubRegRanges(*CommonRange, CommonRange->LaneMask, RangeCopy,
LaneMask &= ~RMask; PrevLaneMask, CP);
DstLaneMask &= ~RMask;
} }
if (LaneMask != 0) { if (DstLaneMask != 0) {
DEBUG(dbgs() << format("\t\tNew Lane %04X\n", LaneMask)); DEBUG(dbgs() << format("\t\tNew Lane %04X\n", DstLaneMask));
LI.createSubRangeFrom(Allocator, LaneMask, ToMerge); LI.createSubRangeFrom(Allocator, DstLaneMask, ToMerge);
} }
} }
@ -2364,9 +2392,9 @@ bool RegisterCoalescer::joinVirtRegs(CoalescerPair &CP) {
LiveInterval &LHS = LIS->getInterval(CP.getDstReg()); LiveInterval &LHS = LIS->getInterval(CP.getDstReg());
bool TrackSubRegLiveness = MRI->tracksSubRegLiveness(); bool TrackSubRegLiveness = MRI->tracksSubRegLiveness();
JoinVals RHSVals(RHS, CP.getSrcReg(), CP.getSrcIdx(), NewVNInfo, CP, LIS, TRI, JoinVals RHSVals(RHS, CP.getSrcReg(), CP.getSrcIdx(), NewVNInfo, CP, LIS, TRI,
false, TrackSubRegLiveness); 0, false, TrackSubRegLiveness);
JoinVals LHSVals(LHS, CP.getDstReg(), CP.getDstIdx(), NewVNInfo, CP, LIS, TRI, JoinVals LHSVals(LHS, CP.getDstReg(), CP.getDstIdx(), NewVNInfo, CP, LIS, TRI,
false, TrackSubRegLiveness); 0, false, TrackSubRegLiveness);
DEBUG(dbgs() << "\t\tRHS = " << RHS DEBUG(dbgs() << "\t\tRHS = " << RHS
<< "\n\t\tLHS = " << LHS << "\n\t\tLHS = " << LHS
@ -2411,7 +2439,7 @@ bool RegisterCoalescer::joinVirtRegs(CoalescerPair &CP) {
DEBUG(dbgs() << "\t\tRHS Mask: " DEBUG(dbgs() << "\t\tRHS Mask: "
<< format("%04X", Mask) << "\n"); << format("%04X", Mask) << "\n");
mergeSubRangeInto(LHS, RHS, Mask, CP); mergeSubRangeInto(LHS, RHS, Mask, 0, CP);
} else { } else {
// Pair up subranges and merge. // Pair up subranges and merge.
for (LiveInterval::SubRange &R : RHS.subranges()) { for (LiveInterval::SubRange &R : RHS.subranges()) {
@ -2425,7 +2453,7 @@ bool RegisterCoalescer::joinVirtRegs(CoalescerPair &CP) {
<< " => " << format("%04X", RMask) << "\n"); << " => " << format("%04X", RMask) << "\n");
} }
mergeSubRangeInto(LHS, R, RMask, CP); mergeSubRangeInto(LHS, R, RMask, R.LaneMask, CP);
} }
} }