22#include <mlir/IR/AsmState.h>
24#include <llvm/ADT/STLExtras.h>
25#include <llvm/ADT/SmallVector.h>
26#include <llvm/Support/Debug.h>
27#include <llvm/Support/ErrorHandling.h>
30#define GEN_PASS_DEF_INTERVALANALYSISPRINTERPASS
34#define DEBUG_TYPE "llzk-interval-analysis-pass"
44 using Base = IntervalAnalysisPrinterPassBase<PassImpl>;
47 void runOnOperation()
override {
48 markAllAnalysesPreserved();
52 auto modOp = llvm::dyn_cast<ModuleOp>(getOperation());
54 constexpr const char *msg =
"IntervalAnalysisPrinterPass error: should be run on ModuleOp!";
55 getOperation()->emitError(msg).report();
61 if (!fieldName.empty()) {
63 if (failed(fieldLookupRes)) {
66 "IntervalAnalysisPrinterPass error: unknown field \"", fieldName,
"\" specified"
71 selectedField = fieldLookupRes.value();
73 llvm::dbgs() <<
"[IntervalAnalysisPrinterPass] using explicit -field override '"
74 << selectedField.get().name() <<
"'\n";
77 selectedField = detectedField.value();
79 llvm::dbgs() <<
"[IntervalAnalysisPrinterPass] detected module field '"
80 << selectedField.get().name() <<
"' from module felt usage\n";
83 modOp->emitWarning() <<
"could not detect a unique module field; falling back to '"
84 << selectedField.get().name() <<
'\'';
86 llvm::dbgs() <<
"[IntervalAnalysisPrinterPass] no explicit or detectable module field; "
88 << selectedField.get().name() <<
"'\n";
92 auto &mia = getAnalysis<ModuleIntervalAnalysis>();
93 mia.setField(selectedField);
94 mia.setPropagateInputConstraints(propagateInputConstraints);
95 mia.setTrackUnreducedIntervals(printUnreducedIntervals);
96 auto am = getAnalysisManager();
97 mia.ensureAnalysisRun(am);
98 AsmState asmState(modOp);
100 auto printValueInterval = [
this, &asmState, &mia](raw_ostream &out,
int indent, Value value) {
101 if (llvm::isa<llzk::array::ArrayType, StructType>(value.getType())) {
111 value.printAsOperand(out, asmState);
112 if (
auto opResult = llvm::dyn_cast<OpResult>(value)) {
113 out <<
" [" << opResult.getOwner()->getName().getStringRef() <<
"]";
121 auto printFunctionSSAIntervals =
122 [&printValueInterval](raw_ostream &out,
FuncDefOp fn, llvm::StringRef fnName) {
128 out.indent(4) << fnName <<
" {";
129 for (BlockArgument arg : fn.getArguments()) {
130 printValueInterval(out, 8, arg);
132 fn.walk([&](Operation *op) {
133 if (op == fn.getOperation()) {
136 for (Value result : op->getResults()) {
137 printValueInterval(out, 8, result);
141 out.indent(4) <<
'}';
145 for (
const auto &[s, si] : mia.getCurrentResults()) {
150 "could not resolve fully qualified name of struct " + Twine(structDef.getName())
152 os << fullName.value() <<
' ';
153 si.get().print(os, printSolverConstraints, printComputeIntervals, printUnreducedIntervals);
154 if (printSSAIntervals) {
155 os << fullName.value() <<
" SSAIntervals {";
156 if (printComputeIntervals) {
160 if (
auto productFn = structDef.getProductFuncOp();
161 productFn && (!structDef.getConstrainFuncOp() || printComputeIntervals)) {
Tracks a solver expression and an interval range for that expression.
const Interval & getInterval() const
bool hasUnreducedInterval() const
const UnreducedInterval & getUnreducedInterval() const
static llvm::FailureOr< std::reference_wrapper< const Field > > tryGetField(llvm::StringRef fieldName)
Get a Field from a given field name string, or failure if the field is not defined.
static const Field & getField(llvm::StringRef fieldName, EmitErrorFn errFn)
Get a Field from a given field name string.
constexpr char FUNC_NAME_COMPUTE[]
Symbol name for the witness generation (and resp.
std::reference_wrapper< const Field > FieldRef
Typealias for a stable reference to a known Field.
constexpr char FUNC_NAME_CONSTRAIN[]
llvm::raw_ostream & toStream(OutputStream val)
void ensure(bool condition, const llvm::Twine &errMsg)
constexpr char FUNC_NAME_PRODUCT[]
FailureOr< SymbolRefAttr > getPathFromTopRoot(SymbolOpInterface to, ModuleOp *foundRoot)
std::optional< std::reference_wrapper< const Field > > tryDetectSpecifiedField(mlir::Operation *root)
Try to detect a uniquely used field from the enclosing LLZK module.