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