Enzyme main
Loading...
Searching...
No Matches
PrintAliasAnalysis.cpp
Go to the documentation of this file.
1//===- PrintAliasAnalysis.cpp - Pass to print alias analysis --------------===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8//
9// This file implements a pass to print the results of running alias
10// analysis.
11//
12//===----------------------------------------------------------------------===//
13
15#include "Dialect/Ops.h"
16#include "Passes/PassDetails.h"
17#include "Passes/Passes.h"
18
19#include "mlir/Analysis/DataFlow/ConstantPropagationAnalysis.h"
20#include "mlir/Analysis/DataFlow/DeadCodeAnalysis.h"
21#include "mlir/Interfaces/FunctionInterfaces.h"
22
23using namespace mlir;
24using namespace mlir::enzyme;
25
26namespace mlir {
27namespace enzyme {
28#define GEN_PASS_DEF_PRINTALIASANALYSISPASS
29#include "Passes/Passes.h.inc"
30} // namespace enzyme
31} // namespace mlir
32
33namespace {
34
35struct PrintAliasAnalysisPass
36 : public enzyme::impl::PrintAliasAnalysisPassBase<PrintAliasAnalysisPass> {
37
38 void runOnOperation() override {
39 DataFlowSolver solver;
40
41 solver.load<enzyme::AliasAnalysis>(&getContext());
43 solver.load<dataflow::DeadCodeAnalysis>();
44 solver.load<dataflow::SparseConstantPropagation>();
45
46 if (failed(solver.initializeAndRun(getOperation()))) {
47 return signalPassFailure();
48 }
49 raw_ostream &os = llvm::outs();
50
51 SmallVector<std::pair<Attribute, Value>> taggedPointers;
52 getOperation()->walk([&](FunctionOpInterface funcOp) {
53 for (auto arg : funcOp.getArguments()) {
54 if (funcOp.getArgAttr(arg.getArgNumber(), "enzyme.tag")) {
55 taggedPointers.push_back(
56 {funcOp.getArgAttr(arg.getArgNumber(), "enzyme.tag"), arg});
57 }
58 }
59
60 funcOp.walk([&](Operation *op) {
61 if (op->hasAttr("tag")) {
62 for (OpResult result : op->getResults()) {
63 taggedPointers.push_back({op->getAttr("tag"), result});
64 }
65 }
66 });
67 });
68
69 for (const auto &[tag, value] : taggedPointers) {
70 const auto *state = solver.lookupState<enzyme::AliasClassLattice>(value);
71 if (state) {
72 os << "tag " << tag << " " << *state << "\n";
73 }
74 }
75
76 if (taggedPointers.empty())
77 return;
78
79 // Compare all tagged pointers
80 for (unsigned i = 0; i < taggedPointers.size() - 1; i++) {
81 for (unsigned j = i + 1; j < taggedPointers.size(); j++) {
82 const auto &[tagA, a] = taggedPointers[i];
83 const auto &[tagB, b] = taggedPointers[j];
84
85 const auto *lhs = solver.lookupState<enzyme::AliasClassLattice>(a);
86 const auto *rhs = solver.lookupState<enzyme::AliasClassLattice>(b);
87 if (!(lhs && rhs))
88 continue;
89
90 os << tagA << " and " << tagB << ": " << lhs->alias(*rhs) << "\n";
91 }
92 }
93
94 getOperation()->walk([&solver, &os](Operation *op) {
95 if (auto funcOp = dyn_cast<FunctionOpInterface>(op)) {
96 for (auto arg : funcOp.getArguments()) {
97 auto *state = solver.lookupState<enzyme::AliasClassLattice>(arg);
98 if (!state)
99 continue;
100 // TODO(zinenko): this has been overriding the argument...
101 // Use an array attr instead (will break syntactic tests).
103 [&](DistinctAttr aliasClass, enzyme::AliasClassSet::State state) {
104 if (state == enzyme::AliasClassSet::State::Undefined)
105 funcOp.setArgAttr(
106 arg.getArgNumber(), "enzyme.ac",
107 StringAttr::get(arg.getContext(), "undefined"));
108 else if (state == enzyme::AliasClassSet::State::Unknown)
109 funcOp.setArgAttr(
110 arg.getArgNumber(), "enzyme.ac",
111 StringAttr::get(arg.getContext(), "unknown"));
112 else
113 funcOp.setArgAttr(arg.getArgNumber(), "enzyme.ac",
114 aliasClass);
115 return ChangeResult::NoChange;
116 });
117 }
118 } else if (op->hasTrait<OpTrait::ReturnLike>() &&
119 isa<FunctionOpInterface>(op->getParentOp())) {
120 os << "points-to-pointer sets for op @" << op->getLoc() << ":\n";
121 if (auto *state = solver.lookupState<enzyme::PointsToSets>(
122 solver.getProgramPointBefore(op)))
123 os << *state << "\n";
124 else
125 os << "NOT computed\n";
126 }
127 if (op->hasAttr("tag")) {
128 for (OpResult result : op->getResults()) {
129 auto *state = solver.lookupState<enzyme::AliasClassLattice>(result);
130 if (state) {
131 if (state->isUnknown()) {
132 op->setAttr("ac",
133 StringAttr::get(result.getContext(), "<unknown>"));
134 } else if (state->isUndefined()) {
135 op->setAttr("ac",
136 StringAttr::get(result.getContext(), "<undefined>"));
137 } else {
138 for (auto aliasClass : state->getAliasClasses()) {
139 op->setAttr("ac", aliasClass);
140 }
141 }
142 }
143 }
144 }
145 });
146 }
147};
148} // namespace
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