aboutsummaryrefslogtreecommitdiffstats
path: root/contrib/libs/llvm12/lib/IR/StructuralHash.cpp
blob: cf8e7cb1d68d5381e98ee900b8008e1a5e506fa8 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
//===-- 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 { 
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 
 
} // namespace 
 
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