1 //===----- llvm/CodeGen/GlobalISel/GISelChangeObserver.h ------------------===// 2 // 3 // The LLVM Compiler Infrastructure 4 // 5 // This file is distributed under the University of Illinois Open Source 6 // License. See LICENSE.TXT for details. 7 // 8 //===----------------------------------------------------------------------===// 9 // 10 /// This contains common code to allow clients to notify changes to machine 11 /// instr. 12 // 13 //===----------------------------------------------------------------------===// 14 #ifndef LLVM_CODEGEN_GLOBALISEL_GISELCHANGEOBSERVER_H 15 #define LLVM_CODEGEN_GLOBALISEL_GISELCHANGEOBSERVER_H 16 17 #include "llvm/ADT/SmallPtrSet.h" 18 #include "llvm/CodeGen/MachineFunction.h" 19 20 namespace llvm { 21 class MachineInstr; 22 class MachineRegisterInfo; 23 24 /// Abstract class that contains various methods for clients to notify about 25 /// changes. This should be the preferred way for APIs to notify changes. 26 /// Typically calling erasingInstr/createdInstr multiple times should not affect 27 /// the result. The observer would likely need to check if it was already 28 /// notified earlier (consider using GISelWorkList). 29 class GISelChangeObserver { 30 SmallPtrSet<MachineInstr *, 4> ChangingAllUsesOfReg; 31 32 public: ~GISelChangeObserver()33 virtual ~GISelChangeObserver() {} 34 35 /// An instruction is about to be erased. 36 virtual void erasingInstr(MachineInstr &MI) = 0; 37 /// An instruction was created and inserted into the function. 38 virtual void createdInstr(MachineInstr &MI) = 0; 39 /// This instruction is about to be mutated in some way. 40 virtual void changingInstr(MachineInstr &MI) = 0; 41 /// This instruction was mutated in some way. 42 virtual void changedInstr(MachineInstr &MI) = 0; 43 44 /// All the instructions using the given register are being changed. 45 /// For convenience, finishedChangingAllUsesOfReg() will report the completion 46 /// of the changes. The use list may change between this call and 47 /// finishedChangingAllUsesOfReg(). 48 void changingAllUsesOfReg(const MachineRegisterInfo &MRI, unsigned Reg); 49 /// All instructions reported as changing by changingAllUsesOfReg() have 50 /// finished being changed. 51 void finishedChangingAllUsesOfReg(); 52 53 }; 54 55 /// Simple wrapper observer that takes several observers, and calls 56 /// each one for each event. If there are multiple observers (say CSE, 57 /// Legalizer, Combiner), it's sufficient to register this to the machine 58 /// function as the delegate. 59 class GISelObserverWrapper : public MachineFunction::Delegate, 60 public GISelChangeObserver { 61 SmallVector<GISelChangeObserver *, 4> Observers; 62 63 public: 64 GISelObserverWrapper() = default; GISelObserverWrapper(ArrayRef<GISelChangeObserver * > Obs)65 GISelObserverWrapper(ArrayRef<GISelChangeObserver *> Obs) 66 : Observers(Obs.begin(), Obs.end()) {} 67 // Adds an observer. addObserver(GISelChangeObserver * O)68 void addObserver(GISelChangeObserver *O) { Observers.push_back(O); } 69 // Removes an observer from the list and does nothing if observer is not 70 // present. removeObserver(GISelChangeObserver * O)71 void removeObserver(GISelChangeObserver *O) { 72 auto It = std::find(Observers.begin(), Observers.end(), O); 73 if (It != Observers.end()) 74 Observers.erase(It); 75 } 76 // API for Observer. erasingInstr(MachineInstr & MI)77 void erasingInstr(MachineInstr &MI) override { 78 for (auto &O : Observers) 79 O->erasingInstr(MI); 80 } createdInstr(MachineInstr & MI)81 void createdInstr(MachineInstr &MI) override { 82 for (auto &O : Observers) 83 O->createdInstr(MI); 84 } changingInstr(MachineInstr & MI)85 void changingInstr(MachineInstr &MI) override { 86 for (auto &O : Observers) 87 O->changingInstr(MI); 88 } changedInstr(MachineInstr & MI)89 void changedInstr(MachineInstr &MI) override { 90 for (auto &O : Observers) 91 O->changedInstr(MI); 92 } 93 // API for MachineFunction::Delegate MF_HandleInsertion(MachineInstr & MI)94 void MF_HandleInsertion(MachineInstr &MI) override { createdInstr(MI); } MF_HandleRemoval(MachineInstr & MI)95 void MF_HandleRemoval(MachineInstr &MI) override { erasingInstr(MI); } 96 }; 97 98 /// A simple RAII based CSEInfo installer. 99 /// Use this in a scope to install a delegate to the MachineFunction and reset 100 /// it at the end of the scope. 101 class RAIIDelegateInstaller { 102 MachineFunction &MF; 103 MachineFunction::Delegate *Delegate; 104 105 public: 106 RAIIDelegateInstaller(MachineFunction &MF, MachineFunction::Delegate *Del); 107 ~RAIIDelegateInstaller(); 108 }; 109 110 } // namespace llvm 111 #endif 112