Halide
IREquality.h
Go to the documentation of this file.
1 #ifndef HALIDE_IR_EQUALITY_H
2 #define HALIDE_IR_EQUALITY_H
3 
4 /** \file
5  * Methods to test Exprs and Stmts for equality of value
6  */
7 
8 #include "IR.h"
9 
10 namespace Halide {
11 namespace Internal {
12 
13 /** A compare struct suitable for use in std::map and std::set that
14  * computes a lexical ordering on IR nodes. */
15 struct IRDeepCompare {
16  EXPORT bool operator()(const Expr &a, const Expr &b) const;
17  EXPORT bool operator()(const Stmt &a, const Stmt &b) const;
18 };
19 
20 /** Lossily track known equal exprs with a cache. On collision, the
21  * old pair is evicted. Used below by ExprWithCompareCache. */
23 private:
24  struct Entry {
25  Expr a, b;
26  };
27 
28  int bits;
29 
30  uint32_t hash(const Expr &a, const Expr &b) const {
31  // Note this hash is symmetric in a and b, so that a
32  // comparison in a and b hashes to the same bucket as
33  // a comparison on b and a.
34  uint64_t pa = (uint64_t)(a.get());
35  uint64_t pb = (uint64_t)(b.get());
36  uint64_t mix = (pa + pb) + (pa ^ pb);
37  mix ^= (mix >> bits);
38  mix ^= (mix >> (bits*2));
39  uint32_t bottom = mix & ((1 << bits) - 1);
40  return bottom;
41  }
42 
43  std::vector<Entry> entries;
44 
45 public:
46  void insert(const Expr &a, const Expr &b) {
47  uint32_t h = hash(a, b);
48  entries[h].a = a;
49  entries[h].b = b;
50  }
51 
52  bool contains(const Expr &a, const Expr &b) const {
53  uint32_t h = hash(a, b);
54  const Entry &e = entries[h];
55  return ((a.same_as(e.a) && b.same_as(e.b)) ||
56  (a.same_as(e.b) && b.same_as(e.a)));
57  }
58 
59  void clear() {
60  for (size_t i = 0; i < entries.size(); i++) {
61  entries[i].a = Expr();
62  entries[i].b = Expr();
63  }
64  }
65 
67  IRCompareCache(int b) : bits(b), entries(static_cast<size_t>(1) << bits) {}
68 };
69 
70 /** A wrapper about Exprs so that they can be deeply compared with a
71  * cache for known-equal subexpressions. Useful for unsanitized Exprs
72  * coming in from the front-end, which may be horrible graphs with
73  * sub-expressions that are equal by value but not by identity. This
74  * isn't a comparison object like IRDeepCompare above, because libc++
75  * requires that comparison objects be stateless (and constructs a new
76  * one for each comparison!), so they can't have a cache associated
77  * with them. However, by sneakily making the cache a mutable member
78  * of the objects being compared, we can dodge this issue.
79  *
80  * Clunky example usage:
81  *
82 \code
83 Expr a, b, c, query;
84 std::set<ExprWithCompareCache> s;
85 IRCompareCache cache(8);
86 s.insert(ExprWithCompareCache(a, &cache));
87 s.insert(ExprWithCompareCache(b, &cache));
88 s.insert(ExprWithCompareCache(c, &cache));
89 if (m.contains(ExprWithCompareCache(query, &cache))) {...}
90 \endcode
91  *
92  */
96 
97  ExprWithCompareCache() : cache(nullptr) {}
98  ExprWithCompareCache(const Expr &e, IRCompareCache *c) : expr(e), cache(c) {}
99 
100  /** The comparison uses (and updates) the cache */
101  EXPORT bool operator<(const ExprWithCompareCache &other) const;
102 };
103 
104 /** Compare IR nodes for equality of value. Traverses entire IR
105  * tree. For equality of reference, use Expr::same_as. If you're
106  * comparing non-CSE'd Exprs, use graph_equal, which is safe for nasty
107  * graphs of IR nodes. */
108 // @{
109 EXPORT bool equal(const Expr &a, const Expr &b);
110 EXPORT bool equal(const Stmt &a, const Stmt &b);
111 EXPORT bool graph_equal(const Expr &a, const Expr &b);
112 EXPORT bool graph_equal(const Stmt &a, const Stmt &b);
113 // @}
114 
115 
116 
117 EXPORT void ir_equality_test();
118 
119 }
120 }
121 
122 #endif
A compare struct suitable for use in std::map and std::set that computes a lexical ordering on IR nod...
Definition: IREquality.h:15
ExprWithCompareCache(const Expr &e, IRCompareCache *c)
Definition: IREquality.h:98
A fragment of Halide syntax.
Definition: Expr.h:276
A reference-counted handle to a statement node.
Definition: Expr.h:356
void insert(const Expr &a, const Expr &b)
Definition: IREquality.h:46
bool contains(const Expr &a, const Expr &b) const
Definition: IREquality.h:52
Defines methods for manipulating and analyzing boolean expressions.
bool same_as(const IntrusivePtr &other) const
Definition: IntrusivePtr.h:145
decltype((Other) 0<(T) 1) operator<(const Other &a, const GeneratorParam< T > &b)
Less than comparison between GeneratorParam<T> and any type that supports operator< with T...
Definition: Generator.h:872
unsigned __INT32_TYPE__ uint32_t
Lossily track known equal exprs with a cache.
Definition: IREquality.h:22
Subtypes for Halide expressions (Halide::Expr) and statements (Halide::Internal::Stmt) ...
EXPORT bool equal(const Expr &a, const Expr &b)
Compare IR nodes for equality of value.
__SIZE_TYPE__ size_t
EXPORT void ir_equality_test()
T * get() const
Access the raw pointer in a variety of ways.
Definition: IntrusivePtr.h:89
#define EXPORT
Definition: Util.h:30
EXPORT bool operator()(const Expr &a, const Expr &b) const
EXPORT bool graph_equal(const Expr &a, const Expr &b)
Compare IR nodes for equality of value.
unsigned __INT64_TYPE__ uint64_t
A wrapper about Exprs so that they can be deeply compared with a cache for known-equal subexpressions...
Definition: IREquality.h:93