1 //===----- llvm/CodeGen/GlobalISel/GISelChangeObserver.h ------------------===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
10 /// This contains common code to allow clients to notify changes to machine
13 //===----------------------------------------------------------------------===//
14 #ifndef LLVM_CODEGEN_GLOBALISEL_GISELCHANGEOBSERVER_H
15 #define LLVM_CODEGEN_GLOBALISEL_GISELCHANGEOBSERVER_H
17 #include "llvm/ADT/SmallPtrSet.h"
18 #include "llvm/CodeGen/MachineFunction.h"
22 class MachineRegisterInfo;
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;
33 virtual ~GISelChangeObserver() {}
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;
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();
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;
64 GISelObserverWrapper() = default;
65 GISelObserverWrapper(ArrayRef<GISelChangeObserver *> Obs)
66 : Observers(Obs.begin(), Obs.end()) {}
68 void addObserver(GISelChangeObserver *O) { Observers.push_back(O); }
69 // Removes an observer from the list and does nothing if observer is not
71 void removeObserver(GISelChangeObserver *O) {
72 auto It = std::find(Observers.begin(), Observers.end(), O);
73 if (It != Observers.end())
77 void erasingInstr(MachineInstr &MI) override {
78 for (auto &O : Observers)
81 void createdInstr(MachineInstr &MI) override {
82 for (auto &O : Observers)
85 void changingInstr(MachineInstr &MI) override {
86 for (auto &O : Observers)
89 void changedInstr(MachineInstr &MI) override {
90 for (auto &O : Observers)
93 // API for MachineFunction::Delegate
94 void MF_HandleInsertion(MachineInstr &MI) override { createdInstr(MI); }
95 void MF_HandleRemoval(MachineInstr &MI) override { erasingInstr(MI); }
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 {
103 MachineFunction::Delegate *Delegate;
106 RAIIDelegateInstaller(MachineFunction &MF, MachineFunction::Delegate *Del);
107 ~RAIIDelegateInstaller();