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