//===- CodeGenDAGPatterns.h - Read DAG patterns from .td file ---*- C++ -*-===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
// This file declares the CodeGenDAGPatterns class, which is used to read and
// represent the patterns present in a .td file for instructions.
//
//===----------------------------------------------------------------------===//

#ifndef LLVM_UTILS_TABLEGEN_COMMON_CODEGENDAGPATTERNS_H
#define LLVM_UTILS_TABLEGEN_COMMON_CODEGENDAGPATTERNS_H

#include "Basic/CodeGenIntrinsics.h"
#include "Basic/SDNodeProperties.h"
#include "CodeGenTarget.h"
#include "llvm/ADT/IntrusiveRefCntPtr.h"
#include "llvm/ADT/MapVector.h"
#include "llvm/ADT/PointerUnion.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/StringMap.h"
#include "llvm/ADT/StringSet.h"
#include "llvm/ADT/Twine.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/MathExtras.h"
#include "llvm/TableGen/Record.h"
#include <algorithm>
#include <array>
#include <map>
#include <numeric>
#include <vector>

namespace llvm {

class Init;
class ListInit;
class DagInit;
class SDNodeInfo;
class TreePattern;
class TreePatternNode;
class CodeGenDAGPatterns;

/// Shared pointer for TreePatternNode.
using TreePatternNodePtr = IntrusiveRefCntPtr<TreePatternNode>;

/// This represents a set of MVTs. Since the underlying type for the MVT
/// is uint16_t, there are at most 65536 values. To reduce the number of memory
/// allocations and deallocations, represent the set as a sequence of bits.
/// To reduce the allocations even further, make MachineValueTypeSet own
/// the storage and use std::array as the bit container.
struct MachineValueTypeSet {
  static unsigned constexpr Capacity = 512;
  using WordType = uint64_t;
  static unsigned constexpr WordWidth = CHAR_BIT * sizeof(WordType);
  static unsigned constexpr NumWords = Capacity / WordWidth;
  static_assert(NumWords * WordWidth == Capacity,
                "Capacity should be a multiple of WordWidth");

  LLVM_ATTRIBUTE_ALWAYS_INLINE
  MachineValueTypeSet() { clear(); }

  LLVM_ATTRIBUTE_ALWAYS_INLINE
  unsigned size() const {
    unsigned Count = 0;
    for (WordType W : Words)
      Count += llvm::popcount(W);
    return Count;
  }
  LLVM_ATTRIBUTE_ALWAYS_INLINE
  void clear() { Words.fill(0); }
  LLVM_ATTRIBUTE_ALWAYS_INLINE
  bool empty() const {
    for (WordType W : Words)
      if (W != 0)
        return false;
    return true;
  }
  LLVM_ATTRIBUTE_ALWAYS_INLINE
  unsigned count(MVT T) const {
    assert(T.SimpleTy < Capacity && "Capacity needs to be enlarged");
    return (Words[T.SimpleTy / WordWidth] >> (T.SimpleTy % WordWidth)) & 1;
  }
  std::pair<MachineValueTypeSet &, bool> insert(MVT T) {
    assert(T.SimpleTy < Capacity && "Capacity needs to be enlarged");
    bool V = count(T);
    Words[T.SimpleTy / WordWidth] |= WordType(1) << (T.SimpleTy % WordWidth);
    return {*this, V};
  }
  MachineValueTypeSet &insert(const MachineValueTypeSet &S) {
    for (unsigned i = 0; i != NumWords; ++i)
      Words[i] |= S.Words[i];
    return *this;
  }
  LLVM_ATTRIBUTE_ALWAYS_INLINE
  void erase(MVT T) {
    assert(T.SimpleTy < Capacity && "Capacity needs to be enlarged");
    Words[T.SimpleTy / WordWidth] &= ~(WordType(1) << (T.SimpleTy % WordWidth));
  }

  void writeToStream(raw_ostream &OS) const;

  struct const_iterator {
    // Some implementations of the C++ library require these traits to be
    // defined.
    using iterator_category = std::forward_iterator_tag;
    using value_type = MVT;
    using difference_type = ptrdiff_t;
    using pointer = const MVT *;
    using reference = const MVT &;

    LLVM_ATTRIBUTE_ALWAYS_INLINE
    MVT operator*() const {
      assert(Pos != Capacity);
      return MVT::SimpleValueType(Pos);
    }
    LLVM_ATTRIBUTE_ALWAYS_INLINE
    const_iterator(const MachineValueTypeSet *S, bool End) : Set(S) {
      Pos = End ? Capacity : find_from_pos(0);
    }
    LLVM_ATTRIBUTE_ALWAYS_INLINE
    const_iterator &operator++() {
      assert(Pos != Capacity);
      Pos = find_from_pos(Pos + 1);
      return *this;
    }

    LLVM_ATTRIBUTE_ALWAYS_INLINE
    bool operator==(const const_iterator &It) const {
      return Set == It.Set && Pos == It.Pos;
    }
    LLVM_ATTRIBUTE_ALWAYS_INLINE
    bool operator!=(const const_iterator &It) const { return !operator==(It); }

  private:
    unsigned find_from_pos(unsigned P) const {
      unsigned SkipWords = P / WordWidth;

      for (unsigned i = SkipWords; i != NumWords; ++i) {
        WordType W = Set->Words[i];

        // If P is in the middle of a word, process it manually here, because
        // the trailing bits need to be masked off to use countr_zero.
        if (i == SkipWords) {
          unsigned SkipBits = P % WordWidth;
          W &= maskTrailingZeros<WordType>(SkipBits);
        }

        if (W != 0)
          return i * WordWidth + llvm::countr_zero(W);
      }
      return Capacity;
    }

    const MachineValueTypeSet *Set;
    unsigned Pos;
  };

  LLVM_ATTRIBUTE_ALWAYS_INLINE
  const_iterator begin() const { return const_iterator(this, false); }
  LLVM_ATTRIBUTE_ALWAYS_INLINE
  const_iterator end() const { return const_iterator(this, true); }

  LLVM_ATTRIBUTE_ALWAYS_INLINE
  bool operator==(const MachineValueTypeSet &S) const {
    return Words == S.Words;
  }
  LLVM_ATTRIBUTE_ALWAYS_INLINE
  bool operator!=(const MachineValueTypeSet &S) const { return !operator==(S); }

private:
  friend struct const_iterator;
  std::array<WordType, NumWords> Words;
};

raw_ostream &operator<<(raw_ostream &OS, const MachineValueTypeSet &T);

struct TypeSetByHwMode : public InfoByHwMode<MachineValueTypeSet> {
  using SetType = MachineValueTypeSet;
  unsigned AddrSpace = std::numeric_limits<unsigned>::max();

  TypeSetByHwMode() = default;
  TypeSetByHwMode(const TypeSetByHwMode &VTS) = default;
  TypeSetByHwMode &operator=(const TypeSetByHwMode &) = default;
  TypeSetByHwMode(MVT VT) : TypeSetByHwMode(ValueTypeByHwMode(VT)) {}
  TypeSetByHwMode(ArrayRef<ValueTypeByHwMode> VTList);

  SetType &getOrCreate(unsigned Mode) { return Map[Mode]; }

  bool isValueTypeByHwMode(bool AllowEmpty) const;
  ValueTypeByHwMode getValueTypeByHwMode(bool SkipEmpty = false) const;

  LLVM_ATTRIBUTE_ALWAYS_INLINE
  bool isMachineValueType() const {
    return isSimple() && getSimple().size() == 1;
  }

  LLVM_ATTRIBUTE_ALWAYS_INLINE
  MVT getMachineValueType() const {
    assert(isMachineValueType());
    return *getSimple().begin();
  }

  bool isPossible() const;

  bool isPointer() const { return getValueTypeByHwMode().isPointer(); }

  unsigned getPtrAddrSpace() const {
    assert(isPointer());
    return getValueTypeByHwMode().PtrAddrSpace;
  }

  bool insert(const ValueTypeByHwMode &VVT);
  bool constrain(const TypeSetByHwMode &VTS);
  template <typename Predicate> bool constrain(Predicate P);
  template <typename Predicate>
  bool assign_if(const TypeSetByHwMode &VTS, Predicate P);

  void writeToStream(raw_ostream &OS) const;

  bool operator==(const TypeSetByHwMode &VTS) const;
  bool operator!=(const TypeSetByHwMode &VTS) const { return !(*this == VTS); }

  void dump() const;
  bool validate() const;

private:
  unsigned PtrAddrSpace = std::numeric_limits<unsigned>::max();
  /// Intersect two sets. Return true if anything has changed.
  bool intersect(SetType &Out, const SetType &In);
};

raw_ostream &operator<<(raw_ostream &OS, const TypeSetByHwMode &T);

struct TypeInfer {
  TypeInfer(TreePattern &T) : TP(T) {}

  /// The protocol in the following functions (Merge*, force*, Enforce*,
  /// expand*) is to return "true" if a change has been made, "false"
  /// otherwise.

  bool MergeInTypeInfo(TypeSetByHwMode &Out, const TypeSetByHwMode &In) const;
  bool MergeInTypeInfo(TypeSetByHwMode &Out, MVT InVT) const {
    return MergeInTypeInfo(Out, TypeSetByHwMode(InVT));
  }
  bool MergeInTypeInfo(TypeSetByHwMode &Out,
                       const ValueTypeByHwMode &InVT) const {
    return MergeInTypeInfo(Out, TypeSetByHwMode(InVT));
  }

  /// Reduce the set \p Out to have at most one element for each mode.
  bool forceArbitrary(TypeSetByHwMode &Out);

  /// The following four functions ensure that upon return the set \p Out
  /// will only contain types of the specified kind: integer, floating-point,
  /// scalar, or vector.
  /// If \p Out is empty, all legal types of the specified kind will be added
  /// to it. Otherwise, all types that are not of the specified kind will be
  /// removed from \p Out.
  bool EnforceInteger(TypeSetByHwMode &Out);
  bool EnforceFloatingPoint(TypeSetByHwMode &Out);
  bool EnforceScalar(TypeSetByHwMode &Out);
  bool EnforceVector(TypeSetByHwMode &Out);

  /// If \p Out is empty, fill it with all legal types. Otherwise, leave it
  /// unchanged.
  bool EnforceAny(TypeSetByHwMode &Out);
  /// Make sure that for each type in \p Small, there exists a larger type
  /// in \p Big. \p SmallIsVT indicates that this is being called for
  /// SDTCisVTSmallerThanOp. In that case the TypeSetByHwMode is re-created for
  /// each call and needs special consideration in how we detect changes.
  bool EnforceSmallerThan(TypeSetByHwMode &Small, TypeSetByHwMode &Big,
                          bool SmallIsVT = false);
  /// 1. Ensure that for each type T in \p Vec, T is a vector type, and that
  ///    for each type U in \p Elem, U is a scalar type.
  /// 2. Ensure that for each (scalar) type U in \p Elem, there exists a
  ///    (vector) type T in \p Vec, such that U is the element type of T.
  bool EnforceVectorEltTypeIs(TypeSetByHwMode &Vec, TypeSetByHwMode &Elem);
  bool EnforceVectorEltTypeIs(TypeSetByHwMode &Vec,
                              const ValueTypeByHwMode &VVT);
  /// Ensure that for each type T in \p Sub, T is a vector type, and there
  /// exists a type U in \p Vec such that U is a vector type with the same
  /// element type as T and at least as many elements as T.
  bool EnforceVectorSubVectorTypeIs(TypeSetByHwMode &Vec, TypeSetByHwMode &Sub);
  /// 1. Ensure that \p V has a scalar type iff \p W has a scalar type.
  /// 2. Ensure that for each vector type T in \p V, there exists a vector
  ///    type U in \p W, such that T and U have the same number of elements.
  /// 3. Ensure that for each vector type U in \p W, there exists a vector
  ///    type T in \p V, such that T and U have the same number of elements
  ///    (reverse of 2).
  bool EnforceSameNumElts(TypeSetByHwMode &V, TypeSetByHwMode &W);
  /// 1. Ensure that for each type T in \p A, there exists a type U in \p B,
  ///    such that T and U have equal size in bits.
  /// 2. Ensure that for each type U in \p B, there exists a type T in \p A
  ///    such that T and U have equal size in bits (reverse of 1).
  bool EnforceSameSize(TypeSetByHwMode &A, TypeSetByHwMode &B);

  /// For each overloaded type (i.e. of form *Any), replace it with the
  /// corresponding subset of legal, specific types.
  void expandOverloads(TypeSetByHwMode &VTS) const;
  void expandOverloads(TypeSetByHwMode::SetType &Out,
                       const TypeSetByHwMode::SetType &Legal) const;

  struct ValidateOnExit {
    ValidateOnExit(const TypeSetByHwMode &T, const TypeInfer &TI)
        : Infer(TI), VTS(T) {}
    ~ValidateOnExit();
    const TypeInfer &Infer;
    const TypeSetByHwMode &VTS;
  };

  struct SuppressValidation {
    SuppressValidation(TypeInfer &TI) : Infer(TI), SavedValidate(TI.Validate) {
      Infer.Validate = false;
    }
    ~SuppressValidation() { Infer.Validate = SavedValidate; }
    TypeInfer &Infer;
    bool SavedValidate;
  };

  TreePattern &TP;
  bool Validate = true; // Indicate whether to validate types.

private:
  const TypeSetByHwMode &getLegalTypes() const;

  /// Cached legal types (in default mode).
  mutable bool LegalTypesCached = false;
  mutable TypeSetByHwMode LegalCache;
};

/// Set type used to track multiply used variables in patterns
using MultipleUseVarSet = StringSet<>;

/// SDTypeConstraint - This is a discriminated union of constraints,
/// corresponding to the SDTypeConstraint tablegen class in Target.td.
struct SDTypeConstraint {
  SDTypeConstraint() = default;
  SDTypeConstraint(const Record *R, const CodeGenHwModes &CGH);

  unsigned OperandNo; // The operand # this constraint applies to.
  enum KindTy {
    SDTCisVT,
    SDTCisPtrTy,
    SDTCisInt,
    SDTCisFP,
    SDTCisVec,
    SDTCisSameAs,
    SDTCisVTSmallerThanOp,
    SDTCisOpSmallerThanOp,
    SDTCisEltOfVec,
    SDTCisSubVecOfVec,
    SDTCVecEltisVT,
    SDTCisSameNumEltsAs,
    SDTCisSameSizeAs
  } ConstraintType;

  unsigned OtherOperandNo;

  // The VT for SDTCisVT and SDTCVecEltisVT.
  // Must not be in the union because it has a non-trivial destructor.
  ValueTypeByHwMode VVT;

  /// ApplyTypeConstraint - Given a node in a pattern, apply this type
  /// constraint to the nodes operands.  This returns true if it makes a
  /// change, false otherwise.  If a type contradiction is found, an error
  /// is flagged.
  bool ApplyTypeConstraint(TreePatternNode &N, const SDNodeInfo &NodeInfo,
                           TreePattern &TP) const;

  friend bool operator==(const SDTypeConstraint &LHS,
                         const SDTypeConstraint &RHS);
  friend bool operator<(const SDTypeConstraint &LHS,
                        const SDTypeConstraint &RHS);
};

bool operator==(const SDTypeConstraint &LHS, const SDTypeConstraint &RHS);
bool operator<(const SDTypeConstraint &LHS, const SDTypeConstraint &RHS);

/// ScopedName - A name of a node associated with a "scope" that indicates
/// the context (e.g. instance of Pattern or PatFrag) in which the name was
/// used. This enables substitution of pattern fragments while keeping track
/// of what name(s) were originally given to various nodes in the tree.
class ScopedName {
  unsigned Scope;
  std::string Identifier;

public:
  ScopedName(unsigned Scope, StringRef Identifier)
      : Scope(Scope), Identifier(Identifier.str()) {
    assert(Scope != 0 &&
           "Scope == 0 is used to indicate predicates without arguments");
  }

  unsigned getScope() const { return Scope; }
  const std::string &getIdentifier() const { return Identifier; }

  bool operator==(const ScopedName &o) const;
  bool operator!=(const ScopedName &o) const;
};

/// SDNodeInfo - One of these records is created for each SDNode instance in
/// the target .td file.  This represents the various dag nodes we will be
/// processing.
class SDNodeInfo {
  const Record *Def;
  StringRef EnumName;
  StringRef SDClassName;
  unsigned NumResults;
  int NumOperands;
  unsigned Properties;
  bool IsStrictFP;
  uint32_t TSFlags;
  std::vector<SDTypeConstraint> TypeConstraints;

public:
  // Parse the specified record.
  SDNodeInfo(const Record *R, const CodeGenHwModes &CGH);

  unsigned getNumResults() const { return NumResults; }

  /// getNumOperands - This is the number of operands required or -1 if
  /// variadic.
  int getNumOperands() const { return NumOperands; }
  const Record *getRecord() const { return Def; }
  StringRef getEnumName() const { return EnumName; }
  StringRef getSDClassName() const { return SDClassName; }

  const std::vector<SDTypeConstraint> &getTypeConstraints() const {
    return TypeConstraints;
  }

  /// getKnownType - If the type constraints on this node imply a fixed type
  /// (e.g. all stores return void, etc), then return it as an
  /// MVT.  Otherwise, return MVT::Other.
  MVT getKnownType(unsigned ResNo) const;

  unsigned getProperties() const { return Properties; }

  /// hasProperty - Return true if this node has the specified property.
  ///
  bool hasProperty(enum SDNP Prop) const { return Properties & (1 << Prop); }

  bool isStrictFP() const { return IsStrictFP; }

  uint32_t getTSFlags() const { return TSFlags; }

  /// ApplyTypeConstraints - Given a node in a pattern, apply the type
  /// constraints for this node to the operands of the node.  This returns
  /// true if it makes a change, false otherwise.  If a type contradiction is
  /// found, an error is flagged.
  bool ApplyTypeConstraints(TreePatternNode &N, TreePattern &TP) const;
};

/// TreePredicateFn - This is an abstraction that represents the predicates on
/// a PatFrag node.  This is a simple one-word wrapper around a pointer to
/// provide nice accessors.
class TreePredicateFn {
  /// PatFragRec - This is the TreePattern for the PatFrag that we
  /// originally came from.
  TreePattern *PatFragRec;

public:
  /// TreePredicateFn constructor.  Here 'N' is a subclass of PatFrag.
  TreePredicateFn(TreePattern *N);

  TreePattern *getOrigPatFragRecord() const { return PatFragRec; }

  /// isAlwaysTrue - Return true if this is a noop predicate.
  bool isAlwaysTrue() const;

  bool isImmediatePattern() const { return hasImmCode(); }

  /// getImmediatePredicateCode - Return the code that evaluates this pattern if
  /// this is an immediate predicate.  It is an error to call this on a
  /// non-immediate pattern.
  std::string getImmediatePredicateCode() const {
    std::string Result = getImmCode();
    assert(!Result.empty() && "Isn't an immediate pattern!");
    return Result;
  }

  bool operator==(const TreePredicateFn &RHS) const {
    return PatFragRec == RHS.PatFragRec;
  }

  bool operator!=(const TreePredicateFn &RHS) const { return !(*this == RHS); }

  /// Return the name to use in the generated code to reference this, this is
  /// "Predicate_foo" if from a pattern fragment "foo".
  std::string getFnName() const;

  /// getCodeToRunOnSDNode - Return the code for the function body that
  /// evaluates this predicate.  The argument is expected to be in "Node",
  /// not N.  This handles casting and conversion to a concrete node type as
  /// appropriate.
  std::string getCodeToRunOnSDNode() const;

  /// Get the data type of the argument to getImmediatePredicateCode().
  StringRef getImmType() const;

  /// Get a string that describes the type returned by getImmType() but is
  /// usable as part of an identifier.
  StringRef getImmTypeIdentifier() const;

  // Predicate code uses the PatFrag's captured operands.
  bool usesOperands() const;

  // Check if the HasNoUse predicate is set.
  bool hasNoUse() const;
  // Check if the HasOneUse predicate is set.
  bool hasOneUse() const;

  // Is the desired predefined predicate for a load?
  bool isLoad() const;
  // Is the desired predefined predicate for a store?
  bool isStore() const;
  // Is the desired predefined predicate for an atomic?
  bool isAtomic() const;

  /// Is this predicate the predefined unindexed load predicate?
  /// Is this predicate the predefined unindexed store predicate?
  bool isUnindexed() const;
  /// Is this predicate the predefined non-extending load predicate?
  bool isNonExtLoad() const;
  /// Is this predicate the predefined any-extend load predicate?
  bool isAnyExtLoad() const;
  /// Is this predicate the predefined sign-extend load predicate?
  bool isSignExtLoad() const;
  /// Is this predicate the predefined zero-extend load predicate?
  bool isZeroExtLoad() const;
  /// Is this predicate the predefined non-truncating store predicate?
  bool isNonTruncStore() const;
  /// Is this predicate the predefined truncating store predicate?
  bool isTruncStore() const;

  /// Is this predicate the predefined monotonic atomic predicate?
  bool isAtomicOrderingMonotonic() const;
  /// Is this predicate the predefined acquire atomic predicate?
  bool isAtomicOrderingAcquire() const;
  /// Is this predicate the predefined release atomic predicate?
  bool isAtomicOrderingRelease() const;
  /// Is this predicate the predefined acquire-release atomic predicate?
  bool isAtomicOrderingAcquireRelease() const;
  /// Is this predicate the predefined sequentially consistent atomic predicate?
  bool isAtomicOrderingSequentiallyConsistent() const;

  /// Is this predicate the predefined acquire-or-stronger atomic predicate?
  bool isAtomicOrderingAcquireOrStronger() const;
  /// Is this predicate the predefined weaker-than-acquire atomic predicate?
  bool isAtomicOrderingWeakerThanAcquire() const;

  /// Is this predicate the predefined release-or-stronger atomic predicate?
  bool isAtomicOrderingReleaseOrStronger() const;
  /// Is this predicate the predefined weaker-than-release atomic predicate?
  bool isAtomicOrderingWeakerThanRelease() const;

  /// If non-null, indicates that this predicate is a predefined memory VT
  /// predicate for a load/store and returns the ValueType record for the memory
  /// VT.
  const Record *getMemoryVT() const;
  /// If non-null, indicates that this predicate is a predefined memory VT
  /// predicate (checking only the scalar type) for load/store and returns the
  /// ValueType record for the memory VT.
  const Record *getScalarMemoryVT() const;

  const ListInit *getAddressSpaces() const;
  int64_t getMinAlignment() const;

  // If true, indicates that GlobalISel-based C++ code was supplied.
  bool hasGISelPredicateCode() const;
  std::string getGISelPredicateCode() const;

  // If true, indicates that GlobalISel-based C++ code was supplied for checking
  // register operands.
  bool hasGISelLeafPredicateCode() const;
  std::string getGISelLeafPredicateCode() const;

private:
  bool hasPredCode() const;
  bool hasImmCode() const;
  std::string getPredCode() const;
  std::string getImmCode() const;
  bool immCodeUsesAPInt() const;
  bool immCodeUsesAPFloat() const;

  bool isPredefinedPredicateEqualTo(StringRef Field, bool Value) const;
};

struct TreePredicateCall {
  TreePredicateFn Fn;

  // Scope -- unique identifier for retrieving named arguments. 0 is used when
  // the predicate does not use named arguments.
  unsigned Scope;

  TreePredicateCall(const TreePredicateFn &Fn, unsigned Scope)
      : Fn(Fn), Scope(Scope) {}

  bool operator==(const TreePredicateCall &o) const {
    return Fn == o.Fn && Scope == o.Scope;
  }
  bool operator!=(const TreePredicateCall &o) const { return !(*this == o); }
};

class TreePatternNode : public RefCountedBase<TreePatternNode> {
  /// The type of each node result.  Before and during type inference, each
  /// result may be a set of possible types.  After (successful) type inference,
  /// each is a single concrete type.
  std::vector<TypeSetByHwMode> Types;

  /// The index of each result in results of the pattern.
  std::vector<unsigned> ResultPerm;

  /// OperatorOrVal - The Record for the operator if this is an interior node
  /// (not a leaf) or the init value (e.g. the "GPRC" record, or "7") for a
  /// leaf.
  PointerUnion<const Record *, const Init *> OperatorOrVal;

  /// Name - The name given to this node with the :$foo notation.
  ///
  StringRef Name;

  std::vector<ScopedName> NamesAsPredicateArg;

  /// PredicateCalls - The predicate functions to execute on this node to check
  /// for a match.  If this list is empty, no predicate is involved.
  std::vector<TreePredicateCall> PredicateCalls;

  /// TransformFn - The transformation function to execute on this node before
  /// it can be substituted into the resulting instruction on a pattern match.
  const Record *TransformFn;

  std::vector<TreePatternNodePtr> Children;

  /// If this was instantiated from a PatFrag node, and the PatFrag was derived
  /// from "GISelFlags": the original Record derived from GISelFlags.
  const Record *GISelFlags = nullptr;

public:
  TreePatternNode(const Record *Op, std::vector<TreePatternNodePtr> Ch,
                  unsigned NumResults)
      : OperatorOrVal(Op), TransformFn(nullptr), Children(std::move(Ch)) {
    Types.resize(NumResults);
    ResultPerm.resize(NumResults);
    std::iota(ResultPerm.begin(), ResultPerm.end(), 0);
  }
  TreePatternNode(const Init *val, unsigned NumResults) // leaf ctor
      : OperatorOrVal(val), TransformFn(nullptr) {
    Types.resize(NumResults);
    ResultPerm.resize(NumResults);
    std::iota(ResultPerm.begin(), ResultPerm.end(), 0);
  }

  bool hasName() const { return !Name.empty(); }
  StringRef getName() const { return Name; }
  void setName(StringRef N) { Name = N; }

  const std::vector<ScopedName> &getNamesAsPredicateArg() const {
    return NamesAsPredicateArg;
  }
  void setNamesAsPredicateArg(const std::vector<ScopedName> &Names) {
    NamesAsPredicateArg = Names;
  }
  void addNameAsPredicateArg(const ScopedName &N) {
    NamesAsPredicateArg.push_back(N);
  }

  bool isLeaf() const { return isa<const Init *>(OperatorOrVal); }

  // Type accessors.
  unsigned getNumTypes() const { return Types.size(); }
  ValueTypeByHwMode getType(unsigned ResNo) const {
    return Types[ResNo].getValueTypeByHwMode(/*SkipEmpty=*/true);
  }
  const std::vector<TypeSetByHwMode> &getExtTypes() const { return Types; }
  const TypeSetByHwMode &getExtType(unsigned ResNo) const {
    return Types[ResNo];
  }
  TypeSetByHwMode &getExtType(unsigned ResNo) { return Types[ResNo]; }
  void setType(unsigned ResNo, const TypeSetByHwMode &T) { Types[ResNo] = T; }
  MVT getSimpleType(unsigned ResNo) const {
    return Types[ResNo].getMachineValueType();
  }

  bool hasConcreteType(unsigned ResNo) const {
    return Types[ResNo].isValueTypeByHwMode(false);
  }
  bool isTypeCompletelyUnknown(unsigned ResNo, TreePattern &TP) const {
    return Types[ResNo].empty();
  }

  unsigned getNumResults() const { return ResultPerm.size(); }
  unsigned getResultIndex(unsigned ResNo) const { return ResultPerm[ResNo]; }
  void setResultIndex(unsigned ResNo, unsigned RI) { ResultPerm[ResNo] = RI; }

  const Init *getLeafValue() const {
    assert(isLeaf());
    return cast<const Init *>(OperatorOrVal);
  }
  const Record *getOperator() const {
    assert(!isLeaf());
    return cast<const Record *>(OperatorOrVal);
  }

  using child_iterator = pointee_iterator<decltype(Children)::iterator>;
  using child_const_iterator =
      pointee_iterator<decltype(Children)::const_iterator>;

  iterator_range<child_iterator> children() {
    return make_pointee_range(Children);
  }

  iterator_range<child_const_iterator> children() const {
    return make_pointee_range(Children);
  }

  unsigned getNumChildren() const { return Children.size(); }
  const TreePatternNode &getChild(unsigned N) const {
    return *Children[N].get();
  }
  TreePatternNode &getChild(unsigned N) { return *Children[N].get(); }
  const TreePatternNodePtr &getChildShared(unsigned N) const {
    return Children[N];
  }
  TreePatternNodePtr &getChildSharedPtr(unsigned N) { return Children[N]; }
  void setChild(unsigned i, TreePatternNodePtr N) { Children[i] = N; }

  /// hasChild - Return true if N is any of our children.
  bool hasChild(const TreePatternNode *N) const {
    for (const TreePatternNodePtr &Child : Children)
      if (Child.get() == N)
        return true;
    return false;
  }

  bool hasProperTypeByHwMode() const;
  bool hasPossibleType() const;
  bool setDefaultMode(unsigned Mode);

  bool hasAnyPredicate() const { return !PredicateCalls.empty(); }

  const std::vector<TreePredicateCall> &getPredicateCalls() const {
    return PredicateCalls;
  }
  void clearPredicateCalls() { PredicateCalls.clear(); }
  void setPredicateCalls(const std::vector<TreePredicateCall> &Calls) {
    assert(PredicateCalls.empty() && "Overwriting non-empty predicate list!");
    PredicateCalls = Calls;
  }
  void addPredicateCall(const TreePredicateCall &Call) {
    assert(!Call.Fn.isAlwaysTrue() && "Empty predicate string!");
    assert(!is_contained(PredicateCalls, Call) &&
           "predicate applied recursively");
    PredicateCalls.push_back(Call);
  }
  void addPredicateCall(const TreePredicateFn &Fn, unsigned Scope) {
    assert((Scope != 0) == Fn.usesOperands());
    addPredicateCall(TreePredicateCall(Fn, Scope));
  }

  const Record *getTransformFn() const { return TransformFn; }
  void setTransformFn(const Record *Fn) { TransformFn = Fn; }

  /// getIntrinsicInfo - If this node corresponds to an intrinsic, return the
  /// CodeGenIntrinsic information for it, otherwise return a null pointer.
  const CodeGenIntrinsic *getIntrinsicInfo(const CodeGenDAGPatterns &CDP) const;

  /// getComplexPatternInfo - If this node corresponds to a ComplexPattern,
  /// return the ComplexPattern information, otherwise return null.
  const ComplexPattern *
  getComplexPatternInfo(const CodeGenDAGPatterns &CGP) const;

  /// Returns the number of MachineInstr operands that would be produced by this
  /// node if it mapped directly to an output Instruction's
  /// operand. ComplexPattern specifies this explicitly; MIOperandInfo gives it
  /// for Operands; otherwise 1.
  unsigned getNumMIResults(const CodeGenDAGPatterns &CGP) const;

  /// NodeHasProperty - Return true if this node has the specified property.
  bool NodeHasProperty(SDNP Property, const CodeGenDAGPatterns &CGP) const;

  /// TreeHasProperty - Return true if any node in this tree has the specified
  /// property.
  bool TreeHasProperty(SDNP Property, const CodeGenDAGPatterns &CGP) const;

  /// isCommutativeIntrinsic - Return true if the node is an intrinsic which is
  /// marked isCommutative.
  bool isCommutativeIntrinsic(const CodeGenDAGPatterns &CDP) const;

  void setGISelFlagsRecord(const Record *R) { GISelFlags = R; }
  const Record *getGISelFlagsRecord() const { return GISelFlags; }

  void print(raw_ostream &OS) const;
  void dump() const;

public: // Higher level manipulation routines.
  /// clone - Return a new copy of this tree.
  ///
  TreePatternNodePtr clone() const;

  /// RemoveAllTypes - Recursively strip all the types of this tree.
  void RemoveAllTypes();

  /// isIsomorphicTo - Return true if this node is recursively isomorphic to
  /// the specified node.  For this comparison, all of the state of the node
  /// is considered, except for the assigned name.  Nodes with differing names
  /// that are otherwise identical are considered isomorphic.
  bool isIsomorphicTo(const TreePatternNode &N,
                      const MultipleUseVarSet &DepVars) const;

  /// SubstituteFormalArguments - Replace the formal arguments in this tree
  /// with actual values specified by ArgMap.
  void
  SubstituteFormalArguments(std::map<StringRef, TreePatternNodePtr> &ArgMap);

  /// InlinePatternFragments - If \p T pattern refers to any pattern
  /// fragments, return the set of inlined versions (this can be more than
  /// one if a PatFrags record has multiple alternatives).
  void InlinePatternFragments(TreePattern &TP,
                              std::vector<TreePatternNodePtr> &OutAlternatives);

  /// ApplyTypeConstraints - Apply all of the type constraints relevant to
  /// this node and its children in the tree.  This returns true if it makes a
  /// change, false otherwise.  If a type contradiction is found, flag an error.
  bool ApplyTypeConstraints(TreePattern &TP, bool NotRegisters);

  /// UpdateNodeType - Set the node type of N to VT if VT contains
  /// information.  If N already contains a conflicting type, then flag an
  /// error.  This returns true if any information was updated.
  ///
  bool UpdateNodeType(unsigned ResNo, const TypeSetByHwMode &InTy,
                      TreePattern &TP);
  bool UpdateNodeType(unsigned ResNo, MVT InTy, TreePattern &TP);
  bool UpdateNodeType(unsigned ResNo, const ValueTypeByHwMode &InTy,
                      TreePattern &TP);

  // Update node type with types inferred from an instruction operand or result
  // def from the ins/outs lists.
  // Return true if the type changed.
  bool UpdateNodeTypeFromInst(unsigned ResNo, const Record *Operand,
                              TreePattern &TP);

  /// ContainsUnresolvedType - Return true if this tree contains any
  /// unresolved types.
  bool ContainsUnresolvedType(TreePattern &TP) const;

  /// canPatternMatch - If it is impossible for this pattern to match on this
  /// target, fill in Reason and return false.  Otherwise, return true.
  bool canPatternMatch(std::string &Reason,
                       const CodeGenDAGPatterns &CDP) const;
};

inline raw_ostream &operator<<(raw_ostream &OS, const TreePatternNode &TPN) {
  TPN.print(OS);
  return OS;
}

/// TreePattern - Represent a pattern, used for instructions, pattern
/// fragments, etc.
///
class TreePattern {
  /// Trees - The list of pattern trees which corresponds to this pattern.
  /// Note that PatFrag's only have a single tree.
  ///
  std::vector<TreePatternNodePtr> Trees;

  /// NamedNodes - This is all of the nodes that have names in the trees in this
  /// pattern.
  StringMap<SmallVector<TreePatternNode *, 1>> NamedNodes;

  /// TheRecord - The actual TableGen record corresponding to this pattern.
  ///
  const Record *TheRecord;

  /// Args - This is a list of all of the arguments to this pattern (for
  /// PatFrag patterns), which are the 'node' markers in this pattern.
  std::vector<std::string> Args;

  /// CDP - the top-level object coordinating this madness.
  ///
  CodeGenDAGPatterns &CDP;

  /// isInputPattern - True if this is an input pattern, something to match.
  /// False if this is an output pattern, something to emit.
  bool isInputPattern;

  /// hasError - True if the currently processed nodes have unresolvable types
  /// or other non-fatal errors
  bool HasError;

  /// It's important that the usage of operands in ComplexPatterns is
  /// consistent: each named operand can be defined by at most one
  /// ComplexPattern. This records the ComplexPattern instance and the operand
  /// number for each operand encountered in a ComplexPattern to aid in that
  /// check.
  StringMap<std::pair<const Record *, unsigned>> ComplexPatternOperands;

  TypeInfer Infer;

public:
  /// TreePattern constructor - Parse the specified DagInits into the
  /// current record.
  TreePattern(const Record *TheRec, const ListInit *RawPat, bool isInput,
              CodeGenDAGPatterns &ise);
  TreePattern(const Record *TheRec, const DagInit *Pat, bool isInput,
              CodeGenDAGPatterns &ise);
  TreePattern(const Record *TheRec, ArrayRef<const Init *> Args,
              ArrayRef<const StringInit *> ArgNames, bool isInput,
              CodeGenDAGPatterns &ise);
  TreePattern(const Record *TheRec, TreePatternNodePtr Pat, bool isInput,
              CodeGenDAGPatterns &ise);

  /// getTrees - Return the tree patterns which corresponds to this pattern.
  ///
  const std::vector<TreePatternNodePtr> &getTrees() const { return Trees; }
  unsigned getNumTrees() const { return Trees.size(); }
  const TreePatternNodePtr &getTree(unsigned i) const { return Trees[i]; }
  const TreePatternNodePtr &getOnlyTree() const {
    assert(Trees.size() == 1 && "Doesn't have exactly one pattern!");
    return Trees[0];
  }

  const StringMap<SmallVector<TreePatternNode *, 1>> &getNamedNodesMap() {
    if (NamedNodes.empty())
      ComputeNamedNodes();
    return NamedNodes;
  }

  /// getRecord - Return the actual TableGen record corresponding to this
  /// pattern.
  ///
  const Record *getRecord() const { return TheRecord; }

  unsigned getNumArgs() const { return Args.size(); }
  const std::string &getArgName(unsigned i) const {
    assert(i < Args.size() && "Argument reference out of range!");
    return Args[i];
  }
  std::vector<std::string> &getArgList() { return Args; }

  CodeGenDAGPatterns &getDAGPatterns() const { return CDP; }

  /// InlinePatternFragments - If this pattern refers to any pattern
  /// fragments, inline them into place, giving us a pattern without any
  /// PatFrags references.  This may increase the number of trees in the
  /// pattern if a PatFrags has multiple alternatives.
  void InlinePatternFragments() {
    std::vector<TreePatternNodePtr> Copy;
    Trees.swap(Copy);
    for (const TreePatternNodePtr &C : Copy)
      C->InlinePatternFragments(*this, Trees);
  }

  /// InferAllTypes - Infer/propagate as many types throughout the expression
  /// patterns as possible.  Return true if all types are inferred, false
  /// otherwise.  Bail out if a type contradiction is found.
  bool InferAllTypes(
      const StringMap<SmallVector<TreePatternNode *, 1>> *NamedTypes = nullptr);

  /// error - If this is the first error in the current resolution step,
  /// print it and set the error flag.  Otherwise, continue silently.
  void error(const Twine &Msg);
  bool hasError() const { return HasError; }
  void resetError() { HasError = false; }

  TypeInfer &getInfer() { return Infer; }

  void print(raw_ostream &OS) const;
  void dump() const;

private:
  TreePatternNodePtr ParseTreePattern(const Init *DI, StringRef OpName);
  TreePatternNodePtr
  ParseRootlessTreePattern(ArrayRef<const Init *> Args,
                           ArrayRef<const StringInit *> ArgNames);
  void ComputeNamedNodes();
  void ComputeNamedNodes(TreePatternNode &N);
};

inline bool TreePatternNode::UpdateNodeType(unsigned ResNo,
                                            const TypeSetByHwMode &InTy,
                                            TreePattern &TP) {
  TypeSetByHwMode VTS(InTy);
  TP.getInfer().expandOverloads(VTS);
  return TP.getInfer().MergeInTypeInfo(Types[ResNo], VTS);
}

inline bool TreePatternNode::UpdateNodeType(unsigned ResNo, MVT InTy,
                                            TreePattern &TP) {
  TypeSetByHwMode VTS(InTy);
  TP.getInfer().expandOverloads(VTS);
  return TP.getInfer().MergeInTypeInfo(Types[ResNo], VTS);
}

inline bool TreePatternNode::UpdateNodeType(unsigned ResNo,
                                            const ValueTypeByHwMode &InTy,
                                            TreePattern &TP) {
  TypeSetByHwMode VTS(InTy);
  TP.getInfer().expandOverloads(VTS);
  return TP.getInfer().MergeInTypeInfo(Types[ResNo], VTS);
}

/// DAGDefaultOperand - One of these is created for each OperandWithDefaultOps
/// that has a set ExecuteAlways / DefaultOps field.
struct DAGDefaultOperand {
  std::vector<TreePatternNodePtr> DefaultOps;
};

class DAGInstruction {
  std::vector<const Record *> Results;
  std::vector<const Record *> Operands;
  std::vector<const Record *> ImpResults;
  TreePatternNodePtr SrcPattern;
  TreePatternNodePtr ResultPattern;

public:
  DAGInstruction(std::vector<const Record *> &&Results,
                 std::vector<const Record *> &&Operands,
                 std::vector<const Record *> &&ImpResults,
                 TreePatternNodePtr SrcPattern = nullptr,
                 TreePatternNodePtr ResultPattern = nullptr)
      : Results(std::move(Results)), Operands(std::move(Operands)),
        ImpResults(std::move(ImpResults)), SrcPattern(SrcPattern),
        ResultPattern(ResultPattern) {}

  unsigned getNumResults() const { return Results.size(); }
  unsigned getNumOperands() const { return Operands.size(); }
  unsigned getNumImpResults() const { return ImpResults.size(); }
  ArrayRef<const Record *> getImpResults() const { return ImpResults; }

  const Record *getResult(unsigned RN) const {
    assert(RN < Results.size());
    return Results[RN];
  }

  const Record *getOperand(unsigned ON) const {
    assert(ON < Operands.size());
    return Operands[ON];
  }

  const Record *getImpResult(unsigned RN) const {
    assert(RN < ImpResults.size());
    return ImpResults[RN];
  }

  TreePatternNodePtr getSrcPattern() const { return SrcPattern; }
  TreePatternNodePtr getResultPattern() const { return ResultPattern; }
};

/// PatternToMatch - Used by CodeGenDAGPatterns to keep tab of patterns
/// processed to produce isel.
class PatternToMatch {
  const Record *SrcRecord;       // Originating Record for the pattern.
  const ListInit *Predicates;    // Top level predicate conditions to match.
  TreePatternNodePtr SrcPattern; // Source pattern to match.
  TreePatternNodePtr DstPattern; // Resulting pattern.
  std::vector<const Record *> Dstregs; // Physical register defs being matched.
  std::string HwModeFeatures;
  int AddedComplexity;    // Add to matching pattern complexity.
  bool GISelShouldIgnore; // Should GlobalISel ignore importing this pattern.
  unsigned ID;            // Unique ID for the record.

public:
  PatternToMatch(const Record *srcrecord, const ListInit *preds,
                 TreePatternNodePtr src, TreePatternNodePtr dst,
                 ArrayRef<const Record *> dstregs, int complexity, unsigned uid,
                 bool ignore, const Twine &hwmodefeatures = "")
      : SrcRecord(srcrecord), Predicates(preds), SrcPattern(src),
        DstPattern(dst), Dstregs(dstregs), HwModeFeatures(hwmodefeatures.str()),
        AddedComplexity(complexity), GISelShouldIgnore(ignore), ID(uid) {}

  const Record *getSrcRecord() const { return SrcRecord; }
  const ListInit *getPredicates() const { return Predicates; }
  TreePatternNode &getSrcPattern() const { return *SrcPattern; }
  TreePatternNodePtr getSrcPatternShared() const { return SrcPattern; }
  TreePatternNode &getDstPattern() const { return *DstPattern; }
  TreePatternNodePtr getDstPatternShared() const { return DstPattern; }
  ArrayRef<const Record *> getDstRegs() const { return Dstregs; }
  StringRef getHwModeFeatures() const { return HwModeFeatures; }
  int getAddedComplexity() const { return AddedComplexity; }
  bool getGISelShouldIgnore() const { return GISelShouldIgnore; }
  unsigned getID() const { return ID; }

  std::string getPredicateCheck() const;
  void
  getPredicateRecords(SmallVectorImpl<const Record *> &PredicateRecs) const;

  /// Compute the complexity metric for the input pattern.  This roughly
  /// corresponds to the number of nodes that are covered.
  int getPatternComplexity(const CodeGenDAGPatterns &CGP) const;
};

class CodeGenDAGPatterns {
public:
  using NodeXForm = std::pair<const Record *, std::string>;

private:
  const RecordKeeper &Records;
  CodeGenTarget Target;
  CodeGenIntrinsicTable Intrinsics;

  std::map<const Record *, SDNodeInfo, LessRecordByID> SDNodes;

  std::map<const Record *, NodeXForm, LessRecordByID> SDNodeXForms;
  std::map<const Record *, ComplexPattern, LessRecordByID> ComplexPatterns;
  std::map<const Record *, std::unique_ptr<TreePattern>, LessRecordByID>
      PatternFragments;
  std::map<const Record *, DAGDefaultOperand, LessRecordByID> DefaultOperands;
  std::map<const Record *, DAGInstruction, LessRecordByID> Instructions;

