[LLD][COFF] Emit tail merge pdata for delay load thunks on ARM64EC (#116810)
[llvm-project.git] / mlir / lib / Analysis / Liveness.cpp
blobe3245d68b369989d7d50eb4c2211d3bcfb207ef5
1 //===- Liveness.cpp - Liveness analysis for MLIR --------------------------===//
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 // 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"
23 using namespace mlir;
25 namespace {
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);
48 break;
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
69 // at the end.
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);
75 for (Region &region : op->getRegions())
76 for (Block &child : region.getBlocks())
77 for (BlockArgument arg : child.getArguments())
78 defValues.insert(arg);
79 });
80 llvm::set_subtract(useValues, defValues);
83 /// Updates live-in information of the current block. To do so it uses the
84 /// default liveness-computation formula: newIn = use union out \ def. The
85 /// methods returns true, if the set has changed (newIn != in), false
86 /// otherwise.
87 bool updateLiveIn() {
88 ValueSetT newIn = useValues;
89 llvm::set_union(newIn, outValues);
90 llvm::set_subtract(newIn, defValues);
92 // It is sufficient to check the set sizes (instead of their contents) since
93 // the live-in set can only grow monotonically during all update operations.
94 if (newIn.size() == inValues.size())
95 return false;
97 inValues = std::move(newIn);
98 return true;
101 /// Updates live-out information of the current block. It iterates over all
102 /// successors and unifies their live-in values with the current live-out
103 /// values.
104 void updateLiveOut(const DenseMap<Block *, BlockInfoBuilder> &builders) {
105 for (Block *succ : block->getSuccessors()) {
106 const BlockInfoBuilder &builder = builders.find(succ)->second;
107 llvm::set_union(outValues, builder.inValues);
111 /// The current block.
112 Block *block{nullptr};
114 /// The set of all live in values.
115 ValueSetT inValues;
117 /// The set of all live out values.
118 ValueSetT outValues;
120 /// The set of all defined values.
121 ValueSetT defValues;
123 /// The set of all used values.
124 ValueSetT useValues;
126 } // namespace
128 /// Builds the internal liveness block mapping.
129 static void buildBlockMapping(Operation *operation,
130 DenseMap<Block *, BlockInfoBuilder> &builders) {
131 SetVector<Block *> toProcess;
133 operation->walk<WalkOrder::PreOrder>([&](Block *block) {
134 BlockInfoBuilder &builder =
135 builders.try_emplace(block, block).first->second;
137 if (builder.updateLiveIn())
138 toProcess.insert(block->pred_begin(), block->pred_end());
141 // Propagate the in and out-value sets (fixpoint iteration).
142 while (!toProcess.empty()) {
143 Block *current = toProcess.pop_back_val();
144 BlockInfoBuilder &builder = builders[current];
146 // Update the current out values.
147 builder.updateLiveOut(builders);
149 // Compute (potentially) updated live in values.
150 if (builder.updateLiveIn())
151 toProcess.insert(current->pred_begin(), current->pred_end());
155 //===----------------------------------------------------------------------===//
156 // Liveness
157 //===----------------------------------------------------------------------===//
159 /// Creates a new Liveness analysis that computes liveness information for all
160 /// associated regions.
161 Liveness::Liveness(Operation *op) : operation(op) { build(); }
163 /// Initializes the internal mappings.
164 void Liveness::build() {
165 // Build internal block mapping.
166 DenseMap<Block *, BlockInfoBuilder> builders;
167 buildBlockMapping(operation, builders);
169 // Store internal block data.
170 for (auto &entry : builders) {
171 BlockInfoBuilder &builder = entry.second;
172 LivenessBlockInfo &info = blockMapping[entry.first];
174 info.block = builder.block;
175 info.inValues = std::move(builder.inValues);
176 info.outValues = std::move(builder.outValues);
180 /// Gets liveness info (if any) for the given value.
181 Liveness::OperationListT Liveness::resolveLiveness(Value value) const {
182 OperationListT result;
183 SmallPtrSet<Block *, 32> visited;
184 SmallVector<Block *, 8> toProcess;
186 // Start with the defining block
187 Block *currentBlock;
188 if (Operation *defOp = value.getDefiningOp())
189 currentBlock = defOp->getBlock();
190 else
191 currentBlock = cast<BlockArgument>(value).getOwner();
192 toProcess.push_back(currentBlock);
193 visited.insert(currentBlock);
195 // Start with all associated blocks
196 for (OpOperand &use : value.getUses()) {
197 Block *useBlock = use.getOwner()->getBlock();
198 if (visited.insert(useBlock).second)
199 toProcess.push_back(useBlock);
202 while (!toProcess.empty()) {
203 // Get block and block liveness information.
204 Block *block = toProcess.back();
205 toProcess.pop_back();
206 const LivenessBlockInfo *blockInfo = getLiveness(block);
208 // Note that start and end will be in the same block.
209 Operation *start = blockInfo->getStartOperation(value);
210 Operation *end = blockInfo->getEndOperation(value, start);
212 result.push_back(start);
213 while (start != end) {
214 start = start->getNextNode();
215 result.push_back(start);
218 for (Block *successor : block->getSuccessors()) {
219 if (getLiveness(successor)->isLiveIn(value) &&
220 visited.insert(successor).second)
221 toProcess.push_back(successor);
225 return result;
228 /// Gets liveness info (if any) for the block.
229 const LivenessBlockInfo *Liveness::getLiveness(Block *block) const {
230 auto it = blockMapping.find(block);
231 return it == blockMapping.end() ? nullptr : &it->second;
234 /// Returns a reference to a set containing live-in values.
235 const Liveness::ValueSetT &Liveness::getLiveIn(Block *block) const {
236 return getLiveness(block)->in();
239 /// Returns a reference to a set containing live-out values.
240 const Liveness::ValueSetT &Liveness::getLiveOut(Block *block) const {
241 return getLiveness(block)->out();
244 /// Returns true if `value` is not live after `operation`.
245 bool Liveness::isDeadAfter(Value value, Operation *operation) const {
246 Block *block = operation->getBlock();
247 const LivenessBlockInfo *blockInfo = getLiveness(block);
249 // The given value escapes the associated block.
250 if (blockInfo->isLiveOut(value))
251 return false;
253 Operation *endOperation = blockInfo->getEndOperation(value, operation);
254 // If the operation is a real user of `value` the first check is sufficient.
255 // If not, we will have to test whether the end operation is executed before
256 // the given operation in the block.
257 return endOperation == operation || endOperation->isBeforeInBlock(operation);
260 /// Dumps the liveness information in a human readable format.
261 void Liveness::dump() const { print(llvm::errs()); }
263 /// Dumps the liveness information to the given stream.
264 void Liveness::print(raw_ostream &os) const {
265 os << "// ---- Liveness -----\n";
267 // Builds unique block/value mappings for testing purposes.
268 DenseMap<Block *, size_t> blockIds;
269 DenseMap<Operation *, size_t> operationIds;
270 DenseMap<Value, size_t> valueIds;
271 operation->walk<WalkOrder::PreOrder>([&](Block *block) {
272 blockIds.insert({block, blockIds.size()});
273 for (BlockArgument argument : block->getArguments())
274 valueIds.insert({argument, valueIds.size()});
275 for (Operation &operation : *block) {
276 operationIds.insert({&operation, operationIds.size()});
277 for (Value result : operation.getResults())
278 valueIds.insert({result, valueIds.size()});
282 // Local printing helpers
283 auto printValueRef = [&](Value value) {
284 if (value.getDefiningOp())
285 os << "val_" << valueIds[value];
286 else {
287 auto blockArg = cast<BlockArgument>(value);
288 os << "arg" << blockArg.getArgNumber() << "@"
289 << blockIds[blockArg.getOwner()];
291 os << " ";
294 auto printValueRefs = [&](const ValueSetT &values) {
295 std::vector<Value> orderedValues(values.begin(), values.end());
296 llvm::sort(orderedValues, [&](Value left, Value right) {
297 return valueIds[left] < valueIds[right];
299 for (Value value : orderedValues)
300 printValueRef(value);
303 // Dump information about in and out values.
304 operation->walk<WalkOrder::PreOrder>([&](Block *block) {
305 os << "// - Block: " << blockIds[block] << "\n";
306 const auto *liveness = getLiveness(block);
307 os << "// --- LiveIn: ";
308 printValueRefs(liveness->inValues);
309 os << "\n// --- LiveOut: ";
310 printValueRefs(liveness->outValues);
311 os << "\n";
313 // Print liveness intervals.
314 os << "// --- BeginLivenessIntervals";
315 for (Operation &op : *block) {
316 if (op.getNumResults() < 1)
317 continue;
318 os << "\n";
319 for (Value result : op.getResults()) {
320 os << "// ";
321 printValueRef(result);
322 os << ":";
323 auto liveOperations = resolveLiveness(result);
324 llvm::sort(liveOperations, [&](Operation *left, Operation *right) {
325 return operationIds[left] < operationIds[right];
327 for (Operation *operation : liveOperations) {
328 os << "\n// ";
329 operation->print(os);
333 os << "\n// --- EndLivenessIntervals\n";
335 // Print currently live values.
336 os << "// --- BeginCurrentlyLive\n";
337 for (Operation &op : *block) {
338 auto currentlyLive = liveness->currentlyLiveValues(&op);
339 if (currentlyLive.empty())
340 continue;
341 os << "// ";
342 op.print(os);
343 os << " [";
344 printValueRefs(currentlyLive);
345 os << "\b]\n";
347 os << "// --- EndCurrentlyLive\n";
349 os << "// -------------------\n";
352 //===----------------------------------------------------------------------===//
353 // LivenessBlockInfo
354 //===----------------------------------------------------------------------===//
356 /// Returns true if the given value is in the live-in set.
357 bool LivenessBlockInfo::isLiveIn(Value value) const {
358 return inValues.count(value);
361 /// Returns true if the given value is in the live-out set.
362 bool LivenessBlockInfo::isLiveOut(Value value) const {
363 return outValues.count(value);
366 /// Gets the start operation for the given value (must be referenced in this
367 /// block).
368 Operation *LivenessBlockInfo::getStartOperation(Value value) const {
369 Operation *definingOp = value.getDefiningOp();
370 // The given value is either live-in or is defined
371 // in the scope of this block.
372 if (isLiveIn(value) || !definingOp)
373 return &block->front();
374 return definingOp;
377 /// Gets the end operation for the given value using the start operation
378 /// provided (must be referenced in this block).
379 Operation *LivenessBlockInfo::getEndOperation(Value value,
380 Operation *startOperation) const {
381 // The given value is either dying in this block or live-out.
382 if (isLiveOut(value))
383 return &block->back();
385 // Resolve the last operation (must exist by definition).
386 Operation *endOperation = startOperation;
387 for (Operation *useOp : value.getUsers()) {
388 // Find the associated operation in the current block (if any).
389 useOp = block->findAncestorOpInBlock(*useOp);
390 // Check whether the use is in our block and after the current end
391 // operation.
392 if (useOp && endOperation->isBeforeInBlock(useOp))
393 endOperation = useOp;
395 return endOperation;
398 /// Return the values that are currently live as of the given operation.
399 LivenessBlockInfo::ValueSetT
400 LivenessBlockInfo::currentlyLiveValues(Operation *op) const {
401 ValueSetT liveSet;
403 // Given a value, check which ops are within its live range. For each of
404 // those ops, add the value to the set of live values as-of that op.
405 auto addValueToCurrentlyLiveSets = [&](Value value) {
406 // Determine the live range of this value inside this block.
407 Operation *startOfLiveRange = value.getDefiningOp();
408 Operation *endOfLiveRange = nullptr;
409 // If it's a live in or a block argument, then the start is the beginning
410 // of the block.
411 if (isLiveIn(value) || isa<BlockArgument>(value))
412 startOfLiveRange = &block->front();
413 else
414 startOfLiveRange = block->findAncestorOpInBlock(*startOfLiveRange);
416 // If it's a live out, then the end is the back of the block.
417 if (isLiveOut(value))
418 endOfLiveRange = &block->back();
420 // We must have at least a startOfLiveRange at this point. Given this, we
421 // can use the existing getEndOperation to find the end of the live range.
422 if (startOfLiveRange && !endOfLiveRange)
423 endOfLiveRange = getEndOperation(value, startOfLiveRange);
425 assert(endOfLiveRange && "Must have endOfLiveRange at this point!");
426 // If this op is within the live range, insert the value into the set.
427 if (!(op->isBeforeInBlock(startOfLiveRange) ||
428 endOfLiveRange->isBeforeInBlock(op)))
429 liveSet.insert(value);
432 // Handle block arguments if any.
433 for (Value arg : block->getArguments())
434 addValueToCurrentlyLiveSets(arg);
436 // Handle live-ins. Between the live ins and all the op results that gives us
437 // every value in the block.
438 for (Value in : inValues)
439 addValueToCurrentlyLiveSets(in);
441 // Now walk the block and handle all values used in the block and values
442 // defined by the block.
443 for (Operation &walkOp :
444 llvm::make_range(block->begin(), ++op->getIterator()))
445 for (auto result : walkOp.getResults())
446 addValueToCurrentlyLiveSets(result);
448 return liveSet;