//===- 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/DenseMap.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;

  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 PtrAddrSpace != std::numeric_limits<unsigned>::max();
  }

  unsigned getPtrAddrSpace() const {
    assert(isPointer());
    return 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;
  DenseMap<const Record *, unsigned> IntrinsicIDs;

  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 {
    return Intrinsics[getIntrinsicID(R)];
  }

  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 {
    auto I = IntrinsicIDs.find(R);
    assert(I != IntrinsicIDs.end() && "Unknown intrinsic!");
    return I->second;
  }

  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
