785 lines · c
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-exception6//7//===----------------------------------------------------------------------===//8//9// This file contains definitions for "predicates" used when converting PDL into10// a matcher tree. Predicates are composed of three different parts:11//12// * Positions13// - A position refers to a specific location on the input DAG, i.e. an14// existing MLIR entity being matched. These can be attributes, operands,15// operations, results, and types. Each position also defines a relation to16// its parent. For example, the operand `[0] -> 1` has a parent operation17// position `[0]`. The attribute `[0, 1] -> "myAttr"` has parent operation18// position of `[0, 1]`. The operation `[0, 1]` has a parent operand edge19// `[0] -> 1` (i.e. it is the defining op of operand 1). The only position20// without a parent is `[0]`, which refers to the root operation.21// * Questions22// - A question refers to a query on a specific positional value. For23// example, an operation name question checks the name of an operation24// position.25// * Answers26// - An answer is the expected result of a question. For example, when27// matching an operation with the name "foo.op". The question would be an28// 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 40namespace mlir {41namespace pdl_to_pdl_interp {42namespace Predicates {43/// An enumeration of the kinds of predicates.44enum Kind : unsigned {45 /// Positions, ordered by decreasing priority.46 OperationPos,47 OperandPos,48 OperandGroupPos,49 AttributePos,50 ConstraintResultPos,51 ResultPos,52 ResultGroupPos,53 TypePos,54 AttributeLiteralPos,55 TypeLiteralPos,56 UsersPos,57 ForEachPos,58 59 // Questions, ordered by dependency and decreasing priority.60 IsNotNullQuestion,61 OperationNameQuestion,62 TypeQuestion,63 AttributeQuestion,64 OperandCountAtLeastQuestion,65 OperandCountQuestion,66 ResultCountAtLeastQuestion,67 ResultCountQuestion,68 EqualToQuestion,69 ConstraintQuestion,70 71 // Answers.72 AttributeAnswer,73 FalseAnswer,74 OperationNameAnswer,75 TrueAnswer,76 TypeAnswer,77 UnsignedAnswer,78};79} // namespace Predicates80 81/// Base class for all predicates, used to allow efficient pointer comparison.82template <typename ConcreteT, typename BaseT, typename Key,83 Predicates::Kind Kind>84class PredicateBase : public BaseT {85public:86 using KeyTy = Key;87 using Base = PredicateBase<ConcreteT, BaseT, Key, Kind>;88 89 template <typename KeyT>90 explicit PredicateBase(KeyT &&key)91 : BaseT(Kind), key(std::forward<KeyT>(key)) {}92 93 /// Get an instance of this position.94 template <typename... Args>95 static ConcreteT *get(StorageUniquer &uniquer, Args &&...args) {96 return uniquer.get<ConcreteT>(/*initFn=*/{}, std::forward<Args>(args)...);97 }98 99 /// Construct an instance with the given storage allocator.100 template <typename KeyT>101 static ConcreteT *construct(StorageUniquer::StorageAllocator &alloc,102 KeyT &&key) {103 return new (alloc.allocate<ConcreteT>()) ConcreteT(std::forward<KeyT>(key));104 }105 106 /// Utility methods required by the storage allocator.107 bool operator==(const KeyTy &key) const { return this->key == key; }108 static bool classof(const BaseT *pred) { return pred->getKind() == Kind; }109 110 /// Return the key value of this predicate.111 const KeyTy &getValue() const { return key; }112 113protected:114 KeyTy key;115};116 117/// Base storage for simple predicates that only unique with the kind.118template <typename ConcreteT, typename BaseT, Predicates::Kind Kind>119class PredicateBase<ConcreteT, BaseT, void, Kind> : public BaseT {120public:121 using Base = PredicateBase<ConcreteT, BaseT, void, Kind>;122 123 explicit PredicateBase() : BaseT(Kind) {}124 125 static ConcreteT *get(StorageUniquer &uniquer) {126 return uniquer.get<ConcreteT>();127 }128 static bool classof(const BaseT *pred) { return pred->getKind() == Kind; }129};130 131//===----------------------------------------------------------------------===//132// Positions133//===----------------------------------------------------------------------===//134 135struct OperationPosition;136 137/// A position describes a value on the input IR on which a predicate may be138/// applied, such as an operation or attribute. This enables re-use between139/// predicates, and assists generating bytecode and memory management.140///141/// Operation positions form the base of other positions, which are formed142/// relative to a parent operation. Operations are anchored at Operand nodes,143/// except for the root operation which is parentless.144class Position : public StorageUniquer::BaseStorage {145public:146 explicit Position(Predicates::Kind kind) : kind(kind) {}147 virtual ~Position();148 149 /// Returns the depth of the first ancestor operation position.150 unsigned getOperationDepth() const;151 152 /// Returns the parent position. The root operation position has no parent.153 Position *getParent() const { return parent; }154 155 /// Returns the kind of this position.156 Predicates::Kind getKind() const { return kind; }157 158protected:159 /// Link to the parent position.160 Position *parent = nullptr;161 162private:163 /// The kind of this position.164 Predicates::Kind kind;165};166 167//===----------------------------------------------------------------------===//168// AttributePosition169//===----------------------------------------------------------------------===//170 171/// A position describing an attribute of an operation.172struct AttributePosition173 : public PredicateBase<AttributePosition, Position,174 std::pair<OperationPosition *, StringAttr>,175 Predicates::AttributePos> {176 explicit AttributePosition(const KeyTy &key);177 178 /// Returns the attribute name of this position.179 StringAttr getName() const { return key.second; }180};181 182//===----------------------------------------------------------------------===//183// AttributeLiteralPosition184//===----------------------------------------------------------------------===//185 186/// A position describing a literal attribute.187struct AttributeLiteralPosition188 : public PredicateBase<AttributeLiteralPosition, Position, Attribute,189 Predicates::AttributeLiteralPos> {190 using PredicateBase::PredicateBase;191};192 193//===----------------------------------------------------------------------===//194// ForEachPosition195//===----------------------------------------------------------------------===//196 197/// A position describing an iterative choice of an operation.198struct ForEachPosition : public PredicateBase<ForEachPosition, Position,199 std::pair<Position *, unsigned>,200 Predicates::ForEachPos> {201 explicit ForEachPosition(const KeyTy &key) : Base(key) { parent = key.first; }202 203 /// Returns the ID, for differentiating various loops.204 /// For upward traversals, this is the index of the root.205 unsigned getID() const { return key.second; }206};207 208//===----------------------------------------------------------------------===//209// OperandPosition210//===----------------------------------------------------------------------===//211 212/// A position describing an operand of an operation.213struct OperandPosition214 : public PredicateBase<OperandPosition, Position,215 std::pair<OperationPosition *, unsigned>,216 Predicates::OperandPos> {217 explicit OperandPosition(const KeyTy &key);218 219 /// Returns the operand number of this position.220 unsigned getOperandNumber() const { return key.second; }221};222 223//===----------------------------------------------------------------------===//224// OperandGroupPosition225//===----------------------------------------------------------------------===//226 227/// A position describing an operand group of an operation.228struct OperandGroupPosition229 : public PredicateBase<230 OperandGroupPosition, Position,231 std::tuple<OperationPosition *, std::optional<unsigned>, bool>,232 Predicates::OperandGroupPos> {233 explicit OperandGroupPosition(const KeyTy &key);234 235 /// Returns a hash suitable for the given keytype.236 static llvm::hash_code hashKey(const KeyTy &key) {237 return llvm::hash_value(key);238 }239 240 /// Returns the group number of this position. If std::nullopt, this group241 /// refers to all operands.242 std::optional<unsigned> getOperandGroupNumber() const {243 return std::get<1>(key);244 }245 246 /// Returns if the operand group has unknown size. If false, the operand group247 /// has at max one element.248 bool isVariadic() const { return std::get<2>(key); }249};250 251//===----------------------------------------------------------------------===//252// OperationPosition253//===----------------------------------------------------------------------===//254 255/// An operation position describes an operation node in the IR. Other position256/// kinds are formed with respect to an operation position.257struct OperationPosition : public PredicateBase<OperationPosition, Position,258 std::pair<Position *, unsigned>,259 Predicates::OperationPos> {260 explicit OperationPosition(const KeyTy &key) : Base(key) {261 parent = key.first;262 }263 264 /// Returns a hash suitable for the given keytype.265 static llvm::hash_code hashKey(const KeyTy &key) {266 return llvm::hash_value(key);267 }268 269 /// Gets the root position.270 static OperationPosition *getRoot(StorageUniquer &uniquer) {271 return Base::get(uniquer, nullptr, 0);272 }273 274 /// Gets an operation position with the given parent.275 static OperationPosition *get(StorageUniquer &uniquer, Position *parent) {276 return Base::get(uniquer, parent, parent->getOperationDepth() + 1);277 }278 279 /// Returns the depth of this position.280 unsigned getDepth() const { return key.second; }281 282 /// Returns if this operation position corresponds to the root.283 bool isRoot() const { return getDepth() == 0; }284 285 /// Returns if this operation represents an operand defining op.286 bool isOperandDefiningOp() const;287};288 289//===----------------------------------------------------------------------===//290// ConstraintPosition291//===----------------------------------------------------------------------===//292 293struct ConstraintQuestion;294 295/// A position describing the result of a native constraint. It saves the296/// corresponding ConstraintQuestion and result index to enable referring297/// back to them298struct ConstraintPosition299 : public PredicateBase<ConstraintPosition, Position,300 std::pair<ConstraintQuestion *, unsigned>,301 Predicates::ConstraintResultPos> {302 using PredicateBase::PredicateBase;303 304 /// Returns the ConstraintQuestion to enable keeping track of the native305 /// constraint this position stems from.306 ConstraintQuestion *getQuestion() const { return key.first; }307 308 // Returns the result index of this position309 unsigned getIndex() const { return key.second; }310};311 312//===----------------------------------------------------------------------===//313// ResultPosition314//===----------------------------------------------------------------------===//315 316/// A position describing a result of an operation.317struct ResultPosition318 : public PredicateBase<ResultPosition, Position,319 std::pair<OperationPosition *, unsigned>,320 Predicates::ResultPos> {321 explicit ResultPosition(const KeyTy &key) : Base(key) { parent = key.first; }322 323 /// Returns the result number of this position.324 unsigned getResultNumber() const { return key.second; }325};326 327//===----------------------------------------------------------------------===//328// ResultGroupPosition329//===----------------------------------------------------------------------===//330 331/// A position describing a result group of an operation.332struct ResultGroupPosition333 : public PredicateBase<334 ResultGroupPosition, Position,335 std::tuple<OperationPosition *, std::optional<unsigned>, bool>,336 Predicates::ResultGroupPos> {337 explicit ResultGroupPosition(const KeyTy &key) : Base(key) {338 parent = std::get<0>(key);339 }340 341 /// Returns a hash suitable for the given keytype.342 static llvm::hash_code hashKey(const KeyTy &key) {343 return llvm::hash_value(key);344 }345 346 /// Returns the group number of this position. If std::nullopt, this group347 /// refers to all results.348 std::optional<unsigned> getResultGroupNumber() const {349 return std::get<1>(key);350 }351 352 /// Returns if the result group has unknown size. If false, the result group353 /// has at max one element.354 bool isVariadic() const { return std::get<2>(key); }355};356 357//===----------------------------------------------------------------------===//358// TypePosition359//===----------------------------------------------------------------------===//360 361/// A position describing the result type of an entity, i.e. an Attribute,362/// Operand, Result, etc.363struct TypePosition : public PredicateBase<TypePosition, Position, Position *,364 Predicates::TypePos> {365 explicit TypePosition(const KeyTy &key) : Base(key) {366 assert((isa<AttributePosition, OperandPosition, OperandGroupPosition,367 ResultPosition, ResultGroupPosition>(key)) &&368 "expected parent to be an attribute, operand, or result");369 parent = key;370 }371};372 373//===----------------------------------------------------------------------===//374// TypeLiteralPosition375//===----------------------------------------------------------------------===//376 377/// A position describing a literal type or type range. The value is stored as378/// either a TypeAttr, or an ArrayAttr of TypeAttr.379struct TypeLiteralPosition380 : public PredicateBase<TypeLiteralPosition, Position, Attribute,381 Predicates::TypeLiteralPos> {382 using PredicateBase::PredicateBase;383};384 385//===----------------------------------------------------------------------===//386// UsersPosition387//===----------------------------------------------------------------------===//388 389/// A position describing the users of a value or a range of values. The second390/// value in the key indicates whether we choose users of a representative for391/// a range (this is true, e.g., in the upward traversals).392struct UsersPosition393 : public PredicateBase<UsersPosition, Position, std::pair<Position *, bool>,394 Predicates::UsersPos> {395 explicit UsersPosition(const KeyTy &key) : Base(key) { parent = key.first; }396 397 /// Returns a hash suitable for the given keytype.398 static llvm::hash_code hashKey(const KeyTy &key) {399 return llvm::hash_value(key);400 }401 402 /// Indicates whether to compute a range of a representative.403 bool useRepresentative() const { return key.second; }404};405 406//===----------------------------------------------------------------------===//407// Qualifiers408//===----------------------------------------------------------------------===//409 410/// An ordinal predicate consists of a "Question" and a set of acceptable411/// "Answers" (later converted to ordinal values). A predicate will query some412/// property of a positional value and decide what to do based on the result.413///414/// This makes top-level predicate representations ordinal (SwitchOp). Later,415/// predicates that end up with only one acceptable answer (including all416/// boolean kinds) will be converted to boolean predicates (PredicateOp) in the417/// matcher.418///419/// For simplicity, both are represented as "qualifiers", with a base kind and420/// perhaps additional properties. For example, all OperationName predicates ask421/// the same question, but GenericConstraint predicates may ask different ones.422class Qualifier : public StorageUniquer::BaseStorage {423public:424 explicit Qualifier(Predicates::Kind kind) : kind(kind) {}425 426 /// Returns the kind of this qualifier.427 Predicates::Kind getKind() const { return kind; }428 429private:430 /// The kind of this position.431 Predicates::Kind kind;432};433 434//===----------------------------------------------------------------------===//435// Answers436//===----------------------------------------------------------------------===//437 438/// An Answer representing an `Attribute` value.439struct AttributeAnswer440 : public PredicateBase<AttributeAnswer, Qualifier, Attribute,441 Predicates::AttributeAnswer> {442 using Base::Base;443};444 445/// An Answer representing an `OperationName` value.446struct OperationNameAnswer447 : public PredicateBase<OperationNameAnswer, Qualifier, OperationName,448 Predicates::OperationNameAnswer> {449 using Base::Base;450};451 452/// An Answer representing a boolean `true` value.453struct TrueAnswer454 : PredicateBase<TrueAnswer, Qualifier, void, Predicates::TrueAnswer> {455 using Base::Base;456};457 458/// An Answer representing a boolean 'false' value.459struct FalseAnswer460 : PredicateBase<FalseAnswer, Qualifier, void, Predicates::FalseAnswer> {461 using Base::Base;462};463 464/// An Answer representing a `Type` value. The value is stored as either a465/// TypeAttr, or an ArrayAttr of TypeAttr.466struct TypeAnswer : public PredicateBase<TypeAnswer, Qualifier, Attribute,467 Predicates::TypeAnswer> {468 using Base::Base;469};470 471/// An Answer representing an unsigned value.472struct UnsignedAnswer473 : public PredicateBase<UnsignedAnswer, Qualifier, unsigned,474 Predicates::UnsignedAnswer> {475 using Base::Base;476};477 478//===----------------------------------------------------------------------===//479// Questions480//===----------------------------------------------------------------------===//481 482/// Compare an `Attribute` to a constant value.483struct AttributeQuestion484 : public PredicateBase<AttributeQuestion, Qualifier, void,485 Predicates::AttributeQuestion> {};486 487/// Apply a parameterized constraint to multiple position values and possibly488/// produce results.489struct ConstraintQuestion490 : public PredicateBase<491 ConstraintQuestion, Qualifier,492 std::tuple<StringRef, ArrayRef<Position *>, ArrayRef<Type>, bool>,493 Predicates::ConstraintQuestion> {494 using Base::Base;495 496 /// Return the name of the constraint.497 StringRef getName() const { return std::get<0>(key); }498 499 /// Return the arguments of the constraint.500 ArrayRef<Position *> getArgs() const { return std::get<1>(key); }501 502 /// Return the result types of the constraint.503 ArrayRef<Type> getResultTypes() const { return std::get<2>(key); }504 505 /// Return the negation status of the constraint.506 bool getIsNegated() const { return std::get<3>(key); }507 508 /// Construct an instance with the given storage allocator.509 static ConstraintQuestion *construct(StorageUniquer::StorageAllocator &alloc,510 KeyTy key) {511 return Base::construct(alloc, KeyTy{alloc.copyInto(std::get<0>(key)),512 alloc.copyInto(std::get<1>(key)),513 alloc.copyInto(std::get<2>(key)),514 std::get<3>(key)});515 }516 517 /// Returns a hash suitable for the given keytype.518 static llvm::hash_code hashKey(const KeyTy &key) {519 return llvm::hash_value(key);520 }521};522 523/// Compare the equality of two values.524struct EqualToQuestion525 : public PredicateBase<EqualToQuestion, Qualifier, Position *,526 Predicates::EqualToQuestion> {527 using Base::Base;528};529 530/// Compare a positional value with null, i.e. check if it exists.531struct IsNotNullQuestion532 : public PredicateBase<IsNotNullQuestion, Qualifier, void,533 Predicates::IsNotNullQuestion> {};534 535/// Compare the number of operands of an operation with a known value.536struct OperandCountQuestion537 : public PredicateBase<OperandCountQuestion, Qualifier, void,538 Predicates::OperandCountQuestion> {};539struct OperandCountAtLeastQuestion540 : public PredicateBase<OperandCountAtLeastQuestion, Qualifier, void,541 Predicates::OperandCountAtLeastQuestion> {};542 543/// Compare the name of an operation with a known value.544struct OperationNameQuestion545 : public PredicateBase<OperationNameQuestion, Qualifier, void,546 Predicates::OperationNameQuestion> {};547 548/// Compare the number of results of an operation with a known value.549struct ResultCountQuestion550 : public PredicateBase<ResultCountQuestion, Qualifier, void,551 Predicates::ResultCountQuestion> {};552struct ResultCountAtLeastQuestion553 : public PredicateBase<ResultCountAtLeastQuestion, Qualifier, void,554 Predicates::ResultCountAtLeastQuestion> {};555 556/// Compare the type of an attribute or value with a known type.557struct TypeQuestion : public PredicateBase<TypeQuestion, Qualifier, void,558 Predicates::TypeQuestion> {};559 560//===----------------------------------------------------------------------===//561// PredicateUniquer562//===----------------------------------------------------------------------===//563 564/// This class provides a storage uniquer that is used to allocate predicate565/// instances.566class PredicateUniquer : public StorageUniquer {567public:568 PredicateUniquer() {569 // Register the types of Positions with the uniquer.570 registerParametricStorageType<AttributePosition>();571 registerParametricStorageType<AttributeLiteralPosition>();572 registerParametricStorageType<ConstraintPosition>();573 registerParametricStorageType<ForEachPosition>();574 registerParametricStorageType<OperandPosition>();575 registerParametricStorageType<OperandGroupPosition>();576 registerParametricStorageType<OperationPosition>();577 registerParametricStorageType<ResultPosition>();578 registerParametricStorageType<ResultGroupPosition>();579 registerParametricStorageType<TypePosition>();580 registerParametricStorageType<TypeLiteralPosition>();581 registerParametricStorageType<UsersPosition>();582 583 // Register the types of Questions with the uniquer.584 registerParametricStorageType<AttributeAnswer>();585 registerParametricStorageType<OperationNameAnswer>();586 registerParametricStorageType<TypeAnswer>();587 registerParametricStorageType<UnsignedAnswer>();588 registerSingletonStorageType<FalseAnswer>();589 registerSingletonStorageType<TrueAnswer>();590 591 // Register the types of Answers with the uniquer.592 registerParametricStorageType<ConstraintQuestion>();593 registerParametricStorageType<EqualToQuestion>();594 registerSingletonStorageType<AttributeQuestion>();595 registerSingletonStorageType<IsNotNullQuestion>();596 registerSingletonStorageType<OperandCountQuestion>();597 registerSingletonStorageType<OperandCountAtLeastQuestion>();598 registerSingletonStorageType<OperationNameQuestion>();599 registerSingletonStorageType<ResultCountQuestion>();600 registerSingletonStorageType<ResultCountAtLeastQuestion>();601 registerSingletonStorageType<TypeQuestion>();602 }603};604 605//===----------------------------------------------------------------------===//606// PredicateBuilder607//===----------------------------------------------------------------------===//608 609/// This class provides utilities for constructing predicates.610class PredicateBuilder {611public:612 PredicateBuilder(PredicateUniquer &uniquer, MLIRContext *ctx)613 : uniquer(uniquer), ctx(ctx) {}614 615 //===--------------------------------------------------------------------===//616 // Positions617 //===--------------------------------------------------------------------===//618 619 /// Returns the root operation position.620 Position *getRoot() { return OperationPosition::getRoot(uniquer); }621 622 /// Returns the parent position defining the value held by the given operand.623 OperationPosition *getOperandDefiningOp(Position *p) {624 assert((isa<OperandPosition, OperandGroupPosition>(p)) &&625 "expected operand position");626 return OperationPosition::get(uniquer, p);627 }628 629 /// Returns the operation position equivalent to the given position.630 OperationPosition *getPassthroughOp(Position *p) {631 assert((isa<ForEachPosition>(p)) && "expected users position");632 return OperationPosition::get(uniquer, p);633 }634 635 // Returns a position for a new value created by a constraint.636 ConstraintPosition *getConstraintPosition(ConstraintQuestion *q,637 unsigned index) {638 return ConstraintPosition::get(uniquer, std::make_pair(q, index));639 }640 641 /// Returns an attribute position for an attribute of the given operation.642 Position *getAttribute(OperationPosition *p, StringRef name) {643 return AttributePosition::get(uniquer, p, StringAttr::get(ctx, name));644 }645 646 /// Returns an attribute position for the given attribute.647 Position *getAttributeLiteral(Attribute attr) {648 return AttributeLiteralPosition::get(uniquer, attr);649 }650 651 Position *getForEach(Position *p, unsigned id) {652 return ForEachPosition::get(uniquer, p, id);653 }654 655 /// Returns an operand position for an operand of the given operation.656 Position *getOperand(OperationPosition *p, unsigned operand) {657 return OperandPosition::get(uniquer, p, operand);658 }659 660 /// Returns a position for a group of operands of the given operation.661 Position *getOperandGroup(OperationPosition *p, std::optional<unsigned> group,662 bool isVariadic) {663 return OperandGroupPosition::get(uniquer, p, group, isVariadic);664 }665 Position *getAllOperands(OperationPosition *p) {666 return getOperandGroup(p, /*group=*/std::nullopt, /*isVariadic=*/true);667 }668 669 /// Returns a result position for a result of the given operation.670 Position *getResult(OperationPosition *p, unsigned result) {671 return ResultPosition::get(uniquer, p, result);672 }673 674 /// Returns a position for a group of results of the given operation.675 Position *getResultGroup(OperationPosition *p, std::optional<unsigned> group,676 bool isVariadic) {677 return ResultGroupPosition::get(uniquer, p, group, isVariadic);678 }679 Position *getAllResults(OperationPosition *p) {680 return getResultGroup(p, /*group=*/std::nullopt, /*isVariadic=*/true);681 }682 683 /// Returns a type position for the given entity.684 Position *getType(Position *p) { return TypePosition::get(uniquer, p); }685 686 /// Returns a type position for the given type value. The value is stored687 /// as either a TypeAttr, or an ArrayAttr of TypeAttr.688 Position *getTypeLiteral(Attribute attr) {689 return TypeLiteralPosition::get(uniquer, attr);690 }691 692 /// Returns the users of a position using the value at the given operand.693 UsersPosition *getUsers(Position *p, bool useRepresentative) {694 assert((isa<OperandPosition, OperandGroupPosition, ResultPosition,695 ResultGroupPosition>(p)) &&696 "expected result position");697 return UsersPosition::get(uniquer, p, useRepresentative);698 }699 700 //===--------------------------------------------------------------------===//701 // Qualifiers702 //===--------------------------------------------------------------------===//703 704 /// An ordinal predicate consists of a "Question" and a set of acceptable705 /// "Answers" (later converted to ordinal values). A predicate will query some706 /// property of a positional value and decide what to do based on the result.707 using Predicate = std::pair<Qualifier *, Qualifier *>;708 709 /// Create a predicate comparing an attribute to a known value.710 Predicate getAttributeConstraint(Attribute attr) {711 return {AttributeQuestion::get(uniquer),712 AttributeAnswer::get(uniquer, attr)};713 }714 715 /// Create a predicate checking if two values are equal.716 Predicate getEqualTo(Position *pos) {717 return {EqualToQuestion::get(uniquer, pos), TrueAnswer::get(uniquer)};718 }719 720 /// Create a predicate checking if two values are not equal.721 Predicate getNotEqualTo(Position *pos) {722 return {EqualToQuestion::get(uniquer, pos), FalseAnswer::get(uniquer)};723 }724 725 /// Create a predicate that applies a generic constraint.726 Predicate getConstraint(StringRef name, ArrayRef<Position *> args,727 ArrayRef<Type> resultTypes, bool isNegated) {728 return {ConstraintQuestion::get(729 uniquer, std::make_tuple(name, args, resultTypes, isNegated)),730 TrueAnswer::get(uniquer)};731 }732 733 /// Create a predicate comparing a value with null.734 Predicate getIsNotNull() {735 return {IsNotNullQuestion::get(uniquer), TrueAnswer::get(uniquer)};736 }737 738 /// Create a predicate comparing the number of operands of an operation to a739 /// known value.740 Predicate getOperandCount(unsigned count) {741 return {OperandCountQuestion::get(uniquer),742 UnsignedAnswer::get(uniquer, count)};743 }744 Predicate getOperandCountAtLeast(unsigned count) {745 return {OperandCountAtLeastQuestion::get(uniquer),746 UnsignedAnswer::get(uniquer, count)};747 }748 749 /// Create a predicate comparing the name of an operation to a known value.750 Predicate getOperationName(StringRef name) {751 return {OperationNameQuestion::get(uniquer),752 OperationNameAnswer::get(uniquer, OperationName(name, ctx))};753 }754 755 /// Create a predicate comparing the number of results of an operation to a756 /// known value.757 Predicate getResultCount(unsigned count) {758 return {ResultCountQuestion::get(uniquer),759 UnsignedAnswer::get(uniquer, count)};760 }761 Predicate getResultCountAtLeast(unsigned count) {762 return {ResultCountAtLeastQuestion::get(uniquer),763 UnsignedAnswer::get(uniquer, count)};764 }765 766 /// Create a predicate comparing the type of an attribute or value to a known767 /// type. The value is stored as either a TypeAttr, or an ArrayAttr of768 /// TypeAttr.769 Predicate getTypeConstraint(Attribute type) {770 return {TypeQuestion::get(uniquer), TypeAnswer::get(uniquer, type)};771 }772 773private:774 /// The uniquer used when allocating predicate nodes.775 PredicateUniquer &uniquer;776 777 /// The current MLIR context.778 MLIRContext *ctx;779};780 781} // namespace pdl_to_pdl_interp782} // namespace mlir783 784#endif // MLIR_CONVERSION_PDLTOPDLINTERP_PREDICATE_H_785