basic_block.h 8.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249
  1. // Copyright (c) 2015-2016 The Khronos Group 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_VAL_BASIC_BLOCK_H_
  15. #define SOURCE_VAL_BASIC_BLOCK_H_
  16. #include <bitset>
  17. #include <cstdint>
  18. #include <functional>
  19. #include <memory>
  20. #include <vector>
  21. #include "source/latest_version_spirv_header.h"
  22. namespace spvtools {
  23. namespace val {
  24. enum BlockType : uint32_t {
  25. kBlockTypeUndefined,
  26. kBlockTypeSelection,
  27. kBlockTypeLoop,
  28. kBlockTypeMerge,
  29. kBlockTypeBreak,
  30. kBlockTypeContinue,
  31. kBlockTypeReturn,
  32. kBlockTypeCOUNT ///< Total number of block types. (must be the last element)
  33. };
  34. class Instruction;
  35. // This class represents a basic block in a SPIR-V module
  36. class BasicBlock {
  37. public:
  38. /// Constructor for a BasicBlock
  39. ///
  40. /// @param[in] id The ID of the basic block
  41. explicit BasicBlock(uint32_t id);
  42. /// Returns the id of the BasicBlock
  43. uint32_t id() const { return id_; }
  44. /// Returns the predecessors of the BasicBlock
  45. const std::vector<BasicBlock*>* predecessors() const {
  46. return &predecessors_;
  47. }
  48. /// Returns the predecessors of the BasicBlock
  49. std::vector<BasicBlock*>* predecessors() { return &predecessors_; }
  50. /// Returns the successors of the BasicBlock
  51. const std::vector<BasicBlock*>* successors() const { return &successors_; }
  52. /// Returns the successors of the BasicBlock
  53. std::vector<BasicBlock*>* successors() { return &successors_; }
  54. /// Returns true if the block is reachable in the CFG
  55. bool reachable() const { return reachable_; }
  56. /// Returns true if BasicBlock is of the given type
  57. bool is_type(BlockType type) const {
  58. if (type == kBlockTypeUndefined) return type_.none();
  59. return type_.test(type);
  60. }
  61. /// Sets the reachability of the basic block in the CFG
  62. void set_reachable(bool reachability) { reachable_ = reachability; }
  63. /// Sets the type of the BasicBlock
  64. void set_type(BlockType type) {
  65. if (type == kBlockTypeUndefined)
  66. type_.reset();
  67. else
  68. type_.set(type);
  69. }
  70. /// Sets the immedate dominator of this basic block
  71. ///
  72. /// @param[in] dom_block The dominator block
  73. void SetImmediateDominator(BasicBlock* dom_block);
  74. /// Sets the immedate post dominator of this basic block
  75. ///
  76. /// @param[in] pdom_block The post dominator block
  77. void SetImmediatePostDominator(BasicBlock* pdom_block);
  78. /// Returns the immedate dominator of this basic block
  79. BasicBlock* immediate_dominator();
  80. /// Returns the immedate dominator of this basic block
  81. const BasicBlock* immediate_dominator() const;
  82. /// Returns the immedate post dominator of this basic block
  83. BasicBlock* immediate_post_dominator();
  84. /// Returns the immedate post dominator of this basic block
  85. const BasicBlock* immediate_post_dominator() const;
  86. /// Returns the label instruction for the block, or nullptr if not set.
  87. const Instruction* label() const { return label_; }
  88. //// Registers the label instruction for the block.
  89. void set_label(const Instruction* t) { label_ = t; }
  90. /// Registers the terminator instruction for the block.
  91. void set_terminator(const Instruction* t) { terminator_ = t; }
  92. /// Returns the terminator instruction for the block.
  93. const Instruction* terminator() const { return terminator_; }
  94. /// Adds @p next BasicBlocks as successors of this BasicBlock
  95. void RegisterSuccessors(
  96. const std::vector<BasicBlock*>& next = std::vector<BasicBlock*>());
  97. /// Returns true if the id of the BasicBlock matches
  98. bool operator==(const BasicBlock& other) const { return other.id_ == id_; }
  99. /// Returns true if the id of the BasicBlock matches
  100. bool operator==(const uint32_t& other_id) const { return other_id == id_; }
  101. /// Returns true if this block dominates the other block.
  102. /// Assumes dominators have been computed.
  103. bool dominates(const BasicBlock& other) const;
  104. /// Returns true if this block postdominates the other block.
  105. /// Assumes dominators have been computed.
  106. bool postdominates(const BasicBlock& other) const;
  107. /// @brief A BasicBlock dominator iterator class
  108. ///
  109. /// This iterator will iterate over the (post)dominators of the block
  110. class DominatorIterator {
  111. public:
  112. using iterator_category = std::forward_iterator_tag;
  113. using value_type = BasicBlock*;
  114. using pointer = value_type*;
  115. using reference = value_type&;
  116. using difference_type = std::ptrdiff_t;
  117. /// @brief Constructs the end of dominator iterator
  118. ///
  119. /// This will create an iterator which will represent the element
  120. /// before the root node of the dominator tree
  121. DominatorIterator();
  122. /// @brief Constructs an iterator for the given block which points to
  123. /// @p block
  124. ///
  125. /// @param block The block which is referenced by the iterator
  126. /// @param dominator_func This function will be called to get the immediate
  127. /// (post)dominator of the current block
  128. DominatorIterator(
  129. const BasicBlock* block,
  130. std::function<const BasicBlock*(const BasicBlock*)> dominator_func);
  131. /// @brief Advances the iterator
  132. DominatorIterator& operator++();
  133. /// @brief Returns the current element
  134. const BasicBlock*& operator*();
  135. friend bool operator==(const DominatorIterator& lhs,
  136. const DominatorIterator& rhs);
  137. private:
  138. const BasicBlock* current_;
  139. std::function<const BasicBlock*(const BasicBlock*)> dom_func_;
  140. };
  141. /// Returns a dominator iterator which points to the current block
  142. const DominatorIterator dom_begin() const;
  143. /// Returns a dominator iterator which points to the current block
  144. DominatorIterator dom_begin();
  145. /// Returns a dominator iterator which points to one element past the first
  146. /// block
  147. const DominatorIterator dom_end() const;
  148. /// Returns a dominator iterator which points to one element past the first
  149. /// block
  150. DominatorIterator dom_end();
  151. /// Returns a post dominator iterator which points to the current block
  152. const DominatorIterator pdom_begin() const;
  153. /// Returns a post dominator iterator which points to the current block
  154. DominatorIterator pdom_begin();
  155. /// Returns a post dominator iterator which points to one element past the
  156. /// last block
  157. const DominatorIterator pdom_end() const;
  158. /// Returns a post dominator iterator which points to one element past the
  159. /// last block
  160. DominatorIterator pdom_end();
  161. private:
  162. /// Id of the BasicBlock
  163. const uint32_t id_;
  164. /// Pointer to the immediate dominator of the BasicBlock
  165. BasicBlock* immediate_dominator_;
  166. /// Pointer to the immediate dominator of the BasicBlock
  167. BasicBlock* immediate_post_dominator_;
  168. /// The set of predecessors of the BasicBlock
  169. std::vector<BasicBlock*> predecessors_;
  170. /// The set of successors of the BasicBlock
  171. std::vector<BasicBlock*> successors_;
  172. /// The type of the block
  173. std::bitset<kBlockTypeCOUNT> type_;
  174. /// True if the block is reachable in the CFG
  175. bool reachable_;
  176. /// label of this block, if any.
  177. const Instruction* label_;
  178. /// Terminator of this block.
  179. const Instruction* terminator_;
  180. };
  181. /// @brief Returns true if the iterators point to the same element or if both
  182. /// iterators point to the @p dom_end block
  183. bool operator==(const BasicBlock::DominatorIterator& lhs,
  184. const BasicBlock::DominatorIterator& rhs);
  185. /// @brief Returns true if the iterators point to different elements and they
  186. /// do not both point to the @p dom_end block
  187. bool operator!=(const BasicBlock::DominatorIterator& lhs,
  188. const BasicBlock::DominatorIterator& rhs);
  189. } // namespace val
  190. } // namespace spvtools
  191. #endif // SOURCE_VAL_BASIC_BLOCK_H_