xref: /llvm-project/mlir/lib/Analysis/Liveness.cpp (revision 63e8c0a0e48939371652f907bb868d74869ae00a)
14b0198acSAlexander Belyaev //===- Liveness.cpp - Liveness analysis for MLIR --------------------------===//
24b0198acSAlexander Belyaev //
330857107SMehdi Amini // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
456222a06SMehdi Amini // See https://llvm.org/LICENSE.txt for license information.
556222a06SMehdi Amini // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
64b0198acSAlexander Belyaev //
756222a06SMehdi Amini //===----------------------------------------------------------------------===//
84b0198acSAlexander Belyaev //
94b0198acSAlexander Belyaev // Implementation of the liveness analysis.
104b0198acSAlexander Belyaev //
114b0198acSAlexander Belyaev //===----------------------------------------------------------------------===//
124b0198acSAlexander Belyaev 
134b0198acSAlexander Belyaev #include "mlir/Analysis/Liveness.h"
144b0198acSAlexander Belyaev #include "mlir/IR/Block.h"
154b0198acSAlexander Belyaev #include "mlir/IR/Operation.h"
164b0198acSAlexander Belyaev #include "mlir/IR/Region.h"
174b0198acSAlexander Belyaev #include "mlir/IR/Value.h"
18aba43035SDmitri Gribenko #include "llvm/ADT/STLExtras.h"
194b0198acSAlexander Belyaev #include "llvm/ADT/SetOperations.h"
204b0198acSAlexander Belyaev #include "llvm/ADT/SetVector.h"
214b0198acSAlexander Belyaev #include "llvm/Support/raw_ostream.h"
224b0198acSAlexander Belyaev 
234b0198acSAlexander Belyaev using namespace mlir;
244b0198acSAlexander Belyaev 
25df186507SBenjamin Kramer namespace {
264b0198acSAlexander Belyaev /// Builds and holds block information during the construction phase.
274b0198acSAlexander Belyaev struct BlockInfoBuilder {
284b0198acSAlexander Belyaev   using ValueSetT = Liveness::ValueSetT;
294b0198acSAlexander Belyaev 
304b0198acSAlexander Belyaev   /// Constructs an empty block builder.
31abb336d2SMehdi Amini   BlockInfoBuilder() = default;
324b0198acSAlexander Belyaev 
334b0198acSAlexander Belyaev   /// Fills the block builder with initial liveness information.
BlockInfoBuilder__anonf9c92e380111::BlockInfoBuilder344b0198acSAlexander Belyaev   BlockInfoBuilder(Block *block) : block(block) {
35c79227caSMarcel Koester     auto gatherOutValues = [&](Value value) {
36c79227caSMarcel Koester       // Check whether this value will be in the outValues set (its uses escape
37c79227caSMarcel Koester       // this block). Due to the SSA properties of the program, the uses must
38c79227caSMarcel Koester       // occur after the definition. Therefore, we do not have to check
394b0198acSAlexander Belyaev       // additional conditions to detect an escaping value.
40c79227caSMarcel Koester       for (Operation *useOp : value.getUsers()) {
41c79227caSMarcel Koester         Block *ownerBlock = useOp->getBlock();
42c79227caSMarcel Koester         // Find an owner block in the current region. Note that a value does not
43c79227caSMarcel Koester         // escape this block if it is used in a nested region.
44c79227caSMarcel Koester         ownerBlock = block->getParent()->findAncestorBlockInRegion(*ownerBlock);
45c79227caSMarcel Koester         assert(ownerBlock && "Use leaves the current parent region");
46c79227caSMarcel Koester         if (ownerBlock != block) {
47c79227caSMarcel Koester           outValues.insert(value);
484b0198acSAlexander Belyaev           break;
494b0198acSAlexander Belyaev         }
504b0198acSAlexander Belyaev       }
51c79227caSMarcel Koester     };
52c79227caSMarcel Koester 
53c79227caSMarcel Koester     // Mark all block arguments (phis) as defined.
54c79227caSMarcel Koester     for (BlockArgument argument : block->getArguments()) {
55c79227caSMarcel Koester       // Insert value into the set of defined values.
56c79227caSMarcel Koester       defValues.insert(argument);
57c79227caSMarcel Koester 
58c79227caSMarcel Koester       // Gather all out values of all arguments in the current block.
59c79227caSMarcel Koester       gatherOutValues(argument);
60c79227caSMarcel Koester     }
61c79227caSMarcel Koester 
62c79227caSMarcel Koester     // Gather out values of all operations in the current block.
63c79227caSMarcel Koester     for (Operation &operation : *block)
64c79227caSMarcel Koester       for (Value result : operation.getResults())
65c79227caSMarcel Koester         gatherOutValues(result);
66c79227caSMarcel Koester 
6717de7ed5SRahul Joshi     // Mark all nested operation results as defined, and nested operation
6817de7ed5SRahul Joshi     // operands as used. All defined value will be removed from the used set
6917de7ed5SRahul Joshi     // at the end.
70c79227caSMarcel Koester     block->walk([&](Operation *op) {
71c79227caSMarcel Koester       for (Value result : op->getResults())
72c79227caSMarcel Koester         defValues.insert(result);
7317de7ed5SRahul Joshi       for (Value operand : op->getOperands())
744b0198acSAlexander Belyaev         useValues.insert(operand);
75*63e8c0a0SIvan Kulagin       for (Region &region : op->getRegions())
76*63e8c0a0SIvan Kulagin         for (Block &child : region.getBlocks())
77*63e8c0a0SIvan Kulagin           for (BlockArgument arg : child.getArguments())
78*63e8c0a0SIvan Kulagin             defValues.insert(arg);
79c79227caSMarcel Koester     });
8017de7ed5SRahul Joshi     llvm::set_subtract(useValues, defValues);
814b0198acSAlexander Belyaev   }
824b0198acSAlexander Belyaev 
83c79227caSMarcel Koester   /// Updates live-in information of the current block. To do so it uses the
84c79227caSMarcel Koester   /// default liveness-computation formula: newIn = use union out \ def. The
85c79227caSMarcel Koester   /// methods returns true, if the set has changed (newIn != in), false
86c79227caSMarcel Koester   /// otherwise.
updateLiveIn__anonf9c92e380111::BlockInfoBuilder874b0198acSAlexander Belyaev   bool updateLiveIn() {
884b0198acSAlexander Belyaev     ValueSetT newIn = useValues;
894b0198acSAlexander Belyaev     llvm::set_union(newIn, outValues);
904b0198acSAlexander Belyaev     llvm::set_subtract(newIn, defValues);
914b0198acSAlexander Belyaev 
92c79227caSMarcel Koester     // It is sufficient to check the set sizes (instead of their contents) since
93c79227caSMarcel Koester     // the live-in set can only grow monotonically during all update operations.
944b0198acSAlexander Belyaev     if (newIn.size() == inValues.size())
954b0198acSAlexander Belyaev       return false;
964b0198acSAlexander Belyaev 
9717de7ed5SRahul Joshi     inValues = std::move(newIn);
984b0198acSAlexander Belyaev     return true;
994b0198acSAlexander Belyaev   }
1004b0198acSAlexander Belyaev 
101c79227caSMarcel Koester   /// Updates live-out information of the current block. It iterates over all
102c79227caSMarcel Koester   /// successors and unifies their live-in values with the current live-out
103c79227caSMarcel Koester   /// values.
updateLiveOut__anonf9c92e380111::BlockInfoBuilder10417de7ed5SRahul Joshi   void updateLiveOut(const DenseMap<Block *, BlockInfoBuilder> &builders) {
1054b0198acSAlexander Belyaev     for (Block *succ : block->getSuccessors()) {
10617de7ed5SRahul Joshi       const BlockInfoBuilder &builder = builders.find(succ)->second;
1074b0198acSAlexander Belyaev       llvm::set_union(outValues, builder.inValues);
1084b0198acSAlexander Belyaev     }
1094b0198acSAlexander Belyaev   }
1104b0198acSAlexander Belyaev 
1114b0198acSAlexander Belyaev   /// The current block.
112e5639b3fSMehdi Amini   Block *block{nullptr};
1134b0198acSAlexander Belyaev 
1144b0198acSAlexander Belyaev   /// The set of all live in values.
1154b0198acSAlexander Belyaev   ValueSetT inValues;
1164b0198acSAlexander Belyaev 
1174b0198acSAlexander Belyaev   /// The set of all live out values.
1184b0198acSAlexander Belyaev   ValueSetT outValues;
1194b0198acSAlexander Belyaev 
1204b0198acSAlexander Belyaev   /// The set of all defined values.
1214b0198acSAlexander Belyaev   ValueSetT defValues;
1224b0198acSAlexander Belyaev 
1234b0198acSAlexander Belyaev   /// The set of all used values.
1244b0198acSAlexander Belyaev   ValueSetT useValues;
1254b0198acSAlexander Belyaev };
126df186507SBenjamin Kramer } // namespace
1274b0198acSAlexander Belyaev 
1284b0198acSAlexander Belyaev /// Builds the internal liveness block mapping.
buildBlockMapping(Operation * operation,DenseMap<Block *,BlockInfoBuilder> & builders)1291664462dSFrederik Gossen static void buildBlockMapping(Operation *operation,
1304b0198acSAlexander Belyaev                               DenseMap<Block *, BlockInfoBuilder> &builders) {
1314efb7754SRiver Riddle   SetVector<Block *> toProcess;
1324b0198acSAlexander Belyaev 
13371a86245SDiego Caballero   operation->walk<WalkOrder::PreOrder>([&](Block *block) {
1344b0198acSAlexander Belyaev     BlockInfoBuilder &builder =
1351664462dSFrederik Gossen         builders.try_emplace(block, block).first->second;
1364b0198acSAlexander Belyaev 
1374b0198acSAlexander Belyaev     if (builder.updateLiveIn())
1381664462dSFrederik Gossen       toProcess.insert(block->pred_begin(), block->pred_end());
139c79227caSMarcel Koester   });
1404b0198acSAlexander Belyaev 
14117de7ed5SRahul Joshi   // Propagate the in and out-value sets (fixpoint iteration).
1424b0198acSAlexander Belyaev   while (!toProcess.empty()) {
1434b0198acSAlexander Belyaev     Block *current = toProcess.pop_back_val();
1444b0198acSAlexander Belyaev     BlockInfoBuilder &builder = builders[current];
1454b0198acSAlexander Belyaev 
1464b0198acSAlexander Belyaev     // Update the current out values.
1474b0198acSAlexander Belyaev     builder.updateLiveOut(builders);
1484b0198acSAlexander Belyaev 
1494b0198acSAlexander Belyaev     // Compute (potentially) updated live in values.
1504b0198acSAlexander Belyaev     if (builder.updateLiveIn())
1514b0198acSAlexander Belyaev       toProcess.insert(current->pred_begin(), current->pred_end());
1524b0198acSAlexander Belyaev   }
1534b0198acSAlexander Belyaev }
1544b0198acSAlexander Belyaev 
1554b0198acSAlexander Belyaev //===----------------------------------------------------------------------===//
1564b0198acSAlexander Belyaev // Liveness
1574b0198acSAlexander Belyaev //===----------------------------------------------------------------------===//
1584b0198acSAlexander Belyaev 
159c79227caSMarcel Koester /// Creates a new Liveness analysis that computes liveness information for all
160c79227caSMarcel Koester /// associated regions.
Liveness(Operation * op)1611664462dSFrederik Gossen Liveness::Liveness(Operation *op) : operation(op) { build(); }
1624b0198acSAlexander Belyaev 
1634b0198acSAlexander Belyaev /// Initializes the internal mappings.
build()1641664462dSFrederik Gossen void Liveness::build() {
1654b0198acSAlexander Belyaev   // Build internal block mapping.
1664b0198acSAlexander Belyaev   DenseMap<Block *, BlockInfoBuilder> builders;
1671664462dSFrederik Gossen   buildBlockMapping(operation, builders);
1684b0198acSAlexander Belyaev 
1694b0198acSAlexander Belyaev   // Store internal block data.
1704b0198acSAlexander Belyaev   for (auto &entry : builders) {
1714b0198acSAlexander Belyaev     BlockInfoBuilder &builder = entry.second;
1724b0198acSAlexander Belyaev     LivenessBlockInfo &info = blockMapping[entry.first];
1734b0198acSAlexander Belyaev 
1744b0198acSAlexander Belyaev     info.block = builder.block;
1754b0198acSAlexander Belyaev     info.inValues = std::move(builder.inValues);
1764b0198acSAlexander Belyaev     info.outValues = std::move(builder.outValues);
1774b0198acSAlexander Belyaev   }
1784b0198acSAlexander Belyaev }
1794b0198acSAlexander Belyaev 
1804b0198acSAlexander Belyaev /// Gets liveness info (if any) for the given value.
resolveLiveness(Value value) const181e62a6956SRiver Riddle Liveness::OperationListT Liveness::resolveLiveness(Value value) const {
1824b0198acSAlexander Belyaev   OperationListT result;
1834b0198acSAlexander Belyaev   SmallPtrSet<Block *, 32> visited;
1844b0198acSAlexander Belyaev   SmallVector<Block *, 8> toProcess;
1854b0198acSAlexander Belyaev 
1864b0198acSAlexander Belyaev   // Start with the defining block
1874b0198acSAlexander Belyaev   Block *currentBlock;
1882bdf33ccSRiver Riddle   if (Operation *defOp = value.getDefiningOp())
1894b0198acSAlexander Belyaev     currentBlock = defOp->getBlock();
1904b0198acSAlexander Belyaev   else
1915550c821STres Popp     currentBlock = cast<BlockArgument>(value).getOwner();
1924b0198acSAlexander Belyaev   toProcess.push_back(currentBlock);
1934b0198acSAlexander Belyaev   visited.insert(currentBlock);
1944b0198acSAlexander Belyaev 
1954b0198acSAlexander Belyaev   // Start with all associated blocks
1962bdf33ccSRiver Riddle   for (OpOperand &use : value.getUses()) {
1974b0198acSAlexander Belyaev     Block *useBlock = use.getOwner()->getBlock();
1984b0198acSAlexander Belyaev     if (visited.insert(useBlock).second)
1994b0198acSAlexander Belyaev       toProcess.push_back(useBlock);
2004b0198acSAlexander Belyaev   }
2014b0198acSAlexander Belyaev 
2024b0198acSAlexander Belyaev   while (!toProcess.empty()) {
2034b0198acSAlexander Belyaev     // Get block and block liveness information.
2044b0198acSAlexander Belyaev     Block *block = toProcess.back();
2054b0198acSAlexander Belyaev     toProcess.pop_back();
2064b0198acSAlexander Belyaev     const LivenessBlockInfo *blockInfo = getLiveness(block);
2074b0198acSAlexander Belyaev 
2084b0198acSAlexander Belyaev     // Note that start and end will be in the same block.
2094b0198acSAlexander Belyaev     Operation *start = blockInfo->getStartOperation(value);
2104b0198acSAlexander Belyaev     Operation *end = blockInfo->getEndOperation(value, start);
2114b0198acSAlexander Belyaev 
2124b0198acSAlexander Belyaev     result.push_back(start);
2134b0198acSAlexander Belyaev     while (start != end) {
2144b0198acSAlexander Belyaev       start = start->getNextNode();
2154b0198acSAlexander Belyaev       result.push_back(start);
2164b0198acSAlexander Belyaev     }
2174b0198acSAlexander Belyaev 
2184b0198acSAlexander Belyaev     for (Block *successor : block->getSuccessors()) {
2194b0198acSAlexander Belyaev       if (getLiveness(successor)->isLiveIn(value) &&
2204b0198acSAlexander Belyaev           visited.insert(successor).second)
2214b0198acSAlexander Belyaev         toProcess.push_back(successor);
2224b0198acSAlexander Belyaev     }
2234b0198acSAlexander Belyaev   }
2244b0198acSAlexander Belyaev 
2254b0198acSAlexander Belyaev   return result;
2264b0198acSAlexander Belyaev }
2274b0198acSAlexander Belyaev 
2284b0198acSAlexander Belyaev /// Gets liveness info (if any) for the block.
getLiveness(Block * block) const2294b0198acSAlexander Belyaev const LivenessBlockInfo *Liveness::getLiveness(Block *block) const {
2304b0198acSAlexander Belyaev   auto it = blockMapping.find(block);
2314b0198acSAlexander Belyaev   return it == blockMapping.end() ? nullptr : &it->second;
2324b0198acSAlexander Belyaev }
2334b0198acSAlexander Belyaev 
2344b0198acSAlexander Belyaev /// Returns a reference to a set containing live-in values.
getLiveIn(Block * block) const2354b0198acSAlexander Belyaev const Liveness::ValueSetT &Liveness::getLiveIn(Block *block) const {
2364b0198acSAlexander Belyaev   return getLiveness(block)->in();
2374b0198acSAlexander Belyaev }
2384b0198acSAlexander Belyaev 
2394b0198acSAlexander Belyaev /// Returns a reference to a set containing live-out values.
getLiveOut(Block * block) const2404b0198acSAlexander Belyaev const Liveness::ValueSetT &Liveness::getLiveOut(Block *block) const {
2414b0198acSAlexander Belyaev   return getLiveness(block)->out();
2424b0198acSAlexander Belyaev }
2434b0198acSAlexander Belyaev 
24417de7ed5SRahul Joshi /// Returns true if `value` is not live after `operation`.
isDeadAfter(Value value,Operation * operation) const24517de7ed5SRahul Joshi bool Liveness::isDeadAfter(Value value, Operation *operation) const {
2464b0198acSAlexander Belyaev   Block *block = operation->getBlock();
2474b0198acSAlexander Belyaev   const LivenessBlockInfo *blockInfo = getLiveness(block);
2484b0198acSAlexander Belyaev 
2494b0198acSAlexander Belyaev   // The given value escapes the associated block.
2504b0198acSAlexander Belyaev   if (blockInfo->isLiveOut(value))
2514b0198acSAlexander Belyaev     return false;
2524b0198acSAlexander Belyaev 
2534b0198acSAlexander Belyaev   Operation *endOperation = blockInfo->getEndOperation(value, operation);
2544b0198acSAlexander Belyaev   // If the operation is a real user of `value` the first check is sufficient.
2554b0198acSAlexander Belyaev   // If not, we will have to test whether the end operation is executed before
2564b0198acSAlexander Belyaev   // the given operation in the block.
2574b0198acSAlexander Belyaev   return endOperation == operation || endOperation->isBeforeInBlock(operation);
2584b0198acSAlexander Belyaev }
2594b0198acSAlexander Belyaev 
2604b0198acSAlexander Belyaev /// Dumps the liveness information in a human readable format.
dump() const2614b0198acSAlexander Belyaev void Liveness::dump() const { print(llvm::errs()); }
2624b0198acSAlexander Belyaev 
2634b0198acSAlexander Belyaev /// Dumps the liveness information to the given stream.
print(raw_ostream & os) const2644b0198acSAlexander Belyaev void Liveness::print(raw_ostream &os) const {
2654b0198acSAlexander Belyaev   os << "// ---- Liveness -----\n";
2664b0198acSAlexander Belyaev 
2674b0198acSAlexander Belyaev   // Builds unique block/value mappings for testing purposes.
2684b0198acSAlexander Belyaev   DenseMap<Block *, size_t> blockIds;
2694b0198acSAlexander Belyaev   DenseMap<Operation *, size_t> operationIds;
270e62a6956SRiver Riddle   DenseMap<Value, size_t> valueIds;
27171a86245SDiego Caballero   operation->walk<WalkOrder::PreOrder>([&](Block *block) {
2721664462dSFrederik Gossen     blockIds.insert({block, blockIds.size()});
2731664462dSFrederik Gossen     for (BlockArgument argument : block->getArguments())
2744b0198acSAlexander Belyaev       valueIds.insert({argument, valueIds.size()});
2751664462dSFrederik Gossen     for (Operation &operation : *block) {
2764b0198acSAlexander Belyaev       operationIds.insert({&operation, operationIds.size()});
277e62a6956SRiver Riddle       for (Value result : operation.getResults())
2784b0198acSAlexander Belyaev         valueIds.insert({result, valueIds.size()});
2794b0198acSAlexander Belyaev     }
280c79227caSMarcel Koester   });
2814b0198acSAlexander Belyaev 
2824b0198acSAlexander Belyaev   // Local printing helpers
283e62a6956SRiver Riddle   auto printValueRef = [&](Value value) {
2848e640ca5SMarcel Koester     if (value.getDefiningOp())
285c79227caSMarcel Koester       os << "val_" << valueIds[value];
2864b0198acSAlexander Belyaev     else {
2875550c821STres Popp       auto blockArg = cast<BlockArgument>(value);
2882bdf33ccSRiver Riddle       os << "arg" << blockArg.getArgNumber() << "@"
2892bdf33ccSRiver Riddle          << blockIds[blockArg.getOwner()];
2904b0198acSAlexander Belyaev     }
2914b0198acSAlexander Belyaev     os << " ";
2924b0198acSAlexander Belyaev   };
2934b0198acSAlexander Belyaev 
2944b0198acSAlexander Belyaev   auto printValueRefs = [&](const ValueSetT &values) {
295e62a6956SRiver Riddle     std::vector<Value> orderedValues(values.begin(), values.end());
296aba43035SDmitri Gribenko     llvm::sort(orderedValues, [&](Value left, Value right) {
2974b0198acSAlexander Belyaev       return valueIds[left] < valueIds[right];
2984b0198acSAlexander Belyaev     });
299e62a6956SRiver Riddle     for (Value value : orderedValues)
3004b0198acSAlexander Belyaev       printValueRef(value);
3014b0198acSAlexander Belyaev   };
3024b0198acSAlexander Belyaev 
3034b0198acSAlexander Belyaev   // Dump information about in and out values.
30471a86245SDiego Caballero   operation->walk<WalkOrder::PreOrder>([&](Block *block) {
3051664462dSFrederik Gossen     os << "// - Block: " << blockIds[block] << "\n";
3061664462dSFrederik Gossen     const auto *liveness = getLiveness(block);
3074b0198acSAlexander Belyaev     os << "// --- LiveIn: ";
3084b0198acSAlexander Belyaev     printValueRefs(liveness->inValues);
3094b0198acSAlexander Belyaev     os << "\n// --- LiveOut: ";
3104b0198acSAlexander Belyaev     printValueRefs(liveness->outValues);
3114b0198acSAlexander Belyaev     os << "\n";
3124b0198acSAlexander Belyaev 
3134b0198acSAlexander Belyaev     // Print liveness intervals.
314f382dfc0Sbzcheeseman     os << "// --- BeginLivenessIntervals";
3151664462dSFrederik Gossen     for (Operation &op : *block) {
3164b0198acSAlexander Belyaev       if (op.getNumResults() < 1)
3174b0198acSAlexander Belyaev         continue;
3184b0198acSAlexander Belyaev       os << "\n";
319e62a6956SRiver Riddle       for (Value result : op.getResults()) {
3204b0198acSAlexander Belyaev         os << "// ";
3214b0198acSAlexander Belyaev         printValueRef(result);
3224b0198acSAlexander Belyaev         os << ":";
3234b0198acSAlexander Belyaev         auto liveOperations = resolveLiveness(result);
324aba43035SDmitri Gribenko         llvm::sort(liveOperations, [&](Operation *left, Operation *right) {
3254b0198acSAlexander Belyaev           return operationIds[left] < operationIds[right];
3264b0198acSAlexander Belyaev         });
3274b0198acSAlexander Belyaev         for (Operation *operation : liveOperations) {
3284b0198acSAlexander Belyaev           os << "\n//     ";
3294b0198acSAlexander Belyaev           operation->print(os);
3304b0198acSAlexander Belyaev         }
3314b0198acSAlexander Belyaev       }
3324b0198acSAlexander Belyaev     }
333f382dfc0Sbzcheeseman     os << "\n// --- EndLivenessIntervals\n";
334f382dfc0Sbzcheeseman 
335f382dfc0Sbzcheeseman     // Print currently live values.
336f382dfc0Sbzcheeseman     os << "// --- BeginCurrentlyLive\n";
337f382dfc0Sbzcheeseman     for (Operation &op : *block) {
338f382dfc0Sbzcheeseman       auto currentlyLive = liveness->currentlyLiveValues(&op);
339f382dfc0Sbzcheeseman       if (currentlyLive.empty())
340f382dfc0Sbzcheeseman         continue;
341f382dfc0Sbzcheeseman       os << "//     ";
342f382dfc0Sbzcheeseman       op.print(os);
343f382dfc0Sbzcheeseman       os << " [";
344f382dfc0Sbzcheeseman       printValueRefs(currentlyLive);
345f382dfc0Sbzcheeseman       os << "\b]\n";
346f382dfc0Sbzcheeseman     }
347f382dfc0Sbzcheeseman     os << "// --- EndCurrentlyLive\n";
348c79227caSMarcel Koester   });
3494b0198acSAlexander Belyaev   os << "// -------------------\n";
3504b0198acSAlexander Belyaev }
3514b0198acSAlexander Belyaev 
3524b0198acSAlexander Belyaev //===----------------------------------------------------------------------===//
3534b0198acSAlexander Belyaev // LivenessBlockInfo
3544b0198acSAlexander Belyaev //===----------------------------------------------------------------------===//
3554b0198acSAlexander Belyaev 
3564b0198acSAlexander Belyaev /// Returns true if the given value is in the live-in set.
isLiveIn(Value value) const357e62a6956SRiver Riddle bool LivenessBlockInfo::isLiveIn(Value value) const {
3584b0198acSAlexander Belyaev   return inValues.count(value);
3594b0198acSAlexander Belyaev }
3604b0198acSAlexander Belyaev 
3614b0198acSAlexander Belyaev /// Returns true if the given value is in the live-out set.
isLiveOut(Value value) const362e62a6956SRiver Riddle bool LivenessBlockInfo::isLiveOut(Value value) const {
3634b0198acSAlexander Belyaev   return outValues.count(value);
3644b0198acSAlexander Belyaev }
3654b0198acSAlexander Belyaev 
366c79227caSMarcel Koester /// Gets the start operation for the given value (must be referenced in this
367c79227caSMarcel Koester /// block).
getStartOperation(Value value) const368e62a6956SRiver Riddle Operation *LivenessBlockInfo::getStartOperation(Value value) const {
3692bdf33ccSRiver Riddle   Operation *definingOp = value.getDefiningOp();
3704b0198acSAlexander Belyaev   // The given value is either live-in or is defined
3714b0198acSAlexander Belyaev   // in the scope of this block.
3724b0198acSAlexander Belyaev   if (isLiveIn(value) || !definingOp)
3734b0198acSAlexander Belyaev     return &block->front();
3744b0198acSAlexander Belyaev   return definingOp;
3754b0198acSAlexander Belyaev }
3764b0198acSAlexander Belyaev 
3774b0198acSAlexander Belyaev /// Gets the end operation for the given value using the start operation
3784b0198acSAlexander Belyaev /// provided (must be referenced in this block).
getEndOperation(Value value,Operation * startOperation) const379e62a6956SRiver Riddle Operation *LivenessBlockInfo::getEndOperation(Value value,
3804b0198acSAlexander Belyaev                                               Operation *startOperation) const {
3814b0198acSAlexander Belyaev   // The given value is either dying in this block or live-out.
3824b0198acSAlexander Belyaev   if (isLiveOut(value))
3834b0198acSAlexander Belyaev     return &block->back();
3844b0198acSAlexander Belyaev 
3854b0198acSAlexander Belyaev   // Resolve the last operation (must exist by definition).
3864b0198acSAlexander Belyaev   Operation *endOperation = startOperation;
387c79227caSMarcel Koester   for (Operation *useOp : value.getUsers()) {
388c79227caSMarcel Koester     // Find the associated operation in the current block (if any).
389c79227caSMarcel Koester     useOp = block->findAncestorOpInBlock(*useOp);
390c79227caSMarcel Koester     // Check whether the use is in our block and after the current end
391c79227caSMarcel Koester     // operation.
392c79227caSMarcel Koester     if (useOp && endOperation->isBeforeInBlock(useOp))
393c79227caSMarcel Koester       endOperation = useOp;
3944b0198acSAlexander Belyaev   }
3954b0198acSAlexander Belyaev   return endOperation;
3964b0198acSAlexander Belyaev }
397f382dfc0Sbzcheeseman 
398f382dfc0Sbzcheeseman /// Return the values that are currently live as of the given operation.
399f382dfc0Sbzcheeseman LivenessBlockInfo::ValueSetT
currentlyLiveValues(Operation * op) const400f382dfc0Sbzcheeseman LivenessBlockInfo::currentlyLiveValues(Operation *op) const {
401f382dfc0Sbzcheeseman   ValueSetT liveSet;
402f382dfc0Sbzcheeseman 
403f382dfc0Sbzcheeseman   // Given a value, check which ops are within its live range. For each of
404f382dfc0Sbzcheeseman   // those ops, add the value to the set of live values as-of that op.
405f382dfc0Sbzcheeseman   auto addValueToCurrentlyLiveSets = [&](Value value) {
406f382dfc0Sbzcheeseman     // Determine the live range of this value inside this block.
407f382dfc0Sbzcheeseman     Operation *startOfLiveRange = value.getDefiningOp();
408f382dfc0Sbzcheeseman     Operation *endOfLiveRange = nullptr;
409f382dfc0Sbzcheeseman     // If it's a live in or a block argument, then the start is the beginning
410f382dfc0Sbzcheeseman     // of the block.
4115550c821STres Popp     if (isLiveIn(value) || isa<BlockArgument>(value))
412f382dfc0Sbzcheeseman       startOfLiveRange = &block->front();
413f382dfc0Sbzcheeseman     else
414f382dfc0Sbzcheeseman       startOfLiveRange = block->findAncestorOpInBlock(*startOfLiveRange);
415f382dfc0Sbzcheeseman 
416f382dfc0Sbzcheeseman     // If it's a live out, then the end is the back of the block.
417f382dfc0Sbzcheeseman     if (isLiveOut(value))
418f382dfc0Sbzcheeseman       endOfLiveRange = &block->back();
419f382dfc0Sbzcheeseman 
420f382dfc0Sbzcheeseman     // We must have at least a startOfLiveRange at this point. Given this, we
421f382dfc0Sbzcheeseman     // can use the existing getEndOperation to find the end of the live range.
422f382dfc0Sbzcheeseman     if (startOfLiveRange && !endOfLiveRange)
423f382dfc0Sbzcheeseman       endOfLiveRange = getEndOperation(value, startOfLiveRange);
424f382dfc0Sbzcheeseman 
425f382dfc0Sbzcheeseman     assert(endOfLiveRange && "Must have endOfLiveRange at this point!");
426f382dfc0Sbzcheeseman     // If this op is within the live range, insert the value into the set.
427f382dfc0Sbzcheeseman     if (!(op->isBeforeInBlock(startOfLiveRange) ||
428f382dfc0Sbzcheeseman           endOfLiveRange->isBeforeInBlock(op)))
429f382dfc0Sbzcheeseman       liveSet.insert(value);
430f382dfc0Sbzcheeseman   };
431f382dfc0Sbzcheeseman 
432f382dfc0Sbzcheeseman   // Handle block arguments if any.
433f382dfc0Sbzcheeseman   for (Value arg : block->getArguments())
434f382dfc0Sbzcheeseman     addValueToCurrentlyLiveSets(arg);
435f382dfc0Sbzcheeseman 
436f382dfc0Sbzcheeseman   // Handle live-ins. Between the live ins and all the op results that gives us
437f382dfc0Sbzcheeseman   // every value in the block.
438f382dfc0Sbzcheeseman   for (Value in : inValues)
439f382dfc0Sbzcheeseman     addValueToCurrentlyLiveSets(in);
440f382dfc0Sbzcheeseman 
441f382dfc0Sbzcheeseman   // Now walk the block and handle all values used in the block and values
442f382dfc0Sbzcheeseman   // defined by the block.
443f382dfc0Sbzcheeseman   for (Operation &walkOp :
444f382dfc0Sbzcheeseman        llvm::make_range(block->begin(), ++op->getIterator()))
445f382dfc0Sbzcheeseman     for (auto result : walkOp.getResults())
446f382dfc0Sbzcheeseman       addValueToCurrentlyLiveSets(result);
447f382dfc0Sbzcheeseman 
448f382dfc0Sbzcheeseman   return liveSet;
449f382dfc0Sbzcheeseman }
450