mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2025-08-15 06:29:05 +00:00
Extend the CoalescerPair interface to handle symmetric sub-register copies.
Now both SrcReg and DstReg can be sub-registers of the final coalesced register. CoalescerPair::setRegisters still rejects such copies because RegisterCoalescer doesn't yet handle them. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@156848 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
@@ -226,7 +226,8 @@ static bool isMoveInstr(const TargetRegisterInfo &tri, const MachineInstr *MI,
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool CoalescerPair::setRegisters(const MachineInstr *MI) {
|
bool CoalescerPair::setRegisters(const MachineInstr *MI) {
|
||||||
SrcReg = DstReg = SubIdx = 0;
|
SrcReg = DstReg = 0;
|
||||||
|
SrcIdx = DstIdx = 0;
|
||||||
NewRC = 0;
|
NewRC = 0;
|
||||||
Flipped = CrossClass = false;
|
Flipped = CrossClass = false;
|
||||||
|
|
||||||
@@ -269,45 +270,44 @@ bool CoalescerPair::setRegisters(const MachineInstr *MI) {
|
|||||||
|
|
||||||
// Both registers have subreg indices.
|
// Both registers have subreg indices.
|
||||||
if (SrcSub && DstSub) {
|
if (SrcSub && DstSub) {
|
||||||
unsigned SrcPre, DstPre;
|
|
||||||
NewRC = TRI.getCommonSuperRegClass(SrcRC, SrcSub, DstRC, DstSub,
|
NewRC = TRI.getCommonSuperRegClass(SrcRC, SrcSub, DstRC, DstSub,
|
||||||
SrcPre, DstPre);
|
SrcIdx, DstIdx);
|
||||||
if (!NewRC)
|
if (!NewRC)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
// We cannot handle the case where both Src and Dst would be a
|
// We cannot handle the case where both Src and Dst would be a
|
||||||
// sub-register. Yet.
|
// sub-register. Yet.
|
||||||
if (SrcPre && DstPre) {
|
if (SrcIdx && DstIdx) {
|
||||||
DEBUG(dbgs() << "\tCannot handle " << NewRC->getName()
|
DEBUG(dbgs() << "\tCannot handle " << NewRC->getName()
|
||||||
<< " with subregs " << TRI.getSubRegIndexName(SrcPre)
|
<< " with subregs " << TRI.getSubRegIndexName(SrcIdx)
|
||||||
<< " and " << TRI.getSubRegIndexName(DstPre) << '\n');
|
<< " and " << TRI.getSubRegIndexName(DstIdx) << '\n');
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
} else if (DstSub) {
|
||||||
// One of these will be 0, so one register is a sub-register of the other.
|
// SrcReg will be merged with a sub-register of DstReg.
|
||||||
SrcSub = DstPre;
|
SrcIdx = DstSub;
|
||||||
DstSub = SrcPre;
|
|
||||||
}
|
|
||||||
|
|
||||||
// There can be no SrcSub.
|
|
||||||
if (SrcSub) {
|
|
||||||
std::swap(Src, Dst);
|
|
||||||
std::swap(SrcRC, DstRC);
|
|
||||||
DstSub = SrcSub;
|
|
||||||
SrcSub = 0;
|
|
||||||
assert(!Flipped && "Unexpected flip");
|
|
||||||
Flipped = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Find the new register class.
|
|
||||||
if (!NewRC) {
|
|
||||||
if (DstSub)
|
|
||||||
NewRC = TRI.getMatchingSuperRegClass(DstRC, SrcRC, DstSub);
|
NewRC = TRI.getMatchingSuperRegClass(DstRC, SrcRC, DstSub);
|
||||||
else
|
} else if (SrcSub) {
|
||||||
|
// DstReg will be merged with a sub-register of SrcReg.
|
||||||
|
DstIdx = SrcSub;
|
||||||
|
NewRC = TRI.getMatchingSuperRegClass(SrcRC, DstRC, SrcSub);
|
||||||
|
} else {
|
||||||
|
// This is a straight copy without sub-registers.
|
||||||
NewRC = TRI.getCommonSubClass(DstRC, SrcRC);
|
NewRC = TRI.getCommonSubClass(DstRC, SrcRC);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// The combined constraint may be impossible to satisfy.
|
||||||
if (!NewRC)
|
if (!NewRC)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
// Prefer SrcReg to be a sub-register of DstReg.
|
||||||
|
// FIXME: Coalescer should support subregs symmetrically.
|
||||||
|
if (DstIdx && !SrcIdx) {
|
||||||
|
std::swap(Src, Dst);
|
||||||
|
std::swap(SrcIdx, DstIdx);
|
||||||
|
Flipped = !Flipped;
|
||||||
|
}
|
||||||
|
|
||||||
CrossClass = NewRC != DstRC || NewRC != SrcRC;
|
CrossClass = NewRC != DstRC || NewRC != SrcRC;
|
||||||
}
|
}
|
||||||
// Check our invariants
|
// Check our invariants
|
||||||
@@ -316,14 +316,14 @@ bool CoalescerPair::setRegisters(const MachineInstr *MI) {
|
|||||||
"Cannot have a physical SubIdx");
|
"Cannot have a physical SubIdx");
|
||||||
SrcReg = Src;
|
SrcReg = Src;
|
||||||
DstReg = Dst;
|
DstReg = Dst;
|
||||||
SubIdx = DstSub;
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CoalescerPair::flip() {
|
bool CoalescerPair::flip() {
|
||||||
if (SubIdx || TargetRegisterInfo::isPhysicalRegister(DstReg))
|
if (TargetRegisterInfo::isPhysicalRegister(DstReg))
|
||||||
return false;
|
return false;
|
||||||
std::swap(SrcReg, DstReg);
|
std::swap(SrcReg, DstReg);
|
||||||
|
std::swap(SrcIdx, DstIdx);
|
||||||
Flipped = !Flipped;
|
Flipped = !Flipped;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -347,7 +347,7 @@ bool CoalescerPair::isCoalescable(const MachineInstr *MI) const {
|
|||||||
if (TargetRegisterInfo::isPhysicalRegister(DstReg)) {
|
if (TargetRegisterInfo::isPhysicalRegister(DstReg)) {
|
||||||
if (!TargetRegisterInfo::isPhysicalRegister(Dst))
|
if (!TargetRegisterInfo::isPhysicalRegister(Dst))
|
||||||
return false;
|
return false;
|
||||||
assert(!SubIdx && "Inconsistent CoalescerPair state.");
|
assert(!DstIdx && !SrcIdx && "Inconsistent CoalescerPair state.");
|
||||||
// DstSub could be set for a physreg from INSERT_SUBREG.
|
// DstSub could be set for a physreg from INSERT_SUBREG.
|
||||||
if (DstSub)
|
if (DstSub)
|
||||||
Dst = TRI.getSubReg(Dst, DstSub);
|
Dst = TRI.getSubReg(Dst, DstSub);
|
||||||
@@ -361,7 +361,7 @@ bool CoalescerPair::isCoalescable(const MachineInstr *MI) const {
|
|||||||
if (DstReg != Dst)
|
if (DstReg != Dst)
|
||||||
return false;
|
return false;
|
||||||
// Registers match, do the subregisters line up?
|
// Registers match, do the subregisters line up?
|
||||||
return compose(TRI, SubIdx, SrcSub) == DstSub;
|
return compose(TRI, SrcIdx, SrcSub) == compose(TRI, DstIdx, DstSub);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -529,8 +529,7 @@ bool RegisterCoalescer::adjustCopiesBackFrom(const CoalescerPair &CP,
|
|||||||
// Rewrite the copy. If the copy instruction was killing the destination
|
// Rewrite the copy. If the copy instruction was killing the destination
|
||||||
// register before the merge, find the last use and trim the live range. That
|
// register before the merge, find the last use and trim the live range. That
|
||||||
// will also add the isKill marker.
|
// will also add the isKill marker.
|
||||||
CopyMI->substituteRegister(IntA.reg, IntB.reg, CP.getSubIdx(),
|
CopyMI->substituteRegister(IntA.reg, IntB.reg, CP.getSrcIdx(), *TRI);
|
||||||
*TRI);
|
|
||||||
if (ALR->end == CopyIdx)
|
if (ALR->end == CopyIdx)
|
||||||
LIS->shrinkToUses(&IntA);
|
LIS->shrinkToUses(&IntA);
|
||||||
|
|
||||||
@@ -915,7 +914,7 @@ void RegisterCoalescer::updateRegDefsUses(const CoalescerPair &CP) {
|
|||||||
bool DstIsPhys = CP.isPhys();
|
bool DstIsPhys = CP.isPhys();
|
||||||
unsigned SrcReg = CP.getSrcReg();
|
unsigned SrcReg = CP.getSrcReg();
|
||||||
unsigned DstReg = CP.getDstReg();
|
unsigned DstReg = CP.getDstReg();
|
||||||
unsigned SubIdx = CP.getSubIdx();
|
unsigned SubIdx = CP.getSrcIdx();
|
||||||
|
|
||||||
// Update LiveDebugVariables.
|
// Update LiveDebugVariables.
|
||||||
LDV->renameRegister(SrcReg, DstReg, SubIdx);
|
LDV->renameRegister(SrcReg, DstReg, SubIdx);
|
||||||
@@ -1089,7 +1088,7 @@ bool RegisterCoalescer::joinCopy(MachineInstr *CopyMI, bool &Again) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
DEBUG(dbgs() << "\tConsidering merging " << PrintReg(CP.getSrcReg(), TRI)
|
DEBUG(dbgs() << "\tConsidering merging " << PrintReg(CP.getSrcReg(), TRI)
|
||||||
<< " with " << PrintReg(CP.getDstReg(), TRI, CP.getSubIdx())
|
<< " with " << PrintReg(CP.getDstReg(), TRI, CP.getSrcIdx())
|
||||||
<< "\n");
|
<< "\n");
|
||||||
|
|
||||||
// Enforce policies.
|
// Enforce policies.
|
||||||
@@ -1110,7 +1109,7 @@ bool RegisterCoalescer::joinCopy(MachineInstr *CopyMI, bool &Again) {
|
|||||||
});
|
});
|
||||||
|
|
||||||
// When possible, let DstReg be the larger interval.
|
// When possible, let DstReg be the larger interval.
|
||||||
if (!CP.getSubIdx() && LIS->getInterval(CP.getSrcReg()).ranges.size() >
|
if (!CP.getSrcIdx() && LIS->getInterval(CP.getSrcReg()).ranges.size() >
|
||||||
LIS->getInterval(CP.getDstReg()).ranges.size())
|
LIS->getInterval(CP.getDstReg()).ranges.size())
|
||||||
CP.flip();
|
CP.flip();
|
||||||
}
|
}
|
||||||
|
@@ -36,10 +36,13 @@ namespace llvm {
|
|||||||
/// SrcReg - the virtual register that will be coalesced into dstReg.
|
/// SrcReg - the virtual register that will be coalesced into dstReg.
|
||||||
unsigned SrcReg;
|
unsigned SrcReg;
|
||||||
|
|
||||||
/// subReg_ - The subregister index of srcReg in DstReg. It is possible the
|
/// DstIdx - The sub-register index of the old DstReg in the new coalesced
|
||||||
/// coalesce SrcReg into a subreg of the larger DstReg when DstReg is a
|
/// register.
|
||||||
/// virtual register.
|
unsigned DstIdx;
|
||||||
unsigned SubIdx;
|
|
||||||
|
/// SrcIdx - The sub-register index of the old SrcReg in the new coalesced
|
||||||
|
/// register.
|
||||||
|
unsigned SrcIdx;
|
||||||
|
|
||||||
/// Partial - True when the original copy was a partial subregister copy.
|
/// Partial - True when the original copy was a partial subregister copy.
|
||||||
bool Partial;
|
bool Partial;
|
||||||
@@ -52,12 +55,13 @@ namespace llvm {
|
|||||||
bool Flipped;
|
bool Flipped;
|
||||||
|
|
||||||
/// NewRC - The register class of the coalesced register, or NULL if DstReg
|
/// NewRC - The register class of the coalesced register, or NULL if DstReg
|
||||||
/// is a physreg.
|
/// is a physreg. This register class may be a super-register of both
|
||||||
|
/// SrcReg and DstReg.
|
||||||
const TargetRegisterClass *NewRC;
|
const TargetRegisterClass *NewRC;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
CoalescerPair(const TargetInstrInfo &tii, const TargetRegisterInfo &tri)
|
CoalescerPair(const TargetInstrInfo &tii, const TargetRegisterInfo &tri)
|
||||||
: TII(tii), TRI(tri), DstReg(0), SrcReg(0), SubIdx(0),
|
: TII(tii), TRI(tri), DstReg(0), SrcReg(0), DstIdx(0), SrcIdx(0),
|
||||||
Partial(false), CrossClass(false), Flipped(false), NewRC(0) {}
|
Partial(false), CrossClass(false), Flipped(false), NewRC(0) {}
|
||||||
|
|
||||||
/// setRegisters - set registers to match the copy instruction MI. Return
|
/// setRegisters - set registers to match the copy instruction MI. Return
|
||||||
@@ -94,9 +98,13 @@ namespace llvm {
|
|||||||
/// getSrcReg - Return the virtual register that will be coalesced away.
|
/// getSrcReg - Return the virtual register that will be coalesced away.
|
||||||
unsigned getSrcReg() const { return SrcReg; }
|
unsigned getSrcReg() const { return SrcReg; }
|
||||||
|
|
||||||
/// getSubIdx - Return the subregister index in DstReg that SrcReg will be
|
/// getDstIdx - Return the subregister index that DstReg will be coalesced
|
||||||
/// coalesced into, or 0.
|
/// into, or 0.
|
||||||
unsigned getSubIdx() const { return SubIdx; }
|
unsigned getDstIdx() const { return DstIdx; }
|
||||||
|
|
||||||
|
/// getSrcIdx - Return the subregister index that SrcReg will be coalesced
|
||||||
|
/// into, or 0.
|
||||||
|
unsigned getSrcIdx() const { return SrcIdx; }
|
||||||
|
|
||||||
/// getNewRC - Return the register class of the coalesced register.
|
/// getNewRC - Return the register class of the coalesced register.
|
||||||
const TargetRegisterClass *getNewRC() const { return NewRC; }
|
const TargetRegisterClass *getNewRC() const { return NewRC; }
|
||||||
|
Reference in New Issue
Block a user