Halide  17.0.2
Halide compiler and libraries
ModulusRemainder.h
Go to the documentation of this file.
1 #ifndef HALIDE_MODULUS_REMAINDER_H
2 #define HALIDE_MODULUS_REMAINDER_H
3 
4 /** \file
5  * Routines for statically determining what expressions are divisible by.
6  */
7 
8 #include <cstdint>
9 
10 #include "Util.h"
11 
12 namespace Halide {
13 
14 struct Expr;
15 
16 namespace Internal {
17 
18 template<typename T>
19 class Scope;
20 
21 /** The result of modulus_remainder analysis. These represent strided
22  * subsets of the integers. A ModulusRemainder object m represents all
23  * integers x such that there exists y such that x == m.modulus * y +
24  * m.remainder. Note that under this definition a set containing a
25  * single integer (a constant) is represented using a modulus of
26  * zero. These sets can be combined with several mathematical
27  * operators in the obvious way. E.g. m1 + m2 contains (at least) all
28  * integers x1 + x2 such that x1 belongs to m1 and x2 belongs to
29  * m2. These combinations are conservative. If some internal math
30  * would overflow, it defaults to all of the integers (modulus == 1,
31  * remainder == 0). */
32 
34  ModulusRemainder() = default;
36  : modulus(m), remainder(r) {
37  }
38 
40 
41  // Take a conservatively-large union of two sets. Contains all
42  // elements from both sets, and maybe some more stuff.
44 
45  // Take a conservatively-large intersection. Everything in the
46  // result is in at least one of the two sets, but not always both.
48 
49  bool operator==(const ModulusRemainder &other) const {
50  return (modulus == other.modulus) && (remainder == other.remainder);
51  }
52 };
53 
59 
65 
66 /** For things like alignment analysis, often it's helpful to know
67  * if an integer expression is some multiple of a constant plus
68  * some other constant. For example, it is straight-forward to
69  * deduce that ((10*x + 2)*(6*y - 3) - 1) is congruent to five
70  * modulo six.
71  *
72  * We get the most information when the modulus is large. E.g. if
73  * something is congruent to 208 modulo 384, then we also know it's
74  * congruent to 0 mod 8, and we can possibly use it as an index for an
75  * aligned load. If all else fails, we can just say that an integer is
76  * congruent to zero modulo one.
77  */
79 
80 /** If we have alignment information about external variables, we can
81  * let the analysis know about that using this version of
82  * modulus_remainder: */
84 
85 /** Reduce an expression modulo some integer. Returns true and assigns
86  * to remainder if an answer could be found. */
87 ///@{
88 HALIDE_MUST_USE_RESULT bool reduce_expr_modulo(const Expr &e, int64_t modulus, int64_t *remainder);
89 HALIDE_MUST_USE_RESULT bool reduce_expr_modulo(const Expr &e, int64_t modulus, int64_t *remainder, const Scope<ModulusRemainder> &scope);
90 ///@}
91 
93 
94 /** The greatest common divisor of two integers */
96 
97 /** The least common multiple of two integers */
99 
100 } // namespace Internal
101 } // namespace Halide
102 
103 #endif
#define HALIDE_MUST_USE_RESULT
Definition: HalideRuntime.h:65
Various utility functions used internally Halide.
A common pattern when traversing Halide IR is that you need to keep track of stuff when you find a Le...
Definition: Scope.h:94
ModulusRemainder modulus_remainder(const Expr &e)
For things like alignment analysis, often it's helpful to know if an integer expression is some multi...
int64_t gcd(int64_t, int64_t)
The greatest common divisor of two integers.
ModulusRemainder operator+(const ModulusRemainder &a, const ModulusRemainder &b)
ModulusRemainder operator%(const ModulusRemainder &a, const ModulusRemainder &b)
ModulusRemainder operator*(const ModulusRemainder &a, const ModulusRemainder &b)
void modulus_remainder_test()
HALIDE_MUST_USE_RESULT bool reduce_expr_modulo(const Expr &e, int64_t modulus, int64_t *remainder)
Reduce an expression modulo some integer.
ModulusRemainder operator-(const ModulusRemainder &a, const ModulusRemainder &b)
ModulusRemainder operator/(const ModulusRemainder &a, const ModulusRemainder &b)
int64_t lcm(int64_t, int64_t)
The least common multiple of two integers.
This file defines the class FunctionDAG, which is our representation of a Halide pipeline,...
@ Internal
Not visible externally, similar to 'static' linkage in C.
signed __INT64_TYPE__ int64_t
A fragment of Halide syntax.
Definition: Expr.h:258
The result of modulus_remainder analysis.
static ModulusRemainder unify(const ModulusRemainder &a, const ModulusRemainder &b)
ModulusRemainder(int64_t m, int64_t r)
bool operator==(const ModulusRemainder &other) const
static ModulusRemainder intersect(const ModulusRemainder &a, const ModulusRemainder &b)