Coverage Report

Created: 2020-06-26 05:44

/home/arjun/llvm-project/mlir/lib/IR/Value.cpp
Line
Count
Source (jump to first uncovered line)
1
//===- Value.cpp - MLIR Value Classes -------------------------------------===//
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/Value.h"
10
#include "mlir/IR/Block.h"
11
#include "mlir/IR/Operation.h"
12
#include "mlir/IR/StandardTypes.h"
13
#include "llvm/ADT/SmallPtrSet.h"
14
15
using namespace mlir;
16
using namespace mlir::detail;
17
18
/// Construct a value.
19
Value::Value(BlockArgumentImpl *impl)
20
0
    : ownerAndKind(impl, Kind::BlockArgument) {}
21
0
Value::Value(Operation *op, unsigned resultNo) {
22
0
  assert(op->getNumResults() > resultNo && "invalid result number");
23
0
  if (LLVM_LIKELY(canPackResultInline(resultNo))) {
24
0
    ownerAndKind = {op, static_cast<Kind>(resultNo)};
25
0
    return;
26
0
  }
27
0
28
0
  // If we can't pack the result directly, grab the use list from the parent op.
29
0
  unsigned trailingNo = resultNo - OpResult::getMaxInlineResults();
30
0
  ownerAndKind = {op->getTrailingResult(trailingNo), Kind::TrailingOpResult};
31
0
}
32
33
/// Return the type of this value.
34
0
Type Value::getType() const {
35
0
  if (BlockArgument arg = dyn_cast<BlockArgument>())
36
0
    return arg.getType();
37
0
38
0
  // If this is an operation result, query the parent operation.
39
0
  OpResult result = cast<OpResult>();
40
0
  Operation *owner = result.getOwner();
41
0
  if (owner->hasSingleResult)
42
0
    return owner->resultType;
43
0
  return owner->resultType.cast<TupleType>().getType(result.getResultNumber());
44
0
}
45
46
/// Mutate the type of this Value to be of the specified type.
47
0
void Value::setType(Type newType) {
48
0
  if (BlockArgument arg = dyn_cast<BlockArgument>())
49
0
    return arg.setType(newType);
50
0
  OpResult result = cast<OpResult>();
51
0
52
0
  // If the owner has a single result, simply update it directly.
53
0
  Operation *owner = result.getOwner();
54
0
  if (owner->hasSingleResult) {
55
0
    owner->resultType = newType;
56
0
    return;
57
0
  }
58
0
  unsigned resultNo = result.getResultNumber();
59
0
60
0
  // Otherwise, rebuild the tuple if the new type is different from the current.
61
0
  auto curTypes = owner->resultType.cast<TupleType>().getTypes();
62
0
  if (curTypes[resultNo] == newType)
63
0
    return;
64
0
  auto newTypes = llvm::to_vector<4>(curTypes);
65
0
  newTypes[resultNo] = newType;
66
0
  owner->resultType = TupleType::get(newTypes, newType.getContext());
67
0
}
68
69
/// If this value is the result of an Operation, return the operation that
70
/// defines it.
71
0
Operation *Value::getDefiningOp() const {
72
0
  if (auto result = dyn_cast<OpResult>())
73
0
    return result.getOwner();
74
0
  return nullptr;
75
0
}
76
77
0
Location Value::getLoc() const {
78
0
  if (auto *op = getDefiningOp())
79
0
    return op->getLoc();
80
0
  return UnknownLoc::get(getContext());
81
0
}
82
83
/// Return the Region in which this Value is defined.
84
0
Region *Value::getParentRegion() {
85
0
  if (auto *op = getDefiningOp())
86
0
    return op->getParentRegion();
87
0
  return cast<BlockArgument>().getOwner()->getParent();
88
0
}
89
90
/// Return the Block in which this Value is defined.
91
0
Block *Value::getParentBlock() {
92
0
  if (Operation *op = getDefiningOp())
93
0
    return op->getBlock();
94
0
  return cast<BlockArgument>().getOwner();
95
0
}
96
97
//===----------------------------------------------------------------------===//
98
// Value::UseLists
99
//===----------------------------------------------------------------------===//
100
101
/// Provide the use list that is attached to this value.
102
0
IRObjectWithUseList<OpOperand> *Value::getUseList() const {
103
0
  if (BlockArgument arg = dyn_cast<BlockArgument>())
104
0
    return arg.getImpl();
105
0
  if (getKind() != Kind::TrailingOpResult) {
106
0
    OpResult result = cast<OpResult>();
107
0
    return result.getOwner()->getInlineResult(result.getResultNumber());
108
0
  }
109
0
110
0
  // Otherwise this is a trailing operation result, which contains a use list.
111
0
  return reinterpret_cast<TrailingOpResult *>(ownerAndKind.getPointer());
112
0
}
113
114
/// Drop all uses of this object from their respective owners.
115
0
void Value::dropAllUses() const { return getUseList()->dropAllUses(); }
116
117
/// Replace all uses of 'this' value with the new value, updating anything in
118
/// the IR that uses 'this' to use the other value instead.  When this returns
119
/// there are zero uses of 'this'.
120
0
void Value::replaceAllUsesWith(Value newValue) const {
121
0
  return getUseList()->replaceAllUsesWith(newValue);
122
0
}
123
124
/// Replace all uses of 'this' value with the new value, updating anything in
125
/// the IR that uses 'this' to use the other value instead except if the user is
126
/// listed in 'exceptions' .
127
void Value::replaceAllUsesExcept(
128
0
    Value newValue, const SmallPtrSetImpl<Operation *> &exceptions) const {
129
0
  for (auto &use : llvm::make_early_inc_range(getUses())) {
130
0
    if (exceptions.count(use.getOwner()) == 0)
131
0
      use.set(newValue);
132
0
  }
133
0
}
134
135
/// Replace all uses of 'this' value with 'newValue' if the given callback
136
/// returns true.
137
void Value::replaceUsesWithIf(Value newValue,
138
0
                              function_ref<bool(OpOperand &)> shouldReplace) {
139
0
  for (OpOperand &use : llvm::make_early_inc_range(getUses()))
140
0
    if (shouldReplace(use))
141
0
      use.set(newValue);
142
0
}
143
144
/// Returns true if the value is used outside of the given block.
145
0
bool Value::isUsedOutsideOfBlock(Block *block) {
146
0
  return llvm::any_of(getUsers(), [block](Operation *user) {
147
0
    return user->getBlock() != block;
148
0
  });
149
0
}
150
151
//===--------------------------------------------------------------------===//
152
// Uses
153
154
0
auto Value::use_begin() const -> use_iterator {
155
0
  return getUseList()->use_begin();
156
0
}
157
158
/// Returns true if this value has exactly one use.
159
0
bool Value::hasOneUse() const { return getUseList()->hasOneUse(); }
160
161
/// Returns true if this value has no uses.
162
0
bool Value::use_empty() const { return getUseList()->use_empty(); }
163
164
//===----------------------------------------------------------------------===//
165
// OpResult
166
//===----------------------------------------------------------------------===//
167
168
/// Returns the operation that owns this result.
169
0
Operation *OpResult::getOwner() const {
170
0
  // If the result is in-place, the `owner` is the operation.
171
0
  void *owner = ownerAndKind.getPointer();
172
0
  if (LLVM_LIKELY(getKind() != Kind::TrailingOpResult))
173
0
    return static_cast<Operation *>(owner);
174
0
175
0
  // Otherwise, query the trailing result for the owner.
176
0
  return static_cast<TrailingOpResult *>(owner)->getOwner();
177
0
}
178
179
/// Return the result number of this result.
180
0
unsigned OpResult::getResultNumber() const {
181
0
  // If the result is in-place, we can use the kind directly.
182
0
  if (LLVM_LIKELY(getKind() != Kind::TrailingOpResult))
183
0
    return static_cast<unsigned>(ownerAndKind.getInt());
184
0
  // Otherwise, query the trailing result.
185
0
  auto *result = static_cast<TrailingOpResult *>(ownerAndKind.getPointer());
186
0
  return result->getResultNumber();
187
0
}
188
189
/// Given a number of operation results, returns the number that need to be
190
/// stored inline.
191
0
unsigned OpResult::getNumInline(unsigned numResults) {
192
0
  return std::min(numResults, getMaxInlineResults());
193
0
}
194
195
/// Given a number of operation results, returns the number that need to be
196
/// stored as trailing.
197
0
unsigned OpResult::getNumTrailing(unsigned numResults) {
198
0
  // If we can pack all of the results, there is no need for additional storage.
199
0
  unsigned maxInline = getMaxInlineResults();
200
0
  return numResults <= maxInline ? 0 : numResults - maxInline;
201
0
}
202
203
//===----------------------------------------------------------------------===//
204
// BlockOperand
205
//===----------------------------------------------------------------------===//
206
207
/// Provide the use list that is attached to the given block.
208
0
IRObjectWithUseList<BlockOperand> *BlockOperand::getUseList(Block *value) {
209
0
  return value;
210
0
}
211
212
/// Return which operand this is in the operand list.
213
0
unsigned BlockOperand::getOperandNumber() {
214
0
  return this - &getOwner()->getBlockOperands()[0];
215
0
}
216
217
//===----------------------------------------------------------------------===//
218
// OpOperand
219
//===----------------------------------------------------------------------===//
220
221
/// Provide the use list that is attached to the given value.
222
0
IRObjectWithUseList<OpOperand> *OpOperand::getUseList(Value value) {
223
0
  return value.getUseList();
224
0
}
225
226
/// Return the current value being used by this operand.
227
0
Value OpOperand::get() const {
228
0
  return IROperand<OpOperand, OpaqueValue>::get();
229
0
}
230
231
/// Set the operand to the given value.
232
0
void OpOperand::set(Value value) {
233
0
  IROperand<OpOperand, OpaqueValue>::set(value);
234
0
}
235
236
/// Return which operand this is in the operand list.
237
0
unsigned OpOperand::getOperandNumber() {
238
0
  return this - &getOwner()->getOpOperands()[0];
239
0
}
240
241
//===----------------------------------------------------------------------===//
242
// OpaqueValue
243
//===----------------------------------------------------------------------===//
244
245
/// Implicit conversion from 'Value'.
246
0
OpaqueValue::OpaqueValue(Value value) : impl(value.getAsOpaquePointer()) {}
247
248
/// Implicit conversion back to 'Value'.
249
0
OpaqueValue::operator Value() const {
250
0
  return Value::getFromOpaquePointer(impl);
251
0
}