1 // Copyright (c) 2015-2016 The Khronos Group 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 "source/val/basic_block.h"
16
17 #include <algorithm>
18 #include <utility>
19 #include <vector>
20
21 namespace spvtools {
22 namespace val {
23
BasicBlock(uint32_t label_id)24 BasicBlock::BasicBlock(uint32_t label_id)
25 : id_(label_id),
26 immediate_dominator_(nullptr),
27 immediate_structural_dominator_(nullptr),
28 immediate_structural_post_dominator_(nullptr),
29 predecessors_(),
30 successors_(),
31 type_(0),
32 reachable_(false),
33 structurally_reachable_(false),
34 label_(nullptr),
35 terminator_(nullptr) {}
36
SetImmediateDominator(BasicBlock * dom_block)37 void BasicBlock::SetImmediateDominator(BasicBlock* dom_block) {
38 immediate_dominator_ = dom_block;
39 }
40
SetImmediateStructuralDominator(BasicBlock * dom_block)41 void BasicBlock::SetImmediateStructuralDominator(BasicBlock* dom_block) {
42 immediate_structural_dominator_ = dom_block;
43 }
44
SetImmediateStructuralPostDominator(BasicBlock * pdom_block)45 void BasicBlock::SetImmediateStructuralPostDominator(BasicBlock* pdom_block) {
46 immediate_structural_post_dominator_ = pdom_block;
47 }
48
immediate_dominator() const49 const BasicBlock* BasicBlock::immediate_dominator() const {
50 return immediate_dominator_;
51 }
52
immediate_structural_dominator() const53 const BasicBlock* BasicBlock::immediate_structural_dominator() const {
54 return immediate_structural_dominator_;
55 }
56
immediate_structural_post_dominator() const57 const BasicBlock* BasicBlock::immediate_structural_post_dominator() const {
58 return immediate_structural_post_dominator_;
59 }
60
immediate_dominator()61 BasicBlock* BasicBlock::immediate_dominator() { return immediate_dominator_; }
immediate_structural_dominator()62 BasicBlock* BasicBlock::immediate_structural_dominator() {
63 return immediate_structural_dominator_;
64 }
immediate_structural_post_dominator()65 BasicBlock* BasicBlock::immediate_structural_post_dominator() {
66 return immediate_structural_post_dominator_;
67 }
68
RegisterSuccessors(const std::vector<BasicBlock * > & next_blocks)69 void BasicBlock::RegisterSuccessors(
70 const std::vector<BasicBlock*>& next_blocks) {
71 for (auto& block : next_blocks) {
72 block->predecessors_.push_back(this);
73 successors_.push_back(block);
74
75 // Register structural successors/predecessors too.
76 block->structural_predecessors_.push_back(this);
77 structural_successors_.push_back(block);
78 }
79 }
80
dominates(const BasicBlock & other) const81 bool BasicBlock::dominates(const BasicBlock& other) const {
82 return (this == &other) ||
83 !(other.dom_end() ==
84 std::find(other.dom_begin(), other.dom_end(), this));
85 }
86
structurally_dominates(const BasicBlock & other) const87 bool BasicBlock::structurally_dominates(const BasicBlock& other) const {
88 return (this == &other) || !(other.structural_dom_end() ==
89 std::find(other.structural_dom_begin(),
90 other.structural_dom_end(), this));
91 }
92
structurally_postdominates(const BasicBlock & other) const93 bool BasicBlock::structurally_postdominates(const BasicBlock& other) const {
94 return (this == &other) || !(other.structural_pdom_end() ==
95 std::find(other.structural_pdom_begin(),
96 other.structural_pdom_end(), this));
97 }
98
DominatorIterator()99 BasicBlock::DominatorIterator::DominatorIterator() : current_(nullptr) {}
100
DominatorIterator(const BasicBlock * block,std::function<const BasicBlock * (const BasicBlock *)> dominator_func)101 BasicBlock::DominatorIterator::DominatorIterator(
102 const BasicBlock* block,
103 std::function<const BasicBlock*(const BasicBlock*)> dominator_func)
104 : current_(block), dom_func_(dominator_func) {}
105
operator ++()106 BasicBlock::DominatorIterator& BasicBlock::DominatorIterator::operator++() {
107 if (current_ == dom_func_(current_)) {
108 current_ = nullptr;
109 } else {
110 current_ = dom_func_(current_);
111 }
112 return *this;
113 }
114
dom_begin() const115 const BasicBlock::DominatorIterator BasicBlock::dom_begin() const {
116 return DominatorIterator(
117 this, [](const BasicBlock* b) { return b->immediate_dominator(); });
118 }
119
dom_begin()120 BasicBlock::DominatorIterator BasicBlock::dom_begin() {
121 return DominatorIterator(
122 this, [](const BasicBlock* b) { return b->immediate_dominator(); });
123 }
124
dom_end() const125 const BasicBlock::DominatorIterator BasicBlock::dom_end() const {
126 return DominatorIterator();
127 }
128
dom_end()129 BasicBlock::DominatorIterator BasicBlock::dom_end() {
130 return DominatorIterator();
131 }
132
structural_dom_begin() const133 const BasicBlock::DominatorIterator BasicBlock::structural_dom_begin() const {
134 return DominatorIterator(this, [](const BasicBlock* b) {
135 return b->immediate_structural_dominator();
136 });
137 }
138
structural_dom_begin()139 BasicBlock::DominatorIterator BasicBlock::structural_dom_begin() {
140 return DominatorIterator(this, [](const BasicBlock* b) {
141 return b->immediate_structural_dominator();
142 });
143 }
144
structural_dom_end() const145 const BasicBlock::DominatorIterator BasicBlock::structural_dom_end() const {
146 return DominatorIterator();
147 }
148
structural_dom_end()149 BasicBlock::DominatorIterator BasicBlock::structural_dom_end() {
150 return DominatorIterator();
151 }
152
structural_pdom_begin() const153 const BasicBlock::DominatorIterator BasicBlock::structural_pdom_begin() const {
154 return DominatorIterator(this, [](const BasicBlock* b) {
155 return b->immediate_structural_post_dominator();
156 });
157 }
158
structural_pdom_begin()159 BasicBlock::DominatorIterator BasicBlock::structural_pdom_begin() {
160 return DominatorIterator(this, [](const BasicBlock* b) {
161 return b->immediate_structural_post_dominator();
162 });
163 }
164
structural_pdom_end() const165 const BasicBlock::DominatorIterator BasicBlock::structural_pdom_end() const {
166 return DominatorIterator();
167 }
168
structural_pdom_end()169 BasicBlock::DominatorIterator BasicBlock::structural_pdom_end() {
170 return DominatorIterator();
171 }
172
operator ==(const BasicBlock::DominatorIterator & lhs,const BasicBlock::DominatorIterator & rhs)173 bool operator==(const BasicBlock::DominatorIterator& lhs,
174 const BasicBlock::DominatorIterator& rhs) {
175 return lhs.current_ == rhs.current_;
176 }
177
operator !=(const BasicBlock::DominatorIterator & lhs,const BasicBlock::DominatorIterator & rhs)178 bool operator!=(const BasicBlock::DominatorIterator& lhs,
179 const BasicBlock::DominatorIterator& rhs) {
180 return !(lhs == rhs);
181 }
182
operator *()183 const BasicBlock*& BasicBlock::DominatorIterator::operator*() {
184 return current_;
185 }
186
187 } // namespace val
188 } // namespace spvtools
189