Coverage Report

Created: 2025-11-16 06:14

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/spirv-tools/source/val/basic_block.h
Line
Count
Source
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
#ifndef SOURCE_VAL_BASIC_BLOCK_H_
16
#define SOURCE_VAL_BASIC_BLOCK_H_
17
18
#include <bitset>
19
#include <cstdint>
20
#include <functional>
21
#include <memory>
22
#include <vector>
23
24
#include "source/latest_version_spirv_header.h"
25
26
namespace spvtools {
27
namespace val {
28
29
enum BlockType : uint32_t {
30
  kBlockTypeUndefined,
31
  kBlockTypeSelection,
32
  kBlockTypeLoop,
33
  kBlockTypeMerge,
34
  kBlockTypeBreak,
35
  kBlockTypeContinue,
36
  kBlockTypeReturn,
37
  kBlockTypeCOUNT  ///< Total number of block types. (must be the last element)
38
};
39
40
class Instruction;
41
42
// This class represents a basic block in a SPIR-V module
43
class BasicBlock {
44
 public:
45
  /// Constructor for a BasicBlock
46
  ///
47
  /// @param[in] id The ID of the basic block
48
  explicit BasicBlock(uint32_t id);
49
50
  /// Returns the id of the BasicBlock
51
33.1M
  uint32_t id() const { return id_; }
52
53
  /// Returns the predecessors of the BasicBlock
54
656k
  const std::vector<BasicBlock*>* predecessors() const {
55
656k
    return &predecessors_;
56
656k
  }
57
58
  /// Returns the predecessors of the BasicBlock
59
375k
  std::vector<BasicBlock*>* predecessors() { return &predecessors_; }
60
61
  /// Returns the successors of the BasicBlock
62
885k
  const std::vector<BasicBlock*>* successors() const { return &successors_; }
63
64
  /// Returns the successors of the BasicBlock
65
859k
  std::vector<BasicBlock*>* successors() { return &successors_; }
66
67
  /// Returns the structural successors of the BasicBlock
68
0
  std::vector<BasicBlock*>* structural_predecessors() {
69
0
    return &structural_predecessors_;
70
0
  }
71
72
  /// Returns the structural predecessors of the BasicBlock
73
5.30M
  const std::vector<BasicBlock*>* structural_predecessors() const {
74
5.30M
    return &structural_predecessors_;
75
5.30M
  }
76
77
  /// Returns the structural successors of the BasicBlock
78
808k
  std::vector<BasicBlock*>* structural_successors() {
79
808k
    return &structural_successors_;
80
808k
  }
81
82
  /// Returns the structural predecessors of the BasicBlock
83
5.27M
  const std::vector<BasicBlock*>* structural_successors() const {
84
5.27M
    return &structural_successors_;
85
5.27M
  }
86
87
  /// Returns true if the block is reachable in the CFG.
88
1.70M
  bool reachable() const { return reachable_; }
89
90
  /// Returns true if the block is structurally reachable in the CFG.
91
1.89M
  bool structurally_reachable() const { return structurally_reachable_; }
92
93
  /// Returns true if BasicBlock is of the given type
94
2.03M
  bool is_type(BlockType type) const {
95
2.03M
    if (type == kBlockTypeUndefined) return type_.none();
96
2.03M
    return type_.test(type);
97
2.03M
  }
98
99
  /// Sets the reachability of the basic block in the CFG
100
308k
  void set_reachable(bool reachability) { reachable_ = reachability; }
101
102
  /// Sets the structural reachability of the basic block in the CFG
103
330k
  void set_structurally_reachable(bool reachability) {
104
330k
    structurally_reachable_ = reachability;
105
330k
  }
106
107
  /// Sets the type of the BasicBlock
108
339k
  void set_type(BlockType type) {
109
339k
    if (type == kBlockTypeUndefined)
110
0
      type_.reset();
111
339k
    else
112
339k
      type_.set(type);
113
339k
  }
114
115
  /// Sets the immediate dominator of this basic block
116
  ///
117
  /// @param[in] dom_block The dominator block
118
  void SetImmediateDominator(BasicBlock* dom_block);
119
120
  /// Sets the immediate dominator of this basic block
121
  ///
122
  /// @param[in] dom_block The dominator block
123
  void SetImmediateStructuralDominator(BasicBlock* dom_block);
124
125
  /// Sets the immediate post dominator of this basic block
126
  ///
127
  /// @param[in] pdom_block The post dominator block
128
  void SetImmediateStructuralPostDominator(BasicBlock* pdom_block);
129
130
  /// Returns the immediate dominator of this basic block
131
  BasicBlock* immediate_dominator();
132
133
  /// Returns the immediate dominator of this basic block
134
  const BasicBlock* immediate_dominator() const;
135
136
  /// Returns the immediate dominator of this basic block
137
  BasicBlock* immediate_structural_dominator();
138
139
  /// Returns the immediate dominator of this basic block
140
  const BasicBlock* immediate_structural_dominator() const;
141
142
  /// Returns the immediate post dominator of this basic block
143
  BasicBlock* immediate_structural_post_dominator();
144
145
  /// Returns the immediate post dominator of this basic block
146
  const BasicBlock* immediate_structural_post_dominator() const;
147
148
  /// Returns the label instruction for the block, or nullptr if not set.
149
52.2k
  const Instruction* label() const { return label_; }
150
151
  //// Registers the label instruction for the block.
152
392k
  void set_label(const Instruction* t) { label_ = t; }
153
154
  /// Registers the terminator instruction for the block.
155
391k
  void set_terminator(const Instruction* t) { terminator_ = t; }
156
157
  /// Returns the terminator instruction for the block.
158
625k
  const Instruction* terminator() const { return terminator_; }
159
160
  /// Adds @p next BasicBlocks as successors of this BasicBlock
161
  void RegisterSuccessors(
162
      const std::vector<BasicBlock*>& next = std::vector<BasicBlock*>());
163
164
  /// Returns true if the id of the BasicBlock matches
165
0
  bool operator==(const BasicBlock& other) const { return other.id_ == id_; }
166
167
  /// Returns true if the id of the BasicBlock matches
168
474k
  bool operator==(const uint32_t& other_id) const { return other_id == id_; }
169
170
  /// Returns true if this block dominates the other block.
171
  /// Assumes dominators have been computed.
172
  bool dominates(const BasicBlock& other) const;
173
174
  /// Returns true if this block structurally dominates the other block.
175
  /// Assumes structural dominators have been computed.
176
  bool structurally_dominates(const BasicBlock& other) const;
177
178
  /// Returns true if this block structurally postdominates the other block.
179
  /// Assumes structural dominators have been computed.
180
  bool structurally_postdominates(const BasicBlock& other) const;
181
182
203k
  void RegisterStructuralSuccessor(BasicBlock* block) {
183
203k
    block->structural_predecessors_.push_back(this);
184
203k
    structural_successors_.push_back(block);
185
203k
  }
186
187
  /// @brief A BasicBlock dominator iterator class
188
  ///
189
  /// This iterator will iterate over the (post)dominators of the block
190
  class DominatorIterator {
191
   public:
192
    using iterator_category = std::forward_iterator_tag;
193
    using value_type = BasicBlock*;
194
    using pointer = value_type*;
195
    using reference = value_type&;
196
    using difference_type = std::ptrdiff_t;
197
198
    /// @brief Constructs the end of dominator iterator
199
    ///
200
    /// This will create an iterator which will represent the element
201
    /// before the root node of the dominator tree
202
    DominatorIterator();
203
204
    /// @brief Constructs an iterator for the given block which points to
205
    ///        @p block
206
    ///
207
    /// @param block          The block which is referenced by the iterator
208
    /// @param dominator_func This function will be called to get the immediate
209
    ///                       (post)dominator of the current block
210
    DominatorIterator(
211
        const BasicBlock* block,
212
        std::function<const BasicBlock*(const BasicBlock*)> dominator_func);
213
214
    /// @brief Advances the iterator
215
    DominatorIterator& operator++();
216
217
    /// @brief Returns the current element
218
    const BasicBlock*& operator*();
219
220
    friend bool operator==(const DominatorIterator& lhs,
221
                           const DominatorIterator& rhs);
222
223
   private:
224
    const BasicBlock* current_;
225
    std::function<const BasicBlock*(const BasicBlock*)> dom_func_;
226
  };
227
228
  /// Returns a dominator iterator which points to the current block
229
  const DominatorIterator dom_begin() const;
230
231
  /// Returns a dominator iterator which points to the current block
232
  DominatorIterator dom_begin();
233
234
  /// Returns a dominator iterator which points to one element past the first
235
  /// block
236
  const DominatorIterator dom_end() const;
237
238
  /// Returns a dominator iterator which points to one element past the first
239
  /// block
240
  DominatorIterator dom_end();
241
242
  /// Returns a dominator iterator which points to the current block
243
  const DominatorIterator structural_dom_begin() const;
244
245
  /// Returns a dominator iterator which points to the current block
246
  DominatorIterator structural_dom_begin();
247
248
  /// Returns a dominator iterator which points to one element past the first
249
  /// block
250
  const DominatorIterator structural_dom_end() const;
251
252
  /// Returns a dominator iterator which points to one element past the first
253
  /// block
254
  DominatorIterator structural_dom_end();
255
256
  /// Returns a post dominator iterator which points to the current block
257
  const DominatorIterator structural_pdom_begin() const;
258
  /// Returns a post dominator iterator which points to the current block
259
  DominatorIterator structural_pdom_begin();
260
261
  /// Returns a post dominator iterator which points to one element past the
262
  /// last block
263
  const DominatorIterator structural_pdom_end() const;
264
265
  /// Returns a post dominator iterator which points to one element past the
266
  /// last block
267
  DominatorIterator structural_pdom_end();
268
269
 private:
270
  /// Id of the BasicBlock
271
  const uint32_t id_;
272
273
  /// Pointer to the immediate dominator of the BasicBlock
274
  BasicBlock* immediate_dominator_;
275
276
  /// Pointer to the immediate structural dominator of the BasicBlock
277
  BasicBlock* immediate_structural_dominator_;
278
279
  /// Pointer to the immediate structural post dominator of the BasicBlock
280
  BasicBlock* immediate_structural_post_dominator_;
281
282
  /// The set of predecessors of the BasicBlock
283
  std::vector<BasicBlock*> predecessors_;
284
285
  /// The set of successors of the BasicBlock
286
  std::vector<BasicBlock*> successors_;
287
288
  /// The type of the block
289
  std::bitset<kBlockTypeCOUNT> type_;
290
291
  /// True if the block is reachable in the CFG
292
  bool reachable_;
293
294
  /// True if the block is structurally reachable in the CFG
295
  bool structurally_reachable_;
296
297
  /// label of this block, if any.
298
  const Instruction* label_;
299
300
  /// Terminator of this block.
301
  const Instruction* terminator_;
302
303
  std::vector<BasicBlock*> structural_predecessors_;
304
  std::vector<BasicBlock*> structural_successors_;
305
};
306
307
/// @brief Returns true if the iterators point to the same element or if both
308
///        iterators point to the @p dom_end block
309
bool operator==(const BasicBlock::DominatorIterator& lhs,
310
                const BasicBlock::DominatorIterator& rhs);
311
312
/// @brief Returns true if the iterators point to different elements and they
313
///        do not both point to the @p dom_end block
314
bool operator!=(const BasicBlock::DominatorIterator& lhs,
315
                const BasicBlock::DominatorIterator& rhs);
316
317
}  // namespace val
318
}  // namespace spvtools
319
320
#endif  // SOURCE_VAL_BASIC_BLOCK_H_