LLZK 0.1.0
Veridise's ZK Language IR
Loading...
Searching...
No Matches
Intervals.h
Go to the documentation of this file.
1//===-- Intervals.h ---------------------------------------------*- C++ -*-===//
2//
3// Part of the LLZK Project, under the Apache License v2.0.
4// See LICENSE.txt for license information.
5// Copyright 2025 Veridise Inc.
6// SPDX-License-Identifier: Apache-2.0
7//
8//===----------------------------------------------------------------------===//
9
10#pragma once
11
12#include "llzk/Analysis/Field.h"
13
14#include <mlir/Support/LogicalResult.h>
15
16#include <algorithm>
17
18namespace llzk {
19
20/* UnreducedInterval */
21
22class Interval;
23
27public:
35 static size_t getMaxBitWidth(const UnreducedInterval &lhs, const UnreducedInterval &rhs) {
36 return std::max(
37 {lhs.a.getBitWidth(), lhs.b.getBitWidth(), rhs.a.getBitWidth(), rhs.b.getBitWidth()}
38 );
39 }
40
41 UnreducedInterval(llvm::APSInt x, llvm::APSInt y) : a(x), b(y) {}
42 UnreducedInterval(llvm::APInt x, llvm::APInt y) : a(x), b(y) {}
44 UnreducedInterval(uint64_t x, uint64_t y) : a(llvm::APInt(64, x)), b(llvm::APInt(64, y)) {}
45
46 /* Operations */
47
51 Interval reduce(const Field &field) const;
52
57
62
72
82
92
102
104 friend UnreducedInterval operator+(const UnreducedInterval &lhs, const UnreducedInterval &rhs);
105 friend UnreducedInterval operator-(const UnreducedInterval &lhs, const UnreducedInterval &rhs);
106 friend UnreducedInterval operator*(const UnreducedInterval &lhs, const UnreducedInterval &rhs);
107
108 /* Comparisons */
109
110 bool overlaps(const UnreducedInterval &rhs) const;
111
112 friend std::strong_ordering
113 operator<=>(const UnreducedInterval &lhs, const UnreducedInterval &rhs);
114
115 friend bool operator==(const UnreducedInterval &lhs, const UnreducedInterval &rhs) {
116 return std::is_eq(lhs <=> rhs);
117 };
118
119 /* Utility */
120 llvm::APSInt getLHS() const { return a; }
121 llvm::APSInt getRHS() const { return b; }
122
125 llvm::APSInt width() const;
126
128 bool isEmpty() const;
129
130 bool isNotEmpty() const { return !isEmpty(); }
131
132 void print(llvm::raw_ostream &os) const { os << "Unreduced:[ " << a << ", " << b << " ]"; }
133
134 friend llvm::raw_ostream &operator<<(llvm::raw_ostream &os, const UnreducedInterval &ui) {
135 ui.print(os);
136 return os;
137 }
138
139private:
140 llvm::APSInt a, b;
141};
142
143/* Interval */
144
214class Interval {
215public:
216 enum class Type { TypeA = 0, TypeB, TypeC, TypeF, Empty, Degenerate, Entire };
217 static constexpr std::array<std::string_view, 7> TypeNames = {"TypeA", "TypeB", "TypeC",
218 "TypeF", "Empty", "Degenerate",
219 "Entire"};
220
221 static std::string_view TypeName(Type t) { return TypeNames.at(static_cast<size_t>(t)); }
222
223 /* Static constructors for convenience */
224
225 static Interval Empty(const Field &f) { return Interval(Type::Empty, f); }
226
227 static Interval Degenerate(const Field &f, llvm::APSInt val) {
228 return Interval(Type::Degenerate, f, val, val);
229 }
230
231 static Interval False(const Field &f) { return Interval::Degenerate(f, f.zero()); }
232
233 static Interval True(const Field &f) { return Interval::Degenerate(f, f.one()); }
234
235 static Interval Boolean(const Field &f) { return Interval::TypeA(f, f.zero(), f.one()); }
236
237 static Interval Entire(const Field &f) { return Interval(Type::Entire, f); }
238
239 static Interval TypeA(const Field &f, llvm::APSInt a, llvm::APSInt b) {
240 return Interval(Type::TypeA, f, a, b);
241 }
242
243 static Interval TypeB(const Field &f, llvm::APSInt a, llvm::APSInt b) {
244 return Interval(Type::TypeB, f, a, b);
245 }
246
247 static Interval TypeC(const Field &f, llvm::APSInt a, llvm::APSInt b) {
248 return Interval(Type::TypeC, f, a, b);
249 }
250
251 static Interval TypeF(const Field &f, llvm::APSInt a, llvm::APSInt b) {
252 return Interval(Type::TypeF, f, a, b);
253 }
254
258
261
265
269
270 template <std::pair<Type, Type>... Pairs>
271 static bool areOneOf(const Interval &a, const Interval &b) {
272 return ((a.ty == std::get<0>(Pairs) && b.ty == std::get<1>(Pairs)) || ...);
273 }
274
276 Interval join(const Interval &rhs) const;
277
279 Interval intersect(const Interval &rhs) const;
280
294 Interval difference(const Interval &other) const;
295
296 /* arithmetic ops */
297
298 Interval operator-() const;
299 Interval operator~() const;
300 friend Interval operator+(const Interval &lhs, const Interval &rhs);
301 friend Interval operator-(const Interval &lhs, const Interval &rhs);
302 friend Interval operator*(const Interval &lhs, const Interval &rhs);
303 friend Interval operator%(const Interval &lhs, const Interval &rhs);
305 friend mlir::FailureOr<Interval> operator/(const Interval &lhs, const Interval &rhs);
306 friend Interval operator&(const Interval &lhs, const Interval &rhs);
307 friend Interval operator<<(const Interval &lhs, const Interval &rhs);
308 friend Interval operator>>(const Interval &lhs, const Interval &rhs);
309
310 /* boolean ops */
311 friend Interval boolAnd(const Interval &lhs, const Interval &rhs);
312 friend Interval boolOr(const Interval &lhs, const Interval &rhs);
313 friend Interval boolXor(const Interval &lhs, const Interval &rhs);
314 friend Interval boolNot(const Interval &iv);
315
316 /* Checks and Comparisons */
317
318 inline bool isEmpty() const { return ty == Type::Empty; }
319 inline bool isNotEmpty() const { return !isEmpty(); }
320 inline bool isDegenerate() const { return ty == Type::Degenerate; }
321 inline bool isEntire() const { return ty == Type::Entire; }
322 inline bool isTypeA() const { return ty == Type::TypeA; }
323 inline bool isTypeB() const { return ty == Type::TypeB; }
324 inline bool isTypeC() const { return ty == Type::TypeC; }
325 inline bool isTypeF() const { return ty == Type::TypeF; }
326
327 inline bool isBoolFalse() const { return *this == Interval::False(field.get()); }
328 inline bool isBoolTrue() const { return *this == Interval::True(field.get()); }
329 inline bool isBoolEither() const { return *this == Interval::Boolean(field.get()); }
330 inline bool isBoolean() const { return isBoolFalse() || isBoolTrue() || isBoolEither(); }
331
332 template <Type... Types> bool is() const { return ((ty == Types) || ...); }
333
334 bool operator==(const Interval &rhs) const { return ty == rhs.ty && a == rhs.a && b == rhs.b; }
335
336 /* Getters */
337
338 const Field &getField() const { return field.get(); }
339
340 llvm::APSInt width() const;
341
342 llvm::APSInt lhs() const { return a; }
343 llvm::APSInt rhs() const { return b; }
344
345 /* Utility */
346 struct Hash {
347 unsigned operator()(const Interval &i) const {
348 return std::hash<const Field *> {}(&i.field.get()) ^ std::hash<Type> {}(i.ty) ^
349 llvm::hash_value(i.a) ^ llvm::hash_value(i.b);
350 }
351 };
352
353 void print(llvm::raw_ostream &os) const;
354
355 friend llvm::raw_ostream &operator<<(llvm::raw_ostream &os, const Interval &i) {
356 i.print(os);
357 return os;
358 }
359
360private:
361 Interval(Type t, const Field &f) : field(f), ty(t), a(f.zero()), b(f.zero()) {}
362 Interval(Type t, const Field &f, llvm::APSInt lhs, llvm::APSInt rhs)
363 : field(f), ty(t), a(f.reduce(lhs)), b(f.reduce(rhs)) {}
364
365 std::reference_wrapper<const Field> field;
366 Type ty;
367 llvm::APSInt a, b;
368};
369
370} // namespace llzk
Information about the prime finite field used for the interval analysis.
Definition Field.h:22
llvm::APSInt one() const
Returns 1 at the bitwidth of the field.
Definition Field.h:46
llvm::APSInt zero() const
Returns 0 at the bitwidth of the field.
Definition Field.h:43
Intervals over a finite field.
Definition Intervals.h:214
bool isEmpty() const
Definition Intervals.h:318
static Interval True(const Field &f)
Definition Intervals.h:233
static constexpr std::array< std::string_view, 7 > TypeNames
Definition Intervals.h:217
bool isTypeA() const
Definition Intervals.h:322
Interval intersect(const Interval &rhs) const
Intersect.
bool isBoolean() const
Definition Intervals.h:330
friend Interval boolOr(const Interval &lhs, const Interval &rhs)
static std::string_view TypeName(Type t)
Definition Intervals.h:221
llvm::APSInt rhs() const
Definition Intervals.h:343
bool isTypeC() const
Definition Intervals.h:324
friend Interval operator<<(const Interval &lhs, const Interval &rhs)
void print(llvm::raw_ostream &os) const
UnreducedInterval toUnreduced() const
Convert to an UnreducedInterval.
static Interval Boolean(const Field &f)
Definition Intervals.h:235
bool isBoolFalse() const
Definition Intervals.h:327
bool isTypeB() const
Definition Intervals.h:323
UnreducedInterval firstUnreduced() const
Get the first side of the interval for TypeF intervals, otherwise just get the full interval as an Un...
static Interval Entire(const Field &f)
Definition Intervals.h:237
bool isDegenerate() const
Definition Intervals.h:320
const Field & getField() const
Definition Intervals.h:338
bool isBoolTrue() const
Definition Intervals.h:328
bool is() const
Definition Intervals.h:332
UnreducedInterval secondUnreduced() const
Get the second side of the interval for TypeA, TypeB, and TypeC intervals.
static Interval TypeC(const Field &f, llvm::APSInt a, llvm::APSInt b)
Definition Intervals.h:247
bool isNotEmpty() const
Definition Intervals.h:319
static Interval TypeF(const Field &f, llvm::APSInt a, llvm::APSInt b)
Definition Intervals.h:251
friend Interval boolAnd(const Interval &lhs, const Interval &rhs)
bool isBoolEither() const
Definition Intervals.h:329
static Interval TypeB(const Field &f, llvm::APSInt a, llvm::APSInt b)
Definition Intervals.h:243
friend llvm::raw_ostream & operator<<(llvm::raw_ostream &os, const Interval &i)
Definition Intervals.h:355
bool operator==(const Interval &rhs) const
Definition Intervals.h:334
bool isTypeF() const
Definition Intervals.h:325
llvm::APSInt width() const
static Interval False(const Field &f)
Definition Intervals.h:231
friend Interval operator*(const Interval &lhs, const Interval &rhs)
llvm::APSInt lhs() const
Definition Intervals.h:342
static Interval Empty(const Field &f)
Definition Intervals.h:225
Interval operator~() const
static bool areOneOf(const Interval &a, const Interval &b)
Definition Intervals.h:271
friend Interval operator>>(const Interval &lhs, const Interval &rhs)
static Interval Degenerate(const Field &f, llvm::APSInt val)
Definition Intervals.h:227
Interval()
To satisfy the dataflow::ScalarLatticeValue requirements, this class must be default initializable.
Definition Intervals.h:257
friend mlir::FailureOr< Interval > operator/(const Interval &lhs, const Interval &rhs)
Returns failure if a division-by-zero is encountered.
static Interval TypeA(const Field &f, llvm::APSInt a, llvm::APSInt b)
Definition Intervals.h:239
friend Interval operator+(const Interval &lhs, const Interval &rhs)
bool isEntire() const
Definition Intervals.h:321
friend Interval boolXor(const Interval &lhs, const Interval &rhs)
Interval difference(const Interval &other) const
Computes and returns this - (this & other) if the operation produces a single interval.
friend Interval operator%(const Interval &lhs, const Interval &rhs)
Interval operator-() const
Interval join(const Interval &rhs) const
Union.
friend Interval boolNot(const Interval &iv)
friend Interval operator&(const Interval &lhs, const Interval &rhs)
An inclusive interval [a, b] where a and b are arbitrary integers not necessarily bound to a given fi...
Definition Intervals.h:26
UnreducedInterval operator-() const
Definition Intervals.cpp:94
friend UnreducedInterval operator+(const UnreducedInterval &lhs, const UnreducedInterval &rhs)
UnreducedInterval intersect(const UnreducedInterval &rhs) const
Compute and return the intersection of this interval and the given RHS.
Definition Intervals.cpp:52
UnreducedInterval(llvm::APInt x, llvm::APInt y)
Definition Intervals.h:42
bool isEmpty() const
Returns true iff width() is zero.
UnreducedInterval(llvm::APSInt x, llvm::APSInt y)
Definition Intervals.h:41
llvm::APSInt width() const
Compute the width of this interval within a given field f.
UnreducedInterval computeLTPart(const UnreducedInterval &rhs) const
Return the part of the interval that is guaranteed to be less than the rhs's max value.
Definition Intervals.cpp:62
UnreducedInterval computeGEPart(const UnreducedInterval &rhs) const
Return the part of the interval that is greater than or equal to the rhs's lower bound.
Definition Intervals.cpp:87
friend std::strong_ordering operator<=>(const UnreducedInterval &lhs, const UnreducedInterval &rhs)
bool isNotEmpty() const
Definition Intervals.h:130
UnreducedInterval(uint64_t x, uint64_t y)
This constructor is primarily for convenience for unit tests.
Definition Intervals.h:44
bool overlaps(const UnreducedInterval &rhs) const
llvm::APSInt getRHS() const
Definition Intervals.h:121
friend llvm::raw_ostream & operator<<(llvm::raw_ostream &os, const UnreducedInterval &ui)
Definition Intervals.h:134
llvm::APSInt getLHS() const
Definition Intervals.h:120
friend bool operator==(const UnreducedInterval &lhs, const UnreducedInterval &rhs)
Definition Intervals.h:115
UnreducedInterval doUnion(const UnreducedInterval &rhs) const
Compute and return the union of this interval and the given RHS.
Definition Intervals.cpp:57
void print(llvm::raw_ostream &os) const
Definition Intervals.h:132
static size_t getMaxBitWidth(const UnreducedInterval &lhs, const UnreducedInterval &rhs)
A utility method to determine the largest bitwidth among arms of two UnreducedIntervals.
Definition Intervals.h:35
UnreducedInterval computeGTPart(const UnreducedInterval &rhs) const
Return the part of the interval that is greater than the rhs's lower bound.
Definition Intervals.cpp:78
Interval reduce(const Field &field) const
Reduce the interval to an interval in the given field.
Definition Intervals.cpp:20
UnreducedInterval computeLEPart(const UnreducedInterval &rhs) const
Return the part of the interval that is less than or equal to the rhs's upper bound.
Definition Intervals.cpp:71
friend UnreducedInterval operator*(const UnreducedInterval &lhs, const UnreducedInterval &rhs)
unsigned operator()(const Interval &i) const
Definition Intervals.h:347