construct.h 5.6 KB

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