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