Coverage Report

Created: 2020-06-26 05:44

/home/arjun/llvm-project/mlir/lib/IR/Block.cpp
Line
Count
Source (jump to first uncovered line)
1
//===- Block.cpp - MLIR Block Class ---------------------------------------===//
2
//
3
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4
// See https://llvm.org/LICENSE.txt for license information.
5
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6
//
7
//===----------------------------------------------------------------------===//
8
9
#include "mlir/IR/Block.h"
10
#include "mlir/IR/Builders.h"
11
#include "mlir/IR/Operation.h"
12
using namespace mlir;
13
14
//===----------------------------------------------------------------------===//
15
// BlockArgument
16
//===----------------------------------------------------------------------===//
17
18
/// Returns the number of this argument.
19
0
unsigned BlockArgument::getArgNumber() const {
20
0
  // Arguments are not stored in place, so we have to find it within the list.
21
0
  auto argList = getOwner()->getArguments();
22
0
  return std::distance(argList.begin(), llvm::find(argList, *this));
23
0
}
24
25
//===----------------------------------------------------------------------===//
26
// Block
27
//===----------------------------------------------------------------------===//
28
29
Block::~Block() {
30
  assert(!verifyOpOrder() && "Expected valid operation ordering.");
31
  clear();
32
  for (BlockArgument arg : arguments)
33
    arg.destroy();
34
}
35
36
0
Region *Block::getParent() const { return parentValidOpOrderPair.getPointer(); }
37
38
/// Returns the closest surrounding operation that contains this block or
39
/// nullptr if this block is unlinked.
40
0
Operation *Block::getParentOp() {
41
0
  return getParent() ? getParent()->getParentOp() : nullptr;
42
0
}
43
44
/// Return if this block is the entry block in the parent region.
45
0
bool Block::isEntryBlock() { return this == &getParent()->front(); }
46
47
/// Insert this block (which must not already be in a region) right before the
48
/// specified block.
49
0
void Block::insertBefore(Block *block) {
50
0
  assert(!getParent() && "already inserted into a block!");
51
0
  assert(block->getParent() && "cannot insert before a block without a parent");
52
0
  block->getParent()->getBlocks().insert(block->getIterator(), this);
53
0
}
54
55
/// Unlink this block from its current region and insert it right before the
56
/// specific block.
57
0
void Block::moveBefore(Block *block) {
58
0
  assert(block->getParent() && "cannot insert before a block without a parent");
59
0
  block->getParent()->getBlocks().splice(
60
0
      block->getIterator(), getParent()->getBlocks(), getIterator());
61
0
}
62
63
/// Unlink this Block from its parent Region and delete it.
64
0
void Block::erase() {
65
0
  assert(getParent() && "Block has no parent");
66
0
  getParent()->getBlocks().erase(this);
67
0
}
68
69
/// Returns 'op' if 'op' lies in this block, or otherwise finds the
70
/// ancestor operation of 'op' that lies in this block. Returns nullptr if
71
/// the latter fails.
72
0
Operation *Block::findAncestorOpInBlock(Operation &op) {
73
0
  // Traverse up the operation hierarchy starting from the owner of operand to
74
0
  // find the ancestor operation that resides in the block of 'forOp'.
75
0
  auto *currOp = &op;
76
0
  while (currOp->getBlock() != this) {
77
0
    currOp = currOp->getParentOp();
78
0
    if (!currOp)
79
0
      return nullptr;
80
0
  }
81
0
  return currOp;
82
0
}
83
84
/// This drops all operand uses from operations within this block, which is
85
/// an essential step in breaking cyclic dependences between references when
86
/// they are to be deleted.
87
0
void Block::dropAllReferences() {
88
0
  for (Operation &i : *this)
89
0
    i.dropAllReferences();
90
0
}
91
92
0
void Block::dropAllDefinedValueUses() {
93
0
  for (auto arg : getArguments())
94
0
    arg.dropAllUses();
95
0
  for (auto &op : *this)
96
0
    op.dropAllDefinedValueUses();
97
0
  dropAllUses();
98
0
}
99
100
/// Returns true if the ordering of the child operations is valid, false
101
/// otherwise.
102
0
bool Block::isOpOrderValid() { return parentValidOpOrderPair.getInt(); }
103
104
/// Invalidates the current ordering of operations.
105
0
void Block::invalidateOpOrder() {
106
0
  // Validate the current ordering.
107
0
  assert(!verifyOpOrder());
108
0
  parentValidOpOrderPair.setInt(false);
109
0
}
110
111
/// Verifies the current ordering of child operations. Returns false if the
112
/// order is valid, true otherwise.
113
0
bool Block::verifyOpOrder() {
114
0
  // The order is already known to be invalid.
115
0
  if (!isOpOrderValid())
116
0
    return false;
117
0
  // The order is valid if there are less than 2 operations.
118
0
  if (operations.empty() || std::next(operations.begin()) == operations.end())
119
0
    return false;
120
0
121
0
  Operation *prev = nullptr;
122
0
  for (auto &i : *this) {
123
0
    // The previous operation must have a smaller order index than the next as
124
0
    // it appears earlier in the list.
125
0
    if (prev && prev->orderIndex != Operation::kInvalidOrderIdx &&
126
0
        prev->orderIndex >= i.orderIndex)
127
0
      return true;
128
0
    prev = &i;
129
0
  }
130
0
  return false;
131
0
}
132
133
/// Recomputes the ordering of child operations within the block.
134
0
void Block::recomputeOpOrder() {
135
0
  parentValidOpOrderPair.setInt(true);
136
0
137
0
  unsigned orderIndex = 0;
138
0
  for (auto &op : *this)
139
0
    op.orderIndex = (orderIndex += Operation::kOrderStride);
140
0
}
141
142
//===----------------------------------------------------------------------===//
143
// Argument list management.
144
//===----------------------------------------------------------------------===//
145
146
/// Return a range containing the types of the arguments for this block.
147
0
auto Block::getArgumentTypes() -> ValueTypeRange<BlockArgListType> {
148
0
  return ValueTypeRange<BlockArgListType>(getArguments());
149
0
}
150
151
0
BlockArgument Block::addArgument(Type type) {
152
0
  BlockArgument arg = BlockArgument::create(type, this);
153
0
  arguments.push_back(arg);
154
0
  return arg;
155
0
}
156
157
/// Add one argument to the argument list for each type specified in the list.
158
0
auto Block::addArguments(TypeRange types) -> iterator_range<args_iterator> {
159
0
  size_t initialSize = arguments.size();
160
0
  arguments.reserve(initialSize + types.size());
161
0
  for (auto type : types)
162
0
    addArgument(type);
163
0
  return {arguments.data() + initialSize, arguments.data() + arguments.size()};
164
0
}
165
166
0
BlockArgument Block::insertArgument(unsigned index, Type type) {
167
0
  auto arg = BlockArgument::create(type, this);
168
0
  assert(index <= arguments.size());
169
0
  arguments.insert(arguments.begin() + index, arg);
170
0
  return arg;
171
0
}
172
173
0
void Block::eraseArgument(unsigned index) {
174
0
  assert(index < arguments.size());
175
0
  arguments[index].destroy();
176
0
  arguments.erase(arguments.begin() + index);
177
0
}
178
179
/// Insert one value to the given position of the argument list. The existing
180
/// arguments are shifted. The block is expected not to have predecessors.
181
0
BlockArgument Block::insertArgument(args_iterator it, Type type) {
182
0
  assert(llvm::empty(getPredecessors()) &&
183
0
         "cannot insert arguments to blocks with predecessors");
184
0
185
0
  // Use the args_iterator (on the BlockArgListType) to compute the insertion
186
0
  // iterator in the underlying argument storage.
187
0
  size_t distance = std::distance(args_begin(), it);
188
0
  auto arg = BlockArgument::create(type, this);
189
0
  arguments.insert(std::next(arguments.begin(), distance), arg);
190
0
  return arg;
191
0
}
192
193
//===----------------------------------------------------------------------===//
194
// Terminator management
195
//===----------------------------------------------------------------------===//
196
197
/// Get the terminator operation of this block. This function asserts that
198
/// the block has a valid terminator operation.
199
0
Operation *Block::getTerminator() {
200
0
  assert(!empty() && !back().isKnownNonTerminator());
201
0
  return &back();
202
0
}
203
204
/// Return true if this block has no predecessors.
205
0
bool Block::hasNoPredecessors() { return pred_begin() == pred_end(); }
206
207
// Indexed successor access.
208
0
unsigned Block::getNumSuccessors() {
209
0
  return empty() ? 0 : back().getNumSuccessors();
210
0
}
211
212
0
Block *Block::getSuccessor(unsigned i) {
213
0
  assert(i < getNumSuccessors());
214
0
  return getTerminator()->getSuccessor(i);
215
0
}
216
217
/// If this block has exactly one predecessor, return it.  Otherwise, return
218
/// null.
219
///
220
/// Note that multiple edges from a single block (e.g. if you have a cond
221
/// branch with the same block as the true/false destinations) is not
222
/// considered to be a single predecessor.
223
0
Block *Block::getSinglePredecessor() {
224
0
  auto it = pred_begin();
225
0
  if (it == pred_end())
226
0
    return nullptr;
227
0
  auto *firstPred = *it;
228
0
  ++it;
229
0
  return it == pred_end() ? firstPred : nullptr;
230
0
}
231
232
/// If this block has a unique predecessor, i.e., all incoming edges originate
233
/// from one block, return it. Otherwise, return null.
234
0
Block *Block::getUniquePredecessor() {
235
0
  auto it = pred_begin(), e = pred_end();
236
0
  if (it == e)
237
0
    return nullptr;
238
0
239
0
  // Check for any conflicting predecessors.
240
0
  auto *firstPred = *it;
241
0
  for (++it; it != e; ++it)
242
0
    if (*it != firstPred)
243
0
      return nullptr;
244
0
  return firstPred;
245
0
}
246
247
//===----------------------------------------------------------------------===//
248
// Other
249
//===----------------------------------------------------------------------===//
250
251
/// Split the block into two blocks before the specified operation or
252
/// iterator.
253
///
254
/// Note that all operations BEFORE the specified iterator stay as part of
255
/// the original basic block, and the rest of the operations in the original
256
/// block are moved to the new block, including the old terminator.  The
257
/// original block is left without a terminator.
258
///
259
/// The newly formed Block is returned, and the specified iterator is
260
/// invalidated.
261
0
Block *Block::splitBlock(iterator splitBefore) {
262
0
  // Start by creating a new basic block, and insert it immediate after this
263
0
  // one in the containing region.
264
0
  auto newBB = new Block();
265
0
  getParent()->getBlocks().insert(std::next(Region::iterator(this)), newBB);
266
0
267
0
  // Move all of the operations from the split point to the end of the region
268
0
  // into the new block.
269
0
  newBB->getOperations().splice(newBB->end(), getOperations(), splitBefore,
270
0
                                end());
271
0
  return newBB;
272
0
}
273
274
//===----------------------------------------------------------------------===//
275
// Predecessors
276
//===----------------------------------------------------------------------===//
277
278
0
Block *PredecessorIterator::unwrap(BlockOperand &value) {
279
0
  return value.getOwner()->getBlock();
280
0
}
281
282
/// Get the successor number in the predecessor terminator.
283
0
unsigned PredecessorIterator::getSuccessorIndex() const {
284
0
  return I->getOperandNumber();
285
0
}
286
287
//===----------------------------------------------------------------------===//
288
// Successors
289
//===----------------------------------------------------------------------===//
290
291
0
SuccessorRange::SuccessorRange(Block *block) : SuccessorRange(nullptr, 0) {
292
0
  if (Operation *term = block->getTerminator())
293
0
    if ((count = term->getNumSuccessors()))
294
0
      base = term->getBlockOperands().data();
295
0
}
296
297
0
SuccessorRange::SuccessorRange(Operation *term) : SuccessorRange(nullptr, 0) {
298
0
  if ((count = term->getNumSuccessors()))
299
0
    base = term->getBlockOperands().data();
300
0
}