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"
15989f1c72Sserge-sans-paille #include "llvm/ADT/APFloat.h"
16989f1c72Sserge-sans-paille #include "llvm/ADT/APInt.h"
17989f1c72Sserge-sans-paille #include "llvm/ADT/ArrayRef.h"
18989f1c72Sserge-sans-paille #include "llvm/ADT/DenseMapInfo.h"
19989f1c72Sserge-sans-paille #include "llvm/ADT/Hashing.h"
20989f1c72Sserge-sans-paille #include "llvm/ADT/STLExtras.h"
21989f1c72Sserge-sans-paille #include "llvm/ADT/SmallVector.h"
227fff1fbdSPuyan Lotfi #include "llvm/ADT/Statistic.h"
23989f1c72Sserge-sans-paille #include "llvm/ADT/ilist_iterator.h"
24989f1c72Sserge-sans-paille #include "llvm/ADT/iterator_range.h"
25989f1c72Sserge-sans-paille #include "llvm/CodeGen/MachineBasicBlock.h"
26989f1c72Sserge-sans-paille #include "llvm/CodeGen/MachineFunction.h"
276670f5d1SSimon Pilgrim #include "llvm/CodeGen/MachineInstr.h"
28989f1c72Sserge-sans-paille #include "llvm/CodeGen/MachineInstrBundleIterator.h"
29989f1c72Sserge-sans-paille #include "llvm/CodeGen/MachineMemOperand.h"
307fff1fbdSPuyan Lotfi #include "llvm/CodeGen/MachineOperand.h"
317fff1fbdSPuyan Lotfi #include "llvm/CodeGen/MachineRegisterInfo.h"
32989f1c72Sserge-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"
36989f1c72Sserge-sans-paille #include "llvm/MC/MCSymbol.h"
37989f1c72Sserge-sans-paille #include "llvm/Support/Alignment.h"
38989f1c72Sserge-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 
stableHashValue(const MachineOperand & MO)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.
stableHashValue(const MachineInstr & MI,bool HashVRegs,bool HashConstantPoolIndices,bool HashMemOperands)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 
stableHashValue(const MachineBasicBlock & MBB)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.
203*9e6d1f4bSKazu Hirata   for (const 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 
stableHashValue(const MachineFunction & MF)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.
212*9e6d1f4bSKazu Hirata   for (const 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