Details | Last modification | View Log | RSS feed
| Rev | Author | Line No. | Line |
|---|---|---|---|
| 14 | pmbaty | 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() = default; |
||
| 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 = llvm::find(Observers, 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 |