File: | build/llvm-toolchain-snapshot-15~++20220420111733+e13d2efed663/mlir/include/mlir/IR/Value.h |
Warning: | line 118, column 33 Called C++ object pointer is null |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
1 | //===- ControlFlowInterfaces.cpp - ControlFlow Interfaces -----------------===// | |||
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 <utility> | |||
10 | ||||
11 | #include "mlir/Interfaces/ControlFlowInterfaces.h" | |||
12 | #include "mlir/IR/BuiltinTypes.h" | |||
13 | #include "llvm/ADT/SmallPtrSet.h" | |||
14 | ||||
15 | using namespace mlir; | |||
16 | ||||
17 | //===----------------------------------------------------------------------===// | |||
18 | // ControlFlowInterfaces | |||
19 | //===----------------------------------------------------------------------===// | |||
20 | ||||
21 | #include "mlir/Interfaces/ControlFlowInterfaces.cpp.inc" | |||
22 | ||||
23 | SuccessorOperands::SuccessorOperands(MutableOperandRange forwardedOperands) | |||
24 | : producedOperandCount(0), forwardedOperands(std::move(forwardedOperands)) { | |||
25 | } | |||
26 | ||||
27 | SuccessorOperands::SuccessorOperands(unsigned int producedOperandCount, | |||
28 | MutableOperandRange forwardedOperands) | |||
29 | : producedOperandCount(producedOperandCount), | |||
30 | forwardedOperands(std::move(forwardedOperands)) {} | |||
31 | ||||
32 | //===----------------------------------------------------------------------===// | |||
33 | // BranchOpInterface | |||
34 | //===----------------------------------------------------------------------===// | |||
35 | ||||
36 | /// Returns the `BlockArgument` corresponding to operand `operandIndex` in some | |||
37 | /// successor if 'operandIndex' is within the range of 'operands', or None if | |||
38 | /// `operandIndex` isn't a successor operand index. | |||
39 | Optional<BlockArgument> | |||
40 | detail::getBranchSuccessorArgument(const SuccessorOperands &operands, | |||
41 | unsigned operandIndex, Block *successor) { | |||
42 | OperandRange forwardedOperands = operands.getForwardedOperands(); | |||
43 | // Check that the operands are valid. | |||
44 | if (forwardedOperands.empty()) | |||
45 | return llvm::None; | |||
46 | ||||
47 | // Check to ensure that this operand is within the range. | |||
48 | unsigned operandsStart = forwardedOperands.getBeginOperandIndex(); | |||
49 | if (operandIndex < operandsStart || | |||
50 | operandIndex >= (operandsStart + forwardedOperands.size())) | |||
51 | return llvm::None; | |||
52 | ||||
53 | // Index the successor. | |||
54 | unsigned argIndex = | |||
55 | operands.getProducedOperandCount() + operandIndex - operandsStart; | |||
56 | return successor->getArgument(argIndex); | |||
57 | } | |||
58 | ||||
59 | /// Verify that the given operands match those of the given successor block. | |||
60 | LogicalResult | |||
61 | detail::verifyBranchSuccessorOperands(Operation *op, unsigned succNo, | |||
62 | const SuccessorOperands &operands) { | |||
63 | // Check the count. | |||
64 | unsigned operandCount = operands.size(); | |||
65 | Block *destBB = op->getSuccessor(succNo); | |||
66 | if (operandCount != destBB->getNumArguments()) | |||
| ||||
67 | return op->emitError() << "branch has " << operandCount | |||
68 | << " operands for successor #" << succNo | |||
69 | << ", but target block has " | |||
70 | << destBB->getNumArguments(); | |||
71 | ||||
72 | // Check the types. | |||
73 | for (unsigned i = operands.getProducedOperandCount(); i != operandCount; | |||
74 | ++i) { | |||
75 | if (!cast<BranchOpInterface>(op).areTypesCompatible( | |||
76 | operands[i].getType(), destBB->getArgument(i).getType())) | |||
77 | return op->emitError() << "type mismatch for bb argument #" << i | |||
78 | << " of successor #" << succNo; | |||
79 | } | |||
80 | return success(); | |||
81 | } | |||
82 | ||||
83 | //===----------------------------------------------------------------------===// | |||
84 | // RegionBranchOpInterface | |||
85 | //===----------------------------------------------------------------------===// | |||
86 | ||||
87 | /// Verify that types match along all region control flow edges originating from | |||
88 | /// `sourceNo` (region # if source is a region, llvm::None if source is parent | |||
89 | /// op). `getInputsTypesForRegion` is a function that returns the types of the | |||
90 | /// inputs that flow from `sourceIndex' to the given region, or llvm::None if | |||
91 | /// the exact type match verification is not necessary (e.g., if the Op verifies | |||
92 | /// the match itself). | |||
93 | static LogicalResult | |||
94 | verifyTypesAlongAllEdges(Operation *op, Optional<unsigned> sourceNo, | |||
95 | function_ref<Optional<TypeRange>(Optional<unsigned>)> | |||
96 | getInputsTypesForRegion) { | |||
97 | auto regionInterface = cast<RegionBranchOpInterface>(op); | |||
98 | ||||
99 | SmallVector<RegionSuccessor, 2> successors; | |||
100 | unsigned numInputs; | |||
101 | if (sourceNo) { | |||
102 | Region &srcRegion = op->getRegion(sourceNo.getValue()); | |||
103 | numInputs = srcRegion.getNumArguments(); | |||
104 | } else { | |||
105 | numInputs = op->getNumOperands(); | |||
106 | } | |||
107 | SmallVector<Attribute, 2> operands(numInputs, nullptr); | |||
108 | regionInterface.getSuccessorRegions(sourceNo, operands, successors); | |||
109 | ||||
110 | for (RegionSuccessor &succ : successors) { | |||
111 | Optional<unsigned> succRegionNo; | |||
112 | if (!succ.isParent()) | |||
113 | succRegionNo = succ.getSuccessor()->getRegionNumber(); | |||
114 | ||||
115 | auto printEdgeName = [&](InFlightDiagnostic &diag) -> InFlightDiagnostic & { | |||
116 | diag << "from "; | |||
117 | if (sourceNo) | |||
118 | diag << "Region #" << sourceNo.getValue(); | |||
119 | else | |||
120 | diag << "parent operands"; | |||
121 | ||||
122 | diag << " to "; | |||
123 | if (succRegionNo) | |||
124 | diag << "Region #" << succRegionNo.getValue(); | |||
125 | else | |||
126 | diag << "parent results"; | |||
127 | return diag; | |||
128 | }; | |||
129 | ||||
130 | Optional<TypeRange> sourceTypes = getInputsTypesForRegion(succRegionNo); | |||
131 | if (!sourceTypes.hasValue()) | |||
132 | continue; | |||
133 | ||||
134 | TypeRange succInputsTypes = succ.getSuccessorInputs().getTypes(); | |||
135 | if (sourceTypes->size() != succInputsTypes.size()) { | |||
136 | InFlightDiagnostic diag = op->emitOpError(" region control flow edge "); | |||
137 | return printEdgeName(diag) << ": source has " << sourceTypes->size() | |||
138 | << " operands, but target successor needs " | |||
139 | << succInputsTypes.size(); | |||
140 | } | |||
141 | ||||
142 | for (const auto &typesIdx : | |||
143 | llvm::enumerate(llvm::zip(*sourceTypes, succInputsTypes))) { | |||
144 | Type sourceType = std::get<0>(typesIdx.value()); | |||
145 | Type inputType = std::get<1>(typesIdx.value()); | |||
146 | if (!regionInterface.areTypesCompatible(sourceType, inputType)) { | |||
147 | InFlightDiagnostic diag = op->emitOpError(" along control flow edge "); | |||
148 | return printEdgeName(diag) | |||
149 | << ": source type #" << typesIdx.index() << " " << sourceType | |||
150 | << " should match input type #" << typesIdx.index() << " " | |||
151 | << inputType; | |||
152 | } | |||
153 | } | |||
154 | } | |||
155 | return success(); | |||
156 | } | |||
157 | ||||
158 | /// Verify that types match along control flow edges described the given op. | |||
159 | LogicalResult detail::verifyTypesAlongControlFlowEdges(Operation *op) { | |||
160 | auto regionInterface = cast<RegionBranchOpInterface>(op); | |||
161 | ||||
162 | auto inputTypesFromParent = [&](Optional<unsigned> regionNo) -> TypeRange { | |||
163 | if (regionNo.hasValue()) { | |||
164 | return regionInterface.getSuccessorEntryOperands(regionNo.getValue()) | |||
165 | .getTypes(); | |||
166 | } | |||
167 | ||||
168 | // If the successor of a parent op is the parent itself | |||
169 | // RegionBranchOpInterface does not have an API to query what the entry | |||
170 | // operands will be in that case. Vend out the result types of the op in | |||
171 | // that case so that type checking succeeds for this case. | |||
172 | return op->getResultTypes(); | |||
173 | }; | |||
174 | ||||
175 | // Verify types along control flow edges originating from the parent. | |||
176 | if (failed(verifyTypesAlongAllEdges(op, llvm::None, inputTypesFromParent))) | |||
177 | return failure(); | |||
178 | ||||
179 | // RegionBranchOpInterface should not be implemented by Ops that do not have | |||
180 | // attached regions. | |||
181 | assert(op->getNumRegions() != 0)(static_cast <bool> (op->getNumRegions() != 0) ? void (0) : __assert_fail ("op->getNumRegions() != 0", "mlir/lib/Interfaces/ControlFlowInterfaces.cpp" , 181, __extension__ __PRETTY_FUNCTION__)); | |||
182 | ||||
183 | auto areTypesCompatible = [&](TypeRange lhs, TypeRange rhs) { | |||
184 | if (lhs.size() != rhs.size()) | |||
185 | return false; | |||
186 | for (auto types : llvm::zip(lhs, rhs)) { | |||
187 | if (!regionInterface.areTypesCompatible(std::get<0>(types), | |||
188 | std::get<1>(types))) { | |||
189 | return false; | |||
190 | } | |||
191 | } | |||
192 | return true; | |||
193 | }; | |||
194 | ||||
195 | // Verify types along control flow edges originating from each region. | |||
196 | for (unsigned regionNo : llvm::seq(0U, op->getNumRegions())) { | |||
197 | Region ®ion = op->getRegion(regionNo); | |||
198 | ||||
199 | // Since there can be multiple `ReturnLike` terminators or others | |||
200 | // implementing the `RegionBranchTerminatorOpInterface`, all should have the | |||
201 | // same operand types when passing them to the same region. | |||
202 | ||||
203 | Optional<OperandRange> regionReturnOperands; | |||
204 | for (Block &block : region) { | |||
205 | Operation *terminator = block.getTerminator(); | |||
206 | auto terminatorOperands = | |||
207 | getRegionBranchSuccessorOperands(terminator, regionNo); | |||
208 | if (!terminatorOperands) | |||
209 | continue; | |||
210 | ||||
211 | if (!regionReturnOperands) { | |||
212 | regionReturnOperands = terminatorOperands; | |||
213 | continue; | |||
214 | } | |||
215 | ||||
216 | // Found more than one ReturnLike terminator. Make sure the operand types | |||
217 | // match with the first one. | |||
218 | if (!areTypesCompatible(regionReturnOperands->getTypes(), | |||
219 | terminatorOperands->getTypes())) | |||
220 | return op->emitOpError("Region #") | |||
221 | << regionNo | |||
222 | << " operands mismatch between return-like terminators"; | |||
223 | } | |||
224 | ||||
225 | auto inputTypesFromRegion = | |||
226 | [&](Optional<unsigned> regionNo) -> Optional<TypeRange> { | |||
227 | // If there is no return-like terminator, the op itself should verify | |||
228 | // type consistency. | |||
229 | if (!regionReturnOperands) | |||
230 | return llvm::None; | |||
231 | ||||
232 | // All successors get the same set of operand types. | |||
233 | return TypeRange(regionReturnOperands->getTypes()); | |||
234 | }; | |||
235 | ||||
236 | if (failed(verifyTypesAlongAllEdges(op, regionNo, inputTypesFromRegion))) | |||
237 | return failure(); | |||
238 | } | |||
239 | ||||
240 | return success(); | |||
241 | } | |||
242 | ||||
243 | /// Return `true` if region `r` is reachable from region `begin` according to | |||
244 | /// the RegionBranchOpInterface (by taking a branch). | |||
245 | static bool isRegionReachable(Region *begin, Region *r) { | |||
246 | assert(begin->getParentOp() == r->getParentOp() &&(static_cast <bool> (begin->getParentOp() == r->getParentOp () && "expected that both regions belong to the same op" ) ? void (0) : __assert_fail ("begin->getParentOp() == r->getParentOp() && \"expected that both regions belong to the same op\"" , "mlir/lib/Interfaces/ControlFlowInterfaces.cpp", 247, __extension__ __PRETTY_FUNCTION__)) | |||
247 | "expected that both regions belong to the same op")(static_cast <bool> (begin->getParentOp() == r->getParentOp () && "expected that both regions belong to the same op" ) ? void (0) : __assert_fail ("begin->getParentOp() == r->getParentOp() && \"expected that both regions belong to the same op\"" , "mlir/lib/Interfaces/ControlFlowInterfaces.cpp", 247, __extension__ __PRETTY_FUNCTION__)); | |||
248 | auto op = cast<RegionBranchOpInterface>(begin->getParentOp()); | |||
249 | SmallVector<bool> visited(op->getNumRegions(), false); | |||
250 | visited[begin->getRegionNumber()] = true; | |||
251 | ||||
252 | // Retrieve all successors of the region and enqueue them in the worklist. | |||
253 | SmallVector<unsigned> worklist; | |||
254 | auto enqueueAllSuccessors = [&](unsigned index) { | |||
255 | SmallVector<RegionSuccessor> successors; | |||
256 | op.getSuccessorRegions(index, successors); | |||
257 | for (RegionSuccessor successor : successors) | |||
258 | if (!successor.isParent()) | |||
259 | worklist.push_back(successor.getSuccessor()->getRegionNumber()); | |||
260 | }; | |||
261 | enqueueAllSuccessors(begin->getRegionNumber()); | |||
262 | ||||
263 | // Process all regions in the worklist via DFS. | |||
264 | while (!worklist.empty()) { | |||
265 | unsigned nextRegion = worklist.pop_back_val(); | |||
266 | if (nextRegion == r->getRegionNumber()) | |||
267 | return true; | |||
268 | if (visited[nextRegion]) | |||
269 | continue; | |||
270 | visited[nextRegion] = true; | |||
271 | enqueueAllSuccessors(nextRegion); | |||
272 | } | |||
273 | ||||
274 | return false; | |||
275 | } | |||
276 | ||||
277 | /// Return `true` if `a` and `b` are in mutually exclusive regions. | |||
278 | /// | |||
279 | /// 1. Find the first common of `a` and `b` (ancestor) that implements | |||
280 | /// RegionBranchOpInterface. | |||
281 | /// 2. Determine the regions `regionA` and `regionB` in which `a` and `b` are | |||
282 | /// contained. | |||
283 | /// 3. Check if `regionA` and `regionB` are mutually exclusive. They are | |||
284 | /// mutually exclusive if they are not reachable from each other as per | |||
285 | /// RegionBranchOpInterface::getSuccessorRegions. | |||
286 | bool mlir::insideMutuallyExclusiveRegions(Operation *a, Operation *b) { | |||
287 | assert(a && "expected non-empty operation")(static_cast <bool> (a && "expected non-empty operation" ) ? void (0) : __assert_fail ("a && \"expected non-empty operation\"" , "mlir/lib/Interfaces/ControlFlowInterfaces.cpp", 287, __extension__ __PRETTY_FUNCTION__)); | |||
288 | assert(b && "expected non-empty operation")(static_cast <bool> (b && "expected non-empty operation" ) ? void (0) : __assert_fail ("b && \"expected non-empty operation\"" , "mlir/lib/Interfaces/ControlFlowInterfaces.cpp", 288, __extension__ __PRETTY_FUNCTION__)); | |||
289 | ||||
290 | auto branchOp = a->getParentOfType<RegionBranchOpInterface>(); | |||
291 | while (branchOp) { | |||
292 | // Check if b is inside branchOp. (We already know that a is.) | |||
293 | if (!branchOp->isProperAncestor(b)) { | |||
294 | // Check next enclosing RegionBranchOpInterface. | |||
295 | branchOp = branchOp->getParentOfType<RegionBranchOpInterface>(); | |||
296 | continue; | |||
297 | } | |||
298 | ||||
299 | // b is contained in branchOp. Retrieve the regions in which `a` and `b` | |||
300 | // are contained. | |||
301 | Region *regionA = nullptr, *regionB = nullptr; | |||
302 | for (Region &r : branchOp->getRegions()) { | |||
303 | if (r.findAncestorOpInRegion(*a)) { | |||
304 | assert(!regionA && "already found a region for a")(static_cast <bool> (!regionA && "already found a region for a" ) ? void (0) : __assert_fail ("!regionA && \"already found a region for a\"" , "mlir/lib/Interfaces/ControlFlowInterfaces.cpp", 304, __extension__ __PRETTY_FUNCTION__)); | |||
305 | regionA = &r; | |||
306 | } | |||
307 | if (r.findAncestorOpInRegion(*b)) { | |||
308 | assert(!regionB && "already found a region for b")(static_cast <bool> (!regionB && "already found a region for b" ) ? void (0) : __assert_fail ("!regionB && \"already found a region for b\"" , "mlir/lib/Interfaces/ControlFlowInterfaces.cpp", 308, __extension__ __PRETTY_FUNCTION__)); | |||
309 | regionB = &r; | |||
310 | } | |||
311 | } | |||
312 | assert(regionA && regionB && "could not find region of op")(static_cast <bool> (regionA && regionB && "could not find region of op") ? void (0) : __assert_fail ("regionA && regionB && \"could not find region of op\"" , "mlir/lib/Interfaces/ControlFlowInterfaces.cpp", 312, __extension__ __PRETTY_FUNCTION__)); | |||
313 | ||||
314 | // `a` and `b` are in mutually exclusive regions if both regions are | |||
315 | // distinct and neither region is reachable from the other region. | |||
316 | return regionA != regionB && !isRegionReachable(regionA, regionB) && | |||
317 | !isRegionReachable(regionB, regionA); | |||
318 | } | |||
319 | ||||
320 | // Could not find a common RegionBranchOpInterface among a's and b's | |||
321 | // ancestors. | |||
322 | return false; | |||
323 | } | |||
324 | ||||
325 | bool RegionBranchOpInterface::isRepetitiveRegion(unsigned index) { | |||
326 | Region *region = &getOperation()->getRegion(index); | |||
327 | return isRegionReachable(region, region); | |||
328 | } | |||
329 | ||||
330 | Region *mlir::getEnclosingRepetitiveRegion(Operation *op) { | |||
331 | while (Region *region = op->getParentRegion()) { | |||
332 | op = region->getParentOp(); | |||
333 | if (auto branchOp = dyn_cast<RegionBranchOpInterface>(op)) | |||
334 | if (branchOp.isRepetitiveRegion(region->getRegionNumber())) | |||
335 | return region; | |||
336 | } | |||
337 | return nullptr; | |||
338 | } | |||
339 | ||||
340 | Region *mlir::getEnclosingRepetitiveRegion(Value value) { | |||
341 | Region *region = value.getParentRegion(); | |||
342 | while (region) { | |||
343 | Operation *op = region->getParentOp(); | |||
344 | if (auto branchOp = dyn_cast<RegionBranchOpInterface>(op)) | |||
345 | if (branchOp.isRepetitiveRegion(region->getRegionNumber())) | |||
346 | return region; | |||
347 | region = op->getParentRegion(); | |||
348 | } | |||
349 | return nullptr; | |||
350 | } | |||
351 | ||||
352 | //===----------------------------------------------------------------------===// | |||
353 | // RegionBranchTerminatorOpInterface | |||
354 | //===----------------------------------------------------------------------===// | |||
355 | ||||
356 | /// Returns true if the given operation is either annotated with the | |||
357 | /// `ReturnLike` trait or implements the `RegionBranchTerminatorOpInterface`. | |||
358 | bool mlir::isRegionReturnLike(Operation *operation) { | |||
359 | return dyn_cast<RegionBranchTerminatorOpInterface>(operation) || | |||
360 | operation->hasTrait<OpTrait::ReturnLike>(); | |||
361 | } | |||
362 | ||||
363 | /// Returns the mutable operands that are passed to the region with the given | |||
364 | /// `regionIndex`. If the operation does not implement the | |||
365 | /// `RegionBranchTerminatorOpInterface` and is not marked as `ReturnLike`, the | |||
366 | /// result will be `llvm::None`. In all other cases, the resulting | |||
367 | /// `OperandRange` represents all operands that are passed to the specified | |||
368 | /// successor region. If `regionIndex` is `llvm::None`, all operands that are | |||
369 | /// passed to the parent operation will be returned. | |||
370 | Optional<MutableOperandRange> | |||
371 | mlir::getMutableRegionBranchSuccessorOperands(Operation *operation, | |||
372 | Optional<unsigned> regionIndex) { | |||
373 | // Try to query a RegionBranchTerminatorOpInterface to determine | |||
374 | // all successor operands that will be passed to the successor | |||
375 | // input arguments. | |||
376 | if (auto regionTerminatorInterface = | |||
377 | dyn_cast<RegionBranchTerminatorOpInterface>(operation)) | |||
378 | return regionTerminatorInterface.getMutableSuccessorOperands(regionIndex); | |||
379 | ||||
380 | // TODO: The ReturnLike trait should imply a default implementation of the | |||
381 | // RegionBranchTerminatorOpInterface. This would make this code significantly | |||
382 | // easier. Furthermore, this may even make this function obsolete. | |||
383 | if (operation->hasTrait<OpTrait::ReturnLike>()) | |||
384 | return MutableOperandRange(operation); | |||
385 | return llvm::None; | |||
386 | } | |||
387 | ||||
388 | /// Returns the read only operands that are passed to the region with the given | |||
389 | /// `regionIndex`. See `getMutableRegionBranchSuccessorOperands` for more | |||
390 | /// information. | |||
391 | Optional<OperandRange> | |||
392 | mlir::getRegionBranchSuccessorOperands(Operation *operation, | |||
393 | Optional<unsigned> regionIndex) { | |||
394 | auto range = getMutableRegionBranchSuccessorOperands(operation, regionIndex); | |||
395 | return range ? Optional<OperandRange>(*range) : llvm::None; | |||
396 | } |
1 | //===- ControlFlowInterfaces.h - ControlFlow Interfaces ---------*- C++ -*-===// |
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 | // This file contains the definitions of the branch interfaces defined in |
10 | // `ControlFlowInterfaces.td`. |
11 | // |
12 | //===----------------------------------------------------------------------===// |
13 | |
14 | #ifndef MLIR_INTERFACES_CONTROLFLOWINTERFACES_H |
15 | #define MLIR_INTERFACES_CONTROLFLOWINTERFACES_H |
16 | |
17 | #include "mlir/IR/OpDefinition.h" |
18 | |
19 | namespace mlir { |
20 | class BranchOpInterface; |
21 | class RegionBranchOpInterface; |
22 | |
23 | /// This class models how operands are forwarded to block arguments in control |
24 | /// flow. It consists of a number, denoting how many of the successors block |
25 | /// arguments are produced by the operation, followed by a range of operands |
26 | /// that are forwarded. The produced operands are passed to the first few |
27 | /// block arguments of the successor, followed by the forwarded operands. |
28 | /// It is unsupported to pass them in a different order. |
29 | /// |
30 | /// An example operation with both of these concepts would be a branch-on-error |
31 | /// operation, that internally produces an error object on the error path: |
32 | /// |
33 | /// invoke %function(%0) |
34 | /// label ^success ^error(%1 : i32) |
35 | /// |
36 | /// ^error(%e: !error, %arg0 : i32): |
37 | /// ... |
38 | /// |
39 | /// This operation would return an instance of SuccessorOperands with a produced |
40 | /// operand count of 1 (mapped to %e in the successor) and a forwarded |
41 | /// operands range consisting of %1 in the example above (mapped to %arg0 in the |
42 | /// successor). |
43 | class SuccessorOperands { |
44 | public: |
45 | /// Constructs a SuccessorOperands with no produced operands that simply |
46 | /// forwards operands to the successor. |
47 | explicit SuccessorOperands(MutableOperandRange forwardedOperands); |
48 | |
49 | /// Constructs a SuccessorOperands with the given amount of produced operands |
50 | /// and forwarded operands. |
51 | SuccessorOperands(unsigned producedOperandCount, |
52 | MutableOperandRange forwardedOperands); |
53 | |
54 | /// Returns the amount of operands passed to the successor. This consists both |
55 | /// of produced operands by the operation as well as forwarded ones. |
56 | unsigned size() const { |
57 | return producedOperandCount + forwardedOperands.size(); |
58 | } |
59 | |
60 | /// Returns true if there are no successor operands. |
61 | bool empty() const { return size() == 0; } |
62 | |
63 | /// Returns the amount of operands that are produced internally by the |
64 | /// operation. These are passed to the first few block arguments. |
65 | unsigned getProducedOperandCount() const { return producedOperandCount; } |
66 | |
67 | /// Returns true if the successor operand denoted by `index` is produced by |
68 | /// the operation. |
69 | bool isOperandProduced(unsigned index) const { |
70 | return index < producedOperandCount; |
71 | } |
72 | |
73 | /// Returns the Value that is passed to the successors block argument denoted |
74 | /// by `index`. If it is produced by the operation, no such value exists and |
75 | /// a null Value is returned. |
76 | Value operator[](unsigned index) const { |
77 | if (isOperandProduced(index)) |
78 | return Value(); |
79 | return forwardedOperands[index - producedOperandCount]; |
80 | } |
81 | |
82 | /// Get the range of operands that are simply forwarded to the successor. |
83 | OperandRange getForwardedOperands() const { return forwardedOperands; } |
84 | |
85 | /// Get a slice of the operands forwarded to the successor. The given range |
86 | /// must not contain any operands produced by the operation. |
87 | MutableOperandRange slice(unsigned subStart, unsigned subLen) const { |
88 | assert(!isOperandProduced(subStart) &&(static_cast <bool> (!isOperandProduced(subStart) && "can't slice operands produced by the operation") ? void (0) : __assert_fail ("!isOperandProduced(subStart) && \"can't slice operands produced by the operation\"" , "mlir/include/mlir/Interfaces/ControlFlowInterfaces.h", 89, __extension__ __PRETTY_FUNCTION__)) |
89 | "can't slice operands produced by the operation")(static_cast <bool> (!isOperandProduced(subStart) && "can't slice operands produced by the operation") ? void (0) : __assert_fail ("!isOperandProduced(subStart) && \"can't slice operands produced by the operation\"" , "mlir/include/mlir/Interfaces/ControlFlowInterfaces.h", 89, __extension__ __PRETTY_FUNCTION__)); |
90 | return forwardedOperands.slice(subStart - producedOperandCount, subLen); |
91 | } |
92 | |
93 | /// Erase operands forwarded to the successor. The given range must |
94 | /// not contain any operands produced by the operation. |
95 | void erase(unsigned subStart, unsigned subLen = 1) { |
96 | assert(!isOperandProduced(subStart) &&(static_cast <bool> (!isOperandProduced(subStart) && "can't erase operands produced by the operation") ? void (0) : __assert_fail ("!isOperandProduced(subStart) && \"can't erase operands produced by the operation\"" , "mlir/include/mlir/Interfaces/ControlFlowInterfaces.h", 97, __extension__ __PRETTY_FUNCTION__)) |
97 | "can't erase operands produced by the operation")(static_cast <bool> (!isOperandProduced(subStart) && "can't erase operands produced by the operation") ? void (0) : __assert_fail ("!isOperandProduced(subStart) && \"can't erase operands produced by the operation\"" , "mlir/include/mlir/Interfaces/ControlFlowInterfaces.h", 97, __extension__ __PRETTY_FUNCTION__)); |
98 | forwardedOperands.erase(subStart - producedOperandCount, subLen); |
99 | } |
100 | |
101 | /// Add new operands that are forwarded to the successor. |
102 | void append(ValueRange valueRange) { forwardedOperands.append(valueRange); } |
103 | |
104 | /// Gets the index of the forwarded operand within the operation which maps |
105 | /// to the block argument denoted by `blockArgumentIndex`. The block argument |
106 | /// must be mapped to a forwarded operand. |
107 | unsigned getOperandIndex(unsigned blockArgumentIndex) const { |
108 | assert(!isOperandProduced(blockArgumentIndex) &&(static_cast <bool> (!isOperandProduced(blockArgumentIndex ) && "can't map operand produced by the operation") ? void (0) : __assert_fail ("!isOperandProduced(blockArgumentIndex) && \"can't map operand produced by the operation\"" , "mlir/include/mlir/Interfaces/ControlFlowInterfaces.h", 109 , __extension__ __PRETTY_FUNCTION__)) |
109 | "can't map operand produced by the operation")(static_cast <bool> (!isOperandProduced(blockArgumentIndex ) && "can't map operand produced by the operation") ? void (0) : __assert_fail ("!isOperandProduced(blockArgumentIndex) && \"can't map operand produced by the operation\"" , "mlir/include/mlir/Interfaces/ControlFlowInterfaces.h", 109 , __extension__ __PRETTY_FUNCTION__)); |
110 | OperandRange operands = forwardedOperands; |
111 | return operands.getBeginOperandIndex() + |
112 | (blockArgumentIndex - producedOperandCount); |
113 | } |
114 | |
115 | private: |
116 | /// Amount of operands that are produced internally within the operation and |
117 | /// passed to the first few block arguments. |
118 | unsigned producedOperandCount; |
119 | /// Range of operands that are forwarded to the remaining block arguments. |
120 | MutableOperandRange forwardedOperands; |
121 | }; |
122 | |
123 | //===----------------------------------------------------------------------===// |
124 | // BranchOpInterface |
125 | //===----------------------------------------------------------------------===// |
126 | |
127 | namespace detail { |
128 | /// Return the `BlockArgument` corresponding to operand `operandIndex` in some |
129 | /// successor if `operandIndex` is within the range of `operands`, or None if |
130 | /// `operandIndex` isn't a successor operand index. |
131 | Optional<BlockArgument> |
132 | getBranchSuccessorArgument(const SuccessorOperands &operands, |
133 | unsigned operandIndex, Block *successor); |
134 | |
135 | /// Verify that the given operands match those of the given successor block. |
136 | LogicalResult verifyBranchSuccessorOperands(Operation *op, unsigned succNo, |
137 | const SuccessorOperands &operands); |
138 | } // namespace detail |
139 | |
140 | //===----------------------------------------------------------------------===// |
141 | // RegionBranchOpInterface |
142 | //===----------------------------------------------------------------------===// |
143 | |
144 | namespace detail { |
145 | /// Verify that types match along control flow edges described the given op. |
146 | LogicalResult verifyTypesAlongControlFlowEdges(Operation *op); |
147 | } // namespace detail |
148 | |
149 | /// This class represents a successor of a region. A region successor can either |
150 | /// be another region, or the parent operation. If the successor is a region, |
151 | /// this class represents the destination region, as well as a set of arguments |
152 | /// from that region that will be populated when control flows into the region. |
153 | /// If the successor is the parent operation, this class represents an optional |
154 | /// set of results that will be populated when control returns to the parent |
155 | /// operation. |
156 | /// |
157 | /// This interface assumes that the values from the current region that are used |
158 | /// to populate the successor inputs are the operands of the return-like |
159 | /// terminator operations in the blocks within this region. |
160 | class RegionSuccessor { |
161 | public: |
162 | /// Initialize a successor that branches to another region of the parent |
163 | /// operation. |
164 | RegionSuccessor(Region *region, Block::BlockArgListType regionInputs = {}) |
165 | : region(region), inputs(regionInputs) {} |
166 | /// Initialize a successor that branches back to/out of the parent operation. |
167 | RegionSuccessor(Optional<Operation::result_range> results = {}) |
168 | : inputs(results ? ValueRange(*results) : ValueRange()) {} |
169 | |
170 | /// Return the given region successor. Returns nullptr if the successor is the |
171 | /// parent operation. |
172 | Region *getSuccessor() const { return region; } |
173 | |
174 | /// Return true if the successor is the parent operation. |
175 | bool isParent() const { return region == nullptr; } |
176 | |
177 | /// Return the inputs to the successor that are remapped by the exit values of |
178 | /// the current region. |
179 | ValueRange getSuccessorInputs() const { return inputs; } |
180 | |
181 | private: |
182 | Region *region{nullptr}; |
183 | ValueRange inputs; |
184 | }; |
185 | |
186 | /// This class represents upper and lower bounds on the number of times a region |
187 | /// of a `RegionBranchOpInterface` can be invoked. The lower bound is at least |
188 | /// zero, but the upper bound may not be known. |
189 | class InvocationBounds { |
190 | public: |
191 | /// Create invocation bounds. The lower bound must be at least 0 and only the |
192 | /// upper bound can be unknown. |
193 | InvocationBounds(unsigned lb, Optional<unsigned> ub) : lower(lb), upper(ub) { |
194 | assert((!ub || ub >= lb) && "upper bound cannot be less than lower bound")(static_cast <bool> ((!ub || ub >= lb) && "upper bound cannot be less than lower bound" ) ? void (0) : __assert_fail ("(!ub || ub >= lb) && \"upper bound cannot be less than lower bound\"" , "mlir/include/mlir/Interfaces/ControlFlowInterfaces.h", 194 , __extension__ __PRETTY_FUNCTION__)); |
195 | } |
196 | |
197 | /// Return the lower bound. |
198 | unsigned getLowerBound() const { return lower; } |
199 | |
200 | /// Return the upper bound. |
201 | Optional<unsigned> getUpperBound() const { return upper; } |
202 | |
203 | /// Returns the unknown invocation bounds, i.e., there is no information on |
204 | /// how many times a region may be invoked. |
205 | static InvocationBounds getUnknown() { return {0, llvm::None}; } |
206 | |
207 | private: |
208 | /// The minimum number of times the successor region will be invoked. |
209 | unsigned lower; |
210 | /// The maximum number of times the successor region will be invoked or `None` |
211 | /// if an upper bound is not known. |
212 | Optional<unsigned> upper; |
213 | }; |
214 | |
215 | /// Return `true` if `a` and `b` are in mutually exclusive regions as per |
216 | /// RegionBranchOpInterface. |
217 | bool insideMutuallyExclusiveRegions(Operation *a, Operation *b); |
218 | |
219 | /// Return the first enclosing region of the given op that may be executed |
220 | /// repetitively as per RegionBranchOpInterface or `nullptr` if no such region |
221 | /// exists. |
222 | Region *getEnclosingRepetitiveRegion(Operation *op); |
223 | |
224 | /// Return the first enclosing region of the given Value that may be executed |
225 | /// repetitively as per RegionBranchOpInterface or `nullptr` if no such region |
226 | /// exists. |
227 | Region *getEnclosingRepetitiveRegion(Value value); |
228 | |
229 | //===----------------------------------------------------------------------===// |
230 | // RegionBranchTerminatorOpInterface |
231 | //===----------------------------------------------------------------------===// |
232 | |
233 | /// Returns true if the given operation is either annotated with the |
234 | /// `ReturnLike` trait or implements the `RegionBranchTerminatorOpInterface`. |
235 | bool isRegionReturnLike(Operation *operation); |
236 | |
237 | /// Returns the mutable operands that are passed to the region with the given |
238 | /// `regionIndex`. If the operation does not implement the |
239 | /// `RegionBranchTerminatorOpInterface` and is not marked as `ReturnLike`, the |
240 | /// result will be `llvm::None`. In all other cases, the resulting |
241 | /// `OperandRange` represents all operands that are passed to the specified |
242 | /// successor region. If `regionIndex` is `llvm::None`, all operands that are |
243 | /// passed to the parent operation will be returned. |
244 | Optional<MutableOperandRange> |
245 | getMutableRegionBranchSuccessorOperands(Operation *operation, |
246 | Optional<unsigned> regionIndex); |
247 | |
248 | /// Returns the read only operands that are passed to the region with the given |
249 | /// `regionIndex`. See `getMutableRegionBranchSuccessorOperands` for more |
250 | /// information. |
251 | Optional<OperandRange> |
252 | getRegionBranchSuccessorOperands(Operation *operation, |
253 | Optional<unsigned> regionIndex); |
254 | |
255 | //===----------------------------------------------------------------------===// |
256 | // ControlFlow Traits |
257 | //===----------------------------------------------------------------------===// |
258 | |
259 | namespace OpTrait { |
260 | /// This trait indicates that a terminator operation is "return-like". This |
261 | /// means that it exits its current region and forwards its operands as "exit" |
262 | /// values to the parent region. Operations with this trait are not permitted to |
263 | /// contain successors or produce results. |
264 | template <typename ConcreteType> |
265 | struct ReturnLike : public TraitBase<ConcreteType, ReturnLike> { |
266 | static LogicalResult verifyTrait(Operation *op) { |
267 | static_assert(ConcreteType::template hasTrait<IsTerminator>(), |
268 | "expected operation to be a terminator"); |
269 | static_assert(ConcreteType::template hasTrait<ZeroResult>(), |
270 | "expected operation to have zero results"); |
271 | static_assert(ConcreteType::template hasTrait<ZeroSuccessor>(), |
272 | "expected operation to have zero successors"); |
273 | return success(); |
274 | } |
275 | }; |
276 | } // namespace OpTrait |
277 | |
278 | } // namespace mlir |
279 | |
280 | //===----------------------------------------------------------------------===// |
281 | // ControlFlow Interfaces |
282 | //===----------------------------------------------------------------------===// |
283 | |
284 | /// Include the generated interface declarations. |
285 | #include "mlir/Interfaces/ControlFlowInterfaces.h.inc" |
286 | |
287 | #endif // MLIR_INTERFACES_CONTROLFLOWINTERFACES_H |
1 | //===- Value.h - Base of the SSA Value hierarchy ----------------*- C++ -*-===// | |||
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 | // This file defines generic Value type and manipulation utilities. | |||
10 | // | |||
11 | //===----------------------------------------------------------------------===// | |||
12 | ||||
13 | #ifndef MLIR_IR_VALUE_H | |||
14 | #define MLIR_IR_VALUE_H | |||
15 | ||||
16 | #include "mlir/IR/Types.h" | |||
17 | #include "mlir/IR/UseDefLists.h" | |||
18 | #include "mlir/Support/LLVM.h" | |||
19 | #include "llvm/Support/PointerLikeTypeTraits.h" | |||
20 | ||||
21 | namespace mlir { | |||
22 | class AsmState; | |||
23 | class Block; | |||
24 | class BlockArgument; | |||
25 | class Operation; | |||
26 | class OpOperand; | |||
27 | class OpPrintingFlags; | |||
28 | class OpResult; | |||
29 | class Region; | |||
30 | class Value; | |||
31 | ||||
32 | //===----------------------------------------------------------------------===// | |||
33 | // Value | |||
34 | //===----------------------------------------------------------------------===// | |||
35 | ||||
36 | namespace detail { | |||
37 | ||||
38 | /// The base class for all derived Value classes. It contains all of the | |||
39 | /// components that are shared across Value classes. | |||
40 | class alignas(8) ValueImpl : public IRObjectWithUseList<OpOperand> { | |||
41 | public: | |||
42 | /// The enumeration represents the various different kinds of values the | |||
43 | /// internal representation may take. We use all of the bits from Type that we | |||
44 | /// can to store indices inline. | |||
45 | enum class Kind { | |||
46 | /// The first N kinds are all inline operation results. An inline operation | |||
47 | /// result means that the kind represents the result number. This removes | |||
48 | /// the need to store an additional index value. The derived class here is | |||
49 | /// an `OpResultImpl`. | |||
50 | InlineOpResult = 0, | |||
51 | ||||
52 | /// The next kind represents a 'out-of-line' operation result. This is for | |||
53 | /// results with numbers larger than we can represent inline. The derived | |||
54 | /// class here is an `OpResultImpl`. | |||
55 | OutOfLineOpResult = 6, | |||
56 | ||||
57 | /// The last kind represents a block argument. The derived class here is an | |||
58 | /// `BlockArgumentImpl`. | |||
59 | BlockArgument = 7 | |||
60 | }; | |||
61 | ||||
62 | /// Return the type of this value. | |||
63 | Type getType() const { return typeAndKind.getPointer(); } | |||
64 | ||||
65 | /// Set the type of this value. | |||
66 | void setType(Type type) { return typeAndKind.setPointer(type); } | |||
67 | ||||
68 | /// Return the kind of this value. | |||
69 | Kind getKind() const { return typeAndKind.getInt(); } | |||
70 | ||||
71 | protected: | |||
72 | ValueImpl(Type type, Kind kind) : typeAndKind(type, kind) {} | |||
73 | ||||
74 | /// The type of this result and the kind. | |||
75 | llvm::PointerIntPair<Type, 3, Kind> typeAndKind; | |||
76 | }; | |||
77 | } // namespace detail | |||
78 | ||||
79 | /// This class represents an instance of an SSA value in the MLIR system, | |||
80 | /// representing a computable value that has a type and a set of users. An SSA | |||
81 | /// value is either a BlockArgument or the result of an operation. Note: This | |||
82 | /// class has value-type semantics and is just a simple wrapper around a | |||
83 | /// ValueImpl that is either owner by a block(in the case of a BlockArgument) or | |||
84 | /// an Operation(in the case of an OpResult). | |||
85 | class Value { | |||
86 | public: | |||
87 | constexpr Value(detail::ValueImpl *impl = nullptr) : impl(impl) {} | |||
88 | ||||
89 | template <typename U> | |||
90 | bool isa() const { | |||
91 | assert(*this && "isa<> used on a null type.")(static_cast <bool> (*this && "isa<> used on a null type." ) ? void (0) : __assert_fail ("*this && \"isa<> used on a null type.\"" , "mlir/include/mlir/IR/Value.h", 91, __extension__ __PRETTY_FUNCTION__ )); | |||
92 | return U::classof(*this); | |||
93 | } | |||
94 | ||||
95 | template <typename First, typename Second, typename... Rest> | |||
96 | bool isa() const { | |||
97 | return isa<First>() || isa<Second, Rest...>(); | |||
98 | } | |||
99 | template <typename U> | |||
100 | U dyn_cast() const { | |||
101 | return isa<U>() ? U(impl) : U(nullptr); | |||
102 | } | |||
103 | template <typename U> | |||
104 | U dyn_cast_or_null() const { | |||
105 | return (*this && isa<U>()) ? U(impl) : U(nullptr); | |||
106 | } | |||
107 | template <typename U> | |||
108 | U cast() const { | |||
109 | assert(isa<U>())(static_cast <bool> (isa<U>()) ? void (0) : __assert_fail ("isa<U>()", "mlir/include/mlir/IR/Value.h", 109, __extension__ __PRETTY_FUNCTION__)); | |||
110 | return U(impl); | |||
111 | } | |||
112 | ||||
113 | explicit operator bool() const { return impl; } | |||
114 | bool operator==(const Value &other) const { return impl == other.impl; } | |||
115 | bool operator!=(const Value &other) const { return !(*this == other); } | |||
116 | ||||
117 | /// Return the type of this value. | |||
118 | Type getType() const { return impl->getType(); } | |||
| ||||
119 | ||||
120 | /// Utility to get the associated MLIRContext that this value is defined in. | |||
121 | MLIRContext *getContext() const { return getType().getContext(); } | |||
122 | ||||
123 | /// Mutate the type of this Value to be of the specified type. | |||
124 | /// | |||
125 | /// Note that this is an extremely dangerous operation which can create | |||
126 | /// completely invalid IR very easily. It is strongly recommended that you | |||
127 | /// recreate IR objects with the right types instead of mutating them in | |||
128 | /// place. | |||
129 | void setType(Type newType) { impl->setType(newType); } | |||
130 | ||||
131 | /// If this value is the result of an operation, return the operation that | |||
132 | /// defines it. | |||
133 | Operation *getDefiningOp() const; | |||
134 | ||||
135 | /// If this value is the result of an operation of type OpTy, return the | |||
136 | /// operation that defines it. | |||
137 | template <typename OpTy> | |||
138 | OpTy getDefiningOp() const { | |||
139 | return llvm::dyn_cast_or_null<OpTy>(getDefiningOp()); | |||
140 | } | |||
141 | ||||
142 | /// Return the location of this value. | |||
143 | Location getLoc() const; | |||
144 | void setLoc(Location loc); | |||
145 | ||||
146 | /// Return the Region in which this Value is defined. | |||
147 | Region *getParentRegion(); | |||
148 | ||||
149 | /// Return the Block in which this Value is defined. | |||
150 | Block *getParentBlock(); | |||
151 | ||||
152 | //===--------------------------------------------------------------------===// | |||
153 | // UseLists | |||
154 | //===--------------------------------------------------------------------===// | |||
155 | ||||
156 | /// Drop all uses of this object from their respective owners. | |||
157 | void dropAllUses() const { return impl->dropAllUses(); } | |||
158 | ||||
159 | /// Replace all uses of 'this' value with the new value, updating anything in | |||
160 | /// the IR that uses 'this' to use the other value instead. When this returns | |||
161 | /// there are zero uses of 'this'. | |||
162 | void replaceAllUsesWith(Value newValue) const { | |||
163 | impl->replaceAllUsesWith(newValue); | |||
164 | } | |||
165 | ||||
166 | /// Replace all uses of 'this' value with 'newValue', updating anything in the | |||
167 | /// IR that uses 'this' to use the other value instead except if the user is | |||
168 | /// listed in 'exceptions' . | |||
169 | void | |||
170 | replaceAllUsesExcept(Value newValue, | |||
171 | const SmallPtrSetImpl<Operation *> &exceptions) const; | |||
172 | ||||
173 | /// Replace all uses of 'this' value with 'newValue', updating anything in the | |||
174 | /// IR that uses 'this' to use the other value instead except if the user is | |||
175 | /// 'exceptedUser'. | |||
176 | void replaceAllUsesExcept(Value newValue, Operation *exceptedUser) const; | |||
177 | ||||
178 | /// Replace all uses of 'this' value with 'newValue' if the given callback | |||
179 | /// returns true. | |||
180 | void replaceUsesWithIf(Value newValue, | |||
181 | function_ref<bool(OpOperand &)> shouldReplace); | |||
182 | ||||
183 | /// Returns true if the value is used outside of the given block. | |||
184 | bool isUsedOutsideOfBlock(Block *block); | |||
185 | ||||
186 | //===--------------------------------------------------------------------===// | |||
187 | // Uses | |||
188 | ||||
189 | /// This class implements an iterator over the uses of a value. | |||
190 | using use_iterator = ValueUseIterator<OpOperand>; | |||
191 | using use_range = iterator_range<use_iterator>; | |||
192 | ||||
193 | use_iterator use_begin() const { return impl->use_begin(); } | |||
194 | use_iterator use_end() const { return use_iterator(); } | |||
195 | ||||
196 | /// Returns a range of all uses, which is useful for iterating over all uses. | |||
197 | use_range getUses() const { return {use_begin(), use_end()}; } | |||
198 | ||||
199 | /// Returns true if this value has exactly one use. | |||
200 | bool hasOneUse() const { return impl->hasOneUse(); } | |||
201 | ||||
202 | /// Returns true if this value has no uses. | |||
203 | bool use_empty() const { return impl->use_empty(); } | |||
204 | ||||
205 | //===--------------------------------------------------------------------===// | |||
206 | // Users | |||
207 | ||||
208 | using user_iterator = ValueUserIterator<use_iterator, OpOperand>; | |||
209 | using user_range = iterator_range<user_iterator>; | |||
210 | ||||
211 | user_iterator user_begin() const { return use_begin(); } | |||
212 | user_iterator user_end() const { return use_end(); } | |||
213 | user_range getUsers() const { return {user_begin(), user_end()}; } | |||
214 | ||||
215 | //===--------------------------------------------------------------------===// | |||
216 | // Utilities | |||
217 | ||||
218 | void print(raw_ostream &os); | |||
219 | void print(raw_ostream &os, const OpPrintingFlags &flags); | |||
220 | void print(raw_ostream &os, AsmState &state); | |||
221 | void dump(); | |||
222 | ||||
223 | /// Print this value as if it were an operand. | |||
224 | void printAsOperand(raw_ostream &os, AsmState &state); | |||
225 | ||||
226 | /// Methods for supporting PointerLikeTypeTraits. | |||
227 | void *getAsOpaquePointer() const { return impl; } | |||
228 | static Value getFromOpaquePointer(const void *pointer) { | |||
229 | return reinterpret_cast<detail::ValueImpl *>(const_cast<void *>(pointer)); | |||
230 | } | |||
231 | detail::ValueImpl *getImpl() const { return impl; } | |||
232 | ||||
233 | friend ::llvm::hash_code hash_value(Value arg); | |||
234 | ||||
235 | protected: | |||
236 | /// A pointer to the internal implementation of the value. | |||
237 | detail::ValueImpl *impl; | |||
238 | }; | |||
239 | ||||
240 | inline raw_ostream &operator<<(raw_ostream &os, Value value) { | |||
241 | value.print(os); | |||
242 | return os; | |||
243 | } | |||
244 | ||||
245 | //===----------------------------------------------------------------------===// | |||
246 | // OpOperand | |||
247 | //===----------------------------------------------------------------------===// | |||
248 | ||||
249 | /// This class represents an operand of an operation. Instances of this class | |||
250 | /// contain a reference to a specific `Value`. | |||
251 | class OpOperand : public IROperand<OpOperand, Value> { | |||
252 | public: | |||
253 | /// Provide the use list that is attached to the given value. | |||
254 | static IRObjectWithUseList<OpOperand> *getUseList(Value value) { | |||
255 | return value.getImpl(); | |||
256 | } | |||
257 | ||||
258 | /// Return which operand this is in the OpOperand list of the Operation. | |||
259 | unsigned getOperandNumber(); | |||
260 | ||||
261 | private: | |||
262 | /// Keep the constructor private and accessible to the OperandStorage class | |||
263 | /// only to avoid hard-to-debug typo/programming mistakes. | |||
264 | friend class OperandStorage; | |||
265 | using IROperand<OpOperand, Value>::IROperand; | |||
266 | }; | |||
267 | ||||
268 | //===----------------------------------------------------------------------===// | |||
269 | // BlockArgument | |||
270 | //===----------------------------------------------------------------------===// | |||
271 | ||||
272 | namespace detail { | |||
273 | /// The internal implementation of a BlockArgument. | |||
274 | class BlockArgumentImpl : public ValueImpl { | |||
275 | public: | |||
276 | static bool classof(const ValueImpl *value) { | |||
277 | return value->getKind() == ValueImpl::Kind::BlockArgument; | |||
278 | } | |||
279 | ||||
280 | private: | |||
281 | BlockArgumentImpl(Type type, Block *owner, int64_t index, Location loc) | |||
282 | : ValueImpl(type, Kind::BlockArgument), owner(owner), index(index), | |||
283 | loc(loc) {} | |||
284 | ||||
285 | /// The owner of this argument. | |||
286 | Block *owner; | |||
287 | ||||
288 | /// The position in the argument list. | |||
289 | int64_t index; | |||
290 | ||||
291 | /// The source location of this argument. | |||
292 | Location loc; | |||
293 | ||||
294 | /// Allow access to owner and constructor. | |||
295 | friend BlockArgument; | |||
296 | }; | |||
297 | } // namespace detail | |||
298 | ||||
299 | /// This class represents an argument of a Block. | |||
300 | class BlockArgument : public Value { | |||
301 | public: | |||
302 | using Value::Value; | |||
303 | ||||
304 | static bool classof(Value value) { | |||
305 | return llvm::isa<detail::BlockArgumentImpl>(value.getImpl()); | |||
306 | } | |||
307 | ||||
308 | /// Returns the block that owns this argument. | |||
309 | Block *getOwner() const { return getImpl()->owner; } | |||
310 | ||||
311 | /// Returns the number of this argument. | |||
312 | unsigned getArgNumber() const { return getImpl()->index; } | |||
313 | ||||
314 | /// Return the location for this argument. | |||
315 | Location getLoc() const { return getImpl()->loc; } | |||
316 | void setLoc(Location loc) { getImpl()->loc = loc; } | |||
317 | ||||
318 | private: | |||
319 | /// Allocate a new argument with the given type and owner. | |||
320 | static BlockArgument create(Type type, Block *owner, int64_t index, | |||
321 | Location loc) { | |||
322 | return new detail::BlockArgumentImpl(type, owner, index, loc); | |||
323 | } | |||
324 | ||||
325 | /// Destroy and deallocate this argument. | |||
326 | void destroy() { delete getImpl(); } | |||
327 | ||||
328 | /// Get a raw pointer to the internal implementation. | |||
329 | detail::BlockArgumentImpl *getImpl() const { | |||
330 | return reinterpret_cast<detail::BlockArgumentImpl *>(impl); | |||
331 | } | |||
332 | ||||
333 | /// Cache the position in the block argument list. | |||
334 | void setArgNumber(int64_t index) { getImpl()->index = index; } | |||
335 | ||||
336 | /// Allow access to `create`, `destroy` and `setArgNumber`. | |||
337 | friend Block; | |||
338 | ||||
339 | /// Allow access to 'getImpl'. | |||
340 | friend Value; | |||
341 | }; | |||
342 | ||||
343 | //===----------------------------------------------------------------------===// | |||
344 | // OpResult | |||
345 | //===----------------------------------------------------------------------===// | |||
346 | ||||
347 | namespace detail { | |||
348 | /// This class provides the implementation for an operation result. | |||
349 | class alignas(8) OpResultImpl : public ValueImpl { | |||
350 | public: | |||
351 | using ValueImpl::ValueImpl; | |||
352 | ||||
353 | static bool classof(const ValueImpl *value) { | |||
354 | return value->getKind() != ValueImpl::Kind::BlockArgument; | |||
355 | } | |||
356 | ||||
357 | /// Returns the parent operation of this result. | |||
358 | Operation *getOwner() const; | |||
359 | ||||
360 | /// Returns the result number of this op result. | |||
361 | unsigned getResultNumber() const; | |||
362 | ||||
363 | /// Returns the next operation result at `offset` after this result. This | |||
364 | /// method is useful when indexing the result storage of an operation, given | |||
365 | /// that there is more than one kind of operation result (with the different | |||
366 | /// kinds having different sizes) and that operations are stored in reverse | |||
367 | /// order. | |||
368 | OpResultImpl *getNextResultAtOffset(intptr_t offset); | |||
369 | ||||
370 | /// Returns the maximum number of results that can be stored inline. | |||
371 | static unsigned getMaxInlineResults() { | |||
372 | return static_cast<unsigned>(Kind::OutOfLineOpResult); | |||
373 | } | |||
374 | }; | |||
375 | ||||
376 | /// This class provides the implementation for an operation result whose index | |||
377 | /// can be represented "inline" in the underlying ValueImpl. | |||
378 | struct InlineOpResult : public OpResultImpl { | |||
379 | public: | |||
380 | InlineOpResult(Type type, unsigned resultNo) | |||
381 | : OpResultImpl(type, static_cast<ValueImpl::Kind>(resultNo)) { | |||
382 | assert(resultNo < getMaxInlineResults())(static_cast <bool> (resultNo < getMaxInlineResults( )) ? void (0) : __assert_fail ("resultNo < getMaxInlineResults()" , "mlir/include/mlir/IR/Value.h", 382, __extension__ __PRETTY_FUNCTION__ )); | |||
383 | } | |||
384 | ||||
385 | /// Return the result number of this op result. | |||
386 | unsigned getResultNumber() const { return static_cast<unsigned>(getKind()); } | |||
387 | ||||
388 | static bool classof(const OpResultImpl *value) { | |||
389 | return value->getKind() != ValueImpl::Kind::OutOfLineOpResult; | |||
390 | } | |||
391 | }; | |||
392 | ||||
393 | /// This class provides the implementation for an operation result whose index | |||
394 | /// cannot be represented "inline", and thus requires an additional index field. | |||
395 | class OutOfLineOpResult : public OpResultImpl { | |||
396 | public: | |||
397 | OutOfLineOpResult(Type type, uint64_t outOfLineIndex) | |||
398 | : OpResultImpl(type, Kind::OutOfLineOpResult), | |||
399 | outOfLineIndex(outOfLineIndex) {} | |||
400 | ||||
401 | static bool classof(const OpResultImpl *value) { | |||
402 | return value->getKind() == ValueImpl::Kind::OutOfLineOpResult; | |||
403 | } | |||
404 | ||||
405 | /// Return the result number of this op result. | |||
406 | unsigned getResultNumber() const { | |||
407 | return outOfLineIndex + getMaxInlineResults(); | |||
408 | } | |||
409 | ||||
410 | /// The trailing result number, or the offset from the beginning of the | |||
411 | /// `OutOfLineOpResult` array. | |||
412 | uint64_t outOfLineIndex; | |||
413 | }; | |||
414 | ||||
415 | /// Return the result number of this op result. | |||
416 | inline unsigned OpResultImpl::getResultNumber() const { | |||
417 | if (const auto *outOfLineResult = dyn_cast<OutOfLineOpResult>(this)) | |||
418 | return outOfLineResult->getResultNumber(); | |||
419 | return cast<InlineOpResult>(this)->getResultNumber(); | |||
420 | } | |||
421 | ||||
422 | } // namespace detail | |||
423 | ||||
424 | /// This is a value defined by a result of an operation. | |||
425 | class OpResult : public Value { | |||
426 | public: | |||
427 | using Value::Value; | |||
428 | ||||
429 | static bool classof(Value value) { | |||
430 | return llvm::isa<detail::OpResultImpl>(value.getImpl()); | |||
431 | } | |||
432 | ||||
433 | /// Returns the operation that owns this result. | |||
434 | Operation *getOwner() const { return getImpl()->getOwner(); } | |||
435 | ||||
436 | /// Returns the number of this result. | |||
437 | unsigned getResultNumber() const { return getImpl()->getResultNumber(); } | |||
438 | ||||
439 | private: | |||
440 | /// Get a raw pointer to the internal implementation. | |||
441 | detail::OpResultImpl *getImpl() const { | |||
442 | return reinterpret_cast<detail::OpResultImpl *>(impl); | |||
443 | } | |||
444 | ||||
445 | /// Given a number of operation results, returns the number that need to be | |||
446 | /// stored inline. | |||
447 | static unsigned getNumInline(unsigned numResults); | |||
448 | ||||
449 | /// Given a number of operation results, returns the number that need to be | |||
450 | /// stored as trailing. | |||
451 | static unsigned getNumTrailing(unsigned numResults); | |||
452 | ||||
453 | /// Allow access to constructor. | |||
454 | friend Operation; | |||
455 | }; | |||
456 | ||||
457 | /// Make Value hashable. | |||
458 | inline ::llvm::hash_code hash_value(Value arg) { | |||
459 | return ::llvm::hash_value(arg.getImpl()); | |||
460 | } | |||
461 | ||||
462 | } // namespace mlir | |||
463 | ||||
464 | namespace llvm { | |||
465 | ||||
466 | template <> | |||
467 | struct DenseMapInfo<mlir::Value> { | |||
468 | static mlir::Value getEmptyKey() { | |||
469 | void *pointer = llvm::DenseMapInfo<void *>::getEmptyKey(); | |||
470 | return mlir::Value::getFromOpaquePointer(pointer); | |||
471 | } | |||
472 | static mlir::Value getTombstoneKey() { | |||
473 | void *pointer = llvm::DenseMapInfo<void *>::getTombstoneKey(); | |||
474 | return mlir::Value::getFromOpaquePointer(pointer); | |||
475 | } | |||
476 | static unsigned getHashValue(mlir::Value val) { | |||
477 | return mlir::hash_value(val); | |||
478 | } | |||
479 | static bool isEqual(mlir::Value lhs, mlir::Value rhs) { return lhs == rhs; } | |||
480 | }; | |||
481 | template <> | |||
482 | struct DenseMapInfo<mlir::BlockArgument> : public DenseMapInfo<mlir::Value> { | |||
483 | static mlir::BlockArgument getEmptyKey() { | |||
484 | void *pointer = llvm::DenseMapInfo<void *>::getEmptyKey(); | |||
485 | return reinterpret_cast<mlir::detail::BlockArgumentImpl *>(pointer); | |||
486 | } | |||
487 | static mlir::BlockArgument getTombstoneKey() { | |||
488 | void *pointer = llvm::DenseMapInfo<void *>::getTombstoneKey(); | |||
489 | return reinterpret_cast<mlir::detail::BlockArgumentImpl *>(pointer); | |||
490 | } | |||
491 | }; | |||
492 | template <> | |||
493 | struct DenseMapInfo<mlir::OpResult> : public DenseMapInfo<mlir::Value> { | |||
494 | static mlir::OpResult getEmptyKey() { | |||
495 | void *pointer = llvm::DenseMapInfo<void *>::getEmptyKey(); | |||
496 | return reinterpret_cast<mlir::detail::OpResultImpl *>(pointer); | |||
497 | } | |||
498 | static mlir::OpResult getTombstoneKey() { | |||
499 | void *pointer = llvm::DenseMapInfo<void *>::getTombstoneKey(); | |||
500 | return reinterpret_cast<mlir::detail::OpResultImpl *>(pointer); | |||
501 | } | |||
502 | }; | |||
503 | ||||
504 | /// Allow stealing the low bits of a value. | |||
505 | template <> | |||
506 | struct PointerLikeTypeTraits<mlir::Value> { | |||
507 | public: | |||
508 | static inline void *getAsVoidPointer(mlir::Value value) { | |||
509 | return const_cast<void *>(value.getAsOpaquePointer()); | |||
510 | } | |||
511 | static inline mlir::Value getFromVoidPointer(void *pointer) { | |||
512 | return mlir::Value::getFromOpaquePointer(pointer); | |||
513 | } | |||
514 | enum { | |||
515 | NumLowBitsAvailable = | |||
516 | PointerLikeTypeTraits<mlir::detail::ValueImpl *>::NumLowBitsAvailable | |||
517 | }; | |||
518 | }; | |||
519 | template <> | |||
520 | struct PointerLikeTypeTraits<mlir::BlockArgument> | |||
521 | : public PointerLikeTypeTraits<mlir::Value> { | |||
522 | public: | |||
523 | static inline mlir::BlockArgument getFromVoidPointer(void *pointer) { | |||
524 | return reinterpret_cast<mlir::detail::BlockArgumentImpl *>(pointer); | |||
525 | } | |||
526 | }; | |||
527 | template <> | |||
528 | struct PointerLikeTypeTraits<mlir::OpResult> | |||
529 | : public PointerLikeTypeTraits<mlir::Value> { | |||
530 | public: | |||
531 | static inline mlir::OpResult getFromVoidPointer(void *pointer) { | |||
532 | return reinterpret_cast<mlir::detail::OpResultImpl *>(pointer); | |||
533 | } | |||
534 | }; | |||
535 | ||||
536 | } // namespace llvm | |||
537 | ||||
538 | #endif |