1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130
|
//===- TestDeadCodeAnalysis.cpp - Test dead code 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/Analysis/DataFlow/ConstantPropagationAnalysis.h"
#include "mlir/Analysis/DataFlow/DeadCodeAnalysis.h"
#include "mlir/IR/Matchers.h"
#include "mlir/Pass/Pass.h"
using namespace mlir;
using namespace mlir::dataflow;
/// Print the liveness of every block, control-flow edge, and the predecessors
/// of all regions, callables, and calls.
static void printAnalysisResults(DataFlowSolver &solver, Operation *op,
raw_ostream &os) {
op->walk([&](Operation *op) {
auto tag = op->getAttrOfType<StringAttr>("tag");
if (!tag)
return;
os << tag.getValue() << ":\n";
for (Region ®ion : op->getRegions()) {
os << " region #" << region.getRegionNumber() << "\n";
for (Block &block : region) {
os << " ";
block.printAsOperand(os);
os << " = ";
auto *live = solver.lookupState<Executable>(&block);
if (live)
os << *live;
else
os << "dead";
os << "\n";
for (Block *pred : block.getPredecessors()) {
os << " from ";
pred->printAsOperand(os);
os << " = ";
auto *live = solver.lookupState<Executable>(
solver.getProgramPoint<CFGEdge>(pred, &block));
if (live)
os << *live;
else
os << "dead";
os << "\n";
}
}
if (!region.empty()) {
auto *preds = solver.lookupState<PredecessorState>(®ion.front());
if (preds)
os << "region_preds: " << *preds << "\n";
}
}
auto *preds = solver.lookupState<PredecessorState>(op);
if (preds)
os << "op_preds: " << *preds << "\n";
});
}
namespace {
/// This is a simple analysis that implements a transfer function for constant
/// operations.
struct ConstantAnalysis : public DataFlowAnalysis {
using DataFlowAnalysis::DataFlowAnalysis;
LogicalResult initialize(Operation *top) override {
WalkResult result = top->walk([&](Operation *op) {
if (failed(visit(op)))
return WalkResult::interrupt();
return WalkResult::advance();
});
return success(!result.wasInterrupted());
}
LogicalResult visit(ProgramPoint point) override {
Operation *op = point.get<Operation *>();
Attribute value;
if (matchPattern(op, m_Constant(&value))) {
auto *constant = getOrCreate<Lattice<ConstantValue>>(op->getResult(0));
propagateIfChanged(
constant, constant->join(ConstantValue(value, op->getDialect())));
return success();
}
setAllToUnknownConstants(op->getResults());
for (Region ®ion : op->getRegions())
setAllToUnknownConstants(region.getArguments());
return success();
}
/// Set all given values as not constants.
void setAllToUnknownConstants(ValueRange values) {
for (Value value : values) {
auto *constant = getOrCreate<Lattice<ConstantValue>>(value);
propagateIfChanged(constant,
constant->join(ConstantValue::getUnknownConstant()));
}
}
};
/// This is a simple pass that runs dead code analysis with a constant value
/// provider that only understands constant operations.
struct TestDeadCodeAnalysisPass
: public PassWrapper<TestDeadCodeAnalysisPass, OperationPass<>> {
MLIR_DEFINE_EXPLICIT_INTERNAL_INLINE_TYPE_ID(TestDeadCodeAnalysisPass)
StringRef getArgument() const override { return "test-dead-code-analysis"; }
void runOnOperation() override {
Operation *op = getOperation();
DataFlowSolver solver;
solver.load<DeadCodeAnalysis>();
solver.load<ConstantAnalysis>();
if (failed(solver.initializeAndRun(op)))
return signalPassFailure();
printAnalysisResults(solver, op, llvm::errs());
}
};
} // end anonymous namespace
namespace mlir {
namespace test {
void registerTestDeadCodeAnalysisPass() {
PassRegistration<TestDeadCodeAnalysisPass>();
}
} // end namespace test
} // end namespace mlir
|