basic_block.h 8.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247
  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 <cstdint>
  17. #include <bitset>
  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. kBlockTypeHeader,
  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. /// Ends the block without a successor
  87. void RegisterBranchInstruction(SpvOp branch_instruction);
  88. /// Returns the label instruction for the block, or nullptr if not set.
  89. const Instruction* label() const { return label_; }
  90. //// Registers the label instruction for the block.
  91. void set_label(const Instruction* t) { label_ = t; }
  92. /// Registers the terminator instruction for the block.
  93. void set_terminator(const Instruction* t) { terminator_ = t; }
  94. /// Returns the terminator instruction for the block.
  95. const Instruction* terminator() const { return terminator_; }
  96. /// Adds @p next BasicBlocks as successors of this BasicBlock
  97. void RegisterSuccessors(
  98. const std::vector<BasicBlock*>& next = std::vector<BasicBlock*>());
  99. /// Returns true if the id of the BasicBlock matches
  100. bool operator==(const BasicBlock& other) const { return other.id_ == id_; }
  101. /// Returns true if the id of the BasicBlock matches
  102. bool operator==(const uint32_t& other_id) const { return other_id == id_; }
  103. /// Returns true if this block dominates the other block.
  104. /// Assumes dominators have been computed.
  105. bool dominates(const BasicBlock& other) const;
  106. /// Returns true if this block postdominates the other block.
  107. /// Assumes dominators have been computed.
  108. bool postdominates(const BasicBlock& other) const;
  109. /// @brief A BasicBlock dominator iterator class
  110. ///
  111. /// This iterator will iterate over the (post)dominators of the block
  112. class DominatorIterator
  113. : public std::iterator<std::forward_iterator_tag, BasicBlock*> {
  114. public:
  115. /// @brief Constructs the end of dominator iterator
  116. ///
  117. /// This will create an iterator which will represent the element
  118. /// before the root node of the dominator tree
  119. DominatorIterator();
  120. /// @brief Constructs an iterator for the given block which points to
  121. /// @p block
  122. ///
  123. /// @param block The block which is referenced by the iterator
  124. /// @param dominator_func This function will be called to get the immediate
  125. /// (post)dominator of the current block
  126. DominatorIterator(
  127. const BasicBlock* block,
  128. std::function<const BasicBlock*(const BasicBlock*)> dominator_func);
  129. /// @brief Advances the iterator
  130. DominatorIterator& operator++();
  131. /// @brief Returns the current element
  132. const BasicBlock*& operator*();
  133. friend bool operator==(const DominatorIterator& lhs,
  134. const DominatorIterator& rhs);
  135. private:
  136. const BasicBlock* current_;
  137. std::function<const BasicBlock*(const BasicBlock*)> dom_func_;
  138. };
  139. /// Returns a dominator iterator which points to the current block
  140. const DominatorIterator dom_begin() const;
  141. /// Returns a dominator iterator which points to the current block
  142. DominatorIterator dom_begin();
  143. /// Returns a dominator iterator which points to one element past the first
  144. /// block
  145. const DominatorIterator dom_end() const;
  146. /// Returns a dominator iterator which points to one element past the first
  147. /// block
  148. DominatorIterator dom_end();
  149. /// Returns a post dominator iterator which points to the current block
  150. const DominatorIterator pdom_begin() const;
  151. /// Returns a post dominator iterator which points to the current block
  152. DominatorIterator pdom_begin();
  153. /// Returns a post dominator iterator which points to one element past the
  154. /// last block
  155. const DominatorIterator pdom_end() const;
  156. /// Returns a post dominator iterator which points to one element past the
  157. /// last block
  158. DominatorIterator pdom_end();
  159. private:
  160. /// Id of the BasicBlock
  161. const uint32_t id_;
  162. /// Pointer to the immediate dominator of the BasicBlock
  163. BasicBlock* immediate_dominator_;
  164. /// Pointer to the immediate dominator of the BasicBlock
  165. BasicBlock* immediate_post_dominator_;
  166. /// The set of predecessors of the BasicBlock
  167. std::vector<BasicBlock*> predecessors_;
  168. /// The set of successors of the BasicBlock
  169. std::vector<BasicBlock*> successors_;
  170. /// The type of the block
  171. std::bitset<kBlockTypeCOUNT> type_;
  172. /// True if the block is reachable in the CFG
  173. bool reachable_;
  174. /// label of this block, if any.
  175. const Instruction* label_;
  176. /// Terminator of this block.
  177. const Instruction* terminator_;
  178. };
  179. /// @brief Returns true if the iterators point to the same element or if both
  180. /// iterators point to the @p dom_end block
  181. bool operator==(const BasicBlock::DominatorIterator& lhs,
  182. const BasicBlock::DominatorIterator& rhs);
  183. /// @brief Returns true if the iterators point to different elements and they
  184. /// do not both point to the @p dom_end block
  185. bool operator!=(const BasicBlock::DominatorIterator& lhs,
  186. const BasicBlock::DominatorIterator& rhs);
  187. } // namespace val
  188. } // namespace spvtools
  189. #endif // SOURCE_VAL_BASIC_BLOCK_H_