1 //===- SDBMExpr.h - MLIR SDBM Expression ------------------------*- C++ -*-===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 //
9 // A striped difference-bound matrix (SDBM) expression is a constant expression,
10 // an identifier, a binary expression with constant RHS and +, stripe operators
11 // or a difference expression between two identifiers.
12 //
13 //===----------------------------------------------------------------------===//
14
15 #ifndef MLIR_DIALECT_SDBM_SDBMEXPR_H
16 #define MLIR_DIALECT_SDBM_SDBMEXPR_H
17
18 #include "mlir/Support/LLVM.h"
19 #include "llvm/ADT/DenseMapInfo.h"
20
21 namespace mlir {
22
23 class AffineExpr;
24 class MLIRContext;
25
26 enum class SDBMExprKind { Add, Stripe, Diff, Constant, DimId, SymbolId, Neg };
27
28 namespace detail {
29 struct SDBMExprStorage;
30 struct SDBMBinaryExprStorage;
31 struct SDBMDiffExprStorage;
32 struct SDBMTermExprStorage;
33 struct SDBMConstantExprStorage;
34 struct SDBMNegExprStorage;
35 } // namespace detail
36
37 class SDBMConstantExpr;
38 class SDBMDialect;
39 class SDBMDimExpr;
40 class SDBMSymbolExpr;
41 class SDBMTermExpr;
42
43 /// Striped Difference-Bounded Matrix (SDBM) expression is a base left-hand side
44 /// expression for the SDBM framework. SDBM expressions are a subset of affine
45 /// expressions supporting low-complexity algorithms for the operations used in
46 /// loop transformations. In particular, are supported:
47 /// - constant expressions;
48 /// - single variables (dimensions and symbols) with +1 or -1 coefficient;
49 /// - stripe expressions: "x # C", where "x" is a single variable or another
50 /// stripe expression, "#" is the stripe operator, and "C" is a constant
51 /// expression; "#" is defined as x - x mod C.
52 /// - sum expressions between single variable/stripe expressions and constant
53 /// expressions;
54 /// - difference expressions between single variable/stripe expressions.
55 /// `SDBMExpr` class hierarchy provides a type-safe interface to constructing
56 /// and operating on SDBM expressions. For example, it requires the LHS of a
57 /// sum expression to be a single variable or a stripe expression. These
58 /// restrictions are intended to force the caller to perform the necessary
59 /// simplifications to stay within the SDBM domain, because SDBM expressions do
60 /// not combine in more cases than they do. This choice may be reconsidered in
61 /// the future.
62 ///
63 /// SDBM expressions are grouped into the following structure
64 /// - expression
65 /// - varying
66 /// - direct
67 /// - sum <- (term, constant)
68 /// - term
69 /// - symbol
70 /// - dimension
71 /// - stripe <- (direct, constant)
72 /// - negation <- (direct)
73 /// - difference <- (direct, term)
74 /// - constant
75 /// The notation <- (...) denotes the types of subexpressions a compound
76 /// expression can combine. The tree of subexpressions essentially imposes the
77 /// following canonicalization rules:
78 /// - constants are always folded;
79 /// - constants can only appear on the RHS of an expression;
80 /// - double negation must be elided;
81 /// - an additive constant term is only allowed in a sum expression, and
82 /// should be sunk into the nearest such expression in the tree;
83 /// - zero constant expression can only appear at the top level.
84 ///
85 /// `SDBMExpr` and derived classes are thin wrappers around a pointer owned by
86 /// an MLIRContext, and should be used by-value. They are uniqued in the
87 /// MLIRContext and immortal.
88 class SDBMExpr {
89 public:
90 using ImplType = detail::SDBMExprStorage;
SDBMExpr()91 SDBMExpr() : impl(nullptr) {}
SDBMExpr(ImplType * expr)92 /* implicit */ SDBMExpr(ImplType *expr) : impl(expr) {}
93
94 /// SDBM expressions are thin wrappers around a unique'ed immutable pointer,
95 /// which makes them trivially assignable and trivially copyable.
96 SDBMExpr(const SDBMExpr &) = default;
97 SDBMExpr &operator=(const SDBMExpr &) = default;
98
99 /// SDBM expressions can be compared straight-forwardly.
100 bool operator==(const SDBMExpr &other) const { return impl == other.impl; }
101 bool operator!=(const SDBMExpr &other) const { return !(*this == other); }
102
103 /// SDBM expressions are convertible to `bool`: null expressions are converted
104 /// to false, non-null expressions are converted to true.
105 explicit operator bool() const { return impl != nullptr; }
106 bool operator!() const { return !static_cast<bool>(*this); }
107
108 /// Negate the given SDBM expression.
109 SDBMExpr operator-();
110
111 /// Prints the SDBM expression.
112 void print(raw_ostream &os) const;
113 void dump() const;
114
115 /// LLVM-style casts.
isa()116 template <typename U> bool isa() const { return U::isClassFor(*this); }
dyn_cast()117 template <typename U> U dyn_cast() const {
118 if (!isa<U>())
119 return {};
120 return U(const_cast<SDBMExpr *>(this)->impl);
121 }
cast()122 template <typename U> U cast() const {
123 assert(isa<U>() && "cast to incorrect subtype");
124 return U(const_cast<SDBMExpr *>(this)->impl);
125 }
126
127 /// Support for LLVM hashing.
hash_value()128 ::llvm::hash_code hash_value() const { return ::llvm::hash_value(impl); }
129
130 /// Returns the kind of the SDBM expression.
131 SDBMExprKind getKind() const;
132
133 /// Returns the MLIR context in which this expression lives.
134 MLIRContext *getContext() const;
135
136 /// Returns the SDBM dialect instance.
137 SDBMDialect *getDialect() const;
138
139 /// Convert the SDBM expression into an Affine expression. This always
140 /// succeeds because SDBM are a subset of affine.
141 AffineExpr getAsAffineExpr() const;
142
143 /// Try constructing an SDBM expression from the given affine expression.
144 /// This may fail if the affine expression is not representable as SDBM, in
145 /// which case llvm::None is returned. The conversion procedure recognizes
146 /// (nested) multiplicative ((x floordiv B) * B) and additive (x - x mod B)
147 /// patterns for the stripe expression.
148 static Optional<SDBMExpr> tryConvertAffineExpr(AffineExpr affine);
149
150 protected:
151 ImplType *impl;
152 };
153
154 /// SDBM constant expression, wraps a 64-bit integer.
155 class SDBMConstantExpr : public SDBMExpr {
156 public:
157 using ImplType = detail::SDBMConstantExprStorage;
158
159 using SDBMExpr::SDBMExpr;
160
161 /// Obtain or create a constant expression unique'ed in the given dialect
162 /// (which belongs to a context).
163 static SDBMConstantExpr get(SDBMDialect *dialect, int64_t value);
164
isClassFor(const SDBMExpr & expr)165 static bool isClassFor(const SDBMExpr &expr) {
166 return expr.getKind() == SDBMExprKind::Constant;
167 }
168
169 int64_t getValue() const;
170 };
171
172 /// SDBM varying expression can be one of:
173 /// - input variable expression;
174 /// - stripe expression;
175 /// - negation (product with -1) of either of the above.
176 /// - sum of a varying and a constant expression
177 /// - difference between varying expressions
178 class SDBMVaryingExpr : public SDBMExpr {
179 public:
180 using ImplType = detail::SDBMExprStorage;
181 using SDBMExpr::SDBMExpr;
182
isClassFor(const SDBMExpr & expr)183 static bool isClassFor(const SDBMExpr &expr) {
184 return expr.getKind() == SDBMExprKind::DimId ||
185 expr.getKind() == SDBMExprKind::SymbolId ||
186 expr.getKind() == SDBMExprKind::Neg ||
187 expr.getKind() == SDBMExprKind::Stripe ||
188 expr.getKind() == SDBMExprKind::Add ||
189 expr.getKind() == SDBMExprKind::Diff;
190 }
191 };
192
193 /// SDBM direct expression includes exactly one variable (symbol or dimension),
194 /// which is not negated in the expression. It can be one of:
195 /// - term expression;
196 /// - sum expression.
197 class SDBMDirectExpr : public SDBMVaryingExpr {
198 public:
199 using SDBMVaryingExpr::SDBMVaryingExpr;
200
201 /// If this is a sum expression, return its variable part, otherwise return
202 /// self.
203 SDBMTermExpr getTerm();
204
205 /// If this is a sum expression, return its constant part, otherwise return 0.
206 int64_t getConstant();
207
isClassFor(const SDBMExpr & expr)208 static bool isClassFor(const SDBMExpr &expr) {
209 return expr.getKind() == SDBMExprKind::DimId ||
210 expr.getKind() == SDBMExprKind::SymbolId ||
211 expr.getKind() == SDBMExprKind::Stripe ||
212 expr.getKind() == SDBMExprKind::Add;
213 }
214 };
215
216 /// SDBM term expression can be one of:
217 /// - single variable expression;
218 /// - stripe expression.
219 /// Stripe expressions are treated as terms since, in the SDBM domain, they are
220 /// attached to temporary variables and can appear anywhere a variable can.
221 class SDBMTermExpr : public SDBMDirectExpr {
222 public:
223 using SDBMDirectExpr::SDBMDirectExpr;
224
isClassFor(const SDBMExpr & expr)225 static bool isClassFor(const SDBMExpr &expr) {
226 return expr.getKind() == SDBMExprKind::DimId ||
227 expr.getKind() == SDBMExprKind::SymbolId ||
228 expr.getKind() == SDBMExprKind::Stripe;
229 }
230 };
231
232 /// SDBM sum expression. LHS is a term expression and RHS is a constant.
233 class SDBMSumExpr : public SDBMDirectExpr {
234 public:
235 using ImplType = detail::SDBMBinaryExprStorage;
236 using SDBMDirectExpr::SDBMDirectExpr;
237
238 /// Obtain or create a sum expression unique'ed in the given context.
239 static SDBMSumExpr get(SDBMTermExpr lhs, SDBMConstantExpr rhs);
240
isClassFor(const SDBMExpr & expr)241 static bool isClassFor(const SDBMExpr &expr) {
242 SDBMExprKind kind = expr.getKind();
243 return kind == SDBMExprKind::Add;
244 }
245
246 SDBMTermExpr getLHS() const;
247 SDBMConstantExpr getRHS() const;
248 };
249
250 /// SDBM difference expression. LHS is a direct expression, i.e. it may be a
251 /// sum of a term and a constant. RHS is a term expression. Thus the
252 /// expression (t1 - t2 + C) with term expressions t1,t2 is represented as
253 /// diff(sum(t1, C), t2)
254 /// and it is possible to extract the constant factor without negating it.
255 class SDBMDiffExpr : public SDBMVaryingExpr {
256 public:
257 using ImplType = detail::SDBMDiffExprStorage;
258 using SDBMVaryingExpr::SDBMVaryingExpr;
259
260 /// Obtain or create a difference expression unique'ed in the given context.
261 static SDBMDiffExpr get(SDBMDirectExpr lhs, SDBMTermExpr rhs);
262
isClassFor(const SDBMExpr & expr)263 static bool isClassFor(const SDBMExpr &expr) {
264 return expr.getKind() == SDBMExprKind::Diff;
265 }
266
267 SDBMDirectExpr getLHS() const;
268 SDBMTermExpr getRHS() const;
269 };
270
271 /// SDBM stripe expression "x # C" where "x" is a term expression, "C" is a
272 /// constant expression and "#" is the stripe operator defined as:
273 /// x # C = x - x mod C.
274 class SDBMStripeExpr : public SDBMTermExpr {
275 public:
276 using ImplType = detail::SDBMBinaryExprStorage;
277 using SDBMTermExpr::SDBMTermExpr;
278
isClassFor(const SDBMExpr & expr)279 static bool isClassFor(const SDBMExpr &expr) {
280 return expr.getKind() == SDBMExprKind::Stripe;
281 }
282
283 static SDBMStripeExpr get(SDBMDirectExpr var, SDBMConstantExpr stripeFactor);
284
285 SDBMDirectExpr getLHS() const;
286 SDBMConstantExpr getStripeFactor() const;
287 };
288
289 /// SDBM "input" variable expression can be either a dimension identifier or
290 /// a symbol identifier. When used to define SDBM functions, dimensions are
291 /// interpreted as function arguments while symbols are treated as unknown but
292 /// constant values, hence the name.
293 class SDBMInputExpr : public SDBMTermExpr {
294 public:
295 using ImplType = detail::SDBMTermExprStorage;
296 using SDBMTermExpr::SDBMTermExpr;
297
isClassFor(const SDBMExpr & expr)298 static bool isClassFor(const SDBMExpr &expr) {
299 return expr.getKind() == SDBMExprKind::DimId ||
300 expr.getKind() == SDBMExprKind::SymbolId;
301 }
302
303 unsigned getPosition() const;
304 };
305
306 /// SDBM dimension expression. Dimensions correspond to function arguments
307 /// when defining functions using SDBM expressions.
308 class SDBMDimExpr : public SDBMInputExpr {
309 public:
310 using ImplType = detail::SDBMTermExprStorage;
311 using SDBMInputExpr::SDBMInputExpr;
312
313 /// Obtain or create a dimension expression unique'ed in the given dialect
314 /// (which belongs to a context).
315 static SDBMDimExpr get(SDBMDialect *dialect, unsigned position);
316
isClassFor(const SDBMExpr & expr)317 static bool isClassFor(const SDBMExpr &expr) {
318 return expr.getKind() == SDBMExprKind::DimId;
319 }
320 };
321
322 /// SDBM symbol expression. Symbols correspond to symbolic constants when
323 /// defining functions using SDBM expressions.
324 class SDBMSymbolExpr : public SDBMInputExpr {
325 public:
326 using ImplType = detail::SDBMTermExprStorage;
327 using SDBMInputExpr::SDBMInputExpr;
328
329 /// Obtain or create a symbol expression unique'ed in the given dialect (which
330 /// belongs to a context).
331 static SDBMSymbolExpr get(SDBMDialect *dialect, unsigned position);
332
isClassFor(const SDBMExpr & expr)333 static bool isClassFor(const SDBMExpr &expr) {
334 return expr.getKind() == SDBMExprKind::SymbolId;
335 }
336 };
337
338 /// Negation of an SDBM variable expression. Equivalent to multiplying the
339 /// expression with -1 (SDBM does not support other coefficients that 1 and -1).
340 class SDBMNegExpr : public SDBMVaryingExpr {
341 public:
342 using ImplType = detail::SDBMNegExprStorage;
343 using SDBMVaryingExpr::SDBMVaryingExpr;
344
345 /// Obtain or create a negation expression unique'ed in the given context.
346 static SDBMNegExpr get(SDBMDirectExpr var);
347
isClassFor(const SDBMExpr & expr)348 static bool isClassFor(const SDBMExpr &expr) {
349 return expr.getKind() == SDBMExprKind::Neg;
350 }
351
352 SDBMDirectExpr getVar() const;
353 };
354
355 /// A visitor class for SDBM expressions. Calls the kind-specific function
356 /// depending on the kind of expression it visits.
357 template <typename Derived, typename Result = void> class SDBMVisitor {
358 public:
359 /// Visit the given SDBM expression, dispatching to kind-specific functions.
visit(SDBMExpr expr)360 Result visit(SDBMExpr expr) {
361 auto *derived = static_cast<Derived *>(this);
362 switch (expr.getKind()) {
363 case SDBMExprKind::Add:
364 case SDBMExprKind::Diff:
365 case SDBMExprKind::DimId:
366 case SDBMExprKind::SymbolId:
367 case SDBMExprKind::Neg:
368 case SDBMExprKind::Stripe:
369 return derived->visitVarying(expr.cast<SDBMVaryingExpr>());
370 case SDBMExprKind::Constant:
371 return derived->visitConstant(expr.cast<SDBMConstantExpr>());
372 }
373
374 llvm_unreachable("unsupported SDBM expression kind");
375 }
376
377 /// Traverse the SDBM expression tree calling `visit` on each node
378 /// in depth-first preorder.
walkPreorder(SDBMExpr expr)379 void walkPreorder(SDBMExpr expr) { return walk</*isPreorder=*/true>(expr); }
380
381 /// Traverse the SDBM expression tree calling `visit` on each node in
382 /// depth-first postorder.
walkPostorder(SDBMExpr expr)383 void walkPostorder(SDBMExpr expr) { return walk</*isPreorder=*/false>(expr); }
384
385 protected:
386 /// Default visitors do nothing.
visitSum(SDBMSumExpr)387 void visitSum(SDBMSumExpr) {}
visitDiff(SDBMDiffExpr)388 void visitDiff(SDBMDiffExpr) {}
visitStripe(SDBMStripeExpr)389 void visitStripe(SDBMStripeExpr) {}
visitDim(SDBMDimExpr)390 void visitDim(SDBMDimExpr) {}
visitSymbol(SDBMSymbolExpr)391 void visitSymbol(SDBMSymbolExpr) {}
visitNeg(SDBMNegExpr)392 void visitNeg(SDBMNegExpr) {}
visitConstant(SDBMConstantExpr)393 void visitConstant(SDBMConstantExpr) {}
394
395 /// Default implementation of visitDirect dispatches to the dedicated for sums
396 /// or delegates to visitTerm for the other expression kinds. Concrete
397 /// visitors can overload it.
visitDirect(SDBMDirectExpr expr)398 Result visitDirect(SDBMDirectExpr expr) {
399 auto *derived = static_cast<Derived *>(this);
400 if (auto sum = expr.dyn_cast<SDBMSumExpr>())
401 return derived->visitSum(sum);
402 else
403 return derived->visitTerm(expr.cast<SDBMTermExpr>());
404 }
405
406 /// Default implementation of visitTerm dispatches to the special functions
407 /// for stripes and other variables. Concrete visitors can override it.
visitTerm(SDBMTermExpr expr)408 Result visitTerm(SDBMTermExpr expr) {
409 auto *derived = static_cast<Derived *>(this);
410 if (expr.getKind() == SDBMExprKind::Stripe)
411 return derived->visitStripe(expr.cast<SDBMStripeExpr>());
412 else
413 return derived->visitInput(expr.cast<SDBMInputExpr>());
414 }
415
416 /// Default implementation of visitInput dispatches to the special
417 /// functions for dimensions or symbols. Concrete visitors can override it to
418 /// visit all variables instead.
visitInput(SDBMInputExpr expr)419 Result visitInput(SDBMInputExpr expr) {
420 auto *derived = static_cast<Derived *>(this);
421 if (expr.getKind() == SDBMExprKind::DimId)
422 return derived->visitDim(expr.cast<SDBMDimExpr>());
423 else
424 return derived->visitSymbol(expr.cast<SDBMSymbolExpr>());
425 }
426
427 /// Default implementation of visitVarying dispatches to the special
428 /// functions for variables and negations thereof. Concrete visitors can
429 /// override it to visit all variables and negations instead.
visitVarying(SDBMVaryingExpr expr)430 Result visitVarying(SDBMVaryingExpr expr) {
431 auto *derived = static_cast<Derived *>(this);
432 if (auto var = expr.dyn_cast<SDBMDirectExpr>())
433 return derived->visitDirect(var);
434 else if (auto neg = expr.dyn_cast<SDBMNegExpr>())
435 return derived->visitNeg(neg);
436 else if (auto diff = expr.dyn_cast<SDBMDiffExpr>())
437 return derived->visitDiff(diff);
438
439 llvm_unreachable("unhandled subtype of varying SDBM expression");
440 }
441
walk(SDBMExpr expr)442 template <bool isPreorder> void walk(SDBMExpr expr) {
443 if (isPreorder)
444 visit(expr);
445 if (auto sumExpr = expr.dyn_cast<SDBMSumExpr>()) {
446 walk<isPreorder>(sumExpr.getLHS());
447 walk<isPreorder>(sumExpr.getRHS());
448 } else if (auto diffExpr = expr.dyn_cast<SDBMDiffExpr>()) {
449 walk<isPreorder>(diffExpr.getLHS());
450 walk<isPreorder>(diffExpr.getRHS());
451 } else if (auto stripeExpr = expr.dyn_cast<SDBMStripeExpr>()) {
452 walk<isPreorder>(stripeExpr.getLHS());
453 walk<isPreorder>(stripeExpr.getStripeFactor());
454 } else if (auto negExpr = expr.dyn_cast<SDBMNegExpr>()) {
455 walk<isPreorder>(negExpr.getVar());
456 }
457 if (!isPreorder)
458 visit(expr);
459 }
460 };
461
462 /// Overloaded arithmetic operators for SDBM expressions asserting that their
463 /// arguments have the proper SDBM expression subtype. Perform canonicalization
464 /// and constant folding on these expressions.
465 namespace ops_assertions {
466
467 /// Add two SDBM expressions. At least one of the expressions must be a
468 /// constant or a negation, but both expressions cannot be negations
469 /// simultaneously.
470 SDBMExpr operator+(SDBMExpr lhs, SDBMExpr rhs);
471 inline SDBMExpr operator+(SDBMExpr lhs, int64_t rhs) {
472 return lhs + SDBMConstantExpr::get(lhs.getDialect(), rhs);
473 }
474 inline SDBMExpr operator+(int64_t lhs, SDBMExpr rhs) {
475 return SDBMConstantExpr::get(rhs.getDialect(), lhs) + rhs;
476 }
477
478 /// Subtract an SDBM expression from another SDBM expression. Both expressions
479 /// must not be difference expressions.
480 SDBMExpr operator-(SDBMExpr lhs, SDBMExpr rhs);
481 inline SDBMExpr operator-(SDBMExpr lhs, int64_t rhs) {
482 return lhs - SDBMConstantExpr::get(lhs.getDialect(), rhs);
483 }
484 inline SDBMExpr operator-(int64_t lhs, SDBMExpr rhs) {
485 return SDBMConstantExpr::get(rhs.getDialect(), lhs) - rhs;
486 }
487
488 /// Construct a stripe expression from a positive expression and a positive
489 /// constant stripe factor.
490 SDBMExpr stripe(SDBMExpr expr, SDBMExpr factor);
stripe(SDBMExpr expr,int64_t factor)491 inline SDBMExpr stripe(SDBMExpr expr, int64_t factor) {
492 return stripe(expr, SDBMConstantExpr::get(expr.getDialect(), factor));
493 }
494 } // namespace ops_assertions
495
496 } // end namespace mlir
497
498 namespace llvm {
499 // SDBMExpr hash just like pointers.
500 template <> struct DenseMapInfo<mlir::SDBMExpr> {
501 static mlir::SDBMExpr getEmptyKey() {
502 auto *pointer = llvm::DenseMapInfo<void *>::getEmptyKey();
503 return mlir::SDBMExpr(static_cast<mlir::SDBMExpr::ImplType *>(pointer));
504 }
505 static mlir::SDBMExpr getTombstoneKey() {
506 auto *pointer = llvm::DenseMapInfo<void *>::getTombstoneKey();
507 return mlir::SDBMExpr(static_cast<mlir::SDBMExpr::ImplType *>(pointer));
508 }
509 static unsigned getHashValue(mlir::SDBMExpr expr) {
510 return expr.hash_value();
511 }
512 static bool isEqual(mlir::SDBMExpr lhs, mlir::SDBMExpr rhs) {
513 return lhs == rhs;
514 }
515 };
516
517 // SDBMDirectExpr hash just like pointers.
518 template <> struct DenseMapInfo<mlir::SDBMDirectExpr> {
519 static mlir::SDBMDirectExpr getEmptyKey() {
520 auto *pointer = llvm::DenseMapInfo<void *>::getEmptyKey();
521 return mlir::SDBMDirectExpr(
522 static_cast<mlir::SDBMExpr::ImplType *>(pointer));
523 }
524 static mlir::SDBMDirectExpr getTombstoneKey() {
525 auto *pointer = llvm::DenseMapInfo<void *>::getTombstoneKey();
526 return mlir::SDBMDirectExpr(
527 static_cast<mlir::SDBMExpr::ImplType *>(pointer));
528 }
529 static unsigned getHashValue(mlir::SDBMDirectExpr expr) {
530 return expr.hash_value();
531 }
532 static bool isEqual(mlir::SDBMDirectExpr lhs, mlir::SDBMDirectExpr rhs) {
533 return lhs == rhs;
534 }
535 };
536
537 // SDBMTermExpr hash just like pointers.
538 template <> struct DenseMapInfo<mlir::SDBMTermExpr> {
539 static mlir::SDBMTermExpr getEmptyKey() {
540 auto *pointer = llvm::DenseMapInfo<void *>::getEmptyKey();
541 return mlir::SDBMTermExpr(static_cast<mlir::SDBMExpr::ImplType *>(pointer));
542 }
543 static mlir::SDBMTermExpr getTombstoneKey() {
544 auto *pointer = llvm::DenseMapInfo<void *>::getTombstoneKey();
545 return mlir::SDBMTermExpr(static_cast<mlir::SDBMExpr::ImplType *>(pointer));
546 }
547 static unsigned getHashValue(mlir::SDBMTermExpr expr) {
548 return expr.hash_value();
549 }
550 static bool isEqual(mlir::SDBMTermExpr lhs, mlir::SDBMTermExpr rhs) {
551 return lhs == rhs;
552 }
553 };
554
555 // SDBMConstantExpr hash just like pointers.
556 template <> struct DenseMapInfo<mlir::SDBMConstantExpr> {
557 static mlir::SDBMConstantExpr getEmptyKey() {
558 auto *pointer = llvm::DenseMapInfo<void *>::getEmptyKey();
559 return mlir::SDBMConstantExpr(
560 static_cast<mlir::SDBMExpr::ImplType *>(pointer));
561 }
562 static mlir::SDBMConstantExpr getTombstoneKey() {
563 auto *pointer = llvm::DenseMapInfo<void *>::getTombstoneKey();
564 return mlir::SDBMConstantExpr(
565 static_cast<mlir::SDBMExpr::ImplType *>(pointer));
566 }
567 static unsigned getHashValue(mlir::SDBMConstantExpr expr) {
568 return expr.hash_value();
569 }
570 static bool isEqual(mlir::SDBMConstantExpr lhs, mlir::SDBMConstantExpr rhs) {
571 return lhs == rhs;
572 }
573 };
574 } // namespace llvm
575
576 #endif // MLIR_DIALECT_SDBM_SDBMEXPR_H
577