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