StructuralHash.cpp 2.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081
  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 details {
  15. // Basic hashing mechanism to detect structural change to the IR, used to verify
  16. // pass return status consistency with actual change. Loosely copied from
  17. // llvm/lib/Transforms/Utils/FunctionComparator.cpp
  18. class StructuralHash {
  19. uint64_t Hash = 0x6acaa36bef8325c5ULL;
  20. void update(uint64_t V) { Hash = hashing::detail::hash_16_bytes(Hash, V); }
  21. public:
  22. StructuralHash() = default;
  23. void update(const Function &F) {
  24. if (F.empty())
  25. return;
  26. update(F.isVarArg());
  27. update(F.arg_size());
  28. SmallVector<const BasicBlock *, 8> BBs;
  29. SmallPtrSet<const BasicBlock *, 16> VisitedBBs;
  30. BBs.push_back(&F.getEntryBlock());
  31. VisitedBBs.insert(BBs[0]);
  32. while (!BBs.empty()) {
  33. const BasicBlock *BB = BBs.pop_back_val();
  34. update(45798); // Block header
  35. for (auto &Inst : *BB)
  36. update(Inst.getOpcode());
  37. const Instruction *Term = BB->getTerminator();
  38. for (unsigned i = 0, e = Term->getNumSuccessors(); i != e; ++i) {
  39. if (!VisitedBBs.insert(Term->getSuccessor(i)).second)
  40. continue;
  41. BBs.push_back(Term->getSuccessor(i));
  42. }
  43. }
  44. }
  45. void update(const Module &M) {
  46. for (const Function &F : M)
  47. update(F);
  48. }
  49. uint64_t getHash() const { return Hash; }
  50. };
  51. } // namespace details
  52. uint64_t llvm::StructuralHash(const Function &F) {
  53. ::details::StructuralHash H;
  54. H.update(F);
  55. return H.getHash();
  56. }
  57. uint64_t llvm::StructuralHash(const Module &M) {
  58. ::details::StructuralHash H;
  59. H.update(M);
  60. return H.getHash();
  61. }
  62. #endif