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:
Matthias Braun 2015-06-16 18:22:28 +00:00
parent ff881427ec
commit 944aaeb28b

View File

@ -167,6 +167,7 @@ class VirtRegRewriter : public MachineFunctionPass {
void rewrite();
void addMBBLiveIns();
bool readsUndefSubreg(const MachineOperand &MO) const;
public:
static char ID;
VirtRegRewriter() : MachineFunctionPass(ID) {}
@ -288,6 +289,31 @@ void VirtRegRewriter::addMBBLiveIns() {
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() {
bool NoSubRegLiveness = !MRI->subRegLivenessEnabled();
SmallVector<unsigned, 8> SuperDeads;
@ -367,32 +393,51 @@ void VirtRegRewriter::rewrite() {
assert(!MRI->isReserved(PhysReg) && "Reserved register assignment");
// Preserve semantics of sub-register operands.
if (MO.getSubReg()) {
// A virtual register kill refers to the whole register, so we may
// have to add <imp-use,kill> operands for the super-register. A
// partial redef always kills and redefines the super-register.
if (NoSubRegLiveness && MO.readsReg()
&& (MO.isDef() || MO.isKill()))
SuperKills.push_back(PhysReg);
unsigned SubReg = MO.getSubReg();
if (SubReg != 0) {
if (NoSubRegLiveness) {
// A virtual register kill refers to the whole register, so we may
// have to add <imp-use,kill> operands for the super-register. A
// partial redef always kills and redefines the super-register.
if (MO.readsReg() && (MO.isDef() || MO.isKill()))
SuperKills.push_back(PhysReg);
if (MO.isDef()) {
// 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.
MO.setIsUndef(false);
// Also add implicit defs for the super-register.
if (NoSubRegLiveness) {
if (MO.isDef()) {
// Also add implicit defs for the super-register.
if (MO.isDead())
SuperDeads.push_back(PhysReg);
else
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 = TRI->getSubReg(PhysReg, MO.getSubReg());
PhysReg = TRI->getSubReg(PhysReg, SubReg);
assert(PhysReg && "Invalid SubReg for physical register");
MO.setSubReg(0);
}