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/ArrayRef.h" 1881ad6265SDimitry Andric #include "llvm/ADT/DenseMapInfo.h" 1981ad6265SDimitry Andric #include "llvm/ADT/Hashing.h" 2081ad6265SDimitry Andric #include "llvm/ADT/STLExtras.h" 2181ad6265SDimitry Andric #include "llvm/ADT/SmallVector.h" 22e8d8bef9SDimitry Andric #include "llvm/ADT/Statistic.h" 2381ad6265SDimitry Andric #include "llvm/ADT/ilist_iterator.h" 2481ad6265SDimitry Andric #include "llvm/ADT/iterator_range.h" 2581ad6265SDimitry Andric #include "llvm/CodeGen/MachineBasicBlock.h" 2681ad6265SDimitry Andric #include "llvm/CodeGen/MachineFunction.h" 27e8d8bef9SDimitry Andric #include "llvm/CodeGen/MachineInstr.h" 2881ad6265SDimitry Andric #include "llvm/CodeGen/MachineInstrBundleIterator.h" 2981ad6265SDimitry Andric #include "llvm/CodeGen/MachineMemOperand.h" 30e8d8bef9SDimitry Andric #include "llvm/CodeGen/MachineOperand.h" 31e8d8bef9SDimitry Andric #include "llvm/CodeGen/MachineRegisterInfo.h" 3281ad6265SDimitry 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" 3681ad6265SDimitry Andric #include "llvm/MC/MCSymbol.h" 3781ad6265SDimitry Andric #include "llvm/Support/Alignment.h" 3881ad6265SDimitry 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: 66*bdd1243dSDimitry Andric if (MO.getReg().isVirtual()) { 67e8d8bef9SDimitry Andric const MachineRegisterInfo &MRI = MO.getParent()->getMF()->getRegInfo(); 6881ad6265SDimitry Andric SmallVector<unsigned> DefOpcodes; 6981ad6265SDimitry Andric for (auto &Def : MRI.def_instructions(MO.getReg())) 7081ad6265SDimitry Andric DefOpcodes.push_back(Def.getOpcode()); 7181ad6265SDimitry 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: 122*bdd1243dSDimitry Andric case MachineOperand::MO_RegisterLiveOut: { 123*bdd1243dSDimitry Andric if (const MachineInstr *MI = MO.getParent()) { 124*bdd1243dSDimitry Andric if (const MachineBasicBlock *MBB = MI->getParent()) { 125*bdd1243dSDimitry Andric if (const MachineFunction *MF = MBB->getParent()) { 126*bdd1243dSDimitry Andric const TargetRegisterInfo *TRI = MF->getSubtarget().getRegisterInfo(); 127*bdd1243dSDimitry Andric unsigned RegMaskSize = 128*bdd1243dSDimitry Andric MachineOperand::getRegMaskSize(TRI->getNumRegs()); 129*bdd1243dSDimitry Andric const uint32_t *RegMask = MO.getRegMask(); 130*bdd1243dSDimitry Andric std::vector<llvm::stable_hash> RegMaskHashes(RegMask, 131*bdd1243dSDimitry Andric RegMask + RegMaskSize); 132*bdd1243dSDimitry Andric return hash_combine(MO.getType(), MO.getTargetFlags(), 133*bdd1243dSDimitry Andric stable_hash_combine_array(RegMaskHashes.data(), 134*bdd1243dSDimitry Andric RegMaskHashes.size())); 135*bdd1243dSDimitry Andric } 136*bdd1243dSDimitry Andric } 137*bdd1243dSDimitry Andric } 138*bdd1243dSDimitry Andric 139*bdd1243dSDimitry Andric assert(0 && "MachineOperand not associated with any MachineFunction"); 140*bdd1243dSDimitry Andric return hash_combine(MO.getType(), MO.getTargetFlags()); 141*bdd1243dSDimitry Andric } 142e8d8bef9SDimitry Andric 143e8d8bef9SDimitry Andric case MachineOperand::MO_ShuffleMask: { 144e8d8bef9SDimitry Andric std::vector<llvm::stable_hash> ShuffleMaskHashes; 145e8d8bef9SDimitry Andric 146e8d8bef9SDimitry Andric llvm::transform( 147e8d8bef9SDimitry Andric MO.getShuffleMask(), std::back_inserter(ShuffleMaskHashes), 148e8d8bef9SDimitry Andric [](int S) -> llvm::stable_hash { return llvm::stable_hash(S); }); 149e8d8bef9SDimitry Andric 150e8d8bef9SDimitry Andric return hash_combine(MO.getType(), MO.getTargetFlags(), 151e8d8bef9SDimitry Andric stable_hash_combine_array(ShuffleMaskHashes.data(), 152e8d8bef9SDimitry Andric ShuffleMaskHashes.size())); 153e8d8bef9SDimitry Andric } 154e8d8bef9SDimitry Andric case MachineOperand::MO_MCSymbol: { 155e8d8bef9SDimitry Andric auto SymbolName = MO.getMCSymbol()->getName(); 156e8d8bef9SDimitry Andric return hash_combine(MO.getType(), MO.getTargetFlags(), 157e8d8bef9SDimitry Andric stable_hash_combine_string(SymbolName)); 158e8d8bef9SDimitry Andric } 159e8d8bef9SDimitry Andric case MachineOperand::MO_CFIIndex: 160e8d8bef9SDimitry Andric return stable_hash_combine(MO.getType(), MO.getTargetFlags(), 161e8d8bef9SDimitry Andric MO.getCFIIndex()); 162e8d8bef9SDimitry Andric case MachineOperand::MO_IntrinsicID: 163e8d8bef9SDimitry Andric return stable_hash_combine(MO.getType(), MO.getTargetFlags(), 164e8d8bef9SDimitry Andric MO.getIntrinsicID()); 165e8d8bef9SDimitry Andric case MachineOperand::MO_Predicate: 166e8d8bef9SDimitry Andric return stable_hash_combine(MO.getType(), MO.getTargetFlags(), 167e8d8bef9SDimitry Andric MO.getPredicate()); 168*bdd1243dSDimitry Andric case MachineOperand::MO_DbgInstrRef: 169*bdd1243dSDimitry Andric return stable_hash_combine(MO.getType(), MO.getInstrRefInstrIndex(), 170*bdd1243dSDimitry Andric MO.getInstrRefOpIndex()); 171e8d8bef9SDimitry Andric } 172e8d8bef9SDimitry Andric llvm_unreachable("Invalid machine operand type"); 173e8d8bef9SDimitry Andric } 174e8d8bef9SDimitry Andric 175e8d8bef9SDimitry Andric /// A stable hash value for machine instructions. 176e8d8bef9SDimitry Andric /// Returns 0 if no stable hash could be computed. 177e8d8bef9SDimitry Andric /// The hashing and equality testing functions ignore definitions so this is 178e8d8bef9SDimitry Andric /// useful for CSE, etc. 179e8d8bef9SDimitry Andric stable_hash llvm::stableHashValue(const MachineInstr &MI, bool HashVRegs, 180e8d8bef9SDimitry Andric bool HashConstantPoolIndices, 181e8d8bef9SDimitry Andric bool HashMemOperands) { 182e8d8bef9SDimitry Andric // Build up a buffer of hash code components. 183e8d8bef9SDimitry Andric SmallVector<stable_hash, 16> HashComponents; 184e8d8bef9SDimitry Andric HashComponents.reserve(MI.getNumOperands() + MI.getNumMemOperands() + 2); 185e8d8bef9SDimitry Andric HashComponents.push_back(MI.getOpcode()); 186e8d8bef9SDimitry Andric HashComponents.push_back(MI.getFlags()); 187e8d8bef9SDimitry Andric for (const MachineOperand &MO : MI.operands()) { 188*bdd1243dSDimitry Andric if (!HashVRegs && MO.isReg() && MO.isDef() && MO.getReg().isVirtual()) 189e8d8bef9SDimitry Andric continue; // Skip virtual register defs. 190e8d8bef9SDimitry Andric 191e8d8bef9SDimitry Andric if (MO.isCPI()) { 192e8d8bef9SDimitry Andric HashComponents.push_back(stable_hash_combine( 193e8d8bef9SDimitry Andric MO.getType(), MO.getTargetFlags(), MO.getIndex())); 194e8d8bef9SDimitry Andric continue; 195e8d8bef9SDimitry Andric } 196e8d8bef9SDimitry Andric 197e8d8bef9SDimitry Andric stable_hash StableHash = stableHashValue(MO); 198e8d8bef9SDimitry Andric if (!StableHash) 199e8d8bef9SDimitry Andric return 0; 200e8d8bef9SDimitry Andric HashComponents.push_back(StableHash); 201e8d8bef9SDimitry Andric } 202e8d8bef9SDimitry Andric 203e8d8bef9SDimitry Andric for (const auto *Op : MI.memoperands()) { 204e8d8bef9SDimitry Andric if (!HashMemOperands) 205e8d8bef9SDimitry Andric break; 206e8d8bef9SDimitry Andric HashComponents.push_back(static_cast<unsigned>(Op->getSize())); 207e8d8bef9SDimitry Andric HashComponents.push_back(static_cast<unsigned>(Op->getFlags())); 208e8d8bef9SDimitry Andric HashComponents.push_back(static_cast<unsigned>(Op->getOffset())); 209fe6060f1SDimitry Andric HashComponents.push_back(static_cast<unsigned>(Op->getSuccessOrdering())); 210e8d8bef9SDimitry Andric HashComponents.push_back(static_cast<unsigned>(Op->getAddrSpace())); 211e8d8bef9SDimitry Andric HashComponents.push_back(static_cast<unsigned>(Op->getSyncScopeID())); 212e8d8bef9SDimitry Andric HashComponents.push_back(static_cast<unsigned>(Op->getBaseAlign().value())); 213e8d8bef9SDimitry Andric HashComponents.push_back(static_cast<unsigned>(Op->getFailureOrdering())); 214e8d8bef9SDimitry Andric } 215e8d8bef9SDimitry Andric 216e8d8bef9SDimitry Andric return stable_hash_combine_range(HashComponents.begin(), 217e8d8bef9SDimitry Andric HashComponents.end()); 218e8d8bef9SDimitry Andric } 21981ad6265SDimitry Andric 22081ad6265SDimitry Andric stable_hash llvm::stableHashValue(const MachineBasicBlock &MBB) { 22181ad6265SDimitry Andric SmallVector<stable_hash> HashComponents; 22281ad6265SDimitry Andric // TODO: Hash more stuff like block alignment and branch probabilities. 223fcaf7f86SDimitry Andric for (const auto &MI : MBB) 22481ad6265SDimitry Andric HashComponents.push_back(stableHashValue(MI)); 22581ad6265SDimitry Andric return stable_hash_combine_range(HashComponents.begin(), 22681ad6265SDimitry Andric HashComponents.end()); 22781ad6265SDimitry Andric } 22881ad6265SDimitry Andric 22981ad6265SDimitry Andric stable_hash llvm::stableHashValue(const MachineFunction &MF) { 23081ad6265SDimitry Andric SmallVector<stable_hash> HashComponents; 23181ad6265SDimitry Andric // TODO: Hash lots more stuff like function alignment and stack objects. 232fcaf7f86SDimitry Andric for (const auto &MBB : MF) 23381ad6265SDimitry Andric HashComponents.push_back(stableHashValue(MBB)); 23481ad6265SDimitry Andric return stable_hash_combine_range(HashComponents.begin(), 23581ad6265SDimitry Andric HashComponents.end()); 23681ad6265SDimitry Andric } 237