Home | History | Annotate | Line # | Download | only in GlobalISel
      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() {}
     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)
     73       : Observers(Obs.begin(), Obs.end()) {}
     74   // Adds an observer.
     75   void addObserver(GISelChangeObserver *O) { Observers.push_back(O); }
     76   // Removes an observer from the list and does nothing if observer is not
     77   // present.
     78   void removeObserver(GISelChangeObserver *O) {
     79     auto It = std::find(Observers.begin(), Observers.end(), O);
     80     if (It != Observers.end())
     81       Observers.erase(It);
     82   }
     83   // API for Observer.
     84   void erasingInstr(MachineInstr &MI) override {
     85     for (auto &O : Observers)
     86       O->erasingInstr(MI);
     87   }
     88   void createdInstr(MachineInstr &MI) override {
     89     for (auto &O : Observers)
     90       O->createdInstr(MI);
     91   }
     92   void changingInstr(MachineInstr &MI) override {
     93     for (auto &O : Observers)
     94       O->changingInstr(MI);
     95   }
     96   void changedInstr(MachineInstr &MI) override {
     97     for (auto &O : Observers)
     98       O->changedInstr(MI);
     99   }
    100   // API for MachineFunction::Delegate
    101   void MF_HandleInsertion(MachineInstr &MI) override { createdInstr(MI); }
    102   void MF_HandleRemoval(MachineInstr &MI) override { erasingInstr(MI); }
    103 };
    104 
    105 /// A simple RAII based Delegate installer.
    106 /// Use this in a scope to install a delegate to the MachineFunction and reset
    107 /// it at the end of the scope.
    108 class RAIIDelegateInstaller {
    109   MachineFunction &MF;
    110   MachineFunction::Delegate *Delegate;
    111 
    112 public:
    113   RAIIDelegateInstaller(MachineFunction &MF, MachineFunction::Delegate *Del);
    114   ~RAIIDelegateInstaller();
    115 };
    116 
    117 /// A simple RAII based Observer installer.
    118 /// Use this in a scope to install the Observer to the MachineFunction and reset
    119 /// it at the end of the scope.
    120 class RAIIMFObserverInstaller {
    121   MachineFunction &MF;
    122 
    123 public:
    124   RAIIMFObserverInstaller(MachineFunction &MF, GISelChangeObserver &Observer);
    125   ~RAIIMFObserverInstaller();
    126 };
    127 
    128 /// Class to install both of the above.
    129 class RAIIMFObsDelInstaller {
    130   RAIIDelegateInstaller DelI;
    131   RAIIMFObserverInstaller ObsI;
    132 
    133 public:
    134   RAIIMFObsDelInstaller(MachineFunction &MF, GISelObserverWrapper &Wrapper)
    135       : DelI(MF, &Wrapper), ObsI(MF, Wrapper) {}
    136   ~RAIIMFObsDelInstaller() = default;
    137 };
    138 
    139 } // namespace llvm
    140 #endif
    141