RegisterCoalescer: Simplify subrange splitting code; NFC

- Use slightly better variable names / compute in a more direct way.

llvm-svn: 296905
This commit is contained in:
Matthias Braun 2017-03-03 19:05:34 +00:00
parent b471d4f25a
commit a04d7ad851
4 changed files with 75 additions and 98 deletions

View File

@ -227,15 +227,22 @@ namespace llvm {
LiveRange(const LiveRange &Other, BumpPtrAllocator &Allocator) {
assert(Other.segmentSet == nullptr &&
"Copying of LiveRanges with active SegmentSets is not supported");
assign(Other, Allocator);
}
/// Copies values numbers and live segments from \p Other into this range.
void assign(const LiveRange &Other, BumpPtrAllocator &Allocator) {
if (this == &Other)
return;
assert(Other.segmentSet == nullptr &&
"Copying of LiveRanges with active SegmentSets is not supported");
// Duplicate valnos.
for (const VNInfo *VNI : Other.valnos) {
for (const VNInfo *VNI : Other.valnos)
createValueCopy(VNI, Allocator);
}
// Now we can copy segments and remap their valnos.
for (const Segment &S : Other.segments) {
for (const Segment &S : Other.segments)
segments.push_back(Segment(S.start, S.end, valnos[S.valno->id]));
}
}
/// advanceTo - Advance the specified iterator to point to the Segment
@ -767,6 +774,19 @@ namespace llvm {
const MachineRegisterInfo &MRI,
const SlotIndexes &Indexes) const;
/// Refines the subranges to support \p LaneMask. This may only be called
/// for LI.hasSubrange()==true. Subregister ranges are split or created
/// until \p LaneMask can be matched exactly. \p Mod is executed on the
/// matching subranges.
///
/// Example:
/// Given an interval with subranges with lanemasks L0F00, L00F0 and
/// L000F, refining for mask L0018. Will split the L00F0 lane into
/// L00E0 and L0010 and the L000F lane into L0007 and L0008. The Mod
/// function will be applied to the L0010 and L0008 subranges.
void refineSubRanges(BumpPtrAllocator &Allocator, LaneBitmask LaneMask,
std::function<void(LiveInterval::SubRange&)> Mod);
bool operator<(const LiveInterval& other) const {
const SlotIndex &thisIndex = beginIndex();
const SlotIndex &otherIndex = other.beginIndex();

View File

@ -863,6 +863,37 @@ void LiveInterval::clearSubRanges() {
SubRanges = nullptr;
}
void LiveInterval::refineSubRanges(BumpPtrAllocator &Allocator,
LaneBitmask LaneMask, std::function<void(LiveInterval::SubRange&)> Apply) {
LaneBitmask ToApply = LaneMask;
for (SubRange &SR : subranges()) {
LaneBitmask SRMask = SR.LaneMask;
LaneBitmask Matching = SRMask & LaneMask;
if (Matching.none())
continue;
SubRange *MatchingRange;
if (SRMask == Matching) {
// The subrange fits (it does not cover bits outside \p LaneMask).
MatchingRange = &SR;
} else {
// We have to split the subrange into a matching and non-matching part.
// Reduce lanemask of existing lane to non-matching part.
SR.LaneMask = SRMask & ~Matching;
// Create a new subrange for the matching part
MatchingRange = createSubRangeFrom(Allocator, Matching, SR);
}
Apply(*MatchingRange);
ToApply &= ~Matching;
}
// Create a new subrange if there are uncovered bits left.
if (ToApply.any()) {
SubRange *NewRange = createSubRange(Allocator, ToApply);
Apply(*NewRange);
}
}
unsigned LiveInterval::getSize() const {
unsigned Sum = 0;
for (const Segment &S : segments)

View File

@ -75,34 +75,11 @@ void LiveRangeCalc::calculate(LiveInterval &LI, bool TrackSubRegs) {
LI.createSubRangeFrom(*Alloc, ClassMask, LI);
}
LaneBitmask Mask = SubMask;
for (LiveInterval::SubRange &S : LI.subranges()) {
// A Mask for subregs common to the existing subrange and current def.
LaneBitmask Common = S.LaneMask & Mask;
if (Common.none())
continue;
LiveInterval::SubRange *CommonRange;
// A Mask for subregs covered by the subrange but not the current def.
LaneBitmask RM = S.LaneMask & ~Mask;
if (RM.any()) {
// Split the subrange S into two parts: one covered by the current
// def (CommonRange), and the one not affected by it (updated S).
S.LaneMask = RM;
CommonRange = LI.createSubRangeFrom(*Alloc, Common, S);
} else {
assert(Common == S.LaneMask);
CommonRange = &S;
}
LI.refineSubRanges(*Alloc, SubMask,
[&MO, this](LiveInterval::SubRange &SR) {
if (MO.isDef())
createDeadDef(*Indexes, *Alloc, *CommonRange, MO);
Mask &= ~Common;
}
// Create a new SubRange for subregs we did not cover yet.
if (Mask.any()) {
LiveInterval::SubRange *NewRange = LI.createSubRange(*Alloc, Mask);
if (MO.isDef())
createDeadDef(*Indexes, *Alloc, *NewRange, MO);
}
createDeadDef(*Indexes, *Alloc, SR, MO);
});
}
// Create the def in the main liverange. We do not have to do this if

View File

@ -815,42 +815,14 @@ bool RegisterCoalescer::removeCopyByCommutingDef(const CoalescerPair &CP,
VNInfo *ASubValNo = SA.getVNInfoAt(AIdx);
assert(ASubValNo != nullptr);
LaneBitmask AMask = SA.LaneMask;
for (LiveInterval::SubRange &SB : IntB.subranges()) {
LaneBitmask BMask = SB.LaneMask;
LaneBitmask Common = BMask & AMask;
if (Common.none())
continue;
DEBUG( dbgs() << "\t\tCopy_Merge " << PrintLaneMask(BMask)
<< " into " << PrintLaneMask(Common) << '\n');
LaneBitmask BRest = BMask & ~AMask;
LiveInterval::SubRange *CommonRange;
if (BRest.any()) {
SB.LaneMask = BRest;
DEBUG(dbgs() << "\t\tReduce Lane to " << PrintLaneMask(BRest)
<< '\n');
// Duplicate SubRange for newly merged common stuff.
CommonRange = IntB.createSubRangeFrom(Allocator, Common, SB);
} else {
// We van reuse the L SubRange.
SB.LaneMask = Common;
CommonRange = &SB;
}
LiveRange RangeCopy(SB, Allocator);
VNInfo *BSubValNo = CommonRange->getVNInfoAt(CopyIdx);
assert(BSubValNo->def == CopyIdx);
BSubValNo->def = ASubValNo->def;
addSegmentsWithValNo(*CommonRange, BSubValNo, SA, ASubValNo);
AMask &= ~BMask;
}
if (AMask.any()) {
DEBUG(dbgs() << "\t\tNew Lane " << PrintLaneMask(AMask) << '\n');
LiveRange *NewRange = IntB.createSubRange(Allocator, AMask);
VNInfo *BSubValNo = NewRange->getNextValue(CopyIdx, Allocator);
addSegmentsWithValNo(*NewRange, BSubValNo, SA, ASubValNo);
}
IntB.refineSubRanges(Allocator, SA.LaneMask,
[&Allocator,&SA,CopyIdx,ASubValNo](LiveInterval::SubRange &SR) {
VNInfo *BSubValNo = SR.empty()
? SR.getNextValue(CopyIdx, Allocator)
: SR.getVNInfoAt(CopyIdx);
assert(BSubValNo != nullptr);
addSegmentsWithValNo(SR, BSubValNo, SA, ASubValNo);
});
}
}
@ -2926,39 +2898,16 @@ void RegisterCoalescer::mergeSubRangeInto(LiveInterval &LI,
LaneBitmask LaneMask,
CoalescerPair &CP) {
BumpPtrAllocator &Allocator = LIS->getVNInfoAllocator();
for (LiveInterval::SubRange &R : LI.subranges()) {
LaneBitmask RMask = R.LaneMask;
// LaneMask of subregisters common to subrange R and ToMerge.
LaneBitmask Common = RMask & LaneMask;
// There is nothing to do without common subregs.
if (Common.none())
continue;
DEBUG(dbgs() << "\t\tCopy+Merge " << PrintLaneMask(RMask) << " into "
<< PrintLaneMask(Common) << '\n');
// LaneMask of subregisters contained in the R range but not in ToMerge,
// they have to split into their own subrange.
LaneBitmask LRest = RMask & ~LaneMask;
LiveInterval::SubRange *CommonRange;
if (LRest.any()) {
R.LaneMask = LRest;
DEBUG(dbgs() << "\t\tReduce Lane to " << PrintLaneMask(LRest) << '\n');
// Duplicate SubRange for newly merged common stuff.
CommonRange = LI.createSubRangeFrom(Allocator, Common, R);
LI.refineSubRanges(Allocator, LaneMask,
[this,&Allocator,&ToMerge,&CP](LiveInterval::SubRange &SR) {
if (SR.empty()) {
SR.assign(ToMerge, Allocator);
} else {
// Reuse the existing range.
R.LaneMask = Common;
CommonRange = &R;
// joinSubRegRange() destroys the merged range, so we need a copy.
LiveRange RangeCopy(ToMerge, Allocator);
joinSubRegRanges(SR, RangeCopy, SR.LaneMask, CP);
}
LiveRange RangeCopy(ToMerge, Allocator);
joinSubRegRanges(*CommonRange, RangeCopy, Common, CP);
LaneMask &= ~RMask;
}
if (LaneMask.any()) {
DEBUG(dbgs() << "\t\tNew Lane " << PrintLaneMask(LaneMask) << '\n');
LI.createSubRangeFrom(Allocator, LaneMask, ToMerge);
}
});
}
bool RegisterCoalescer::joinVirtRegs(CoalescerPair &CP) {