20#include "mlir/Analysis/DataFlow/ConstantPropagationAnalysis.h"
21#include "mlir/Analysis/DataFlow/DeadCodeAnalysis.h"
22#include "mlir/Interfaces/FunctionInterfaces.h"
29#define GEN_PASS_DEF_PRINTALIASANALYSISPASS
30#include "Passes/Passes.h.inc"
36struct PrintAliasAnalysisPass
37 :
public enzyme::impl::PrintAliasAnalysisPassBase<PrintAliasAnalysisPass> {
39 void runOnOperation()
override {
40 DataFlowSolver solver;
44 solver.load<dataflow::DeadCodeAnalysis>();
45 solver.load<dataflow::SparseConstantPropagation>();
47 if (failed(solver.initializeAndRun(getOperation()))) {
48 return signalPassFailure();
50 raw_ostream &os = llvm::outs();
52 SmallVector<std::pair<Attribute, Value>> taggedPointers;
53 getOperation()->walk([&](FunctionOpInterface funcOp) {
54 for (
auto arg : funcOp.getArguments()) {
55 if (funcOp.getArgAttr(arg.getArgNumber(),
"enzyme.tag")) {
56 taggedPointers.push_back(
57 {funcOp.getArgAttr(arg.getArgNumber(),
"enzyme.tag"), arg});
61 funcOp.walk([&](Operation *op) {
62 if (op->hasAttr(
"tag")) {
63 for (OpResult result : op->getResults()) {
64 taggedPointers.push_back({op->getAttr(
"tag"), result});
70 for (
const auto &[tag, value] : taggedPointers) {
73 os <<
"tag " << tag <<
" " << *state <<
"\n";
77 if (taggedPointers.empty())
81 for (
unsigned i = 0; i < taggedPointers.size() - 1; i++) {
82 for (
unsigned j = i + 1; j < taggedPointers.size(); j++) {
83 const auto &[tagA, a] = taggedPointers[i];
84 const auto &[tagB, b] = taggedPointers[j];
91 os << tagA <<
" and " << tagB <<
": " << lhs->
alias(*rhs) <<
"\n";
95 getOperation()->walk([&solver, &os](Operation *op) {
96 if (
auto funcOp = dyn_cast<FunctionOpInterface>(op)) {
97 for (
auto arg : funcOp.getArguments()) {
105 if (state == enzyme::AliasClassSet::State::Undefined)
107 arg.getArgNumber(),
"enzyme.ac",
108 StringAttr::get(arg.getContext(),
"undefined"));
109 else if (state == enzyme::AliasClassSet::State::Unknown)
111 arg.getArgNumber(),
"enzyme.ac",
112 StringAttr::get(arg.getContext(),
"unknown"));
114 funcOp.setArgAttr(arg.getArgNumber(),
"enzyme.ac",
116 return ChangeResult::NoChange;
120 isa<FunctionOpInterface>(op->getParentOp())) {
121 os <<
"points-to-pointer sets for op @" << op->getLoc() <<
":\n";
123 solver.getProgramPointBefore(op)))
124 os << *state <<
"\n";
126 os <<
"NOT computed\n";
128 if (op->hasAttr(
"tag")) {
129 for (OpResult result : op->getResults()) {
132 if (state->isUnknown()) {
134 StringAttr::get(result.getContext(),
"<unknown>"));
135 }
else if (state->isUndefined()) {
137 StringAttr::get(result.getContext(),
"<undefined>"));
139 for (
auto aliasClass : state->getAliasClasses()) {
140 op->setAttr(
"ac", aliasClass);
This analysis implements interprocedural alias analysis.
const AliasClassSet & getAliasClassesObject() const
::mlir::AliasResult alias(const AbstractSparseLattice &other) const
ChangeResult foreachElement(function_ref< ChangeResult(ValueT, State)> callback) const
bool isFunctionReturnLike(Operation *op)