| //===-- StructuralHash.cpp - IR Hash for expensive checks -------*- C++ -*-===// |
| // |
| // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. |
| // See https://llvm.org/LICENSE.txt for license information. |
| // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception |
| // |
| //===----------------------------------------------------------------------===// |
| // |
| |
| #ifdef EXPENSIVE_CHECKS |
| |
| #include "llvm/IR/StructuralHash.h" |
| #include "llvm/IR/Function.h" |
| #include "llvm/IR/Module.h" |
| |
| using namespace llvm; |
| |
| 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(const 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(const Module &M) { |
| for (const Function &F : M) |
| update(F); |
| } |
| |
| uint64_t getHash() const { return Hash; } |
| }; |
| |
| } // namespace details |
| |
| uint64_t llvm::StructuralHash(const Function &F) { |
| ::details::StructuralHash H; |
| H.update(F); |
| return H.getHash(); |
| } |
| |
| uint64_t llvm::StructuralHash(const Module &M) { |
| ::details::StructuralHash H; |
| H.update(M); |
| return H.getHash(); |
| } |
| |
| #endif |