blob: 8c32a0ffda7e2f3a9d720a6b5b2aac1c37b726ef [file] [log] [blame]
//===- Liveness.h - Liveness analysis for MLIR ------------------*- C++ -*-===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
// This file contains an analysis for computing liveness information from a
// given top-level operation. The current version of the analysis uses a
// traditional algorithm to resolve detailed live-range information about all
// values within the specified regions. It is also possible to query liveness
// information on block level.
//
//===----------------------------------------------------------------------===//
#ifndef MLIR_ANALYSIS_LIVENESS_H
#define MLIR_ANALYSIS_LIVENESS_H
#include <vector>
#include "mlir/Support/LLVM.h"
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/SmallPtrSet.h"
namespace mlir {
class Block;
class LivenessBlockInfo;
class Operation;
class Region;
class Value;
/// Represents an analysis for computing liveness information from a
/// given top-level operation. The analysis iterates over all associated
/// regions that are attached to the given top-level operation. It
/// computes liveness information for every value and block that are
/// included in the mentioned regions. It relies on a fixpoint iteration
/// to compute all live-in and live-out values of all included blocks.
/// Sample usage:
/// Liveness liveness(topLevelOp);
/// auto &allInValues = liveness.getLiveIn(block);
/// auto &allOutValues = liveness.getLiveOut(block);
/// auto allOperationsInWhichValueIsLive = liveness.resolveLiveness(value);
/// bool isDeafAfter = liveness.isDeadAfter(value, operation);
class Liveness {
public:
using OperationListT = std::vector<Operation *>;
using BlockMapT = DenseMap<Block *, LivenessBlockInfo>;
using ValueSetT = SmallPtrSet<Value, 16>;
public:
/// Creates a new Liveness analysis that computes liveness
/// information for all associated regions.
Liveness(Operation *op);
/// Returns the operation this analysis was constructed from.
Operation *getOperation() const { return operation; }
/// Gets liveness info (if any) for the given value.
/// This includes all operations in which the given value is live.
/// Note that the operations in this list are not ordered and the current
/// implementation is computationally expensive (as it iterates over all
/// blocks in which the given value is live).
OperationListT resolveLiveness(Value value) const;
/// Gets liveness info (if any) for the block.
const LivenessBlockInfo *getLiveness(Block *block) const;
/// Returns a reference to a set containing live-in values (unordered).
const ValueSetT &getLiveIn(Block *block) const;
/// Returns a reference to a set containing live-out values (unordered).
const ValueSetT &getLiveOut(Block *block) const;
/// Returns true if `value` is not live after `operation`.
bool isDeadAfter(Value value, Operation *operation) const;
/// Dumps the liveness information in a human readable format.
void dump() const;
/// Dumps the liveness information to the given stream.
void print(raw_ostream &os) const;
private:
/// Initializes the internal mappings.
void build();
private:
/// The operation this analysis was constructed from.
Operation *operation;
/// Maps blocks to internal liveness information.
BlockMapT blockMapping;
};
/// This class represents liveness information on block level.
class LivenessBlockInfo {
public:
/// A typedef declaration of a value set.
using ValueSetT = Liveness::ValueSetT;
public:
/// Returns the underlying block.
Block *getBlock() const { return block; }
/// Returns all values that are live at the beginning
/// of the block (unordered).
const ValueSetT &in() const { return inValues; }
/// Returns all values that are live at the end
/// of the block (unordered).
const ValueSetT &out() const { return outValues; }
/// Returns true if the given value is in the live-in set.
bool isLiveIn(Value value) const;
/// Returns true if the given value is in the live-out set.
bool isLiveOut(Value value) const;
/// Gets the start operation for the given value. This is the first operation
/// the given value is considered to be live. This could either be the start
/// operation of the current block (in case the value is live-in) or the
/// operation that defines the given value (must be referenced in this block).
Operation *getStartOperation(Value value) const;
/// Gets the end operation for the given value using the start operation
/// provided (must be referenced in this block).
Operation *getEndOperation(Value value, Operation *startOperation) const;
private:
/// The underlying block.
Block *block;
/// The set of all live in values.
ValueSetT inValues;
/// The set of all live out values.
ValueSetT outValues;
friend class Liveness;
};
} // end namespace mlir
#endif // MLIR_ANALYSIS_LIVENESS_H