1 //===- lib/CodeGen/MachineStableHash.cpp ----------------------------------===//
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
7 //===----------------------------------------------------------------------===//
9 // Stable hashing for MachineInstr and MachineOperand. Useful or getting a
10 // hash across runs, modules, etc.
12 //===----------------------------------------------------------------------===//
14 #include "llvm/CodeGen/MachineStableHash.h"
15 #include "llvm/ADT/FoldingSet.h"
16 #include "llvm/ADT/Statistic.h"
17 #include "llvm/ADT/StringExtras.h"
18 #include "llvm/Analysis/Loads.h"
19 #include "llvm/Analysis/MemoryLocation.h"
20 #include "llvm/CodeGen/MIRFormatter.h"
21 #include "llvm/CodeGen/MIRPrinter.h"
22 #include "llvm/CodeGen/MachineFrameInfo.h"
23 #include "llvm/CodeGen/MachineInstr.h"
24 #include "llvm/CodeGen/MachineJumpTableInfo.h"
25 #include "llvm/CodeGen/MachineOperand.h"
26 #include "llvm/CodeGen/MachineRegisterInfo.h"
27 #include "llvm/CodeGen/StableHashing.h"
28 #include "llvm/CodeGen/TargetInstrInfo.h"
29 #include "llvm/CodeGen/TargetRegisterInfo.h"
30 #include "llvm/Config/llvm-config.h"
31 #include "llvm/IR/Constants.h"
32 #include "llvm/IR/IRPrintingPasses.h"
33 #include "llvm/IR/Instructions.h"
34 #include "llvm/IR/ModuleSlotTracker.h"
35 #include "llvm/MC/MCDwarf.h"
36 #include "llvm/Target/TargetIntrinsicInfo.h"
37 #include "llvm/Target/TargetMachine.h"
39 #define DEBUG_TYPE "machine-stable-hash"
43 STATISTIC(StableHashBailingMachineBasicBlock
,
44 "Number of encountered unsupported MachineOperands that were "
45 "MachineBasicBlocks while computing stable hashes");
46 STATISTIC(StableHashBailingConstantPoolIndex
,
47 "Number of encountered unsupported MachineOperands that were "
48 "ConstantPoolIndex while computing stable hashes");
49 STATISTIC(StableHashBailingTargetIndexNoName
,
50 "Number of encountered unsupported MachineOperands that were "
51 "TargetIndex with no name");
52 STATISTIC(StableHashBailingGlobalAddress
,
53 "Number of encountered unsupported MachineOperands that were "
54 "GlobalAddress while computing stable hashes");
55 STATISTIC(StableHashBailingBlockAddress
,
56 "Number of encountered unsupported MachineOperands that were "
57 "BlockAddress while computing stable hashes");
58 STATISTIC(StableHashBailingMetadataUnsupported
,
59 "Number of encountered unsupported MachineOperands that were "
60 "Metadata of an unsupported kind while computing stable hashes");
62 stable_hash
llvm::stableHashValue(const MachineOperand
&MO
) {
63 switch (MO
.getType()) {
64 case MachineOperand::MO_Register
:
65 if (Register::isVirtualRegister(MO
.getReg())) {
66 const MachineRegisterInfo
&MRI
= MO
.getParent()->getMF()->getRegInfo();
67 return MRI
.getVRegDef(MO
.getReg())->getOpcode();
70 // Register operands don't have target flags.
71 return stable_hash_combine(MO
.getType(), MO
.getReg(), MO
.getSubReg(),
73 case MachineOperand::MO_Immediate
:
74 return stable_hash_combine(MO
.getType(), MO
.getTargetFlags(), MO
.getImm());
75 case MachineOperand::MO_CImmediate
:
76 case MachineOperand::MO_FPImmediate
: {
77 auto Val
= MO
.isCImm() ? MO
.getCImm()->getValue()
78 : MO
.getFPImm()->getValueAPF().bitcastToAPInt();
80 stable_hash_combine_array(Val
.getRawData(), Val
.getNumWords());
81 return hash_combine(MO
.getType(), MO
.getTargetFlags(), ValHash
);
84 case MachineOperand::MO_MachineBasicBlock
:
85 StableHashBailingMachineBasicBlock
++;
87 case MachineOperand::MO_ConstantPoolIndex
:
88 StableHashBailingConstantPoolIndex
++;
90 case MachineOperand::MO_BlockAddress
:
91 StableHashBailingBlockAddress
++;
93 case MachineOperand::MO_Metadata
:
94 StableHashBailingMetadataUnsupported
++;
96 case MachineOperand::MO_GlobalAddress
:
97 StableHashBailingGlobalAddress
++;
99 case MachineOperand::MO_TargetIndex
: {
100 if (const char *Name
= MO
.getTargetIndexName())
101 return stable_hash_combine(MO
.getType(), MO
.getTargetFlags(),
102 stable_hash_combine_string(Name
),
104 StableHashBailingTargetIndexNoName
++;
108 case MachineOperand::MO_FrameIndex
:
109 case MachineOperand::MO_JumpTableIndex
:
110 return stable_hash_combine(MO
.getType(), MO
.getTargetFlags(),
113 case MachineOperand::MO_ExternalSymbol
:
114 return hash_combine(MO
.getType(), MO
.getTargetFlags(), MO
.getOffset(),
115 stable_hash_combine_string(MO
.getSymbolName()));
117 case MachineOperand::MO_RegisterMask
:
118 case MachineOperand::MO_RegisterLiveOut
:
119 return hash_combine(MO
.getType(), MO
.getTargetFlags(), MO
.getRegMask());
121 case MachineOperand::MO_ShuffleMask
: {
122 std::vector
<llvm::stable_hash
> ShuffleMaskHashes
;
125 MO
.getShuffleMask(), std::back_inserter(ShuffleMaskHashes
),
126 [](int S
) -> llvm::stable_hash
{ return llvm::stable_hash(S
); });
128 return hash_combine(MO
.getType(), MO
.getTargetFlags(),
129 stable_hash_combine_array(ShuffleMaskHashes
.data(),
130 ShuffleMaskHashes
.size()));
132 case MachineOperand::MO_MCSymbol
: {
133 auto SymbolName
= MO
.getMCSymbol()->getName();
134 return hash_combine(MO
.getType(), MO
.getTargetFlags(),
135 stable_hash_combine_string(SymbolName
));
137 case MachineOperand::MO_CFIIndex
:
138 return stable_hash_combine(MO
.getType(), MO
.getTargetFlags(),
140 case MachineOperand::MO_IntrinsicID
:
141 return stable_hash_combine(MO
.getType(), MO
.getTargetFlags(),
142 MO
.getIntrinsicID());
143 case MachineOperand::MO_Predicate
:
144 return stable_hash_combine(MO
.getType(), MO
.getTargetFlags(),
147 llvm_unreachable("Invalid machine operand type");
150 /// A stable hash value for machine instructions.
151 /// Returns 0 if no stable hash could be computed.
152 /// The hashing and equality testing functions ignore definitions so this is
153 /// useful for CSE, etc.
154 stable_hash
llvm::stableHashValue(const MachineInstr
&MI
, bool HashVRegs
,
155 bool HashConstantPoolIndices
,
156 bool HashMemOperands
) {
157 // Build up a buffer of hash code components.
158 SmallVector
<stable_hash
, 16> HashComponents
;
159 HashComponents
.reserve(MI
.getNumOperands() + MI
.getNumMemOperands() + 2);
160 HashComponents
.push_back(MI
.getOpcode());
161 HashComponents
.push_back(MI
.getFlags());
162 for (const MachineOperand
&MO
: MI
.operands()) {
163 if (!HashVRegs
&& MO
.isReg() && MO
.isDef() &&
164 Register::isVirtualRegister(MO
.getReg()))
165 continue; // Skip virtual register defs.
168 HashComponents
.push_back(stable_hash_combine(
169 MO
.getType(), MO
.getTargetFlags(), MO
.getIndex()));
173 stable_hash StableHash
= stableHashValue(MO
);
176 HashComponents
.push_back(StableHash
);
179 for (const auto *Op
: MI
.memoperands()) {
180 if (!HashMemOperands
)
182 HashComponents
.push_back(static_cast<unsigned>(Op
->getSize()));
183 HashComponents
.push_back(static_cast<unsigned>(Op
->getFlags()));
184 HashComponents
.push_back(static_cast<unsigned>(Op
->getOffset()));
185 HashComponents
.push_back(static_cast<unsigned>(Op
->getSuccessOrdering()));
186 HashComponents
.push_back(static_cast<unsigned>(Op
->getAddrSpace()));
187 HashComponents
.push_back(static_cast<unsigned>(Op
->getSyncScopeID()));
188 HashComponents
.push_back(static_cast<unsigned>(Op
->getBaseAlign().value()));
189 HashComponents
.push_back(static_cast<unsigned>(Op
->getFailureOrdering()));
192 return stable_hash_combine_range(HashComponents
.begin(),
193 HashComponents
.end());