//===- LivenessAnalysis.cpp - Liveness analysis ---------------------------===// // // 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 // //===----------------------------------------------------------------------===// #include "mlir/IR/SymbolTable.h" #include <cassert> #include <mlir/Analysis/DataFlow/LivenessAnalysis.h> #include <mlir/Analysis/DataFlow/ConstantPropagationAnalysis.h> #include <mlir/Analysis/DataFlow/DeadCodeAnalysis.h> #include <mlir/Analysis/DataFlow/SparseAnalysis.h> #include <mlir/Analysis/DataFlowFramework.h> #include <mlir/IR/Operation.h> #include <mlir/IR/Value.h> #include <mlir/Interfaces/CallInterfaces.h> #include <mlir/Interfaces/SideEffectInterfaces.h> #include <mlir/Support/LLVM.h> usingnamespacemlir; usingnamespacemlir::dataflow; //===----------------------------------------------------------------------===// // Liveness //===----------------------------------------------------------------------===// void Liveness::print(raw_ostream &os) const { … } ChangeResult Liveness::markLive() { … } ChangeResult Liveness::meet(const AbstractSparseLattice &other) { … } //===----------------------------------------------------------------------===// // LivenessAnalysis //===----------------------------------------------------------------------===// /// For every value, liveness analysis determines whether or not it is "live". /// /// A value is considered "live" iff it: /// (1) has memory effects OR /// (2) is returned by a public function OR /// (3) is used to compute a value of type (1) or (2). /// It is also to be noted that a value could be of multiple types (1/2/3) at /// the same time. /// /// A value "has memory effects" iff it: /// (1.a) is an operand of an op with memory effects OR /// (1.b) is a non-forwarded branch operand and its branch op could take the /// control to a block that has an op with memory effects OR /// (1.c) is a non-forwarded call operand. /// /// A value `A` is said to be "used to compute" value `B` iff `B` cannot be /// computed in the absence of `A`. Thus, in this implementation, we say that /// value `A` is used to compute value `B` iff: /// (3.a) `B` is a result of an op with operand `A` OR /// (3.b) `A` is used to compute some value `C` and `C` is used to compute /// `B`. LogicalResult LivenessAnalysis::visitOperation(Operation *op, ArrayRef<Liveness *> operands, ArrayRef<const Liveness *> results) { … } void LivenessAnalysis::visitBranchOperand(OpOperand &operand) { … } void LivenessAnalysis::visitCallOperand(OpOperand &operand) { … } void LivenessAnalysis::setToExitState(Liveness *lattice) { … } //===----------------------------------------------------------------------===// // RunLivenessAnalysis //===----------------------------------------------------------------------===// RunLivenessAnalysis::RunLivenessAnalysis(Operation *op) { … } const Liveness *RunLivenessAnalysis::getLiveness(Value val) { … }