aboutsummaryrefslogtreecommitdiff
path: root/contrib/llvm/lib/CodeGen/MachineVerifier.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/llvm/lib/CodeGen/MachineVerifier.cpp')
-rw-r--r--contrib/llvm/lib/CodeGen/MachineVerifier.cpp341
1 files changed, 256 insertions, 85 deletions
diff --git a/contrib/llvm/lib/CodeGen/MachineVerifier.cpp b/contrib/llvm/lib/CodeGen/MachineVerifier.cpp
index 428295ec2cc6..a70adb050455 100644
--- a/contrib/llvm/lib/CodeGen/MachineVerifier.cpp
+++ b/contrib/llvm/lib/CodeGen/MachineVerifier.cpp
@@ -58,7 +58,7 @@ namespace {
Banner(b)
{}
- bool runOnMachineFunction(MachineFunction &MF);
+ unsigned verify(MachineFunction &MF);
Pass *const PASS;
const char *Banner;
@@ -217,10 +217,22 @@ namespace {
LaneBitmask LaneMask) const;
void report_context(const LiveRange::Segment &S) const;
void report_context(const VNInfo &VNI) const;
+ void report_context(SlotIndex Pos) const;
+ void report_context_liverange(const LiveRange &LR) const;
+ void report_context_lanemask(LaneBitmask LaneMask) const;
+ void report_context_vreg(unsigned VReg) 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);
@@ -239,6 +251,7 @@ namespace {
void verifyStackFrame();
void verifySlotIndexes() const;
+ void verifyProperties(const MachineFunction &MF);
};
struct MachineVerifierPass : public MachineFunctionPass {
@@ -256,7 +269,9 @@ namespace {
}
bool runOnMachineFunction(MachineFunction &MF) override {
- MF.verify(this, Banner.c_str());
+ unsigned FoundErrors = MachineVerifier(this, Banner.c_str()).verify(MF);
+ if (FoundErrors)
+ report_fatal_error("Found "+Twine(FoundErrors)+" machine code errors.");
return false;
}
};
@@ -271,9 +286,13 @@ FunctionPass *llvm::createMachineVerifierPass(const std::string &Banner) {
return new MachineVerifierPass(Banner);
}
-void MachineFunction::verify(Pass *p, const char *Banner) const {
- MachineVerifier(p, Banner)
- .runOnMachineFunction(const_cast<MachineFunction&>(*this));
+bool MachineFunction::verify(Pass *p, const char *Banner, bool AbortOnErrors)
+ const {
+ MachineFunction &MF = const_cast<MachineFunction&>(*this);
+ unsigned FoundErrors = MachineVerifier(p, Banner).verify(MF);
+ if (AbortOnErrors && FoundErrors)
+ report_fatal_error("Found "+Twine(FoundErrors)+" machine code errors.");
+ return FoundErrors == 0;
}
void MachineVerifier::verifySlotIndexes() const {
@@ -289,7 +308,20 @@ void MachineVerifier::verifySlotIndexes() const {
}
}
-bool MachineVerifier::runOnMachineFunction(MachineFunction &MF) {
+void MachineVerifier::verifyProperties(const MachineFunction &MF) {
+ // If a pass has introduced virtual registers without clearing the
+ // AllVRegsAllocated property (or set it without allocating the vregs)
+ // then report an error.
+ if (MF.getProperties().hasProperty(
+ MachineFunctionProperties::Property::AllVRegsAllocated) &&
+ MRI->getNumVirtRegs()) {
+ report(
+ "Function has AllVRegsAllocated property but there are VReg operands",
+ &MF);
+ }
+}
+
+unsigned MachineVerifier::verify(MachineFunction &MF) {
foundErrors = 0;
this->MF = &MF;
@@ -313,6 +345,8 @@ bool MachineVerifier::runOnMachineFunction(MachineFunction &MF) {
verifySlotIndexes();
+ verifyProperties(MF);
+
visitMachineFunctionBefore();
for (MachineFunction::const_iterator MFI = MF.begin(), MFE = MF.end();
MFI!=MFE; ++MFI) {
@@ -374,9 +408,6 @@ bool MachineVerifier::runOnMachineFunction(MachineFunction &MF) {
}
visitMachineFunctionAfter();
- if (foundErrors)
- report_fatal_error("Found "+Twine(foundErrors)+" machine code errors.");
-
// Clean up.
regsLive.clear();
regsDefined.clear();
@@ -386,7 +417,7 @@ bool MachineVerifier::runOnMachineFunction(MachineFunction &MF) {
regsLiveInButUnused.clear();
MBBInfoMap.clear();
- return false; // no changes
+ return foundErrors;
}
void MachineVerifier::report(const char *msg, const MachineFunction *MF) {
@@ -420,8 +451,8 @@ void MachineVerifier::report(const char *msg, const MachineInstr *MI) {
assert(MI);
report(msg, MI->getParent());
errs() << "- instruction: ";
- if (Indexes && Indexes->hasIndex(MI))
- errs() << Indexes->getInstructionIndex(MI) << '\t';
+ if (Indexes && Indexes->hasIndex(*MI))
+ errs() << Indexes->getInstructionIndex(*MI) << '\t';
MI->print(errs(), /*SkipOpers=*/true);
errs() << '\n';
}
@@ -435,16 +466,20 @@ void MachineVerifier::report(const char *msg,
errs() << "\n";
}
+void MachineVerifier::report_context(SlotIndex Pos) const {
+ errs() << "- at: " << Pos << '\n';
+}
+
void MachineVerifier::report_context(const LiveInterval &LI) const {
errs() << "- interval: " << LI << '\n';
}
void MachineVerifier::report_context(const LiveRange &LR, unsigned Reg,
LaneBitmask LaneMask) const {
+ report_context_liverange(LR);
errs() << "- register: " << PrintReg(Reg, TRI) << '\n';
if (LaneMask != 0)
- errs() << "- lanemask: " << PrintLaneMask(LaneMask) << '\n';
- errs() << "- liverange: " << LR << '\n';
+ report_context_lanemask(LaneMask);
}
void MachineVerifier::report_context(const LiveRange::Segment &S) const {
@@ -455,6 +490,26 @@ void MachineVerifier::report_context(const VNInfo &VNI) const {
errs() << "- ValNo: " << VNI.id << " (def " << VNI.def << ")\n";
}
+void MachineVerifier::report_context_liverange(const LiveRange &LR) const {
+ errs() << "- liverange: " << LR << '\n';
+}
+
+void MachineVerifier::report_context_vreg(unsigned VReg) const {
+ errs() << "- v. register: " << PrintReg(VReg, TRI) << '\n';
+}
+
+void MachineVerifier::report_context_vreg_regunit(unsigned VRegOrUnit) const {
+ if (TargetRegisterInfo::isVirtualRegister(VRegOrUnit)) {
+ report_context_vreg(VRegOrUnit);
+ } 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) {
@@ -521,7 +576,7 @@ MachineVerifier::visitMachineBasicBlockBefore(const MachineBasicBlock *MBB) {
// it is an entry block or landing pad.
for (const auto &LI : MBB->liveins()) {
if (isAllocatable(LI.PhysReg) && !MBB->isEHPad() &&
- MBB != MBB->getParent()->begin()) {
+ MBB->getIterator() != MBB->getParent()->begin()) {
report("MBB has allocable live-in, but isn't entry or landing-pad.", MBB);
}
}
@@ -567,8 +622,8 @@ MachineVerifier::visitMachineBasicBlockBefore(const MachineBasicBlock *MBB) {
// Call AnalyzeBranch. If it succeeds, there several more conditions to check.
MachineBasicBlock *TBB = nullptr, *FBB = nullptr;
SmallVector<MachineOperand, 4> Cond;
- if (!TII->AnalyzeBranch(*const_cast<MachineBasicBlock *>(MBB),
- TBB, FBB, Cond)) {
+ if (!TII->analyzeBranch(*const_cast<MachineBasicBlock *>(MBB), TBB, FBB,
+ Cond)) {
// Ok, AnalyzeBranch thinks it knows what's going on with this block. Let's
// check whether its answers match up with reality.
if (!TBB && !FBB) {
@@ -591,7 +646,7 @@ MachineVerifier::visitMachineBasicBlockBefore(const MachineBasicBlock *MBB) {
"differs from its CFG successor!", MBB);
}
if (!MBB->empty() && MBB->back().isBarrier() &&
- !TII->isPredicated(&MBB->back())) {
+ !TII->isPredicated(MBB->back())) {
report("MBB exits via unconditional fall-through but ends with a "
"barrier instruction!", MBB);
}
@@ -721,8 +776,8 @@ MachineVerifier::visitMachineBasicBlockBefore(const MachineBasicBlock *MBB) {
// This function gets called for all bundle headers, including normal
// stand-alone unbundled instructions.
void MachineVerifier::visitMachineBundleBefore(const MachineInstr *MI) {
- if (Indexes && Indexes->hasIndex(MI)) {
- SlotIndex idx = Indexes->getInstructionIndex(MI);
+ if (Indexes && Indexes->hasIndex(*MI)) {
+ SlotIndex idx = Indexes->getInstructionIndex(*MI);
if (!(idx > lastIndex)) {
report("Instruction index out of order", MI);
errs() << "Last instruction was at " << lastIndex << '\n';
@@ -733,7 +788,7 @@ void MachineVerifier::visitMachineBundleBefore(const MachineInstr *MI) {
// Ensure non-terminators don't follow terminators.
// Ignore predicated terminators formed by if conversion.
// FIXME: If conversion shouldn't need to violate this rule.
- if (MI->isTerminator() && !TII->isPredicated(MI)) {
+ if (MI->isTerminator() && !TII->isPredicated(*MI)) {
if (!FirstTerminator)
FirstTerminator = MI;
} else if (FirstTerminator) {
@@ -755,8 +810,9 @@ void MachineVerifier::verifyInlineAsm(const MachineInstr *MI) {
if (!MI->getOperand(1).isImm())
report("Asm flags must be an immediate", MI);
// Allowed flags are Extra_HasSideEffects = 1, Extra_IsAlignStack = 2,
- // Extra_AsmDialect = 4, Extra_MayLoad = 8, and Extra_MayStore = 16.
- if (!isUInt<5>(MI->getOperand(1).getImm()))
+ // Extra_AsmDialect = 4, Extra_MayLoad = 8, and Extra_MayStore = 16,
+ // and Extra_IsConvergent = 32.
+ if (!isUInt<6>(MI->getOperand(1).getImm()))
report("Unknown asm flags", &MI->getOperand(1), 1);
static_assert(InlineAsm::MIOp_FirstOperand == 2, "Asm format changed");
@@ -810,7 +866,7 @@ void MachineVerifier::visitMachineInstrBefore(const MachineInstr *MI) {
// Debug values must not have a slot index.
// Other instructions must have one, unless they are inside a bundle.
if (LiveInts) {
- bool mapped = !LiveInts->isNotInMIMap(MI);
+ bool mapped = !LiveInts->isNotInMIMap(*MI);
if (MI->isDebugValue()) {
if (mapped)
report("Debug instruction has a slot index", MI);
@@ -824,7 +880,7 @@ void MachineVerifier::visitMachineInstrBefore(const MachineInstr *MI) {
}
StringRef ErrorInfo;
- if (!TII->verifyInstruction(MI, ErrorInfo))
+ if (!TII->verifyInstruction(*MI, ErrorInfo))
report(ErrorInfo.data(), MI);
}
@@ -929,7 +985,30 @@ MachineVerifier::visitMachineOperand(const MachineOperand *MO, unsigned MONum) {
}
} else {
// Virtual register.
- const TargetRegisterClass *RC = MRI->getRegClass(Reg);
+ const TargetRegisterClass *RC = MRI->getRegClassOrNull(Reg);
+ if (!RC) {
+ // This is a generic virtual register.
+ // It must have a size and it must not have a SubIdx.
+ unsigned Size = MRI->getSize(Reg);
+ if (!Size) {
+ report("Generic virtual register must have a size", MO, MONum);
+ return;
+ }
+ // Make sure the register fits into its register bank if any.
+ const RegisterBank *RegBank = MRI->getRegBankOrNull(Reg);
+ if (RegBank && RegBank->getSize() < Size) {
+ report("Register bank is too small for virtual register", MO,
+ MONum);
+ errs() << "Register bank " << RegBank->getName() << " too small("
+ << RegBank->getSize() << ") to fit " << Size << "-bits\n";
+ return;
+ }
+ if (SubIdx) {
+ report("Generic virtual register does not subregister index", MO, MONum);
+ return;
+ }
+ break;
+ }
if (SubIdx) {
const TargetRegisterClass *SRC =
TRI->getSubClassWithSubReg(RC, SubIdx);
@@ -984,10 +1063,10 @@ MachineVerifier::visitMachineOperand(const MachineOperand *MO, unsigned MONum) {
case MachineOperand::MO_FrameIndex:
if (LiveStks && LiveStks->hasInterval(MO->getIndex()) &&
- LiveInts && !LiveInts->isNotInMIMap(MI)) {
+ LiveInts && !LiveInts->isNotInMIMap(*MI)) {
int FI = MO->getIndex();
LiveInterval &LI = LiveStks->getInterval(FI);
- SlotIndex Idx = LiveInts->getInstructionIndex(MI);
+ SlotIndex Idx = LiveInts->getInstructionIndex(*MI);
bool stores = MI->mayStore();
bool loads = MI->mayLoad();
@@ -1028,6 +1107,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();
@@ -1048,23 +1204,13 @@ void MachineVerifier::checkLiveness(const MachineOperand *MO, unsigned MONum) {
}
// Check LiveInts liveness and kill.
- if (LiveInts && !LiveInts->isNotInMIMap(MI)) {
- SlotIndex UseIdx = LiveInts->getInstructionIndex(MI);
+ if (LiveInts && !LiveInts->isNotInMIMap(*MI)) {
+ SlotIndex UseIdx = LiveInts->getInstructionIndex(*MI);
// 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);
- errs() << UseIdx << " is not live in " << PrintRegUnit(*Units, TRI)
- << ' ' << *LR << '\n';
- }
- if (MO->isKill() && !LRQ.isKill()) {
- report("Live range continues after kill flag", MO, MONum);
- errs() << PrintRegUnit(*Units, TRI) << ' ' << *LR << '\n';
- }
- }
+ if (const LiveRange *LR = LiveInts->getCachedRegUnit(*Units))
+ checkLivenessAtUse(MO, MONum, UseIdx, *LR, *Units);
}
}
@@ -1072,16 +1218,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);
- errs() << UseIdx << " is not live in " << LI << '\n';
- }
- // 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);
- errs() << "Live range: " << LI << '\n';
+ 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);
@@ -1154,33 +1312,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)) {
- SlotIndex DefIdx = LiveInts->getInstructionIndex(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);
- errs() << "Valno " << VNI->id << " is not defined at "
- << DefIdx << " in " << LI << '\n';
+
+ 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);
- errs() << DefIdx << " is not live in " << LI << '\n';
- }
- // 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);
- errs() << "Live range: " << LI << '\n';
- }
+ report("Virtual register has no Live interval", MO, MONum);
}
- } else {
- report("Virtual register has no Live interval", MO, MONum);
}
}
}
@@ -1360,9 +1514,10 @@ void MachineVerifier::visitMachineFunctionAfter() {
BBInfo &MInfo = MBBInfoMap[&MF->front()];
for (RegSet::iterator
I = MInfo.vregsRequired.begin(), E = MInfo.vregsRequired.end(); I != E;
- ++I)
- report("Virtual register def doesn't dominate all uses.",
- MRI->getVRegDef(*I));
+ ++I) {
+ report("Virtual register defs don't dominate all uses.", MF);
+ report_context_vreg(*I);
+ }
}
if (LiveVars)
@@ -1474,7 +1629,7 @@ void MachineVerifier::verifyLiveRangeValue(const LiveRange &LR,
if (Reg != 0) {
bool hasDef = false;
bool isEarlyClobber = false;
- for (ConstMIBundleOperands MOI(MI); MOI.isValid(); ++MOI) {
+ for (ConstMIBundleOperands MOI(*MI); MOI.isValid(); ++MOI) {
if (!MOI->isReg() || !MOI->isDef())
continue;
if (TargetRegisterInfo::isVirtualRegister(Reg)) {
@@ -1613,18 +1768,33 @@ void MachineVerifier::verifyLiveRangeSegment(const LiveRange &LR,
// use, or a dead flag on a def.
bool hasRead = false;
bool hasSubRegDef = false;
- for (ConstMIBundleOperands MOI(MI); MOI.isValid(); ++MOI) {
+ bool hasDeadDef = false;
+ for (ConstMIBundleOperands MOI(*MI); MOI.isValid(); ++MOI) {
if (!MOI->isReg() || MOI->getReg() != Reg)
continue;
if (LaneMask != 0 &&
(LaneMask & TRI->getSubRegIndexLaneMask(MOI->getSubReg())) == 0)
continue;
- if (MOI->isDef() && MOI->getSubReg() != 0)
- hasSubRegDef = true;
+ if (MOI->isDef()) {
+ if (MOI->getSubReg() != 0)
+ hasSubRegDef = true;
+ if (MOI->isDead())
+ hasDeadDef = true;
+ }
if (MOI->readsReg())
hasRead = true;
}
- if (!S.end.isDead()) {
+ if (S.end.isDead()) {
+ // Make sure that the corresponding machine operand for a "dead" live
+ // range has the dead flag. We cannot perform this check for subregister
+ // liveranges as partially dead values are allowed.
+ if (LaneMask == 0 && !hasDeadDef) {
+ report("Instruction ending live segment on dead slot has no dead flag",
+ MI);
+ report_context(LR, Reg, LaneMask);
+ report_context(S);
+ }
+ } else {
if (!hasRead) {
// When tracking subregister liveness, the main range must start new
// values on partial register writes, even if there is no read.
@@ -1670,8 +1840,9 @@ void MachineVerifier::verifyLiveRangeSegment(const LiveRange &LR,
SlotIndex PEnd = LiveInts->getMBBEndIdx(*PI);
const VNInfo *PVNI = LR.getVNInfoBefore(PEnd);
- // All predecessors must have a live-out value.
- if (!PVNI) {
+ // All predecessors must have a live-out value if this is not a
+ // subregister liverange.
+ if (!PVNI && LaneMask == 0) {
report("Register not marked live out of predecessor", *PI);
report_context(LR, Reg, LaneMask);
report_context(*VNI);