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