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); + Error 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 @@ -101,7 +101,7 @@ void MF_HandleRemoval(MachineInstr &MI) override { erasingInstr(MI); } }; -/// A simple RAII based CSEInfo installer. +/// A simple RAII based Delegate installer. /// Use this in a scope to install a delegate to the MachineFunction and reset /// it at the end of the scope. class RAIIDelegateInstaller { @@ -113,5 +113,27 @@ ~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(); +}; + +/// Class to install both of the above. +class RAIIMFObsDelInstaller { + RAIIDelegateInstaller DelI; + RAIIMFObserverInstaller ObsI; + +public: + RAIIMFObsDelInstaller(MachineFunction &MF, GISelObserverWrapper &Wrapper) + : DelI(MF, &Wrapper), ObsI(MF, Wrapper) {} + ~RAIIMFObsDelInstaller() = default; +}; + } // namespace llvm #endif Index: llvm/include/llvm/CodeGen/MachineFunction.h =================================================================== --- llvm/include/llvm/CodeGen/MachineFunction.h +++ llvm/include/llvm/CodeGen/MachineFunction.h @@ -72,6 +72,7 @@ class TargetSubtargetInfo; struct WasmEHFuncInfo; struct WinEHFuncInfo; +class GISelChangeObserver; template <> struct ilist_alloc_traits { void deleteNode(MachineBasicBlock *MBB); @@ -396,6 +397,7 @@ private: Delegate *TheDelegate = nullptr; + GISelChangeObserver *Observer = nullptr; using CallSiteInfoMap = DenseMap; /// Map a call instruction to call site arguments forwarding info. @@ -444,6 +446,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 @@ -261,6 +261,39 @@ #endif } +Error 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) + return createStringError(std::make_error_code(std::errc::not_supported), + "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; + if (!InstrMapping.count(UMI.MI)) + return createStringError(std::make_error_code(std::errc::not_supported), + "Node in CSE without InstrMapping", UMI.MI); + + if (InstrMapping[UMI.MI] != &UMI) + return createStringError(std::make_error_code(std::errc::not_supported), + "Mismatch in CSE mapping"); + } +#endif + return Error::success(); +} + void GISelCSEInfo::print() { LLVM_DEBUG(for (auto &It : OpcodeHitTable) { @@ -370,6 +403,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 @@ -2381,6 +2381,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 @@ -28,6 +28,7 @@ #include "llvm/CodeGen/TargetSubtargetInfo.h" #include "llvm/InitializePasses.h" #include "llvm/Support/Debug.h" +#include "llvm/Support/Error.h" #include "llvm/Target/TargetMachine.h" #include @@ -180,7 +181,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); + RAIIMFObsDelInstaller Installer(MF, WrapperObserver); LegalizerHelper Helper(MF, LI, WrapperObserver, MIRBuilder); LegalizationArtifactCombiner ArtCombiner(MIRBuilder, MRI, LI); auto RemoveDeadInstFromLists = [&WrapperObserver](MachineInstr *DeadMI) { @@ -305,6 +306,7 @@ // We want CSEInfo in addition to WorkListObserver to observe all changes. AuxObservers.push_back(CSEInfo); } + assert(!CSEInfo || !errorToBool(CSEInfo->verify())); const LegalizerInfo &LI = *MF.getSubtarget().getLegalizerInfo(); MFResult Result = legalizeMachineFunction(MF, LI, AuxObservers, *MIRBuilder); @@ -324,5 +326,11 @@ reportGISelFailure(MF, TPC, MORE, R); return false; } + // If for some reason CSE was not enabled, make sure that we invalidate the + // CSEInfo object (as we currently declare that the analysis is preserved). + // The next time get on the wrapper is called, it will force it to recompute + // the analysis. + if (!EnableCSE) + Wrapper.setComputed(false); return Result.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" @@ -62,6 +63,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; }