//===- 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() 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(); }
  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);

  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
