pass.h 5.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172
  1. // Copyright (c) 2016 Google Inc.
  2. //
  3. // Licensed under the Apache License, Version 2.0 (the "License");
  4. // you may not use this file except in compliance with the License.
  5. // You may obtain a copy of the License at
  6. //
  7. // http://www.apache.org/licenses/LICENSE-2.0
  8. //
  9. // Unless required by applicable law or agreed to in writing, software
  10. // distributed under the License is distributed on an "AS IS" BASIS,
  11. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. // See the License for the specific language governing permissions and
  13. // limitations under the License.
  14. #ifndef SOURCE_OPT_PASS_H_
  15. #define SOURCE_OPT_PASS_H_
  16. #include <algorithm>
  17. #include <map>
  18. #include <unordered_map>
  19. #include <unordered_set>
  20. #include <utility>
  21. #include "source/opt/basic_block.h"
  22. #include "source/opt/def_use_manager.h"
  23. #include "source/opt/ir_context.h"
  24. #include "source/opt/module.h"
  25. #include "spirv-tools/libspirv.hpp"
  26. #include "types.h"
  27. // Avoid unused variable warning/error on Linux
  28. #ifndef NDEBUG
  29. #define USE_ASSERT(x) assert(x)
  30. #else
  31. #define USE_ASSERT(x) ((void)(x))
  32. #endif
  33. namespace spvtools {
  34. namespace opt {
  35. // Abstract class of a pass. All passes should implement this abstract class
  36. // and all analysis and transformation is done via the Process() method.
  37. class Pass {
  38. public:
  39. // The status of processing a module using a pass.
  40. //
  41. // The numbers for the cases are assigned to make sure that Failure & anything
  42. // is Failure, SuccessWithChange & any success is SuccessWithChange.
  43. enum class Status {
  44. Failure = 0x00,
  45. SuccessWithChange = 0x10,
  46. SuccessWithoutChange = 0x11,
  47. };
  48. using ProcessFunction = std::function<bool(Function*)>;
  49. // Destructs the pass.
  50. virtual ~Pass() = default;
  51. // Returns a descriptive name for this pass.
  52. //
  53. // NOTE: When deriving a new pass class, make sure you make the name
  54. // compatible with the corresponding spirv-opt command-line flag. For example,
  55. // if you add the flag --my-pass to spirv-opt, make this function return
  56. // "my-pass" (no leading hyphens).
  57. virtual const char* name() const = 0;
  58. // Sets the message consumer to the given |consumer|. |consumer| which will be
  59. // invoked every time there is a message to be communicated to the outside.
  60. void SetMessageConsumer(MessageConsumer c) { consumer_ = std::move(c); }
  61. // Returns the reference to the message consumer for this pass.
  62. const MessageConsumer& consumer() const { return consumer_; }
  63. // Returns the def-use manager used for this pass. TODO(dnovillo): This should
  64. // be handled by the pass manager.
  65. analysis::DefUseManager* get_def_use_mgr() const {
  66. return context()->get_def_use_mgr();
  67. }
  68. analysis::DecorationManager* get_decoration_mgr() const {
  69. return context()->get_decoration_mgr();
  70. }
  71. FeatureManager* get_feature_mgr() const {
  72. return context()->get_feature_mgr();
  73. }
  74. // Returns a pointer to the current module for this pass.
  75. Module* get_module() const { return context_->module(); }
  76. // Sets the pointer to the current context for this pass.
  77. void SetContextForTesting(IRContext* ctx) { context_ = ctx; }
  78. // Returns a pointer to the current context for this pass.
  79. IRContext* context() const { return context_; }
  80. // Returns a pointer to the CFG for current module.
  81. CFG* cfg() const { return context()->cfg(); }
  82. // Run the pass on the given |module|. Returns Status::Failure if errors occur
  83. // when processing. Returns the corresponding Status::Success if processing is
  84. // successful to indicate whether changes are made to the module. If there
  85. // were any changes it will also invalidate the analyses in the IRContext
  86. // that are not preserved.
  87. //
  88. // It is an error if |Run| is called twice with the same instance of the pass.
  89. // If this happens the return value will be |Failure|.
  90. Status Run(IRContext* ctx);
  91. // Returns the set of analyses that the pass is guaranteed to preserve.
  92. virtual IRContext::Analysis GetPreservedAnalyses() {
  93. return IRContext::kAnalysisNone;
  94. }
  95. // Return type id for |ptrInst|'s pointee
  96. uint32_t GetPointeeTypeId(const Instruction* ptrInst) const;
  97. // Return base type of |ty_id| type
  98. Instruction* GetBaseType(uint32_t ty_id);
  99. // Return true if |inst| returns scalar, vector or matrix type with base
  100. // float and |width|
  101. bool IsFloat(uint32_t ty_id, uint32_t width);
  102. // Return the id of OpConstantNull of type |type_id|. Create if necessary.
  103. uint32_t GetNullId(uint32_t type_id);
  104. protected:
  105. // Constructs a new pass.
  106. //
  107. // The constructed instance will have an empty message consumer, which just
  108. // ignores all messages from the library. Use SetMessageConsumer() to supply
  109. // one if messages are of concern.
  110. Pass();
  111. // Processes the given |module|. Returns Status::Failure if errors occur when
  112. // processing. Returns the corresponding Status::Success if processing is
  113. // successful to indicate whether changes are made to the module.
  114. virtual Status Process() = 0;
  115. // Return the next available SSA id and increment it.
  116. // TODO(1841): Handle id overflow.
  117. uint32_t TakeNextId() { return context_->TakeNextId(); }
  118. // Returns the id whose value is the same as |object_to_copy| except its type
  119. // is |new_type_id|. Any instructions needed to generate this value will be
  120. // inserted before |insertion_position|. Returns 0 if a copy could not be
  121. // done.
  122. uint32_t GenerateCopy(Instruction* object_to_copy, uint32_t new_type_id,
  123. Instruction* insertion_position);
  124. private:
  125. MessageConsumer consumer_; // Message consumer.
  126. // The context that this pass belongs to.
  127. IRContext* context_;
  128. // An instance of a pass can only be run once because it is too hard to
  129. // enforce proper resetting of internal state for each instance. This member
  130. // is used to check that we do not run the same instance twice.
  131. bool already_run_;
  132. };
  133. inline Pass::Status CombineStatus(Pass::Status a, Pass::Status b) {
  134. return std::min(a, b);
  135. }
  136. } // namespace opt
  137. } // namespace spvtools
  138. #endif // SOURCE_OPT_PASS_H_