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" 1581ad6265SDimitry Andric #include "llvm/ADT/APFloat.h" 1681ad6265SDimitry Andric #include "llvm/ADT/APInt.h" 1781ad6265SDimitry Andric #include "llvm/ADT/Hashing.h" 1881ad6265SDimitry Andric #include "llvm/ADT/STLExtras.h" 1981ad6265SDimitry Andric #include "llvm/ADT/SmallVector.h" 205f757f3fSDimitry Andric #include "llvm/ADT/StableHashing.h" 21e8d8bef9SDimitry Andric #include "llvm/ADT/Statistic.h" 2281ad6265SDimitry Andric #include "llvm/ADT/ilist_iterator.h" 2381ad6265SDimitry Andric #include "llvm/CodeGen/MachineBasicBlock.h" 2481ad6265SDimitry Andric #include "llvm/CodeGen/MachineFunction.h" 25e8d8bef9SDimitry Andric #include "llvm/CodeGen/MachineInstr.h" 2681ad6265SDimitry Andric #include "llvm/CodeGen/MachineInstrBundleIterator.h" 2781ad6265SDimitry Andric #include "llvm/CodeGen/MachineMemOperand.h" 28e8d8bef9SDimitry Andric #include "llvm/CodeGen/MachineOperand.h" 29e8d8bef9SDimitry Andric #include "llvm/CodeGen/MachineRegisterInfo.h" 3081ad6265SDimitry Andric #include "llvm/CodeGen/Register.h" 31e8d8bef9SDimitry Andric #include "llvm/Config/llvm-config.h" 32e8d8bef9SDimitry Andric #include "llvm/IR/Constants.h" 3381ad6265SDimitry Andric #include "llvm/MC/MCSymbol.h" 3481ad6265SDimitry Andric #include "llvm/Support/Alignment.h" 3581ad6265SDimitry Andric #include "llvm/Support/ErrorHandling.h" 36e8d8bef9SDimitry Andric 37e8d8bef9SDimitry Andric #define DEBUG_TYPE "machine-stable-hash" 38e8d8bef9SDimitry Andric 39e8d8bef9SDimitry Andric using namespace llvm; 40e8d8bef9SDimitry Andric 41e8d8bef9SDimitry Andric STATISTIC(StableHashBailingMachineBasicBlock, 42e8d8bef9SDimitry Andric "Number of encountered unsupported MachineOperands that were " 43e8d8bef9SDimitry Andric "MachineBasicBlocks while computing stable hashes"); 44e8d8bef9SDimitry Andric STATISTIC(StableHashBailingConstantPoolIndex, 45e8d8bef9SDimitry Andric "Number of encountered unsupported MachineOperands that were " 46e8d8bef9SDimitry Andric "ConstantPoolIndex while computing stable hashes"); 47e8d8bef9SDimitry Andric STATISTIC(StableHashBailingTargetIndexNoName, 48e8d8bef9SDimitry Andric "Number of encountered unsupported MachineOperands that were " 49e8d8bef9SDimitry Andric "TargetIndex with no name"); 50e8d8bef9SDimitry Andric STATISTIC(StableHashBailingGlobalAddress, 51e8d8bef9SDimitry Andric "Number of encountered unsupported MachineOperands that were " 52e8d8bef9SDimitry Andric "GlobalAddress while computing stable hashes"); 53e8d8bef9SDimitry Andric STATISTIC(StableHashBailingBlockAddress, 54e8d8bef9SDimitry Andric "Number of encountered unsupported MachineOperands that were " 55e8d8bef9SDimitry Andric "BlockAddress while computing stable hashes"); 56e8d8bef9SDimitry Andric STATISTIC(StableHashBailingMetadataUnsupported, 57e8d8bef9SDimitry Andric "Number of encountered unsupported MachineOperands that were " 58e8d8bef9SDimitry Andric "Metadata of an unsupported kind while computing stable hashes"); 59e8d8bef9SDimitry Andric 60e8d8bef9SDimitry Andric stable_hash llvm::stableHashValue(const MachineOperand &MO) { 61e8d8bef9SDimitry Andric switch (MO.getType()) { 62e8d8bef9SDimitry Andric case MachineOperand::MO_Register: 63bdd1243dSDimitry Andric if (MO.getReg().isVirtual()) { 64e8d8bef9SDimitry Andric const MachineRegisterInfo &MRI = MO.getParent()->getMF()->getRegInfo(); 6581ad6265SDimitry Andric SmallVector<unsigned> DefOpcodes; 6681ad6265SDimitry Andric for (auto &Def : MRI.def_instructions(MO.getReg())) 6781ad6265SDimitry Andric DefOpcodes.push_back(Def.getOpcode()); 6881ad6265SDimitry Andric return hash_combine_range(DefOpcodes.begin(), DefOpcodes.end()); 69e8d8bef9SDimitry Andric } 70e8d8bef9SDimitry Andric 71e8d8bef9SDimitry Andric // Register operands don't have target flags. 72e8d8bef9SDimitry Andric return stable_hash_combine(MO.getType(), MO.getReg(), MO.getSubReg(), 73e8d8bef9SDimitry Andric MO.isDef()); 74e8d8bef9SDimitry Andric case MachineOperand::MO_Immediate: 75e8d8bef9SDimitry Andric return stable_hash_combine(MO.getType(), MO.getTargetFlags(), MO.getImm()); 76e8d8bef9SDimitry Andric case MachineOperand::MO_CImmediate: 77e8d8bef9SDimitry Andric case MachineOperand::MO_FPImmediate: { 78e8d8bef9SDimitry Andric auto Val = MO.isCImm() ? MO.getCImm()->getValue() 79e8d8bef9SDimitry Andric : MO.getFPImm()->getValueAPF().bitcastToAPInt(); 80e8d8bef9SDimitry Andric auto ValHash = 81e8d8bef9SDimitry Andric stable_hash_combine_array(Val.getRawData(), Val.getNumWords()); 82e8d8bef9SDimitry Andric return hash_combine(MO.getType(), MO.getTargetFlags(), ValHash); 83e8d8bef9SDimitry Andric } 84e8d8bef9SDimitry Andric 85e8d8bef9SDimitry Andric case MachineOperand::MO_MachineBasicBlock: 86e8d8bef9SDimitry Andric StableHashBailingMachineBasicBlock++; 87e8d8bef9SDimitry Andric return 0; 88e8d8bef9SDimitry Andric case MachineOperand::MO_ConstantPoolIndex: 89e8d8bef9SDimitry Andric StableHashBailingConstantPoolIndex++; 90e8d8bef9SDimitry Andric return 0; 91e8d8bef9SDimitry Andric case MachineOperand::MO_BlockAddress: 92e8d8bef9SDimitry Andric StableHashBailingBlockAddress++; 93e8d8bef9SDimitry Andric return 0; 94e8d8bef9SDimitry Andric case MachineOperand::MO_Metadata: 95e8d8bef9SDimitry Andric StableHashBailingMetadataUnsupported++; 96e8d8bef9SDimitry Andric return 0; 97e8d8bef9SDimitry Andric case MachineOperand::MO_GlobalAddress: 98e8d8bef9SDimitry Andric StableHashBailingGlobalAddress++; 99e8d8bef9SDimitry Andric return 0; 100e8d8bef9SDimitry Andric case MachineOperand::MO_TargetIndex: { 101e8d8bef9SDimitry Andric if (const char *Name = MO.getTargetIndexName()) 102e8d8bef9SDimitry Andric return stable_hash_combine(MO.getType(), MO.getTargetFlags(), 103e8d8bef9SDimitry Andric stable_hash_combine_string(Name), 104e8d8bef9SDimitry Andric MO.getOffset()); 105e8d8bef9SDimitry Andric StableHashBailingTargetIndexNoName++; 106e8d8bef9SDimitry Andric return 0; 107e8d8bef9SDimitry Andric } 108e8d8bef9SDimitry Andric 109e8d8bef9SDimitry Andric case MachineOperand::MO_FrameIndex: 110e8d8bef9SDimitry Andric case MachineOperand::MO_JumpTableIndex: 111e8d8bef9SDimitry Andric return stable_hash_combine(MO.getType(), MO.getTargetFlags(), 112e8d8bef9SDimitry Andric MO.getIndex()); 113e8d8bef9SDimitry Andric 114e8d8bef9SDimitry Andric case MachineOperand::MO_ExternalSymbol: 115e8d8bef9SDimitry Andric return hash_combine(MO.getType(), MO.getTargetFlags(), MO.getOffset(), 116e8d8bef9SDimitry Andric stable_hash_combine_string(MO.getSymbolName())); 117e8d8bef9SDimitry Andric 118e8d8bef9SDimitry Andric case MachineOperand::MO_RegisterMask: 119bdd1243dSDimitry Andric case MachineOperand::MO_RegisterLiveOut: { 120bdd1243dSDimitry Andric if (const MachineInstr *MI = MO.getParent()) { 121bdd1243dSDimitry Andric if (const MachineBasicBlock *MBB = MI->getParent()) { 122bdd1243dSDimitry Andric if (const MachineFunction *MF = MBB->getParent()) { 123bdd1243dSDimitry Andric const TargetRegisterInfo *TRI = MF->getSubtarget().getRegisterInfo(); 124bdd1243dSDimitry Andric unsigned RegMaskSize = 125bdd1243dSDimitry Andric MachineOperand::getRegMaskSize(TRI->getNumRegs()); 126bdd1243dSDimitry Andric const uint32_t *RegMask = MO.getRegMask(); 127bdd1243dSDimitry Andric std::vector<llvm::stable_hash> RegMaskHashes(RegMask, 128bdd1243dSDimitry Andric RegMask + RegMaskSize); 129bdd1243dSDimitry Andric return hash_combine(MO.getType(), MO.getTargetFlags(), 130bdd1243dSDimitry Andric stable_hash_combine_array(RegMaskHashes.data(), 131bdd1243dSDimitry Andric RegMaskHashes.size())); 132bdd1243dSDimitry Andric } 133bdd1243dSDimitry Andric } 134bdd1243dSDimitry Andric } 135bdd1243dSDimitry Andric 136bdd1243dSDimitry Andric assert(0 && "MachineOperand not associated with any MachineFunction"); 137bdd1243dSDimitry Andric return hash_combine(MO.getType(), MO.getTargetFlags()); 138bdd1243dSDimitry Andric } 139e8d8bef9SDimitry Andric 140e8d8bef9SDimitry Andric case MachineOperand::MO_ShuffleMask: { 141e8d8bef9SDimitry Andric std::vector<llvm::stable_hash> ShuffleMaskHashes; 142e8d8bef9SDimitry Andric 143e8d8bef9SDimitry Andric llvm::transform( 144e8d8bef9SDimitry Andric MO.getShuffleMask(), std::back_inserter(ShuffleMaskHashes), 145e8d8bef9SDimitry Andric [](int S) -> llvm::stable_hash { return llvm::stable_hash(S); }); 146e8d8bef9SDimitry Andric 147e8d8bef9SDimitry Andric return hash_combine(MO.getType(), MO.getTargetFlags(), 148e8d8bef9SDimitry Andric stable_hash_combine_array(ShuffleMaskHashes.data(), 149e8d8bef9SDimitry Andric ShuffleMaskHashes.size())); 150e8d8bef9SDimitry Andric } 151e8d8bef9SDimitry Andric case MachineOperand::MO_MCSymbol: { 152e8d8bef9SDimitry Andric auto SymbolName = MO.getMCSymbol()->getName(); 153e8d8bef9SDimitry Andric return hash_combine(MO.getType(), MO.getTargetFlags(), 154e8d8bef9SDimitry Andric stable_hash_combine_string(SymbolName)); 155e8d8bef9SDimitry Andric } 156e8d8bef9SDimitry Andric case MachineOperand::MO_CFIIndex: 157e8d8bef9SDimitry Andric return stable_hash_combine(MO.getType(), MO.getTargetFlags(), 158e8d8bef9SDimitry Andric MO.getCFIIndex()); 159e8d8bef9SDimitry Andric case MachineOperand::MO_IntrinsicID: 160e8d8bef9SDimitry Andric return stable_hash_combine(MO.getType(), MO.getTargetFlags(), 161e8d8bef9SDimitry Andric MO.getIntrinsicID()); 162e8d8bef9SDimitry Andric case MachineOperand::MO_Predicate: 163e8d8bef9SDimitry Andric return stable_hash_combine(MO.getType(), MO.getTargetFlags(), 164e8d8bef9SDimitry Andric MO.getPredicate()); 165bdd1243dSDimitry Andric case MachineOperand::MO_DbgInstrRef: 166bdd1243dSDimitry Andric return stable_hash_combine(MO.getType(), MO.getInstrRefInstrIndex(), 167bdd1243dSDimitry Andric MO.getInstrRefOpIndex()); 168e8d8bef9SDimitry Andric } 169e8d8bef9SDimitry Andric llvm_unreachable("Invalid machine operand type"); 170e8d8bef9SDimitry Andric } 171e8d8bef9SDimitry Andric 172e8d8bef9SDimitry Andric /// A stable hash value for machine instructions. 173e8d8bef9SDimitry Andric /// Returns 0 if no stable hash could be computed. 174e8d8bef9SDimitry Andric /// The hashing and equality testing functions ignore definitions so this is 175e8d8bef9SDimitry Andric /// useful for CSE, etc. 176e8d8bef9SDimitry Andric stable_hash llvm::stableHashValue(const MachineInstr &MI, bool HashVRegs, 177e8d8bef9SDimitry Andric bool HashConstantPoolIndices, 178e8d8bef9SDimitry Andric bool HashMemOperands) { 179e8d8bef9SDimitry Andric // Build up a buffer of hash code components. 180e8d8bef9SDimitry Andric SmallVector<stable_hash, 16> HashComponents; 181e8d8bef9SDimitry Andric HashComponents.reserve(MI.getNumOperands() + MI.getNumMemOperands() + 2); 182e8d8bef9SDimitry Andric HashComponents.push_back(MI.getOpcode()); 183e8d8bef9SDimitry Andric HashComponents.push_back(MI.getFlags()); 184e8d8bef9SDimitry Andric for (const MachineOperand &MO : MI.operands()) { 185bdd1243dSDimitry Andric if (!HashVRegs && MO.isReg() && MO.isDef() && MO.getReg().isVirtual()) 186e8d8bef9SDimitry Andric continue; // Skip virtual register defs. 187e8d8bef9SDimitry Andric 188e8d8bef9SDimitry Andric if (MO.isCPI()) { 189e8d8bef9SDimitry Andric HashComponents.push_back(stable_hash_combine( 190e8d8bef9SDimitry Andric MO.getType(), MO.getTargetFlags(), MO.getIndex())); 191e8d8bef9SDimitry Andric continue; 192e8d8bef9SDimitry Andric } 193e8d8bef9SDimitry Andric 194e8d8bef9SDimitry Andric stable_hash StableHash = stableHashValue(MO); 195e8d8bef9SDimitry Andric if (!StableHash) 196e8d8bef9SDimitry Andric return 0; 197e8d8bef9SDimitry Andric HashComponents.push_back(StableHash); 198e8d8bef9SDimitry Andric } 199e8d8bef9SDimitry Andric 200e8d8bef9SDimitry Andric for (const auto *Op : MI.memoperands()) { 201e8d8bef9SDimitry Andric if (!HashMemOperands) 202e8d8bef9SDimitry Andric break; 203*0fca6ea1SDimitry Andric HashComponents.push_back(static_cast<unsigned>(Op->getSize().getValue())); 204e8d8bef9SDimitry Andric HashComponents.push_back(static_cast<unsigned>(Op->getFlags())); 205e8d8bef9SDimitry Andric HashComponents.push_back(static_cast<unsigned>(Op->getOffset())); 206fe6060f1SDimitry Andric HashComponents.push_back(static_cast<unsigned>(Op->getSuccessOrdering())); 207e8d8bef9SDimitry Andric HashComponents.push_back(static_cast<unsigned>(Op->getAddrSpace())); 208e8d8bef9SDimitry Andric HashComponents.push_back(static_cast<unsigned>(Op->getSyncScopeID())); 209e8d8bef9SDimitry Andric HashComponents.push_back(static_cast<unsigned>(Op->getBaseAlign().value())); 210e8d8bef9SDimitry Andric HashComponents.push_back(static_cast<unsigned>(Op->getFailureOrdering())); 211e8d8bef9SDimitry Andric } 212e8d8bef9SDimitry Andric 213e8d8bef9SDimitry Andric return stable_hash_combine_range(HashComponents.begin(), 214e8d8bef9SDimitry Andric HashComponents.end()); 215e8d8bef9SDimitry Andric } 21681ad6265SDimitry Andric 21781ad6265SDimitry Andric stable_hash llvm::stableHashValue(const MachineBasicBlock &MBB) { 21881ad6265SDimitry Andric SmallVector<stable_hash> HashComponents; 21981ad6265SDimitry Andric // TODO: Hash more stuff like block alignment and branch probabilities. 220fcaf7f86SDimitry Andric for (const auto &MI : MBB) 22181ad6265SDimitry Andric HashComponents.push_back(stableHashValue(MI)); 22281ad6265SDimitry Andric return stable_hash_combine_range(HashComponents.begin(), 22381ad6265SDimitry Andric HashComponents.end()); 22481ad6265SDimitry Andric } 22581ad6265SDimitry Andric 22681ad6265SDimitry Andric stable_hash llvm::stableHashValue(const MachineFunction &MF) { 22781ad6265SDimitry Andric SmallVector<stable_hash> HashComponents; 22881ad6265SDimitry Andric // TODO: Hash lots more stuff like function alignment and stack objects. 229fcaf7f86SDimitry Andric for (const auto &MBB : MF) 23081ad6265SDimitry Andric HashComponents.push_back(stableHashValue(MBB)); 23181ad6265SDimitry Andric return stable_hash_combine_range(HashComponents.begin(), 23281ad6265SDimitry Andric HashComponents.end()); 23381ad6265SDimitry Andric } 234