[llvm] 3667d87 - Double check that passes correctly set their Modified status
via llvm-commits
llvm-commits at lists.llvm.org
Tue Jul 14 01:00:37 PDT 2020
Author: serge-sans-paille
Date: 2020-07-14T09:56:49+02:00
New Revision: 3667d87a33d3c8d4072a41fd84bb880c59347dc0
URL: https://github.com/llvm/llvm-project/commit/3667d87a33d3c8d4072a41fd84bb880c59347dc0
DIFF: https://github.com/llvm/llvm-project/commit/3667d87a33d3c8d4072a41fd84bb880c59347dc0.diff
LOG: Double check that passes correctly set their Modified status
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
Added:
Modified:
llvm/lib/IR/LegacyPassManager.cpp
llvm/unittests/IR/LegacyPassManagerTest.cpp
Removed:
################################################################################
diff --git a/llvm/lib/IR/LegacyPassManager.cpp b/llvm/lib/IR/LegacyPassManager.cpp
index 4189aea46294..74869fa62c66 100644
--- a/llvm/lib/IR/LegacyPassManager.cpp
+++ b/llvm/lib/IR/LegacyPassManager.cpp
@@ -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
@@ -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();
@@ -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();
diff --git a/llvm/unittests/IR/LegacyPassManagerTest.cpp b/llvm/unittests/IR/LegacyPassManagerTest.cpp
index b7801b52481d..8dda94b1b032 100644
--- a/llvm/unittests/IR/LegacyPassManagerTest.cpp
+++ b/llvm/unittests/IR/LegacyPassManagerTest.cpp
@@ -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;
More information about the llvm-commits
mailing list