1 //===- Liveness.cpp - Liveness analysis for MLIR --------------------------===//
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
7 //===----------------------------------------------------------------------===//
9 // Implementation of the liveness analysis.
11 //===----------------------------------------------------------------------===//
13 #include "mlir/Analysis/Liveness.h"
14 #include "mlir/IR/Block.h"
15 #include "mlir/IR/Operation.h"
16 #include "mlir/IR/Region.h"
17 #include "mlir/IR/Value.h"
18 #include "llvm/ADT/STLExtras.h"
19 #include "llvm/ADT/SetOperations.h"
20 #include "llvm/ADT/SetVector.h"
21 #include "llvm/Support/raw_ostream.h"
26 /// Builds and holds block information during the construction phase.
27 struct BlockInfoBuilder
{
28 using ValueSetT
= Liveness::ValueSetT
;
30 /// Constructs an empty block builder.
31 BlockInfoBuilder() = default;
33 /// Fills the block builder with initial liveness information.
34 BlockInfoBuilder(Block
*block
) : block(block
) {
35 auto gatherOutValues
= [&](Value value
) {
36 // Check whether this value will be in the outValues set (its uses escape
37 // this block). Due to the SSA properties of the program, the uses must
38 // occur after the definition. Therefore, we do not have to check
39 // additional conditions to detect an escaping value.
40 for (Operation
*useOp
: value
.getUsers()) {
41 Block
*ownerBlock
= useOp
->getBlock();
42 // Find an owner block in the current region. Note that a value does not
43 // escape this block if it is used in a nested region.
44 ownerBlock
= block
->getParent()->findAncestorBlockInRegion(*ownerBlock
);
45 assert(ownerBlock
&& "Use leaves the current parent region");
46 if (ownerBlock
!= block
) {
47 outValues
.insert(value
);
53 // Mark all block arguments (phis) as defined.
54 for (BlockArgument argument
: block
->getArguments()) {
55 // Insert value into the set of defined values.
56 defValues
.insert(argument
);
58 // Gather all out values of all arguments in the current block.
59 gatherOutValues(argument
);
62 // Gather out values of all operations in the current block.
63 for (Operation
&operation
: *block
)
64 for (Value result
: operation
.getResults())
65 gatherOutValues(result
);
67 // Mark all nested operation results as defined, and nested operation
68 // operands as used. All defined value will be removed from the used set
70 block
->walk([&](Operation
*op
) {
71 for (Value result
: op
->getResults())
72 defValues
.insert(result
);
73 for (Value operand
: op
->getOperands())
74 useValues
.insert(operand
);
76 llvm::set_subtract(useValues
, defValues
);
79 /// Updates live-in information of the current block. To do so it uses the
80 /// default liveness-computation formula: newIn = use union out \ def. The
81 /// methods returns true, if the set has changed (newIn != in), false
84 ValueSetT newIn
= useValues
;
85 llvm::set_union(newIn
, outValues
);
86 llvm::set_subtract(newIn
, defValues
);
88 // It is sufficient to check the set sizes (instead of their contents) since
89 // the live-in set can only grow monotonically during all update operations.
90 if (newIn
.size() == inValues
.size())
93 inValues
= std::move(newIn
);
97 /// Updates live-out information of the current block. It iterates over all
98 /// successors and unifies their live-in values with the current live-out
100 void updateLiveOut(const DenseMap
<Block
*, BlockInfoBuilder
> &builders
) {
101 for (Block
*succ
: block
->getSuccessors()) {
102 const BlockInfoBuilder
&builder
= builders
.find(succ
)->second
;
103 llvm::set_union(outValues
, builder
.inValues
);
107 /// The current block.
108 Block
*block
{nullptr};
110 /// The set of all live in values.
113 /// The set of all live out values.
116 /// The set of all defined values.
119 /// The set of all used values.
124 /// Builds the internal liveness block mapping.
125 static void buildBlockMapping(Operation
*operation
,
126 DenseMap
<Block
*, BlockInfoBuilder
> &builders
) {
127 SetVector
<Block
*> toProcess
;
129 operation
->walk
<WalkOrder::PreOrder
>([&](Block
*block
) {
130 BlockInfoBuilder
&builder
=
131 builders
.try_emplace(block
, block
).first
->second
;
133 if (builder
.updateLiveIn())
134 toProcess
.insert(block
->pred_begin(), block
->pred_end());
137 // Propagate the in and out-value sets (fixpoint iteration).
138 while (!toProcess
.empty()) {
139 Block
*current
= toProcess
.pop_back_val();
140 BlockInfoBuilder
&builder
= builders
[current
];
142 // Update the current out values.
143 builder
.updateLiveOut(builders
);
145 // Compute (potentially) updated live in values.
146 if (builder
.updateLiveIn())
147 toProcess
.insert(current
->pred_begin(), current
->pred_end());
151 //===----------------------------------------------------------------------===//
153 //===----------------------------------------------------------------------===//
155 /// Creates a new Liveness analysis that computes liveness information for all
156 /// associated regions.
157 Liveness::Liveness(Operation
*op
) : operation(op
) { build(); }
159 /// Initializes the internal mappings.
160 void Liveness::build() {
161 // Build internal block mapping.
162 DenseMap
<Block
*, BlockInfoBuilder
> builders
;
163 buildBlockMapping(operation
, builders
);
165 // Store internal block data.
166 for (auto &entry
: builders
) {
167 BlockInfoBuilder
&builder
= entry
.second
;
168 LivenessBlockInfo
&info
= blockMapping
[entry
.first
];
170 info
.block
= builder
.block
;
171 info
.inValues
= std::move(builder
.inValues
);
172 info
.outValues
= std::move(builder
.outValues
);
176 /// Gets liveness info (if any) for the given value.
177 Liveness::OperationListT
Liveness::resolveLiveness(Value value
) const {
178 OperationListT result
;
179 SmallPtrSet
<Block
*, 32> visited
;
180 SmallVector
<Block
*, 8> toProcess
;
182 // Start with the defining block
184 if (Operation
*defOp
= value
.getDefiningOp())
185 currentBlock
= defOp
->getBlock();
187 currentBlock
= value
.cast
<BlockArgument
>().getOwner();
188 toProcess
.push_back(currentBlock
);
189 visited
.insert(currentBlock
);
191 // Start with all associated blocks
192 for (OpOperand
&use
: value
.getUses()) {
193 Block
*useBlock
= use
.getOwner()->getBlock();
194 if (visited
.insert(useBlock
).second
)
195 toProcess
.push_back(useBlock
);
198 while (!toProcess
.empty()) {
199 // Get block and block liveness information.
200 Block
*block
= toProcess
.back();
201 toProcess
.pop_back();
202 const LivenessBlockInfo
*blockInfo
= getLiveness(block
);
204 // Note that start and end will be in the same block.
205 Operation
*start
= blockInfo
->getStartOperation(value
);
206 Operation
*end
= blockInfo
->getEndOperation(value
, start
);
208 result
.push_back(start
);
209 while (start
!= end
) {
210 start
= start
->getNextNode();
211 result
.push_back(start
);
214 for (Block
*successor
: block
->getSuccessors()) {
215 if (getLiveness(successor
)->isLiveIn(value
) &&
216 visited
.insert(successor
).second
)
217 toProcess
.push_back(successor
);
224 /// Gets liveness info (if any) for the block.
225 const LivenessBlockInfo
*Liveness::getLiveness(Block
*block
) const {
226 auto it
= blockMapping
.find(block
);
227 return it
== blockMapping
.end() ? nullptr : &it
->second
;
230 /// Returns a reference to a set containing live-in values.
231 const Liveness::ValueSetT
&Liveness::getLiveIn(Block
*block
) const {
232 return getLiveness(block
)->in();
235 /// Returns a reference to a set containing live-out values.
236 const Liveness::ValueSetT
&Liveness::getLiveOut(Block
*block
) const {
237 return getLiveness(block
)->out();
240 /// Returns true if `value` is not live after `operation`.
241 bool Liveness::isDeadAfter(Value value
, Operation
*operation
) const {
242 Block
*block
= operation
->getBlock();
243 const LivenessBlockInfo
*blockInfo
= getLiveness(block
);
245 // The given value escapes the associated block.
246 if (blockInfo
->isLiveOut(value
))
249 Operation
*endOperation
= blockInfo
->getEndOperation(value
, operation
);
250 // If the operation is a real user of `value` the first check is sufficient.
251 // If not, we will have to test whether the end operation is executed before
252 // the given operation in the block.
253 return endOperation
== operation
|| endOperation
->isBeforeInBlock(operation
);
256 /// Dumps the liveness information in a human readable format.
257 void Liveness::dump() const { print(llvm::errs()); }
259 /// Dumps the liveness information to the given stream.
260 void Liveness::print(raw_ostream
&os
) const {
261 os
<< "// ---- Liveness -----\n";
263 // Builds unique block/value mappings for testing purposes.
264 DenseMap
<Block
*, size_t> blockIds
;
265 DenseMap
<Operation
*, size_t> operationIds
;
266 DenseMap
<Value
, size_t> valueIds
;
267 operation
->walk
<WalkOrder::PreOrder
>([&](Block
*block
) {
268 blockIds
.insert({block
, blockIds
.size()});
269 for (BlockArgument argument
: block
->getArguments())
270 valueIds
.insert({argument
, valueIds
.size()});
271 for (Operation
&operation
: *block
) {
272 operationIds
.insert({&operation
, operationIds
.size()});
273 for (Value result
: operation
.getResults())
274 valueIds
.insert({result
, valueIds
.size()});
278 // Local printing helpers
279 auto printValueRef
= [&](Value value
) {
280 if (value
.getDefiningOp())
281 os
<< "val_" << valueIds
[value
];
283 auto blockArg
= value
.cast
<BlockArgument
>();
284 os
<< "arg" << blockArg
.getArgNumber() << "@"
285 << blockIds
[blockArg
.getOwner()];
290 auto printValueRefs
= [&](const ValueSetT
&values
) {
291 std::vector
<Value
> orderedValues(values
.begin(), values
.end());
292 llvm::sort(orderedValues
, [&](Value left
, Value right
) {
293 return valueIds
[left
] < valueIds
[right
];
295 for (Value value
: orderedValues
)
296 printValueRef(value
);
299 // Dump information about in and out values.
300 operation
->walk
<WalkOrder::PreOrder
>([&](Block
*block
) {
301 os
<< "// - Block: " << blockIds
[block
] << "\n";
302 const auto *liveness
= getLiveness(block
);
303 os
<< "// --- LiveIn: ";
304 printValueRefs(liveness
->inValues
);
305 os
<< "\n// --- LiveOut: ";
306 printValueRefs(liveness
->outValues
);
309 // Print liveness intervals.
310 os
<< "// --- BeginLivenessIntervals";
311 for (Operation
&op
: *block
) {
312 if (op
.getNumResults() < 1)
315 for (Value result
: op
.getResults()) {
317 printValueRef(result
);
319 auto liveOperations
= resolveLiveness(result
);
320 llvm::sort(liveOperations
, [&](Operation
*left
, Operation
*right
) {
321 return operationIds
[left
] < operationIds
[right
];
323 for (Operation
*operation
: liveOperations
) {
325 operation
->print(os
);
329 os
<< "\n// --- EndLivenessIntervals\n";
331 // Print currently live values.
332 os
<< "// --- BeginCurrentlyLive\n";
333 for (Operation
&op
: *block
) {
334 auto currentlyLive
= liveness
->currentlyLiveValues(&op
);
335 if (currentlyLive
.empty())
340 printValueRefs(currentlyLive
);
343 os
<< "// --- EndCurrentlyLive\n";
345 os
<< "// -------------------\n";
348 //===----------------------------------------------------------------------===//
350 //===----------------------------------------------------------------------===//
352 /// Returns true if the given value is in the live-in set.
353 bool LivenessBlockInfo::isLiveIn(Value value
) const {
354 return inValues
.count(value
);
357 /// Returns true if the given value is in the live-out set.
358 bool LivenessBlockInfo::isLiveOut(Value value
) const {
359 return outValues
.count(value
);
362 /// Gets the start operation for the given value (must be referenced in this
364 Operation
*LivenessBlockInfo::getStartOperation(Value value
) const {
365 Operation
*definingOp
= value
.getDefiningOp();
366 // The given value is either live-in or is defined
367 // in the scope of this block.
368 if (isLiveIn(value
) || !definingOp
)
369 return &block
->front();
373 /// Gets the end operation for the given value using the start operation
374 /// provided (must be referenced in this block).
375 Operation
*LivenessBlockInfo::getEndOperation(Value value
,
376 Operation
*startOperation
) const {
377 // The given value is either dying in this block or live-out.
378 if (isLiveOut(value
))
379 return &block
->back();
381 // Resolve the last operation (must exist by definition).
382 Operation
*endOperation
= startOperation
;
383 for (Operation
*useOp
: value
.getUsers()) {
384 // Find the associated operation in the current block (if any).
385 useOp
= block
->findAncestorOpInBlock(*useOp
);
386 // Check whether the use is in our block and after the current end
388 if (useOp
&& endOperation
->isBeforeInBlock(useOp
))
389 endOperation
= useOp
;
394 /// Return the values that are currently live as of the given operation.
395 LivenessBlockInfo::ValueSetT
396 LivenessBlockInfo::currentlyLiveValues(Operation
*op
) const {
399 // Given a value, check which ops are within its live range. For each of
400 // those ops, add the value to the set of live values as-of that op.
401 auto addValueToCurrentlyLiveSets
= [&](Value value
) {
402 // Determine the live range of this value inside this block.
403 Operation
*startOfLiveRange
= value
.getDefiningOp();
404 Operation
*endOfLiveRange
= nullptr;
405 // If it's a live in or a block argument, then the start is the beginning
407 if (isLiveIn(value
) || value
.isa
<BlockArgument
>())
408 startOfLiveRange
= &block
->front();
410 startOfLiveRange
= block
->findAncestorOpInBlock(*startOfLiveRange
);
412 // If it's a live out, then the end is the back of the block.
413 if (isLiveOut(value
))
414 endOfLiveRange
= &block
->back();
416 // We must have at least a startOfLiveRange at this point. Given this, we
417 // can use the existing getEndOperation to find the end of the live range.
418 if (startOfLiveRange
&& !endOfLiveRange
)
419 endOfLiveRange
= getEndOperation(value
, startOfLiveRange
);
421 assert(endOfLiveRange
&& "Must have endOfLiveRange at this point!");
422 // If this op is within the live range, insert the value into the set.
423 if (!(op
->isBeforeInBlock(startOfLiveRange
) ||
424 endOfLiveRange
->isBeforeInBlock(op
)))
425 liveSet
.insert(value
);
428 // Handle block arguments if any.
429 for (Value arg
: block
->getArguments())
430 addValueToCurrentlyLiveSets(arg
);
432 // Handle live-ins. Between the live ins and all the op results that gives us
433 // every value in the block.
434 for (Value in
: inValues
)
435 addValueToCurrentlyLiveSets(in
);
437 // Now walk the block and handle all values used in the block and values
438 // defined by the block.
439 for (Operation
&walkOp
:
440 llvm::make_range(block
->begin(), ++op
->getIterator()))
441 for (auto result
: walkOp
.getResults())
442 addValueToCurrentlyLiveSets(result
);