  // Specific SDNode definitions:
  const Record *intrinsic_void_sdnode;
  const Record *intrinsic_w_chain_sdnode, *intrinsic_wo_chain_sdnode;

  /// PatternsToMatch - All of the things we are matching on the DAG.  The first
  /// value is the pattern to match, the second pattern is the result to
  /// emit.
  std::vector<PatternToMatch> PatternsToMatch;

  TypeSetByHwMode LegalVTS;
  TypeSetByHwMode LegalPtrVTS;

  unsigned NumScopes = 0;

public:
  CodeGenDAGPatterns(const RecordKeeper &R, bool ExpandHwMode = true);

  CodeGenTarget &getTargetInfo() { return Target; }
  const CodeGenTarget &getTargetInfo() const { return Target; }
  const TypeSetByHwMode &getLegalTypes() const { return LegalVTS; }
  const TypeSetByHwMode &getLegalPtrTypes() const { return LegalPtrVTS; }

  const Record *getSDNodeNamed(StringRef Name) const;

  const SDNodeInfo &getSDNodeInfo(const Record *R) const {
    auto F = SDNodes.find(R);
    assert(F != SDNodes.end() && "Unknown node!");
    return F->second;
  }

  // Node transformation lookups.
  const NodeXForm &getSDNodeTransform(const Record *R) const {
    auto F = SDNodeXForms.find(R);
    assert(F != SDNodeXForms.end() && "Invalid transform!");
    return F->second;
  }

  const ComplexPattern &getComplexPattern(const Record *R) const {
    auto F = ComplexPatterns.find(R);
    assert(F != ComplexPatterns.end() && "Unknown addressing mode!");
    return F->second;
  }

  const CodeGenIntrinsic &getIntrinsic(const Record *R) const {
    for (const CodeGenIntrinsic &Intrinsic : Intrinsics)
      if (Intrinsic.TheDef == R)
        return Intrinsic;
    llvm_unreachable("Unknown intrinsic!");
  }

  const CodeGenIntrinsic &getIntrinsicInfo(unsigned IID) const {
    if (IID - 1 < Intrinsics.size())
      return Intrinsics[IID - 1];
    llvm_unreachable("Bad intrinsic ID!");
  }

  unsigned getIntrinsicID(const Record *R) const {
    for (unsigned i = 0, e = Intrinsics.size(); i != e; ++i)
      if (Intrinsics[i].TheDef == R)
        return i;
    llvm_unreachable("Unknown intrinsic!");
  }

  const DAGDefaultOperand &getDefaultOperand(const Record *R) const {
    auto F = DefaultOperands.find(R);
    assert(F != DefaultOperands.end() && "Isn't an analyzed default operand!");
    return F->second;
  }

  // Pattern Fragment information.
  TreePattern *getPatternFragment(const Record *R) const {
    auto F = PatternFragments.find(R);
    assert(F != PatternFragments.end() && "Invalid pattern fragment request!");
    return F->second.get();
  }
  TreePattern *getPatternFragmentIfRead(const Record *R) const {
    auto F = PatternFragments.find(R);
    if (F == PatternFragments.end())
      return nullptr;
    return F->second.get();
  }

  using pf_iterator = decltype(PatternFragments)::const_iterator;
  pf_iterator pf_begin() const { return PatternFragments.begin(); }
  pf_iterator pf_end() const { return PatternFragments.end(); }
  iterator_range<pf_iterator> ptfs() const { return PatternFragments; }

  // Patterns to match information.
  using ptm_iterator = std::vector<PatternToMatch>::const_iterator;
  ptm_iterator ptm_begin() const { return PatternsToMatch.begin(); }
  ptm_iterator ptm_end() const { return PatternsToMatch.end(); }
  iterator_range<ptm_iterator> ptms() const { return PatternsToMatch; }

  /// Parse the Pattern for an instruction, and insert the result in DAGInsts.
  using DAGInstMap = std::map<const Record *, DAGInstruction, LessRecordByID>;
  void parseInstructionPattern(const CodeGenInstruction &CGI,
                               const ListInit *Pattern, DAGInstMap &DAGInsts);

  const DAGInstruction &getInstruction(const Record *R) const {
    auto F = Instructions.find(R);
    assert(F != Instructions.end() && "Unknown instruction!");
    return F->second;
  }

  const Record *get_intrinsic_void_sdnode() const {
    return intrinsic_void_sdnode;
  }
  const Record *get_intrinsic_w_chain_sdnode() const {
    return intrinsic_w_chain_sdnode;
  }
  const Record *get_intrinsic_wo_chain_sdnode() const {
    return intrinsic_wo_chain_sdnode;
  }

  unsigned allocateScope() { return ++NumScopes; }

  bool operandHasDefault(const Record *Op) const {
    return Op->isSubClassOf("OperandWithDefaultOps") &&
           !getDefaultOperand(Op).DefaultOps.empty();
  }

private:
  TypeSetByHwMode ComputeLegalPtrTypes() const;
  void ParseNodeInfo();
  void ParseNodeTransforms();
  void ParseComplexPatterns();
  void ParsePatternFragments(bool OutFrags = false);
  void ParseDefaultOperands();
  void ParseInstructions();
  void ParsePatterns();
  void ExpandHwModeBasedTypes();
  void InferInstructionFlags();
  void GenerateVariants();
  void VerifyInstructionFlags();

  void ParseOnePattern(const Record *TheDef, TreePattern &Pattern,
                       TreePattern &Result,
                       ArrayRef<const Record *> InstImpResults,
                       bool ShouldIgnore = false);
  void AddPatternToMatch(TreePattern *Pattern, PatternToMatch &&PTM);

  using InstInputsTy = std::map<StringRef, TreePatternNodePtr>;
  using InstResultsTy =
      MapVector<StringRef, TreePatternNodePtr, std::map<StringRef, unsigned>>;
  void FindPatternInputsAndOutputs(TreePattern &I, TreePatternNodePtr Pat,
                                   InstInputsTy &InstInputs,
                                   InstResultsTy &InstResults,
                                   std::vector<const Record *> &InstImpResults);
  unsigned getNewUID();
};

inline bool SDNodeInfo::ApplyTypeConstraints(TreePatternNode &N,
                                             TreePattern &TP) const {
  bool MadeChange = false;
  for (const SDTypeConstraint &TypeConstraint : TypeConstraints)
    MadeChange |= TypeConstraint.ApplyTypeConstraint(N, *this, TP);
  return MadeChange;
}

} // end namespace llvm

#endif // LLVM_UTILS_TABLEGEN_COMMON_CODEGENDAGPATTERNS_H
