GISelChangeObserver.h 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151
  1. #pragma once
  2. #ifdef __GNUC__
  3. #pragma GCC diagnostic push
  4. #pragma GCC diagnostic ignored "-Wunused-parameter"
  5. #endif
  6. //===----- llvm/CodeGen/GlobalISel/GISelChangeObserver.h --------*- C++ -*-===//
  7. //
  8. // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
  9. // See https://llvm.org/LICENSE.txt for license information.
  10. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
  11. //
  12. //===----------------------------------------------------------------------===//
  13. /// \file
  14. /// This contains common code to allow clients to notify changes to machine
  15. /// instr.
  16. ///
  17. //===----------------------------------------------------------------------===//
  18. #ifndef LLVM_CODEGEN_GLOBALISEL_GISELCHANGEOBSERVER_H
  19. #define LLVM_CODEGEN_GLOBALISEL_GISELCHANGEOBSERVER_H
  20. #include "llvm/ADT/SmallPtrSet.h"
  21. #include "llvm/CodeGen/MachineFunction.h"
  22. namespace llvm {
  23. class MachineInstr;
  24. class MachineRegisterInfo;
  25. /// Abstract class that contains various methods for clients to notify about
  26. /// changes. This should be the preferred way for APIs to notify changes.
  27. /// Typically calling erasingInstr/createdInstr multiple times should not affect
  28. /// the result. The observer would likely need to check if it was already
  29. /// notified earlier (consider using GISelWorkList).
  30. class GISelChangeObserver {
  31. SmallPtrSet<MachineInstr *, 4> ChangingAllUsesOfReg;
  32. public:
  33. virtual ~GISelChangeObserver() = default;
  34. /// An instruction is about to be erased.
  35. virtual void erasingInstr(MachineInstr &MI) = 0;
  36. /// An instruction has been created and inserted into the function.
  37. /// Note that the instruction might not be a fully fledged instruction at this
  38. /// point and won't be if the MachineFunction::Delegate is calling it. This is
  39. /// because the delegate only sees the construction of the MachineInstr before
  40. /// operands have been added.
  41. virtual void createdInstr(MachineInstr &MI) = 0;
  42. /// This instruction is about to be mutated in some way.
  43. virtual void changingInstr(MachineInstr &MI) = 0;
  44. /// This instruction was mutated in some way.
  45. virtual void changedInstr(MachineInstr &MI) = 0;
  46. /// All the instructions using the given register are being changed.
  47. /// For convenience, finishedChangingAllUsesOfReg() will report the completion
  48. /// of the changes. The use list may change between this call and
  49. /// finishedChangingAllUsesOfReg().
  50. void changingAllUsesOfReg(const MachineRegisterInfo &MRI, Register Reg);
  51. /// All instructions reported as changing by changingAllUsesOfReg() have
  52. /// finished being changed.
  53. void finishedChangingAllUsesOfReg();
  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.
  59. class GISelObserverWrapper : public MachineFunction::Delegate,
  60. public GISelChangeObserver {
  61. SmallVector<GISelChangeObserver *, 4> Observers;
  62. public:
  63. GISelObserverWrapper() = default;
  64. GISelObserverWrapper(ArrayRef<GISelChangeObserver *> Obs)
  65. : Observers(Obs.begin(), Obs.end()) {}
  66. // Adds an observer.
  67. void addObserver(GISelChangeObserver *O) { Observers.push_back(O); }
  68. // Removes an observer from the list and does nothing if observer is not
  69. // present.
  70. void removeObserver(GISelChangeObserver *O) {
  71. auto It = std::find(Observers.begin(), Observers.end(), O);
  72. if (It != Observers.end())
  73. Observers.erase(It);
  74. }
  75. // API for Observer.
  76. void erasingInstr(MachineInstr &MI) override {
  77. for (auto &O : Observers)
  78. O->erasingInstr(MI);
  79. }
  80. void createdInstr(MachineInstr &MI) override {
  81. for (auto &O : Observers)
  82. O->createdInstr(MI);
  83. }
  84. void changingInstr(MachineInstr &MI) override {
  85. for (auto &O : Observers)
  86. O->changingInstr(MI);
  87. }
  88. void changedInstr(MachineInstr &MI) override {
  89. for (auto &O : Observers)
  90. O->changedInstr(MI);
  91. }
  92. // API for MachineFunction::Delegate
  93. void MF_HandleInsertion(MachineInstr &MI) override { createdInstr(MI); }
  94. void MF_HandleRemoval(MachineInstr &MI) override { erasingInstr(MI); }
  95. };
  96. /// A simple RAII based Delegate installer.
  97. /// Use this in a scope to install a delegate to the MachineFunction and reset
  98. /// it at the end of the scope.
  99. class RAIIDelegateInstaller {
  100. MachineFunction &MF;
  101. MachineFunction::Delegate *Delegate;
  102. public:
  103. RAIIDelegateInstaller(MachineFunction &MF, MachineFunction::Delegate *Del);
  104. ~RAIIDelegateInstaller();
  105. };
  106. /// A simple RAII based Observer installer.
  107. /// Use this in a scope to install the Observer to the MachineFunction and reset
  108. /// it at the end of the scope.
  109. class RAIIMFObserverInstaller {
  110. MachineFunction &MF;
  111. public:
  112. RAIIMFObserverInstaller(MachineFunction &MF, GISelChangeObserver &Observer);
  113. ~RAIIMFObserverInstaller();
  114. };
  115. /// Class to install both of the above.
  116. class RAIIMFObsDelInstaller {
  117. RAIIDelegateInstaller DelI;
  118. RAIIMFObserverInstaller ObsI;
  119. public:
  120. RAIIMFObsDelInstaller(MachineFunction &MF, GISelObserverWrapper &Wrapper)
  121. : DelI(MF, &Wrapper), ObsI(MF, Wrapper) {}
  122. ~RAIIMFObsDelInstaller() = default;
  123. };
  124. } // namespace llvm
  125. #endif
  126. #ifdef __GNUC__
  127. #pragma GCC diagnostic pop
  128. #endif