mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2025-07-16 11:24:39 +00:00
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:
@@ -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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (ValueIn == nullptr)
|
||||||
break;
|
break;
|
||||||
unsigned Reg = MI->getOperand(1).getReg();
|
VNI = ValueIn;
|
||||||
if (!TargetRegisterInfo::isVirtualRegister(Reg))
|
Reg = SrcReg;
|
||||||
break;
|
|
||||||
LiveQueryResult LRQ = LIS->getInterval(Reg).Query(VNI->def);
|
|
||||||
if (!LRQ.valueIn())
|
|
||||||
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);
|
return CR_Erase;
|
||||||
// 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;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// 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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user