Index: llvm/include/llvm/CodeGen/GlobalISel/CSEInfo.h =================================================================== --- llvm/include/llvm/CodeGen/GlobalISel/CSEInfo.h +++ llvm/include/llvm/CodeGen/GlobalISel/CSEInfo.h @@ -120,6 +120,8 @@ void setMF(MachineFunction &MF); + void verify(); + /// Records a newly created inst in a list and lazily insert it to the CSEMap. /// Sometimes, this method might be called with a partially constructed /// MachineInstr, Index: llvm/include/llvm/CodeGen/GlobalISel/GISelChangeObserver.h =================================================================== --- llvm/include/llvm/CodeGen/GlobalISel/GISelChangeObserver.h +++ llvm/include/llvm/CodeGen/GlobalISel/GISelChangeObserver.h @@ -113,5 +113,16 @@ ~RAIIDelegateInstaller(); }; +/// A simple RAII based Observer installer. +/// Use this in a scope to install the Observer to the MachineFunction and reset +/// it at the end of the scope. +class RAIIMFObserverInstaller { + MachineFunction &MF; + +public: + RAIIMFObserverInstaller(MachineFunction &MF, GISelChangeObserver &Observer); + ~RAIIMFObserverInstaller(); +}; + } // namespace llvm #endif Index: llvm/include/llvm/CodeGen/MachineFunction.h =================================================================== --- llvm/include/llvm/CodeGen/MachineFunction.h +++ llvm/include/llvm/CodeGen/MachineFunction.h @@ -71,6 +71,7 @@ class TargetSubtargetInfo; struct WasmEHFuncInfo; struct WinEHFuncInfo; +class GISelChangeObserver; template <> struct ilist_alloc_traits { void deleteNode(MachineBasicBlock *MBB); @@ -395,6 +396,7 @@ private: Delegate *TheDelegate = nullptr; + GISelChangeObserver *Observer = nullptr; using CallSiteInfoMap = DenseMap; /// Map a call instruction to call site arguments forwarding info. @@ -439,6 +441,10 @@ TheDelegate = delegate; } + void setObserver(GISelChangeObserver *O) { Observer = O; } + + GISelChangeObserver *getObserver() const { return Observer; } + MachineModuleInfo &getMMI() const { return MMI; } MCContext &getContext() const { return Ctx; } Index: llvm/lib/CodeGen/GlobalISel/CSEInfo.cpp =================================================================== --- llvm/lib/CodeGen/GlobalISel/CSEInfo.cpp +++ llvm/lib/CodeGen/GlobalISel/CSEInfo.cpp @@ -255,6 +255,34 @@ #endif } +void GISelCSEInfo::verify() { +#ifndef NDEBUG + handleRecordedInsts(); + // For each instruction in map from MI -> UMI, + // Profile(MI) and make sure UMI is found for that profile. + for (auto &It : InstrMapping) { + FoldingSetNodeID TmpID; + GISelInstProfileBuilder(TmpID, *MRI).addNodeID(It.first); + void *InsertPos; + UniqueMachineInstr *FoundNode = + CSEMap.FindNodeOrInsertPos(TmpID, InsertPos); + if (FoundNode != It.second) + LLVM_DEBUG(dbgs() << "Instr mismatch :" << *It.first;); + assert(FoundNode == It.second && "CSEMap mismatch. InstrMapping has MIs " + "without corresponding Nodes in CSEMap"); + } + + // For every node in the CSEMap, make sure that the InstrMapping + // points to it. + for (auto It = CSEMap.begin(), End = CSEMap.end(); It != End; ++It) { + const UniqueMachineInstr &UMI = *It; + assert(InstrMapping.count(UMI.MI) && "Node in CSE without InstrMapping"); + assert(InstrMapping[UMI.MI] == &UMI && + "Node in CSE with incorrect InstrMapping"); + } +#endif +} + void GISelCSEInfo::print() { LLVM_DEBUG(for (auto &It : OpcodeHitTable) { @@ -364,6 +392,7 @@ GISelCSEAnalysisWrapper::get(std::unique_ptr CSEOpt, bool Recompute) { if (!AlreadyComputed || Recompute) { + Info.releaseMemory(); Info.setCSEConfig(std::move(CSEOpt)); Info.analyze(*MF); AlreadyComputed = true; Index: llvm/lib/CodeGen/GlobalISel/GISelChangeObserver.cpp =================================================================== --- llvm/lib/CodeGen/GlobalISel/GISelChangeObserver.cpp +++ llvm/lib/CodeGen/GlobalISel/GISelChangeObserver.cpp @@ -38,3 +38,11 @@ } RAIIDelegateInstaller::~RAIIDelegateInstaller() { MF.resetDelegate(Delegate); } + +RAIIMFObserverInstaller::RAIIMFObserverInstaller(MachineFunction &MF, + GISelChangeObserver &Observer) + : MF(MF) { + MF.setObserver(&Observer); +} + +RAIIMFObserverInstaller::~RAIIMFObserverInstaller() { MF.setObserver(nullptr); } Index: llvm/lib/CodeGen/GlobalISel/IRTranslator.cpp =================================================================== --- llvm/lib/CodeGen/GlobalISel/IRTranslator.cpp +++ llvm/lib/CodeGen/GlobalISel/IRTranslator.cpp @@ -2269,6 +2269,7 @@ WrapperObserver.addObserver(&Verifier); #endif // ifndef NDEBUG RAIIDelegateInstaller DelInstall(*MF, &WrapperObserver); + RAIIMFObserverInstaller ObsInstall(*MF, WrapperObserver); for (const BasicBlock *BB : RPOT) { MachineBasicBlock &MBB = getMBB(*BB); // Set the insertion point of all the following translations to Index: llvm/lib/CodeGen/GlobalISel/Legalizer.cpp =================================================================== --- llvm/lib/CodeGen/GlobalISel/Legalizer.cpp +++ llvm/lib/CodeGen/GlobalISel/Legalizer.cpp @@ -199,6 +199,7 @@ // Now install the observer as the delegate to MF. // This will keep all the observers notified about new insertions/deletions. RAIIDelegateInstaller DelInstall(MF, &WrapperObserver); + RAIIMFObserverInstaller ObsInstall(MF, WrapperObserver); LegalizerHelper Helper(MF, WrapperObserver, *MIRBuilder.get()); const LegalizerInfo &LInfo(Helper.getLegalizerInfo()); LegalizationArtifactCombiner ArtCombiner(*MIRBuilder.get(), MF.getRegInfo(), @@ -294,6 +295,8 @@ reportGISelFailure(MF, TPC, MORE, R); return false; } + if (CSEInfo) + CSEInfo->verify(); return Changed; } Index: llvm/lib/CodeGen/GlobalISel/Utils.cpp =================================================================== --- llvm/lib/CodeGen/GlobalISel/Utils.cpp +++ llvm/lib/CodeGen/GlobalISel/Utils.cpp @@ -12,6 +12,7 @@ #include "llvm/CodeGen/GlobalISel/Utils.h" #include "llvm/ADT/APFloat.h" #include "llvm/ADT/Twine.h" +#include "llvm/CodeGen/GlobalISel/GISelChangeObserver.h" #include "llvm/CodeGen/GlobalISel/RegisterBankInfo.h" #include "llvm/CodeGen/MachineInstr.h" #include "llvm/CodeGen/MachineInstrBuilder.h" @@ -63,6 +64,15 @@ TII.get(TargetOpcode::COPY), Reg) .addReg(ConstrainedReg); } + } else { + if (GISelChangeObserver *Observer = MF.getObserver()) { + if (!RegMO.isDef()) { + MachineInstr *RegDef = MRI.getVRegDef(Reg); + Observer->changedInstr(*RegDef); + } + Observer->changingAllUsesOfReg(MRI, Reg); + Observer->finishedChangingAllUsesOfReg(); + } } return ConstrainedReg; }