StructuralHash.cpp 2.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384
  1. //===-- StructuralHash.cpp - IR Hash for expensive checks -------*- C++ -*-===//
  2. //
  3. // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
  4. // See https://llvm.org/LICENSE.txt for license information.
  5. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
  6. //
  7. //===----------------------------------------------------------------------===//
  8. //
  9. #ifdef EXPENSIVE_CHECKS
  10. #include "llvm/IR/StructuralHash.h"
  11. #include "llvm/IR/Function.h"
  12. #include "llvm/IR/Module.h"
  13. using namespace llvm;
  14. namespace {
  15. namespace details {
  16. // Basic hashing mechanism to detect structural change to the IR, used to verify
  17. // pass return status consistency with actual change. Loosely copied from
  18. // llvm/lib/Transforms/Utils/FunctionComparator.cpp
  19. class StructuralHash {
  20. uint64_t Hash = 0x6acaa36bef8325c5ULL;
  21. void update(uint64_t V) { Hash = hashing::detail::hash_16_bytes(Hash, V); }
  22. public:
  23. StructuralHash() = default;
  24. void update(const Function &F) {
  25. if (F.empty())
  26. return;
  27. update(F.isVarArg());
  28. update(F.arg_size());
  29. SmallVector<const BasicBlock *, 8> BBs;
  30. SmallPtrSet<const BasicBlock *, 16> VisitedBBs;
  31. BBs.push_back(&F.getEntryBlock());
  32. VisitedBBs.insert(BBs[0]);
  33. while (!BBs.empty()) {
  34. const BasicBlock *BB = BBs.pop_back_val();
  35. update(45798); // Block header
  36. for (auto &Inst : *BB)
  37. update(Inst.getOpcode());
  38. const Instruction *Term = BB->getTerminator();
  39. for (unsigned i = 0, e = Term->getNumSuccessors(); i != e; ++i) {
  40. if (!VisitedBBs.insert(Term->getSuccessor(i)).second)
  41. continue;
  42. BBs.push_back(Term->getSuccessor(i));
  43. }
  44. }
  45. }
  46. void update(const Module &M) {
  47. for (const Function &F : M)
  48. update(F);
  49. }
  50. uint64_t getHash() const { return Hash; }
  51. };
  52. } // namespace details
  53. } // namespace
  54. uint64_t llvm::StructuralHash(const Function &F) {
  55. details::StructuralHash H;
  56. H.update(F);
  57. return H.getHash();
  58. }
  59. uint64_t llvm::StructuralHash(const Module &M) {
  60. details::StructuralHash H;
  61. H.update(M);
  62. return H.getHash();
  63. }
  64. #endif