[RISCV] Fix mgather -> riscv.masked.strided.load combine not extending indices (...
[llvm-project.git] / llvm / lib / CodeGen / MachineStableHash.cpp
blob1cd90474898e7769e799e894271640318e960b03
1 //===- lib/CodeGen/MachineStableHash.cpp ----------------------------------===//
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 // 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/APFloat.h"
16 #include "llvm/ADT/APInt.h"
17 #include "llvm/ADT/Hashing.h"
18 #include "llvm/ADT/STLExtras.h"
19 #include "llvm/ADT/SmallVector.h"
20 #include "llvm/ADT/StableHashing.h"
21 #include "llvm/ADT/Statistic.h"
22 #include "llvm/ADT/ilist_iterator.h"
23 #include "llvm/CodeGen/MachineBasicBlock.h"
24 #include "llvm/CodeGen/MachineFunction.h"
25 #include "llvm/CodeGen/MachineInstr.h"
26 #include "llvm/CodeGen/MachineInstrBundleIterator.h"
27 #include "llvm/CodeGen/MachineMemOperand.h"
28 #include "llvm/CodeGen/MachineOperand.h"
29 #include "llvm/CodeGen/MachineRegisterInfo.h"
30 #include "llvm/CodeGen/Register.h"
31 #include "llvm/Config/llvm-config.h"
32 #include "llvm/IR/Constants.h"
33 #include "llvm/MC/MCSymbol.h"
34 #include "llvm/Support/Alignment.h"
35 #include "llvm/Support/ErrorHandling.h"
37 #define DEBUG_TYPE "machine-stable-hash"
39 using namespace llvm;
41 STATISTIC(StableHashBailingMachineBasicBlock,
42 "Number of encountered unsupported MachineOperands that were "
43 "MachineBasicBlocks while computing stable hashes");
44 STATISTIC(StableHashBailingConstantPoolIndex,
45 "Number of encountered unsupported MachineOperands that were "
46 "ConstantPoolIndex while computing stable hashes");
47 STATISTIC(StableHashBailingTargetIndexNoName,
48 "Number of encountered unsupported MachineOperands that were "
49 "TargetIndex with no name");
50 STATISTIC(StableHashBailingGlobalAddress,
51 "Number of encountered unsupported MachineOperands that were "
52 "GlobalAddress while computing stable hashes");
53 STATISTIC(StableHashBailingBlockAddress,
54 "Number of encountered unsupported MachineOperands that were "
55 "BlockAddress while computing stable hashes");
56 STATISTIC(StableHashBailingMetadataUnsupported,
57 "Number of encountered unsupported MachineOperands that were "
58 "Metadata of an unsupported kind while computing stable hashes");
60 stable_hash llvm::stableHashValue(const MachineOperand &MO) {
61 switch (MO.getType()) {
62 case MachineOperand::MO_Register:
63 if (MO.getReg().isVirtual()) {
64 const MachineRegisterInfo &MRI = MO.getParent()->getMF()->getRegInfo();
65 SmallVector<unsigned> DefOpcodes;
66 for (auto &Def : MRI.def_instructions(MO.getReg()))
67 DefOpcodes.push_back(Def.getOpcode());
68 return hash_combine_range(DefOpcodes.begin(), DefOpcodes.end());
71 // Register operands don't have target flags.
72 return stable_hash_combine(MO.getType(), MO.getReg(), MO.getSubReg(),
73 MO.isDef());
74 case MachineOperand::MO_Immediate:
75 return stable_hash_combine(MO.getType(), MO.getTargetFlags(), MO.getImm());
76 case MachineOperand::MO_CImmediate:
77 case MachineOperand::MO_FPImmediate: {
78 auto Val = MO.isCImm() ? MO.getCImm()->getValue()
79 : MO.getFPImm()->getValueAPF().bitcastToAPInt();
80 auto ValHash =
81 stable_hash_combine_array(Val.getRawData(), Val.getNumWords());
82 return hash_combine(MO.getType(), MO.getTargetFlags(), ValHash);
85 case MachineOperand::MO_MachineBasicBlock:
86 StableHashBailingMachineBasicBlock++;
87 return 0;
88 case MachineOperand::MO_ConstantPoolIndex:
89 StableHashBailingConstantPoolIndex++;
90 return 0;
91 case MachineOperand::MO_BlockAddress:
92 StableHashBailingBlockAddress++;
93 return 0;
94 case MachineOperand::MO_Metadata:
95 StableHashBailingMetadataUnsupported++;
96 return 0;
97 case MachineOperand::MO_GlobalAddress:
98 StableHashBailingGlobalAddress++;
99 return 0;
100 case MachineOperand::MO_TargetIndex: {
101 if (const char *Name = MO.getTargetIndexName())
102 return stable_hash_combine(MO.getType(), MO.getTargetFlags(),
103 stable_hash_combine_string(Name),
104 MO.getOffset());
105 StableHashBailingTargetIndexNoName++;
106 return 0;
109 case MachineOperand::MO_FrameIndex:
110 case MachineOperand::MO_JumpTableIndex:
111 return stable_hash_combine(MO.getType(), MO.getTargetFlags(),
112 MO.getIndex());
114 case MachineOperand::MO_ExternalSymbol:
115 return hash_combine(MO.getType(), MO.getTargetFlags(), MO.getOffset(),
116 stable_hash_combine_string(MO.getSymbolName()));
118 case MachineOperand::MO_RegisterMask:
119 case MachineOperand::MO_RegisterLiveOut: {
120 if (const MachineInstr *MI = MO.getParent()) {
121 if (const MachineBasicBlock *MBB = MI->getParent()) {
122 if (const MachineFunction *MF = MBB->getParent()) {
123 const TargetRegisterInfo *TRI = MF->getSubtarget().getRegisterInfo();
124 unsigned RegMaskSize =
125 MachineOperand::getRegMaskSize(TRI->getNumRegs());
126 const uint32_t *RegMask = MO.getRegMask();
127 std::vector<llvm::stable_hash> RegMaskHashes(RegMask,
128 RegMask + RegMaskSize);
129 return hash_combine(MO.getType(), MO.getTargetFlags(),
130 stable_hash_combine_array(RegMaskHashes.data(),
131 RegMaskHashes.size()));
136 assert(0 && "MachineOperand not associated with any MachineFunction");
137 return hash_combine(MO.getType(), MO.getTargetFlags());
140 case MachineOperand::MO_ShuffleMask: {
141 std::vector<llvm::stable_hash> ShuffleMaskHashes;
143 llvm::transform(
144 MO.getShuffleMask(), std::back_inserter(ShuffleMaskHashes),
145 [](int S) -> llvm::stable_hash { return llvm::stable_hash(S); });
147 return hash_combine(MO.getType(), MO.getTargetFlags(),
148 stable_hash_combine_array(ShuffleMaskHashes.data(),
149 ShuffleMaskHashes.size()));
151 case MachineOperand::MO_MCSymbol: {
152 auto SymbolName = MO.getMCSymbol()->getName();
153 return hash_combine(MO.getType(), MO.getTargetFlags(),
154 stable_hash_combine_string(SymbolName));
156 case MachineOperand::MO_CFIIndex:
157 return stable_hash_combine(MO.getType(), MO.getTargetFlags(),
158 MO.getCFIIndex());
159 case MachineOperand::MO_IntrinsicID:
160 return stable_hash_combine(MO.getType(), MO.getTargetFlags(),
161 MO.getIntrinsicID());
162 case MachineOperand::MO_Predicate:
163 return stable_hash_combine(MO.getType(), MO.getTargetFlags(),
164 MO.getPredicate());
165 case MachineOperand::MO_DbgInstrRef:
166 return stable_hash_combine(MO.getType(), MO.getInstrRefInstrIndex(),
167 MO.getInstrRefOpIndex());
169 llvm_unreachable("Invalid machine operand type");
172 /// A stable hash value for machine instructions.
173 /// Returns 0 if no stable hash could be computed.
174 /// The hashing and equality testing functions ignore definitions so this is
175 /// useful for CSE, etc.
176 stable_hash llvm::stableHashValue(const MachineInstr &MI, bool HashVRegs,
177 bool HashConstantPoolIndices,
178 bool HashMemOperands) {
179 // Build up a buffer of hash code components.
180 SmallVector<stable_hash, 16> HashComponents;
181 HashComponents.reserve(MI.getNumOperands() + MI.getNumMemOperands() + 2);
182 HashComponents.push_back(MI.getOpcode());
183 HashComponents.push_back(MI.getFlags());
184 for (const MachineOperand &MO : MI.operands()) {
185 if (!HashVRegs && MO.isReg() && MO.isDef() && MO.getReg().isVirtual())
186 continue; // Skip virtual register defs.
188 if (MO.isCPI()) {
189 HashComponents.push_back(stable_hash_combine(
190 MO.getType(), MO.getTargetFlags(), MO.getIndex()));
191 continue;
194 stable_hash StableHash = stableHashValue(MO);
195 if (!StableHash)
196 return 0;
197 HashComponents.push_back(StableHash);
200 for (const auto *Op : MI.memoperands()) {
201 if (!HashMemOperands)
202 break;
203 HashComponents.push_back(static_cast<unsigned>(Op->getSize()));
204 HashComponents.push_back(static_cast<unsigned>(Op->getFlags()));
205 HashComponents.push_back(static_cast<unsigned>(Op->getOffset()));
206 HashComponents.push_back(static_cast<unsigned>(Op->getSuccessOrdering()));
207 HashComponents.push_back(static_cast<unsigned>(Op->getAddrSpace()));
208 HashComponents.push_back(static_cast<unsigned>(Op->getSyncScopeID()));
209 HashComponents.push_back(static_cast<unsigned>(Op->getBaseAlign().value()));
210 HashComponents.push_back(static_cast<unsigned>(Op->getFailureOrdering()));
213 return stable_hash_combine_range(HashComponents.begin(),
214 HashComponents.end());
217 stable_hash llvm::stableHashValue(const MachineBasicBlock &MBB) {
218 SmallVector<stable_hash> HashComponents;
219 // TODO: Hash more stuff like block alignment and branch probabilities.
220 for (const auto &MI : MBB)
221 HashComponents.push_back(stableHashValue(MI));
222 return stable_hash_combine_range(HashComponents.begin(),
223 HashComponents.end());
226 stable_hash llvm::stableHashValue(const MachineFunction &MF) {
227 SmallVector<stable_hash> HashComponents;
228 // TODO: Hash lots more stuff like function alignment and stack objects.
229 for (const auto &MBB : MF)
230 HashComponents.push_back(stableHashValue(MBB));
231 return stable_hash_combine_range(HashComponents.begin(),
232 HashComponents.end());