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