xref: /netbsd-src/external/apache2/llvm/dist/llvm/lib/CodeGen/MachineStableHash.cpp (revision 82d56013d7b633d116a93943de88e08335357a7c)
1*82d56013Sjoerg //===- lib/CodeGen/MachineStableHash.cpp ----------------------------------===//
2*82d56013Sjoerg //
3*82d56013Sjoerg // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4*82d56013Sjoerg // See https://llvm.org/LICENSE.txt for license information.
5*82d56013Sjoerg // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6*82d56013Sjoerg //
7*82d56013Sjoerg //===----------------------------------------------------------------------===//
8*82d56013Sjoerg //
9*82d56013Sjoerg // Stable hashing for MachineInstr and MachineOperand. Useful or getting a
10*82d56013Sjoerg // hash across runs, modules, etc.
11*82d56013Sjoerg //
12*82d56013Sjoerg //===----------------------------------------------------------------------===//
13*82d56013Sjoerg 
14*82d56013Sjoerg #include "llvm/CodeGen/MachineStableHash.h"
15*82d56013Sjoerg #include "llvm/ADT/FoldingSet.h"
16*82d56013Sjoerg #include "llvm/ADT/Statistic.h"
17*82d56013Sjoerg #include "llvm/ADT/StringExtras.h"
18*82d56013Sjoerg #include "llvm/Analysis/Loads.h"
19*82d56013Sjoerg #include "llvm/Analysis/MemoryLocation.h"
20*82d56013Sjoerg #include "llvm/CodeGen/MIRFormatter.h"
21*82d56013Sjoerg #include "llvm/CodeGen/MIRPrinter.h"
22*82d56013Sjoerg #include "llvm/CodeGen/MachineFrameInfo.h"
23*82d56013Sjoerg #include "llvm/CodeGen/MachineInstr.h"
24*82d56013Sjoerg #include "llvm/CodeGen/MachineJumpTableInfo.h"
25*82d56013Sjoerg #include "llvm/CodeGen/MachineOperand.h"
26*82d56013Sjoerg #include "llvm/CodeGen/MachineRegisterInfo.h"
27*82d56013Sjoerg #include "llvm/CodeGen/StableHashing.h"
28*82d56013Sjoerg #include "llvm/CodeGen/TargetInstrInfo.h"
29*82d56013Sjoerg #include "llvm/CodeGen/TargetRegisterInfo.h"
30*82d56013Sjoerg #include "llvm/Config/llvm-config.h"
31*82d56013Sjoerg #include "llvm/IR/Constants.h"
32*82d56013Sjoerg #include "llvm/IR/IRPrintingPasses.h"
33*82d56013Sjoerg #include "llvm/IR/Instructions.h"
34*82d56013Sjoerg #include "llvm/IR/ModuleSlotTracker.h"
35*82d56013Sjoerg #include "llvm/MC/MCDwarf.h"
36*82d56013Sjoerg #include "llvm/Target/TargetIntrinsicInfo.h"
37*82d56013Sjoerg #include "llvm/Target/TargetMachine.h"
38*82d56013Sjoerg 
39*82d56013Sjoerg #define DEBUG_TYPE "machine-stable-hash"
40*82d56013Sjoerg 
41*82d56013Sjoerg using namespace llvm;
42*82d56013Sjoerg 
43*82d56013Sjoerg STATISTIC(StableHashBailingMachineBasicBlock,
44*82d56013Sjoerg           "Number of encountered unsupported MachineOperands that were "
45*82d56013Sjoerg           "MachineBasicBlocks while computing stable hashes");
46*82d56013Sjoerg STATISTIC(StableHashBailingConstantPoolIndex,
47*82d56013Sjoerg           "Number of encountered unsupported MachineOperands that were "
48*82d56013Sjoerg           "ConstantPoolIndex while computing stable hashes");
49*82d56013Sjoerg STATISTIC(StableHashBailingTargetIndexNoName,
50*82d56013Sjoerg           "Number of encountered unsupported MachineOperands that were "
51*82d56013Sjoerg           "TargetIndex with no name");
52*82d56013Sjoerg STATISTIC(StableHashBailingGlobalAddress,
53*82d56013Sjoerg           "Number of encountered unsupported MachineOperands that were "
54*82d56013Sjoerg           "GlobalAddress while computing stable hashes");
55*82d56013Sjoerg STATISTIC(StableHashBailingBlockAddress,
56*82d56013Sjoerg           "Number of encountered unsupported MachineOperands that were "
57*82d56013Sjoerg           "BlockAddress while computing stable hashes");
58*82d56013Sjoerg STATISTIC(StableHashBailingMetadataUnsupported,
59*82d56013Sjoerg           "Number of encountered unsupported MachineOperands that were "
60*82d56013Sjoerg           "Metadata of an unsupported kind while computing stable hashes");
61*82d56013Sjoerg 
stableHashValue(const MachineOperand & MO)62*82d56013Sjoerg stable_hash llvm::stableHashValue(const MachineOperand &MO) {
63*82d56013Sjoerg   switch (MO.getType()) {
64*82d56013Sjoerg   case MachineOperand::MO_Register:
65*82d56013Sjoerg     if (Register::isVirtualRegister(MO.getReg())) {
66*82d56013Sjoerg       const MachineRegisterInfo &MRI = MO.getParent()->getMF()->getRegInfo();
67*82d56013Sjoerg       return MRI.getVRegDef(MO.getReg())->getOpcode();
68*82d56013Sjoerg     }
69*82d56013Sjoerg 
70*82d56013Sjoerg     // Register operands don't have target flags.
71*82d56013Sjoerg     return stable_hash_combine(MO.getType(), MO.getReg(), MO.getSubReg(),
72*82d56013Sjoerg                                MO.isDef());
73*82d56013Sjoerg   case MachineOperand::MO_Immediate:
74*82d56013Sjoerg     return stable_hash_combine(MO.getType(), MO.getTargetFlags(), MO.getImm());
75*82d56013Sjoerg   case MachineOperand::MO_CImmediate:
76*82d56013Sjoerg   case MachineOperand::MO_FPImmediate: {
77*82d56013Sjoerg     auto Val = MO.isCImm() ? MO.getCImm()->getValue()
78*82d56013Sjoerg                            : MO.getFPImm()->getValueAPF().bitcastToAPInt();
79*82d56013Sjoerg     auto ValHash =
80*82d56013Sjoerg         stable_hash_combine_array(Val.getRawData(), Val.getNumWords());
81*82d56013Sjoerg     return hash_combine(MO.getType(), MO.getTargetFlags(), ValHash);
82*82d56013Sjoerg   }
83*82d56013Sjoerg 
84*82d56013Sjoerg   case MachineOperand::MO_MachineBasicBlock:
85*82d56013Sjoerg     StableHashBailingMachineBasicBlock++;
86*82d56013Sjoerg     return 0;
87*82d56013Sjoerg   case MachineOperand::MO_ConstantPoolIndex:
88*82d56013Sjoerg     StableHashBailingConstantPoolIndex++;
89*82d56013Sjoerg     return 0;
90*82d56013Sjoerg   case MachineOperand::MO_BlockAddress:
91*82d56013Sjoerg     StableHashBailingBlockAddress++;
92*82d56013Sjoerg     return 0;
93*82d56013Sjoerg   case MachineOperand::MO_Metadata:
94*82d56013Sjoerg     StableHashBailingMetadataUnsupported++;
95*82d56013Sjoerg     return 0;
96*82d56013Sjoerg   case MachineOperand::MO_GlobalAddress:
97*82d56013Sjoerg     StableHashBailingGlobalAddress++;
98*82d56013Sjoerg     return 0;
99*82d56013Sjoerg   case MachineOperand::MO_TargetIndex: {
100*82d56013Sjoerg     if (const char *Name = MO.getTargetIndexName())
101*82d56013Sjoerg       return stable_hash_combine(MO.getType(), MO.getTargetFlags(),
102*82d56013Sjoerg                                  stable_hash_combine_string(Name),
103*82d56013Sjoerg                                  MO.getOffset());
104*82d56013Sjoerg     StableHashBailingTargetIndexNoName++;
105*82d56013Sjoerg     return 0;
106*82d56013Sjoerg   }
107*82d56013Sjoerg 
108*82d56013Sjoerg   case MachineOperand::MO_FrameIndex:
109*82d56013Sjoerg   case MachineOperand::MO_JumpTableIndex:
110*82d56013Sjoerg     return stable_hash_combine(MO.getType(), MO.getTargetFlags(),
111*82d56013Sjoerg                                MO.getIndex());
112*82d56013Sjoerg 
113*82d56013Sjoerg   case MachineOperand::MO_ExternalSymbol:
114*82d56013Sjoerg     return hash_combine(MO.getType(), MO.getTargetFlags(), MO.getOffset(),
115*82d56013Sjoerg                         stable_hash_combine_string(MO.getSymbolName()));
116*82d56013Sjoerg 
117*82d56013Sjoerg   case MachineOperand::MO_RegisterMask:
118*82d56013Sjoerg   case MachineOperand::MO_RegisterLiveOut:
119*82d56013Sjoerg     return hash_combine(MO.getType(), MO.getTargetFlags(), MO.getRegMask());
120*82d56013Sjoerg 
121*82d56013Sjoerg   case MachineOperand::MO_ShuffleMask: {
122*82d56013Sjoerg     std::vector<llvm::stable_hash> ShuffleMaskHashes;
123*82d56013Sjoerg 
124*82d56013Sjoerg     llvm::transform(
125*82d56013Sjoerg         MO.getShuffleMask(), std::back_inserter(ShuffleMaskHashes),
126*82d56013Sjoerg         [](int S) -> llvm::stable_hash { return llvm::stable_hash(S); });
127*82d56013Sjoerg 
128*82d56013Sjoerg     return hash_combine(MO.getType(), MO.getTargetFlags(),
129*82d56013Sjoerg                         stable_hash_combine_array(ShuffleMaskHashes.data(),
130*82d56013Sjoerg                                                   ShuffleMaskHashes.size()));
131*82d56013Sjoerg   }
132*82d56013Sjoerg   case MachineOperand::MO_MCSymbol: {
133*82d56013Sjoerg     auto SymbolName = MO.getMCSymbol()->getName();
134*82d56013Sjoerg     return hash_combine(MO.getType(), MO.getTargetFlags(),
135*82d56013Sjoerg                         stable_hash_combine_string(SymbolName));
136*82d56013Sjoerg   }
137*82d56013Sjoerg   case MachineOperand::MO_CFIIndex:
138*82d56013Sjoerg     return stable_hash_combine(MO.getType(), MO.getTargetFlags(),
139*82d56013Sjoerg                                MO.getCFIIndex());
140*82d56013Sjoerg   case MachineOperand::MO_IntrinsicID:
141*82d56013Sjoerg     return stable_hash_combine(MO.getType(), MO.getTargetFlags(),
142*82d56013Sjoerg                                MO.getIntrinsicID());
143*82d56013Sjoerg   case MachineOperand::MO_Predicate:
144*82d56013Sjoerg     return stable_hash_combine(MO.getType(), MO.getTargetFlags(),
145*82d56013Sjoerg                                MO.getPredicate());
146*82d56013Sjoerg   }
147*82d56013Sjoerg   llvm_unreachable("Invalid machine operand type");
148*82d56013Sjoerg }
149*82d56013Sjoerg 
150*82d56013Sjoerg /// A stable hash value for machine instructions.
151*82d56013Sjoerg /// Returns 0 if no stable hash could be computed.
152*82d56013Sjoerg /// The hashing and equality testing functions ignore definitions so this is
153*82d56013Sjoerg /// useful for CSE, etc.
stableHashValue(const MachineInstr & MI,bool HashVRegs,bool HashConstantPoolIndices,bool HashMemOperands)154*82d56013Sjoerg stable_hash llvm::stableHashValue(const MachineInstr &MI, bool HashVRegs,
155*82d56013Sjoerg                                   bool HashConstantPoolIndices,
156*82d56013Sjoerg                                   bool HashMemOperands) {
157*82d56013Sjoerg   // Build up a buffer of hash code components.
158*82d56013Sjoerg   SmallVector<stable_hash, 16> HashComponents;
159*82d56013Sjoerg   HashComponents.reserve(MI.getNumOperands() + MI.getNumMemOperands() + 2);
160*82d56013Sjoerg   HashComponents.push_back(MI.getOpcode());
161*82d56013Sjoerg   HashComponents.push_back(MI.getFlags());
162*82d56013Sjoerg   for (const MachineOperand &MO : MI.operands()) {
163*82d56013Sjoerg     if (!HashVRegs && MO.isReg() && MO.isDef() &&
164*82d56013Sjoerg         Register::isVirtualRegister(MO.getReg()))
165*82d56013Sjoerg       continue; // Skip virtual register defs.
166*82d56013Sjoerg 
167*82d56013Sjoerg     if (MO.isCPI()) {
168*82d56013Sjoerg       HashComponents.push_back(stable_hash_combine(
169*82d56013Sjoerg           MO.getType(), MO.getTargetFlags(), MO.getIndex()));
170*82d56013Sjoerg       continue;
171*82d56013Sjoerg     }
172*82d56013Sjoerg 
173*82d56013Sjoerg     stable_hash StableHash = stableHashValue(MO);
174*82d56013Sjoerg     if (!StableHash)
175*82d56013Sjoerg       return 0;
176*82d56013Sjoerg     HashComponents.push_back(StableHash);
177*82d56013Sjoerg   }
178*82d56013Sjoerg 
179*82d56013Sjoerg   for (const auto *Op : MI.memoperands()) {
180*82d56013Sjoerg     if (!HashMemOperands)
181*82d56013Sjoerg       break;
182*82d56013Sjoerg     HashComponents.push_back(static_cast<unsigned>(Op->getSize()));
183*82d56013Sjoerg     HashComponents.push_back(static_cast<unsigned>(Op->getFlags()));
184*82d56013Sjoerg     HashComponents.push_back(static_cast<unsigned>(Op->getOffset()));
185*82d56013Sjoerg     HashComponents.push_back(static_cast<unsigned>(Op->getOrdering()));
186*82d56013Sjoerg     HashComponents.push_back(static_cast<unsigned>(Op->getAddrSpace()));
187*82d56013Sjoerg     HashComponents.push_back(static_cast<unsigned>(Op->getSyncScopeID()));
188*82d56013Sjoerg     HashComponents.push_back(static_cast<unsigned>(Op->getBaseAlign().value()));
189*82d56013Sjoerg     HashComponents.push_back(static_cast<unsigned>(Op->getFailureOrdering()));
190*82d56013Sjoerg   }
191*82d56013Sjoerg 
192*82d56013Sjoerg   return stable_hash_combine_range(HashComponents.begin(),
193*82d56013Sjoerg                                    HashComponents.end());
194*82d56013Sjoerg }
195