17fff1fbdSPuyan Lotfi //===- lib/CodeGen/MachineStableHash.cpp ----------------------------------===// 27fff1fbdSPuyan Lotfi // 37fff1fbdSPuyan Lotfi // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 47fff1fbdSPuyan Lotfi // See https://llvm.org/LICENSE.txt for license information. 57fff1fbdSPuyan Lotfi // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 67fff1fbdSPuyan Lotfi // 77fff1fbdSPuyan Lotfi //===----------------------------------------------------------------------===// 87fff1fbdSPuyan Lotfi // 97fff1fbdSPuyan Lotfi // Stable hashing for MachineInstr and MachineOperand. Useful or getting a 107fff1fbdSPuyan Lotfi // hash across runs, modules, etc. 117fff1fbdSPuyan Lotfi // 127fff1fbdSPuyan Lotfi //===----------------------------------------------------------------------===// 137fff1fbdSPuyan Lotfi 147fff1fbdSPuyan Lotfi #include "llvm/CodeGen/MachineStableHash.h" 157fff1fbdSPuyan Lotfi #include "llvm/ADT/FoldingSet.h" 167fff1fbdSPuyan Lotfi #include "llvm/ADT/Statistic.h" 177fff1fbdSPuyan Lotfi #include "llvm/ADT/StringExtras.h" 187fff1fbdSPuyan Lotfi #include "llvm/Analysis/Loads.h" 197fff1fbdSPuyan Lotfi #include "llvm/Analysis/MemoryLocation.h" 207fff1fbdSPuyan Lotfi #include "llvm/CodeGen/MIRFormatter.h" 217fff1fbdSPuyan Lotfi #include "llvm/CodeGen/MIRPrinter.h" 227fff1fbdSPuyan Lotfi #include "llvm/CodeGen/MachineFrameInfo.h" 236670f5d1SSimon Pilgrim #include "llvm/CodeGen/MachineInstr.h" 247fff1fbdSPuyan Lotfi #include "llvm/CodeGen/MachineJumpTableInfo.h" 257fff1fbdSPuyan Lotfi #include "llvm/CodeGen/MachineOperand.h" 267fff1fbdSPuyan Lotfi #include "llvm/CodeGen/MachineRegisterInfo.h" 277fff1fbdSPuyan Lotfi #include "llvm/CodeGen/StableHashing.h" 287fff1fbdSPuyan Lotfi #include "llvm/CodeGen/TargetInstrInfo.h" 297fff1fbdSPuyan Lotfi #include "llvm/CodeGen/TargetRegisterInfo.h" 307fff1fbdSPuyan Lotfi #include "llvm/Config/llvm-config.h" 317fff1fbdSPuyan Lotfi #include "llvm/IR/Constants.h" 327fff1fbdSPuyan Lotfi #include "llvm/IR/IRPrintingPasses.h" 337fff1fbdSPuyan Lotfi #include "llvm/IR/Instructions.h" 347fff1fbdSPuyan Lotfi #include "llvm/IR/ModuleSlotTracker.h" 357fff1fbdSPuyan Lotfi #include "llvm/MC/MCDwarf.h" 367fff1fbdSPuyan Lotfi #include "llvm/Target/TargetIntrinsicInfo.h" 377fff1fbdSPuyan Lotfi #include "llvm/Target/TargetMachine.h" 387fff1fbdSPuyan Lotfi 397fff1fbdSPuyan Lotfi #define DEBUG_TYPE "machine-stable-hash" 407fff1fbdSPuyan Lotfi 417fff1fbdSPuyan Lotfi using namespace llvm; 427fff1fbdSPuyan Lotfi 437fff1fbdSPuyan Lotfi STATISTIC(StableHashBailingMachineBasicBlock, 447fff1fbdSPuyan Lotfi "Number of encountered unsupported MachineOperands that were " 457fff1fbdSPuyan Lotfi "MachineBasicBlocks while computing stable hashes"); 467fff1fbdSPuyan Lotfi STATISTIC(StableHashBailingConstantPoolIndex, 477fff1fbdSPuyan Lotfi "Number of encountered unsupported MachineOperands that were " 487fff1fbdSPuyan Lotfi "ConstantPoolIndex while computing stable hashes"); 497fff1fbdSPuyan Lotfi STATISTIC(StableHashBailingTargetIndexNoName, 507fff1fbdSPuyan Lotfi "Number of encountered unsupported MachineOperands that were " 517fff1fbdSPuyan Lotfi "TargetIndex with no name"); 527fff1fbdSPuyan Lotfi STATISTIC(StableHashBailingGlobalAddress, 537fff1fbdSPuyan Lotfi "Number of encountered unsupported MachineOperands that were " 547fff1fbdSPuyan Lotfi "GlobalAddress while computing stable hashes"); 557fff1fbdSPuyan Lotfi STATISTIC(StableHashBailingBlockAddress, 567fff1fbdSPuyan Lotfi "Number of encountered unsupported MachineOperands that were " 577fff1fbdSPuyan Lotfi "BlockAddress while computing stable hashes"); 587fff1fbdSPuyan Lotfi STATISTIC(StableHashBailingMetadataUnsupported, 597fff1fbdSPuyan Lotfi "Number of encountered unsupported MachineOperands that were " 607fff1fbdSPuyan Lotfi "Metadata of an unsupported kind while computing stable hashes"); 617fff1fbdSPuyan Lotfi 627fff1fbdSPuyan Lotfi stable_hash llvm::stableHashValue(const MachineOperand &MO) { 637fff1fbdSPuyan Lotfi switch (MO.getType()) { 647fff1fbdSPuyan Lotfi case MachineOperand::MO_Register: 657fff1fbdSPuyan Lotfi if (Register::isVirtualRegister(MO.getReg())) { 667fff1fbdSPuyan Lotfi const MachineRegisterInfo &MRI = MO.getParent()->getMF()->getRegInfo(); 679a547e70SJay Foad SmallVector<unsigned> DefOpcodes; 689a547e70SJay Foad for (auto &Def : MRI.def_instructions(MO.getReg())) 699a547e70SJay Foad DefOpcodes.push_back(Def.getOpcode()); 709a547e70SJay Foad return hash_combine_range(DefOpcodes.begin(), DefOpcodes.end()); 717fff1fbdSPuyan Lotfi } 727fff1fbdSPuyan Lotfi 737fff1fbdSPuyan Lotfi // Register operands don't have target flags. 747fff1fbdSPuyan Lotfi return stable_hash_combine(MO.getType(), MO.getReg(), MO.getSubReg(), 757fff1fbdSPuyan Lotfi MO.isDef()); 767fff1fbdSPuyan Lotfi case MachineOperand::MO_Immediate: 777fff1fbdSPuyan Lotfi return stable_hash_combine(MO.getType(), MO.getTargetFlags(), MO.getImm()); 787fff1fbdSPuyan Lotfi case MachineOperand::MO_CImmediate: 797fff1fbdSPuyan Lotfi case MachineOperand::MO_FPImmediate: { 807fff1fbdSPuyan Lotfi auto Val = MO.isCImm() ? MO.getCImm()->getValue() 817fff1fbdSPuyan Lotfi : MO.getFPImm()->getValueAPF().bitcastToAPInt(); 827fff1fbdSPuyan Lotfi auto ValHash = 837fff1fbdSPuyan Lotfi stable_hash_combine_array(Val.getRawData(), Val.getNumWords()); 847fff1fbdSPuyan Lotfi return hash_combine(MO.getType(), MO.getTargetFlags(), ValHash); 857fff1fbdSPuyan Lotfi } 867fff1fbdSPuyan Lotfi 877fff1fbdSPuyan Lotfi case MachineOperand::MO_MachineBasicBlock: 887fff1fbdSPuyan Lotfi StableHashBailingMachineBasicBlock++; 897fff1fbdSPuyan Lotfi return 0; 907fff1fbdSPuyan Lotfi case MachineOperand::MO_ConstantPoolIndex: 917fff1fbdSPuyan Lotfi StableHashBailingConstantPoolIndex++; 927fff1fbdSPuyan Lotfi return 0; 937fff1fbdSPuyan Lotfi case MachineOperand::MO_BlockAddress: 947fff1fbdSPuyan Lotfi StableHashBailingBlockAddress++; 957fff1fbdSPuyan Lotfi return 0; 967fff1fbdSPuyan Lotfi case MachineOperand::MO_Metadata: 977fff1fbdSPuyan Lotfi StableHashBailingMetadataUnsupported++; 987fff1fbdSPuyan Lotfi return 0; 997fff1fbdSPuyan Lotfi case MachineOperand::MO_GlobalAddress: 1007fff1fbdSPuyan Lotfi StableHashBailingGlobalAddress++; 1017fff1fbdSPuyan Lotfi return 0; 1027fff1fbdSPuyan Lotfi case MachineOperand::MO_TargetIndex: { 1037fff1fbdSPuyan Lotfi if (const char *Name = MO.getTargetIndexName()) 1047fff1fbdSPuyan Lotfi return stable_hash_combine(MO.getType(), MO.getTargetFlags(), 1057fff1fbdSPuyan Lotfi stable_hash_combine_string(Name), 1067fff1fbdSPuyan Lotfi MO.getOffset()); 1077fff1fbdSPuyan Lotfi StableHashBailingTargetIndexNoName++; 1087fff1fbdSPuyan Lotfi return 0; 1097fff1fbdSPuyan Lotfi } 1107fff1fbdSPuyan Lotfi 1117fff1fbdSPuyan Lotfi case MachineOperand::MO_FrameIndex: 1127fff1fbdSPuyan Lotfi case MachineOperand::MO_JumpTableIndex: 1137fff1fbdSPuyan Lotfi return stable_hash_combine(MO.getType(), MO.getTargetFlags(), 1147fff1fbdSPuyan Lotfi MO.getIndex()); 1157fff1fbdSPuyan Lotfi 1167fff1fbdSPuyan Lotfi case MachineOperand::MO_ExternalSymbol: 1177fff1fbdSPuyan Lotfi return hash_combine(MO.getType(), MO.getTargetFlags(), MO.getOffset(), 1187fff1fbdSPuyan Lotfi stable_hash_combine_string(MO.getSymbolName())); 1197fff1fbdSPuyan Lotfi 1207fff1fbdSPuyan Lotfi case MachineOperand::MO_RegisterMask: 1217fff1fbdSPuyan Lotfi case MachineOperand::MO_RegisterLiveOut: 1227fff1fbdSPuyan Lotfi return hash_combine(MO.getType(), MO.getTargetFlags(), MO.getRegMask()); 1237fff1fbdSPuyan Lotfi 1247fff1fbdSPuyan Lotfi case MachineOperand::MO_ShuffleMask: { 1257fff1fbdSPuyan Lotfi std::vector<llvm::stable_hash> ShuffleMaskHashes; 1267fff1fbdSPuyan Lotfi 1277fff1fbdSPuyan Lotfi llvm::transform( 1287fff1fbdSPuyan Lotfi MO.getShuffleMask(), std::back_inserter(ShuffleMaskHashes), 1297fff1fbdSPuyan Lotfi [](int S) -> llvm::stable_hash { return llvm::stable_hash(S); }); 1307fff1fbdSPuyan Lotfi 1317fff1fbdSPuyan Lotfi return hash_combine(MO.getType(), MO.getTargetFlags(), 1327fff1fbdSPuyan Lotfi stable_hash_combine_array(ShuffleMaskHashes.data(), 1337fff1fbdSPuyan Lotfi ShuffleMaskHashes.size())); 1347fff1fbdSPuyan Lotfi } 1357fff1fbdSPuyan Lotfi case MachineOperand::MO_MCSymbol: { 1367fff1fbdSPuyan Lotfi auto SymbolName = MO.getMCSymbol()->getName(); 1377fff1fbdSPuyan Lotfi return hash_combine(MO.getType(), MO.getTargetFlags(), 1387fff1fbdSPuyan Lotfi stable_hash_combine_string(SymbolName)); 1397fff1fbdSPuyan Lotfi } 1407fff1fbdSPuyan Lotfi case MachineOperand::MO_CFIIndex: 1417fff1fbdSPuyan Lotfi return stable_hash_combine(MO.getType(), MO.getTargetFlags(), 1427fff1fbdSPuyan Lotfi MO.getCFIIndex()); 1437fff1fbdSPuyan Lotfi case MachineOperand::MO_IntrinsicID: 1447fff1fbdSPuyan Lotfi return stable_hash_combine(MO.getType(), MO.getTargetFlags(), 1457fff1fbdSPuyan Lotfi MO.getIntrinsicID()); 1467fff1fbdSPuyan Lotfi case MachineOperand::MO_Predicate: 1477fff1fbdSPuyan Lotfi return stable_hash_combine(MO.getType(), MO.getTargetFlags(), 1487fff1fbdSPuyan Lotfi MO.getPredicate()); 1497fff1fbdSPuyan Lotfi } 1507fff1fbdSPuyan Lotfi llvm_unreachable("Invalid machine operand type"); 1517fff1fbdSPuyan Lotfi } 1527fff1fbdSPuyan Lotfi 1537fff1fbdSPuyan Lotfi /// A stable hash value for machine instructions. 1547fff1fbdSPuyan Lotfi /// Returns 0 if no stable hash could be computed. 1557fff1fbdSPuyan Lotfi /// The hashing and equality testing functions ignore definitions so this is 1567fff1fbdSPuyan Lotfi /// useful for CSE, etc. 1577fff1fbdSPuyan Lotfi stable_hash llvm::stableHashValue(const MachineInstr &MI, bool HashVRegs, 1587fff1fbdSPuyan Lotfi bool HashConstantPoolIndices, 1597fff1fbdSPuyan Lotfi bool HashMemOperands) { 1607fff1fbdSPuyan Lotfi // Build up a buffer of hash code components. 1617fff1fbdSPuyan Lotfi SmallVector<stable_hash, 16> HashComponents; 1627fff1fbdSPuyan Lotfi HashComponents.reserve(MI.getNumOperands() + MI.getNumMemOperands() + 2); 1637fff1fbdSPuyan Lotfi HashComponents.push_back(MI.getOpcode()); 1647fff1fbdSPuyan Lotfi HashComponents.push_back(MI.getFlags()); 1657fff1fbdSPuyan Lotfi for (const MachineOperand &MO : MI.operands()) { 1667fff1fbdSPuyan Lotfi if (!HashVRegs && MO.isReg() && MO.isDef() && 1677fff1fbdSPuyan Lotfi Register::isVirtualRegister(MO.getReg())) 1687fff1fbdSPuyan Lotfi continue; // Skip virtual register defs. 1697fff1fbdSPuyan Lotfi 1707fff1fbdSPuyan Lotfi if (MO.isCPI()) { 1717fff1fbdSPuyan Lotfi HashComponents.push_back(stable_hash_combine( 1727fff1fbdSPuyan Lotfi MO.getType(), MO.getTargetFlags(), MO.getIndex())); 1737fff1fbdSPuyan Lotfi continue; 1747fff1fbdSPuyan Lotfi } 1757fff1fbdSPuyan Lotfi 1767fff1fbdSPuyan Lotfi stable_hash StableHash = stableHashValue(MO); 1777fff1fbdSPuyan Lotfi if (!StableHash) 1787fff1fbdSPuyan Lotfi return 0; 1797fff1fbdSPuyan Lotfi HashComponents.push_back(StableHash); 1807fff1fbdSPuyan Lotfi } 1817fff1fbdSPuyan Lotfi 1827fff1fbdSPuyan Lotfi for (const auto *Op : MI.memoperands()) { 1837fff1fbdSPuyan Lotfi if (!HashMemOperands) 1847fff1fbdSPuyan Lotfi break; 1857fff1fbdSPuyan Lotfi HashComponents.push_back(static_cast<unsigned>(Op->getSize())); 1867fff1fbdSPuyan Lotfi HashComponents.push_back(static_cast<unsigned>(Op->getFlags())); 1877fff1fbdSPuyan Lotfi HashComponents.push_back(static_cast<unsigned>(Op->getOffset())); 18874909e4bSEli Friedman HashComponents.push_back(static_cast<unsigned>(Op->getSuccessOrdering())); 1897fff1fbdSPuyan Lotfi HashComponents.push_back(static_cast<unsigned>(Op->getAddrSpace())); 1907fff1fbdSPuyan Lotfi HashComponents.push_back(static_cast<unsigned>(Op->getSyncScopeID())); 1917fff1fbdSPuyan Lotfi HashComponents.push_back(static_cast<unsigned>(Op->getBaseAlign().value())); 1927fff1fbdSPuyan Lotfi HashComponents.push_back(static_cast<unsigned>(Op->getFailureOrdering())); 1937fff1fbdSPuyan Lotfi } 1947fff1fbdSPuyan Lotfi 1957fff1fbdSPuyan Lotfi return stable_hash_combine_range(HashComponents.begin(), 1967fff1fbdSPuyan Lotfi HashComponents.end()); 1977fff1fbdSPuyan Lotfi } 198*b47e2dc9SJay Foad 199*b47e2dc9SJay Foad stable_hash llvm::stableHashValue(const MachineBasicBlock &MBB) { 200*b47e2dc9SJay Foad SmallVector<stable_hash> HashComponents; 201*b47e2dc9SJay Foad // TODO: Hash more stuff like block alignment and branch probabilities. 202*b47e2dc9SJay Foad for (auto &MI : MBB) 203*b47e2dc9SJay Foad HashComponents.push_back(stableHashValue(MI)); 204*b47e2dc9SJay Foad return stable_hash_combine_range(HashComponents.begin(), 205*b47e2dc9SJay Foad HashComponents.end()); 206*b47e2dc9SJay Foad } 207*b47e2dc9SJay Foad 208*b47e2dc9SJay Foad stable_hash llvm::stableHashValue(const MachineFunction &MF) { 209*b47e2dc9SJay Foad SmallVector<stable_hash> HashComponents; 210*b47e2dc9SJay Foad // TODO: Hash lots more stuff like function alignment and stack objects. 211*b47e2dc9SJay Foad for (auto &MBB : MF) 212*b47e2dc9SJay Foad HashComponents.push_back(stableHashValue(MBB)); 213*b47e2dc9SJay Foad return stable_hash_combine_range(HashComponents.begin(), 214*b47e2dc9SJay Foad HashComponents.end()); 215*b47e2dc9SJay Foad } 216