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(); 677fff1fbdSPuyan Lotfi return MRI.getVRegDef(MO.getReg())->getOpcode(); 687fff1fbdSPuyan Lotfi } 697fff1fbdSPuyan Lotfi 707fff1fbdSPuyan Lotfi // Register operands don't have target flags. 717fff1fbdSPuyan Lotfi return stable_hash_combine(MO.getType(), MO.getReg(), MO.getSubReg(), 727fff1fbdSPuyan Lotfi MO.isDef()); 737fff1fbdSPuyan Lotfi case MachineOperand::MO_Immediate: 747fff1fbdSPuyan Lotfi return stable_hash_combine(MO.getType(), MO.getTargetFlags(), MO.getImm()); 757fff1fbdSPuyan Lotfi case MachineOperand::MO_CImmediate: 767fff1fbdSPuyan Lotfi case MachineOperand::MO_FPImmediate: { 777fff1fbdSPuyan Lotfi auto Val = MO.isCImm() ? MO.getCImm()->getValue() 787fff1fbdSPuyan Lotfi : MO.getFPImm()->getValueAPF().bitcastToAPInt(); 797fff1fbdSPuyan Lotfi auto ValHash = 807fff1fbdSPuyan Lotfi stable_hash_combine_array(Val.getRawData(), Val.getNumWords()); 817fff1fbdSPuyan Lotfi return hash_combine(MO.getType(), MO.getTargetFlags(), ValHash); 827fff1fbdSPuyan Lotfi } 837fff1fbdSPuyan Lotfi 847fff1fbdSPuyan Lotfi case MachineOperand::MO_MachineBasicBlock: 857fff1fbdSPuyan Lotfi StableHashBailingMachineBasicBlock++; 867fff1fbdSPuyan Lotfi return 0; 877fff1fbdSPuyan Lotfi case MachineOperand::MO_ConstantPoolIndex: 887fff1fbdSPuyan Lotfi StableHashBailingConstantPoolIndex++; 897fff1fbdSPuyan Lotfi return 0; 907fff1fbdSPuyan Lotfi case MachineOperand::MO_BlockAddress: 917fff1fbdSPuyan Lotfi StableHashBailingBlockAddress++; 927fff1fbdSPuyan Lotfi return 0; 937fff1fbdSPuyan Lotfi case MachineOperand::MO_Metadata: 947fff1fbdSPuyan Lotfi StableHashBailingMetadataUnsupported++; 957fff1fbdSPuyan Lotfi return 0; 967fff1fbdSPuyan Lotfi case MachineOperand::MO_GlobalAddress: 977fff1fbdSPuyan Lotfi StableHashBailingGlobalAddress++; 987fff1fbdSPuyan Lotfi return 0; 997fff1fbdSPuyan Lotfi case MachineOperand::MO_TargetIndex: { 1007fff1fbdSPuyan Lotfi if (const char *Name = MO.getTargetIndexName()) 1017fff1fbdSPuyan Lotfi return stable_hash_combine(MO.getType(), MO.getTargetFlags(), 1027fff1fbdSPuyan Lotfi stable_hash_combine_string(Name), 1037fff1fbdSPuyan Lotfi MO.getOffset()); 1047fff1fbdSPuyan Lotfi StableHashBailingTargetIndexNoName++; 1057fff1fbdSPuyan Lotfi return 0; 1067fff1fbdSPuyan Lotfi } 1077fff1fbdSPuyan Lotfi 1087fff1fbdSPuyan Lotfi case MachineOperand::MO_FrameIndex: 1097fff1fbdSPuyan Lotfi case MachineOperand::MO_JumpTableIndex: 1107fff1fbdSPuyan Lotfi return stable_hash_combine(MO.getType(), MO.getTargetFlags(), 1117fff1fbdSPuyan Lotfi MO.getIndex()); 1127fff1fbdSPuyan Lotfi 1137fff1fbdSPuyan Lotfi case MachineOperand::MO_ExternalSymbol: 1147fff1fbdSPuyan Lotfi return hash_combine(MO.getType(), MO.getTargetFlags(), MO.getOffset(), 1157fff1fbdSPuyan Lotfi stable_hash_combine_string(MO.getSymbolName())); 1167fff1fbdSPuyan Lotfi 1177fff1fbdSPuyan Lotfi case MachineOperand::MO_RegisterMask: 1187fff1fbdSPuyan Lotfi case MachineOperand::MO_RegisterLiveOut: 1197fff1fbdSPuyan Lotfi return hash_combine(MO.getType(), MO.getTargetFlags(), MO.getRegMask()); 1207fff1fbdSPuyan Lotfi 1217fff1fbdSPuyan Lotfi case MachineOperand::MO_ShuffleMask: { 1227fff1fbdSPuyan Lotfi std::vector<llvm::stable_hash> ShuffleMaskHashes; 1237fff1fbdSPuyan Lotfi 1247fff1fbdSPuyan Lotfi llvm::transform( 1257fff1fbdSPuyan Lotfi MO.getShuffleMask(), std::back_inserter(ShuffleMaskHashes), 1267fff1fbdSPuyan Lotfi [](int S) -> llvm::stable_hash { return llvm::stable_hash(S); }); 1277fff1fbdSPuyan Lotfi 1287fff1fbdSPuyan Lotfi return hash_combine(MO.getType(), MO.getTargetFlags(), 1297fff1fbdSPuyan Lotfi stable_hash_combine_array(ShuffleMaskHashes.data(), 1307fff1fbdSPuyan Lotfi ShuffleMaskHashes.size())); 1317fff1fbdSPuyan Lotfi } 1327fff1fbdSPuyan Lotfi case MachineOperand::MO_MCSymbol: { 1337fff1fbdSPuyan Lotfi auto SymbolName = MO.getMCSymbol()->getName(); 1347fff1fbdSPuyan Lotfi return hash_combine(MO.getType(), MO.getTargetFlags(), 1357fff1fbdSPuyan Lotfi stable_hash_combine_string(SymbolName)); 1367fff1fbdSPuyan Lotfi } 1377fff1fbdSPuyan Lotfi case MachineOperand::MO_CFIIndex: 1387fff1fbdSPuyan Lotfi return stable_hash_combine(MO.getType(), MO.getTargetFlags(), 1397fff1fbdSPuyan Lotfi MO.getCFIIndex()); 1407fff1fbdSPuyan Lotfi case MachineOperand::MO_IntrinsicID: 1417fff1fbdSPuyan Lotfi return stable_hash_combine(MO.getType(), MO.getTargetFlags(), 1427fff1fbdSPuyan Lotfi MO.getIntrinsicID()); 1437fff1fbdSPuyan Lotfi case MachineOperand::MO_Predicate: 1447fff1fbdSPuyan Lotfi return stable_hash_combine(MO.getType(), MO.getTargetFlags(), 1457fff1fbdSPuyan Lotfi MO.getPredicate()); 1467fff1fbdSPuyan Lotfi } 1477fff1fbdSPuyan Lotfi llvm_unreachable("Invalid machine operand type"); 1487fff1fbdSPuyan Lotfi } 1497fff1fbdSPuyan Lotfi 1507fff1fbdSPuyan Lotfi /// A stable hash value for machine instructions. 1517fff1fbdSPuyan Lotfi /// Returns 0 if no stable hash could be computed. 1527fff1fbdSPuyan Lotfi /// The hashing and equality testing functions ignore definitions so this is 1537fff1fbdSPuyan Lotfi /// useful for CSE, etc. 1547fff1fbdSPuyan Lotfi stable_hash llvm::stableHashValue(const MachineInstr &MI, bool HashVRegs, 1557fff1fbdSPuyan Lotfi bool HashConstantPoolIndices, 1567fff1fbdSPuyan Lotfi bool HashMemOperands) { 1577fff1fbdSPuyan Lotfi // Build up a buffer of hash code components. 1587fff1fbdSPuyan Lotfi SmallVector<stable_hash, 16> HashComponents; 1597fff1fbdSPuyan Lotfi HashComponents.reserve(MI.getNumOperands() + MI.getNumMemOperands() + 2); 1607fff1fbdSPuyan Lotfi HashComponents.push_back(MI.getOpcode()); 1617fff1fbdSPuyan Lotfi HashComponents.push_back(MI.getFlags()); 1627fff1fbdSPuyan Lotfi for (const MachineOperand &MO : MI.operands()) { 1637fff1fbdSPuyan Lotfi if (!HashVRegs && MO.isReg() && MO.isDef() && 1647fff1fbdSPuyan Lotfi Register::isVirtualRegister(MO.getReg())) 1657fff1fbdSPuyan Lotfi continue; // Skip virtual register defs. 1667fff1fbdSPuyan Lotfi 1677fff1fbdSPuyan Lotfi if (MO.isCPI()) { 1687fff1fbdSPuyan Lotfi HashComponents.push_back(stable_hash_combine( 1697fff1fbdSPuyan Lotfi MO.getType(), MO.getTargetFlags(), MO.getIndex())); 1707fff1fbdSPuyan Lotfi continue; 1717fff1fbdSPuyan Lotfi } 1727fff1fbdSPuyan Lotfi 1737fff1fbdSPuyan Lotfi stable_hash StableHash = stableHashValue(MO); 1747fff1fbdSPuyan Lotfi if (!StableHash) 1757fff1fbdSPuyan Lotfi return 0; 1767fff1fbdSPuyan Lotfi HashComponents.push_back(StableHash); 1777fff1fbdSPuyan Lotfi } 1787fff1fbdSPuyan Lotfi 1797fff1fbdSPuyan Lotfi for (const auto *Op : MI.memoperands()) { 1807fff1fbdSPuyan Lotfi if (!HashMemOperands) 1817fff1fbdSPuyan Lotfi break; 1827fff1fbdSPuyan Lotfi HashComponents.push_back(static_cast<unsigned>(Op->getSize())); 1837fff1fbdSPuyan Lotfi HashComponents.push_back(static_cast<unsigned>(Op->getFlags())); 1847fff1fbdSPuyan Lotfi HashComponents.push_back(static_cast<unsigned>(Op->getOffset())); 185*74909e4bSEli Friedman HashComponents.push_back(static_cast<unsigned>(Op->getSuccessOrdering())); 1867fff1fbdSPuyan Lotfi HashComponents.push_back(static_cast<unsigned>(Op->getAddrSpace())); 1877fff1fbdSPuyan Lotfi HashComponents.push_back(static_cast<unsigned>(Op->getSyncScopeID())); 1887fff1fbdSPuyan Lotfi HashComponents.push_back(static_cast<unsigned>(Op->getBaseAlign().value())); 1897fff1fbdSPuyan Lotfi HashComponents.push_back(static_cast<unsigned>(Op->getFailureOrdering())); 1907fff1fbdSPuyan Lotfi } 1917fff1fbdSPuyan Lotfi 1927fff1fbdSPuyan Lotfi return stable_hash_combine_range(HashComponents.begin(), 1937fff1fbdSPuyan Lotfi HashComponents.end()); 1947fff1fbdSPuyan Lotfi } 195