123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152 |
- // Copyright (c) 2015-2016 The Khronos Group Inc.
- //
- // Licensed under the Apache License, Version 2.0 (the "License");
- // you may not use this file except in compliance with the License.
- // You may obtain a copy of the License at
- //
- // http://www.apache.org/licenses/LICENSE-2.0
- //
- // Unless required by applicable law or agreed to in writing, software
- // distributed under the License is distributed on an "AS IS" BASIS,
- // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- // See the License for the specific language governing permissions and
- // limitations under the License.
- #ifndef SOURCE_VAL_CONSTRUCT_H_
- #define SOURCE_VAL_CONSTRUCT_H_
- #include <cstdint>
- #include <set>
- #include <vector>
- #include "source/val/basic_block.h"
- namespace spvtools {
- namespace val {
- /// Functor for ordering BasicBlocks. BasicBlock pointers must not be null.
- struct less_than_id {
- bool operator()(const BasicBlock* lhs, const BasicBlock* rhs) const {
- return lhs->id() < rhs->id();
- }
- };
- enum class ConstructType : int {
- kNone = 0,
- /// The set of blocks dominated by a selection header, minus the set of blocks
- /// dominated by the header's merge block
- kSelection,
- /// The set of blocks dominated by an OpLoopMerge's Continue Target and post
- /// dominated by the corresponding back
- kContinue,
- /// The set of blocks dominated by a loop header, minus the set of blocks
- /// dominated by the loop's merge block, minus the loop's corresponding
- /// continue construct
- kLoop,
- /// The set of blocks dominated by an OpSwitch's Target or Default, minus the
- /// set of blocks dominated by the OpSwitch's merge block (this construct is
- /// only defined for those OpSwitch Target or Default that are not equal to
- /// the OpSwitch's corresponding merge block)
- kCase
- };
- class Function;
- /// @brief This class tracks the CFG constructs as defined in the SPIR-V spec
- class Construct {
- public:
- Construct(ConstructType type, BasicBlock* dominator,
- BasicBlock* exit = nullptr,
- std::vector<Construct*> constructs = std::vector<Construct*>());
- /// Returns the type of the construct
- ConstructType type() const;
- const std::vector<Construct*>& corresponding_constructs() const;
- std::vector<Construct*>& corresponding_constructs();
- void set_corresponding_constructs(std::vector<Construct*> constructs);
- /// Returns the dominator block of the construct.
- ///
- /// This is usually the header block or the first block of the construct.
- const BasicBlock* entry_block() const;
- /// Returns the dominator block of the construct.
- ///
- /// This is usually the header block or the first block of the construct.
- BasicBlock* entry_block();
- /// Returns the exit block of the construct.
- ///
- /// For a continue construct it is the backedge block of the corresponding
- /// loop construct. For the case construct it is the block that branches to
- /// the OpSwitch merge block or other case blocks. Otherwise it is the merge
- /// block of the corresponding header block
- const BasicBlock* exit_block() const;
- /// Returns the exit block of the construct.
- ///
- /// For a continue construct it is the backedge block of the corresponding
- /// loop construct. For the case construct it is the block that branches to
- /// the OpSwitch merge block or other case blocks. Otherwise it is the merge
- /// block of the corresponding header block
- BasicBlock* exit_block();
- /// Sets the exit block for this construct. This is useful for continue
- /// constructs which do not know the back-edge block during construction
- void set_exit(BasicBlock* exit_block);
- // Returns whether the exit block of this construct is the merge block
- // for an OpLoopMerge or OpSelectionMerge
- bool ExitBlockIsMergeBlock() const {
- return type_ == ConstructType::kLoop || type_ == ConstructType::kSelection;
- }
- using ConstructBlockSet = std::set<BasicBlock*, less_than_id>;
- // Returns the basic blocks in this construct. This function should not
- // be called before the exit block is set and dominators have been
- // calculated.
- ConstructBlockSet blocks(Function* function) const;
- private:
- /// The type of the construct
- ConstructType type_;
- /// These are the constructs that are related to this construct. These
- /// constructs can be the continue construct, for the corresponding loop
- /// construct, the case construct that are part of the same OpSwitch
- /// instruction
- ///
- /// Here is a table that describes what constructs are included in
- /// @p corresponding_constructs_
- /// | this construct | corresponding construct |
- /// |----------------|----------------------------------|
- /// | loop | continue |
- /// | continue | loop |
- /// | case | other cases in the same OpSwitch |
- ///
- /// kContinue and kLoop constructs will always have corresponding
- /// constructs even if they are represented by the same block
- std::vector<Construct*> corresponding_constructs_;
- /// @brief Dominator block for the construct
- ///
- /// The dominator block for the construct. Depending on the construct this may
- /// be a selection header, a continue target of a loop, a loop header or a
- /// Target or Default block of a switch
- BasicBlock* entry_block_;
- /// @brief Exiting block for the construct
- ///
- /// The exit block for the construct. This can be a merge block for the loop
- /// and selection constructs, a back-edge block for a continue construct, or
- /// the branching block for the case construct
- BasicBlock* exit_block_;
- };
- } // namespace val
- } // namespace spvtools
- #endif // SOURCE_VAL_CONSTRUCT_H_
|