Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2026-05-10 08:43:24

0001 //===----- llvm/CodeGen/GlobalISel/GISelChangeObserver.h --------*- C++ -*-===//
0002 //
0003 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
0004 // See https://llvm.org/LICENSE.txt for license information.
0005 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
0006 //
0007 //===----------------------------------------------------------------------===//
0008 /// \file
0009 /// This contains common code to allow clients to notify changes to machine
0010 /// instr.
0011 ///
0012 //===----------------------------------------------------------------------===//
0013 
0014 #ifndef LLVM_CODEGEN_GLOBALISEL_GISELCHANGEOBSERVER_H
0015 #define LLVM_CODEGEN_GLOBALISEL_GISELCHANGEOBSERVER_H
0016 
0017 #include "llvm/ADT/SmallPtrSet.h"
0018 #include "llvm/CodeGen/MachineFunction.h"
0019 
0020 namespace llvm {
0021 class MachineInstr;
0022 class MachineRegisterInfo;
0023 
0024 /// Abstract class that contains various methods for clients to notify about
0025 /// changes. This should be the preferred way for APIs to notify changes.
0026 /// Typically calling erasingInstr/createdInstr multiple times should not affect
0027 /// the result. The observer would likely need to check if it was already
0028 /// notified earlier (consider using GISelWorkList).
0029 class GISelChangeObserver {
0030   SmallPtrSet<MachineInstr *, 4> ChangingAllUsesOfReg;
0031 
0032 public:
0033   virtual ~GISelChangeObserver() = default;
0034 
0035   /// An instruction is about to be erased.
0036   virtual void erasingInstr(MachineInstr &MI) = 0;
0037 
0038   /// An instruction has been created and inserted into the function.
0039   /// Note that the instruction might not be a fully fledged instruction at this
0040   /// point and won't be if the MachineFunction::Delegate is calling it. This is
0041   /// because the delegate only sees the construction of the MachineInstr before
0042   /// operands have been added.
0043   virtual void createdInstr(MachineInstr &MI) = 0;
0044 
0045   /// This instruction is about to be mutated in some way.
0046   virtual void changingInstr(MachineInstr &MI) = 0;
0047 
0048   /// This instruction was mutated in some way.
0049   virtual void changedInstr(MachineInstr &MI) = 0;
0050 
0051   /// All the instructions using the given register are being changed.
0052   /// For convenience, finishedChangingAllUsesOfReg() will report the completion
0053   /// of the changes. The use list may change between this call and
0054   /// finishedChangingAllUsesOfReg().
0055   void changingAllUsesOfReg(const MachineRegisterInfo &MRI, Register Reg);
0056   /// All instructions reported as changing by changingAllUsesOfReg() have
0057   /// finished being changed.
0058   void finishedChangingAllUsesOfReg();
0059 
0060 };
0061 
0062 /// Simple wrapper observer that takes several observers, and calls
0063 /// each one for each event. If there are multiple observers (say CSE,
0064 /// Legalizer, Combiner), it's sufficient to register this to the machine
0065 /// function as the delegate.
0066 class GISelObserverWrapper : public MachineFunction::Delegate,
0067                              public GISelChangeObserver {
0068   SmallVector<GISelChangeObserver *, 4> Observers;
0069 
0070 public:
0071   GISelObserverWrapper() = default;
0072   GISelObserverWrapper(ArrayRef<GISelChangeObserver *> Obs) : Observers(Obs) {}
0073   // Adds an observer.
0074   void addObserver(GISelChangeObserver *O) { Observers.push_back(O); }
0075   // Removes an observer from the list and does nothing if observer is not
0076   // present.
0077   void removeObserver(GISelChangeObserver *O) {
0078     auto It = llvm::find(Observers, O);
0079     if (It != Observers.end())
0080       Observers.erase(It);
0081   }
0082   // Removes all observers
0083   void clearObservers() { Observers.clear(); }
0084 
0085   // API for Observer.
0086   void erasingInstr(MachineInstr &MI) override {
0087     for (auto &O : Observers)
0088       O->erasingInstr(MI);
0089   }
0090   void createdInstr(MachineInstr &MI) override {
0091     for (auto &O : Observers)
0092       O->createdInstr(MI);
0093   }
0094   void changingInstr(MachineInstr &MI) override {
0095     for (auto &O : Observers)
0096       O->changingInstr(MI);
0097   }
0098   void changedInstr(MachineInstr &MI) override {
0099     for (auto &O : Observers)
0100       O->changedInstr(MI);
0101   }
0102   // API for MachineFunction::Delegate
0103   void MF_HandleInsertion(MachineInstr &MI) override { createdInstr(MI); }
0104   void MF_HandleRemoval(MachineInstr &MI) override { erasingInstr(MI); }
0105 };
0106 
0107 /// A simple RAII based Delegate installer.
0108 /// Use this in a scope to install a delegate to the MachineFunction and reset
0109 /// it at the end of the scope.
0110 class RAIIDelegateInstaller {
0111   MachineFunction &MF;
0112   MachineFunction::Delegate *Delegate;
0113 
0114 public:
0115   RAIIDelegateInstaller(MachineFunction &MF, MachineFunction::Delegate *Del);
0116   ~RAIIDelegateInstaller();
0117 };
0118 
0119 /// A simple RAII based Observer installer.
0120 /// Use this in a scope to install the Observer to the MachineFunction and reset
0121 /// it at the end of the scope.
0122 class RAIIMFObserverInstaller {
0123   MachineFunction &MF;
0124 
0125 public:
0126   RAIIMFObserverInstaller(MachineFunction &MF, GISelChangeObserver &Observer);
0127   ~RAIIMFObserverInstaller();
0128 };
0129 
0130 /// Class to install both of the above.
0131 class RAIIMFObsDelInstaller {
0132   RAIIDelegateInstaller DelI;
0133   RAIIMFObserverInstaller ObsI;
0134 
0135 public:
0136   RAIIMFObsDelInstaller(MachineFunction &MF, GISelObserverWrapper &Wrapper)
0137       : DelI(MF, &Wrapper), ObsI(MF, Wrapper) {}
0138   ~RAIIMFObsDelInstaller() = default;
0139 };
0140 
0141 /// A simple RAII based Observer installer.
0142 /// Use this in a scope to install the Observer to the MachineFunction and reset
0143 /// it at the end of the scope.
0144 class RAIITemporaryObserverInstaller {
0145 public:
0146   RAIITemporaryObserverInstaller(GISelObserverWrapper &Observers,
0147                                  GISelChangeObserver &TemporaryObserver);
0148   ~RAIITemporaryObserverInstaller();
0149 
0150 private:
0151   GISelObserverWrapper &Observers;
0152   GISelChangeObserver &TemporaryObserver;
0153 };
0154 
0155 } // namespace llvm
0156 #endif