1+ #include " llvm/CodeGen/MachineBlockHashInfo.h"
2+ #include " llvm/CodeGen/Passes.h"
3+ #include " llvm/Target/TargetMachine.h"
4+ #include " llvm/InitializePasses.h"
5+
6+ using namespace llvm ;
7+
8+ using OperandHashFuncTy = function_ref<uint64_t (uint64_t &, const MachineOperand &)>;
9+
10+ uint64_t hashBlock (const MachineBasicBlock &MBB, OperandHashFuncTy OperandHashFunc) {
11+ uint64_t Hash = 0 ;
12+ for (const MachineInstr &MI : MBB) {
13+ if (MI.isPseudo ())
14+ continue ;
15+ // Ignore unconditional jumps
16+ if (MI.isUnconditionalBranch ())
17+ continue ;
18+ Hash = hashing::detail::hash_16_bytes (Hash, MI.getOpcode ());
19+ for (unsigned i = 0 ; i < MI.getNumOperands (); i++) {
20+ Hash = OperandHashFunc (Hash, MI.getOperand (i));
21+ }
22+ }
23+ return Hash;
24+ }
25+
26+ // / Hashing a 64-bit integer to a 16-bit one.
27+ uint16_t hash_64_to_16 (const uint64_t Hash) {
28+ uint16_t Res = (uint16_t )(Hash & 0xFFFF );
29+ Res ^= (uint16_t )((Hash >> 16 ) & 0xFFFF );
30+ Res ^= (uint16_t )((Hash >> 32 ) & 0xFFFF );
31+ Res ^= (uint16_t )((Hash >> 48 ) & 0xFFFF );
32+ return Res;
33+ }
34+
35+ uint64_t hashInstOperand (uint64_t &Hash, const MachineOperand &Operand) {
36+ return hashing::detail::hash_16_bytes (Hash, hash_value (Operand));
37+ }
38+
39+ INITIALIZE_PASS (MachineBlockHashInfo, " machine-block-hash" ,
40+ " Machine Block Hash Analysis" , true , true )
41+
42+ char MachineBlockHashInfo::ID = 0;
43+
44+ MachineBlockHashInfo::MachineBlockHashInfo () : MachineFunctionPass(ID) {
45+ initializeMachineBlockHashInfoPass (*PassRegistry::getPassRegistry ());
46+ }
47+
48+ void MachineBlockHashInfo::getAnalysisUsage (AnalysisUsage &AU) const {
49+ AU.setPreservesAll ();
50+ MachineFunctionPass::getAnalysisUsage (AU);
51+ }
52+
53+ bool MachineBlockHashInfo::runOnMachineFunction (MachineFunction &F) {
54+ DenseMap<MachineBasicBlock *, BlendedBlockHash> BlendedHashes;
55+ DenseMap<MachineBasicBlock *, uint64_t > OpcodeHashes;
56+ uint16_t Offset = 0 ;
57+ // Initialize hash components
58+ for (MachineBasicBlock &MBB : F) {
59+ BlendedBlockHash BlendedHash;
60+ // offset of the machine basic block
61+ BlendedHash.Offset = Offset;
62+ Offset += MBB.size ();
63+ // Hashing opcodes
64+ uint64_t OpcodeHash = hashBlock (MBB, [](uint64_t &Hash, const MachineOperand &Op) { return Hash; });
65+ OpcodeHashes[&MBB] = OpcodeHash;
66+ BlendedHash.OpcodeHash = hash_64_to_16 (OpcodeHash);
67+ // Hash complete instructions
68+ uint64_t InstrHash = hashBlock (MBB, hashInstOperand);
69+ BlendedHash.InstrHash = hash_64_to_16 (InstrHash);
70+ BlendedHashes[&MBB] = BlendedHash;
71+ }
72+
73+ // Initialize neighbor hash
74+ for (MachineBasicBlock &MBB : F) {
75+ uint64_t Hash = OpcodeHashes[&MBB];
76+ // Append hashes of successors
77+ for (MachineBasicBlock *SuccMBB : MBB.successors ()) {
78+ uint64_t SuccHash = OpcodeHashes[SuccMBB];
79+ Hash = hashing::detail::hash_16_bytes (Hash, SuccHash);
80+ }
81+ // Append hashes of predecessors
82+ for (MachineBasicBlock *PredMBB : MBB.predecessors ()) {
83+ uint64_t PredHash = OpcodeHashes[PredMBB];
84+ Hash = hashing::detail::hash_16_bytes (Hash, PredHash);
85+ }
86+ BlendedHashes[&MBB].NeighborHash = hash_64_to_16 (Hash);
87+ }
88+
89+ // Assign hashes
90+ for (MachineBasicBlock &MBB : F) {
91+ if (MBB.getBBID ()) {
92+ MBBHashInfo[MBB.getBBID ()->BaseID ] = BlendedHashes[&MBB].combine ();
93+ }
94+ }
95+
96+ return false ;
97+ }
98+
99+ uint64_t MachineBlockHashInfo::getMBBHash (const MachineBasicBlock &MBB) {
100+ if (MBB.getBBID ()) {
101+ return MBBHashInfo[MBB.getBBID ()->BaseID ];
102+ }
103+ return 0 ;
104+ }
0 commit comments