forked from OSchip/llvm-project
MachineVerifier: Check that defs/uses are live in subregisters as well.
llvm-svn: 259552
This commit is contained in:
parent
8b175672cb
commit
1377fd6781
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue