Home | History | Annotate | Download | only in opt
      1 // Copyright (c) 2018 Google LLC.
      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 
     15 #ifndef SOURCE_OPT_STRUCT_CFG_ANALYSIS_H_
     16 #define SOURCE_OPT_STRUCT_CFG_ANALYSIS_H_
     17 
     18 #include <unordered_map>
     19 
     20 #include "source/opt/function.h"
     21 #include "source/util/bit_vector.h"
     22 
     23 namespace spvtools {
     24 namespace opt {
     25 
     26 class IRContext;
     27 
     28 // An analysis that, for each basic block, finds the constructs in which it is
     29 // contained, so we can easily get headers and merge nodes.
     30 class StructuredCFGAnalysis {
     31  public:
     32   explicit StructuredCFGAnalysis(IRContext* ctx);
     33 
     34   // Returns the id of the header of the innermost merge construct
     35   // that contains |bb_id|.  Returns |0| if |bb_id| is not contained in any
     36   // merge construct.
     37   uint32_t ContainingConstruct(uint32_t bb_id) {
     38     auto it = bb_to_construct_.find(bb_id);
     39     if (it == bb_to_construct_.end()) {
     40       return 0;
     41     }
     42     return it->second.containing_construct;
     43   }
     44 
     45   // Returns the id of the merge block of the innermost merge construct
     46   // that contains |bb_id|.  Returns |0| if |bb_id| is not contained in any
     47   // merge construct.
     48   uint32_t MergeBlock(uint32_t bb_id);
     49 
     50   // Returns the id of the header of the innermost loop construct
     51   // that contains |bb_id|.  Return |0| if |bb_id| is not contained in any loop
     52   // construct.
     53   uint32_t ContainingLoop(uint32_t bb_id) {
     54     auto it = bb_to_construct_.find(bb_id);
     55     if (it == bb_to_construct_.end()) {
     56       return 0;
     57     }
     58     return it->second.containing_loop;
     59   }
     60 
     61   // Returns the id of the merge block of the innermost loop construct
     62   // that contains |bb_id|.  Return |0| if |bb_id| is not contained in any loop
     63   // construct.
     64   uint32_t LoopMergeBlock(uint32_t bb_id);
     65 
     66   // Returns the id of the continue block of the innermost loop construct
     67   // that contains |bb_id|.  Return |0| if |bb_id| is not contained in any loop
     68   // construct.
     69   uint32_t LoopContinueBlock(uint32_t bb_id);
     70 
     71   bool IsContinueBlock(uint32_t bb_id);
     72   bool IsMergeBlock(uint32_t bb_id);
     73 
     74  private:
     75   // Struct used to hold the information for a basic block.
     76   // |containing_construct| is the header for the innermost containing
     77   // construct, or 0 if no such construct exists.  It could be a selection
     78   // construct or a loop construct. |containing_loop| is the innermost
     79   // containing loop construct, or 0 if the basic bloc is not in a loop.  If the
     80   // basic block is in a selection construct that is contained in a loop
     81   // construct, then these two values will not be the same.
     82   struct ConstructInfo {
     83     uint32_t containing_construct;
     84     uint32_t containing_loop;
     85   };
     86 
     87   // Populates |bb_to_construct_| with the innermost containing merge and loop
     88   // constructs for each basic block in |func|.
     89   void AddBlocksInFunction(Function* func);
     90 
     91   IRContext* context_;
     92 
     93   // A map from a basic block to the headers of its inner most containing
     94   // constructs.
     95   std::unordered_map<uint32_t, ConstructInfo> bb_to_construct_;
     96   utils::BitVector merge_blocks_;
     97 };
     98 
     99 }  // namespace opt
    100 }  // namespace spvtools
    101 #endif  // SOURCE_OPT_STRUCT_CFG_ANALYSIS_H_
    102