1 //===- Predicate.h - Pattern predicates -------------------------*- 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 // This file contains definitions for "predicates" used when converting PDL into 10 // a matcher tree. Predicates are composed of three different parts: 11 // 12 // * Positions 13 // - A position refers to a specific location on the input DAG, i.e. an 14 // existing MLIR entity being matched. These can be attributes, operands, 15 // operations, results, and types. Each position also defines a relation to 16 // its parent. For example, the operand `[0] -> 1` has a parent operation 17 // position `[0]`. The attribute `[0, 1] -> "myAttr"` has parent operation 18 // position of `[0, 1]`. The operation `[0, 1]` has a parent operand edge 19 // `[0] -> 1` (i.e. it is the defining op of operand 1). The only position 20 // without a parent is `[0]`, which refers to the root operation. 21 // * Questions 22 // - A question refers to a query on a specific positional value. For 23 // example, an operation name question checks the name of an operation 24 // position. 25 // * Answers 26 // - An answer is the expected result of a question. For example, when 27 // matching an operation with the name "foo.op". The question would be an 28 // operation name question, with an expected answer of "foo.op". 29 // 30 //===----------------------------------------------------------------------===// 31 32 #ifndef MLIR_LIB_CONVERSION_PDLTOPDLINTERP_PREDICATE_H_ 33 #define MLIR_LIB_CONVERSION_PDLTOPDLINTERP_PREDICATE_H_ 34 35 #include "mlir/IR/MLIRContext.h" 36 #include "mlir/IR/OperationSupport.h" 37 #include "mlir/IR/PatternMatch.h" 38 #include "mlir/IR/Types.h" 39 40 namespace mlir { 41 namespace pdl_to_pdl_interp { 42 namespace Predicates { 43 /// An enumeration of the kinds of predicates. 44 enum Kind : unsigned { 45 /// Positions, ordered by decreasing priority. 46 OperationPos, 47 OperandPos, 48 OperandGroupPos, 49 AttributePos, 50 ResultPos, 51 ResultGroupPos, 52 TypePos, 53 AttributeLiteralPos, 54 TypeLiteralPos, 55 UsersPos, 56 ForEachPos, 57 58 // Questions, ordered by dependency and decreasing priority. 59 IsNotNullQuestion, 60 OperationNameQuestion, 61 TypeQuestion, 62 AttributeQuestion, 63 OperandCountAtLeastQuestion, 64 OperandCountQuestion, 65 ResultCountAtLeastQuestion, 66 ResultCountQuestion, 67 EqualToQuestion, 68 ConstraintQuestion, 69 70 // Answers. 71 AttributeAnswer, 72 FalseAnswer, 73 OperationNameAnswer, 74 TrueAnswer, 75 TypeAnswer, 76 UnsignedAnswer, 77 }; 78 } // namespace Predicates 79 80 /// Base class for all predicates, used to allow efficient pointer comparison. 81 template <typename ConcreteT, typename BaseT, typename Key, 82 Predicates::Kind Kind> 83 class PredicateBase : public BaseT { 84 public: 85 using KeyTy = Key; 86 using Base = PredicateBase<ConcreteT, BaseT, Key, Kind>; 87 88 template <typename KeyT> 89 explicit PredicateBase(KeyT &&key) 90 : BaseT(Kind), key(std::forward<KeyT>(key)) {} 91 92 /// Get an instance of this position. 93 template <typename... Args> 94 static ConcreteT *get(StorageUniquer &uniquer, Args &&...args) { 95 return uniquer.get<ConcreteT>(/*initFn=*/{}, std::forward<Args>(args)...); 96 } 97 98 /// Construct an instance with the given storage allocator. 99 template <typename KeyT> 100 static ConcreteT *construct(StorageUniquer::StorageAllocator &alloc, 101 KeyT &&key) { 102 return new (alloc.allocate<ConcreteT>()) ConcreteT(std::forward<KeyT>(key)); 103 } 104 105 /// Utility methods required by the storage allocator. 106 bool operator==(const KeyTy &key) const { return this->key == key; } 107 static bool classof(const BaseT *pred) { return pred->getKind() == Kind; } 108 109 /// Return the key value of this predicate. 110 const KeyTy &getValue() const { return key; } 111 112 protected: 113 KeyTy key; 114 }; 115 116 /// Base storage for simple predicates that only unique with the kind. 117 template <typename ConcreteT, typename BaseT, Predicates::Kind Kind> 118 class PredicateBase<ConcreteT, BaseT, void, Kind> : public BaseT { 119 public: 120 using Base = PredicateBase<ConcreteT, BaseT, void, Kind>; 121 122 explicit PredicateBase() : BaseT(Kind) {} 123 124 static ConcreteT *get(StorageUniquer &uniquer) { 125 return uniquer.get<ConcreteT>(); 126 } 127 static bool classof(const BaseT *pred) { return pred->getKind() == Kind; } 128 }; 129 130 //===----------------------------------------------------------------------===// 131 // Positions 132 //===----------------------------------------------------------------------===// 133 134 struct OperationPosition; 135 136 /// A position describes a value on the input IR on which a predicate may be 137 /// applied, such as an operation or attribute. This enables re-use between 138 /// predicates, and assists generating bytecode and memory management. 139 /// 140 /// Operation positions form the base of other positions, which are formed 141 /// relative to a parent operation. Operations are anchored at Operand nodes, 142 /// except for the root operation which is parentless. 143 class Position : public StorageUniquer::BaseStorage { 144 public: 145 explicit Position(Predicates::Kind kind) : kind(kind) {} 146 virtual ~Position(); 147 148 /// Returns the depth of the first ancestor operation position. 149 unsigned getOperationDepth() const; 150 151 /// Returns the parent position. The root operation position has no parent. 152 Position *getParent() const { return parent; } 153 154 /// Returns the kind of this position. 155 Predicates::Kind getKind() const { return kind; } 156 157 protected: 158 /// Link to the parent position. 159 Position *parent = nullptr; 160 161 private: 162 /// The kind of this position. 163 Predicates::Kind kind; 164 }; 165 166 //===----------------------------------------------------------------------===// 167 // AttributePosition 168 169 /// A position describing an attribute of an operation. 170 struct AttributePosition 171 : public PredicateBase<AttributePosition, Position, 172 std::pair<OperationPosition *, StringAttr>, 173 Predicates::AttributePos> { 174 explicit AttributePosition(const KeyTy &key); 175 176 /// Returns the attribute name of this position. 177 StringAttr getName() const { return key.second; } 178 }; 179 180 //===----------------------------------------------------------------------===// 181 // AttributeLiteralPosition 182 183 /// A position describing a literal attribute. 184 struct AttributeLiteralPosition 185 : public PredicateBase<AttributeLiteralPosition, Position, Attribute, 186 Predicates::AttributeLiteralPos> { 187 using PredicateBase::PredicateBase; 188 }; 189 190 //===----------------------------------------------------------------------===// 191 // ForEachPosition 192 193 /// A position describing an iterative choice of an operation. 194 struct ForEachPosition : public PredicateBase<ForEachPosition, Position, 195 std::pair<Position *, unsigned>, 196 Predicates::ForEachPos> { 197 explicit ForEachPosition(const KeyTy &key) : Base(key) { parent = key.first; } 198 199 /// Returns the ID, for differentiating various loops. 200 /// For upward traversals, this is the index of the root. 201 unsigned getID() const { return key.second; } 202 }; 203 204 //===----------------------------------------------------------------------===// 205 // OperandPosition 206 207 /// A position describing an operand of an operation. 208 struct OperandPosition 209 : public PredicateBase<OperandPosition, Position, 210 std::pair<OperationPosition *, unsigned>, 211 Predicates::OperandPos> { 212 explicit OperandPosition(const KeyTy &key); 213 214 /// Returns the operand number of this position. 215 unsigned getOperandNumber() const { return key.second; } 216 }; 217 218 //===----------------------------------------------------------------------===// 219 // OperandGroupPosition 220 221 /// A position describing an operand group of an operation. 222 struct OperandGroupPosition 223 : public PredicateBase< 224 OperandGroupPosition, Position, 225 std::tuple<OperationPosition *, Optional<unsigned>, bool>, 226 Predicates::OperandGroupPos> { 227 explicit OperandGroupPosition(const KeyTy &key); 228 229 /// Returns a hash suitable for the given keytype. 230 static llvm::hash_code hashKey(const KeyTy &key) { 231 return llvm::hash_value(key); 232 } 233 234 /// Returns the group number of this position. If None, this group refers to 235 /// all operands. 236 Optional<unsigned> getOperandGroupNumber() const { return std::get<1>(key); } 237 238 /// Returns if the operand group has unknown size. If false, the operand group 239 /// has at max one element. 240 bool isVariadic() const { return std::get<2>(key); } 241 }; 242 243 //===----------------------------------------------------------------------===// 244 // OperationPosition 245 246 /// An operation position describes an operation node in the IR. Other position 247 /// kinds are formed with respect to an operation position. 248 struct OperationPosition : public PredicateBase<OperationPosition, Position, 249 std::pair<Position *, unsigned>, 250 Predicates::OperationPos> { 251 explicit OperationPosition(const KeyTy &key) : Base(key) { 252 parent = key.first; 253 } 254 255 /// Returns a hash suitable for the given keytype. 256 static llvm::hash_code hashKey(const KeyTy &key) { 257 return llvm::hash_value(key); 258 } 259 260 /// Gets the root position. 261 static OperationPosition *getRoot(StorageUniquer &uniquer) { 262 return Base::get(uniquer, nullptr, 0); 263 } 264 265 /// Gets an operation position with the given parent. 266 static OperationPosition *get(StorageUniquer &uniquer, Position *parent) { 267 return Base::get(uniquer, parent, parent->getOperationDepth() + 1); 268 } 269 270 /// Returns the depth of this position. 271 unsigned getDepth() const { return key.second; } 272 273 /// Returns if this operation position corresponds to the root. 274 bool isRoot() const { return getDepth() == 0; } 275 276 /// Returns if this operation represents an operand defining op. 277 bool isOperandDefiningOp() const; 278 }; 279 280 //===----------------------------------------------------------------------===// 281 // ResultPosition 282 283 /// A position describing a result of an operation. 284 struct ResultPosition 285 : public PredicateBase<ResultPosition, Position, 286 std::pair<OperationPosition *, unsigned>, 287 Predicates::ResultPos> { 288 explicit ResultPosition(const KeyTy &key) : Base(key) { parent = key.first; } 289 290 /// Returns the result number of this position. 291 unsigned getResultNumber() const { return key.second; } 292 }; 293 294 //===----------------------------------------------------------------------===// 295 // ResultGroupPosition 296 297 /// A position describing a result group of an operation. 298 struct ResultGroupPosition 299 : public PredicateBase< 300 ResultGroupPosition, Position, 301 std::tuple<OperationPosition *, Optional<unsigned>, bool>, 302 Predicates::ResultGroupPos> { 303 explicit ResultGroupPosition(const KeyTy &key) : Base(key) { 304 parent = std::get<0>(key); 305 } 306 307 /// Returns a hash suitable for the given keytype. 308 static llvm::hash_code hashKey(const KeyTy &key) { 309 return llvm::hash_value(key); 310 } 311 312 /// Returns the group number of this position. If None, this group refers to 313 /// all results. 314 Optional<unsigned> getResultGroupNumber() const { return std::get<1>(key); } 315 316 /// Returns if the result group has unknown size. If false, the result group 317 /// has at max one element. 318 bool isVariadic() const { return std::get<2>(key); } 319 }; 320 321 //===----------------------------------------------------------------------===// 322 // TypePosition 323 324 /// A position describing the result type of an entity, i.e. an Attribute, 325 /// Operand, Result, etc. 326 struct TypePosition : public PredicateBase<TypePosition, Position, Position *, 327 Predicates::TypePos> { 328 explicit TypePosition(const KeyTy &key) : Base(key) { 329 assert((isa<AttributePosition, OperandPosition, OperandGroupPosition, 330 ResultPosition, ResultGroupPosition>(key)) && 331 "expected parent to be an attribute, operand, or result"); 332 parent = key; 333 } 334 }; 335 336 //===----------------------------------------------------------------------===// 337 // TypeLiteralPosition 338 339 /// A position describing a literal type or type range. The value is stored as 340 /// either a TypeAttr, or an ArrayAttr of TypeAttr. 341 struct TypeLiteralPosition 342 : public PredicateBase<TypeLiteralPosition, Position, Attribute, 343 Predicates::TypeLiteralPos> { 344 using PredicateBase::PredicateBase; 345 }; 346 347 //===----------------------------------------------------------------------===// 348 // UsersPosition 349 350 /// A position describing the users of a value or a range of values. The second 351 /// value in the key indicates whether we choose users of a representative for 352 /// a range (this is true, e.g., in the upward traversals). 353 struct UsersPosition 354 : public PredicateBase<UsersPosition, Position, std::pair<Position *, bool>, 355 Predicates::UsersPos> { 356 explicit UsersPosition(const KeyTy &key) : Base(key) { parent = key.first; } 357 358 /// Returns a hash suitable for the given keytype. 359 static llvm::hash_code hashKey(const KeyTy &key) { 360 return llvm::hash_value(key); 361 } 362 363 /// Indicates whether to compute a range of a representative. 364 bool useRepresentative() const { return key.second; } 365 }; 366 367 //===----------------------------------------------------------------------===// 368 // Qualifiers 369 //===----------------------------------------------------------------------===// 370 371 /// An ordinal predicate consists of a "Question" and a set of acceptable 372 /// "Answers" (later converted to ordinal values). A predicate will query some 373 /// property of a positional value and decide what to do based on the result. 374 /// 375 /// This makes top-level predicate representations ordinal (SwitchOp). Later, 376 /// predicates that end up with only one acceptable answer (including all 377 /// boolean kinds) will be converted to boolean predicates (PredicateOp) in the 378 /// matcher. 379 /// 380 /// For simplicity, both are represented as "qualifiers", with a base kind and 381 /// perhaps additional properties. For example, all OperationName predicates ask 382 /// the same question, but GenericConstraint predicates may ask different ones. 383 class Qualifier : public StorageUniquer::BaseStorage { 384 public: 385 explicit Qualifier(Predicates::Kind kind) : kind(kind) {} 386 387 /// Returns the kind of this qualifier. 388 Predicates::Kind getKind() const { return kind; } 389 390 private: 391 /// The kind of this position. 392 Predicates::Kind kind; 393 }; 394 395 //===----------------------------------------------------------------------===// 396 // Answers 397 398 /// An Answer representing an `Attribute` value. 399 struct AttributeAnswer 400 : public PredicateBase<AttributeAnswer, Qualifier, Attribute, 401 Predicates::AttributeAnswer> { 402 using Base::Base; 403 }; 404 405 /// An Answer representing an `OperationName` value. 406 struct OperationNameAnswer 407 : public PredicateBase<OperationNameAnswer, Qualifier, OperationName, 408 Predicates::OperationNameAnswer> { 409 using Base::Base; 410 }; 411 412 /// An Answer representing a boolean `true` value. 413 struct TrueAnswer 414 : PredicateBase<TrueAnswer, Qualifier, void, Predicates::TrueAnswer> { 415 using Base::Base; 416 }; 417 418 /// An Answer representing a boolean 'false' value. 419 struct FalseAnswer 420 : PredicateBase<FalseAnswer, Qualifier, void, Predicates::FalseAnswer> { 421 using Base::Base; 422 }; 423 424 /// An Answer representing a `Type` value. The value is stored as either a 425 /// TypeAttr, or an ArrayAttr of TypeAttr. 426 struct TypeAnswer : public PredicateBase<TypeAnswer, Qualifier, Attribute, 427 Predicates::TypeAnswer> { 428 using Base::Base; 429 }; 430 431 /// An Answer representing an unsigned value. 432 struct UnsignedAnswer 433 : public PredicateBase<UnsignedAnswer, Qualifier, unsigned, 434 Predicates::UnsignedAnswer> { 435 using Base::Base; 436 }; 437 438 //===----------------------------------------------------------------------===// 439 // Questions 440 441 /// Compare an `Attribute` to a constant value. 442 struct AttributeQuestion 443 : public PredicateBase<AttributeQuestion, Qualifier, void, 444 Predicates::AttributeQuestion> {}; 445 446 /// Apply a parameterized constraint to multiple position values. 447 struct ConstraintQuestion 448 : public PredicateBase< 449 ConstraintQuestion, Qualifier, 450 std::tuple<StringRef, ArrayRef<Position *>, Attribute>, 451 Predicates::ConstraintQuestion> { 452 using Base::Base; 453 454 /// Return the name of the constraint. 455 StringRef getName() const { return std::get<0>(key); } 456 457 /// Return the arguments of the constraint. 458 ArrayRef<Position *> getArgs() const { return std::get<1>(key); } 459 460 /// Return the constant parameters of the constraint. 461 ArrayAttr getParams() const { 462 return std::get<2>(key).dyn_cast_or_null<ArrayAttr>(); 463 } 464 465 /// Construct an instance with the given storage allocator. 466 static ConstraintQuestion *construct(StorageUniquer::StorageAllocator &alloc, 467 KeyTy key) { 468 return Base::construct(alloc, KeyTy{alloc.copyInto(std::get<0>(key)), 469 alloc.copyInto(std::get<1>(key)), 470 std::get<2>(key)}); 471 } 472 }; 473 474 /// Compare the equality of two values. 475 struct EqualToQuestion 476 : public PredicateBase<EqualToQuestion, Qualifier, Position *, 477 Predicates::EqualToQuestion> { 478 using Base::Base; 479 }; 480 481 /// Compare a positional value with null, i.e. check if it exists. 482 struct IsNotNullQuestion 483 : public PredicateBase<IsNotNullQuestion, Qualifier, void, 484 Predicates::IsNotNullQuestion> {}; 485 486 /// Compare the number of operands of an operation with a known value. 487 struct OperandCountQuestion 488 : public PredicateBase<OperandCountQuestion, Qualifier, void, 489 Predicates::OperandCountQuestion> {}; 490 struct OperandCountAtLeastQuestion 491 : public PredicateBase<OperandCountAtLeastQuestion, Qualifier, void, 492 Predicates::OperandCountAtLeastQuestion> {}; 493 494 /// Compare the name of an operation with a known value. 495 struct OperationNameQuestion 496 : public PredicateBase<OperationNameQuestion, Qualifier, void, 497 Predicates::OperationNameQuestion> {}; 498 499 /// Compare the number of results of an operation with a known value. 500 struct ResultCountQuestion 501 : public PredicateBase<ResultCountQuestion, Qualifier, void, 502 Predicates::ResultCountQuestion> {}; 503 struct ResultCountAtLeastQuestion 504 : public PredicateBase<ResultCountAtLeastQuestion, Qualifier, void, 505 Predicates::ResultCountAtLeastQuestion> {}; 506 507 /// Compare the type of an attribute or value with a known type. 508 struct TypeQuestion : public PredicateBase<TypeQuestion, Qualifier, void, 509 Predicates::TypeQuestion> {}; 510 511 //===----------------------------------------------------------------------===// 512 // PredicateUniquer 513 //===----------------------------------------------------------------------===// 514 515 /// This class provides a storage uniquer that is used to allocate predicate 516 /// instances. 517 class PredicateUniquer : public StorageUniquer { 518 public: 519 PredicateUniquer() { 520 // Register the types of Positions with the uniquer. 521 registerParametricStorageType<AttributePosition>(); 522 registerParametricStorageType<AttributeLiteralPosition>(); 523 registerParametricStorageType<ForEachPosition>(); 524 registerParametricStorageType<OperandPosition>(); 525 registerParametricStorageType<OperandGroupPosition>(); 526 registerParametricStorageType<OperationPosition>(); 527 registerParametricStorageType<ResultPosition>(); 528 registerParametricStorageType<ResultGroupPosition>(); 529 registerParametricStorageType<TypePosition>(); 530 registerParametricStorageType<TypeLiteralPosition>(); 531 registerParametricStorageType<UsersPosition>(); 532 533 // Register the types of Questions with the uniquer. 534 registerParametricStorageType<AttributeAnswer>(); 535 registerParametricStorageType<OperationNameAnswer>(); 536 registerParametricStorageType<TypeAnswer>(); 537 registerParametricStorageType<UnsignedAnswer>(); 538 registerSingletonStorageType<FalseAnswer>(); 539 registerSingletonStorageType<TrueAnswer>(); 540 541 // Register the types of Answers with the uniquer. 542 registerParametricStorageType<ConstraintQuestion>(); 543 registerParametricStorageType<EqualToQuestion>(); 544 registerSingletonStorageType<AttributeQuestion>(); 545 registerSingletonStorageType<IsNotNullQuestion>(); 546 registerSingletonStorageType<OperandCountQuestion>(); 547 registerSingletonStorageType<OperandCountAtLeastQuestion>(); 548 registerSingletonStorageType<OperationNameQuestion>(); 549 registerSingletonStorageType<ResultCountQuestion>(); 550 registerSingletonStorageType<ResultCountAtLeastQuestion>(); 551 registerSingletonStorageType<TypeQuestion>(); 552 } 553 }; 554 555 //===----------------------------------------------------------------------===// 556 // PredicateBuilder 557 //===----------------------------------------------------------------------===// 558 559 /// This class provides utilities for constructing predicates. 560 class PredicateBuilder { 561 public: 562 PredicateBuilder(PredicateUniquer &uniquer, MLIRContext *ctx) 563 : uniquer(uniquer), ctx(ctx) {} 564 565 //===--------------------------------------------------------------------===// 566 // Positions 567 //===--------------------------------------------------------------------===// 568 569 /// Returns the root operation position. 570 Position *getRoot() { return OperationPosition::getRoot(uniquer); } 571 572 /// Returns the parent position defining the value held by the given operand. 573 OperationPosition *getOperandDefiningOp(Position *p) { 574 assert((isa<OperandPosition, OperandGroupPosition>(p)) && 575 "expected operand position"); 576 return OperationPosition::get(uniquer, p); 577 } 578 579 /// Returns the operation position equivalent to the given position. 580 OperationPosition *getPassthroughOp(Position *p) { 581 assert((isa<ForEachPosition>(p)) && "expected users position"); 582 return OperationPosition::get(uniquer, p); 583 } 584 585 /// Returns an attribute position for an attribute of the given operation. 586 Position *getAttribute(OperationPosition *p, StringRef name) { 587 return AttributePosition::get(uniquer, p, StringAttr::get(ctx, name)); 588 } 589 590 /// Returns an attribute position for the given attribute. 591 Position *getAttributeLiteral(Attribute attr) { 592 return AttributeLiteralPosition::get(uniquer, attr); 593 } 594 595 Position *getForEach(Position *p, unsigned id) { 596 return ForEachPosition::get(uniquer, p, id); 597 } 598 599 /// Returns an operand position for an operand of the given operation. 600 Position *getOperand(OperationPosition *p, unsigned operand) { 601 return OperandPosition::get(uniquer, p, operand); 602 } 603 604 /// Returns a position for a group of operands of the given operation. 605 Position *getOperandGroup(OperationPosition *p, Optional<unsigned> group, 606 bool isVariadic) { 607 return OperandGroupPosition::get(uniquer, p, group, isVariadic); 608 } 609 Position *getAllOperands(OperationPosition *p) { 610 return getOperandGroup(p, /*group=*/llvm::None, /*isVariadic=*/true); 611 } 612 613 /// Returns a result position for a result of the given operation. 614 Position *getResult(OperationPosition *p, unsigned result) { 615 return ResultPosition::get(uniquer, p, result); 616 } 617 618 /// Returns a position for a group of results of the given operation. 619 Position *getResultGroup(OperationPosition *p, Optional<unsigned> group, 620 bool isVariadic) { 621 return ResultGroupPosition::get(uniquer, p, group, isVariadic); 622 } 623 Position *getAllResults(OperationPosition *p) { 624 return getResultGroup(p, /*group=*/llvm::None, /*isVariadic=*/true); 625 } 626 627 /// Returns a type position for the given entity. 628 Position *getType(Position *p) { return TypePosition::get(uniquer, p); } 629 630 /// Returns a type position for the given type value. The value is stored 631 /// as either a TypeAttr, or an ArrayAttr of TypeAttr. 632 Position *getTypeLiteral(Attribute attr) { 633 return TypeLiteralPosition::get(uniquer, attr); 634 } 635 636 /// Returns the users of a position using the value at the given operand. 637 UsersPosition *getUsers(Position *p, bool useRepresentative) { 638 assert((isa<OperandPosition, OperandGroupPosition, ResultPosition, 639 ResultGroupPosition>(p)) && 640 "expected result position"); 641 return UsersPosition::get(uniquer, p, useRepresentative); 642 } 643 644 //===--------------------------------------------------------------------===// 645 // Qualifiers 646 //===--------------------------------------------------------------------===// 647 648 /// An ordinal predicate consists of a "Question" and a set of acceptable 649 /// "Answers" (later converted to ordinal values). A predicate will query some 650 /// property of a positional value and decide what to do based on the result. 651 using Predicate = std::pair<Qualifier *, Qualifier *>; 652 653 /// Create a predicate comparing an attribute to a known value. 654 Predicate getAttributeConstraint(Attribute attr) { 655 return {AttributeQuestion::get(uniquer), 656 AttributeAnswer::get(uniquer, attr)}; 657 } 658 659 /// Create a predicate checking if two values are equal. 660 Predicate getEqualTo(Position *pos) { 661 return {EqualToQuestion::get(uniquer, pos), TrueAnswer::get(uniquer)}; 662 } 663 664 /// Create a predicate checking if two values are not equal. 665 Predicate getNotEqualTo(Position *pos) { 666 return {EqualToQuestion::get(uniquer, pos), FalseAnswer::get(uniquer)}; 667 } 668 669 /// Create a predicate that applies a generic constraint. 670 Predicate getConstraint(StringRef name, ArrayRef<Position *> pos, 671 Attribute params) { 672 return { 673 ConstraintQuestion::get(uniquer, std::make_tuple(name, pos, params)), 674 TrueAnswer::get(uniquer)}; 675 } 676 677 /// Create a predicate comparing a value with null. 678 Predicate getIsNotNull() { 679 return {IsNotNullQuestion::get(uniquer), TrueAnswer::get(uniquer)}; 680 } 681 682 /// Create a predicate comparing the number of operands of an operation to a 683 /// known value. 684 Predicate getOperandCount(unsigned count) { 685 return {OperandCountQuestion::get(uniquer), 686 UnsignedAnswer::get(uniquer, count)}; 687 } 688 Predicate getOperandCountAtLeast(unsigned count) { 689 return {OperandCountAtLeastQuestion::get(uniquer), 690 UnsignedAnswer::get(uniquer, count)}; 691 } 692 693 /// Create a predicate comparing the name of an operation to a known value. 694 Predicate getOperationName(StringRef name) { 695 return {OperationNameQuestion::get(uniquer), 696 OperationNameAnswer::get(uniquer, OperationName(name, ctx))}; 697 } 698 699 /// Create a predicate comparing the number of results of an operation to a 700 /// known value. 701 Predicate getResultCount(unsigned count) { 702 return {ResultCountQuestion::get(uniquer), 703 UnsignedAnswer::get(uniquer, count)}; 704 } 705 Predicate getResultCountAtLeast(unsigned count) { 706 return {ResultCountAtLeastQuestion::get(uniquer), 707 UnsignedAnswer::get(uniquer, count)}; 708 } 709 710 /// Create a predicate comparing the type of an attribute or value to a known 711 /// type. The value is stored as either a TypeAttr, or an ArrayAttr of 712 /// TypeAttr. 713 Predicate getTypeConstraint(Attribute type) { 714 return {TypeQuestion::get(uniquer), TypeAnswer::get(uniquer, type)}; 715 } 716 717 private: 718 /// The uniquer used when allocating predicate nodes. 719 PredicateUniquer &uniquer; 720 721 /// The current MLIR context. 722 MLIRContext *ctx; 723 }; 724 725 } // namespace pdl_to_pdl_interp 726 } // namespace mlir 727 728 #endif // MLIR_CONVERSION_PDLTOPDLINTERP_PREDICATE_H_ 729