mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2024-12-13 04:30:23 +00:00
VirtRegMap: Add undef flag when reading undefined subregisters.
While completely undefined registers are easy to catch and get their <undef> flag early in ProcessImplicitDefs/RegisterCoalescer reading from a partially defined register where just the subreg happens to be undefined is harder to catch so we only add the undef flag in the virtual register rewriting step. No testcase as I cannot reproduce the problem on any of the in-tree targets at the moment. This fixes rdar://21387089 Differential Revision: http://reviews.llvm.org/D10470 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@239838 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
ff881427ec
commit
944aaeb28b
@ -167,6 +167,7 @@ class VirtRegRewriter : public MachineFunctionPass {
|
|||||||
|
|
||||||
void rewrite();
|
void rewrite();
|
||||||
void addMBBLiveIns();
|
void addMBBLiveIns();
|
||||||
|
bool readsUndefSubreg(const MachineOperand &MO) const;
|
||||||
public:
|
public:
|
||||||
static char ID;
|
static char ID;
|
||||||
VirtRegRewriter() : MachineFunctionPass(ID) {}
|
VirtRegRewriter() : MachineFunctionPass(ID) {}
|
||||||
@ -288,6 +289,31 @@ void VirtRegRewriter::addMBBLiveIns() {
|
|||||||
MBB.sortUniqueLiveIns();
|
MBB.sortUniqueLiveIns();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Returns true if the given machine operand \p MO only reads undefined lanes.
|
||||||
|
/// The function only works for use operands with a subregister set.
|
||||||
|
bool VirtRegRewriter::readsUndefSubreg(const MachineOperand &MO) const {
|
||||||
|
// Shortcut if the operand is already marked undef.
|
||||||
|
if (MO.isUndef())
|
||||||
|
return true;
|
||||||
|
|
||||||
|
unsigned Reg = MO.getReg();
|
||||||
|
const LiveInterval &LI = LIS->getInterval(Reg);
|
||||||
|
const MachineInstr &MI = *MO.getParent();
|
||||||
|
SlotIndex BaseIndex = LIS->getInstructionIndex(&MI);
|
||||||
|
// This code is only meant to handle reading undefined subregisters which
|
||||||
|
// we couldn't properly detect before.
|
||||||
|
assert(LI.liveAt(BaseIndex) &&
|
||||||
|
"Reads of completely dead register should be marked undef already");
|
||||||
|
unsigned SubRegIdx = MO.getSubReg();
|
||||||
|
unsigned UseMask = TRI->getSubRegIndexLaneMask(SubRegIdx);
|
||||||
|
// See if any of the relevant subregister liveranges is defined at this point.
|
||||||
|
for (const LiveInterval::SubRange &SR : LI.subranges()) {
|
||||||
|
if ((SR.LaneMask & UseMask) != 0 && SR.liveAt(BaseIndex))
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
void VirtRegRewriter::rewrite() {
|
void VirtRegRewriter::rewrite() {
|
||||||
bool NoSubRegLiveness = !MRI->subRegLivenessEnabled();
|
bool NoSubRegLiveness = !MRI->subRegLivenessEnabled();
|
||||||
SmallVector<unsigned, 8> SuperDeads;
|
SmallVector<unsigned, 8> SuperDeads;
|
||||||
@ -367,32 +393,51 @@ void VirtRegRewriter::rewrite() {
|
|||||||
assert(!MRI->isReserved(PhysReg) && "Reserved register assignment");
|
assert(!MRI->isReserved(PhysReg) && "Reserved register assignment");
|
||||||
|
|
||||||
// Preserve semantics of sub-register operands.
|
// Preserve semantics of sub-register operands.
|
||||||
if (MO.getSubReg()) {
|
unsigned SubReg = MO.getSubReg();
|
||||||
// A virtual register kill refers to the whole register, so we may
|
if (SubReg != 0) {
|
||||||
// have to add <imp-use,kill> operands for the super-register. A
|
if (NoSubRegLiveness) {
|
||||||
// partial redef always kills and redefines the super-register.
|
// A virtual register kill refers to the whole register, so we may
|
||||||
if (NoSubRegLiveness && MO.readsReg()
|
// have to add <imp-use,kill> operands for the super-register. A
|
||||||
&& (MO.isDef() || MO.isKill()))
|
// partial redef always kills and redefines the super-register.
|
||||||
SuperKills.push_back(PhysReg);
|
if (MO.readsReg() && (MO.isDef() || MO.isKill()))
|
||||||
|
SuperKills.push_back(PhysReg);
|
||||||
|
|
||||||
if (MO.isDef()) {
|
if (MO.isDef()) {
|
||||||
// The <def,undef> flag only makes sense for sub-register defs, and
|
// Also add implicit defs for the super-register.
|
||||||
// we are substituting a full physreg. An <imp-use,kill> operand
|
|
||||||
// from the SuperKills list will represent the partial read of the
|
|
||||||
// super-register.
|
|
||||||
MO.setIsUndef(false);
|
|
||||||
|
|
||||||
// Also add implicit defs for the super-register.
|
|
||||||
if (NoSubRegLiveness) {
|
|
||||||
if (MO.isDead())
|
if (MO.isDead())
|
||||||
SuperDeads.push_back(PhysReg);
|
SuperDeads.push_back(PhysReg);
|
||||||
else
|
else
|
||||||
SuperDefs.push_back(PhysReg);
|
SuperDefs.push_back(PhysReg);
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
if (MO.isUse()) {
|
||||||
|
if (readsUndefSubreg(MO))
|
||||||
|
// We need to add an <undef> flag if the subregister is
|
||||||
|
// completely undefined (and we are not adding super-register
|
||||||
|
// defs).
|
||||||
|
MO.setIsUndef(true);
|
||||||
|
} else if (!MO.isDead()) {
|
||||||
|
assert(MO.isDef());
|
||||||
|
// Things get tricky when we ran out of lane mask bits and
|
||||||
|
// merged multiple lanes into the overflow bit: In this case
|
||||||
|
// our subregister liveness tracking isn't precise and we can't
|
||||||
|
// know what subregister parts are undefined, fall back to the
|
||||||
|
// implicit super-register def then.
|
||||||
|
unsigned LaneMask = TRI->getSubRegIndexLaneMask(SubReg);
|
||||||
|
if (TargetRegisterInfo::isImpreciseLaneMask(LaneMask))
|
||||||
|
SuperDefs.push_back(PhysReg);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// The <def,undef> flag only makes sense for sub-register defs, and
|
||||||
|
// we are substituting a full physreg. An <imp-use,kill> operand
|
||||||
|
// from the SuperKills list will represent the partial read of the
|
||||||
|
// super-register.
|
||||||
|
if (MO.isDef())
|
||||||
|
MO.setIsUndef(false);
|
||||||
|
|
||||||
// PhysReg operands cannot have subregister indexes.
|
// PhysReg operands cannot have subregister indexes.
|
||||||
PhysReg = TRI->getSubReg(PhysReg, MO.getSubReg());
|
PhysReg = TRI->getSubReg(PhysReg, SubReg);
|
||||||
assert(PhysReg && "Invalid SubReg for physical register");
|
assert(PhysReg && "Invalid SubReg for physical register");
|
||||||
MO.setSubReg(0);
|
MO.setSubReg(0);
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user