GISelChangeObserver.h revision 343171
1343171Sdim//===----- llvm/CodeGen/GlobalISel/GISelChangeObserver.h ------------------===// 2343171Sdim// 3343171Sdim// The LLVM Compiler Infrastructure 4343171Sdim// 5343171Sdim// This file is distributed under the University of Illinois Open Source 6343171Sdim// License. See LICENSE.TXT for details. 7343171Sdim// 8343171Sdim//===----------------------------------------------------------------------===// 9343171Sdim// 10343171Sdim/// This contains common code to allow clients to notify changes to machine 11343171Sdim/// instr. 12343171Sdim// 13343171Sdim//===----------------------------------------------------------------------===// 14343171Sdim#ifndef LLVM_CODEGEN_GLOBALISEL_GISELCHANGEOBSERVER_H 15343171Sdim#define LLVM_CODEGEN_GLOBALISEL_GISELCHANGEOBSERVER_H 16343171Sdim 17343171Sdim#include "llvm/ADT/SmallPtrSet.h" 18343171Sdim#include "llvm/CodeGen/MachineFunction.h" 19343171Sdim 20343171Sdimnamespace llvm { 21343171Sdimclass MachineInstr; 22343171Sdimclass MachineRegisterInfo; 23343171Sdim 24343171Sdim/// Abstract class that contains various methods for clients to notify about 25343171Sdim/// changes. This should be the preferred way for APIs to notify changes. 26343171Sdim/// Typically calling erasingInstr/createdInstr multiple times should not affect 27343171Sdim/// the result. The observer would likely need to check if it was already 28343171Sdim/// notified earlier (consider using GISelWorkList). 29343171Sdimclass GISelChangeObserver { 30343171Sdim SmallPtrSet<MachineInstr *, 4> ChangingAllUsesOfReg; 31343171Sdim 32343171Sdimpublic: 33343171Sdim virtual ~GISelChangeObserver() {} 34343171Sdim 35343171Sdim /// An instruction is about to be erased. 36343171Sdim virtual void erasingInstr(MachineInstr &MI) = 0; 37343171Sdim /// An instruction was created and inserted into the function. 38343171Sdim virtual void createdInstr(MachineInstr &MI) = 0; 39343171Sdim /// This instruction is about to be mutated in some way. 40343171Sdim virtual void changingInstr(MachineInstr &MI) = 0; 41343171Sdim /// This instruction was mutated in some way. 42343171Sdim virtual void changedInstr(MachineInstr &MI) = 0; 43343171Sdim 44343171Sdim /// All the instructions using the given register are being changed. 45343171Sdim /// For convenience, finishedChangingAllUsesOfReg() will report the completion 46343171Sdim /// of the changes. The use list may change between this call and 47343171Sdim /// finishedChangingAllUsesOfReg(). 48343171Sdim void changingAllUsesOfReg(const MachineRegisterInfo &MRI, unsigned Reg); 49343171Sdim /// All instructions reported as changing by changingAllUsesOfReg() have 50343171Sdim /// finished being changed. 51343171Sdim void finishedChangingAllUsesOfReg(); 52343171Sdim 53343171Sdim}; 54343171Sdim 55343171Sdim/// Simple wrapper observer that takes several observers, and calls 56343171Sdim/// each one for each event. If there are multiple observers (say CSE, 57343171Sdim/// Legalizer, Combiner), it's sufficient to register this to the machine 58343171Sdim/// function as the delegate. 59343171Sdimclass GISelObserverWrapper : public MachineFunction::Delegate, 60343171Sdim public GISelChangeObserver { 61343171Sdim SmallVector<GISelChangeObserver *, 4> Observers; 62343171Sdim 63343171Sdimpublic: 64343171Sdim GISelObserverWrapper() = default; 65343171Sdim GISelObserverWrapper(ArrayRef<GISelChangeObserver *> Obs) 66343171Sdim : Observers(Obs.begin(), Obs.end()) {} 67343171Sdim // Adds an observer. 68343171Sdim void addObserver(GISelChangeObserver *O) { Observers.push_back(O); } 69343171Sdim // Removes an observer from the list and does nothing if observer is not 70343171Sdim // present. 71343171Sdim void removeObserver(GISelChangeObserver *O) { 72343171Sdim auto It = std::find(Observers.begin(), Observers.end(), O); 73343171Sdim if (It != Observers.end()) 74343171Sdim Observers.erase(It); 75343171Sdim } 76343171Sdim // API for Observer. 77343171Sdim void erasingInstr(MachineInstr &MI) override { 78343171Sdim for (auto &O : Observers) 79343171Sdim O->erasingInstr(MI); 80343171Sdim } 81343171Sdim void createdInstr(MachineInstr &MI) override { 82343171Sdim for (auto &O : Observers) 83343171Sdim O->createdInstr(MI); 84343171Sdim } 85343171Sdim void changingInstr(MachineInstr &MI) override { 86343171Sdim for (auto &O : Observers) 87343171Sdim O->changingInstr(MI); 88343171Sdim } 89343171Sdim void changedInstr(MachineInstr &MI) override { 90343171Sdim for (auto &O : Observers) 91343171Sdim O->changedInstr(MI); 92343171Sdim } 93343171Sdim // API for MachineFunction::Delegate 94343171Sdim void MF_HandleInsertion(MachineInstr &MI) override { createdInstr(MI); } 95343171Sdim void MF_HandleRemoval(MachineInstr &MI) override { erasingInstr(MI); } 96343171Sdim}; 97343171Sdim 98343171Sdim/// A simple RAII based CSEInfo installer. 99343171Sdim/// Use this in a scope to install a delegate to the MachineFunction and reset 100343171Sdim/// it at the end of the scope. 101343171Sdimclass RAIIDelegateInstaller { 102343171Sdim MachineFunction &MF; 103343171Sdim MachineFunction::Delegate *Delegate; 104343171Sdim 105343171Sdimpublic: 106343171Sdim RAIIDelegateInstaller(MachineFunction &MF, MachineFunction::Delegate *Del); 107343171Sdim ~RAIIDelegateInstaller(); 108343171Sdim}; 109343171Sdim 110343171Sdim} // namespace llvm 111343171Sdim#endif 112