21#include <mlir/Analysis/DataFlowFramework.h>
22#include <mlir/Dialect/Arith/IR/Arith.h>
23#include <mlir/Pass/AnalysisManager.h>
25#include <llvm/ADT/EquivalenceClasses.h>
27#include <unordered_set>
36 using IndexRange = std::pair<mlir::APInt, mlir::APInt>;
47 return std::holds_alternative<SymbolLookupResult<component::FieldDefOp>>(index) ||
48 std::holds_alternative<component::FieldDefOp>(index);
51 ensure(
isField(),
"ConstrainRefIndex: field requested but not contained");
52 if (std::holds_alternative<component::FieldDefOp>(index)) {
53 return std::get<component::FieldDefOp>(index);
55 return std::get<SymbolLookupResult<component::FieldDefOp>>(index).get();
58 bool isIndex()
const {
return std::holds_alternative<mlir::APInt>(index); }
60 ensure(
isIndex(),
"ConstrainRefIndex: index requested but not contained");
61 return std::get<mlir::APInt>(index);
64 bool isIndexRange()
const {
return std::holds_alternative<IndexRange>(index); }
67 return std::get<IndexRange>(index);
71 void print(mlir::raw_ostream &os)
const;
82 return index == rhs.index;
107static inline mlir::raw_ostream &
operator<<(mlir::raw_ostream &os,
const ConstrainRefIndex &rhs) {
125 static std::vector<ConstrainRef>
129 static std::vector<ConstrainRef>
134 static std::vector<ConstrainRef>
137 explicit ConstrainRef(mlir::BlockArgument b) : root(b), fieldRefs(), constantVal(std::nullopt) {}
139 : root(b), fieldRefs(std::move(f)), constantVal(std::nullopt) {}
142 : root(createOp), fieldRefs(), constantVal(std::nullopt) {}
144 : root(createOp), fieldRefs(std::move(f)), constantVal(std::nullopt) {}
148 : root(std::nullopt), fieldRefs(), constantVal(c) {}
150 : root(std::nullopt), fieldRefs(), constantVal(c) {}
155 return constantVal.has_value() && std::holds_alternative<felt::FeltConstantOp>(*constantVal);
158 return constantVal.has_value() &&
159 std::holds_alternative<mlir::arith::ConstantIndexOp>(*constantVal);
162 return constantVal.has_value() &&
163 std::holds_alternative<polymorphic::ConstReadOp>(*constantVal);
178 return root.has_value() && std::holds_alternative<mlir::BlockArgument>(*root);
182 return std::get<mlir::BlockArgument>(*root);
187 return root.has_value() && std::holds_alternative<component::CreateStructOp>(*root);
191 return std::get<component::CreateStructOp>(*root);
196 return std::get<felt::FeltConstantOp>(*constantVal).getValueAttr().getValue();
200 return toAPInt(std::get<mlir::arith::ConstantIndexOp>(*constantVal).value());
205 __FUNCTION__ + mlir::Twine(
" requires a constant int type!")
225 mlir::FailureOr<ConstrainRef>
231 return mlir::failure();
234 copy.fieldRefs.pop_back();
239 std::vector<ConstrainRef>
244 copy.fieldRefs.push_back(r);
253 const std::vector<ConstrainRefIndex> &
getPieces()
const {
return fieldRefs; }
255 void print(mlir::raw_ostream &os)
const;
281 std::optional<std::variant<mlir::BlockArgument, component::CreateStructOp>> root;
283 std::vector<ConstrainRefIndex> fieldRefs;
285 mutable std::optional<
286 std::variant<felt::FeltConstantOp, mlir::arith::ConstantIndexOp, polymorphic::ConstReadOp>>
295 using Base = std::unordered_set<ConstrainRef, ConstrainRef::Hash>;
307 "ConstrainRefSet must satisfy the ScalarLatticeValue requirements"
314template <>
struct DenseMapInfo<
llzk::ConstrainRef> {
316 return llzk::ConstrainRef(mlir::BlockArgument(
reinterpret_cast<mlir::detail::ValueImpl *
>(1)));
319 return llzk::ConstrainRef(mlir::BlockArgument(
reinterpret_cast<mlir::detail::ValueImpl *
>(2)));
This file defines helpers for manipulating APInts/APSInts for large numbers and operations over those...
Defines an index into an LLZK object.
component::FieldDefOp getField() const
void print(mlir::raw_ostream &os) const
bool isIndexRange() const
ConstrainRefIndex(int64_t i)
ConstrainRefIndex(mlir::APInt i)
bool operator<(const ConstrainRefIndex &rhs) const
bool operator==(const ConstrainRefIndex &rhs) const
ConstrainRefIndex(SymbolLookupResult< component::FieldDefOp > f)
ConstrainRefIndex(component::FieldDefOp f)
IndexRange getIndexRange() const
mlir::APInt getIndex() const
ConstrainRefIndex(IndexRange r)
ConstrainRefIndex(mlir::APInt low, mlir::APInt high)
bool operator>(const ConstrainRefIndex &rhs) const
ConstrainRefSet & join(const ConstrainRefSet &rhs)
friend mlir::raw_ostream & operator<<(mlir::raw_ostream &os, const ConstrainRefSet &rhs)
Defines a reference to a llzk object within a constrain function call.
mlir::APInt getConstantFeltValue() const
bool isTypeVarVal() const
const std::vector< ConstrainRefIndex > & getPieces() const
bool operator<(const ConstrainRef &rhs) const
component::CreateStructOp getCreateStructOp() const
ConstrainRef(felt::FeltConstantOp c)
bool isValidPrefix(const ConstrainRef &prefix) const
Returns true iff prefix is a valid prefix of this reference.
bool isIntegerVal() const
void print(mlir::raw_ostream &os) const
bool isConstantFelt() const
ConstrainRef createChild(ConstrainRef other) const
ConstrainRef(polymorphic::ConstReadOp c)
bool isTemplateConstant() const
ConstrainRef(mlir::BlockArgument b, std::vector< ConstrainRefIndex > f)
mlir::APInt getConstantIndexValue() const
bool isConstantIndex() const
mlir::Type getType() const
std::vector< ConstrainRef > getAllChildren(mlir::SymbolTableCollection &tables, mlir::ModuleOp mod) const
Get all direct children of this ConstrainRef, assuming this ref is not a scalar.
ConstrainRef(mlir::BlockArgument b)
mlir::FailureOr< std::vector< ConstrainRefIndex > > getSuffix(const ConstrainRef &prefix) const
If prefix is a valid prefix of this reference, return the suffix that remains after removing the pref...
bool operator==(const ConstrainRef &rhs) const
mlir::FailureOr< ConstrainRef > getParentPrefix() const
Create a new reference that is the immediate prefix of this reference if possible.
ConstrainRef(mlir::arith::ConstantIndexOp c)
bool isBlockArgument() const
ConstrainRef(component::CreateStructOp createOp, std::vector< ConstrainRefIndex > f)
mlir::FailureOr< ConstrainRef > translate(const ConstrainRef &prefix, const ConstrainRef &other) const
Create a new reference with prefix replaced with other iff prefix is a valid prefix for this referenc...
mlir::BlockArgument getBlockArgument() const
ConstrainRef createChild(ConstrainRefIndex r) const
ConstrainRef(component::CreateStructOp createOp)
bool operator!=(const ConstrainRef &rhs) const
bool isCreateStructOp() const
static std::vector< ConstrainRef > getAllConstrainRefs(mlir::SymbolTableCollection &tables, mlir::ModuleOp mod, ConstrainRef root)
Produce all possible ConstraintRefs that are present starting from the given root.
bool isConstantInt() const
mlir::APInt getConstantValue() const
bool operator>(const ConstrainRef &rhs) const
unsigned getInputNum() const
llvm::APInt toAPInt(int64_t i)
void ensure(bool condition, llvm::Twine errMsg)
bool safeEq(const llvm::APSInt &lhs, const llvm::APSInt &rhs)
raw_ostream & operator<<(raw_ostream &os, const ConstrainRef &rhs)
bool isSignalType(Type type)
ExpressionValue mod(llvm::SMTSolverRef solver, const ExpressionValue &lhs, const ExpressionValue &rhs)
static bool isEqual(const llzk::ConstrainRef &lhs, const llzk::ConstrainRef &rhs)
static llzk::ConstrainRef getTombstoneKey()
static llzk::ConstrainRef getEmptyKey()
static unsigned getHashValue(const llzk::ConstrainRef &ref)
size_t operator()(const ConstrainRefIndex &c) const
size_t operator()(const ConstrainRef &val) const