Skip to content

Commit

Permalink
MachineVerifier: Improve PHI operand checking
Browse files Browse the repository at this point in the history
Additional checks for phi operands:
- first operand should be a virtual register def. It should not be
  tied, implicit, internalread, earlyclobber or a read.
- The other operands should be register/mbb operands next to each other
- The register operands should not be implicit, internalread,
  earlyclobber, debug or tied.
- We can perform most of the PHI checks even for unreachable blocks.

llvm-svn: 319140
  • Loading branch information
MatzeB committed Nov 28, 2017
1 parent adf7582 commit a6d5374
Showing 1 changed file with 54 additions and 28 deletions.
82 changes: 54 additions & 28 deletions llvm/lib/CodeGen/MachineVerifier.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -264,7 +264,7 @@ namespace {

void markReachable(const MachineBasicBlock *MBB);
void calcRegsPassed();
void checkPHIOps(const MachineBasicBlock *MBB);
void checkPHIOps(const MachineBasicBlock &MBB);

void calcRegsRequired();
void verifyLiveVariables();
Expand Down Expand Up @@ -1604,32 +1604,65 @@ void MachineVerifier::calcRegsRequired() {

// Check PHI instructions at the beginning of MBB. It is assumed that
// calcRegsPassed has been run so BBInfo::isLiveOut is valid.
void MachineVerifier::checkPHIOps(const MachineBasicBlock *MBB) {
void MachineVerifier::checkPHIOps(const MachineBasicBlock &MBB) {
BBInfo &MInfo = MBBInfoMap[&MBB];

SmallPtrSet<const MachineBasicBlock*, 8> seen;
for (const auto &BBI : *MBB) {
if (!BBI.isPHI())
for (const MachineInstr &Phi : MBB) {
if (!Phi.isPHI())
break;
seen.clear();

for (unsigned i = 1, e = BBI.getNumOperands(); i != e; i += 2) {
unsigned Reg = BBI.getOperand(i).getReg();
const MachineBasicBlock *Pre = BBI.getOperand(i + 1).getMBB();
if (!Pre->isSuccessor(MBB))
const MachineOperand &MODef = Phi.getOperand(0);
if (!MODef.isReg() || !MODef.isDef()) {
report("Expected first PHI operand to be a register def", &MODef, 0);
continue;
}
if (MODef.isTied() || MODef.isImplicit() || MODef.isInternalRead() ||
MODef.isEarlyClobber() || MODef.isDebug())
report("Unexpected flag on PHI operand", &MODef, 0);
unsigned DefReg = MODef.getReg();
if (!TargetRegisterInfo::isVirtualRegister(DefReg))
report("Expected first PHI operand to be a virtual register", &MODef, 0);

for (unsigned I = 1, E = Phi.getNumOperands(); I != E; I += 2) {
const MachineOperand &MO0 = Phi.getOperand(I);
if (!MO0.isReg()) {
report("Expected PHI operand to be a register", &MO0, I);
continue;
}
if (MO0.isImplicit() || MO0.isInternalRead() || MO0.isEarlyClobber() ||
MO0.isDebug() || MO0.isTied())
report("Unexpected flag on PHI operand", &MO0, I);

const MachineOperand &MO1 = Phi.getOperand(I + 1);
if (!MO1.isMBB()) {
report("Expected PHI operand to be a basic block", &MO1, I + 1);
continue;
seen.insert(Pre);
BBInfo &PrInfo = MBBInfoMap[Pre];
if (PrInfo.reachable && !PrInfo.isLiveOut(Reg))
report("PHI operand is not live-out from predecessor",
&BBI.getOperand(i), i);
}

const MachineBasicBlock &Pre = *MO1.getMBB();
if (!Pre.isSuccessor(&MBB)) {
report("PHI input is not a predecessor block", &MO1, I + 1);
continue;
}

if (MInfo.reachable) {
seen.insert(&Pre);
BBInfo &PrInfo = MBBInfoMap[&Pre];
if (PrInfo.reachable && !PrInfo.isLiveOut(MO0.getReg()))
report("PHI operand is not live-out from predecessor", &MO0, I);
}
}

// Did we see all predecessors?
for (MachineBasicBlock::const_pred_iterator PrI = MBB->pred_begin(),
PrE = MBB->pred_end(); PrI != PrE; ++PrI) {
if (!seen.count(*PrI)) {
report("Missing PHI operand", &BBI);
errs() << "BB#" << (*PrI)->getNumber()
<< " is a predecessor according to the CFG.\n";
if (MInfo.reachable) {
for (MachineBasicBlock *Pred : MBB.predecessors()) {
if (!seen.count(Pred)) {
report("Missing PHI operand", &Phi);
errs() << "BB#" << Pred->getNumber()
<< " is a predecessor according to the CFG.\n";
}
}
}
}
Expand All @@ -1638,15 +1671,8 @@ void MachineVerifier::checkPHIOps(const MachineBasicBlock *MBB) {
void MachineVerifier::visitMachineFunctionAfter() {
calcRegsPassed();

for (const auto &MBB : *MF) {
BBInfo &MInfo = MBBInfoMap[&MBB];

// Skip unreachable MBBs.
if (!MInfo.reachable)
continue;

checkPHIOps(&MBB);
}
for (const MachineBasicBlock &MBB : *MF)
checkPHIOps(MBB);

// Now check liveness info if available
calcRegsRequired();
Expand Down

0 comments on commit a6d5374

Please sign in to comment.