GISelChangeObserver.h revision 344779
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
20namespace llvm {
21class MachineInstr;
22class 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).
29class GISelChangeObserver {
30  SmallPtrSet<MachineInstr *, 4> ChangingAllUsesOfReg;
31
32public:
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.
59class GISelObserverWrapper : public MachineFunction::Delegate,
60                             public GISelChangeObserver {
61  SmallVector<GISelChangeObserver *, 4> Observers;
62
63public:
64  GISelObserverWrapper() = default;
65  GISelObserverWrapper(ArrayRef<GISelChangeObserver *> Obs)
66      : Observers(Obs.begin(), Obs.end()) {}
67  // Adds an observer.
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.
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.
77  void erasingInstr(MachineInstr &MI) override {
78    for (auto &O : Observers)
79      O->erasingInstr(MI);
80  }
81  void createdInstr(MachineInstr &MI) override {
82    for (auto &O : Observers)
83      O->createdInstr(MI);
84  }
85  void changingInstr(MachineInstr &MI) override {
86    for (auto &O : Observers)
87      O->changingInstr(MI);
88  }
89  void changedInstr(MachineInstr &MI) override {
90    for (auto &O : Observers)
91      O->changedInstr(MI);
92  }
93  // API for MachineFunction::Delegate
94  void MF_HandleInsertion(MachineInstr &MI) override { createdInstr(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.
101class RAIIDelegateInstaller {
102  MachineFunction &MF;
103  MachineFunction::Delegate *Delegate;
104
105public:
106  RAIIDelegateInstaller(MachineFunction &MF, MachineFunction::Delegate *Del);
107  ~RAIIDelegateInstaller();
108};
109
110} // namespace llvm
111#endif
112