xref: /llvm-project/llvm/include/llvm/CodeGen/GlobalISel/GISelChangeObserver.h (revision 0bf5846553412978d30b84f06c6b6183890ab8e5)
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 /// \file
9 /// This contains common code to allow clients to notify changes to machine
10 /// instr.
11 ///
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:
33   virtual ~GISelChangeObserver() = default;
34 
35   /// An instruction is about to be erased.
36   virtual void erasingInstr(MachineInstr &MI) = 0;
37 
38   /// An instruction has been created and inserted into the function.
39   /// Note that the instruction might not be a fully fledged instruction at this
40   /// point and won't be if the MachineFunction::Delegate is calling it. This is
41   /// because the delegate only sees the construction of the MachineInstr before
42   /// operands have been added.
43   virtual void createdInstr(MachineInstr &MI) = 0;
44 
45   /// This instruction is about to be mutated in some way.
46   virtual void changingInstr(MachineInstr &MI) = 0;
47 
48   /// This instruction was mutated in some way.
49   virtual void changedInstr(MachineInstr &MI) = 0;
50 
51   /// All the instructions using the given register are being changed.
52   /// For convenience, finishedChangingAllUsesOfReg() will report the completion
53   /// of the changes. The use list may change between this call and
54   /// finishedChangingAllUsesOfReg().
55   void changingAllUsesOfReg(const MachineRegisterInfo &MRI, Register Reg);
56   /// All instructions reported as changing by changingAllUsesOfReg() have
57   /// finished being changed.
58   void finishedChangingAllUsesOfReg();
59 
60 };
61 
62 /// Simple wrapper observer that takes several observers, and calls
63 /// each one for each event. If there are multiple observers (say CSE,
64 /// Legalizer, Combiner), it's sufficient to register this to the machine
65 /// function as the delegate.
66 class GISelObserverWrapper : public MachineFunction::Delegate,
67                              public GISelChangeObserver {
68   SmallVector<GISelChangeObserver *, 4> Observers;
69 
70 public:
71   GISelObserverWrapper() = default;
72   GISelObserverWrapper(ArrayRef<GISelChangeObserver *> Obs) : Observers(Obs) {}
73   // Adds an observer.
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.
77   void removeObserver(GISelChangeObserver *O) {
78     auto It = llvm::find(Observers, O);
79     if (It != Observers.end())
80       Observers.erase(It);
81   }
82   // Removes all observers
83   void clearObservers() { Observers.clear(); }
84 
85   // API for Observer.
86   void erasingInstr(MachineInstr &MI) override {
87     for (auto &O : Observers)
88       O->erasingInstr(MI);
89   }
90   void createdInstr(MachineInstr &MI) override {
91     for (auto &O : Observers)
92       O->createdInstr(MI);
93   }
94   void changingInstr(MachineInstr &MI) override {
95     for (auto &O : Observers)
96       O->changingInstr(MI);
97   }
98   void changedInstr(MachineInstr &MI) override {
99     for (auto &O : Observers)
100       O->changedInstr(MI);
101   }
102   // API for MachineFunction::Delegate
103   void MF_HandleInsertion(MachineInstr &MI) override { createdInstr(MI); }
104   void MF_HandleRemoval(MachineInstr &MI) override { erasingInstr(MI); }
105 };
106 
107 /// A simple RAII based Delegate installer.
108 /// Use this in a scope to install a delegate to the MachineFunction and reset
109 /// it at the end of the scope.
110 class RAIIDelegateInstaller {
111   MachineFunction &MF;
112   MachineFunction::Delegate *Delegate;
113 
114 public:
115   RAIIDelegateInstaller(MachineFunction &MF, MachineFunction::Delegate *Del);
116   ~RAIIDelegateInstaller();
117 };
118 
119 /// A simple RAII based Observer installer.
120 /// Use this in a scope to install the Observer to the MachineFunction and reset
121 /// it at the end of the scope.
122 class RAIIMFObserverInstaller {
123   MachineFunction &MF;
124 
125 public:
126   RAIIMFObserverInstaller(MachineFunction &MF, GISelChangeObserver &Observer);
127   ~RAIIMFObserverInstaller();
128 };
129 
130 /// Class to install both of the above.
131 class RAIIMFObsDelInstaller {
132   RAIIDelegateInstaller DelI;
133   RAIIMFObserverInstaller ObsI;
134 
135 public:
136   RAIIMFObsDelInstaller(MachineFunction &MF, GISelObserverWrapper &Wrapper)
137       : DelI(MF, &Wrapper), ObsI(MF, Wrapper) {}
138   ~RAIIMFObsDelInstaller() = default;
139 };
140 
141 /// A simple RAII based Observer installer.
142 /// Use this in a scope to install the Observer to the MachineFunction and reset
143 /// it at the end of the scope.
144 class RAIITemporaryObserverInstaller {
145 public:
146   RAIITemporaryObserverInstaller(GISelObserverWrapper &Observers,
147                                  GISelChangeObserver &TemporaryObserver);
148   ~RAIITemporaryObserverInstaller();
149 
150 private:
151   GISelObserverWrapper &Observers;
152   GISelChangeObserver &TemporaryObserver;
153 };
154 
155 } // namespace llvm
156 #endif
157