| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320 |
- // 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_BASIC_BLOCK_H_
- #define SOURCE_VAL_BASIC_BLOCK_H_
- #include <bitset>
- #include <cstdint>
- #include <functional>
- #include <memory>
- #include <vector>
- #include "source/latest_version_spirv_header.h"
- namespace spvtools {
- namespace val {
- enum BlockType : uint32_t {
- kBlockTypeUndefined,
- kBlockTypeSelection,
- kBlockTypeLoop,
- kBlockTypeMerge,
- kBlockTypeBreak,
- kBlockTypeContinue,
- kBlockTypeReturn,
- kBlockTypeCOUNT ///< Total number of block types. (must be the last element)
- };
- class Instruction;
- // This class represents a basic block in a SPIR-V module
- class BasicBlock {
- public:
- /// Constructor for a BasicBlock
- ///
- /// @param[in] id The ID of the basic block
- explicit BasicBlock(uint32_t id);
- /// Returns the id of the BasicBlock
- uint32_t id() const { return id_; }
- /// Returns the predecessors of the BasicBlock
- const std::vector<BasicBlock*>* predecessors() const {
- return &predecessors_;
- }
- /// Returns the predecessors of the BasicBlock
- std::vector<BasicBlock*>* predecessors() { return &predecessors_; }
- /// Returns the successors of the BasicBlock
- const std::vector<BasicBlock*>* successors() const { return &successors_; }
- /// Returns the successors of the BasicBlock
- std::vector<BasicBlock*>* successors() { return &successors_; }
- /// Returns the structural successors of the BasicBlock
- std::vector<BasicBlock*>* structural_predecessors() {
- return &structural_predecessors_;
- }
- /// Returns the structural predecessors of the BasicBlock
- const std::vector<BasicBlock*>* structural_predecessors() const {
- return &structural_predecessors_;
- }
- /// Returns the structural successors of the BasicBlock
- std::vector<BasicBlock*>* structural_successors() {
- return &structural_successors_;
- }
- /// Returns the structural predecessors of the BasicBlock
- const std::vector<BasicBlock*>* structural_successors() const {
- return &structural_successors_;
- }
- /// Returns true if the block is reachable in the CFG.
- bool reachable() const { return reachable_; }
- /// Returns true if the block is structurally reachable in the CFG.
- bool structurally_reachable() const { return structurally_reachable_; }
- /// Returns true if BasicBlock is of the given type
- bool is_type(BlockType type) const {
- if (type == kBlockTypeUndefined) return type_.none();
- return type_.test(type);
- }
- /// Sets the reachability of the basic block in the CFG
- void set_reachable(bool reachability) { reachable_ = reachability; }
- /// Sets the structural reachability of the basic block in the CFG
- void set_structurally_reachable(bool reachability) {
- structurally_reachable_ = reachability;
- }
- /// Sets the type of the BasicBlock
- void set_type(BlockType type) {
- if (type == kBlockTypeUndefined)
- type_.reset();
- else
- type_.set(type);
- }
- /// Sets the immediate dominator of this basic block
- ///
- /// @param[in] dom_block The dominator block
- void SetImmediateDominator(BasicBlock* dom_block);
- /// Sets the immediate dominator of this basic block
- ///
- /// @param[in] dom_block The dominator block
- void SetImmediateStructuralDominator(BasicBlock* dom_block);
- /// Sets the immediate post dominator of this basic block
- ///
- /// @param[in] pdom_block The post dominator block
- void SetImmediateStructuralPostDominator(BasicBlock* pdom_block);
- /// Returns the immediate dominator of this basic block
- BasicBlock* immediate_dominator();
- /// Returns the immediate dominator of this basic block
- const BasicBlock* immediate_dominator() const;
- /// Returns the immediate dominator of this basic block
- BasicBlock* immediate_structural_dominator();
- /// Returns the immediate dominator of this basic block
- const BasicBlock* immediate_structural_dominator() const;
- /// Returns the immediate post dominator of this basic block
- BasicBlock* immediate_structural_post_dominator();
- /// Returns the immediate post dominator of this basic block
- const BasicBlock* immediate_structural_post_dominator() const;
- /// Returns the label instruction for the block, or nullptr if not set.
- const Instruction* label() const { return label_; }
- //// Registers the label instruction for the block.
- void set_label(const Instruction* t) { label_ = t; }
- /// Registers the terminator instruction for the block.
- void set_terminator(const Instruction* t) { terminator_ = t; }
- /// Returns the terminator instruction for the block.
- const Instruction* terminator() const { return terminator_; }
- /// Adds @p next BasicBlocks as successors of this BasicBlock
- void RegisterSuccessors(
- const std::vector<BasicBlock*>& next = std::vector<BasicBlock*>());
- /// Returns true if the id of the BasicBlock matches
- bool operator==(const BasicBlock& other) const { return other.id_ == id_; }
- /// Returns true if the id of the BasicBlock matches
- bool operator==(const uint32_t& other_id) const { return other_id == id_; }
- /// Returns true if this block dominates the other block.
- /// Assumes dominators have been computed.
- bool dominates(const BasicBlock& other) const;
- /// Returns true if this block structurally dominates the other block.
- /// Assumes structural dominators have been computed.
- bool structurally_dominates(const BasicBlock& other) const;
- /// Returns true if this block structurally postdominates the other block.
- /// Assumes structural dominators have been computed.
- bool structurally_postdominates(const BasicBlock& other) const;
- void RegisterStructuralSuccessor(BasicBlock* block) {
- block->structural_predecessors_.push_back(this);
- structural_successors_.push_back(block);
- }
- /// @brief A BasicBlock dominator iterator class
- ///
- /// This iterator will iterate over the (post)dominators of the block
- class DominatorIterator {
- public:
- using iterator_category = std::forward_iterator_tag;
- using value_type = BasicBlock*;
- using pointer = value_type*;
- using reference = value_type&;
- using difference_type = std::ptrdiff_t;
- /// @brief Constructs the end of dominator iterator
- ///
- /// This will create an iterator which will represent the element
- /// before the root node of the dominator tree
- DominatorIterator();
- /// @brief Constructs an iterator for the given block which points to
- /// @p block
- ///
- /// @param block The block which is referenced by the iterator
- /// @param dominator_func This function will be called to get the immediate
- /// (post)dominator of the current block
- DominatorIterator(
- const BasicBlock* block,
- std::function<const BasicBlock*(const BasicBlock*)> dominator_func);
- /// @brief Advances the iterator
- DominatorIterator& operator++();
- /// @brief Returns the current element
- const BasicBlock*& operator*();
- friend bool operator==(const DominatorIterator& lhs,
- const DominatorIterator& rhs);
- private:
- const BasicBlock* current_;
- std::function<const BasicBlock*(const BasicBlock*)> dom_func_;
- };
- /// Returns a dominator iterator which points to the current block
- const DominatorIterator dom_begin() const;
- /// Returns a dominator iterator which points to the current block
- DominatorIterator dom_begin();
- /// Returns a dominator iterator which points to one element past the first
- /// block
- const DominatorIterator dom_end() const;
- /// Returns a dominator iterator which points to one element past the first
- /// block
- DominatorIterator dom_end();
- /// Returns a dominator iterator which points to the current block
- const DominatorIterator structural_dom_begin() const;
- /// Returns a dominator iterator which points to the current block
- DominatorIterator structural_dom_begin();
- /// Returns a dominator iterator which points to one element past the first
- /// block
- const DominatorIterator structural_dom_end() const;
- /// Returns a dominator iterator which points to one element past the first
- /// block
- DominatorIterator structural_dom_end();
- /// Returns a post dominator iterator which points to the current block
- const DominatorIterator structural_pdom_begin() const;
- /// Returns a post dominator iterator which points to the current block
- DominatorIterator structural_pdom_begin();
- /// Returns a post dominator iterator which points to one element past the
- /// last block
- const DominatorIterator structural_pdom_end() const;
- /// Returns a post dominator iterator which points to one element past the
- /// last block
- DominatorIterator structural_pdom_end();
- private:
- /// Id of the BasicBlock
- const uint32_t id_;
- /// Pointer to the immediate dominator of the BasicBlock
- BasicBlock* immediate_dominator_;
- /// Pointer to the immediate structural dominator of the BasicBlock
- BasicBlock* immediate_structural_dominator_;
- /// Pointer to the immediate structural post dominator of the BasicBlock
- BasicBlock* immediate_structural_post_dominator_;
- /// The set of predecessors of the BasicBlock
- std::vector<BasicBlock*> predecessors_;
- /// The set of successors of the BasicBlock
- std::vector<BasicBlock*> successors_;
- /// The type of the block
- std::bitset<kBlockTypeCOUNT> type_;
- /// True if the block is reachable in the CFG
- bool reachable_;
- /// True if the block is structurally reachable in the CFG
- bool structurally_reachable_;
- /// label of this block, if any.
- const Instruction* label_;
- /// Terminator of this block.
- const Instruction* terminator_;
- std::vector<BasicBlock*> structural_predecessors_;
- std::vector<BasicBlock*> structural_successors_;
- };
- /// @brief Returns true if the iterators point to the same element or if both
- /// iterators point to the @p dom_end block
- bool operator==(const BasicBlock::DominatorIterator& lhs,
- const BasicBlock::DominatorIterator& rhs);
- /// @brief Returns true if the iterators point to different elements and they
- /// do not both point to the @p dom_end block
- bool operator!=(const BasicBlock::DominatorIterator& lhs,
- const BasicBlock::DominatorIterator& rhs);
- } // namespace val
- } // namespace spvtools
- #endif // SOURCE_VAL_BASIC_BLOCK_H_
|