Skip to content

Commit

Permalink
Double check that passes correctly set their Modified status
Browse files Browse the repository at this point in the history
The approach is simple: if a pass reports that it's not modifying a
Function/Module, compute a loose hash of that Function/Module and compare it
with the original one. If we report no change but there's a hash change, then we
have an error.

This approach misses a lot of change but it's not super intrusive and can
detect most of the simple mistakes.

Differential Revision: https://reviews.llvm.org/D80916
  • Loading branch information
serge-sans-paille committed Jul 14, 2020
1 parent e2b75ca commit 3667d87
Show file tree
Hide file tree
Showing 2 changed files with 88 additions and 1 deletion.
87 changes: 87 additions & 0 deletions llvm/lib/IR/LegacyPassManager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1475,6 +1475,74 @@ void FPPassManager::dumpPassStructure(unsigned Offset) {
}
}

#ifdef EXPENSIVE_CHECKS
namespace {
namespace details {

// Basic hashing mechanism to detect structural change to the IR, used to verify
// pass return status consistency with actual change. Loosely copied from
// llvm/lib/Transforms/Utils/FunctionComparator.cpp

class StructuralHash {
uint64_t Hash = 0x6acaa36bef8325c5ULL;

void update(uint64_t V) { Hash = hashing::detail::hash_16_bytes(Hash, V); }

public:
StructuralHash() = default;

void update(Function &F) {
if (F.empty())
return;

update(F.isVarArg());
update(F.arg_size());

SmallVector<const BasicBlock *, 8> BBs;
SmallPtrSet<const BasicBlock *, 16> VisitedBBs;

BBs.push_back(&F.getEntryBlock());
VisitedBBs.insert(BBs[0]);
while (!BBs.empty()) {
const BasicBlock *BB = BBs.pop_back_val();
update(45798); // Block header
for (auto &Inst : *BB)
update(Inst.getOpcode());

const Instruction *Term = BB->getTerminator();
for (unsigned i = 0, e = Term->getNumSuccessors(); i != e; ++i) {
if (!VisitedBBs.insert(Term->getSuccessor(i)).second)
continue;
BBs.push_back(Term->getSuccessor(i));
}
}
}

void update(Module &M) {
for (Function &F : M)
update(F);
}

uint64_t getHash() const { return Hash; }
};

} // namespace details

uint64_t StructuralHash(Function &F) {
details::StructuralHash H;
H.update(F);
return H.getHash();
}

uint64_t StructuralHash(Module &M) {
details::StructuralHash H;
H.update(M);
return H.getHash();
}

} // end anonymous namespace

#endif

/// Execute all of the passes scheduled for execution by invoking
/// runOnFunction method. Keep track of whether any of the passes modifies
Expand Down Expand Up @@ -1513,7 +1581,16 @@ bool FPPassManager::runOnFunction(Function &F) {
{
PassManagerPrettyStackEntry X(FP, F);
TimeRegion PassTimer(getPassTimer(FP));
#ifdef EXPENSIVE_CHECKS
uint64_t RefHash = StructuralHash(F);
#endif
LocalChanged |= FP->runOnFunction(F);

#ifdef EXPENSIVE_CHECKS
assert((LocalChanged || (RefHash == StructuralHash(F))) &&
"Pass modifies its input and doesn't report it.");
#endif

if (EmitICRemark) {
unsigned NewSize = F.getInstructionCount();

Expand Down Expand Up @@ -1614,7 +1691,17 @@ MPPassManager::runOnModule(Module &M) {
PassManagerPrettyStackEntry X(MP, M);
TimeRegion PassTimer(getPassTimer(MP));

#ifdef EXPENSIVE_CHECKS
uint64_t RefHash = StructuralHash(M);
#endif

LocalChanged |= MP->runOnModule(M);

#ifdef EXPENSIVE_CHECKS
assert((LocalChanged || (RefHash == StructuralHash(M))) &&
"Pass modifies its input and doesn't report it.");
#endif

if (EmitICRemark) {
// Update the size of the module.
unsigned ModuleCount = M.getInstructionCount();
Expand Down
2 changes: 1 addition & 1 deletion llvm/unittests/IR/LegacyPassManagerTest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -680,7 +680,7 @@ namespace llvm {
ASSERT_EQ(M->getFunctionList().size(), 4U);
Function *F = M->getFunction("test2");
Function *SF = splitSimpleFunction(*F);
CallInst::Create(F, "", &SF->getEntryBlock());
CallInst::Create(F, "", &*SF->getEntryBlock().getFirstInsertionPt());
ASSERT_EQ(M->getFunctionList().size(), 5U);
CGModifierPass *P = new CGModifierPass();
legacy::PassManager Passes;
Expand Down

0 comments on commit 3667d87

Please sign in to comment.