Home | History | Annotate | Download | only in opt
      1 // Copyright (c) 2016 Google 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 
     15 #include "basic_block.h"
     16 
     17 namespace spvtools {
     18 namespace ir {
     19 
     20 const Instruction* BasicBlock::GetMergeInst() const {
     21   const Instruction* result = nullptr;
     22   // If it exists, the merge instruction immediately precedes the
     23   // terminator.
     24   auto iter = ctail();
     25   if (iter != cbegin()) {
     26     --iter;
     27     const auto opcode = iter->opcode();
     28     if (opcode == SpvOpLoopMerge || opcode  == SpvOpSelectionMerge) {
     29       result = &*iter;
     30     }
     31   }
     32   return result;
     33 }
     34 
     35 Instruction* BasicBlock::GetMergeInst() {
     36   Instruction* result = nullptr;
     37   // If it exists, the merge instruction immediately precedes the
     38   // terminator.
     39   auto iter = tail();
     40   if (iter != begin()) {
     41     --iter;
     42     const auto opcode = iter->opcode();
     43     if (opcode == SpvOpLoopMerge || opcode  == SpvOpSelectionMerge) {
     44       result = &*iter;
     45     }
     46   }
     47   return result;
     48 }
     49 
     50 const Instruction* BasicBlock::GetLoopMergeInst() const {
     51   if (auto* merge = GetMergeInst()) {
     52     if (merge->opcode() == SpvOpLoopMerge) {
     53       return merge;
     54     }
     55   }
     56   return nullptr;
     57 }
     58 
     59 Instruction* BasicBlock::GetLoopMergeInst() {
     60   if (auto* merge = GetMergeInst()) {
     61     if (merge->opcode() == SpvOpLoopMerge) {
     62       return merge;
     63     }
     64   }
     65   return nullptr;
     66 }
     67 
     68 void BasicBlock::ForEachSuccessorLabel(
     69     const std::function<void(const uint32_t)>& f) {
     70   const auto br = &*insts_.back();
     71   switch (br->opcode()) {
     72     case SpvOpBranch: {
     73       f(br->GetOperand(0).words[0]);
     74     } break;
     75     case SpvOpBranchConditional:
     76     case SpvOpSwitch: {
     77       bool is_first = true;
     78       br->ForEachInId([&is_first, &f](const uint32_t* idp) {
     79         if (!is_first) f(*idp);
     80         is_first = false;
     81       });
     82     } break;
     83     default:
     84       break;
     85   }
     86 }
     87 
     88 void BasicBlock::ForMergeAndContinueLabel(
     89     const std::function<void(const uint32_t)>& f) {
     90   auto ii = insts_.end();
     91   --ii;
     92   if (ii == insts_.begin()) return;
     93   --ii;
     94   if ((*ii)->opcode() == SpvOpSelectionMerge ||
     95       (*ii)->opcode() == SpvOpLoopMerge)
     96     (*ii)->ForEachInId([&f](const uint32_t* idp) {
     97       f(*idp);
     98     });
     99 }
    100 
    101 }  // namespace ir
    102 }  // namespace spvtools
    103 
    104