159 lines
5.6 KiB
C++
159 lines
5.6 KiB
C++
//===- 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;
|
|
|
|
/// Get the set of values that are currently live (if any) for the current op.
|
|
/// This analysis takes an expansive view of "live" in that if a value is
|
|
/// defined by or within the operation or is fully consumed (as in last user)
|
|
/// by or within the operation the value is considered "live". The values in
|
|
/// the list are not ordered.
|
|
///
|
|
/// This check is quite expensive as it does not cache the results of the
|
|
/// computation, so the currently live values have to be recomputed for each
|
|
/// op.
|
|
ValueSetT currentlyLiveValues(Operation *op) const;
|
|
|
|
private:
|
|
/// The underlying block.
|
|
Block *block = nullptr;
|
|
|
|
/// The set of all live in values.
|
|
ValueSetT inValues;
|
|
|
|
/// The set of all live out values.
|
|
ValueSetT outValues;
|
|
|
|
friend class Liveness;
|
|
};
|
|
|
|
} // namespace mlir
|
|
|
|
#endif // MLIR_ANALYSIS_LIVENESS_H
|