construct.h 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170
  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_CONSTRUCT_H_
  15. #define SOURCE_VAL_CONSTRUCT_H_
  16. #include <cstdint>
  17. #include <set>
  18. #include <vector>
  19. #include "source/val/basic_block.h"
  20. namespace spvtools {
  21. namespace val {
  22. class ValidationState_t;
  23. /// Functor for ordering BasicBlocks. BasicBlock pointers must not be null.
  24. struct less_than_id {
  25. bool operator()(const BasicBlock* lhs, const BasicBlock* rhs) const {
  26. return lhs->id() < rhs->id();
  27. }
  28. };
  29. enum class ConstructType : int {
  30. kNone = 0,
  31. /// The set of blocks dominated by a selection header, minus the set of blocks
  32. /// dominated by the header's merge block
  33. kSelection,
  34. /// The set of blocks dominated by an OpLoopMerge's Continue Target and post
  35. /// dominated by the corresponding back
  36. kContinue,
  37. /// The set of blocks dominated by a loop header, minus the set of blocks
  38. /// dominated by the loop's merge block, minus the loop's corresponding
  39. /// continue construct
  40. kLoop,
  41. /// The set of blocks dominated by an OpSwitch's Target or Default, minus the
  42. /// set of blocks dominated by the OpSwitch's merge block (this construct is
  43. /// only defined for those OpSwitch Target or Default that are not equal to
  44. /// the OpSwitch's corresponding merge block)
  45. kCase
  46. };
  47. class Function;
  48. /// @brief This class tracks the CFG constructs as defined in the SPIR-V spec
  49. class Construct {
  50. public:
  51. Construct(ConstructType type, BasicBlock* dominator,
  52. BasicBlock* exit = nullptr,
  53. std::vector<Construct*> constructs = std::vector<Construct*>());
  54. /// Returns the type of the construct
  55. ConstructType type() const;
  56. const std::vector<Construct*>& corresponding_constructs() const;
  57. std::vector<Construct*>& corresponding_constructs();
  58. void set_corresponding_constructs(std::vector<Construct*> constructs);
  59. /// Returns the dominator block of the construct.
  60. ///
  61. /// This is usually the header block or the first block of the construct.
  62. const BasicBlock* entry_block() const;
  63. /// Returns the dominator block of the construct.
  64. ///
  65. /// This is usually the header block or the first block of the construct.
  66. BasicBlock* entry_block();
  67. /// Returns the exit block of the construct.
  68. ///
  69. /// For a continue construct it is the backedge block of the corresponding
  70. /// loop construct. For the case construct it is the block that branches to
  71. /// the OpSwitch merge block or other case blocks. Otherwise it is the merge
  72. /// block of the corresponding header block
  73. const BasicBlock* exit_block() const;
  74. /// Returns the exit block of the construct.
  75. ///
  76. /// For a continue construct it is the backedge block of the corresponding
  77. /// loop construct. For the case construct it is the block that branches to
  78. /// the OpSwitch merge block or other case blocks. Otherwise it is the merge
  79. /// block of the corresponding header block
  80. BasicBlock* exit_block();
  81. /// Sets the exit block for this construct. This is useful for continue
  82. /// constructs which do not know the back-edge block during construction
  83. void set_exit(BasicBlock* exit_block);
  84. // Returns whether the exit block of this construct is the merge block
  85. // for an OpLoopMerge or OpSelectionMerge
  86. bool ExitBlockIsMergeBlock() const {
  87. return type_ == ConstructType::kLoop || type_ == ConstructType::kSelection;
  88. }
  89. using ConstructBlockSet = std::set<BasicBlock*, less_than_id>;
  90. // Returns the basic blocks in this construct. This function should not
  91. // be called before the exit block is set and dominators have been
  92. // calculated.
  93. ConstructBlockSet blocks(Function* function) const;
  94. // Returns true if |dest| is structured exit from the construct. Structured
  95. // exits depend on the construct type.
  96. // Selection:
  97. // * branch to the associated merge
  98. // * branch to the merge or continue of the innermost loop containing the
  99. // selection
  100. // * branch to the merge block of the innermost switch containing the
  101. // selection
  102. // Loop:
  103. // * branch to the associated merge or continue
  104. // Continue:
  105. // * back-edge to the associated loop header
  106. // * branch to the associated loop merge
  107. //
  108. // Note: the validator does not generate case constructs. Switches are
  109. // checked separately from other constructs.
  110. bool IsStructuredExit(ValidationState_t& _, BasicBlock* dest) const;
  111. private:
  112. /// The type of the construct
  113. ConstructType type_;
  114. /// These are the constructs that are related to this construct. These
  115. /// constructs can be the continue construct, for the corresponding loop
  116. /// construct, the case construct that are part of the same OpSwitch
  117. /// instruction
  118. ///
  119. /// Here is a table that describes what constructs are included in
  120. /// @p corresponding_constructs_
  121. /// | this construct | corresponding construct |
  122. /// |----------------|----------------------------------|
  123. /// | loop | continue |
  124. /// | continue | loop |
  125. /// | case | other cases in the same OpSwitch |
  126. ///
  127. /// kContinue and kLoop constructs will always have corresponding
  128. /// constructs even if they are represented by the same block
  129. std::vector<Construct*> corresponding_constructs_;
  130. /// @brief Dominator block for the construct
  131. ///
  132. /// The dominator block for the construct. Depending on the construct this may
  133. /// be a selection header, a continue target of a loop, a loop header or a
  134. /// Target or Default block of a switch
  135. BasicBlock* entry_block_;
  136. /// @brief Exiting block for the construct
  137. ///
  138. /// The exit block for the construct. This can be a merge block for the loop
  139. /// and selection constructs, a back-edge block for a continue construct, or
  140. /// the branching block for the case construct
  141. BasicBlock* exit_block_;
  142. };
  143. } // namespace val
  144. } // namespace spvtools
  145. #endif // SOURCE_VAL_CONSTRUCT_H_