10b57cec5SDimitry Andric //===- CSEInfo.cpp ------------------------------===//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric //
90b57cec5SDimitry Andric //
100b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
110b57cec5SDimitry Andric #include "llvm/CodeGen/GlobalISel/CSEInfo.h"
120b57cec5SDimitry Andric #include "llvm/CodeGen/MachineRegisterInfo.h"
13480093f4SDimitry Andric #include "llvm/InitializePasses.h"
14fe6060f1SDimitry Andric #include "llvm/Support/Error.h"
150b57cec5SDimitry Andric 
160b57cec5SDimitry Andric #define DEBUG_TYPE "cseinfo"
170b57cec5SDimitry Andric 
180b57cec5SDimitry Andric using namespace llvm;
190b57cec5SDimitry Andric char llvm::GISelCSEAnalysisWrapperPass::ID = 0;
GISelCSEAnalysisWrapperPass()20480093f4SDimitry Andric GISelCSEAnalysisWrapperPass::GISelCSEAnalysisWrapperPass()
21480093f4SDimitry Andric     : MachineFunctionPass(ID) {
22480093f4SDimitry Andric   initializeGISelCSEAnalysisWrapperPassPass(*PassRegistry::getPassRegistry());
23480093f4SDimitry Andric }
240b57cec5SDimitry Andric INITIALIZE_PASS_BEGIN(GISelCSEAnalysisWrapperPass, DEBUG_TYPE,
250b57cec5SDimitry Andric                       "Analysis containing CSE Info", false, true)
260b57cec5SDimitry Andric INITIALIZE_PASS_END(GISelCSEAnalysisWrapperPass, DEBUG_TYPE,
270b57cec5SDimitry Andric                     "Analysis containing CSE Info", false, true)
280b57cec5SDimitry Andric 
290b57cec5SDimitry Andric /// -------- UniqueMachineInstr -------------//
300b57cec5SDimitry Andric 
Profile(FoldingSetNodeID & ID)310b57cec5SDimitry Andric void UniqueMachineInstr::Profile(FoldingSetNodeID &ID) {
320b57cec5SDimitry Andric   GISelInstProfileBuilder(ID, MI->getMF()->getRegInfo()).addNodeID(MI);
330b57cec5SDimitry Andric }
340b57cec5SDimitry Andric /// -----------------------------------------
350b57cec5SDimitry Andric 
360b57cec5SDimitry Andric /// --------- CSEConfigFull ---------- ///
shouldCSEOpc(unsigned Opc)370b57cec5SDimitry Andric bool CSEConfigFull::shouldCSEOpc(unsigned Opc) {
380b57cec5SDimitry Andric   switch (Opc) {
390b57cec5SDimitry Andric   default:
400b57cec5SDimitry Andric     break;
410b57cec5SDimitry Andric   case TargetOpcode::G_ADD:
420b57cec5SDimitry Andric   case TargetOpcode::G_AND:
430b57cec5SDimitry Andric   case TargetOpcode::G_ASHR:
440b57cec5SDimitry Andric   case TargetOpcode::G_LSHR:
450b57cec5SDimitry Andric   case TargetOpcode::G_MUL:
460b57cec5SDimitry Andric   case TargetOpcode::G_OR:
470b57cec5SDimitry Andric   case TargetOpcode::G_SHL:
480b57cec5SDimitry Andric   case TargetOpcode::G_SUB:
490b57cec5SDimitry Andric   case TargetOpcode::G_XOR:
500b57cec5SDimitry Andric   case TargetOpcode::G_UDIV:
510b57cec5SDimitry Andric   case TargetOpcode::G_SDIV:
520b57cec5SDimitry Andric   case TargetOpcode::G_UREM:
530b57cec5SDimitry Andric   case TargetOpcode::G_SREM:
540b57cec5SDimitry Andric   case TargetOpcode::G_CONSTANT:
550b57cec5SDimitry Andric   case TargetOpcode::G_FCONSTANT:
565ffd83dbSDimitry Andric   case TargetOpcode::G_IMPLICIT_DEF:
570b57cec5SDimitry Andric   case TargetOpcode::G_ZEXT:
580b57cec5SDimitry Andric   case TargetOpcode::G_SEXT:
590b57cec5SDimitry Andric   case TargetOpcode::G_ANYEXT:
600b57cec5SDimitry Andric   case TargetOpcode::G_UNMERGE_VALUES:
610b57cec5SDimitry Andric   case TargetOpcode::G_TRUNC:
62480093f4SDimitry Andric   case TargetOpcode::G_PTR_ADD:
63e8d8bef9SDimitry Andric   case TargetOpcode::G_EXTRACT:
64bdd1243dSDimitry Andric   case TargetOpcode::G_SELECT:
65bdd1243dSDimitry Andric   case TargetOpcode::G_BUILD_VECTOR:
66bdd1243dSDimitry Andric   case TargetOpcode::G_BUILD_VECTOR_TRUNC:
67bdd1243dSDimitry Andric   case TargetOpcode::G_SEXT_INREG:
680b57cec5SDimitry Andric     return true;
690b57cec5SDimitry Andric   }
700b57cec5SDimitry Andric   return false;
710b57cec5SDimitry Andric }
720b57cec5SDimitry Andric 
shouldCSEOpc(unsigned Opc)730b57cec5SDimitry Andric bool CSEConfigConstantOnly::shouldCSEOpc(unsigned Opc) {
7481ad6265SDimitry Andric   return Opc == TargetOpcode::G_CONSTANT || Opc == TargetOpcode::G_FCONSTANT ||
7581ad6265SDimitry Andric          Opc == TargetOpcode::G_IMPLICIT_DEF;
760b57cec5SDimitry Andric }
770b57cec5SDimitry Andric 
780b57cec5SDimitry Andric std::unique_ptr<CSEConfigBase>
getStandardCSEConfigForOpt(CodeGenOptLevel Level)795f757f3fSDimitry Andric llvm::getStandardCSEConfigForOpt(CodeGenOptLevel Level) {
800b57cec5SDimitry Andric   std::unique_ptr<CSEConfigBase> Config;
815f757f3fSDimitry Andric   if (Level == CodeGenOptLevel::None)
828bcb0991SDimitry Andric     Config = std::make_unique<CSEConfigConstantOnly>();
830b57cec5SDimitry Andric   else
848bcb0991SDimitry Andric     Config = std::make_unique<CSEConfigFull>();
850b57cec5SDimitry Andric   return Config;
860b57cec5SDimitry Andric }
870b57cec5SDimitry Andric 
880b57cec5SDimitry Andric /// -----------------------------------------
890b57cec5SDimitry Andric 
900b57cec5SDimitry Andric /// -------- GISelCSEInfo -------------//
setMF(MachineFunction & MF)910b57cec5SDimitry Andric void GISelCSEInfo::setMF(MachineFunction &MF) {
920b57cec5SDimitry Andric   this->MF = &MF;
930b57cec5SDimitry Andric   this->MRI = &MF.getRegInfo();
940b57cec5SDimitry Andric }
950b57cec5SDimitry Andric 
9681ad6265SDimitry Andric GISelCSEInfo::~GISelCSEInfo() = default;
970b57cec5SDimitry Andric 
isUniqueMachineInstValid(const UniqueMachineInstr & UMI) const980b57cec5SDimitry Andric bool GISelCSEInfo::isUniqueMachineInstValid(
990b57cec5SDimitry Andric     const UniqueMachineInstr &UMI) const {
1000b57cec5SDimitry Andric   // Should we check here and assert that the instruction has been fully
1010b57cec5SDimitry Andric   // constructed?
1020b57cec5SDimitry Andric   // FIXME: Any other checks required to be done here? Remove this method if
1030b57cec5SDimitry Andric   // none.
1040b57cec5SDimitry Andric   return true;
1050b57cec5SDimitry Andric }
1060b57cec5SDimitry Andric 
invalidateUniqueMachineInstr(UniqueMachineInstr * UMI)1070b57cec5SDimitry Andric void GISelCSEInfo::invalidateUniqueMachineInstr(UniqueMachineInstr *UMI) {
1080b57cec5SDimitry Andric   bool Removed = CSEMap.RemoveNode(UMI);
1090b57cec5SDimitry Andric   (void)Removed;
1100b57cec5SDimitry Andric   assert(Removed && "Invalidation called on invalid UMI");
1110b57cec5SDimitry Andric   // FIXME: Should UMI be deallocated/destroyed?
1120b57cec5SDimitry Andric }
1130b57cec5SDimitry Andric 
getNodeIfExists(FoldingSetNodeID & ID,MachineBasicBlock * MBB,void * & InsertPos)1140b57cec5SDimitry Andric UniqueMachineInstr *GISelCSEInfo::getNodeIfExists(FoldingSetNodeID &ID,
1150b57cec5SDimitry Andric                                                   MachineBasicBlock *MBB,
1160b57cec5SDimitry Andric                                                   void *&InsertPos) {
1170b57cec5SDimitry Andric   auto *Node = CSEMap.FindNodeOrInsertPos(ID, InsertPos);
1180b57cec5SDimitry Andric   if (Node) {
1190b57cec5SDimitry Andric     if (!isUniqueMachineInstValid(*Node)) {
1200b57cec5SDimitry Andric       invalidateUniqueMachineInstr(Node);
1210b57cec5SDimitry Andric       return nullptr;
1220b57cec5SDimitry Andric     }
1230b57cec5SDimitry Andric 
1240b57cec5SDimitry Andric     if (Node->MI->getParent() != MBB)
1250b57cec5SDimitry Andric       return nullptr;
1260b57cec5SDimitry Andric   }
1270b57cec5SDimitry Andric   return Node;
1280b57cec5SDimitry Andric }
1290b57cec5SDimitry Andric 
insertNode(UniqueMachineInstr * UMI,void * InsertPos)1300b57cec5SDimitry Andric void GISelCSEInfo::insertNode(UniqueMachineInstr *UMI, void *InsertPos) {
1310b57cec5SDimitry Andric   handleRecordedInsts();
1320b57cec5SDimitry Andric   assert(UMI);
1330b57cec5SDimitry Andric   UniqueMachineInstr *MaybeNewNode = UMI;
1340b57cec5SDimitry Andric   if (InsertPos)
1350b57cec5SDimitry Andric     CSEMap.InsertNode(UMI, InsertPos);
1360b57cec5SDimitry Andric   else
1370b57cec5SDimitry Andric     MaybeNewNode = CSEMap.GetOrInsertNode(UMI);
1380b57cec5SDimitry Andric   if (MaybeNewNode != UMI) {
1390b57cec5SDimitry Andric     // A similar node exists in the folding set. Let's ignore this one.
1400b57cec5SDimitry Andric     return;
1410b57cec5SDimitry Andric   }
1420b57cec5SDimitry Andric   assert(InstrMapping.count(UMI->MI) == 0 &&
1430b57cec5SDimitry Andric          "This instruction should not be in the map");
1440b57cec5SDimitry Andric   InstrMapping[UMI->MI] = MaybeNewNode;
1450b57cec5SDimitry Andric }
1460b57cec5SDimitry Andric 
getUniqueInstrForMI(const MachineInstr * MI)1470b57cec5SDimitry Andric UniqueMachineInstr *GISelCSEInfo::getUniqueInstrForMI(const MachineInstr *MI) {
1480b57cec5SDimitry Andric   assert(shouldCSE(MI->getOpcode()) && "Trying to CSE an unsupported Node");
1490b57cec5SDimitry Andric   auto *Node = new (UniqueInstrAllocator) UniqueMachineInstr(MI);
1500b57cec5SDimitry Andric   return Node;
1510b57cec5SDimitry Andric }
1520b57cec5SDimitry Andric 
insertInstr(MachineInstr * MI,void * InsertPos)1530b57cec5SDimitry Andric void GISelCSEInfo::insertInstr(MachineInstr *MI, void *InsertPos) {
1540b57cec5SDimitry Andric   assert(MI);
1550b57cec5SDimitry Andric   // If it exists in temporary insts, remove it.
1560b57cec5SDimitry Andric   TemporaryInsts.remove(MI);
1570b57cec5SDimitry Andric   auto *Node = getUniqueInstrForMI(MI);
1580b57cec5SDimitry Andric   insertNode(Node, InsertPos);
1590b57cec5SDimitry Andric }
1600b57cec5SDimitry Andric 
getMachineInstrIfExists(FoldingSetNodeID & ID,MachineBasicBlock * MBB,void * & InsertPos)1610b57cec5SDimitry Andric MachineInstr *GISelCSEInfo::getMachineInstrIfExists(FoldingSetNodeID &ID,
1620b57cec5SDimitry Andric                                                     MachineBasicBlock *MBB,
1630b57cec5SDimitry Andric                                                     void *&InsertPos) {
1640b57cec5SDimitry Andric   handleRecordedInsts();
1650b57cec5SDimitry Andric   if (auto *Inst = getNodeIfExists(ID, MBB, InsertPos)) {
1660b57cec5SDimitry Andric     LLVM_DEBUG(dbgs() << "CSEInfo::Found Instr " << *Inst->MI;);
1670b57cec5SDimitry Andric     return const_cast<MachineInstr *>(Inst->MI);
1680b57cec5SDimitry Andric   }
1690b57cec5SDimitry Andric   return nullptr;
1700b57cec5SDimitry Andric }
1710b57cec5SDimitry Andric 
countOpcodeHit(unsigned Opc)1720b57cec5SDimitry Andric void GISelCSEInfo::countOpcodeHit(unsigned Opc) {
1730b57cec5SDimitry Andric #ifndef NDEBUG
1740b57cec5SDimitry Andric   if (OpcodeHitTable.count(Opc))
1750b57cec5SDimitry Andric     OpcodeHitTable[Opc] += 1;
1760b57cec5SDimitry Andric   else
1770b57cec5SDimitry Andric     OpcodeHitTable[Opc] = 1;
1780b57cec5SDimitry Andric #endif
1790b57cec5SDimitry Andric   // Else do nothing.
1800b57cec5SDimitry Andric }
1810b57cec5SDimitry Andric 
recordNewInstruction(MachineInstr * MI)1820b57cec5SDimitry Andric void GISelCSEInfo::recordNewInstruction(MachineInstr *MI) {
1830b57cec5SDimitry Andric   if (shouldCSE(MI->getOpcode())) {
1840b57cec5SDimitry Andric     TemporaryInsts.insert(MI);
1850b57cec5SDimitry Andric     LLVM_DEBUG(dbgs() << "CSEInfo::Recording new MI " << *MI);
1860b57cec5SDimitry Andric   }
1870b57cec5SDimitry Andric }
1880b57cec5SDimitry Andric 
handleRecordedInst(MachineInstr * MI)1890b57cec5SDimitry Andric void GISelCSEInfo::handleRecordedInst(MachineInstr *MI) {
1900b57cec5SDimitry Andric   assert(shouldCSE(MI->getOpcode()) && "Invalid instruction for CSE");
1910b57cec5SDimitry Andric   auto *UMI = InstrMapping.lookup(MI);
1920b57cec5SDimitry Andric   LLVM_DEBUG(dbgs() << "CSEInfo::Handling recorded MI " << *MI);
1930b57cec5SDimitry Andric   if (UMI) {
1940b57cec5SDimitry Andric     // Invalidate this MI.
1950b57cec5SDimitry Andric     invalidateUniqueMachineInstr(UMI);
1960b57cec5SDimitry Andric     InstrMapping.erase(MI);
1970b57cec5SDimitry Andric   }
1980b57cec5SDimitry Andric   /// Now insert the new instruction.
1990b57cec5SDimitry Andric   if (UMI) {
2000b57cec5SDimitry Andric     /// We'll reuse the same UniqueMachineInstr to avoid the new
2010b57cec5SDimitry Andric     /// allocation.
2020b57cec5SDimitry Andric     *UMI = UniqueMachineInstr(MI);
2030b57cec5SDimitry Andric     insertNode(UMI, nullptr);
2040b57cec5SDimitry Andric   } else {
2050b57cec5SDimitry Andric     /// This is a new instruction. Allocate a new UniqueMachineInstr and
2060b57cec5SDimitry Andric     /// Insert.
2070b57cec5SDimitry Andric     insertInstr(MI);
2080b57cec5SDimitry Andric   }
2090b57cec5SDimitry Andric }
2100b57cec5SDimitry Andric 
handleRemoveInst(MachineInstr * MI)2110b57cec5SDimitry Andric void GISelCSEInfo::handleRemoveInst(MachineInstr *MI) {
2120b57cec5SDimitry Andric   if (auto *UMI = InstrMapping.lookup(MI)) {
2130b57cec5SDimitry Andric     invalidateUniqueMachineInstr(UMI);
2140b57cec5SDimitry Andric     InstrMapping.erase(MI);
2150b57cec5SDimitry Andric   }
2160b57cec5SDimitry Andric   TemporaryInsts.remove(MI);
2170b57cec5SDimitry Andric }
2180b57cec5SDimitry Andric 
handleRecordedInsts()2190b57cec5SDimitry Andric void GISelCSEInfo::handleRecordedInsts() {
22006c3fb27SDimitry Andric   if (HandlingRecordedInstrs)
22106c3fb27SDimitry Andric     return;
22206c3fb27SDimitry Andric   HandlingRecordedInstrs = true;
2230b57cec5SDimitry Andric   while (!TemporaryInsts.empty()) {
2240b57cec5SDimitry Andric     auto *MI = TemporaryInsts.pop_back_val();
2250b57cec5SDimitry Andric     handleRecordedInst(MI);
2260b57cec5SDimitry Andric   }
22706c3fb27SDimitry Andric   HandlingRecordedInstrs = false;
2280b57cec5SDimitry Andric }
2290b57cec5SDimitry Andric 
shouldCSE(unsigned Opc) const2300b57cec5SDimitry Andric bool GISelCSEInfo::shouldCSE(unsigned Opc) const {
2310b57cec5SDimitry Andric   assert(CSEOpt.get() && "CSEConfig not set");
2320b57cec5SDimitry Andric   return CSEOpt->shouldCSEOpc(Opc);
2330b57cec5SDimitry Andric }
2340b57cec5SDimitry Andric 
erasingInstr(MachineInstr & MI)2350b57cec5SDimitry Andric void GISelCSEInfo::erasingInstr(MachineInstr &MI) { handleRemoveInst(&MI); }
createdInstr(MachineInstr & MI)2360b57cec5SDimitry Andric void GISelCSEInfo::createdInstr(MachineInstr &MI) { recordNewInstruction(&MI); }
changingInstr(MachineInstr & MI)2370b57cec5SDimitry Andric void GISelCSEInfo::changingInstr(MachineInstr &MI) {
2380b57cec5SDimitry Andric   // For now, perform erase, followed by insert.
2390b57cec5SDimitry Andric   erasingInstr(MI);
2400b57cec5SDimitry Andric   createdInstr(MI);
2410b57cec5SDimitry Andric }
changedInstr(MachineInstr & MI)2420b57cec5SDimitry Andric void GISelCSEInfo::changedInstr(MachineInstr &MI) { changingInstr(MI); }
2430b57cec5SDimitry Andric 
analyze(MachineFunction & MF)2440b57cec5SDimitry Andric void GISelCSEInfo::analyze(MachineFunction &MF) {
2450b57cec5SDimitry Andric   setMF(MF);
2460b57cec5SDimitry Andric   for (auto &MBB : MF) {
2470b57cec5SDimitry Andric     for (MachineInstr &MI : MBB) {
2480b57cec5SDimitry Andric       if (!shouldCSE(MI.getOpcode()))
2490b57cec5SDimitry Andric         continue;
2500b57cec5SDimitry Andric       LLVM_DEBUG(dbgs() << "CSEInfo::Add MI: " << MI);
2510b57cec5SDimitry Andric       insertInstr(&MI);
2520b57cec5SDimitry Andric     }
2530b57cec5SDimitry Andric   }
2540b57cec5SDimitry Andric }
2550b57cec5SDimitry Andric 
releaseMemory()2560b57cec5SDimitry Andric void GISelCSEInfo::releaseMemory() {
2570b57cec5SDimitry Andric   print();
2580b57cec5SDimitry Andric   CSEMap.clear();
2590b57cec5SDimitry Andric   InstrMapping.clear();
2600b57cec5SDimitry Andric   UniqueInstrAllocator.Reset();
2610b57cec5SDimitry Andric   TemporaryInsts.clear();
2620b57cec5SDimitry Andric   CSEOpt.reset();
2630b57cec5SDimitry Andric   MRI = nullptr;
2640b57cec5SDimitry Andric   MF = nullptr;
2650b57cec5SDimitry Andric #ifndef NDEBUG
2660b57cec5SDimitry Andric   OpcodeHitTable.clear();
2670b57cec5SDimitry Andric #endif
2680b57cec5SDimitry Andric }
2690b57cec5SDimitry Andric 
270fe6060f1SDimitry Andric #ifndef NDEBUG
stringify(const MachineInstr * MI,std::string & S)271fe6060f1SDimitry Andric static const char *stringify(const MachineInstr *MI, std::string &S) {
272fe6060f1SDimitry Andric   raw_string_ostream OS(S);
273fe6060f1SDimitry Andric   OS << *MI;
274fe6060f1SDimitry Andric   return OS.str().c_str();
275fe6060f1SDimitry Andric }
276fe6060f1SDimitry Andric #endif
277fe6060f1SDimitry Andric 
verify()2785ffd83dbSDimitry Andric Error GISelCSEInfo::verify() {
2795ffd83dbSDimitry Andric #ifndef NDEBUG
280fe6060f1SDimitry Andric   std::string S1, S2;
2815ffd83dbSDimitry Andric   handleRecordedInsts();
2825ffd83dbSDimitry Andric   // For each instruction in map from MI -> UMI,
2835ffd83dbSDimitry Andric   // Profile(MI) and make sure UMI is found for that profile.
2845ffd83dbSDimitry Andric   for (auto &It : InstrMapping) {
2855ffd83dbSDimitry Andric     FoldingSetNodeID TmpID;
2865ffd83dbSDimitry Andric     GISelInstProfileBuilder(TmpID, *MRI).addNodeID(It.first);
2875ffd83dbSDimitry Andric     void *InsertPos;
2885ffd83dbSDimitry Andric     UniqueMachineInstr *FoundNode =
2895ffd83dbSDimitry Andric         CSEMap.FindNodeOrInsertPos(TmpID, InsertPos);
2905ffd83dbSDimitry Andric     if (FoundNode != It.second)
2915ffd83dbSDimitry Andric       return createStringError(std::errc::not_supported,
2925ffd83dbSDimitry Andric                                "CSEMap mismatch, InstrMapping has MIs without "
293fe6060f1SDimitry Andric                                "corresponding Nodes in CSEMap:\n%s",
294fe6060f1SDimitry Andric                                stringify(It.second->MI, S1));
2955ffd83dbSDimitry Andric   }
2965ffd83dbSDimitry Andric 
2975ffd83dbSDimitry Andric   // For every node in the CSEMap, make sure that the InstrMapping
2985ffd83dbSDimitry Andric   // points to it.
299fe6060f1SDimitry Andric   for (const UniqueMachineInstr &UMI : CSEMap) {
3005ffd83dbSDimitry Andric     if (!InstrMapping.count(UMI.MI))
3015ffd83dbSDimitry Andric       return createStringError(std::errc::not_supported,
302fe6060f1SDimitry Andric                                "Node in CSE without InstrMapping:\n%s",
303fe6060f1SDimitry Andric                                stringify(UMI.MI, S1));
3045ffd83dbSDimitry Andric 
3055ffd83dbSDimitry Andric     if (InstrMapping[UMI.MI] != &UMI)
3065ffd83dbSDimitry Andric       return createStringError(std::make_error_code(std::errc::not_supported),
307fe6060f1SDimitry Andric                                "Mismatch in CSE mapping:\n%s\n%s",
308fe6060f1SDimitry Andric                                stringify(InstrMapping[UMI.MI]->MI, S1),
309fe6060f1SDimitry Andric                                stringify(UMI.MI, S2));
3105ffd83dbSDimitry Andric   }
3115ffd83dbSDimitry Andric #endif
3125ffd83dbSDimitry Andric   return Error::success();
3135ffd83dbSDimitry Andric }
3145ffd83dbSDimitry Andric 
print()3150b57cec5SDimitry Andric void GISelCSEInfo::print() {
3160b57cec5SDimitry Andric   LLVM_DEBUG(for (auto &It
3170b57cec5SDimitry Andric                   : OpcodeHitTable) {
3180b57cec5SDimitry Andric     dbgs() << "CSEInfo::CSE Hit for Opc " << It.first << " : " << It.second
3190b57cec5SDimitry Andric            << "\n";
3200b57cec5SDimitry Andric   };);
3210b57cec5SDimitry Andric }
3220b57cec5SDimitry Andric /// -----------------------------------------
3230b57cec5SDimitry Andric // ---- Profiling methods for FoldingSetNode --- //
3240b57cec5SDimitry Andric const GISelInstProfileBuilder &
addNodeID(const MachineInstr * MI) const3250b57cec5SDimitry Andric GISelInstProfileBuilder::addNodeID(const MachineInstr *MI) const {
3260b57cec5SDimitry Andric   addNodeIDMBB(MI->getParent());
3270b57cec5SDimitry Andric   addNodeIDOpcode(MI->getOpcode());
328fcaf7f86SDimitry Andric   for (const auto &Op : MI->operands())
3290b57cec5SDimitry Andric     addNodeIDMachineOperand(Op);
3300b57cec5SDimitry Andric   addNodeIDFlag(MI->getFlags());
3310b57cec5SDimitry Andric   return *this;
3320b57cec5SDimitry Andric }
3330b57cec5SDimitry Andric 
3340b57cec5SDimitry Andric const GISelInstProfileBuilder &
addNodeIDOpcode(unsigned Opc) const3350b57cec5SDimitry Andric GISelInstProfileBuilder::addNodeIDOpcode(unsigned Opc) const {
3360b57cec5SDimitry Andric   ID.AddInteger(Opc);
3370b57cec5SDimitry Andric   return *this;
3380b57cec5SDimitry Andric }
3390b57cec5SDimitry Andric 
3400b57cec5SDimitry Andric const GISelInstProfileBuilder &
addNodeIDRegType(const LLT Ty) const3415ffd83dbSDimitry Andric GISelInstProfileBuilder::addNodeIDRegType(const LLT Ty) const {
3420b57cec5SDimitry Andric   uint64_t Val = Ty.getUniqueRAWLLTData();
3430b57cec5SDimitry Andric   ID.AddInteger(Val);
3440b57cec5SDimitry Andric   return *this;
3450b57cec5SDimitry Andric }
3460b57cec5SDimitry Andric 
3470b57cec5SDimitry Andric const GISelInstProfileBuilder &
addNodeIDRegType(const TargetRegisterClass * RC) const3480b57cec5SDimitry Andric GISelInstProfileBuilder::addNodeIDRegType(const TargetRegisterClass *RC) const {
3490b57cec5SDimitry Andric   ID.AddPointer(RC);
3500b57cec5SDimitry Andric   return *this;
3510b57cec5SDimitry Andric }
3520b57cec5SDimitry Andric 
3530b57cec5SDimitry Andric const GISelInstProfileBuilder &
addNodeIDRegType(const RegisterBank * RB) const3540b57cec5SDimitry Andric GISelInstProfileBuilder::addNodeIDRegType(const RegisterBank *RB) const {
3550b57cec5SDimitry Andric   ID.AddPointer(RB);
3560b57cec5SDimitry Andric   return *this;
3570b57cec5SDimitry Andric }
3580b57cec5SDimitry Andric 
3590b57cec5SDimitry Andric const GISelInstProfileBuilder &
addNodeIDImmediate(int64_t Imm) const3600b57cec5SDimitry Andric GISelInstProfileBuilder::addNodeIDImmediate(int64_t Imm) const {
3610b57cec5SDimitry Andric   ID.AddInteger(Imm);
3620b57cec5SDimitry Andric   return *this;
3630b57cec5SDimitry Andric }
3640b57cec5SDimitry Andric 
3650b57cec5SDimitry Andric const GISelInstProfileBuilder &
addNodeIDRegNum(Register Reg) const3665ffd83dbSDimitry Andric GISelInstProfileBuilder::addNodeIDRegNum(Register Reg) const {
3670b57cec5SDimitry Andric   ID.AddInteger(Reg);
3680b57cec5SDimitry Andric   return *this;
3690b57cec5SDimitry Andric }
3700b57cec5SDimitry Andric 
3710b57cec5SDimitry Andric const GISelInstProfileBuilder &
addNodeIDRegType(const Register Reg) const3725ffd83dbSDimitry Andric GISelInstProfileBuilder::addNodeIDRegType(const Register Reg) const {
3730b57cec5SDimitry Andric   addNodeIDMachineOperand(MachineOperand::CreateReg(Reg, false));
3740b57cec5SDimitry Andric   return *this;
3750b57cec5SDimitry Andric }
3760b57cec5SDimitry Andric 
3770b57cec5SDimitry Andric const GISelInstProfileBuilder &
addNodeIDMBB(const MachineBasicBlock * MBB) const3780b57cec5SDimitry Andric GISelInstProfileBuilder::addNodeIDMBB(const MachineBasicBlock *MBB) const {
3790b57cec5SDimitry Andric   ID.AddPointer(MBB);
3800b57cec5SDimitry Andric   return *this;
3810b57cec5SDimitry Andric }
3820b57cec5SDimitry Andric 
3830b57cec5SDimitry Andric const GISelInstProfileBuilder &
addNodeIDFlag(unsigned Flag) const3840b57cec5SDimitry Andric GISelInstProfileBuilder::addNodeIDFlag(unsigned Flag) const {
3850b57cec5SDimitry Andric   if (Flag)
3860b57cec5SDimitry Andric     ID.AddInteger(Flag);
3870b57cec5SDimitry Andric   return *this;
3880b57cec5SDimitry Andric }
3890b57cec5SDimitry Andric 
390e8d8bef9SDimitry Andric const GISelInstProfileBuilder &
addNodeIDReg(Register Reg) const391e8d8bef9SDimitry Andric GISelInstProfileBuilder::addNodeIDReg(Register Reg) const {
3920b57cec5SDimitry Andric   LLT Ty = MRI.getType(Reg);
3930b57cec5SDimitry Andric   if (Ty.isValid())
3940b57cec5SDimitry Andric     addNodeIDRegType(Ty);
3955ffd83dbSDimitry Andric 
3965ffd83dbSDimitry Andric   if (const RegClassOrRegBank &RCOrRB = MRI.getRegClassOrRegBank(Reg)) {
39706c3fb27SDimitry Andric     if (const auto *RB = dyn_cast_if_present<const RegisterBank *>(RCOrRB))
3980b57cec5SDimitry Andric       addNodeIDRegType(RB);
39906c3fb27SDimitry Andric     else if (const auto *RC =
40006c3fb27SDimitry Andric                  dyn_cast_if_present<const TargetRegisterClass *>(RCOrRB))
4010b57cec5SDimitry Andric       addNodeIDRegType(RC);
4025ffd83dbSDimitry Andric   }
403e8d8bef9SDimitry Andric   return *this;
404e8d8bef9SDimitry Andric }
4055ffd83dbSDimitry Andric 
addNodeIDMachineOperand(const MachineOperand & MO) const406e8d8bef9SDimitry Andric const GISelInstProfileBuilder &GISelInstProfileBuilder::addNodeIDMachineOperand(
407e8d8bef9SDimitry Andric     const MachineOperand &MO) const {
408e8d8bef9SDimitry Andric   if (MO.isReg()) {
409e8d8bef9SDimitry Andric     Register Reg = MO.getReg();
410e8d8bef9SDimitry Andric     if (!MO.isDef())
411e8d8bef9SDimitry Andric       addNodeIDRegNum(Reg);
412e8d8bef9SDimitry Andric 
413e8d8bef9SDimitry Andric     // Profile the register properties.
414e8d8bef9SDimitry Andric     addNodeIDReg(Reg);
4150b57cec5SDimitry Andric     assert(!MO.isImplicit() && "Unhandled case");
4160b57cec5SDimitry Andric   } else if (MO.isImm())
4170b57cec5SDimitry Andric     ID.AddInteger(MO.getImm());
4180b57cec5SDimitry Andric   else if (MO.isCImm())
4190b57cec5SDimitry Andric     ID.AddPointer(MO.getCImm());
4200b57cec5SDimitry Andric   else if (MO.isFPImm())
4210b57cec5SDimitry Andric     ID.AddPointer(MO.getFPImm());
4220b57cec5SDimitry Andric   else if (MO.isPredicate())
4230b57cec5SDimitry Andric     ID.AddInteger(MO.getPredicate());
4240b57cec5SDimitry Andric   else
4250b57cec5SDimitry Andric     llvm_unreachable("Unhandled operand type");
4260b57cec5SDimitry Andric   // Handle other types
4270b57cec5SDimitry Andric   return *this;
4280b57cec5SDimitry Andric }
4290b57cec5SDimitry Andric 
4300b57cec5SDimitry Andric GISelCSEInfo &
get(std::unique_ptr<CSEConfigBase> CSEOpt,bool Recompute)4310b57cec5SDimitry Andric GISelCSEAnalysisWrapper::get(std::unique_ptr<CSEConfigBase> CSEOpt,
4320b57cec5SDimitry Andric                              bool Recompute) {
4330b57cec5SDimitry Andric   if (!AlreadyComputed || Recompute) {
4345ffd83dbSDimitry Andric     Info.releaseMemory();
4350b57cec5SDimitry Andric     Info.setCSEConfig(std::move(CSEOpt));
4360b57cec5SDimitry Andric     Info.analyze(*MF);
4370b57cec5SDimitry Andric     AlreadyComputed = true;
4380b57cec5SDimitry Andric   }
4390b57cec5SDimitry Andric   return Info;
4400b57cec5SDimitry Andric }
getAnalysisUsage(AnalysisUsage & AU) const4410b57cec5SDimitry Andric void GISelCSEAnalysisWrapperPass::getAnalysisUsage(AnalysisUsage &AU) const {
4420b57cec5SDimitry Andric   AU.setPreservesAll();
4430b57cec5SDimitry Andric   MachineFunctionPass::getAnalysisUsage(AU);
4440b57cec5SDimitry Andric }
4450b57cec5SDimitry Andric 
runOnMachineFunction(MachineFunction & MF)4460b57cec5SDimitry Andric bool GISelCSEAnalysisWrapperPass::runOnMachineFunction(MachineFunction &MF) {
4470b57cec5SDimitry Andric   releaseMemory();
4480b57cec5SDimitry Andric   Wrapper.setMF(MF);
4490b57cec5SDimitry Andric   return false;
4500b57cec5SDimitry Andric }
451