mirror of
https://github.com/RPCS3/llvm.git
synced 2025-01-01 01:14:12 +00:00
Allow the machine verifier to be run outside the PassManager.
Verify LiveVariables information when present. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@89241 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
1e78aa445c
commit
8f16e02fc9
@ -233,7 +233,7 @@ public:
|
||||
|
||||
/// verify - Run the current MachineFunction through the machine code
|
||||
/// verifier, useful for debugger use.
|
||||
void verify() const;
|
||||
void verify(Pass *p=NULL, bool allowDoubleDefs=false) const;
|
||||
|
||||
// Provide accessors for the MachineBasicBlock list...
|
||||
typedef BasicBlockListType::iterator iterator;
|
||||
|
@ -42,23 +42,18 @@
|
||||
using namespace llvm;
|
||||
|
||||
namespace {
|
||||
struct MachineVerifier : public MachineFunctionPass {
|
||||
static char ID; // Pass ID, replacement for typeid
|
||||
struct MachineVerifier {
|
||||
|
||||
MachineVerifier(bool allowDoubleDefs = false) :
|
||||
MachineFunctionPass(&ID),
|
||||
MachineVerifier(Pass *pass, bool allowDoubleDefs) :
|
||||
PASS(pass),
|
||||
allowVirtDoubleDefs(allowDoubleDefs),
|
||||
allowPhysDoubleDefs(allowDoubleDefs),
|
||||
OutFileName(getenv("LLVM_VERIFY_MACHINEINSTRS"))
|
||||
{}
|
||||
|
||||
void getAnalysisUsage(AnalysisUsage &AU) const {
|
||||
AU.setPreservesAll();
|
||||
MachineFunctionPass::getAnalysisUsage(AU);
|
||||
}
|
||||
{}
|
||||
|
||||
bool runOnMachineFunction(MachineFunction &MF);
|
||||
|
||||
Pass *const PASS;
|
||||
const bool allowVirtDoubleDefs;
|
||||
const bool allowPhysDoubleDefs;
|
||||
|
||||
@ -112,6 +107,10 @@ namespace {
|
||||
// regsKilled and regsLiveOut.
|
||||
RegSet vregsPassed;
|
||||
|
||||
// Vregs that must pass through MBB because they are needed by a successor
|
||||
// block. This set is disjoint from regsLiveOut.
|
||||
RegSet vregsRequired;
|
||||
|
||||
BBInfo() : reachable(false) {}
|
||||
|
||||
// Add register to vregsPassed if it belongs there. Return true if
|
||||
@ -133,6 +132,34 @@ namespace {
|
||||
return changed;
|
||||
}
|
||||
|
||||
// Add register to vregsRequired if it belongs there. Return true if
|
||||
// anything changed.
|
||||
bool addRequired(unsigned Reg) {
|
||||
if (!TargetRegisterInfo::isVirtualRegister(Reg))
|
||||
return false;
|
||||
if (regsLiveOut.count(Reg))
|
||||
return false;
|
||||
return vregsRequired.insert(Reg).second;
|
||||
}
|
||||
|
||||
// Same for a full set.
|
||||
bool addRequired(const RegSet &RS) {
|
||||
bool changed = false;
|
||||
for (RegSet::const_iterator I = RS.begin(), E = RS.end(); I != E; ++I)
|
||||
if (addRequired(*I))
|
||||
changed = true;
|
||||
return changed;
|
||||
}
|
||||
|
||||
// Same for a full map.
|
||||
bool addRequired(const RegMap &RM) {
|
||||
bool changed = false;
|
||||
for (RegMap::const_iterator I = RM.begin(), E = RM.end(); I != E; ++I)
|
||||
if (addRequired(I->first))
|
||||
changed = true;
|
||||
return changed;
|
||||
}
|
||||
|
||||
// Live-out registers are either in regsLiveOut or vregsPassed.
|
||||
bool isLiveOut(unsigned Reg) const {
|
||||
return regsLiveOut.count(Reg) || vregsPassed.count(Reg);
|
||||
@ -146,6 +173,9 @@ namespace {
|
||||
return Reg < regsReserved.size() && regsReserved.test(Reg);
|
||||
}
|
||||
|
||||
// Analysis information if available
|
||||
LiveVariables *LiveVars;
|
||||
|
||||
void visitMachineFunctionBefore();
|
||||
void visitMachineBasicBlockBefore(const MachineBasicBlock *MBB);
|
||||
void visitMachineInstrBefore(const MachineInstr *MI);
|
||||
@ -163,20 +193,44 @@ namespace {
|
||||
void calcMaxRegsPassed();
|
||||
void calcMinRegsPassed();
|
||||
void checkPHIOps(const MachineBasicBlock *MBB);
|
||||
|
||||
void calcRegsRequired();
|
||||
void verifyLiveVariables();
|
||||
};
|
||||
|
||||
struct MachineVerifierPass : public MachineFunctionPass {
|
||||
static char ID; // Pass ID, replacement for typeid
|
||||
bool AllowDoubleDefs;
|
||||
|
||||
explicit MachineVerifierPass(bool allowDoubleDefs = false)
|
||||
: MachineFunctionPass(&ID),
|
||||
AllowDoubleDefs(allowDoubleDefs) {}
|
||||
|
||||
void getAnalysisUsage(AnalysisUsage &AU) const {
|
||||
AU.setPreservesAll();
|
||||
MachineFunctionPass::getAnalysisUsage(AU);
|
||||
}
|
||||
|
||||
bool runOnMachineFunction(MachineFunction &MF) {
|
||||
MF.verify(this, AllowDoubleDefs);
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
char MachineVerifier::ID = 0;
|
||||
static RegisterPass<MachineVerifier>
|
||||
char MachineVerifierPass::ID = 0;
|
||||
static RegisterPass<MachineVerifierPass>
|
||||
MachineVer("machineverifier", "Verify generated machine code");
|
||||
static const PassInfo *const MachineVerifyID = &MachineVer;
|
||||
|
||||
FunctionPass *llvm::createMachineVerifierPass(bool allowPhysDoubleDefs) {
|
||||
return new MachineVerifier(allowPhysDoubleDefs);
|
||||
return new MachineVerifierPass(allowPhysDoubleDefs);
|
||||
}
|
||||
|
||||
void MachineFunction::verify() const {
|
||||
MachineVerifier().runOnMachineFunction(const_cast<MachineFunction&>(*this));
|
||||
void MachineFunction::verify(Pass *p, bool allowDoubleDefs) const {
|
||||
MachineVerifier(p, allowDoubleDefs)
|
||||
.runOnMachineFunction(const_cast<MachineFunction&>(*this));
|
||||
}
|
||||
|
||||
bool MachineVerifier::runOnMachineFunction(MachineFunction &MF) {
|
||||
@ -202,6 +256,12 @@ bool MachineVerifier::runOnMachineFunction(MachineFunction &MF) {
|
||||
TRI = TM->getRegisterInfo();
|
||||
MRI = &MF.getRegInfo();
|
||||
|
||||
if (PASS) {
|
||||
LiveVars = PASS->getAnalysisIfAvailable<LiveVariables>();
|
||||
} else {
|
||||
LiveVars = NULL;
|
||||
}
|
||||
|
||||
visitMachineFunctionBefore();
|
||||
for (MachineFunction::const_iterator MFI = MF.begin(), MFE = MF.end();
|
||||
MFI!=MFE; ++MFI) {
|
||||
@ -518,8 +578,9 @@ MachineVerifier::visitMachineOperand(const MachineOperand *MO, unsigned MONum) {
|
||||
} else if (MO->isUse()) {
|
||||
regsLiveInButUnused.erase(Reg);
|
||||
|
||||
bool isKill = false;
|
||||
if (MO->isKill()) {
|
||||
addRegWithSubRegs(regsKilled, Reg);
|
||||
isKill = true;
|
||||
// Tied operands on two-address instuctions MUST NOT have a <kill> flag.
|
||||
if (MI->isRegTiedToDefOperand(MONum))
|
||||
report("Illegal kill flag on two-address instruction operand",
|
||||
@ -529,8 +590,20 @@ MachineVerifier::visitMachineOperand(const MachineOperand *MO, unsigned MONum) {
|
||||
unsigned defIdx;
|
||||
if (MI->isRegTiedToDefOperand(MONum, &defIdx) &&
|
||||
MI->getOperand(defIdx).getReg() == Reg)
|
||||
addRegWithSubRegs(regsKilled, Reg);
|
||||
isKill = true;
|
||||
}
|
||||
if (isKill) {
|
||||
addRegWithSubRegs(regsKilled, Reg);
|
||||
|
||||
// Check that LiveVars knows this kill
|
||||
if (LiveVars && TargetRegisterInfo::isVirtualRegister(Reg)) {
|
||||
LiveVariables::VarInfo &VI = LiveVars->getVarInfo(Reg);
|
||||
if (std::find(VI.Kills.begin(),
|
||||
VI.Kills.end(), MI) == VI.Kills.end())
|
||||
report("Kill missing from LiveVariables", MO, MONum);
|
||||
}
|
||||
}
|
||||
|
||||
// Use of a dead register.
|
||||
if (!regsLive.count(Reg)) {
|
||||
if (TargetRegisterInfo::isPhysicalRegister(Reg)) {
|
||||
@ -734,6 +807,41 @@ void MachineVerifier::calcMinRegsPassed() {
|
||||
}
|
||||
}
|
||||
|
||||
// Calculate the set of virtual registers that must be passed through each basic
|
||||
// block in order to satisfy the requirements of successor blocks. This is very
|
||||
// similar to calcMaxRegsPassed, only backwards.
|
||||
void MachineVerifier::calcRegsRequired() {
|
||||
// First push live-in regs to predecessors' vregsRequired.
|
||||
DenseSet<const MachineBasicBlock*> todo;
|
||||
for (MachineFunction::const_iterator MFI = MF->begin(), MFE = MF->end();
|
||||
MFI != MFE; ++MFI) {
|
||||
const MachineBasicBlock &MBB(*MFI);
|
||||
BBInfo &MInfo = MBBInfoMap[&MBB];
|
||||
for (MachineBasicBlock::const_pred_iterator PrI = MBB.pred_begin(),
|
||||
PrE = MBB.pred_end(); PrI != PrE; ++PrI) {
|
||||
BBInfo &PInfo = MBBInfoMap[*PrI];
|
||||
if (PInfo.addRequired(MInfo.vregsLiveIn))
|
||||
todo.insert(*PrI);
|
||||
}
|
||||
}
|
||||
|
||||
// Iteratively push vregsRequired to predecessors. This will converge to the
|
||||
// same final state regardless of DenseSet iteration order.
|
||||
while (!todo.empty()) {
|
||||
const MachineBasicBlock *MBB = *todo.begin();
|
||||
todo.erase(MBB);
|
||||
BBInfo &MInfo = MBBInfoMap[MBB];
|
||||
for (MachineBasicBlock::const_pred_iterator PrI = MBB->pred_begin(),
|
||||
PrE = MBB->pred_end(); PrI != PrE; ++PrI) {
|
||||
if (*PrI == MBB)
|
||||
continue;
|
||||
BBInfo &SInfo = MBBInfoMap[*PrI];
|
||||
if (SInfo.addRequired(MInfo.vregsRequired))
|
||||
todo.insert(*PrI);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Check PHI instructions at the beginning of MBB. It is assumed that
|
||||
// calcMinRegsPassed has been run so BBInfo::isLiveOut is valid.
|
||||
void MachineVerifier::checkPHIOps(const MachineBasicBlock *MBB) {
|
||||
@ -849,4 +957,39 @@ void MachineVerifier::visitMachineFunctionAfter() {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Now check LiveVariables info if available
|
||||
if (LiveVars) {
|
||||
calcRegsRequired();
|
||||
verifyLiveVariables();
|
||||
}
|
||||
}
|
||||
|
||||
void MachineVerifier::verifyLiveVariables() {
|
||||
assert(LiveVars && "Don't call verifyLiveVariables without LiveVars");
|
||||
for (unsigned Reg = TargetRegisterInfo::FirstVirtualRegister,
|
||||
RegE = MRI->getLastVirtReg()-1; Reg != RegE; ++Reg) {
|
||||
LiveVariables::VarInfo &VI = LiveVars->getVarInfo(Reg);
|
||||
for (MachineFunction::const_iterator MFI = MF->begin(), MFE = MF->end();
|
||||
MFI != MFE; ++MFI) {
|
||||
BBInfo &MInfo = MBBInfoMap[MFI];
|
||||
|
||||
// Our vregsRequired should be identical to LiveVariables' AliveBlocks
|
||||
if (MInfo.vregsRequired.count(Reg)) {
|
||||
if (!VI.AliveBlocks.test(MFI->getNumber())) {
|
||||
report("LiveVariables: Block missing from AliveBlocks", MFI);
|
||||
*OS << "Virtual register %reg" << Reg
|
||||
<< " must be live through the block.\n";
|
||||
}
|
||||
} else {
|
||||
if (VI.AliveBlocks.test(MFI->getNumber())) {
|
||||
report("LiveVariables: Block should not be in AliveBlocks", MFI);
|
||||
*OS << "Virtual register %reg" << Reg
|
||||
<< " is not needed live through the block.\n";
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user