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