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
llvm/lib/CodeGen
|
@ -220,10 +220,19 @@ namespace {
|
||||||
void report_context(SlotIndex Pos) const;
|
void report_context(SlotIndex Pos) const;
|
||||||
void report_context_liverange(const LiveRange &LR) const;
|
void report_context_liverange(const LiveRange &LR) const;
|
||||||
void report_context_regunit(unsigned RegUnit) 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 verifyInlineAsm(const MachineInstr *MI);
|
||||||
|
|
||||||
void checkLiveness(const MachineOperand *MO, unsigned MONum);
|
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 markReachable(const MachineBasicBlock *MBB);
|
||||||
void calcRegsPassed();
|
void calcRegsPassed();
|
||||||
void checkPHIOps(const MachineBasicBlock *MBB);
|
void checkPHIOps(const MachineBasicBlock *MBB);
|
||||||
|
@ -451,7 +460,7 @@ void MachineVerifier::report_context(const LiveRange &LR, unsigned Reg,
|
||||||
report_context_liverange(LR);
|
report_context_liverange(LR);
|
||||||
errs() << "- register: " << PrintReg(Reg, TRI) << '\n';
|
errs() << "- register: " << PrintReg(Reg, TRI) << '\n';
|
||||||
if (LaneMask != 0)
|
if (LaneMask != 0)
|
||||||
errs() << "- lanemask: " << PrintLaneMask(LaneMask) << '\n';
|
report_context_lanemask(LaneMask);
|
||||||
}
|
}
|
||||||
|
|
||||||
void MachineVerifier::report_context(const LiveRange::Segment &S) const {
|
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';
|
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) {
|
void MachineVerifier::markReachable(const MachineBasicBlock *MBB) {
|
||||||
BBInfo &MInfo = MBBInfoMap[MBB];
|
BBInfo &MInfo = MBBInfoMap[MBB];
|
||||||
if (!MInfo.reachable) {
|
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) {
|
void MachineVerifier::checkLiveness(const MachineOperand *MO, unsigned MONum) {
|
||||||
const MachineInstr *MI = MO->getParent();
|
const MachineInstr *MI = MO->getParent();
|
||||||
const unsigned Reg = MO->getReg();
|
const unsigned Reg = MO->getReg();
|
||||||
|
@ -1068,21 +1166,8 @@ void MachineVerifier::checkLiveness(const MachineOperand *MO, unsigned MONum) {
|
||||||
// Check the cached regunit intervals.
|
// Check the cached regunit intervals.
|
||||||
if (TargetRegisterInfo::isPhysicalRegister(Reg) && !isReserved(Reg)) {
|
if (TargetRegisterInfo::isPhysicalRegister(Reg) && !isReserved(Reg)) {
|
||||||
for (MCRegUnitIterator Units(Reg, TRI); Units.isValid(); ++Units) {
|
for (MCRegUnitIterator Units(Reg, TRI); Units.isValid(); ++Units) {
|
||||||
if (const LiveRange *LR = LiveInts->getCachedRegUnit(*Units)) {
|
if (const LiveRange *LR = LiveInts->getCachedRegUnit(*Units))
|
||||||
LiveQueryResult LRQ = LR->Query(UseIdx);
|
checkLivenessAtUse(MO, MONum, UseIdx, *LR, *Units);
|
||||||
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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1090,18 +1175,28 @@ void MachineVerifier::checkLiveness(const MachineOperand *MO, unsigned MONum) {
|
||||||
if (LiveInts->hasInterval(Reg)) {
|
if (LiveInts->hasInterval(Reg)) {
|
||||||
// This is a virtual register interval.
|
// This is a virtual register interval.
|
||||||
const LiveInterval &LI = LiveInts->getInterval(Reg);
|
const LiveInterval &LI = LiveInts->getInterval(Reg);
|
||||||
LiveQueryResult LRQ = LI.Query(UseIdx);
|
checkLivenessAtUse(MO, MONum, UseIdx, LI, Reg);
|
||||||
if (!LRQ.valueIn()) {
|
|
||||||
report("No live segment at use", MO, MONum);
|
if (LI.hasSubRanges() && !MO->isDef()) {
|
||||||
report_context(LI);
|
unsigned SubRegIdx = MO->getSubReg();
|
||||||
report_context(UseIdx);
|
LaneBitmask MOMask = SubRegIdx != 0
|
||||||
}
|
? TRI->getSubRegIndexLaneMask(SubRegIdx)
|
||||||
// Check for extra kill flags.
|
: MRI->getMaxLaneMaskForVReg(Reg);
|
||||||
// Note that we allow missing kill flags for now.
|
LaneBitmask LiveInMask = 0;
|
||||||
if (MO->isKill() && !LRQ.isKill()) {
|
for (const LiveInterval::SubRange &SR : LI.subranges()) {
|
||||||
report("Live range continues after kill flag", MO, MONum);
|
if ((MOMask & SR.LaneMask) == 0)
|
||||||
report_context(LI);
|
continue;
|
||||||
report_context(UseIdx);
|
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 {
|
} else {
|
||||||
report("Virtual register has no live interval", MO, MONum);
|
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);
|
report("Multiple virtual register defs in SSA form", MO, MONum);
|
||||||
|
|
||||||
// Check LiveInts for a live segment, but only for virtual registers.
|
// Check LiveInts for a live segment, but only for virtual registers.
|
||||||
if (LiveInts && TargetRegisterInfo::isVirtualRegister(Reg) &&
|
if (LiveInts && !LiveInts->isNotInMIMap(MI)) {
|
||||||
!LiveInts->isNotInMIMap(MI)) {
|
|
||||||
SlotIndex DefIdx = LiveInts->getInstructionIndex(MI);
|
SlotIndex DefIdx = LiveInts->getInstructionIndex(MI);
|
||||||
DefIdx = DefIdx.getRegSlot(MO->isEarlyClobber());
|
DefIdx = DefIdx.getRegSlot(MO->isEarlyClobber());
|
||||||
if (LiveInts->hasInterval(Reg)) {
|
|
||||||
const LiveInterval &LI = LiveInts->getInterval(Reg);
|
if (TargetRegisterInfo::isVirtualRegister(Reg)) {
|
||||||
if (const VNInfo *VNI = LI.getVNInfoAt(DefIdx)) {
|
if (LiveInts->hasInterval(Reg)) {
|
||||||
assert(VNI && "NULL valno is not allowed");
|
const LiveInterval &LI = LiveInts->getInterval(Reg);
|
||||||
if (VNI->def != DefIdx) {
|
checkLivenessAtDef(MO, MONum, DefIdx, LI, Reg);
|
||||||
report("Inconsistent valno->def", MO, MONum);
|
|
||||||
report_context(LI);
|
if (LI.hasSubRanges()) {
|
||||||
report_context(*VNI);
|
unsigned SubRegIdx = MO->getSubReg();
|
||||||
report_context(DefIdx);
|
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 {
|
} else {
|
||||||
report("No live segment at def", MO, MONum);
|
report("Virtual register has no Live interval", MO, MONum);
|
||||||
report_context(LI);
|
|
||||||
report_context(DefIdx);
|
|
||||||
}
|
}
|
||||||
// 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