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" 15*989f1c72Sserge-sans-paille #include "llvm/ADT/APFloat.h" 16*989f1c72Sserge-sans-paille #include "llvm/ADT/APInt.h" 17*989f1c72Sserge-sans-paille #include "llvm/ADT/ArrayRef.h" 18*989f1c72Sserge-sans-paille #include "llvm/ADT/DenseMapInfo.h" 19*989f1c72Sserge-sans-paille #include "llvm/ADT/Hashing.h" 20*989f1c72Sserge-sans-paille #include "llvm/ADT/STLExtras.h" 21*989f1c72Sserge-sans-paille #include "llvm/ADT/SmallVector.h" 227fff1fbdSPuyan Lotfi #include "llvm/ADT/Statistic.h" 23*989f1c72Sserge-sans-paille #include "llvm/ADT/ilist_iterator.h" 24*989f1c72Sserge-sans-paille #include "llvm/ADT/iterator_range.h" 25*989f1c72Sserge-sans-paille #include "llvm/CodeGen/MachineBasicBlock.h" 26*989f1c72Sserge-sans-paille #include "llvm/CodeGen/MachineFunction.h" 276670f5d1SSimon Pilgrim #include "llvm/CodeGen/MachineInstr.h" 28*989f1c72Sserge-sans-paille #include "llvm/CodeGen/MachineInstrBundleIterator.h" 29*989f1c72Sserge-sans-paille #include "llvm/CodeGen/MachineMemOperand.h" 307fff1fbdSPuyan Lotfi #include "llvm/CodeGen/MachineOperand.h" 317fff1fbdSPuyan Lotfi #include "llvm/CodeGen/MachineRegisterInfo.h" 32*989f1c72Sserge-sans-paille #include "llvm/CodeGen/Register.h" 337fff1fbdSPuyan Lotfi #include "llvm/CodeGen/StableHashing.h" 347fff1fbdSPuyan Lotfi #include "llvm/Config/llvm-config.h" 357fff1fbdSPuyan Lotfi #include "llvm/IR/Constants.h" 36*989f1c72Sserge-sans-paille #include "llvm/MC/MCSymbol.h" 37*989f1c72Sserge-sans-paille #include "llvm/Support/Alignment.h" 38*989f1c72Sserge-sans-paille #include "llvm/Support/ErrorHandling.h" 397fff1fbdSPuyan Lotfi 407fff1fbdSPuyan Lotfi #define DEBUG_TYPE "machine-stable-hash" 417fff1fbdSPuyan Lotfi 427fff1fbdSPuyan Lotfi using namespace llvm; 437fff1fbdSPuyan Lotfi 447fff1fbdSPuyan Lotfi STATISTIC(StableHashBailingMachineBasicBlock, 457fff1fbdSPuyan Lotfi "Number of encountered unsupported MachineOperands that were " 467fff1fbdSPuyan Lotfi "MachineBasicBlocks while computing stable hashes"); 477fff1fbdSPuyan Lotfi STATISTIC(StableHashBailingConstantPoolIndex, 487fff1fbdSPuyan Lotfi "Number of encountered unsupported MachineOperands that were " 497fff1fbdSPuyan Lotfi "ConstantPoolIndex while computing stable hashes"); 507fff1fbdSPuyan Lotfi STATISTIC(StableHashBailingTargetIndexNoName, 517fff1fbdSPuyan Lotfi "Number of encountered unsupported MachineOperands that were " 527fff1fbdSPuyan Lotfi "TargetIndex with no name"); 537fff1fbdSPuyan Lotfi STATISTIC(StableHashBailingGlobalAddress, 547fff1fbdSPuyan Lotfi "Number of encountered unsupported MachineOperands that were " 557fff1fbdSPuyan Lotfi "GlobalAddress while computing stable hashes"); 567fff1fbdSPuyan Lotfi STATISTIC(StableHashBailingBlockAddress, 577fff1fbdSPuyan Lotfi "Number of encountered unsupported MachineOperands that were " 587fff1fbdSPuyan Lotfi "BlockAddress while computing stable hashes"); 597fff1fbdSPuyan Lotfi STATISTIC(StableHashBailingMetadataUnsupported, 607fff1fbdSPuyan Lotfi "Number of encountered unsupported MachineOperands that were " 617fff1fbdSPuyan Lotfi "Metadata of an unsupported kind while computing stable hashes"); 627fff1fbdSPuyan Lotfi 637fff1fbdSPuyan Lotfi stable_hash llvm::stableHashValue(const MachineOperand &MO) { 647fff1fbdSPuyan Lotfi switch (MO.getType()) { 657fff1fbdSPuyan Lotfi case MachineOperand::MO_Register: 667fff1fbdSPuyan Lotfi if (Register::isVirtualRegister(MO.getReg())) { 677fff1fbdSPuyan Lotfi const MachineRegisterInfo &MRI = MO.getParent()->getMF()->getRegInfo(); 689a547e70SJay Foad SmallVector<unsigned> DefOpcodes; 699a547e70SJay Foad for (auto &Def : MRI.def_instructions(MO.getReg())) 709a547e70SJay Foad DefOpcodes.push_back(Def.getOpcode()); 719a547e70SJay Foad return hash_combine_range(DefOpcodes.begin(), DefOpcodes.end()); 727fff1fbdSPuyan Lotfi } 737fff1fbdSPuyan Lotfi 747fff1fbdSPuyan Lotfi // Register operands don't have target flags. 757fff1fbdSPuyan Lotfi return stable_hash_combine(MO.getType(), MO.getReg(), MO.getSubReg(), 767fff1fbdSPuyan Lotfi MO.isDef()); 777fff1fbdSPuyan Lotfi case MachineOperand::MO_Immediate: 787fff1fbdSPuyan Lotfi return stable_hash_combine(MO.getType(), MO.getTargetFlags(), MO.getImm()); 797fff1fbdSPuyan Lotfi case MachineOperand::MO_CImmediate: 807fff1fbdSPuyan Lotfi case MachineOperand::MO_FPImmediate: { 817fff1fbdSPuyan Lotfi auto Val = MO.isCImm() ? MO.getCImm()->getValue() 827fff1fbdSPuyan Lotfi : MO.getFPImm()->getValueAPF().bitcastToAPInt(); 837fff1fbdSPuyan Lotfi auto ValHash = 847fff1fbdSPuyan Lotfi stable_hash_combine_array(Val.getRawData(), Val.getNumWords()); 857fff1fbdSPuyan Lotfi return hash_combine(MO.getType(), MO.getTargetFlags(), ValHash); 867fff1fbdSPuyan Lotfi } 877fff1fbdSPuyan Lotfi 887fff1fbdSPuyan Lotfi case MachineOperand::MO_MachineBasicBlock: 897fff1fbdSPuyan Lotfi StableHashBailingMachineBasicBlock++; 907fff1fbdSPuyan Lotfi return 0; 917fff1fbdSPuyan Lotfi case MachineOperand::MO_ConstantPoolIndex: 927fff1fbdSPuyan Lotfi StableHashBailingConstantPoolIndex++; 937fff1fbdSPuyan Lotfi return 0; 947fff1fbdSPuyan Lotfi case MachineOperand::MO_BlockAddress: 957fff1fbdSPuyan Lotfi StableHashBailingBlockAddress++; 967fff1fbdSPuyan Lotfi return 0; 977fff1fbdSPuyan Lotfi case MachineOperand::MO_Metadata: 987fff1fbdSPuyan Lotfi StableHashBailingMetadataUnsupported++; 997fff1fbdSPuyan Lotfi return 0; 1007fff1fbdSPuyan Lotfi case MachineOperand::MO_GlobalAddress: 1017fff1fbdSPuyan Lotfi StableHashBailingGlobalAddress++; 1027fff1fbdSPuyan Lotfi return 0; 1037fff1fbdSPuyan Lotfi case MachineOperand::MO_TargetIndex: { 1047fff1fbdSPuyan Lotfi if (const char *Name = MO.getTargetIndexName()) 1057fff1fbdSPuyan Lotfi return stable_hash_combine(MO.getType(), MO.getTargetFlags(), 1067fff1fbdSPuyan Lotfi stable_hash_combine_string(Name), 1077fff1fbdSPuyan Lotfi MO.getOffset()); 1087fff1fbdSPuyan Lotfi StableHashBailingTargetIndexNoName++; 1097fff1fbdSPuyan Lotfi return 0; 1107fff1fbdSPuyan Lotfi } 1117fff1fbdSPuyan Lotfi 1127fff1fbdSPuyan Lotfi case MachineOperand::MO_FrameIndex: 1137fff1fbdSPuyan Lotfi case MachineOperand::MO_JumpTableIndex: 1147fff1fbdSPuyan Lotfi return stable_hash_combine(MO.getType(), MO.getTargetFlags(), 1157fff1fbdSPuyan Lotfi MO.getIndex()); 1167fff1fbdSPuyan Lotfi 1177fff1fbdSPuyan Lotfi case MachineOperand::MO_ExternalSymbol: 1187fff1fbdSPuyan Lotfi return hash_combine(MO.getType(), MO.getTargetFlags(), MO.getOffset(), 1197fff1fbdSPuyan Lotfi stable_hash_combine_string(MO.getSymbolName())); 1207fff1fbdSPuyan Lotfi 1217fff1fbdSPuyan Lotfi case MachineOperand::MO_RegisterMask: 1227fff1fbdSPuyan Lotfi case MachineOperand::MO_RegisterLiveOut: 1237fff1fbdSPuyan Lotfi return hash_combine(MO.getType(), MO.getTargetFlags(), MO.getRegMask()); 1247fff1fbdSPuyan Lotfi 1257fff1fbdSPuyan Lotfi case MachineOperand::MO_ShuffleMask: { 1267fff1fbdSPuyan Lotfi std::vector<llvm::stable_hash> ShuffleMaskHashes; 1277fff1fbdSPuyan Lotfi 1287fff1fbdSPuyan Lotfi llvm::transform( 1297fff1fbdSPuyan Lotfi MO.getShuffleMask(), std::back_inserter(ShuffleMaskHashes), 1307fff1fbdSPuyan Lotfi [](int S) -> llvm::stable_hash { return llvm::stable_hash(S); }); 1317fff1fbdSPuyan Lotfi 1327fff1fbdSPuyan Lotfi return hash_combine(MO.getType(), MO.getTargetFlags(), 1337fff1fbdSPuyan Lotfi stable_hash_combine_array(ShuffleMaskHashes.data(), 1347fff1fbdSPuyan Lotfi ShuffleMaskHashes.size())); 1357fff1fbdSPuyan Lotfi } 1367fff1fbdSPuyan Lotfi case MachineOperand::MO_MCSymbol: { 1377fff1fbdSPuyan Lotfi auto SymbolName = MO.getMCSymbol()->getName(); 1387fff1fbdSPuyan Lotfi return hash_combine(MO.getType(), MO.getTargetFlags(), 1397fff1fbdSPuyan Lotfi stable_hash_combine_string(SymbolName)); 1407fff1fbdSPuyan Lotfi } 1417fff1fbdSPuyan Lotfi case MachineOperand::MO_CFIIndex: 1427fff1fbdSPuyan Lotfi return stable_hash_combine(MO.getType(), MO.getTargetFlags(), 1437fff1fbdSPuyan Lotfi MO.getCFIIndex()); 1447fff1fbdSPuyan Lotfi case MachineOperand::MO_IntrinsicID: 1457fff1fbdSPuyan Lotfi return stable_hash_combine(MO.getType(), MO.getTargetFlags(), 1467fff1fbdSPuyan Lotfi MO.getIntrinsicID()); 1477fff1fbdSPuyan Lotfi case MachineOperand::MO_Predicate: 1487fff1fbdSPuyan Lotfi return stable_hash_combine(MO.getType(), MO.getTargetFlags(), 1497fff1fbdSPuyan Lotfi MO.getPredicate()); 1507fff1fbdSPuyan Lotfi } 1517fff1fbdSPuyan Lotfi llvm_unreachable("Invalid machine operand type"); 1527fff1fbdSPuyan Lotfi } 1537fff1fbdSPuyan Lotfi 1547fff1fbdSPuyan Lotfi /// A stable hash value for machine instructions. 1557fff1fbdSPuyan Lotfi /// Returns 0 if no stable hash could be computed. 1567fff1fbdSPuyan Lotfi /// The hashing and equality testing functions ignore definitions so this is 1577fff1fbdSPuyan Lotfi /// useful for CSE, etc. 1587fff1fbdSPuyan Lotfi stable_hash llvm::stableHashValue(const MachineInstr &MI, bool HashVRegs, 1597fff1fbdSPuyan Lotfi bool HashConstantPoolIndices, 1607fff1fbdSPuyan Lotfi bool HashMemOperands) { 1617fff1fbdSPuyan Lotfi // Build up a buffer of hash code components. 1627fff1fbdSPuyan Lotfi SmallVector<stable_hash, 16> HashComponents; 1637fff1fbdSPuyan Lotfi HashComponents.reserve(MI.getNumOperands() + MI.getNumMemOperands() + 2); 1647fff1fbdSPuyan Lotfi HashComponents.push_back(MI.getOpcode()); 1657fff1fbdSPuyan Lotfi HashComponents.push_back(MI.getFlags()); 1667fff1fbdSPuyan Lotfi for (const MachineOperand &MO : MI.operands()) { 1677fff1fbdSPuyan Lotfi if (!HashVRegs && MO.isReg() && MO.isDef() && 1687fff1fbdSPuyan Lotfi Register::isVirtualRegister(MO.getReg())) 1697fff1fbdSPuyan Lotfi continue; // Skip virtual register defs. 1707fff1fbdSPuyan Lotfi 1717fff1fbdSPuyan Lotfi if (MO.isCPI()) { 1727fff1fbdSPuyan Lotfi HashComponents.push_back(stable_hash_combine( 1737fff1fbdSPuyan Lotfi MO.getType(), MO.getTargetFlags(), MO.getIndex())); 1747fff1fbdSPuyan Lotfi continue; 1757fff1fbdSPuyan Lotfi } 1767fff1fbdSPuyan Lotfi 1777fff1fbdSPuyan Lotfi stable_hash StableHash = stableHashValue(MO); 1787fff1fbdSPuyan Lotfi if (!StableHash) 1797fff1fbdSPuyan Lotfi return 0; 1807fff1fbdSPuyan Lotfi HashComponents.push_back(StableHash); 1817fff1fbdSPuyan Lotfi } 1827fff1fbdSPuyan Lotfi 1837fff1fbdSPuyan Lotfi for (const auto *Op : MI.memoperands()) { 1847fff1fbdSPuyan Lotfi if (!HashMemOperands) 1857fff1fbdSPuyan Lotfi break; 1867fff1fbdSPuyan Lotfi HashComponents.push_back(static_cast<unsigned>(Op->getSize())); 1877fff1fbdSPuyan Lotfi HashComponents.push_back(static_cast<unsigned>(Op->getFlags())); 1887fff1fbdSPuyan Lotfi HashComponents.push_back(static_cast<unsigned>(Op->getOffset())); 18974909e4bSEli Friedman HashComponents.push_back(static_cast<unsigned>(Op->getSuccessOrdering())); 1907fff1fbdSPuyan Lotfi HashComponents.push_back(static_cast<unsigned>(Op->getAddrSpace())); 1917fff1fbdSPuyan Lotfi HashComponents.push_back(static_cast<unsigned>(Op->getSyncScopeID())); 1927fff1fbdSPuyan Lotfi HashComponents.push_back(static_cast<unsigned>(Op->getBaseAlign().value())); 1937fff1fbdSPuyan Lotfi HashComponents.push_back(static_cast<unsigned>(Op->getFailureOrdering())); 1947fff1fbdSPuyan Lotfi } 1957fff1fbdSPuyan Lotfi 1967fff1fbdSPuyan Lotfi return stable_hash_combine_range(HashComponents.begin(), 1977fff1fbdSPuyan Lotfi HashComponents.end()); 1987fff1fbdSPuyan Lotfi } 199b47e2dc9SJay Foad 200b47e2dc9SJay Foad stable_hash llvm::stableHashValue(const MachineBasicBlock &MBB) { 201b47e2dc9SJay Foad SmallVector<stable_hash> HashComponents; 202b47e2dc9SJay Foad // TODO: Hash more stuff like block alignment and branch probabilities. 203b47e2dc9SJay Foad for (auto &MI : MBB) 204b47e2dc9SJay Foad HashComponents.push_back(stableHashValue(MI)); 205b47e2dc9SJay Foad return stable_hash_combine_range(HashComponents.begin(), 206b47e2dc9SJay Foad HashComponents.end()); 207b47e2dc9SJay Foad } 208b47e2dc9SJay Foad 209b47e2dc9SJay Foad stable_hash llvm::stableHashValue(const MachineFunction &MF) { 210b47e2dc9SJay Foad SmallVector<stable_hash> HashComponents; 211b47e2dc9SJay Foad // TODO: Hash lots more stuff like function alignment and stack objects. 212b47e2dc9SJay Foad for (auto &MBB : MF) 213b47e2dc9SJay Foad HashComponents.push_back(stableHashValue(MBB)); 214b47e2dc9SJay Foad return stable_hash_combine_range(HashComponents.begin(), 215b47e2dc9SJay Foad HashComponents.end()); 216b47e2dc9SJay Foad } 217