21#include <mlir/Analysis/DataFlowFramework.h>
22#include <mlir/Dialect/Arith/IR/Arith.h>
23#include <mlir/Pass/AnalysisManager.h>
25#include <llvm/ADT/DynamicAPInt.h>
26#include <llvm/ADT/EquivalenceClasses.h>
28#include <unordered_set>
37 using IndexRange = std::pair<llvm::DynamicAPInt, llvm::DynamicAPInt>;
50 return std::holds_alternative<SymbolLookupResult<component::FieldDefOp>>(index) ||
51 std::holds_alternative<component::FieldDefOp>(index);
54 ensure(
isField(),
"SourceRefIndex: field requested but not contained");
55 if (std::holds_alternative<component::FieldDefOp>(index)) {
56 return std::get<component::FieldDefOp>(index);
58 return std::get<SymbolLookupResult<component::FieldDefOp>>(index).get();
61 bool isIndex()
const {
return std::holds_alternative<llvm::DynamicAPInt>(index); }
63 ensure(
isIndex(),
"SourceRefIndex: index requested but not contained");
64 return std::get<llvm::DynamicAPInt>(index);
67 bool isIndexRange()
const {
return std::holds_alternative<IndexRange>(index); }
70 return std::get<IndexRange>(index);
74 void print(mlir::raw_ostream &os)
const;
85 return index == rhs.index;
111static inline mlir::raw_ostream &
operator<<(mlir::raw_ostream &os,
const SourceRefIndex &rhs) {
131 static std::vector<SourceRef>
135 static std::vector<SourceRef>
140 static std::vector<SourceRef>
143 explicit SourceRef(mlir::BlockArgument b) : root(b), fieldRefs(), constantVal(std::nullopt) {}
144 SourceRef(mlir::BlockArgument b, std::vector<SourceRefIndex> f)
145 : root(b), fieldRefs(std::move(f)), constantVal(std::nullopt) {}
148 : root(createOp), fieldRefs(), constantVal(std::nullopt) {}
150 : root(createOp), fieldRefs(std::move(f)), constantVal(std::nullopt) {}
154 : root(std::nullopt), fieldRefs(), constantVal(c) {}
156 : root(std::nullopt), fieldRefs(), constantVal(c) {}
161 return constantVal.has_value() && std::holds_alternative<felt::FeltConstantOp>(*constantVal);
164 return constantVal.has_value() &&
165 std::holds_alternative<mlir::arith::ConstantIndexOp>(*constantVal);
168 return constantVal.has_value() &&
169 std::holds_alternative<polymorphic::ConstReadOp>(*constantVal);
184 return root.has_value() && std::holds_alternative<mlir::BlockArgument>(*root);
188 return std::get<mlir::BlockArgument>(*root);
193 return root.has_value() && std::holds_alternative<component::CreateStructOp>(*root);
197 return std::get<component::CreateStructOp>(*root);
202 isConstantFelt(), mlir::Twine(mlir::StringRef(__FUNCTION__),
" requires a constant felt!")
204 llvm::APInt i = std::get<felt::FeltConstantOp>(*constantVal).getValue();
209 isConstantIndex(), mlir::Twine(mlir::StringRef(__FUNCTION__),
" requires a constant index!")
211 return llvm::DynamicAPInt(std::get<mlir::arith::ConstantIndexOp>(*constantVal).value());
216 mlir::Twine(mlir::StringRef(__FUNCTION__),
" requires a constant int type!")
228 mlir::FailureOr<std::vector<SourceRefIndex>>
getSuffix(
const SourceRef &prefix)
const;
241 return mlir::failure();
244 copy.fieldRefs.pop_back();
249 std::vector<SourceRef>
254 copy.fieldRefs.push_back(r);
263 const std::vector<SourceRefIndex> &
getPieces()
const {
return fieldRefs; }
265 void print(mlir::raw_ostream &os)
const;
291 std::optional<std::variant<mlir::BlockArgument, component::CreateStructOp>> root;
293 std::vector<SourceRefIndex> fieldRefs;
295 mutable std::optional<
296 std::variant<felt::FeltConstantOp, mlir::arith::ConstantIndexOp, polymorphic::ConstReadOp>>
304class SourceRefSet :
public std::unordered_set<SourceRef, SourceRef::Hash> {
305 using Base = std::unordered_set<SourceRef, SourceRef::Hash>;
317 "SourceRefSet must satisfy the ScalarLatticeValue requirements"
324template <>
struct DenseMapInfo<
llzk::SourceRef> {
326 return llzk::SourceRef(mlir::BlockArgument(
reinterpret_cast<mlir::detail::ValueImpl *
>(1)));
329 return llzk::SourceRef(mlir::BlockArgument(
reinterpret_cast<mlir::detail::ValueImpl *
>(2)));
This file implements helper methods for constructing DynamicAPInts.
void print(llvm::raw_ostream &os) const
Defines an index into an LLZK object.
bool operator==(const SourceRefIndex &rhs) const
bool isIndexRange() const
bool operator<(const SourceRefIndex &rhs) const
bool operator>(const SourceRefIndex &rhs) const
component::FieldDefOp getField() const
SourceRefIndex(component::FieldDefOp f)
SourceRefIndex(const llvm::DynamicAPInt &i)
SourceRefIndex(SymbolLookupResult< component::FieldDefOp > f)
SourceRefIndex(const llvm::APInt &low, const llvm::APInt &high)
SourceRefIndex(const llvm::APInt &i)
llvm::DynamicAPInt getIndex() const
void print(mlir::raw_ostream &os) const
IndexRange getIndexRange() const
SourceRefIndex(IndexRange r)
SourceRefIndex(int64_t i)
SourceRefSet & join(const SourceRefSet &rhs)
friend mlir::raw_ostream & operator<<(mlir::raw_ostream &os, const SourceRefSet &rhs)
A reference to a "source", which is the base value from which other SSA values are derived.
SourceRef(component::CreateStructOp createOp, std::vector< SourceRefIndex > f)
bool isIntegerVal() const
bool isBlockArgument() const
llvm::DynamicAPInt getConstantIndexValue() const
std::vector< SourceRef > getAllChildren(mlir::SymbolTableCollection &tables, mlir::ModuleOp mod) const
Get all direct children of this SourceRef, assuming this ref is not a scalar.
SourceRef createChild(SourceRef other) const
mlir::FailureOr< SourceRef > getParentPrefix() const
Create a new reference that is the immediate prefix of this reference if possible.
void print(mlir::raw_ostream &os) const
mlir::FailureOr< std::vector< SourceRefIndex > > getSuffix(const SourceRef &prefix) const
If prefix is a valid prefix of this reference, return the suffix that remains after removing the pref...
bool operator==(const SourceRef &rhs) const
bool isConstantFelt() const
component::CreateStructOp getCreateStructOp() const
SourceRef(felt::FeltConstantOp c)
bool isValidPrefix(const SourceRef &prefix) const
Returns true iff prefix is a valid prefix of this reference.
const std::vector< SourceRefIndex > & getPieces() const
bool isConstantIndex() const
SourceRef createChild(SourceRefIndex r) const
mlir::BlockArgument getBlockArgument() const
llvm::DynamicAPInt getConstantValue() const
static std::vector< SourceRef > getAllSourceRefs(mlir::SymbolTableCollection &tables, mlir::ModuleOp mod, SourceRef root)
Produce all possible SourceRefs that are present starting from the given root.
SourceRef(mlir::arith::ConstantIndexOp c)
SourceRef(mlir::BlockArgument b, std::vector< SourceRefIndex > f)
bool operator<(const SourceRef &rhs) const
SourceRef(mlir::BlockArgument b)
mlir::FailureOr< SourceRef > translate(const SourceRef &prefix, const SourceRef &other) const
Create a new reference with prefix replaced with other iff prefix is a valid prefix for this referenc...
SourceRef(polymorphic::ConstReadOp c)
bool isTemplateConstant() const
bool isTypeVarVal() const
bool operator!=(const SourceRef &rhs) const
SourceRef(component::CreateStructOp createOp)
llvm::DynamicAPInt getConstantFeltValue() const
bool operator>(const SourceRef &rhs) const
unsigned getInputNum() const
bool isConstantInt() const
bool isCreateStructOp() const
mlir::Type getType() const
void ensure(bool condition, const llvm::Twine &errMsg)
DynamicAPInt toDynamicAPInt(StringRef str)
Interval operator<<(const Interval &lhs, const Interval &rhs)
bool isSignalType(Type type)
ExpressionValue mod(llvm::SMTSolverRef solver, const ExpressionValue &lhs, const ExpressionValue &rhs)
static bool isEqual(const llzk::SourceRef &lhs, const llzk::SourceRef &rhs)
static unsigned getHashValue(const llzk::SourceRef &ref)
static llzk::SourceRef getTombstoneKey()
static llzk::SourceRef getEmptyKey()
size_t operator()(const SourceRefIndex &c) const
size_t operator()(const SourceRef &val) const