MachineVerifier: Check that defs/uses are live in subregisters as well.

llvm-svn: 259552
This commit is contained in:
Matthias Braun 2016-02-02 20:04:51 +00:00
parent 8b175672cb
commit 1377fd6781
1 changed files with 141 additions and 52 deletions

View File

@ -220,10 +220,19 @@ namespace {
void report_context(SlotIndex Pos) const;
void report_context_liverange(const LiveRange &LR) const;
void report_context_regunit(unsigned RegUnit) const;
void report_context_lanemask(LaneBitmask LaneMask) const;
void report_context_vreg_regunit(unsigned VRegOrRegUnit) const;
void verifyInlineAsm(const MachineInstr *MI);
void checkLiveness(const MachineOperand *MO, unsigned MONum);
void checkLivenessAtUse(const MachineOperand *MO, unsigned MONum,
SlotIndex UseIdx, const LiveRange &LR, unsigned Reg,
LaneBitmask LaneMask = 0);
void checkLivenessAtDef(const MachineOperand *MO, unsigned MONum,
SlotIndex DefIdx, const LiveRange &LR, unsigned Reg,
LaneBitmask LaneMask = 0);
void markReachable(const MachineBasicBlock *MBB);
void calcRegsPassed();
void checkPHIOps(const MachineBasicBlock *MBB);
@ -451,7 +460,7 @@ void MachineVerifier::report_context(const LiveRange &LR, unsigned Reg,
report_context_liverange(LR);
errs() << "- register: " << PrintReg(Reg, TRI) << '\n';
if (LaneMask != 0)
errs() << "- lanemask: " << PrintLaneMask(LaneMask) << '\n';
report_context_lanemask(LaneMask);
}
void MachineVerifier::report_context(const LiveRange::Segment &S) const {
@ -470,6 +479,18 @@ void MachineVerifier::report_context_regunit(unsigned RegUnit) const {
errs() << "- regunit: " << PrintRegUnit(RegUnit, TRI) << '\n';
}
void MachineVerifier::report_context_vreg_regunit(unsigned VRegOrUnit) const {
if (TargetRegisterInfo::isVirtualRegister(VRegOrUnit)) {
errs() << "- v. register: " << PrintReg(VRegOrUnit, TRI) << '\n';
} else {
errs() << "- regunit: " << PrintRegUnit(VRegOrUnit, TRI) << '\n';
}
}
void MachineVerifier::report_context_lanemask(LaneBitmask LaneMask) const {
errs() << "- lanemask: " << PrintLaneMask(LaneMask) << '\n';
}
void MachineVerifier::markReachable(const MachineBasicBlock *MBB) {
BBInfo &MInfo = MBBInfoMap[MBB];
if (!MInfo.reachable) {
@ -1043,6 +1064,83 @@ MachineVerifier::visitMachineOperand(const MachineOperand *MO, unsigned MONum) {
}
}
void MachineVerifier::checkLivenessAtUse(const MachineOperand *MO,
unsigned MONum, SlotIndex UseIdx, const LiveRange &LR, unsigned VRegOrUnit,
LaneBitmask LaneMask) {
LiveQueryResult LRQ = LR.Query(UseIdx);
// Check if we have a segment at the use, note however that we only need one
// live subregister range, the others may be dead.
if (!LRQ.valueIn() && LaneMask == 0) {
report("No live segment at use", MO, MONum);
report_context_liverange(LR);
report_context_vreg_regunit(VRegOrUnit);
report_context(UseIdx);
}
if (MO->isKill() && !LRQ.isKill()) {
report("Live range continues after kill flag", MO, MONum);
report_context_liverange(LR);
report_context_vreg_regunit(VRegOrUnit);
if (LaneMask != 0)
report_context_lanemask(LaneMask);
report_context(UseIdx);
}
}
void MachineVerifier::checkLivenessAtDef(const MachineOperand *MO,
unsigned MONum, SlotIndex DefIdx, const LiveRange &LR, unsigned VRegOrUnit,
LaneBitmask LaneMask) {
if (const VNInfo *VNI = LR.getVNInfoAt(DefIdx)) {
assert(VNI && "NULL valno is not allowed");
if (VNI->def != DefIdx) {
report("Inconsistent valno->def", MO, MONum);
report_context_liverange(LR);
report_context_vreg_regunit(VRegOrUnit);
if (LaneMask != 0)
report_context_lanemask(LaneMask);
report_context(*VNI);
report_context(DefIdx);
}
} else {
report("No live segment at def", MO, MONum);
report_context_liverange(LR);
report_context_vreg_regunit(VRegOrUnit);
if (LaneMask != 0)
report_context_lanemask(LaneMask);
report_context(DefIdx);
}
// Check that, if the dead def flag is present, LiveInts agree.
if (MO->isDead()) {
LiveQueryResult LRQ = LR.Query(DefIdx);
if (!LRQ.isDeadDef()) {
// In case of physregs we can have a non-dead definition on another
// operand.
bool otherDef = false;
if (!TargetRegisterInfo::isVirtualRegister(VRegOrUnit)) {
const MachineInstr &MI = *MO->getParent();
for (const MachineOperand &MO : MI.operands()) {
if (!MO.isReg() || !MO.isDef() || MO.isDead())
continue;
unsigned Reg = MO.getReg();
for (MCRegUnitIterator Units(Reg, TRI); Units.isValid(); ++Units) {
if (*Units == VRegOrUnit) {
otherDef = true;
break;
}
}
}
}
if (!otherDef) {
report("Live range continues after dead def flag", MO, MONum);
report_context_liverange(LR);
report_context_vreg_regunit(VRegOrUnit);
if (LaneMask != 0)
report_context_lanemask(LaneMask);
}
}
}
}
void MachineVerifier::checkLiveness(const MachineOperand *MO, unsigned MONum) {
const MachineInstr *MI = MO->getParent();
const unsigned Reg = MO->getReg();
@ -1068,21 +1166,8 @@ void MachineVerifier::checkLiveness(const MachineOperand *MO, unsigned MONum) {
// Check the cached regunit intervals.
if (TargetRegisterInfo::isPhysicalRegister(Reg) && !isReserved(Reg)) {
for (MCRegUnitIterator Units(Reg, TRI); Units.isValid(); ++Units) {
if (const LiveRange *LR = LiveInts->getCachedRegUnit(*Units)) {
LiveQueryResult LRQ = LR->Query(UseIdx);
if (!LRQ.valueIn()) {
report("No live segment at use", MO, MONum);
report_context_liverange(*LR);
report_context_regunit(*Units);
report_context(UseIdx);
}
if (MO->isKill() && !LRQ.isKill()) {
report("Live range continues after kill flag", MO, MONum);
report_context_liverange(*LR);
report_context_regunit(*Units);
report_context(UseIdx);
}
}
if (const LiveRange *LR = LiveInts->getCachedRegUnit(*Units))
checkLivenessAtUse(MO, MONum, UseIdx, *LR, *Units);
}
}
@ -1090,18 +1175,28 @@ void MachineVerifier::checkLiveness(const MachineOperand *MO, unsigned MONum) {
if (LiveInts->hasInterval(Reg)) {
// This is a virtual register interval.
const LiveInterval &LI = LiveInts->getInterval(Reg);
LiveQueryResult LRQ = LI.Query(UseIdx);
if (!LRQ.valueIn()) {
report("No live segment at use", MO, MONum);
report_context(LI);
report_context(UseIdx);
}
// Check for extra kill flags.
// Note that we allow missing kill flags for now.
if (MO->isKill() && !LRQ.isKill()) {
report("Live range continues after kill flag", MO, MONum);
report_context(LI);
report_context(UseIdx);
checkLivenessAtUse(MO, MONum, UseIdx, LI, Reg);
if (LI.hasSubRanges() && !MO->isDef()) {
unsigned SubRegIdx = MO->getSubReg();
LaneBitmask MOMask = SubRegIdx != 0
? TRI->getSubRegIndexLaneMask(SubRegIdx)
: MRI->getMaxLaneMaskForVReg(Reg);
LaneBitmask LiveInMask = 0;
for (const LiveInterval::SubRange &SR : LI.subranges()) {
if ((MOMask & SR.LaneMask) == 0)
continue;
checkLivenessAtUse(MO, MONum, UseIdx, SR, Reg, SR.LaneMask);
LiveQueryResult LRQ = SR.Query(UseIdx);
if (LRQ.valueIn())
LiveInMask |= SR.LaneMask;
}
// At least parts of the register has to be live at the use.
if ((LiveInMask & MOMask) == 0) {
report("No live subrange at use", MO, MONum);
report_context(LI);
report_context(UseIdx);
}
}
} else {
report("Virtual register has no live interval", MO, MONum);
@ -1174,35 +1269,29 @@ void MachineVerifier::checkLiveness(const MachineOperand *MO, unsigned MONum) {
report("Multiple virtual register defs in SSA form", MO, MONum);
// Check LiveInts for a live segment, but only for virtual registers.
if (LiveInts && TargetRegisterInfo::isVirtualRegister(Reg) &&
!LiveInts->isNotInMIMap(MI)) {
if (LiveInts && !LiveInts->isNotInMIMap(MI)) {
SlotIndex DefIdx = LiveInts->getInstructionIndex(MI);
DefIdx = DefIdx.getRegSlot(MO->isEarlyClobber());
if (LiveInts->hasInterval(Reg)) {
const LiveInterval &LI = LiveInts->getInterval(Reg);
if (const VNInfo *VNI = LI.getVNInfoAt(DefIdx)) {
assert(VNI && "NULL valno is not allowed");
if (VNI->def != DefIdx) {
report("Inconsistent valno->def", MO, MONum);
report_context(LI);
report_context(*VNI);
report_context(DefIdx);
if (TargetRegisterInfo::isVirtualRegister(Reg)) {
if (LiveInts->hasInterval(Reg)) {
const LiveInterval &LI = LiveInts->getInterval(Reg);
checkLivenessAtDef(MO, MONum, DefIdx, LI, Reg);
if (LI.hasSubRanges()) {
unsigned SubRegIdx = MO->getSubReg();
LaneBitmask MOMask = SubRegIdx != 0
? TRI->getSubRegIndexLaneMask(SubRegIdx)
: MRI->getMaxLaneMaskForVReg(Reg);
for (const LiveInterval::SubRange &SR : LI.subranges()) {
if ((SR.LaneMask & MOMask) == 0)
continue;
checkLivenessAtDef(MO, MONum, DefIdx, SR, Reg, SR.LaneMask);
}
}
} else {
report("No live segment at def", MO, MONum);
report_context(LI);
report_context(DefIdx);
report("Virtual register has no Live interval", MO, MONum);
}
// Check that, if the dead def flag is present, LiveInts agree.
if (MO->isDead()) {
LiveQueryResult LRQ = LI.Query(DefIdx);
if (!LRQ.isDeadDef()) {
report("Live range continues after dead def flag", MO, MONum);
report_context(LI);
}
}
} else {
report("Virtual register has no Live interval", MO, MONum);
}
}
}