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