//===- CodeGenDAGPatterns.cpp - Read DAG patterns from .td file -----------===//
//
// 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 implements the CodeGenDAGPatterns class, which is used to read and
// represent the patterns present in a .td file for instructions.
//
//===----------------------------------------------------------------------===//

#include "CodeGenDAGPatterns.h"
#include "CodeGenInstruction.h"
#include "CodeGenRegisters.h"
#include "SubtargetFeatureInfo.h"
#include "llvm/ADT/DenseSet.h"
#include "llvm/ADT/MapVector.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/SmallSet.h"
#include "llvm/ADT/SmallString.h"
#include "llvm/ADT/StringExtras.h"
#include "llvm/ADT/StringMap.h"
#include "llvm/ADT/Twine.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/InterleavedRange.h"
#include "llvm/Support/TypeSize.h"
#include "llvm/TableGen/Error.h"
#include "llvm/TableGen/Record.h"
#include <algorithm>
#include <cstdio>
#include <iterator>
#include <set>
using namespace llvm;

#define DEBUG_TYPE "dag-patterns"

static inline bool isIntegerOrPtr(MVT VT) {
  return VT.isInteger() || VT == MVT::iPTR;
}
static inline bool isFloatingPoint(MVT VT) { return VT.isFloatingPoint(); }
static inline bool isVector(MVT VT) { return VT.isVector(); }
static inline bool isScalar(MVT VT) { return !VT.isVector(); }

template <typename Predicate>
static bool berase_if(MachineValueTypeSet &S, Predicate P) {
  bool Erased = false;
  // It is ok to iterate over MachineValueTypeSet and remove elements from it
  // at the same time.
  for (MVT T : S) {
    if (!P(T))
      continue;
    Erased = true;
    S.erase(T);
  }
  return Erased;
}

void MachineValueTypeSet::writeToStream(raw_ostream &OS) const {
  SmallVector<MVT, 4> Types(begin(), end());
  array_pod_sort(Types.begin(), Types.end());

  OS << '[';
  ListSeparator LS(" ");
  for (const MVT &T : Types)
    OS << LS << ValueTypeByHwMode::getMVTName(T);
  OS << ']';
}

// --- TypeSetByHwMode

// This is a parameterized type-set class. For each mode there is a list
// of types that are currently possible for a given tree node. Type
// inference will apply to each mode separately.

TypeSetByHwMode::TypeSetByHwMode(ArrayRef<ValueTypeByHwMode> VTList) {
  // Take the address space from the first type in the list.
  if (!VTList.empty())
    AddrSpace = VTList[0].PtrAddrSpace;

  for (const ValueTypeByHwMode &VVT : VTList)
    insert(VVT);
}

bool TypeSetByHwMode::isValueTypeByHwMode(bool AllowEmpty) const {
  for (const auto &I : *this) {
    if (I.second.size() > 1)
      return false;
    if (!AllowEmpty && I.second.empty())
      return false;
  }
  return true;
}

ValueTypeByHwMode TypeSetByHwMode::getValueTypeByHwMode() const {
  assert(isValueTypeByHwMode(true) &&
         "The type set has multiple types for at least one HW mode");
  ValueTypeByHwMode VVT;
  VVT.PtrAddrSpace = AddrSpace;

  for (const auto &I : *this) {
    MVT T = I.second.empty() ? MVT::Other : *I.second.begin();
    VVT.getOrCreateTypeForMode(I.first, T);
  }
  return VVT;
}

bool TypeSetByHwMode::isPossible() const {
  for (const auto &I : *this)
    if (!I.second.empty())
      return true;
  return false;
}

bool TypeSetByHwMode::insert(const ValueTypeByHwMode &VVT) {
  bool Changed = false;
  bool ContainsDefault = false;
  MVT DT = MVT::Other;

  for (const auto &P : VVT) {
    unsigned M = P.first;
    // Make sure there exists a set for each specific mode from VVT.
    Changed |= getOrCreate(M).insert(P.second).second;
    // Cache VVT's default mode.
    if (DefaultMode == M) {
      ContainsDefault = true;
      DT = P.second;
    }
  }

  // If VVT has a default mode, add the corresponding type to all
  // modes in "this" that do not exist in VVT.
  if (ContainsDefault)
    for (auto &I : *this)
      if (!VVT.hasMode(I.first))
        Changed |= I.second.insert(DT).second;

  return Changed;
}

// Constrain the type set to be the intersection with VTS.
bool TypeSetByHwMode::constrain(const TypeSetByHwMode &VTS) {
  bool Changed = false;
  if (hasDefault()) {
    for (const auto &I : VTS) {
      unsigned M = I.first;
      if (M == DefaultMode || hasMode(M))
        continue;
      Map.try_emplace(M, Map.at(DefaultMode));
      Changed = true;
    }
  }

  for (auto &I : *this) {
    unsigned M = I.first;
    SetType &S = I.second;
    if (VTS.hasMode(M) || VTS.hasDefault()) {
      Changed |= intersect(I.second, VTS.get(M));
    } else if (!S.empty()) {
      S.clear();
      Changed = true;
    }
  }
  return Changed;
}

template <typename Predicate> bool TypeSetByHwMode::constrain(Predicate P) {
  bool Changed = false;
  for (auto &I : *this)
    Changed |= berase_if(I.second, [&P](MVT VT) { return !P(VT); });
  return Changed;
}

template <typename Predicate>
bool TypeSetByHwMode::assign_if(const TypeSetByHwMode &VTS, Predicate P) {
  assert(empty());
  for (const auto &I : VTS) {
    SetType &S = getOrCreate(I.first);
    for (auto J : I.second)
      if (P(J))
        S.insert(J);
  }
  return !empty();
}

void TypeSetByHwMode::writeToStream(raw_ostream &OS) const {
  SmallVector<unsigned, 4> Modes;
  Modes.reserve(Map.size());

  for (const auto &I : *this)
    Modes.push_back(I.first);
  if (Modes.empty()) {
    OS << "{}";
    return;
  }
  array_pod_sort(Modes.begin(), Modes.end());

  OS << '{';
  for (unsigned M : Modes) {
    OS << ' ' << getModeName(M) << ':';
    get(M).writeToStream(OS);
  }
  OS << " }";
}

bool TypeSetByHwMode::operator==(const TypeSetByHwMode &VTS) const {
  // The isSimple call is much quicker than hasDefault - check this first.
  bool IsSimple = isSimple();
  bool VTSIsSimple = VTS.isSimple();
  if (IsSimple && VTSIsSimple)
    return getSimple() == VTS.getSimple();

  // Speedup: We have a default if the set is simple.
  bool HaveDefault = IsSimple || hasDefault();
  bool VTSHaveDefault = VTSIsSimple || VTS.hasDefault();
  if (HaveDefault != VTSHaveDefault)
    return false;

  SmallSet<unsigned, 4> Modes;
  Modes.insert_range(llvm::make_first_range(*this));
  Modes.insert_range(llvm::make_first_range(VTS));

  if (HaveDefault) {
    // Both sets have default mode.
    for (unsigned M : Modes) {
      if (get(M) != VTS.get(M))
        return false;
    }
  } else {
    // Neither set has default mode.
    for (unsigned M : Modes) {
      // If there is no default mode, an empty set is equivalent to not having
      // the corresponding mode.
      bool NoModeThis = !hasMode(M) || get(M).empty();
      bool NoModeVTS = !VTS.hasMode(M) || VTS.get(M).empty();
      if (NoModeThis != NoModeVTS)
        return false;
      if (!NoModeThis)
        if (get(M) != VTS.get(M))
          return false;
    }
  }

  return true;
}

raw_ostream &llvm::operator<<(raw_ostream &OS, const MachineValueTypeSet &T) {
  T.writeToStream(OS);
  return OS;
}
raw_ostream &llvm::operator<<(raw_ostream &OS, const TypeSetByHwMode &T) {
  T.writeToStream(OS);
  return OS;
}

LLVM_DUMP_METHOD
void TypeSetByHwMode::dump() const { dbgs() << *this << '\n'; }

bool TypeSetByHwMode::intersect(SetType &Out, const SetType &In) {
  auto IntersectP = [&](std::optional<MVT> WildVT, function_ref<bool(MVT)> P) {
    // Complement of In within this partition.
    auto CompIn = [&](MVT T) -> bool { return !In.count(T) && P(T); };

    if (!WildVT)
      return berase_if(Out, CompIn);

    bool OutW = Out.count(*WildVT), InW = In.count(*WildVT);
    if (OutW == InW)
      return berase_if(Out, CompIn);

    // Compute the intersection of scalars separately to account for only one
    // set containing WildVT.
    // The intersection of WildVT with a set of corresponding types that does
    // not include WildVT will result in the most specific type:
    // - WildVT is more specific than any set with two elements or more
    // - WildVT is less specific than any single type.
    // For example, for iPTR and scalar integer types
    // { iPTR } * { i32 }     -> { i32 }
    // { iPTR } * { i32 i64 } -> { iPTR }
    // and
    // { iPTR i32 } * { i32 }          -> { i32 }
    // { iPTR i32 } * { i32 i64 }      -> { i32 i64 }
    // { iPTR i32 } * { i32 i64 i128 } -> { iPTR i32 }

    // Looking at just this partition, let In' = elements only in In,
    // Out' = elements only in Out, and IO = elements common to both. Normally
    // IO would be returned as the result of the intersection, but we need to
    // account for WildVT being a "wildcard" of sorts. Since elements in IO are
    // those that match both sets exactly, they will all belong to the output.
    // If any of the "leftovers" (i.e. In' or Out') contain WildVT, it means
    // that the other set doesn't have it, but it could have (1) a more
    // specific type, or (2) a set of types that is less specific. The
    // "leftovers" from the other set is what we want to examine more closely.

    auto Leftovers = [&](const SetType &A, const SetType &B) {
      SetType Diff = A;
      berase_if(Diff, [&](MVT T) { return B.count(T) || !P(T); });
      return Diff;
    };

    if (InW) {
      SetType OutLeftovers = Leftovers(Out, In);
      if (OutLeftovers.size() < 2) {
        // WildVT not added to Out. Keep the possible single leftover.
        return false;
      }
      // WildVT replaces the leftovers.
      berase_if(Out, CompIn);
      Out.insert(*WildVT);
      return true;
    }

    // OutW == true
    SetType InLeftovers = Leftovers(In, Out);
    unsigned SizeOut = Out.size();
    berase_if(Out, CompIn); // This will remove at least the WildVT.
    if (InLeftovers.size() < 2) {
      // WildVT deleted from Out. Add back the possible single leftover.
      Out.insert(InLeftovers);
      return true;
    }

    // Keep the WildVT in Out.
    Out.insert(*WildVT);
    // If WildVT was the only element initially removed from Out, then Out
    // has not changed.
    return SizeOut != Out.size();
  };

  // Note: must be non-overlapping
  using WildPartT = std::pair<MVT, std::function<bool(MVT)>>;
  static const WildPartT WildParts[] = {
      {MVT::iPTR, [](MVT T) { return T.isScalarInteger() || T == MVT::iPTR; }},
      {MVT::cPTR,
       [](MVT T) { return T.isCheriCapability() || T == MVT::cPTR; }},
  };

  bool Changed = false;
  for (const auto &I : WildParts)
    Changed |= IntersectP(I.first, I.second);

  Changed |= IntersectP(std::nullopt, [&](MVT T) {
    return !any_of(WildParts, [=](const WildPartT &I) { return I.second(T); });
  });

  return Changed;
}

bool TypeSetByHwMode::validate() const {
  if (empty())
    return true;
  bool AllEmpty = true;
  for (const auto &I : *this)
    AllEmpty &= I.second.empty();
  return !AllEmpty;
}

// --- TypeInfer

bool TypeInfer::MergeInTypeInfo(TypeSetByHwMode &Out,
                                const TypeSetByHwMode &In) const {
  ValidateOnExit _1(Out, *this);
  In.validate();
  if (In.empty() || Out == In || TP.hasError())
    return false;
  if (Out.empty()) {
    Out = In;
    return true;
  }

  bool Changed = Out.constrain(In);
  if (Changed && Out.empty())
    TP.error("Type contradiction");

  return Changed;
}

bool TypeInfer::forceArbitrary(TypeSetByHwMode &Out) {
  ValidateOnExit _1(Out, *this);
  if (TP.hasError())
    return false;
  assert(!Out.empty() && "cannot pick from an empty set");

  bool Changed = false;
  for (auto &I : Out) {
    TypeSetByHwMode::SetType &S = I.second;
    if (S.size() <= 1)
      continue;
    MVT T = *S.begin(); // Pick the first element.
    S.clear();
    S.insert(T);
    Changed = true;
  }
  return Changed;
}

bool TypeInfer::EnforceInteger(TypeSetByHwMode &Out) {
  ValidateOnExit _1(Out, *this);
  if (TP.hasError())
    return false;
  if (!Out.empty())
    return Out.constrain(isIntegerOrPtr);

  return Out.assign_if(getLegalTypes(), isIntegerOrPtr);
}

bool TypeInfer::EnforceFloatingPoint(TypeSetByHwMode &Out) {
  ValidateOnExit _1(Out, *this);
  if (TP.hasError())
    return false;
  if (!Out.empty())
    return Out.constrain(isFloatingPoint);

  return Out.assign_if(getLegalTypes(), isFloatingPoint);
}

bool TypeInfer::EnforceScalar(TypeSetByHwMode &Out) {
  ValidateOnExit _1(Out, *this);
  if (TP.hasError())
    return false;
  if (!Out.empty())
    return Out.constrain(isScalar);

  return Out.assign_if(getLegalTypes(), isScalar);
}

bool TypeInfer::EnforceVector(TypeSetByHwMode &Out) {
  ValidateOnExit _1(Out, *this);
  if (TP.hasError())
    return false;
  if (!Out.empty())
    return Out.constrain(isVector);

  return Out.assign_if(getLegalTypes(), isVector);
}

bool TypeInfer::EnforceAny(TypeSetByHwMode &Out) {
  ValidateOnExit _1(Out, *this);
  if (TP.hasError() || !Out.empty())
    return false;

  Out = getLegalTypes();
  return true;
}

template <typename Iter, typename Pred, typename Less>
static Iter min_if(Iter B, Iter E, Pred P, Less L) {
  if (B == E)
    return E;
  Iter Min = E;
  for (Iter I = B; I != E; ++I) {
    if (!P(*I))
      continue;
    if (Min == E || L(*I, *Min))
      Min = I;
  }
  return Min;
}

template <typename Iter, typename Pred, typename Less>
static Iter max_if(Iter B, Iter E, Pred P, Less L) {
  if (B == E)
    return E;
  Iter Max = E;
  for (Iter I = B; I != E; ++I) {
    if (!P(*I))
      continue;
    if (Max == E || L(*Max, *I))
      Max = I;
  }
  return Max;
}

/// Make sure that for each type in Small, there exists a larger type in Big.
bool TypeInfer::EnforceSmallerThan(TypeSetByHwMode &Small, TypeSetByHwMode &Big,
                                   bool SmallIsVT) {
  ValidateOnExit _1(Small, *this), _2(Big, *this);
  if (TP.hasError())
    return false;
  bool Changed = false;

  assert((!SmallIsVT || !Small.empty()) &&
         "Small should not be empty for SDTCisVTSmallerThanOp");

  if (Small.empty())
    Changed |= EnforceAny(Small);
  if (Big.empty())
    Changed |= EnforceAny(Big);

  assert(Small.hasDefault() && Big.hasDefault());

  SmallVector<unsigned, 4> Modes;
  union_modes(Small, Big, Modes);

  // 1. Only allow integer or floating point types and make sure that
  //    both sides are both integer or both floating point.
  // 2. Make sure that either both sides have vector types, or neither
  //    of them does.
  for (unsigned M : Modes) {
    TypeSetByHwMode::SetType &S = Small.get(M);
    TypeSetByHwMode::SetType &B = Big.get(M);

    assert((!SmallIsVT || !S.empty()) && "Expected non-empty type");

    if (any_of(S, isIntegerOrPtr) && any_of(B, isIntegerOrPtr)) {
      auto NotInt = [](MVT VT) { return !isIntegerOrPtr(VT); };
      Changed |= berase_if(S, NotInt);
      Changed |= berase_if(B, NotInt);
    } else if (any_of(S, isFloatingPoint) && any_of(B, isFloatingPoint)) {
      auto NotFP = [](MVT VT) { return !isFloatingPoint(VT); };
      Changed |= berase_if(S, NotFP);
      Changed |= berase_if(B, NotFP);
    } else if (SmallIsVT && B.empty()) {
      // B is empty and since S is a specific VT, it will never be empty. Don't
      // report this as a change, just clear S and continue. This prevents an
      // infinite loop.
      S.clear();
    } else if (S.empty() || B.empty()) {
      Changed = !S.empty() || !B.empty();
      S.clear();
      B.clear();
    } else {
      TP.error("Incompatible types");
      return Changed;
    }

    if (none_of(S, isVector) || none_of(B, isVector)) {
      Changed |= berase_if(S, isVector);
      Changed |= berase_if(B, isVector);
    }
  }

  auto LT = [](MVT A, MVT B) -> bool {
    // Always treat non-scalable MVTs as smaller than scalable MVTs for the
    // purposes of ordering.
    auto ASize = std::tuple(A.isScalableVector(), A.getScalarSizeInBits(),
                            A.getSizeInBits().getKnownMinValue());
    auto BSize = std::tuple(B.isScalableVector(), B.getScalarSizeInBits(),
                            B.getSizeInBits().getKnownMinValue());
    return ASize < BSize;
  };
  auto SameKindLE = [](MVT A, MVT B) -> bool {
    // This function is used when removing elements: when a vector is compared
    // to a non-vector or a scalable vector to any non-scalable MVT, it should
    // return false (to avoid removal).
    if (std::tuple(A.isVector(), A.isScalableVector()) !=
        std::tuple(B.isVector(), B.isScalableVector()))
      return false;

    return std::tuple(A.getScalarSizeInBits(),
                      A.getSizeInBits().getKnownMinValue()) <=
           std::tuple(B.getScalarSizeInBits(),
                      B.getSizeInBits().getKnownMinValue());
  };

  for (unsigned M : Modes) {
    TypeSetByHwMode::SetType &S = Small.get(M);
    TypeSetByHwMode::SetType &B = Big.get(M);
    // MinS = min scalar in Small, remove all scalars from Big that are
    // smaller-or-equal than MinS.
    auto MinS = min_if(S.begin(), S.end(), isScalar, LT);
    if (MinS != S.end())
      Changed |=
          berase_if(B, std::bind(SameKindLE, std::placeholders::_1, *MinS));

    // MaxS = max scalar in Big, remove all scalars from Small that are
    // larger than MaxS.
    auto MaxS = max_if(B.begin(), B.end(), isScalar, LT);
    if (MaxS != B.end())
      Changed |=
          berase_if(S, std::bind(SameKindLE, *MaxS, std::placeholders::_1));

    // MinV = min vector in Small, remove all vectors from Big that are
    // smaller-or-equal than MinV.
    auto MinV = min_if(S.begin(), S.end(), isVector, LT);
    if (MinV != S.end())
      Changed |=
          berase_if(B, std::bind(SameKindLE, std::placeholders::_1, *MinV));

    // MaxV = max vector in Big, remove all vectors from Small that are
    // larger than MaxV.
    auto MaxV = max_if(B.begin(), B.end(), isVector, LT);
    if (MaxV != B.end())
      Changed |=
          berase_if(S, std::bind(SameKindLE, *MaxV, std::placeholders::_1));
  }

  return Changed;
}

/// 1. Ensure that for each type T in Vec, T is a vector type, and that
///    for each type U in Elem, U is a scalar type.
/// 2. Ensure that for each (scalar) type U in Elem, there exists a (vector)
///    type T in Vec, such that U is the element type of T.
bool TypeInfer::EnforceVectorEltTypeIs(TypeSetByHwMode &Vec,
                                       TypeSetByHwMode &Elem) {
  ValidateOnExit _1(Vec, *this), _2(Elem, *this);
  if (TP.hasError())
    return false;
  bool Changed = false;

  if (Vec.empty())
    Changed |= EnforceVector(Vec);
  if (Elem.empty())
    Changed |= EnforceScalar(Elem);

  SmallVector<unsigned, 4> Modes;
  union_modes(Vec, Elem, Modes);
  for (unsigned M : Modes) {
    TypeSetByHwMode::SetType &V = Vec.get(M);
    TypeSetByHwMode::SetType &E = Elem.get(M);

    Changed |= berase_if(V, isScalar); // Scalar = !vector
    Changed |= berase_if(E, isVector); // Vector = !scalar
    assert(!V.empty() && !E.empty());

    MachineValueTypeSet VT, ST;
    // Collect element types from the "vector" set.
    for (MVT T : V)
      VT.insert(T.getVectorElementType());
    // Collect scalar types from the "element" set.
    for (MVT T : E)
      ST.insert(T);

    // Remove from V all (vector) types whose element type is not in S.
    Changed |= berase_if(V, [&ST](MVT T) -> bool {
      return !ST.count(T.getVectorElementType());
    });
    // Remove from E all (scalar) types, for which there is no corresponding
    // type in V.
    Changed |= berase_if(E, [&VT](MVT T) -> bool { return !VT.count(T); });
  }

  return Changed;
}

bool TypeInfer::EnforceVectorEltTypeIs(TypeSetByHwMode &Vec,
                                       const ValueTypeByHwMode &VVT) {
  TypeSetByHwMode Tmp(VVT);
  ValidateOnExit _1(Vec, *this), _2(Tmp, *this);
  return EnforceVectorEltTypeIs(Vec, Tmp);
}

/// Ensure that for each type T in Sub, T is a vector type, and there
/// exists a type U in Vec such that U is a vector type with the same
/// element type as T and at least as many elements as T.
bool TypeInfer::EnforceVectorSubVectorTypeIs(TypeSetByHwMode &Vec,
                                             TypeSetByHwMode &Sub) {
  ValidateOnExit _1(Vec, *this), _2(Sub, *this);
  if (TP.hasError())
    return false;

  /// Return true if B is a suB-vector of P, i.e. P is a suPer-vector of B.
  auto IsSubVec = [](MVT B, MVT P) -> bool {
    if (!B.isVector() || !P.isVector())
      return false;
    // Logically a <4 x i32> is a valid subvector of <n x 4 x i32>
    // but until there are obvious use-cases for this, keep the
    // types separate.
    if (B.isScalableVector() != P.isScalableVector())
      return false;
    if (B.getVectorElementType() != P.getVectorElementType())
      return false;
    return B.getVectorMinNumElements() < P.getVectorMinNumElements();
  };

  /// Return true if S has no element (vector type) that T is a sub-vector of,
  /// i.e. has the same element type as T and more elements.
  auto NoSubV = [&IsSubVec](const TypeSetByHwMode::SetType &S, MVT T) -> bool {
    for (auto I : S)
      if (IsSubVec(T, I))
        return false;
    return true;
  };

  /// Return true if S has no element (vector type) that T is a super-vector
  /// of, i.e. has the same element type as T and fewer elements.
  auto NoSupV = [&IsSubVec](const TypeSetByHwMode::SetType &S, MVT T) -> bool {
    for (auto I : S)
      if (IsSubVec(I, T))
        return false;
    return true;
  };

  bool Changed = false;

  if (Vec.empty())
    Changed |= EnforceVector(Vec);
  if (Sub.empty())
    Changed |= EnforceVector(Sub);

  SmallVector<unsigned, 4> Modes;
  union_modes(Vec, Sub, Modes);
  for (unsigned M : Modes) {
    TypeSetByHwMode::SetType &S = Sub.get(M);
    TypeSetByHwMode::SetType &V = Vec.get(M);

    Changed |= berase_if(S, isScalar);

    // Erase all types from S that are not sub-vectors of a type in V.
    Changed |= berase_if(S, std::bind(NoSubV, V, std::placeholders::_1));

    // Erase all types from V that are not super-vectors of a type in S.
    Changed |= berase_if(V, std::bind(NoSupV, S, std::placeholders::_1));
  }

  return Changed;
}

/// 1. Ensure that V has a scalar type iff W has a scalar type.
/// 2. Ensure that for each vector type T in V, there exists a vector
///    type U in W, such that T and U have the same number of elements.
/// 3. Ensure that for each vector type U in W, there exists a vector
///    type T in V, such that T and U have the same number of elements
///    (reverse of 2).
bool TypeInfer::EnforceSameNumElts(TypeSetByHwMode &V, TypeSetByHwMode &W) {
  ValidateOnExit _1(V, *this), _2(W, *this);
  if (TP.hasError())
    return false;

  bool Changed = false;
  if (V.empty())
    Changed |= EnforceAny(V);
  if (W.empty())
    Changed |= EnforceAny(W);

  // An actual vector type cannot have 0 elements, so we can treat scalars
  // as zero-length vectors. This way both vectors and scalars can be
  // processed identically.
  auto NoLength = [](const SmallDenseSet<ElementCount> &Lengths,
                     MVT T) -> bool {
    return !Lengths.contains(T.isVector() ? T.getVectorElementCount()
                                          : ElementCount());
  };

  SmallVector<unsigned, 4> Modes;
  union_modes(V, W, Modes);
  for (unsigned M : Modes) {
    TypeSetByHwMode::SetType &VS = V.get(M);
    TypeSetByHwMode::SetType &WS = W.get(M);

    SmallDenseSet<ElementCount> VN, WN;
    for (MVT T : VS)
      VN.insert(T.isVector() ? T.getVectorElementCount() : ElementCount());
    for (MVT T : WS)
      WN.insert(T.isVector() ? T.getVectorElementCount() : ElementCount());

    Changed |= berase_if(VS, std::bind(NoLength, WN, std::placeholders::_1));
    Changed |= berase_if(WS, std::bind(NoLength, VN, std::placeholders::_1));
  }
  return Changed;
}

namespace {
struct TypeSizeComparator {
  bool operator()(const TypeSize &LHS, const TypeSize &RHS) const {
    return std::tuple(LHS.isScalable(), LHS.getKnownMinValue()) <
           std::tuple(RHS.isScalable(), RHS.getKnownMinValue());
  }
};
} // end anonymous namespace

/// 1. Ensure that for each type T in A, there exists a type U in B,
///    such that T and U have equal size in bits.
/// 2. Ensure that for each type U in B, there exists a type T in A
///    such that T and U have equal size in bits (reverse of 1).
bool TypeInfer::EnforceSameSize(TypeSetByHwMode &A, TypeSetByHwMode &B) {
  ValidateOnExit _1(A, *this), _2(B, *this);
  if (TP.hasError())
    return false;
  bool Changed = false;
  if (A.empty())
    Changed |= EnforceAny(A);
  if (B.empty())
    Changed |= EnforceAny(B);

  using TypeSizeSet = SmallSet<TypeSize, 2, TypeSizeComparator>;

  auto NoSize = [](const TypeSizeSet &Sizes, MVT T) -> bool {
    return !Sizes.contains(T.getSizeInBits());
  };

  SmallVector<unsigned, 4> Modes;
  union_modes(A, B, Modes);
  for (unsigned M : Modes) {
    TypeSetByHwMode::SetType &AS = A.get(M);
    TypeSetByHwMode::SetType &BS = B.get(M);
    TypeSizeSet AN, BN;

    for (MVT T : AS)
      AN.insert(T.getSizeInBits());
    for (MVT T : BS)
      BN.insert(T.getSizeInBits());

    Changed |= berase_if(AS, std::bind(NoSize, BN, std::placeholders::_1));
    Changed |= berase_if(BS, std::bind(NoSize, AN, std::placeholders::_1));
  }

  return Changed;
}

void TypeInfer::expandOverloads(TypeSetByHwMode &VTS) const {
  ValidateOnExit _1(VTS, *this);
  const TypeSetByHwMode &Legal = getLegalTypes();
  assert(Legal.isSimple() && "Default-mode only expected");
  const TypeSetByHwMode::SetType &LegalTypes = Legal.getSimple();

  for (auto &I : VTS)
    expandOverloads(I.second, LegalTypes);
}

void TypeInfer::expandOverloads(TypeSetByHwMode::SetType &Out,
                                const TypeSetByHwMode::SetType &Legal) const {
  if (Out.count(MVT::pAny)) {
    Out.erase(MVT::pAny);
    Out.insert(MVT::iPTR);
    for (MVT T : MVT::cheri_capability_valuetypes()) {
      if (Legal.count(T))
        Out.insert(MVT::cPTR);
    }
  } else if (Out.count(MVT::iAny)) {
    Out.erase(MVT::iAny);
    for (MVT T : MVT::integer_valuetypes())
      if (Legal.count(T))
        Out.insert(T);
    for (MVT T : MVT::integer_fixedlen_vector_valuetypes())
      if (Legal.count(T))
        Out.insert(T);
    for (MVT T : MVT::integer_scalable_vector_valuetypes())
      if (Legal.count(T))
        Out.insert(T);
  } else if (Out.count(MVT::fAny)) {
    Out.erase(MVT::fAny);
    for (MVT T : MVT::fp_valuetypes())
      if (Legal.count(T))
        Out.insert(T);
    for (MVT T : MVT::fp_fixedlen_vector_valuetypes())
      if (Legal.count(T))
        Out.insert(T);
    for (MVT T : MVT::fp_scalable_vector_valuetypes())
      if (Legal.count(T))
        Out.insert(T);
  } else if (Out.count(MVT::vAny)) {
    Out.erase(MVT::vAny);
    for (MVT T : MVT::vector_valuetypes())
      if (Legal.count(T))
        Out.insert(T);
  } else if (Out.count(MVT::Any)) {
    Out.erase(MVT::Any);
    for (MVT T : MVT::all_valuetypes())
      if (Legal.count(T))
        Out.insert(T);
  }
}

const TypeSetByHwMode &TypeInfer::getLegalTypes() const {
  if (!LegalTypesCached) {
    TypeSetByHwMode::SetType &LegalTypes = LegalCache.getOrCreate(DefaultMode);
    // Stuff all types from all modes into the default mode.
    const TypeSetByHwMode &LTS = TP.getDAGPatterns().getLegalTypes();
    for (const auto &I : LTS)
      LegalTypes.insert(I.second);
    LegalTypesCached = true;
  }
  assert(LegalCache.isSimple() && "Default-mode only expected");
  return LegalCache;
}

TypeInfer::ValidateOnExit::~ValidateOnExit() {
  if (Infer.Validate && !VTS.validate()) {
#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
    errs() << "Type set is empty for each HW mode:\n"
              "possible type contradiction in the pattern below "
              "(use -print-records with llvm-tblgen to see all "
              "expanded records).\n";
    Infer.TP.dump();
    errs() << "Generated from record:\n";
    Infer.TP.getRecord()->dump();
#endif
    PrintFatalError(Infer.TP.getRecord()->getLoc(),
                    "Type set is empty for each HW mode in '" +
                        Infer.TP.getRecord()->getName() + "'");
  }
}

//===----------------------------------------------------------------------===//
// ScopedName Implementation
//===----------------------------------------------------------------------===//

bool ScopedName::operator==(const ScopedName &o) const {
  return Scope == o.Scope && Identifier == o.Identifier;
}

bool ScopedName::operator!=(const ScopedName &o) const { return !(*this == o); }

//===----------------------------------------------------------------------===//
// TreePredicateFn Implementation
//===----------------------------------------------------------------------===//

/// TreePredicateFn constructor.  Here 'N' is a subclass of PatFrag.
TreePredicateFn::TreePredicateFn(TreePattern *N) : PatFragRec(N) {
  assert(
      (!hasPredCode() || !hasImmCode()) &&
      ".td file corrupt: can't have a node predicate *and* an imm predicate");

  if (hasGISelPredicateCode() && hasGISelLeafPredicateCode())
    PrintFatalError(getOrigPatFragRecord()->getRecord()->getLoc(),
                    ".td file corrupt: can't have GISelPredicateCode *and* "
                    "GISelLeafPredicateCode");
}

bool TreePredicateFn::hasPredCode() const {
  return isLoad() || isStore() || isAtomic() || hasNoUse() || hasOneUse() ||
         !PatFragRec->getRecord()->getValueAsString("PredicateCode").empty();
}

std::string TreePredicateFn::getPredCode() const {
  std::string Code;

  if (!isLoad() && !isStore() && !isAtomic() && getMemoryVT())
    PrintFatalError(getOrigPatFragRecord()->getRecord()->getLoc(),
                    "MemoryVT requires IsLoad or IsStore or IsAtomic");

  if (!isLoad() && !isStore()) {
    if (isUnindexed())
      PrintFatalError(getOrigPatFragRecord()->getRecord()->getLoc(),
                      "IsUnindexed requires IsLoad or IsStore");

    if (getScalarMemoryVT())
      PrintFatalError(getOrigPatFragRecord()->getRecord()->getLoc(),
                      "ScalarMemoryVT requires IsLoad or IsStore");
  }

  if (isLoad() + isStore() + isAtomic() > 1)
    PrintFatalError(getOrigPatFragRecord()->getRecord()->getLoc(),
                    "IsLoad, IsStore, and IsAtomic are mutually exclusive");

  if (isLoad()) {
    if (!isUnindexed() && !isNonExtLoad() && !isAnyExtLoad() &&
        !isSignExtLoad() && !isZeroExtLoad() && getMemoryVT() == nullptr &&
        getScalarMemoryVT() == nullptr && getAddressSpaces() == nullptr &&
        getMinAlignment() < 1)
      PrintFatalError(getOrigPatFragRecord()->getRecord()->getLoc(),
                      "IsLoad cannot be used by itself");
  } else if (!isAtomic()) {
    if (isNonExtLoad())
      PrintFatalError(getOrigPatFragRecord()->getRecord()->getLoc(),
                      "IsNonExtLoad requires IsLoad or IsAtomic");
    if (isAnyExtLoad())
      PrintFatalError(getOrigPatFragRecord()->getRecord()->getLoc(),
                      "IsAnyExtLoad requires IsLoad or IsAtomic");
    if (isSignExtLoad())
      PrintFatalError(getOrigPatFragRecord()->getRecord()->getLoc(),
                      "IsSignExtLoad requires IsLoad or IsAtomic");
    if (isZeroExtLoad())
      PrintFatalError(getOrigPatFragRecord()->getRecord()->getLoc(),
                      "IsZeroExtLoad requires IsLoad or IsAtomic");
  }

  if (isStore()) {
    if (!isUnindexed() && !isTruncStore() && !isNonTruncStore() &&
        getMemoryVT() == nullptr && getScalarMemoryVT() == nullptr &&
        getAddressSpaces() == nullptr && getMinAlignment() < 1)
      PrintFatalError(getOrigPatFragRecord()->getRecord()->getLoc(),
                      "IsStore cannot be used by itself");
  } else {
    if (isNonTruncStore())
      PrintFatalError(getOrigPatFragRecord()->getRecord()->getLoc(),
                      "IsNonTruncStore requires IsStore");
    if (isTruncStore())
      PrintFatalError(getOrigPatFragRecord()->getRecord()->getLoc(),
                      "IsTruncStore requires IsStore");
  }

  if (isAtomic()) {
    if (getMemoryVT() == nullptr && getAddressSpaces() == nullptr &&
        // FIXME: Should atomic loads be IsLoad, IsAtomic, or both?
        !isNonExtLoad() && !isAnyExtLoad() && !isZeroExtLoad() &&
        !isSignExtLoad() && !isAtomicOrderingMonotonic() &&
        !isAtomicOrderingAcquire() && !isAtomicOrderingRelease() &&
        !isAtomicOrderingAcquireRelease() &&
        !isAtomicOrderingSequentiallyConsistent() &&
        !isAtomicOrderingAcquireOrStronger() &&
        !isAtomicOrderingReleaseOrStronger() &&
        !isAtomicOrderingWeakerThanAcquire() &&
        !isAtomicOrderingWeakerThanRelease())
      PrintFatalError(getOrigPatFragRecord()->getRecord()->getLoc(),
                      "IsAtomic cannot be used by itself");
  } else {
    if (isAtomicOrderingMonotonic())
      PrintFatalError(getOrigPatFragRecord()->getRecord()->getLoc(),
                      "IsAtomicOrderingMonotonic requires IsAtomic");
    if (isAtomicOrderingAcquire())
      PrintFatalError(getOrigPatFragRecord()->getRecord()->getLoc(),
                      "IsAtomicOrderingAcquire requires IsAtomic");
    if (isAtomicOrderingRelease())
      PrintFatalError(getOrigPatFragRecord()->getRecord()->getLoc(),
                      "IsAtomicOrderingRelease requires IsAtomic");
    if (isAtomicOrderingAcquireRelease())
      PrintFatalError(getOrigPatFragRecord()->getRecord()->getLoc(),
                      "IsAtomicOrderingAcquireRelease requires IsAtomic");
    if (isAtomicOrderingSequentiallyConsistent())
      PrintFatalError(
          getOrigPatFragRecord()->getRecord()->getLoc(),
          "IsAtomicOrderingSequentiallyConsistent requires IsAtomic");
    if (isAtomicOrderingAcquireOrStronger())
      PrintFatalError(getOrigPatFragRecord()->getRecord()->getLoc(),
                      "IsAtomicOrderingAcquireOrStronger requires IsAtomic");
    if (isAtomicOrderingReleaseOrStronger())
      PrintFatalError(getOrigPatFragRecord()->getRecord()->getLoc(),
                      "IsAtomicOrderingReleaseOrStronger requires IsAtomic");
    if (isAtomicOrderingWeakerThanAcquire())
      PrintFatalError(getOrigPatFragRecord()->getRecord()->getLoc(),
                      "IsAtomicOrderingWeakerThanAcquire requires IsAtomic");
  }

  if (isLoad() || isStore() || isAtomic()) {
    if (const ListInit *AddressSpaces = getAddressSpaces()) {
      Code += "unsigned AddrSpace = cast<MemSDNode>(N)->getAddressSpace();\n"
              " if (";

      ListSeparator LS(" && ");
      for (const Init *Val : AddressSpaces->getElements()) {
        Code += LS;

        const IntInit *IntVal = dyn_cast<IntInit>(Val);
        if (!IntVal) {
          PrintFatalError(getOrigPatFragRecord()->getRecord()->getLoc(),
                          "AddressSpaces element must be integer");
        }

        Code += "AddrSpace != " + utostr(IntVal->getValue());
      }

      Code += ")\nreturn false;\n";
    }

    int64_t MinAlign = getMinAlignment();
    if (MinAlign > 0) {
      Code += "if (cast<MemSDNode>(N)->getAlign() < Align(";
      Code += utostr(MinAlign);
      Code += "))\nreturn false;\n";
    }

    if (const Record *MemoryVT = getMemoryVT())
      Code += ("if (cast<MemSDNode>(N)->getMemoryVT() != MVT::" +
               MemoryVT->getName() + ") return false;\n")
                  .str();
  }

  if (isAtomic() && isAtomicOrderingMonotonic())
    Code += "if (cast<AtomicSDNode>(N)->getMergedOrdering() != "
            "AtomicOrdering::Monotonic) return false;\n";
  if (isAtomic() && isAtomicOrderingAcquire())
    Code += "if (cast<AtomicSDNode>(N)->getMergedOrdering() != "
            "AtomicOrdering::Acquire) return false;\n";
  if (isAtomic() && isAtomicOrderingRelease())
    Code += "if (cast<AtomicSDNode>(N)->getMergedOrdering() != "
            "AtomicOrdering::Release) return false;\n";
  if (isAtomic() && isAtomicOrderingAcquireRelease())
    Code += "if (cast<AtomicSDNode>(N)->getMergedOrdering() != "
            "AtomicOrdering::AcquireRelease) return false;\n";
  if (isAtomic() && isAtomicOrderingSequentiallyConsistent())
    Code += "if (cast<AtomicSDNode>(N)->getMergedOrdering() != "
            "AtomicOrdering::SequentiallyConsistent) return false;\n";

  if (isAtomic() && isAtomicOrderingAcquireOrStronger())
    Code +=
        "if (!isAcquireOrStronger(cast<AtomicSDNode>(N)->getMergedOrdering())) "
        "return false;\n";
  if (isAtomic() && isAtomicOrderingWeakerThanAcquire())
    Code +=
        "if (isAcquireOrStronger(cast<AtomicSDNode>(N)->getMergedOrdering())) "
        "return false;\n";

  if (isAtomic() && isAtomicOrderingReleaseOrStronger())
    Code +=
        "if (!isReleaseOrStronger(cast<AtomicSDNode>(N)->getMergedOrdering())) "
        "return false;\n";
  if (isAtomic() && isAtomicOrderingWeakerThanRelease())
    Code +=
        "if (isReleaseOrStronger(cast<AtomicSDNode>(N)->getMergedOrdering())) "
        "return false;\n";

  if (isAtomic()) {
    if ((isNonExtLoad() + isAnyExtLoad() + isSignExtLoad() + isZeroExtLoad()) >
        1)
      PrintFatalError(
          getOrigPatFragRecord()->getRecord()->getLoc(),
          "IsNonExtLoad, IsAnyExtLoad, IsSignExtLoad, and IsZeroExtLoad are "
          "mutually exclusive");

    if (isNonExtLoad())
      Code += "if (cast<AtomicSDNode>(N)->getExtensionType() != "
              "ISD::NON_EXTLOAD) return false;\n";
    if (isAnyExtLoad())
      Code += "if (cast<AtomicSDNode>(N)->getExtensionType() != ISD::EXTLOAD) "
              "return false;\n";
    if (isSignExtLoad())
      Code += "if (cast<AtomicSDNode>(N)->getExtensionType() != ISD::SEXTLOAD) "
              "return false;\n";
    if (isZeroExtLoad())
      Code += "if (cast<AtomicSDNode>(N)->getExtensionType() != ISD::ZEXTLOAD) "
              "return false;\n";
  }

  if (isLoad() || isStore()) {
    StringRef SDNodeName = isLoad() ? "LoadSDNode" : "StoreSDNode";

    if (isUnindexed())
      Code += ("if (cast<" + SDNodeName +
               ">(N)->getAddressingMode() != ISD::UNINDEXED) "
               "return false;\n")
                  .str();

    if (isLoad()) {
      if ((isNonExtLoad() + isAnyExtLoad() + isSignExtLoad() +
           isZeroExtLoad()) > 1)
        PrintFatalError(getOrigPatFragRecord()->getRecord()->getLoc(),
                        "IsNonExtLoad, IsAnyExtLoad, IsSignExtLoad, and "
                        "IsZeroExtLoad are mutually exclusive");
      if (isNonExtLoad())
        Code += "if (cast<LoadSDNode>(N)->getExtensionType() != "
                "ISD::NON_EXTLOAD) return false;\n";
      if (isAnyExtLoad())
        Code += "if (cast<LoadSDNode>(N)->getExtensionType() != ISD::EXTLOAD) "
                "return false;\n";
      if (isSignExtLoad())
        Code += "if (cast<LoadSDNode>(N)->getExtensionType() != ISD::SEXTLOAD) "
                "return false;\n";
      if (isZeroExtLoad())
        Code += "if (cast<LoadSDNode>(N)->getExtensionType() != ISD::ZEXTLOAD) "
                "return false;\n";
    } else {
      if ((isNonTruncStore() + isTruncStore()) > 1)
        PrintFatalError(
            getOrigPatFragRecord()->getRecord()->getLoc(),
            "IsNonTruncStore, and IsTruncStore are mutually exclusive");
      if (isNonTruncStore())
        Code +=
            " if (cast<StoreSDNode>(N)->isTruncatingStore()) return false;\n";
      if (isTruncStore())
        Code +=
            " if (!cast<StoreSDNode>(N)->isTruncatingStore()) return false;\n";
    }

    if (const Record *ScalarMemoryVT = getScalarMemoryVT())
      Code += ("if (cast<" + SDNodeName +
               ">(N)->getMemoryVT().getScalarType() != MVT::" +
               ScalarMemoryVT->getName() + ") return false;\n")
                  .str();
  }

  if (hasNoUse())
    Code += "if (N->hasAnyUseOfValue(0)) return false;\n";
  if (hasOneUse())
    Code += "if (!N->hasNUsesOfValue(1, 0)) return false;\n";

  std::string PredicateCode =
      PatFragRec->getRecord()->getValueAsString("PredicateCode").str();

  Code += PredicateCode;

  if (PredicateCode.empty() && !Code.empty())
    Code += "return true;\n";

  return Code;
}

bool TreePredicateFn::hasImmCode() const {
  return !PatFragRec->getRecord()->getValueAsString("ImmediateCode").empty();
}

std::string TreePredicateFn::getImmCode() const {
  return PatFragRec->getRecord()->getValueAsString("ImmediateCode").str();
}

bool TreePredicateFn::immCodeUsesAPInt() const {
  return getOrigPatFragRecord()->getRecord()->getValueAsBit("IsAPInt");
}

bool TreePredicateFn::immCodeUsesAPFloat() const {
  bool Unset;
  // The return value will be false when IsAPFloat is unset.
  return getOrigPatFragRecord()->getRecord()->getValueAsBitOrUnset("IsAPFloat",
                                                                   Unset);
}

bool TreePredicateFn::isPredefinedPredicateEqualTo(StringRef Field,
                                                   bool Value) const {
  bool Unset;
  bool Result =
      getOrigPatFragRecord()->getRecord()->getValueAsBitOrUnset(Field, Unset);
  if (Unset)
    return false;
  return Result == Value;
}
bool TreePredicateFn::usesOperands() const {
  return isPredefinedPredicateEqualTo("PredicateCodeUsesOperands", true);
}
bool TreePredicateFn::hasNoUse() const {
  return isPredefinedPredicateEqualTo("HasNoUse", true);
}
bool TreePredicateFn::hasOneUse() const {
  return isPredefinedPredicateEqualTo("HasOneUse", true);
}
bool TreePredicateFn::isLoad() const {
  return isPredefinedPredicateEqualTo("IsLoad", true);
}
bool TreePredicateFn::isStore() const {
  return isPredefinedPredicateEqualTo("IsStore", true);
}
bool TreePredicateFn::isAtomic() const {
  return isPredefinedPredicateEqualTo("IsAtomic", true);
}
bool TreePredicateFn::isUnindexed() const {
  return isPredefinedPredicateEqualTo("IsUnindexed", true);
}
bool TreePredicateFn::isNonExtLoad() const {
  return isPredefinedPredicateEqualTo("IsNonExtLoad", true);
}
bool TreePredicateFn::isAnyExtLoad() const {
  return isPredefinedPredicateEqualTo("IsAnyExtLoad", true);
}
bool TreePredicateFn::isSignExtLoad() const {
  return isPredefinedPredicateEqualTo("IsSignExtLoad", true);
}
bool TreePredicateFn::isZeroExtLoad() const {
  return isPredefinedPredicateEqualTo("IsZeroExtLoad", true);
}
bool TreePredicateFn::isNonTruncStore() const {
  return isPredefinedPredicateEqualTo("IsTruncStore", false);
}
bool TreePredicateFn::isTruncStore() const {
  return isPredefinedPredicateEqualTo("IsTruncStore", true);
}
bool TreePredicateFn::isAtomicOrderingMonotonic() const {
  return isPredefinedPredicateEqualTo("IsAtomicOrderingMonotonic", true);
}
bool TreePredicateFn::isAtomicOrderingAcquire() const {
  return isPredefinedPredicateEqualTo("IsAtomicOrderingAcquire", true);
}
bool TreePredicateFn::isAtomicOrderingRelease() const {
  return isPredefinedPredicateEqualTo("IsAtomicOrderingRelease", true);
}
bool TreePredicateFn::isAtomicOrderingAcquireRelease() const {
  return isPredefinedPredicateEqualTo("IsAtomicOrderingAcquireRelease", true);
}
bool TreePredicateFn::isAtomicOrderingSequentiallyConsistent() const {
  return isPredefinedPredicateEqualTo("IsAtomicOrderingSequentiallyConsistent",
                                      true);
}
bool TreePredicateFn::isAtomicOrderingAcquireOrStronger() const {
  return isPredefinedPredicateEqualTo("IsAtomicOrderingAcquireOrStronger",
                                      true);
}
bool TreePredicateFn::isAtomicOrderingWeakerThanAcquire() const {
  return isPredefinedPredicateEqualTo("IsAtomicOrderingAcquireOrStronger",
                                      false);
}
bool TreePredicateFn::isAtomicOrderingReleaseOrStronger() const {
  return isPredefinedPredicateEqualTo("IsAtomicOrderingReleaseOrStronger",
                                      true);
}
bool TreePredicateFn::isAtomicOrderingWeakerThanRelease() const {
  return isPredefinedPredicateEqualTo("IsAtomicOrderingReleaseOrStronger",
                                      false);
}
const Record *TreePredicateFn::getMemoryVT() const {
  const Record *R = getOrigPatFragRecord()->getRecord();
  if (R->isValueUnset("MemoryVT"))
    return nullptr;
  return R->getValueAsDef("MemoryVT");
}

const ListInit *TreePredicateFn::getAddressSpaces() const {
  const Record *R = getOrigPatFragRecord()->getRecord();
  if (R->isValueUnset("AddressSpaces"))
    return nullptr;
  return R->getValueAsListInit("AddressSpaces");
}

int64_t TreePredicateFn::getMinAlignment() const {
  const Record *R = getOrigPatFragRecord()->getRecord();
  if (R->isValueUnset("MinAlignment"))
    return 0;
  return R->getValueAsInt("MinAlignment");
}

const Record *TreePredicateFn::getScalarMemoryVT() const {
  const Record *R = getOrigPatFragRecord()->getRecord();
  if (R->isValueUnset("ScalarMemoryVT"))
    return nullptr;
  return R->getValueAsDef("ScalarMemoryVT");
}

bool TreePredicateFn::hasGISelPredicateCode() const {
  return !PatFragRec->getRecord()
              ->getValueAsString("GISelPredicateCode")
              .empty();
}

std::string TreePredicateFn::getGISelPredicateCode() const {
  return PatFragRec->getRecord()->getValueAsString("GISelPredicateCode").str();
}

bool TreePredicateFn::hasGISelLeafPredicateCode() const {
  return PatFragRec->getRecord()
      ->getValueAsOptionalString("GISelLeafPredicateCode")
      .has_value();
}

std::string TreePredicateFn::getGISelLeafPredicateCode() const {
  return PatFragRec->getRecord()
      ->getValueAsOptionalString("GISelLeafPredicateCode")
      .value_or(StringRef())
      .str();
}

StringRef TreePredicateFn::getImmType() const {
  if (immCodeUsesAPInt())
    return "const APInt &";
  if (immCodeUsesAPFloat())
    return "const APFloat &";
  return "int64_t";
}

StringRef TreePredicateFn::getImmTypeIdentifier() const {
  if (immCodeUsesAPInt())
    return "APInt";
  if (immCodeUsesAPFloat())
    return "APFloat";
  return "I64";
}

/// isAlwaysTrue - Return true if this is a noop predicate.
bool TreePredicateFn::isAlwaysTrue() const {
  return !hasPredCode() && !hasImmCode();
}

/// Return the name to use in the generated code to reference this, this is
/// "Predicate_foo" if from a pattern fragment "foo".
std::string TreePredicateFn::getFnName() const {
  return "Predicate_" + PatFragRec->getRecord()->getName().str();
}

/// 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 TreePredicateFn::getCodeToRunOnSDNode() const {
  // Handle immediate predicates first.
  std::string ImmCode = getImmCode();
  if (!ImmCode.empty()) {
    if (isLoad())
      PrintFatalError(getOrigPatFragRecord()->getRecord()->getLoc(),
                      "IsLoad cannot be used with ImmLeaf or its subclasses");
    if (isStore())
      PrintFatalError(getOrigPatFragRecord()->getRecord()->getLoc(),
                      "IsStore cannot be used with ImmLeaf or its subclasses");
    if (isUnindexed())
      PrintFatalError(
          getOrigPatFragRecord()->getRecord()->getLoc(),
          "IsUnindexed cannot be used with ImmLeaf or its subclasses");
    if (isNonExtLoad())
      PrintFatalError(
          getOrigPatFragRecord()->getRecord()->getLoc(),
          "IsNonExtLoad cannot be used with ImmLeaf or its subclasses");
    if (isAnyExtLoad())
      PrintFatalError(
          getOrigPatFragRecord()->getRecord()->getLoc(),
          "IsAnyExtLoad cannot be used with ImmLeaf or its subclasses");
    if (isSignExtLoad())
      PrintFatalError(
          getOrigPatFragRecord()->getRecord()->getLoc(),
          "IsSignExtLoad cannot be used with ImmLeaf or its subclasses");
    if (isZeroExtLoad())
      PrintFatalError(
          getOrigPatFragRecord()->getRecord()->getLoc(),
          "IsZeroExtLoad cannot be used with ImmLeaf or its subclasses");
    if (isNonTruncStore())
      PrintFatalError(
          getOrigPatFragRecord()->getRecord()->getLoc(),
          "IsNonTruncStore cannot be used with ImmLeaf or its subclasses");
    if (isTruncStore())
      PrintFatalError(
          getOrigPatFragRecord()->getRecord()->getLoc(),
          "IsTruncStore cannot be used with ImmLeaf or its subclasses");
    if (getMemoryVT())
      PrintFatalError(getOrigPatFragRecord()->getRecord()->getLoc(),
                      "MemoryVT cannot be used with ImmLeaf or its subclasses");
    if (getScalarMemoryVT())
      PrintFatalError(
          getOrigPatFragRecord()->getRecord()->getLoc(),
          "ScalarMemoryVT cannot be used with ImmLeaf or its subclasses");

    std::string Result = ("    " + getImmType() + " Imm = ").str();
    if (immCodeUsesAPFloat())
      Result += "cast<ConstantFPSDNode>(Op.getNode())->getValueAPF();\n";
    else if (immCodeUsesAPInt())
      Result += "Op->getAsAPIntVal();\n";
    else
      Result += "cast<ConstantSDNode>(Op.getNode())->getSExtValue();\n";
    return Result + ImmCode;
  }

  // Handle arbitrary node predicates.
  assert(hasPredCode() && "Don't have any predicate code!");

  // If this is using PatFrags, there are multiple trees to search. They should
  // all have the same class.  FIXME: Is there a way to find a common
  // superclass?
  StringRef ClassName;
  for (const auto &Tree : PatFragRec->getTrees()) {
    StringRef TreeClassName;
    if (Tree->isLeaf())
      TreeClassName = "SDNode";
    else {
      const Record *Op = Tree->getOperator();
      const SDNodeInfo &Info = PatFragRec->getDAGPatterns().getSDNodeInfo(Op);
      TreeClassName = Info.getSDClassName();
    }

    if (ClassName.empty())
      ClassName = TreeClassName;
    else if (ClassName != TreeClassName) {
      PrintFatalError(getOrigPatFragRecord()->getRecord()->getLoc(),
                      "PatFrags trees do not have consistent class");
    }
  }

  std::string Result;
  if (ClassName == "SDNode")
    Result = "    SDNode *N = Op.getNode();\n";
  else
    Result = "    auto *N = cast<" + ClassName.str() + ">(Op.getNode());\n";

  return (Twine(Result) + "    (void)N;\n" + getPredCode()).str();
}

//===----------------------------------------------------------------------===//
// PatternToMatch implementation
//

static bool isImmAllOnesAllZerosMatch(const TreePatternNode &P) {
  if (!P.isLeaf())
    return false;
  const DefInit *DI = dyn_cast<DefInit>(P.getLeafValue());
  if (!DI)
    return false;

  const Record *R = DI->getDef();
  return R->getName() == "immAllOnesV" || R->getName() == "immAllZerosV";
}

/// getPatternSize - Return the 'size' of this pattern.  We want to match large
/// patterns before small ones.  This is used to determine the size of a
/// pattern.
static unsigned getPatternSize(const TreePatternNode &P,
                               const CodeGenDAGPatterns &CGP) {
  unsigned Size = 3; // The node itself.
  // If the root node is a ConstantSDNode, increases its size.
  // e.g. (set R32:$dst, 0).
  if (P.isLeaf() && isa<IntInit>(P.getLeafValue()))
    Size += 2;

  if (const ComplexPattern *AM = P.getComplexPatternInfo(CGP)) {
    Size += AM->getComplexity();
    // We don't want to count any children twice, so return early.
    return Size;
  }

  // If this node has some predicate function that must match, it adds to the
  // complexity of this node.
  if (!P.getPredicateCalls().empty())
    ++Size;

  // Count children in the count if they are also nodes.
  for (const TreePatternNode &Child : P.children()) {
    if (!Child.isLeaf() && Child.getNumTypes()) {
      const TypeSetByHwMode &T0 = Child.getExtType(0);
      // At this point, all variable type sets should be simple, i.e. only
      // have a default mode.
      if (T0.getMachineValueType() != MVT::Other) {
        Size += getPatternSize(Child, CGP);
        continue;
      }
    }
    if (Child.isLeaf()) {
      if (isa<IntInit>(Child.getLeafValue()))
        Size += 5; // Matches a ConstantSDNode (+3) and a specific value (+2).
      else if (Child.getComplexPatternInfo(CGP))
        Size += getPatternSize(Child, CGP);
      else if (isImmAllOnesAllZerosMatch(Child))
        Size += 4; // Matches a build_vector(+3) and a predicate (+1).
      else if (!Child.getPredicateCalls().empty())
        ++Size;
    }
  }

  return Size;
}

/// Compute the complexity metric for the input pattern.  This roughly
/// corresponds to the number of nodes that are covered.
int PatternToMatch::getPatternComplexity(const CodeGenDAGPatterns &CGP) const {
  return getPatternSize(getSrcPattern(), CGP) + getAddedComplexity();
}

void PatternToMatch::getPredicateRecords(
    SmallVectorImpl<const Record *> &PredicateRecs) const {
  for (const Init *I : Predicates->getElements()) {
    if (const DefInit *Pred = dyn_cast<DefInit>(I)) {
      const Record *Def = Pred->getDef();
      if (!Def->isSubClassOf("Predicate")) {
#ifndef NDEBUG
        Def->dump();
#endif
        llvm_unreachable("Unknown predicate type!");
      }
      PredicateRecs.push_back(Def);
    }
  }
  // Sort so that different orders get canonicalized to the same string.
  llvm::sort(PredicateRecs, LessRecord());
  // Remove duplicate predicates.
  PredicateRecs.erase(llvm::unique(PredicateRecs), PredicateRecs.end());
}

/// getPredicateCheck - Return a single string containing all of this
/// pattern's predicates concatenated with "&&" operators.
///
std::string PatternToMatch::getPredicateCheck() const {
  SmallVector<const Record *, 4> PredicateRecs;
  getPredicateRecords(PredicateRecs);

  SmallString<128> PredicateCheck;
  raw_svector_ostream OS(PredicateCheck);
  ListSeparator LS(" && ");
  for (const Record *Pred : PredicateRecs) {
    StringRef CondString = Pred->getValueAsString("CondString");
    if (CondString.empty())
      continue;
    OS << LS << '(' << CondString << ')';
  }

  if (!HwModeFeatures.empty())
    OS << LS << HwModeFeatures;

  return std::string(PredicateCheck);
}

//===----------------------------------------------------------------------===//
// SDTypeConstraint implementation
//

SDTypeConstraint::SDTypeConstraint(const Record *R, const CodeGenHwModes &CGH) {
  OperandNo = R->getValueAsInt("OperandNum");

  if (R->isSubClassOf("SDTCisVT")) {
    ConstraintType = SDTCisVT;
    VVT = getValueTypeByHwMode(R->getValueAsDef("VT"), CGH);
    for (const auto &P : VVT)
      if (P.second == MVT::isVoid)
        PrintFatalError(R->getLoc(), "Cannot use 'Void' as type to SDTCisVT");
  } else if (R->isSubClassOf("SDTCisPtrTy")) {
    ConstraintType = SDTCisPtrTy;
  } else if (R->isSubClassOf("SDTCisInt")) {
    ConstraintType = SDTCisInt;
  } else if (R->isSubClassOf("SDTCisFP")) {
    ConstraintType = SDTCisFP;
  } else if (R->isSubClassOf("SDTCisVec")) {
    ConstraintType = SDTCisVec;
  } else if (R->isSubClassOf("SDTCisSameAs")) {
    ConstraintType = SDTCisSameAs;
    OtherOperandNo = R->getValueAsInt("OtherOperandNum");
  } else if (R->isSubClassOf("SDTCisVTSmallerThanOp")) {
    ConstraintType = SDTCisVTSmallerThanOp;
    OtherOperandNo = R->getValueAsInt("OtherOperandNum");
  } else if (R->isSubClassOf("SDTCisOpSmallerThanOp")) {
    ConstraintType = SDTCisOpSmallerThanOp;
    OtherOperandNo = R->getValueAsInt("BigOperandNum");
  } else if (R->isSubClassOf("SDTCisEltOfVec")) {
    ConstraintType = SDTCisEltOfVec;
    OtherOperandNo = R->getValueAsInt("OtherOpNum");
  } else if (R->isSubClassOf("SDTCisSubVecOfVec")) {
    ConstraintType = SDTCisSubVecOfVec;
    OtherOperandNo = R->getValueAsInt("OtherOpNum");
  } else if (R->isSubClassOf("SDTCVecEltisVT")) {
    ConstraintType = SDTCVecEltisVT;
    VVT = getValueTypeByHwMode(R->getValueAsDef("VT"), CGH);
    for (const auto &P : VVT) {
      MVT T = P.second;
      if (T.isVector())
        PrintFatalError(R->getLoc(),
                        "Cannot use vector type as SDTCVecEltisVT");
      if (!T.isInteger() && !T.isFloatingPoint())
        PrintFatalError(R->getLoc(), "Must use integer or floating point type "
                                     "as SDTCVecEltisVT");
    }
  } else if (R->isSubClassOf("SDTCisSameNumEltsAs")) {
    ConstraintType = SDTCisSameNumEltsAs;
    OtherOperandNo = R->getValueAsInt("OtherOperandNum");
  } else if (R->isSubClassOf("SDTCisSameSizeAs")) {
    ConstraintType = SDTCisSameSizeAs;
    OtherOperandNo = R->getValueAsInt("OtherOperandNum");
  } else {
    PrintFatalError(R->getLoc(),
                    "Unrecognized SDTypeConstraint '" + R->getName() + "'!\n");
  }
}

/// getOperandNum - Return the node corresponding to operand #OpNo in tree
/// N, and the result number in ResNo.
static TreePatternNode &getOperandNum(unsigned OpNo, TreePatternNode &N,
                                      const SDNodeInfo &NodeInfo,
                                      unsigned &ResNo) {
  unsigned NumResults = NodeInfo.getNumResults();
  if (OpNo < NumResults) {
    ResNo = OpNo;
    return N;
  }

  OpNo -= NumResults;

  if (OpNo >= N.getNumChildren()) {
    PrintFatalError([&N, OpNo, NumResults](raw_ostream &OS) {
      OS << "Invalid operand number in type constraint " << (OpNo + NumResults);
      N.print(OS);
    });
  }
  return N.getChild(OpNo);
}

/// 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, flag an error.
bool SDTypeConstraint::ApplyTypeConstraint(TreePatternNode &N,
                                           const SDNodeInfo &NodeInfo,
                                           TreePattern &TP) const {
  if (TP.hasError())
    return false;

  unsigned ResNo = 0; // The result number being referenced.
  TreePatternNode &NodeToApply = getOperandNum(OperandNo, N, NodeInfo, ResNo);
  TypeInfer &TI = TP.getInfer();

  switch (ConstraintType) {
  case SDTCisVT:
    // Operand must be a particular type.
    return NodeToApply.UpdateNodeType(ResNo, VVT, TP);
  case SDTCisPtrTy: {
    // Operand must be a legal pointer (iPTR, or possibly cPTR) type.
    const TypeSetByHwMode &PtrTys = TP.getDAGPatterns().getLegalPtrTypes();
    return NodeToApply.UpdateNodeType(ResNo, PtrTys, TP);
  }
  case SDTCisInt:
    // Require it to be one of the legal integer VTs.
    return TI.EnforceInteger(NodeToApply.getExtType(ResNo));
  case SDTCisFP:
    // Require it to be one of the legal fp VTs.
    return TI.EnforceFloatingPoint(NodeToApply.getExtType(ResNo));
  case SDTCisVec:
    // Require it to be one of the legal vector VTs.
    return TI.EnforceVector(NodeToApply.getExtType(ResNo));
  case SDTCisSameAs: {
    unsigned OResNo = 0;
    TreePatternNode &OtherNode =
        getOperandNum(OtherOperandNo, N, NodeInfo, OResNo);
    return (int)NodeToApply.UpdateNodeType(ResNo, OtherNode.getExtType(OResNo),
                                           TP) |
           (int)OtherNode.UpdateNodeType(OResNo, NodeToApply.getExtType(ResNo),
                                         TP);
  }
  case SDTCisVTSmallerThanOp: {
    // The NodeToApply must be a leaf node that is a VT.  OtherOperandNum must
    // have an integer type that is smaller than the VT.
    if (!NodeToApply.isLeaf() || !isa<DefInit>(NodeToApply.getLeafValue()) ||
        !cast<DefInit>(NodeToApply.getLeafValue())
             ->getDef()
             ->isSubClassOf("ValueType")) {
      TP.error(N.getOperator()->getName() + " expects a VT operand!");
      return false;
    }
    const DefInit *DI = cast<DefInit>(NodeToApply.getLeafValue());
    const CodeGenTarget &T = TP.getDAGPatterns().getTargetInfo();
    auto VVT = getValueTypeByHwMode(DI->getDef(), T.getHwModes());
    TypeSetByHwMode TypeListTmp(VVT);

    unsigned OResNo = 0;
    TreePatternNode &OtherNode =
        getOperandNum(OtherOperandNo, N, NodeInfo, OResNo);

    return TI.EnforceSmallerThan(TypeListTmp, OtherNode.getExtType(OResNo),
                                 /*SmallIsVT*/ true);
  }
  case SDTCisOpSmallerThanOp: {
    unsigned BResNo = 0;
    TreePatternNode &BigOperand =
        getOperandNum(OtherOperandNo, N, NodeInfo, BResNo);
    return TI.EnforceSmallerThan(NodeToApply.getExtType(ResNo),
                                 BigOperand.getExtType(BResNo));
  }
  case SDTCisEltOfVec: {
    unsigned VResNo = 0;
    TreePatternNode &VecOperand =
        getOperandNum(OtherOperandNo, N, NodeInfo, VResNo);
    // Filter vector types out of VecOperand that don't have the right element
    // type.
    return TI.EnforceVectorEltTypeIs(VecOperand.getExtType(VResNo),
                                     NodeToApply.getExtType(ResNo));
  }
  case SDTCisSubVecOfVec: {
    unsigned VResNo = 0;
    TreePatternNode &BigVecOperand =
        getOperandNum(OtherOperandNo, N, NodeInfo, VResNo);

    // Filter vector types out of BigVecOperand that don't have the
    // right subvector type.
    return TI.EnforceVectorSubVectorTypeIs(BigVecOperand.getExtType(VResNo),
                                           NodeToApply.getExtType(ResNo));
  }
  case SDTCVecEltisVT: {
    return TI.EnforceVectorEltTypeIs(NodeToApply.getExtType(ResNo), VVT);
  }
  case SDTCisSameNumEltsAs: {
    unsigned OResNo = 0;
    TreePatternNode &OtherNode =
        getOperandNum(OtherOperandNo, N, NodeInfo, OResNo);
    return TI.EnforceSameNumElts(OtherNode.getExtType(OResNo),
                                 NodeToApply.getExtType(ResNo));
  }
  case SDTCisSameSizeAs: {
    unsigned OResNo = 0;
    TreePatternNode &OtherNode =
        getOperandNum(OtherOperandNo, N, NodeInfo, OResNo);
    return TI.EnforceSameSize(OtherNode.getExtType(OResNo),
                              NodeToApply.getExtType(ResNo));
  }
  }
  llvm_unreachable("Invalid ConstraintType!");
}

bool llvm::operator==(const SDTypeConstraint &LHS,
                      const SDTypeConstraint &RHS) {
  if (std::tie(LHS.OperandNo, LHS.ConstraintType) !=
      std::tie(RHS.OperandNo, RHS.ConstraintType))
    return false;
  switch (LHS.ConstraintType) {
  case SDTypeConstraint::SDTCisVT:
  case SDTypeConstraint::SDTCVecEltisVT:
    return LHS.VVT == RHS.VVT;
  case SDTypeConstraint::SDTCisPtrTy:
  case SDTypeConstraint::SDTCisInt:
  case SDTypeConstraint::SDTCisFP:
  case SDTypeConstraint::SDTCisVec:
    break;
  case SDTypeConstraint::SDTCisSameAs:
  case SDTypeConstraint::SDTCisVTSmallerThanOp:
  case SDTypeConstraint::SDTCisOpSmallerThanOp:
  case SDTypeConstraint::SDTCisEltOfVec:
  case SDTypeConstraint::SDTCisSubVecOfVec:
  case SDTypeConstraint::SDTCisSameNumEltsAs:
  case SDTypeConstraint::SDTCisSameSizeAs:
    return LHS.OtherOperandNo == RHS.OtherOperandNo;
  }
  return true;
}

bool llvm::operator<(const SDTypeConstraint &LHS, const SDTypeConstraint &RHS) {
  if (std::tie(LHS.OperandNo, LHS.ConstraintType) !=
      std::tie(RHS.OperandNo, RHS.ConstraintType))
    return std::tie(LHS.OperandNo, LHS.ConstraintType) <
           std::tie(RHS.OperandNo, RHS.ConstraintType);
  switch (LHS.ConstraintType) {
  case SDTypeConstraint::SDTCisVT:
  case SDTypeConstraint::SDTCVecEltisVT:
    return LHS.VVT < RHS.VVT;
  case SDTypeConstraint::SDTCisPtrTy:
  case SDTypeConstraint::SDTCisInt:
  case SDTypeConstraint::SDTCisFP:
  case SDTypeConstraint::SDTCisVec:
    break;
  case SDTypeConstraint::SDTCisSameAs:
  case SDTypeConstraint::SDTCisVTSmallerThanOp:
  case SDTypeConstraint::SDTCisOpSmallerThanOp:
  case SDTypeConstraint::SDTCisEltOfVec:
  case SDTypeConstraint::SDTCisSubVecOfVec:
  case SDTypeConstraint::SDTCisSameNumEltsAs:
  case SDTypeConstraint::SDTCisSameSizeAs:
    return LHS.OtherOperandNo < RHS.OtherOperandNo;
  }
  return false;
}

/// RegClassByHwMode acts like ValueTypeByHwMode, taking the type of the
/// register class from the active mode.
static TypeSetByHwMode getTypeForRegClassByHwMode(const CodeGenTarget &T,
                                                  const Record *R,
                                                  ArrayRef<SMLoc> Loc) {
  TypeSetByHwMode TypeSet;
  RegClassByHwMode Helper(R, T.getHwModes(), T.getRegBank());

  for (auto [ModeID, RegClass] : Helper) {
    ArrayRef<ValueTypeByHwMode> RegClassVTs = RegClass->getValueTypes();
    MachineValueTypeSet &ModeTypeSet = TypeSet.getOrCreate(ModeID);
    for (const ValueTypeByHwMode &VT : RegClassVTs) {
      if (!VT.hasMode(ModeID) && !VT.hasDefault()) {
        PrintError(R->getLoc(), "Could not resolve VT for Mode " +
                                    T.getHwModes().getModeName(ModeID, true));
        if (VT.getRecord())
          PrintNote(VT.getRecord()->getLoc(), "ValueTypeByHwMode " +
                                                  VT.getRecord()->getName() +
                                                  " defined here");
        PrintFatalNote(Loc, "pattern instantiated here");
        continue;
      }
      ModeTypeSet.insert(VT.getType(ModeID));
    }
  }

  return TypeSet;
}

// Update the node type to match an instruction operand or result as specified
// in the ins or outs lists on the instruction definition. Return true if the
// type was actually changed.
bool TreePatternNode::UpdateNodeTypeFromInst(unsigned ResNo,
                                             const Record *Operand,
                                             TreePattern &TP) {
  // The 'unknown' operand indicates that types should be inferred from the
  // context.
  if (Operand->isSubClassOf("unknown_class"))
    return false;

  // The Operand class specifies a type directly.
  if (Operand->isSubClassOf("Operand")) {
    const Record *R = Operand->getValueAsDef("Type");
    const CodeGenTarget &T = TP.getDAGPatterns().getTargetInfo();
    return UpdateNodeType(ResNo, getValueTypeByHwMode(R, T.getHwModes()), TP);
  }

  // Both RegisterClass and RegisterOperand operands derive their types from a
  // register class def.
  const Record *RC = nullptr;
  if (Operand->isSubClassOf("RegisterClassLike"))
    RC = Operand;
  else if (Operand->isSubClassOf("RegisterOperand"))
    RC = Operand->getValueAsDef("RegClass");

  assert(RC && "Unknown operand type");
  CodeGenTarget &Tgt = TP.getDAGPatterns().getTargetInfo();
  if (RC->isSubClassOf("RegClassByHwMode"))
    return UpdateNodeType(
        ResNo, getTypeForRegClassByHwMode(Tgt, RC, TP.getRecord()->getLoc()),
        TP);

  return UpdateNodeType(ResNo, Tgt.getRegisterClass(RC).getValueTypes(), TP);
}

bool TreePatternNode::ContainsUnresolvedType(TreePattern &TP) const {
  for (const TypeSetByHwMode &Type : Types)
    if (!TP.getInfer().isConcrete(Type, true))
      return true;
  for (const TreePatternNode &Child : children())
    if (Child.ContainsUnresolvedType(TP))
      return true;
  return false;
}

bool TreePatternNode::hasProperTypeByHwMode() const {
  for (const TypeSetByHwMode &S : Types)
    if (!S.isSimple())
      return true;
  for (const TreePatternNodePtr &C : Children)
    if (C->hasProperTypeByHwMode())
      return true;
  return false;
}

bool TreePatternNode::hasPossibleType() const {
  for (const TypeSetByHwMode &S : Types)
    if (!S.isPossible())
      return false;
  for (const TreePatternNodePtr &C : Children)
    if (!C->hasPossibleType())
      return false;
  return true;
}

bool TreePatternNode::setDefaultMode(unsigned Mode) {
  for (TypeSetByHwMode &S : Types) {
    S.makeSimple(Mode);
    // Check if the selected mode had a type conflict.
    if (S.get(DefaultMode).empty())
      return false;
  }
  for (const TreePatternNodePtr &C : Children)
    if (!C->setDefaultMode(Mode))
      return false;
  return true;
}

//===----------------------------------------------------------------------===//
// SDNodeInfo implementation
//
SDNodeInfo::SDNodeInfo(const Record *R, const CodeGenHwModes &CGH) : Def(R) {
  EnumName = R->getValueAsString("Opcode");
  SDClassName = R->getValueAsString("SDClass");
  const Record *TypeProfile = R->getValueAsDef("TypeProfile");
  NumResults = TypeProfile->getValueAsInt("NumResults");
  NumOperands = TypeProfile->getValueAsInt("NumOperands");

  // Parse the properties.
  Properties = parseSDPatternOperatorProperties(R);
  IsStrictFP = R->getValueAsBit("IsStrictFP");

  std::optional<int64_t> MaybeTSFlags =
      R->getValueAsBitsInit("TSFlags")->convertInitializerToInt();
  if (!MaybeTSFlags)
    PrintFatalError(R->getLoc(), "Invalid TSFlags");
  assert(isUInt<32>(*MaybeTSFlags) && "TSFlags bit width out of sync");
  TSFlags = *MaybeTSFlags;

  // Parse the type constraints.
  for (const Record *R : TypeProfile->getValueAsListOfDefs("Constraints"))
    TypeConstraints.emplace_back(R, CGH);
}

/// 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 EEVT::Other.
MVT SDNodeInfo::getKnownType(unsigned ResNo) const {
  unsigned NumResults = getNumResults();
  assert(NumResults <= 1 &&
         "We only work with nodes with zero or one result so far!");
  assert(ResNo == 0 && "Only handles single result nodes so far");

  for (const SDTypeConstraint &Constraint : TypeConstraints) {
    // Make sure that this applies to the correct node result.
    if (Constraint.OperandNo >= NumResults) // FIXME: need value #
      continue;

    switch (Constraint.ConstraintType) {
    default:
      break;
    case SDTypeConstraint::SDTCisVT:
      if (Constraint.VVT.isSimple())
        return Constraint.VVT.getSimple().SimpleTy;
      break;
    case SDTypeConstraint::SDTCisPtrTy:
      return MVT::iPTR;
    }
  }
  return MVT::Other;
}

//===----------------------------------------------------------------------===//
// TreePatternNode implementation
//

static unsigned GetNumNodeResults(const Record *Operator,
                                  CodeGenDAGPatterns &CDP) {
  if (Operator->getName() == "set")
    return 0; // All return nothing.

  if (Operator->isSubClassOf("Intrinsic"))
    return CDP.getIntrinsic(Operator).IS.RetTys.size();

  if (Operator->isSubClassOf("SDNode"))
    return CDP.getSDNodeInfo(Operator).getNumResults();

  if (Operator->isSubClassOf("PatFrags")) {
    // If we've already parsed this pattern fragment, get it.  Otherwise, handle
    // the forward reference case where one pattern fragment references another
    // before it is processed.
    if (TreePattern *PFRec = CDP.getPatternFragmentIfRead(Operator)) {
      // The number of results of a fragment with alternative records is the
      // maximum number of results across all alternatives.
      unsigned NumResults = 0;
      for (const auto &T : PFRec->getTrees())
        NumResults = std::max(NumResults, T->getNumTypes());
      return NumResults;
    }

    const ListInit *LI = Operator->getValueAsListInit("Fragments");
    assert(LI && "Invalid Fragment");
    unsigned NumResults = 0;
    for (const Init *I : LI->getElements()) {
      const Record *Op = nullptr;
      if (const DagInit *Dag = dyn_cast<DagInit>(I))
        if (const DefInit *DI = dyn_cast<DefInit>(Dag->getOperator()))
          Op = DI->getDef();
      assert(Op && "Invalid Fragment");
      NumResults = std::max(NumResults, GetNumNodeResults(Op, CDP));
    }
    return NumResults;
  }

  if (Operator->isSubClassOf("Instruction")) {
    const CodeGenInstruction &InstInfo =
        CDP.getTargetInfo().getInstruction(Operator);

    unsigned NumDefsToAdd = InstInfo.Operands.NumDefs;

    // Subtract any defaulted outputs.
    for (unsigned i = 0; i != InstInfo.Operands.NumDefs; ++i) {
      const Record *OperandNode = InstInfo.Operands[i].Rec;

      if (OperandNode->isSubClassOf("OperandWithDefaultOps") &&
          !CDP.getDefaultOperand(OperandNode).DefaultOps.empty())
        --NumDefsToAdd;
    }

    // Add on one implicit def if it has a resolvable type.
    if (InstInfo.HasOneImplicitDefWithKnownVT(CDP.getTargetInfo()) !=
        MVT::Other)
      ++NumDefsToAdd;
    return NumDefsToAdd;
  }

  if (Operator->isSubClassOf("SDNodeXForm"))
    return 1; // FIXME: Generalize SDNodeXForm

  if (Operator->isSubClassOf("ValueType"))
    return 1; // A type-cast of one result.

  if (Operator->isSubClassOf("ComplexPattern"))
    return 1;

  errs() << *Operator;
  PrintFatalError("Unhandled node in GetNumNodeResults");
}

void TreePatternNode::print(raw_ostream &OS) const {
  if (isLeaf())
    OS << *getLeafValue();
  else
    OS << '(' << getOperator()->getName();

  for (unsigned i = 0, e = Types.size(); i != e; ++i) {
    OS << ':';
    getExtType(i).writeToStream(OS);
  }

  if (!isLeaf()) {
    if (getNumChildren() != 0) {
      OS << " ";
      ListSeparator LS;
      for (const TreePatternNode &Child : children()) {
        OS << LS;
        Child.print(OS);
      }
    }
    OS << ")";
  }

  for (const TreePredicateCall &Pred : PredicateCalls) {
    OS << "<<P:";
    if (Pred.Scope)
      OS << Pred.Scope << ":";
    OS << Pred.Fn.getFnName() << ">>";
  }
  if (TransformFn)
    OS << "<<X:" << TransformFn->getName() << ">>";
  if (!getName().empty())
    OS << ":$" << getName();

  for (const ScopedName &Name : NamesAsPredicateArg)
    OS << ":$pred:" << Name.getScope() << ":" << Name.getIdentifier();
}
void TreePatternNode::dump() const { print(errs()); }

/// isIsomorphicTo - Return true if this node is recursively
/// isomorphic to the specified node.  For this comparison, the node's
/// entire state is considered. The assigned name is ignored, since
/// nodes with differing names are considered isomorphic. However, if
/// the assigned name is present in the dependent variable set, then
/// the assigned name is considered significant and the node is
/// isomorphic if the names match.
bool TreePatternNode::isIsomorphicTo(const TreePatternNode &N,
                                     const MultipleUseVarSet &DepVars) const {
  if (&N == this)
    return true;
  if (N.isLeaf() != isLeaf())
    return false;

  // Check operator of non-leaves early since it can be cheaper than checking
  // types.
  if (!isLeaf())
    if (N.getOperator() != getOperator() ||
        N.getNumChildren() != getNumChildren())
      return false;

  if (getExtTypes() != N.getExtTypes() ||
      getPredicateCalls() != N.getPredicateCalls() ||
      getTransformFn() != N.getTransformFn())
    return false;

  if (isLeaf()) {
    if (const DefInit *DI = dyn_cast<DefInit>(getLeafValue())) {
      if (const DefInit *NDI = dyn_cast<DefInit>(N.getLeafValue())) {
        return ((DI->getDef() == NDI->getDef()) &&
                (!DepVars.contains(getName()) || getName() == N.getName()));
      }
    }
    return getLeafValue() == N.getLeafValue();
  }

  for (unsigned i = 0, e = getNumChildren(); i != e; ++i)
    if (!getChild(i).isIsomorphicTo(N.getChild(i), DepVars))
      return false;
  return true;
}

/// clone - Make a copy of this tree and all of its children.
///
TreePatternNodePtr TreePatternNode::clone() const {
  TreePatternNodePtr New;
  if (isLeaf()) {
    New = makeIntrusiveRefCnt<TreePatternNode>(getLeafValue(), getNumTypes());
  } else {
    std::vector<TreePatternNodePtr> CChildren;
    CChildren.reserve(Children.size());
    for (const TreePatternNode &Child : children())
      CChildren.push_back(Child.clone());
    New = makeIntrusiveRefCnt<TreePatternNode>(
        getOperator(), std::move(CChildren), getNumTypes());
  }
  New->setName(getName());
  New->setNamesAsPredicateArg(getNamesAsPredicateArg());
  New->Types = Types;
  New->setPredicateCalls(getPredicateCalls());
  New->setGISelFlagsRecord(getGISelFlagsRecord());
  New->setTransformFn(getTransformFn());
  return New;
}

/// RemoveAllTypes - Recursively strip all the types of this tree.
void TreePatternNode::RemoveAllTypes() {
  // Reset to unknown type.
  llvm::fill(Types, TypeSetByHwMode());
  if (isLeaf())
    return;
  for (TreePatternNode &Child : children())
    Child.RemoveAllTypes();
}

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

  for (unsigned i = 0, e = getNumChildren(); i != e; ++i) {
    TreePatternNode &Child = getChild(i);
    if (Child.isLeaf()) {
      const Init *Val = Child.getLeafValue();
      // Note that, when substituting into an output pattern, Val might be an
      // UnsetInit.
      if (isa<UnsetInit>(Val) ||
          (isa<DefInit>(Val) &&
           cast<DefInit>(Val)->getDef()->getName() == "node")) {
        // We found a use of a formal argument, replace it with its value.
        TreePatternNodePtr NewChild = ArgMap[Child.getName()];
        assert(NewChild && "Couldn't find formal argument!");
        assert((Child.getPredicateCalls().empty() ||
                NewChild->getPredicateCalls() == Child.getPredicateCalls()) &&
               "Non-empty child predicate clobbered!");
        setChild(i, std::move(NewChild));
      }
    } else {
      getChild(i).SubstituteFormalArguments(ArgMap);
    }
  }
}

/// InlinePatternFragments - If this 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 TreePatternNode::InlinePatternFragments(
    TreePattern &TP, std::vector<TreePatternNodePtr> &OutAlternatives) {

  if (TP.hasError())
    return;

  if (isLeaf()) {
    OutAlternatives.push_back(this); // nothing to do.
    return;
  }

  const Record *Op = getOperator();

  if (!Op->isSubClassOf("PatFrags")) {
    if (getNumChildren() == 0) {
      OutAlternatives.push_back(this);
      return;
    }

    // Recursively inline children nodes.
    std::vector<std::vector<TreePatternNodePtr>> ChildAlternatives(
        getNumChildren());
    for (unsigned i = 0, e = getNumChildren(); i != e; ++i) {
      TreePatternNodePtr Child = getChildShared(i);
      Child->InlinePatternFragments(TP, ChildAlternatives[i]);
      // If there are no alternatives for any child, there are no
      // alternatives for this expression as whole.
      if (ChildAlternatives[i].empty())
        return;

      assert((Child->getPredicateCalls().empty() ||
              llvm::all_of(ChildAlternatives[i],
                           [&](const TreePatternNodePtr &NewChild) {
                             return NewChild->getPredicateCalls() ==
                                    Child->getPredicateCalls();
                           })) &&
             "Non-empty child predicate clobbered!");
    }

    // The end result is an all-pairs construction of the resultant pattern.
    std::vector<unsigned> Idxs(ChildAlternatives.size());
    bool NotDone;
    do {
      // Create the variant and add it to the output list.
      std::vector<TreePatternNodePtr> NewChildren;
      NewChildren.reserve(ChildAlternatives.size());
      for (unsigned i = 0, e = ChildAlternatives.size(); i != e; ++i)
        NewChildren.push_back(ChildAlternatives[i][Idxs[i]]);
      TreePatternNodePtr R = makeIntrusiveRefCnt<TreePatternNode>(
          getOperator(), std::move(NewChildren), getNumTypes());

      // Copy over properties.
      R->setName(getName());
      R->setNamesAsPredicateArg(getNamesAsPredicateArg());
      R->setPredicateCalls(getPredicateCalls());
      R->setGISelFlagsRecord(getGISelFlagsRecord());
      R->setTransformFn(getTransformFn());
      for (unsigned i = 0, e = getNumTypes(); i != e; ++i)
        R->setType(i, getExtType(i));
      for (unsigned i = 0, e = getNumResults(); i != e; ++i)
        R->setResultIndex(i, getResultIndex(i));

      // Register alternative.
      OutAlternatives.push_back(R);

      // Increment indices to the next permutation by incrementing the
      // indices from last index backward, e.g., generate the sequence
      // [0, 0], [0, 1], [1, 0], [1, 1].
      int IdxsIdx;
      for (IdxsIdx = Idxs.size() - 1; IdxsIdx >= 0; --IdxsIdx) {
        if (++Idxs[IdxsIdx] == ChildAlternatives[IdxsIdx].size())
          Idxs[IdxsIdx] = 0;
        else
          break;
      }
      NotDone = (IdxsIdx >= 0);
    } while (NotDone);

    return;
  }

  // Otherwise, we found a reference to a fragment.  First, look up its
  // TreePattern record.
  TreePattern *Frag = TP.getDAGPatterns().getPatternFragment(Op);

  // Verify that we are passing the right number of operands.
  if (Frag->getNumArgs() != getNumChildren()) {
    TP.error("'" + Op->getName() + "' fragment requires " +
             Twine(Frag->getNumArgs()) + " operands!");
    return;
  }

  TreePredicateFn PredFn(Frag);
  unsigned Scope = 0;
  if (TreePredicateFn(Frag).usesOperands())
    Scope = TP.getDAGPatterns().allocateScope();

  // Compute the map of formal to actual arguments.
  std::map<StringRef, TreePatternNodePtr> ArgMap;
  for (unsigned i = 0, e = Frag->getNumArgs(); i != e; ++i) {
    TreePatternNodePtr Child = getChildShared(i);
    if (Scope != 0) {
      Child = Child->clone();
      Child->addNameAsPredicateArg(ScopedName(Scope, Frag->getArgName(i)));
    }
    ArgMap[Frag->getArgName(i)] = Child;
  }

  // Loop over all fragment alternatives.
  for (const auto &Alternative : Frag->getTrees()) {
    TreePatternNodePtr FragTree = Alternative->clone();

    if (!PredFn.isAlwaysTrue())
      FragTree->addPredicateCall(PredFn, Scope);

    // Resolve formal arguments to their actual value.
    if (Frag->getNumArgs())
      FragTree->SubstituteFormalArguments(ArgMap);

    // Transfer types.  Note that the resolved alternative may have fewer
    // (but not more) results than the PatFrags node.
    FragTree->setName(getName());
    for (unsigned i = 0, e = FragTree->getNumTypes(); i != e; ++i)
      FragTree->UpdateNodeType(i, getExtType(i), TP);

    if (Op->isSubClassOf("GISelFlags"))
      FragTree->setGISelFlagsRecord(Op);

    // Transfer in the old predicates.
    for (const TreePredicateCall &Pred : getPredicateCalls())
      FragTree->addPredicateCall(Pred);

    // The fragment we inlined could have recursive inlining that is needed. See
    // if there are any pattern fragments in it and inline them as needed.
    FragTree->InlinePatternFragments(TP, OutAlternatives);
  }
}

/// getImplicitType - Check to see if the specified record has an implicit
/// type which should be applied to it.  This will infer the type of register
/// references from the register file information, for example.
///
/// When Unnamed is set, return the type of a DAG operand with no name, such as
/// the F8RC register class argument in:
///
///   (COPY_TO_REGCLASS GPR:$src, F8RC)
///
/// When Unnamed is false, return the type of a named DAG operand such as the
/// GPR:$src operand above.
///
static TypeSetByHwMode getImplicitType(const Record *R, unsigned ResNo,
                                       bool NotRegisters, bool Unnamed,
                                       TreePattern &TP) {
  CodeGenDAGPatterns &CDP = TP.getDAGPatterns();

  // Check to see if this is a register operand.
  if (R->isSubClassOf("RegisterOperand")) {
    assert(ResNo == 0 && "Regoperand ref only has one result!");
    if (NotRegisters)
      return TypeSetByHwMode(); // Unknown.
    const Record *RegClass = R->getValueAsDef("RegClass");
    const CodeGenTarget &T = TP.getDAGPatterns().getTargetInfo();

    if (RegClass->isSubClassOf("RegClassByHwMode"))
      return getTypeForRegClassByHwMode(T, RegClass, TP.getRecord()->getLoc());

    return TypeSetByHwMode(T.getRegisterClass(RegClass).getValueTypes());
  }

  // Check to see if this is a register or a register class.
  if (R->isSubClassOf("RegisterClass")) {
    assert(ResNo == 0 && "Regclass ref only has one result!");
    // An unnamed register class represents itself as an i32 immediate, for
    // example on a COPY_TO_REGCLASS instruction.
    if (Unnamed)
      return TypeSetByHwMode(MVT::i32);

    // In a named operand, the register class provides the possible set of
    // types.
    if (NotRegisters)
      return TypeSetByHwMode(); // Unknown.
    const CodeGenTarget &T = TP.getDAGPatterns().getTargetInfo();
    return TypeSetByHwMode(T.getRegisterClass(R).getValueTypes());
  }

  if (R->isSubClassOf("RegClassByHwMode")) {
    const CodeGenTarget &T = CDP.getTargetInfo();
    return getTypeForRegClassByHwMode(T, R, TP.getRecord()->getLoc());
  }

  if (R->isSubClassOf("PatFrags")) {
    assert(ResNo == 0 && "FIXME: PatFrag with multiple results?");
    // Pattern fragment types will be resolved when they are inlined.
    return TypeSetByHwMode(); // Unknown.
  }

  if (R->isSubClassOf("Register")) {
    assert(ResNo == 0 && "Registers only produce one result!");
    if (NotRegisters)
      return TypeSetByHwMode(); // Unknown.
    const CodeGenTarget &T = TP.getDAGPatterns().getTargetInfo();
    return TypeSetByHwMode(T.getRegisterVTs(R));
  }

  if (R->isSubClassOf("SubRegIndex")) {
    assert(ResNo == 0 && "SubRegisterIndices only produce one result!");
    return TypeSetByHwMode(MVT::i32);
  }

  if (R->isSubClassOf("ValueType")) {
    assert(ResNo == 0 && "This node only has one result!");
    // An unnamed VTSDNode represents itself as an MVT::Other immediate.
    //
    //   (sext_inreg GPR:$src, i16)
    //                         ~~~
    if (Unnamed)
      return TypeSetByHwMode(MVT::Other);
    // With a name, the ValueType simply provides the type of the named
    // variable.
    //
    //   (sext_inreg i32:$src, i16)
    //               ~~~~~~~~
    if (NotRegisters)
      return TypeSetByHwMode(); // Unknown.
    const CodeGenHwModes &CGH = CDP.getTargetInfo().getHwModes();
    return TypeSetByHwMode(getValueTypeByHwMode(R, CGH));
  }

  if (R->isSubClassOf("CondCode")) {
    assert(ResNo == 0 && "This node only has one result!");
    // Using a CondCodeSDNode.
    return TypeSetByHwMode(MVT::Other);
  }

  if (R->isSubClassOf("ComplexPattern")) {
    assert(ResNo == 0 && "FIXME: ComplexPattern with multiple results?");
    if (NotRegisters)
      return TypeSetByHwMode(); // Unknown.
    const Record *T = CDP.getComplexPattern(R).getValueType();
    const CodeGenHwModes &CGH = CDP.getTargetInfo().getHwModes();
    return TypeSetByHwMode(getValueTypeByHwMode(T, CGH));
  }

  if (R->getName() == "node" || R->getName() == "srcvalue" ||
      R->getName() == "zero_reg" || R->getName() == "immAllOnesV" ||
      R->getName() == "immAllZerosV" || R->getName() == "undef_tied_input") {
    // Placeholder.
    return TypeSetByHwMode(); // Unknown.
  }

  if (R->isSubClassOf("Operand")) {
    const CodeGenHwModes &CGH = CDP.getTargetInfo().getHwModes();
    const Record *T = R->getValueAsDef("Type");
    return TypeSetByHwMode(getValueTypeByHwMode(T, CGH));
  }

  TP.error("Unknown node flavor used in pattern: " + R->getName());
  return TypeSetByHwMode(MVT::Other);
}

/// getIntrinsicInfo - If this node corresponds to an intrinsic, return the
/// CodeGenIntrinsic information for it, otherwise return a null pointer.
const CodeGenIntrinsic *
TreePatternNode::getIntrinsicInfo(const CodeGenDAGPatterns &CDP) const {
  if (getOperator() != CDP.get_intrinsic_void_sdnode() &&
      getOperator() != CDP.get_intrinsic_w_chain_sdnode() &&
      getOperator() != CDP.get_intrinsic_wo_chain_sdnode())
    return nullptr;

  unsigned IID = cast<IntInit>(getChild(0).getLeafValue())->getValue();
  return &CDP.getIntrinsicInfo(IID);
}

/// getComplexPatternInfo - If this node corresponds to a ComplexPattern,
/// return the ComplexPattern information, otherwise return null.
const ComplexPattern *
TreePatternNode::getComplexPatternInfo(const CodeGenDAGPatterns &CGP) const {
  const Record *Rec;
  if (isLeaf()) {
    const DefInit *DI = dyn_cast<DefInit>(getLeafValue());
    if (!DI)
      return nullptr;
    Rec = DI->getDef();
  } else {
    Rec = getOperator();
  }

  if (!Rec->isSubClassOf("ComplexPattern"))
    return nullptr;
  return &CGP.getComplexPattern(Rec);
}

unsigned TreePatternNode::getNumMIResults(const CodeGenDAGPatterns &CGP) const {
  // A ComplexPattern specifically declares how many results it fills in.
  if (const ComplexPattern *CP = getComplexPatternInfo(CGP))
    return CP->getNumOperands();

  // If MIOperandInfo is specified, that gives the count.
  if (isLeaf()) {
    const DefInit *DI = dyn_cast<DefInit>(getLeafValue());
    if (DI && DI->getDef()->isSubClassOf("Operand")) {
      const DagInit *MIOps = DI->getDef()->getValueAsDag("MIOperandInfo");
      if (MIOps->getNumArgs())
        return MIOps->getNumArgs();
    }
  }

  // Otherwise there is just one result.
  return 1;
}

/// NodeHasProperty - Return true if this node has the specified property.
bool TreePatternNode::NodeHasProperty(SDNP Property,
                                      const CodeGenDAGPatterns &CGP) const {
  if (isLeaf()) {
    if (const ComplexPattern *CP = getComplexPatternInfo(CGP))
      return CP->hasProperty(Property);

    return false;
  }

  if (Property != SDNPHasChain) {
    // The chain proprety is already present on the different intrinsic node
    // types (intrinsic_w_chain, intrinsic_void), and is not explicitly listed
    // on the intrinsic. Anything else is specific to the individual intrinsic.
    if (const CodeGenIntrinsic *Int = getIntrinsicInfo(CGP))
      return Int->hasProperty(Property);
  }

  if (!getOperator()->isSubClassOf("SDPatternOperator"))
    return false;

  return CGP.getSDNodeInfo(getOperator()).hasProperty(Property);
}

/// TreeHasProperty - Return true if any node in this tree has the specified
/// property.
bool TreePatternNode::TreeHasProperty(SDNP Property,
                                      const CodeGenDAGPatterns &CGP) const {
  if (NodeHasProperty(Property, CGP))
    return true;
  for (const TreePatternNode &Child : children())
    if (Child.TreeHasProperty(Property, CGP))
      return true;
  return false;
}

/// isCommutativeIntrinsic - Return true if the node corresponds to a
/// commutative intrinsic.
bool TreePatternNode::isCommutativeIntrinsic(
    const CodeGenDAGPatterns &CDP) const {
  if (const CodeGenIntrinsic *Int = getIntrinsicInfo(CDP))
    return Int->isCommutative;
  return false;
}

static bool isOperandClass(const TreePatternNode &N, StringRef Class) {
  if (!N.isLeaf())
    return N.getOperator()->isSubClassOf(Class);

  const DefInit *DI = dyn_cast<DefInit>(N.getLeafValue());
  if (DI && DI->getDef()->isSubClassOf(Class))
    return true;

  return false;
}

static void emitTooManyOperandsError(TreePattern &TP, StringRef InstName,
                                     unsigned Expected, unsigned Actual) {
  TP.error("Instruction '" + InstName + "' was provided " + Twine(Actual) +
           " operands but expected only " + Twine(Expected) + "!");
}

static void emitTooFewOperandsError(TreePattern &TP, StringRef InstName,
                                    unsigned Actual) {
  TP.error("Instruction '" + InstName + "' expects more than the provided " +
           Twine(Actual) + " operands!");
}

/// 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 TreePatternNode::ApplyTypeConstraints(TreePattern &TP, bool NotRegisters) {
  if (TP.hasError())
    return false;

  CodeGenDAGPatterns &CDP = TP.getDAGPatterns();
  if (isLeaf()) {
    if (const DefInit *DI = dyn_cast<DefInit>(getLeafValue())) {
      // If it's a regclass or something else known, include the type.
      bool MadeChange = false;
      for (unsigned i = 0, e = Types.size(); i != e; ++i)
        MadeChange |= UpdateNodeType(
            i, getImplicitType(DI->getDef(), i, NotRegisters, !hasName(), TP),
            TP);
      return MadeChange;
    }

    if (const IntInit *II = dyn_cast<IntInit>(getLeafValue())) {
      assert(Types.size() == 1 && "Invalid IntInit");

      // Int inits are always integers. :)
      bool MadeChange = TP.getInfer().EnforceInteger(Types[0]);

      if (!TP.getInfer().isConcrete(Types[0], false))
        return MadeChange;

      ValueTypeByHwMode VVT = TP.getInfer().getConcrete(Types[0], false);
      for (auto &P : VVT) {
        MVT VT = P.second;
        // Can only check for types of a known size
        if (VT == MVT::iPTR)
          continue;

        // Check that the value doesn't use more bits than we have. It must
        // either be a sign- or zero-extended equivalent of the original.
        unsigned Width = VT.getFixedSizeInBits();
        int64_t Val = II->getValue();
        if (!isIntN(Width, Val) && !isUIntN(Width, Val)) {
          TP.error("Integer value '" + Twine(Val) +
                   "' is out of range for type '" + getEnumName(VT) + "'!");
          break;
        }
      }
      return MadeChange;
    }

    return false;
  }

  if (const CodeGenIntrinsic *Int = getIntrinsicInfo(CDP)) {
    bool MadeChange = false;

    // Apply the result type to the node.
    unsigned NumRetVTs = Int->IS.RetTys.size();
    unsigned NumParamVTs = Int->IS.ParamTys.size();

    for (unsigned i = 0, e = NumRetVTs; i != e; ++i)
      MadeChange |= UpdateNodeType(
          i, getValueType(Int->IS.RetTys[i]->getValueAsDef("VT")), TP);

    if (getNumChildren() != NumParamVTs + 1) {
      TP.error("Intrinsic '" + Int->Name + "' expects " + Twine(NumParamVTs) +
               " operands, not " + Twine(getNumChildren() - 1) + " operands!");
      return false;
    }

    // Apply type info to the intrinsic ID.
    MadeChange |= getChild(0).UpdateNodeType(0, MVT::iPTR, TP);

    for (unsigned i = 0, e = getNumChildren() - 1; i != e; ++i) {
      MadeChange |= getChild(i + 1).ApplyTypeConstraints(TP, NotRegisters);

      MVT OpVT = getValueType(Int->IS.ParamTys[i]->getValueAsDef("VT"));
      assert(getChild(i + 1).getNumTypes() == 1 && "Unhandled case");
      MadeChange |= getChild(i + 1).UpdateNodeType(0, OpVT, TP);
    }
    return MadeChange;
  }

  if (getOperator()->isSubClassOf("SDNode")) {
    const SDNodeInfo &NI = CDP.getSDNodeInfo(getOperator());

    // Check that the number of operands is sane.  Negative operands -> varargs.
    if (NI.getNumOperands() >= 0 &&
        getNumChildren() != (unsigned)NI.getNumOperands()) {
      TP.error(getOperator()->getName() + " node requires exactly " +
               Twine(NI.getNumOperands()) + " operands!");
      return false;
    }

    bool MadeChange = false;
    for (TreePatternNode &Child : children())
      MadeChange |= Child.ApplyTypeConstraints(TP, NotRegisters);
    MadeChange |= NI.ApplyTypeConstraints(*this, TP);
    return MadeChange;
  }

  if (getOperator()->isSubClassOf("Instruction")) {
    const DAGInstruction &Inst = CDP.getInstruction(getOperator());
    const CodeGenInstruction &InstInfo =
        CDP.getTargetInfo().getInstruction(getOperator());

    bool MadeChange = false;

    // Apply the result types to the node, these come from the things in the
    // (outs) list of the instruction.
    unsigned NumResultsToAdd =
        std::min(InstInfo.Operands.NumDefs, Inst.getNumResults());
    for (unsigned ResNo = 0; ResNo != NumResultsToAdd; ++ResNo)
      MadeChange |= UpdateNodeTypeFromInst(ResNo, Inst.getResult(ResNo), TP);

    // If the instruction has implicit defs, we apply the first one as a result.
    // FIXME: This sucks, it should apply all implicit defs.
    if (!InstInfo.ImplicitDefs.empty()) {
      unsigned ResNo = NumResultsToAdd;

      // FIXME: Generalize to multiple possible types and multiple possible
      // ImplicitDefs.
      MVT VT = InstInfo.HasOneImplicitDefWithKnownVT(CDP.getTargetInfo());

      if (VT != MVT::Other)
        MadeChange |= UpdateNodeType(ResNo, VT, TP);
    }

    // If this is an INSERT_SUBREG, constrain the source and destination VTs to
    // be the same.
    if (getOperator()->getName() == "INSERT_SUBREG") {
      assert(getChild(0).getNumTypes() == 1 && "FIXME: Unhandled");
      MadeChange |= UpdateNodeType(0, getChild(0).getExtType(0), TP);
      MadeChange |= getChild(0).UpdateNodeType(0, getExtType(0), TP);
    } else if (getOperator()->getName() == "REG_SEQUENCE") {
      // We need to do extra, custom typechecking for REG_SEQUENCE since it is
      // variadic.

      unsigned NChild = getNumChildren();
      if (NChild < 3) {
        TP.error("REG_SEQUENCE requires at least 3 operands!");
        return false;
      }

      if (NChild % 2 == 0) {
        TP.error("REG_SEQUENCE requires an odd number of operands!");
        return false;
      }

      if (!isOperandClass(getChild(0), "RegisterClass")) {
        TP.error("REG_SEQUENCE requires a RegisterClass for first operand!");
        return false;
      }

      for (unsigned I = 1; I < NChild; I += 2) {
        TreePatternNode &SubIdxChild = getChild(I + 1);
        if (!isOperandClass(SubIdxChild, "SubRegIndex")) {
          TP.error("REG_SEQUENCE requires a SubRegIndex for operand " +
                   Twine(I + 1) + "!");
          return false;
        }
      }
    }

    unsigned NumResults = Inst.getNumResults();
    unsigned NumFixedOperands = InstInfo.Operands.size();

    // If one or more operands with a default value appear at the end of the
    // formal operand list for an instruction, we allow them to be overridden
    // by optional operands provided in the pattern.
    //
    // But if an operand B without a default appears at any point after an
    // operand A with a default, then we don't allow A to be overridden,
    // because there would be no way to specify whether the next operand in
    // the pattern was intended to override A or skip it.
    unsigned NonOverridableOperands = NumFixedOperands;
    while (NonOverridableOperands > NumResults &&
           CDP.operandHasDefault(
               InstInfo.Operands[NonOverridableOperands - 1].Rec))
      --NonOverridableOperands;

    unsigned ChildNo = 0;
    assert(NumResults <= NumFixedOperands);
    for (unsigned i = NumResults, e = NumFixedOperands; i != e; ++i) {
      const Record *OperandNode = InstInfo.Operands[i].Rec;

      // If the operand has a default value, do we use it? We must use the
      // default if we've run out of children of the pattern DAG to consume,
      // or if the operand is followed by a non-defaulted one.
      if (CDP.operandHasDefault(OperandNode) &&
          (i < NonOverridableOperands || ChildNo >= getNumChildren()))
        continue;

      // If we have run out of child nodes and there _isn't_ a default
      // value we can use for the next operand, give an error.
      if (ChildNo >= getNumChildren()) {
        emitTooFewOperandsError(TP, getOperator()->getName(), getNumChildren());
        return false;
      }

      TreePatternNode *Child = &getChild(ChildNo++);
      unsigned ChildResNo = 0; // Instructions always use res #0 of their op.

      // If the operand has sub-operands, they may be provided by distinct
      // child patterns, so attempt to match each sub-operand separately.
      if (OperandNode->isSubClassOf("Operand")) {
        const DagInit *MIOpInfo = OperandNode->getValueAsDag("MIOperandInfo");
        if (unsigned NumArgs = MIOpInfo->getNumArgs()) {
          // But don't do that if the whole operand is being provided by
          // a single ComplexPattern-related Operand.

          if (Child->getNumMIResults(CDP) < NumArgs) {
            // Match first sub-operand against the child we already have.
            const Record *SubRec = cast<DefInit>(MIOpInfo->getArg(0))->getDef();
            MadeChange |= Child->UpdateNodeTypeFromInst(ChildResNo, SubRec, TP);

            // And the remaining sub-operands against subsequent children.
            for (unsigned Arg = 1; Arg < NumArgs; ++Arg) {
              if (ChildNo >= getNumChildren()) {
                emitTooFewOperandsError(TP, getOperator()->getName(),
                                        getNumChildren());
                return false;
              }
              Child = &getChild(ChildNo++);

              SubRec = cast<DefInit>(MIOpInfo->getArg(Arg))->getDef();
              MadeChange |=
                  Child->UpdateNodeTypeFromInst(ChildResNo, SubRec, TP);
            }
            continue;
          }
        }
      }

      // If we didn't match by pieces above, attempt to match the whole
      // operand now.
      MadeChange |= Child->UpdateNodeTypeFromInst(ChildResNo, OperandNode, TP);
    }

    if (!InstInfo.Operands.isVariadic && ChildNo != getNumChildren()) {
      emitTooManyOperandsError(TP, getOperator()->getName(), ChildNo,
                               getNumChildren());
      return false;
    }

    for (TreePatternNode &Child : children())
      MadeChange |= Child.ApplyTypeConstraints(TP, NotRegisters);
    return MadeChange;
  }

  if (getOperator()->isSubClassOf("ComplexPattern")) {
    bool MadeChange = false;

    if (!NotRegisters) {
      assert(Types.size() == 1 && "ComplexPatterns only produce one result!");
      const Record *T = CDP.getComplexPattern(getOperator()).getValueType();
      const CodeGenHwModes &CGH = CDP.getTargetInfo().getHwModes();
      const ValueTypeByHwMode VVT = getValueTypeByHwMode(T, CGH);
      // TODO: AArch64 and AMDGPU use ComplexPattern<untyped, ...> and then
      // exclusively use those as non-leaf nodes with explicit type casts, so
      // for backwards compatibility we do no inference in that case. This is
      // not supported when the ComplexPattern is used as a leaf value,
      // however; this inconsistency should be resolved, either by adding this
      // case there or by altering the backends to not do this (e.g. using Any
      // instead may work).
      if (!VVT.isSimple() || VVT.getSimple() != MVT::Untyped)
        MadeChange |= UpdateNodeType(0, VVT, TP);
    }

    for (TreePatternNode &Child : children())
      MadeChange |= Child.ApplyTypeConstraints(TP, NotRegisters);

    return MadeChange;
  }

  if (!getOperator()->isSubClassOf("SDNodeXForm")) {
    TP.error("unknown node type '" + getOperator()->getName() +
             "' in input pattern");
    return false;
  }

  // Node transforms always take one operand.
  if (getNumChildren() != 1) {
    TP.error("Node transform '" + getOperator()->getName() +
             "' requires one operand!");
    return false;
  }

  bool MadeChange = getChild(0).ApplyTypeConstraints(TP, NotRegisters);
  return MadeChange;
}

/// OnlyOnRHSOfCommutative - Return true if this value is only allowed on the
/// RHS of a commutative operation, not the on LHS.
static bool OnlyOnRHSOfCommutative(const TreePatternNode &N) {
  if (!N.isLeaf() && N.getOperator()->getName() == "imm")
    return true;
  if (N.isLeaf() && isa<IntInit>(N.getLeafValue()))
    return true;
  if (isImmAllOnesAllZerosMatch(N))
    return true;
  return false;
}

/// canPatternMatch - If it is impossible for this pattern to match on this
/// target, fill in Reason and return false.  Otherwise, return true.  This is
/// used as a sanity check for .td files (to prevent people from writing stuff
/// that can never possibly work), and to prevent the pattern permuter from
/// generating stuff that is useless.
bool TreePatternNode::canPatternMatch(std::string &Reason,
                                      const CodeGenDAGPatterns &CDP) const {
  if (isLeaf())
    return true;

  for (const TreePatternNode &Child : children())
    if (!Child.canPatternMatch(Reason, CDP))
      return false;

  // If this is an intrinsic, handle cases that would make it not match.  For
  // example, if an operand is required to be an immediate.
  if (getOperator()->isSubClassOf("Intrinsic")) {
    // TODO:
    return true;
  }

  if (getOperator()->isSubClassOf("ComplexPattern"))
    return true;

  // If this node is a commutative operator, check that the LHS isn't an
  // immediate.
  const SDNodeInfo &NodeInfo = CDP.getSDNodeInfo(getOperator());
  bool isCommIntrinsic = isCommutativeIntrinsic(CDP);
  if (NodeInfo.hasProperty(SDNPCommutative) || isCommIntrinsic) {
    // Scan all of the operands of the node and make sure that only the last one
    // is a constant node, unless the RHS also is.
    if (!OnlyOnRHSOfCommutative(getChild(getNumChildren() - 1))) {
      unsigned Skip = isCommIntrinsic ? 1 : 0; // First operand is intrinsic id.
      for (unsigned i = Skip, e = getNumChildren() - 1; i != e; ++i)
        if (OnlyOnRHSOfCommutative(getChild(i))) {
          Reason =
              "Immediate value must be on the RHS of commutative operators!";
          return false;
        }
    }
  }

  return true;
}

//===----------------------------------------------------------------------===//
// TreePattern implementation
//

TreePattern::TreePattern(const Record *TheRec, const ListInit *RawPat,
                         bool isInput, CodeGenDAGPatterns &cdp)
    : TheRecord(TheRec), CDP(cdp), isInputPattern(isInput), HasError(false),
      Infer(*this) {
  for (const Init *I : RawPat->getElements())
    Trees.push_back(ParseTreePattern(I, ""));
}

TreePattern::TreePattern(const Record *TheRec, const DagInit *Pat, bool isInput,
                         CodeGenDAGPatterns &cdp)
    : TheRecord(TheRec), CDP(cdp), isInputPattern(isInput), HasError(false),
      Infer(*this) {
  Trees.push_back(ParseTreePattern(Pat, ""));
}

TreePattern::TreePattern(const Record *TheRec, ArrayRef<const Init *> Args,
                         ArrayRef<const StringInit *> ArgNames, bool isInput,
                         CodeGenDAGPatterns &cdp)
    : TheRecord(TheRec), CDP(cdp), isInputPattern(isInput), HasError(false),
      Infer(*this) {
  Trees.push_back(ParseRootlessTreePattern(Args, ArgNames));
}

TreePattern::TreePattern(const Record *TheRec, TreePatternNodePtr Pat,
                         bool isInput, CodeGenDAGPatterns &cdp)
    : TheRecord(TheRec), CDP(cdp), isInputPattern(isInput), HasError(false),
      Infer(*this) {
  Trees.push_back(Pat);
}

void TreePattern::error(const Twine &Msg) {
  if (HasError)
    return;
  dump();
  PrintError(TheRecord->getLoc(), "In " + TheRecord->getName() + ": " + Msg);
  HasError = true;
}

void TreePattern::ComputeNamedNodes() {
  for (TreePatternNodePtr &Tree : Trees)
    ComputeNamedNodes(*Tree);
}

void TreePattern::ComputeNamedNodes(TreePatternNode &N) {
  if (!N.getName().empty())
    NamedNodes[N.getName()].push_back(&N);

  for (TreePatternNode &Child : N.children())
    ComputeNamedNodes(Child);
}

TreePatternNodePtr
TreePattern::ParseRootlessTreePattern(ArrayRef<const Init *> Args,
                                      ArrayRef<const StringInit *> ArgNames) {
  std::vector<TreePatternNodePtr> Children;

  for (auto [Arg, ArgName] : llvm::zip_equal(Args, ArgNames)) {
    StringRef NameStr = ArgName ? ArgName->getValue() : "";
    Children.push_back(ParseTreePattern(Arg, NameStr));
  }

  return makeIntrusiveRefCnt<TreePatternNode>(nullptr, std::move(Children), 1);
}

TreePatternNodePtr TreePattern::ParseTreePattern(const Init *TheInit,
                                                 StringRef OpName) {
  RecordKeeper &RK = TheInit->getRecordKeeper();
  // Here, we are creating new records (BitsInit->InitInit), so const_cast
  // TheInit back to non-const pointer.
  if (const DefInit *DI = dyn_cast<DefInit>(TheInit)) {
    const Record *R = DI->getDef();

    // Direct reference to a leaf DagNode or PatFrag?  Turn it into a
    // TreePatternNode of its own.  For example:
    ///   (foo GPR, imm) -> (foo GPR, (imm))
    if (R->isSubClassOf("SDNode") || R->isSubClassOf("PatFrags"))
      return ParseTreePattern(DagInit::get(DI, {}), OpName);

    // Input argument?
    TreePatternNodePtr Res = makeIntrusiveRefCnt<TreePatternNode>(DI, 1);
    if (R->getName() == "node" && !OpName.empty()) {
      if (OpName.empty())
        error("'node' argument requires a name to match with operand list");
      Args.push_back(OpName.str());
    }

    Res->setName(OpName);
    return Res;
  }

  // ?:$name or just $name.
  if (isa<UnsetInit>(TheInit)) {
    if (OpName.empty())
      error("'?' argument requires a name to match with operand list");
    TreePatternNodePtr Res = makeIntrusiveRefCnt<TreePatternNode>(TheInit, 1);
    Args.push_back(OpName.str());
    Res->setName(OpName);
    return Res;
  }

  if (isa<IntInit>(TheInit) || isa<BitInit>(TheInit)) {
    if (!OpName.empty())
      error("Constant int or bit argument should not have a name!");
    if (isa<BitInit>(TheInit))
      TheInit = TheInit->convertInitializerTo(IntRecTy::get(RK));
    return makeIntrusiveRefCnt<TreePatternNode>(TheInit, 1);
  }

  if (const BitsInit *BI = dyn_cast<BitsInit>(TheInit)) {
    // Turn this into an IntInit.
    const Init *II = BI->convertInitializerTo(IntRecTy::get(RK));
    if (!II || !isa<IntInit>(II))
      error("Bits value must be constants!");
    return II ? ParseTreePattern(II, OpName) : nullptr;
  }

  const DagInit *Dag = dyn_cast<DagInit>(TheInit);
  if (!Dag) {
    TheInit->print(errs());
    error("Pattern has unexpected init kind!");
    return nullptr;
  }

  auto ParseCastOperand = [this](const DagInit *Dag, StringRef OpName) {
    if (Dag->getNumArgs() != 1)
      error("Type cast only takes one operand!");

    if (!OpName.empty())
      error("Type cast should not have a name!");

    return ParseTreePattern(Dag->getArg(0), Dag->getArgNameStr(0));
  };

  if (const ListInit *LI = dyn_cast<ListInit>(Dag->getOperator())) {
    // If the operator is a list (of value types), then this must be "type cast"
    // of a leaf node with multiple results.
    TreePatternNodePtr New = ParseCastOperand(Dag, OpName);

    size_t NumTypes = New->getNumTypes();
    if (LI->empty() || LI->size() != NumTypes)
      error("Invalid number of type casts!");

    // Apply the type casts.
    const CodeGenHwModes &CGH = getDAGPatterns().getTargetInfo().getHwModes();
    for (unsigned i = 0; i < std::min(NumTypes, LI->size()); ++i)
      New->UpdateNodeType(
          i, getValueTypeByHwMode(LI->getElementAsRecord(i), CGH), *this);

    return New;
  }

  const DefInit *OpDef = dyn_cast<DefInit>(Dag->getOperator());
  if (!OpDef) {
    error("Pattern has unexpected operator type!");
    return nullptr;
  }
  const Record *Operator = OpDef->getDef();

  if (Operator->isSubClassOf("ValueType")) {
    // If the operator is a ValueType, then this must be "type cast" of a leaf
    // node.
    TreePatternNodePtr New = ParseCastOperand(Dag, OpName);

    if (New->getNumTypes() != 1)
      error("ValueType cast can only have one type!");

    // Apply the type cast.
    const CodeGenHwModes &CGH = getDAGPatterns().getTargetInfo().getHwModes();
    New->UpdateNodeType(0, getValueTypeByHwMode(Operator, CGH), *this);

    return New;
  }

  // Verify that this is something that makes sense for an operator.
  if (!Operator->isSubClassOf("PatFrags") &&
      !Operator->isSubClassOf("SDNode") &&
      !Operator->isSubClassOf("Instruction") &&
      !Operator->isSubClassOf("SDNodeXForm") &&
      !Operator->isSubClassOf("Intrinsic") &&
      !Operator->isSubClassOf("ComplexPattern") && Operator->getName() != "set")
    error("Unrecognized node '" + Operator->getName() + "'!");

  //  Check to see if this is something that is illegal in an input pattern.
  if (isInputPattern) {
    if (Operator->isSubClassOf("Instruction") ||
        Operator->isSubClassOf("SDNodeXForm"))
      error("Cannot use '" + Operator->getName() + "' in an input pattern!");
  } else {
    if (Operator->isSubClassOf("Intrinsic"))
      error("Cannot use '" + Operator->getName() + "' in an output pattern!");

    if (Operator->isSubClassOf("SDNode") && Operator->getName() != "imm" &&
        Operator->getName() != "timm" && Operator->getName() != "fpimm" &&
        Operator->getName() != "tglobaltlsaddr" &&
        Operator->getName() != "tconstpool" &&
        Operator->getName() != "tjumptable" &&
        Operator->getName() != "tframeindex" &&
        Operator->getName() != "texternalsym" &&
        Operator->getName() != "tblockaddress" &&
        Operator->getName() != "tglobaladdr" && Operator->getName() != "bb" &&
        Operator->getName() != "vt" && Operator->getName() != "mcsym")
      error("Cannot use '" + Operator->getName() + "' in an output pattern!");
  }

  std::vector<TreePatternNodePtr> Children;

  // Parse all the operands.
  for (unsigned i = 0, e = Dag->getNumArgs(); i != e; ++i)
    Children.push_back(ParseTreePattern(Dag->getArg(i), Dag->getArgNameStr(i)));

  // Get the actual number of results before Operator is converted to an
  // intrinsic node (which is hard-coded to have either zero or one result).
  unsigned NumResults = GetNumNodeResults(Operator, CDP);

  // If the operator is an intrinsic, then this is just syntactic sugar for
  // (intrinsic_* <number>, ..children..).  Pick the right intrinsic node, and
  // convert the intrinsic name to a number.
  if (Operator->isSubClassOf("Intrinsic")) {
    const CodeGenIntrinsic &Int = getDAGPatterns().getIntrinsic(Operator);
    unsigned IID = getDAGPatterns().getIntrinsicID(Operator) + 1;

    // If this intrinsic returns void, it must have side-effects and thus a
    // chain.
    if (Int.IS.RetTys.empty())
      Operator = getDAGPatterns().get_intrinsic_void_sdnode();
    else if (!Int.ME.doesNotAccessMemory() || Int.hasSideEffects)
      // Has side-effects, requires chain.
      Operator = getDAGPatterns().get_intrinsic_w_chain_sdnode();
    else // Otherwise, no chain.
      Operator = getDAGPatterns().get_intrinsic_wo_chain_sdnode();

    Children.insert(Children.begin(), makeIntrusiveRefCnt<TreePatternNode>(
                                          IntInit::get(RK, IID), 1));
  }

  if (Operator->isSubClassOf("ComplexPattern")) {
    for (unsigned i = 0; i < Children.size(); ++i) {
      TreePatternNodePtr Child = Children[i];

      if (Child->getName().empty())
        error("All arguments to a ComplexPattern must be named");

      // Check that the ComplexPattern uses are consistent: "(MY_PAT $a, $b)"
      // and "(MY_PAT $b, $a)" should not be allowed in the same pattern;
      // neither should "(MY_PAT_1 $a, $b)" and "(MY_PAT_2 $a, $b)".
      auto OperandId = std::pair(Operator, i);
      auto [PrevOp, Inserted] =
          ComplexPatternOperands.try_emplace(Child->getName(), OperandId);
      if (!Inserted && PrevOp->getValue() != OperandId) {
        error("All ComplexPattern operands must appear consistently: "
              "in the same order in just one ComplexPattern instance.");
      }
    }
  }

  TreePatternNodePtr Result = makeIntrusiveRefCnt<TreePatternNode>(
      Operator, std::move(Children), NumResults);
  Result->setName(OpName);

  if (Dag->getName()) {
    assert(Result->getName().empty());
    Result->setName(Dag->getNameStr());
  }
  return Result;
}

/// SimplifyTree - See if we can simplify this tree to eliminate something that
/// will never match in favor of something obvious that will.  This is here
/// strictly as a convenience to target authors because it allows them to write
/// more type generic things and have useless type casts fold away.
///
/// This returns true if any change is made.
static bool SimplifyTree(TreePatternNodePtr &N) {
  if (N->isLeaf())
    return false;

  // If we have a bitconvert with a resolved type and if the source and
  // destination types are the same, then the bitconvert is useless, remove it.
  //
  // We make an exception if the types are completely empty. This can come up
  // when the pattern being simplified is in the Fragments list of a PatFrags,
  // so that the operand is just an untyped "node". In that situation we leave
  // bitconverts unsimplified, and simplify them later once the fragment is
  // expanded into its true context.
  if (N->getOperator()->getName() == "bitconvert" &&
      N->getExtType(0).isValueTypeByHwMode(false) &&
      !N->getExtType(0).empty() &&
      N->getExtType(0) == N->getChild(0).getExtType(0) &&
      N->getName().empty()) {
    if (!N->getPredicateCalls().empty()) {
      std::string Str;
      raw_string_ostream OS(Str);
      OS << *N
         << "\n trivial bitconvert node should not have predicate calls\n";
      PrintFatalError(Str);
      return false;
    }
    N = N->getChildShared(0);
    SimplifyTree(N);
    return true;
  }

  // Walk all children.
  bool MadeChange = false;
  for (unsigned i = 0, e = N->getNumChildren(); i != e; ++i)
    MadeChange |= SimplifyTree(N->getChildSharedPtr(i));

  return MadeChange;
}

/// InferAllTypes - Infer/propagate as many types throughout the expression
/// patterns as possible.  Return true if all types are inferred, false
/// otherwise.  Flags an error if a type contradiction is found.
bool TreePattern::InferAllTypes(
    const StringMap<SmallVector<TreePatternNode *, 1>> *InNamedTypes) {
  if (NamedNodes.empty())
    ComputeNamedNodes();

  bool MadeChange = true;
  while (MadeChange) {
    MadeChange = false;
    for (TreePatternNodePtr &Tree : Trees) {
      MadeChange |= Tree->ApplyTypeConstraints(*this, false);
      MadeChange |= SimplifyTree(Tree);
    }

    // If there are constraints on our named nodes, apply them.
    for (auto &Entry : NamedNodes) {
      SmallVectorImpl<TreePatternNode *> &Nodes = Entry.second;

      // If we have input named node types, propagate their types to the named
      // values here.
      if (InNamedTypes) {
        auto InIter = InNamedTypes->find(Entry.getKey());
        if (InIter == InNamedTypes->end()) {
          error("Node '" + Entry.getKey().str() +
                "' in output pattern but not input pattern");
          return true;
        }

        ArrayRef<TreePatternNode *> InNodes = InIter->second;

        // The input types should be fully resolved by now.
        for (TreePatternNode *Node : Nodes) {
          // If this node is a register class, and it is the root of the pattern
          // then we're mapping something onto an input register.  We allow
          // changing the type of the input register in this case.  This allows
          // us to match things like:
          //  def : Pat<(v1i64 (bitconvert(v2i32 DPR:$src))), (v1i64 DPR:$src)>;
          if (Node == Trees[0].get() && Node->isLeaf()) {
            const DefInit *DI = dyn_cast<DefInit>(Node->getLeafValue());
            if (DI && (DI->getDef()->isSubClassOf("RegisterClass") ||
                       DI->getDef()->isSubClassOf("RegisterOperand")))
              continue;
          }

          assert(Node->getNumTypes() == 1 && InNodes[0]->getNumTypes() == 1 &&
                 "FIXME: cannot name multiple result nodes yet");
          MadeChange |=
              Node->UpdateNodeType(0, InNodes[0]->getExtType(0), *this);
        }
      }

      // If there are multiple nodes with the same name, they must all have the
      // same type.
      if (Entry.second.size() > 1) {
        for (unsigned i = 0, e = Nodes.size() - 1; i != e; ++i) {
          TreePatternNode *N1 = Nodes[i], *N2 = Nodes[i + 1];
          assert(N1->getNumTypes() == 1 && N2->getNumTypes() == 1 &&
                 "FIXME: cannot name multiple result nodes yet");

          MadeChange |= N1->UpdateNodeType(0, N2->getExtType(0), *this);
          MadeChange |= N2->UpdateNodeType(0, N1->getExtType(0), *this);
        }
      }
    }
  }

  bool HasUnresolvedTypes = false;
  for (const TreePatternNodePtr &Tree : Trees)
    HasUnresolvedTypes |= Tree->ContainsUnresolvedType(*this);
  return !HasUnresolvedTypes;
}

void TreePattern::print(raw_ostream &OS) const {
  OS << getRecord()->getName();
  if (!Args.empty())
    OS << '(' << llvm::interleaved(Args) << ')';
  OS << ": ";

  if (Trees.size() > 1)
    OS << "[\n";
  for (const TreePatternNodePtr &Tree : Trees) {
    OS << "\t";
    Tree->print(OS);
    OS << "\n";
  }

  if (Trees.size() > 1)
    OS << "]\n";
}

void TreePattern::dump() const { print(errs()); }

//===----------------------------------------------------------------------===//
// CodeGenDAGPatterns implementation
//

CodeGenDAGPatterns::CodeGenDAGPatterns(const RecordKeeper &R,
                                       PatternRewriterFn PatternRewriter)
    : Records(R), Target(R), Intrinsics(R),
      LegalVTS(Target.getLegalValueTypes()),
      LegalPtrVTS(ComputeLegalPtrTypes()),
      PatternRewriter(std::move(PatternRewriter)) {
  ParseNodeInfo();
  ParseNodeTransforms();
  ParseComplexPatterns();
  ParsePatternFragments();
  ParseDefaultOperands();
  ParseInstructions();
  ParsePatternFragments(/*OutFrags*/ true);
  ParsePatterns();

  // Generate variants.  For example, commutative patterns can match
  // multiple ways.  Add them to PatternsToMatch as well.
  GenerateVariants();

  // Break patterns with parameterized types into a series of patterns,
  // where each one has a fixed type and is predicated on the conditions
  // of the associated HW mode.
  ExpandHwModeBasedTypes();

  // Infer instruction flags.  For example, we can detect loads,
  // stores, and side effects in many cases by examining an
  // instruction's pattern.
  InferInstructionFlags();

  // Verify that instruction flags match the patterns.
  VerifyInstructionFlags();
}

const Record *CodeGenDAGPatterns::getSDNodeNamed(StringRef Name) const {
  const Record *N = Records.getDef(Name);
  if (!N || !N->isSubClassOf("SDNode"))
    PrintFatalError("Error getting SDNode '" + Name + "'!");
  return N;
}

// Compute the subset of iPTR and cPTR legal for each mode, coalescing into the
// default mode where possible to avoid predicate explosion.
TypeSetByHwMode CodeGenDAGPatterns::ComputeLegalPtrTypes() const {
  auto LegalPtrsForSet = [](const MachineValueTypeSet &In) {
    MachineValueTypeSet Out;
    Out.insert(MVT::iPTR);
    for (MVT T : MVT::cheri_capability_valuetypes()) {
      if (In.count(T)) {
        Out.insert(MVT::cPTR);
        break;
      }
    }
    return Out;
  };

  const TypeSetByHwMode &LegalTypes = getLegalTypes();
  MachineValueTypeSet LegalPtrsDefault =
      LegalPtrsForSet(LegalTypes.get(DefaultMode));

  TypeSetByHwMode LegalPtrTypes;
  for (const auto &I : LegalTypes) {
    MachineValueTypeSet S = LegalPtrsForSet(I.second);
    if (I.first != DefaultMode && S == LegalPtrsDefault)
      continue;
    LegalPtrTypes.getOrCreate(I.first).insert(S);
  }

  return LegalPtrTypes;
}

// Parse all of the SDNode definitions for the target, populating SDNodes.
void CodeGenDAGPatterns::ParseNodeInfo() {
  const CodeGenHwModes &CGH = getTargetInfo().getHwModes();

  for (const Record *R : reverse(Records.getAllDerivedDefinitions("SDNode")))
    SDNodes.try_emplace(R, SDNodeInfo(R, CGH));

  // Get the builtin intrinsic nodes.
  intrinsic_void_sdnode = getSDNodeNamed("intrinsic_void");
  intrinsic_w_chain_sdnode = getSDNodeNamed("intrinsic_w_chain");
  intrinsic_wo_chain_sdnode = getSDNodeNamed("intrinsic_wo_chain");
}

/// ParseNodeTransforms - Parse all SDNodeXForm instances into the SDNodeXForms
/// map, and emit them to the file as functions.
void CodeGenDAGPatterns::ParseNodeTransforms() {
  for (const Record *XFormNode :
       reverse(Records.getAllDerivedDefinitions("SDNodeXForm"))) {
    const Record *SDNode = XFormNode->getValueAsDef("Opcode");
    StringRef Code = XFormNode->getValueAsString("XFormFunction");
    SDNodeXForms.try_emplace(XFormNode, NodeXForm(SDNode, Code.str()));
  }
}

void CodeGenDAGPatterns::ParseComplexPatterns() {
  for (const Record *R :
       reverse(Records.getAllDerivedDefinitions("ComplexPattern")))
    ComplexPatterns.try_emplace(R, R);
}

/// ParsePatternFragments - Parse all of the PatFrag definitions in the .td
/// file, building up the PatternFragments map.  After we've collected them all,
/// inline fragments together as necessary, so that there are no references left
/// inside a pattern fragment to a pattern fragment.
///
void CodeGenDAGPatterns::ParsePatternFragments(bool OutFrags) {
  // First step, parse all of the fragments.
  ArrayRef<const Record *> Fragments =
      Records.getAllDerivedDefinitions("PatFrags");
  for (const Record *Frag : Fragments) {
    if (OutFrags != Frag->isSubClassOf("OutPatFrag"))
      continue;

    const ListInit *LI = Frag->getValueAsListInit("Fragments");
    TreePattern *P = (PatternFragments[Frag] = std::make_unique<TreePattern>(
                          Frag, LI, !Frag->isSubClassOf("OutPatFrag"), *this))
                         .get();

    // Validate the argument list, converting it to set, to discard duplicates.
    std::vector<std::string> &Args = P->getArgList();
    // Copy the args so we can take StringRefs to them.
    auto ArgsCopy = Args;
    SmallDenseSet<StringRef, 4> OperandsSet(llvm::from_range, ArgsCopy);

    if (OperandsSet.contains(""))
      P->error("Cannot have unnamed 'node' values in pattern fragment!");

    // Parse the operands list.
    const DagInit *OpsList = Frag->getValueAsDag("Operands");
    const DefInit *OpsOp = dyn_cast<DefInit>(OpsList->getOperator());
    // Special cases: ops == outs == ins. Different names are used to
    // improve readability.
    if (!OpsOp || (OpsOp->getDef()->getName() != "ops" &&
                   OpsOp->getDef()->getName() != "outs" &&
                   OpsOp->getDef()->getName() != "ins"))
      P->error("Operands list should start with '(ops ... '!");

    // Copy over the arguments.
    Args.clear();
    for (unsigned j = 0, e = OpsList->getNumArgs(); j != e; ++j) {
      if (!isa<DefInit>(OpsList->getArg(j)) ||
          cast<DefInit>(OpsList->getArg(j))->getDef()->getName() != "node")
        P->error("Operands list should all be 'node' values.");
      if (!OpsList->getArgName(j))
        P->error("Operands list should have names for each operand!");
      StringRef ArgNameStr = OpsList->getArgNameStr(j);
      if (!OperandsSet.erase(ArgNameStr))
        P->error("'" + ArgNameStr +
                 "' does not occur in pattern or was multiply specified!");
      Args.push_back(ArgNameStr.str());
    }

    if (!OperandsSet.empty())
      P->error("Operands list does not contain an entry for operand '" +
               *OperandsSet.begin() + "'!");

    // If there is a node transformation corresponding to this, keep track of
    // it.
    const Record *Transform = Frag->getValueAsDef("OperandTransform");
    if (!getSDNodeTransform(Transform).second.empty()) // not noop xform?
      for (const auto &T : P->getTrees())
        T->setTransformFn(Transform);
  }

  // Now that we've parsed all of the tree fragments, do a closure on them so
  // that there are not references to PatFrags left inside of them.
  for (const Record *Frag : Fragments) {
    if (OutFrags != Frag->isSubClassOf("OutPatFrag"))
      continue;

    TreePattern &ThePat = *PatternFragments[Frag];
    ThePat.InlinePatternFragments();

    // Infer as many types as possible.  Don't worry about it if we don't infer
    // all of them, some may depend on the inputs of the pattern.  Also, don't
    // validate type sets; validation may cause spurious failures e.g. if a
    // fragment needs floating-point types but the current target does not have
    // any (this is only an error if that fragment is ever used!).
    {
      TypeInfer::SuppressValidation SV(ThePat.getInfer());
      ThePat.InferAllTypes();
      ThePat.resetError();
    }

    // If debugging, print out the pattern fragment result.
    LLVM_DEBUG(ThePat.dump());
  }
}

void CodeGenDAGPatterns::ParseDefaultOperands() {
  ArrayRef<const Record *> DefaultOps =
      Records.getAllDerivedDefinitions("OperandWithDefaultOps");

  for (unsigned i = 0, e = DefaultOps.size(); i != e; ++i) {
    const DagInit *DefaultInfo = DefaultOps[i]->getValueAsDag("DefaultOps");

    // Create a TreePattern to parse this.
    TreePattern P(DefaultOps[i], DefaultInfo->getArgs(),
                  DefaultInfo->getArgNames(), false, *this);
    assert(P.getNumTrees() == 1 && "This ctor can only produce one tree!");

    // Copy the operands over into a DAGDefaultOperand.
    DAGDefaultOperand DefaultOpInfo;

    const TreePatternNodePtr &T = P.getTree(0);
    for (unsigned op = 0, e = T->getNumChildren(); op != e; ++op) {
      TreePatternNodePtr TPN = T->getChildShared(op);
      while (TPN->ApplyTypeConstraints(P, false))
        /* Resolve all types */;

      if (TPN->ContainsUnresolvedType(P)) {
        PrintFatalError("Value #" + Twine(i) + " of OperandWithDefaultOps '" +
                        DefaultOps[i]->getName() +
                        "' doesn't have a concrete type!");
      }
      DefaultOpInfo.DefaultOps.push_back(std::move(TPN));
    }

    // Insert it into the DefaultOperands map so we can find it later.
    DefaultOperands[DefaultOps[i]] = DefaultOpInfo;
  }
}

/// HandleUse - Given "Pat" a leaf in the pattern, check to see if it is an
/// instruction input.  Return true if this is a real use.
static bool HandleUse(TreePattern &I, TreePatternNodePtr Pat,
                      std::map<StringRef, TreePatternNodePtr> &InstInputs) {
  // No name -> not interesting.
  if (Pat->getName().empty()) {
    if (Pat->isLeaf()) {
      const DefInit *DI = dyn_cast<DefInit>(Pat->getLeafValue());
      if (DI && (DI->getDef()->isSubClassOf("RegisterClass") ||
                 DI->getDef()->isSubClassOf("RegisterOperand")))
        I.error("Input " + DI->getDef()->getName() + " must be named!");
    }
    return false;
  }

  const Record *Rec;
  if (Pat->isLeaf()) {
    const DefInit *DI = dyn_cast<DefInit>(Pat->getLeafValue());
    if (!DI)
      I.error("Input $" + Pat->getName() + " must be an identifier!");
    Rec = DI->getDef();
  } else {
    Rec = Pat->getOperator();
  }

  // SRCVALUE nodes are ignored.
  if (Rec->getName() == "srcvalue")
    return false;

  TreePatternNodePtr &Slot = InstInputs[Pat->getName()];
  if (!Slot) {
    Slot = Pat;
    return true;
  }
  const Record *SlotRec;
  if (Slot->isLeaf()) {
    SlotRec = cast<DefInit>(Slot->getLeafValue())->getDef();
  } else {
    assert(Slot->getNumChildren() == 0 && "can't be a use with children!");
    SlotRec = Slot->getOperator();
  }

  // Ensure that the inputs agree if we've already seen this input.
  if (Rec != SlotRec)
    I.error("All $" + Pat->getName() + " inputs must agree with each other");
  // Ensure that the types can agree as well.
  Slot->UpdateNodeType(0, Pat->getExtType(0), I);
  Pat->UpdateNodeType(0, Slot->getExtType(0), I);
  if (Slot->getExtTypes() != Pat->getExtTypes())
    I.error("All $" + Pat->getName() + " inputs must agree with each other");
  return true;
}

/// FindPatternInputsAndOutputs - Scan the specified TreePatternNode (which is
/// part of "I", the instruction), computing the set of inputs and outputs of
/// the pattern.  Report errors if we see anything naughty.
void CodeGenDAGPatterns::FindPatternInputsAndOutputs(
    TreePattern &I, TreePatternNodePtr Pat, InstInputsTy &InstInputs,
    InstResultsTy &InstResults, std::vector<const Record *> &InstImpResults) {
  // The instruction pattern still has unresolved fragments.  For *named*
  // nodes we must resolve those here.  This may not result in multiple
  // alternatives.
  if (!Pat->getName().empty()) {
    TreePattern SrcPattern(I.getRecord(), Pat, true, *this);
    SrcPattern.InlinePatternFragments();
    SrcPattern.InferAllTypes();
    Pat = SrcPattern.getOnlyTree();
  }

  if (Pat->isLeaf()) {
    bool isUse = HandleUse(I, Pat, InstInputs);
    if (!isUse && Pat->getTransformFn())
      I.error("Cannot specify a transform function for a non-input value!");
    return;
  }

  if (Pat->getOperator()->getName() != "set") {
    // If this is not a set, verify that the children nodes are not void typed,
    // and recurse.
    for (unsigned i = 0, e = Pat->getNumChildren(); i != e; ++i) {
      if (Pat->getChild(i).getNumTypes() == 0)
        I.error("Cannot have void nodes inside of patterns!");
      FindPatternInputsAndOutputs(I, Pat->getChildShared(i), InstInputs,
                                  InstResults, InstImpResults);
    }

    // If this is a non-leaf node with no children, treat it basically as if
    // it were a leaf.  This handles nodes like (imm).
    bool isUse = HandleUse(I, Pat, InstInputs);

    if (!isUse && Pat->getTransformFn())
      I.error("Cannot specify a transform function for a non-input value!");
    return;
  }

  // Otherwise, this is a set, validate and collect instruction results.
  if (Pat->getNumChildren() == 0)
    I.error("set requires operands!");

  if (Pat->getTransformFn())
    I.error("Cannot specify a transform function on a set node!");

  // Check the set destinations.
  unsigned NumDests = Pat->getNumChildren() - 1;
  for (unsigned i = 0; i != NumDests; ++i) {
    TreePatternNodePtr Dest = Pat->getChildShared(i);
    // For set destinations we also must resolve fragments here.
    TreePattern DestPattern(I.getRecord(), Dest, false, *this);
    DestPattern.InlinePatternFragments();
    DestPattern.InferAllTypes();
    Dest = DestPattern.getOnlyTree();

    if (!Dest->isLeaf())
      I.error("set destination should be a register!");

    const DefInit *Val = dyn_cast<DefInit>(Dest->getLeafValue());
    if (!Val) {
      I.error("set destination should be a register!");
      continue;
    }

    if (Val->getDef()->isSubClassOf("RegisterClassLike") ||
        Val->getDef()->isSubClassOf("ValueType") ||
        Val->getDef()->isSubClassOf("RegisterOperand")) {
      if (Dest->getName().empty())
        I.error("set destination must have a name!");
      if (!InstResults.insert_or_assign(Dest->getName(), Dest).second)
        I.error("cannot set '" + Dest->getName() + "' multiple times");
    } else if (Val->getDef()->isSubClassOf("Register")) {
      InstImpResults.push_back(Val->getDef());
    } else {
      I.error("set destination should be a register!");
    }
  }

  // Verify and collect info from the computation.
  FindPatternInputsAndOutputs(I, Pat->getChildShared(NumDests), InstInputs,
                              InstResults, InstImpResults);
}

//===----------------------------------------------------------------------===//
// Instruction Analysis
//===----------------------------------------------------------------------===//

class InstAnalyzer {
  const CodeGenDAGPatterns &CDP;

public:
  bool hasSideEffects = false;
  bool mayStore = false;
  bool mayLoad = false;
  bool isBitcast = false;
  bool isVariadic = false;
  bool hasChain = false;

  InstAnalyzer(const CodeGenDAGPatterns &cdp) : CDP(cdp) {}

  void Analyze(const PatternToMatch &Pat) {
    const TreePatternNode &N = Pat.getSrcPattern();
    AnalyzeNode(N);
    // These properties are detected only on the root node.
    isBitcast = IsNodeBitcast(N);
  }

private:
  bool IsNodeBitcast(const TreePatternNode &N) const {
    if (hasSideEffects || mayLoad || mayStore || isVariadic)
      return false;

    if (N.isLeaf())
      return false;
    if (N.getNumChildren() != 1 || !N.getChild(0).isLeaf())
      return false;

    if (N.getOperator()->isSubClassOf("ComplexPattern"))
      return false;

    const SDNodeInfo &OpInfo = CDP.getSDNodeInfo(N.getOperator());
    if (OpInfo.getNumResults() != 1 || OpInfo.getNumOperands() != 1)
      return false;
    return OpInfo.getEnumName() == "ISD::BITCAST";
  }

public:
  void AnalyzeNode(const TreePatternNode &N) {
    if (N.isLeaf()) {
      if (const DefInit *DI = dyn_cast<DefInit>(N.getLeafValue())) {
        const Record *LeafRec = DI->getDef();
        // Handle ComplexPattern leaves.
        if (LeafRec->isSubClassOf("ComplexPattern")) {
          const ComplexPattern &CP = CDP.getComplexPattern(LeafRec);
          if (CP.hasProperty(SDNPMayStore))
            mayStore = true;
          if (CP.hasProperty(SDNPMayLoad))
            mayLoad = true;
          if (CP.hasProperty(SDNPSideEffect))
            hasSideEffects = true;
        }
      }
      return;
    }

    // Analyze children.
    for (const TreePatternNode &Child : N.children())
      AnalyzeNode(Child);

    // Notice properties of the node.
    if (N.NodeHasProperty(SDNPMayStore, CDP))
      mayStore = true;
    if (N.NodeHasProperty(SDNPMayLoad, CDP))
      mayLoad = true;
    if (N.NodeHasProperty(SDNPSideEffect, CDP))
      hasSideEffects = true;
    if (N.NodeHasProperty(SDNPVariadic, CDP))
      isVariadic = true;
    if (N.NodeHasProperty(SDNPHasChain, CDP))
      hasChain = true;

    if (const CodeGenIntrinsic *IntInfo = N.getIntrinsicInfo(CDP)) {
      ModRefInfo MR = IntInfo->ME.getModRef();
      // If this is an intrinsic, analyze it.
      if (isRefSet(MR))
        mayLoad = true; // These may load memory.

      if (isModSet(MR))
        mayStore = true; // Intrinsics that can write to memory are 'mayStore'.

      // Consider intrinsics that don't specify any restrictions on memory
      // effects as having a side-effect.
      if (IntInfo->ME == MemoryEffects::unknown() || IntInfo->hasSideEffects)
        hasSideEffects = true;
    }
  }
};

static bool InferFromPattern(CodeGenInstruction &InstInfo,
                             const InstAnalyzer &PatInfo,
                             const Record *PatDef) {
  bool Error = false;

  // Remember where InstInfo got its flags.
  if (InstInfo.hasUndefFlags())
    InstInfo.InferredFrom = PatDef;

  // Check explicitly set flags for consistency.
  if (InstInfo.hasSideEffects != PatInfo.hasSideEffects &&
      !InstInfo.hasSideEffects_Unset) {
    // Allow explicitly setting hasSideEffects = 1 on instructions, even when
    // the pattern has no side effects. That could be useful for div/rem
    // instructions that may trap.
    if (!InstInfo.hasSideEffects) {
      Error = true;
      PrintError(PatDef->getLoc(), "Pattern doesn't match hasSideEffects = " +
                                       Twine(InstInfo.hasSideEffects));
    }
  }

  if (InstInfo.mayStore != PatInfo.mayStore && !InstInfo.mayStore_Unset) {
    Error = true;
    PrintError(PatDef->getLoc(),
               "Pattern doesn't match mayStore = " + Twine(InstInfo.mayStore));
  }

  if (InstInfo.mayLoad != PatInfo.mayLoad && !InstInfo.mayLoad_Unset) {
    // Allow explicitly setting mayLoad = 1, even when the pattern has no loads.
    // Some targets translate immediates to loads.
    if (!InstInfo.mayLoad) {
      Error = true;
      PrintError(PatDef->getLoc(),
                 "Pattern doesn't match mayLoad = " + Twine(InstInfo.mayLoad));
    }
  }

  // Transfer inferred flags.
  InstInfo.hasSideEffects |= PatInfo.hasSideEffects;
  InstInfo.mayStore |= PatInfo.mayStore;
  InstInfo.mayLoad |= PatInfo.mayLoad;

  // These flags are silently added without any verification.
  // FIXME: To match historical behavior of TableGen, for now add those flags
  // only when we're inferring from the primary instruction pattern.
  if (PatDef->isSubClassOf("Instruction")) {
    InstInfo.isBitcast |= PatInfo.isBitcast;
    InstInfo.hasChain |= PatInfo.hasChain;
    InstInfo.hasChain_Inferred = true;
  }

  // Don't infer isVariadic. This flag means something different on SDNodes and
  // instructions. For example, a CALL SDNode is variadic because it has the
  // call arguments as operands, but a CALL instruction is not variadic - it
  // has argument registers as implicit, not explicit uses.

  return Error;
}

/// hasNullFragReference - Return true if the DAG has any reference to the
/// null_frag operator.
static bool hasNullFragReference(const DagInit *DI) {
  const DefInit *OpDef = dyn_cast<DefInit>(DI->getOperator());
  if (!OpDef)
    return false;
  const Record *Operator = OpDef->getDef();

  // If this is the null fragment, return true.
  if (Operator->getName() == "null_frag")
    return true;
  // If any of the arguments reference the null fragment, return true.
  for (unsigned i = 0, e = DI->getNumArgs(); i != e; ++i) {
    if (auto Arg = dyn_cast<DefInit>(DI->getArg(i)))
      if (Arg->getDef()->getName() == "null_frag")
        return true;
    const DagInit *Arg = dyn_cast<DagInit>(DI->getArg(i));
    if (Arg && hasNullFragReference(Arg))
      return true;
  }

  return false;
}

/// hasNullFragReference - Return true if any DAG in the list references
/// the null_frag operator.
static bool hasNullFragReference(const ListInit *LI) {
  for (const Init *I : LI->getElements()) {
    const DagInit *DI = dyn_cast<DagInit>(I);
    assert(DI && "non-dag in an instruction Pattern list?!");
    if (hasNullFragReference(DI))
      return true;
  }
  return false;
}

/// Get all the instructions in a tree.
static void getInstructionsInTree(TreePatternNode &Tree,
                                  SmallVectorImpl<const Record *> &Instrs) {
  if (Tree.isLeaf())
    return;
  if (Tree.getOperator()->isSubClassOf("Instruction"))
    Instrs.push_back(Tree.getOperator());
  for (TreePatternNode &Child : Tree.children())
    getInstructionsInTree(Child, Instrs);
}

/// Check the class of a pattern leaf node against the instruction operand it
/// represents.
static bool checkOperandClass(const CGIOperandList::OperandInfo &OI,
                              const Record *Leaf) {
  if (OI.Rec == Leaf)
    return true;

  // Allow direct value types to be used in instruction set patterns.
  // The type will be checked later.
  if (Leaf->isSubClassOf("ValueType"))
    return true;

  // Patterns can also be ComplexPattern instances.
  if (Leaf->isSubClassOf("ComplexPattern"))
    return true;

  return false;
}

void CodeGenDAGPatterns::parseInstructionPattern(const CodeGenInstruction &CGI,
                                                 const ListInit *Pat,
                                                 DAGInstMap &DAGInsts) {

  assert(!DAGInsts.count(CGI.TheDef) && "Instruction already parsed!");

  // Parse the instruction.
  TreePattern I(CGI.TheDef, Pat, true, *this);

  // InstInputs - Keep track of all of the inputs of the instruction, along
  // with the record they are declared as.
  std::map<StringRef, TreePatternNodePtr> InstInputs;

  // InstResults - Keep track of all the virtual registers that are 'set'
  // in the instruction, including what reg class they are.
  MapVector<StringRef, TreePatternNodePtr, std::map<StringRef, unsigned>>
      InstResults;

  std::vector<const Record *> InstImpResults;

  // Verify that the top-level forms in the instruction are of void type, and
  // fill in the InstResults map.
  SmallString<32> TypesString;
  for (unsigned j = 0, e = I.getNumTrees(); j != e; ++j) {
    TypesString.clear();
    TreePatternNodePtr Pat = I.getTree(j);
    if (Pat->getNumTypes() != 0) {
      raw_svector_ostream OS(TypesString);
      ListSeparator LS;
      for (unsigned k = 0, ke = Pat->getNumTypes(); k != ke; ++k) {
        OS << LS;
        Pat->getExtType(k).writeToStream(OS);
      }
      I.error("Top-level forms in instruction pattern should have"
              " void types, has types " +
              OS.str());
    }

    // Find inputs and outputs, and verify the structure of the uses/defs.
    FindPatternInputsAndOutputs(I, Pat, InstInputs, InstResults,
                                InstImpResults);
  }

  // Now that we have inputs and outputs of the pattern, inspect the operands
  // list for the instruction.  This determines the order that operands are
  // added to the machine instruction the node corresponds to.
  unsigned NumResults = InstResults.size();

  // Parse the operands list from the (ops) list, validating it.
  assert(I.getArgList().empty() && "Args list should still be empty here!");

  // Check that all of the results occur first in the list.
  std::vector<const Record *> Results;
  std::vector<unsigned> ResultIndices;
  SmallVector<TreePatternNodePtr, 2> ResNodes;
  for (unsigned i = 0; i != NumResults; ++i) {
    if (i == CGI.Operands.size()) {
      StringRef OpName =
          llvm::find_if(InstResults,
                        [](const std::pair<StringRef, TreePatternNodePtr> &P) {
                          return P.second;
                        })
              ->first;

      I.error("'" + OpName + "' set but does not appear in operand list!");
    }

    StringRef OpName = CGI.Operands[i].Name;

    // Check that it exists in InstResults.
    auto InstResultIter = InstResults.find(OpName);
    if (InstResultIter == InstResults.end() || !InstResultIter->second)
      I.error("Operand $" + OpName + " does not exist in operand list!");

    TreePatternNodePtr RNode = InstResultIter->second;
    const Record *R = cast<DefInit>(RNode->getLeafValue())->getDef();
    ResNodes.push_back(std::move(RNode));
    if (!R)
      I.error("Operand $" + OpName +
              " should be a set destination: all "
              "outputs must occur before inputs in operand list!");

    if (!checkOperandClass(CGI.Operands[i], R))
      I.error("Operand $" + OpName + " class mismatch!");

    // Remember the return type.
    Results.push_back(CGI.Operands[i].Rec);

    // Remember the result index.
    ResultIndices.push_back(std::distance(InstResults.begin(), InstResultIter));

    // Okay, this one checks out.
    InstResultIter->second = nullptr;
  }

  // Loop over the inputs next.
  std::vector<TreePatternNodePtr> ResultNodeOperands;
  std::vector<const Record *> Operands;
  for (unsigned i = NumResults, e = CGI.Operands.size(); i != e; ++i) {
    const CGIOperandList::OperandInfo &Op = CGI.Operands[i];
    StringRef OpName = Op.Name;
    if (OpName.empty()) {
      I.error("Operand #" + Twine(i) + " in operands list has no name!");
      continue;
    }

    auto InIter = InstInputs.find(OpName);
    if (InIter == InstInputs.end()) {
      // If this is an operand with a DefaultOps set filled in, we can ignore
      // this.  When we codegen it, we will do so as always executed.
      if (Op.Rec->isSubClassOf("OperandWithDefaultOps")) {
        // Does it have a non-empty DefaultOps field?  If so, ignore this
        // operand.
        if (!getDefaultOperand(Op.Rec).DefaultOps.empty())
          continue;
      }
      I.error("Operand $" + OpName +
              " does not appear in the instruction pattern");
      continue;
    }
    TreePatternNodePtr InVal = InIter->second;
    InstInputs.erase(InIter); // It occurred, remove from map.

    if (InVal->isLeaf() && isa<DefInit>(InVal->getLeafValue())) {
      const Record *InRec = cast<DefInit>(InVal->getLeafValue())->getDef();
      if (!checkOperandClass(Op, InRec)) {
        I.error("Operand $" + OpName +
                "'s register class disagrees"
                " between the operand and pattern");
        continue;
      }
    }
    Operands.push_back(Op.Rec);

    // Construct the result for the dest-pattern operand list.
    TreePatternNodePtr OpNode = InVal->clone();

    // No predicate is useful on the result.
    OpNode->clearPredicateCalls();

    // Promote the xform function to be an explicit node if set.
    if (const Record *Xform = OpNode->getTransformFn()) {
      OpNode->setTransformFn(nullptr);
      std::vector<TreePatternNodePtr> Children;
      Children.push_back(OpNode);
      OpNode = makeIntrusiveRefCnt<TreePatternNode>(Xform, std::move(Children),
                                                    OpNode->getNumTypes());
    }

    ResultNodeOperands.push_back(std::move(OpNode));
  }

  if (!InstInputs.empty())
    I.error("Input operand $" + InstInputs.begin()->first +
            " occurs in pattern but not in operands list!");

  TreePatternNodePtr ResultPattern = makeIntrusiveRefCnt<TreePatternNode>(
      I.getRecord(), std::move(ResultNodeOperands),
      GetNumNodeResults(I.getRecord(), *this));
  // Copy fully inferred output node types to instruction result pattern.
  for (unsigned i = 0; i != NumResults; ++i) {
    assert(ResNodes[i]->getNumTypes() == 1 && "FIXME: Unhandled");
    ResultPattern->setType(i, ResNodes[i]->getExtType(0));
    ResultPattern->setResultIndex(i, ResultIndices[i]);
  }

  // FIXME: Assume only the first tree is the pattern. The others are clobber
  // nodes.
  TreePatternNodePtr Pattern = I.getTree(0);
  TreePatternNodePtr SrcPattern;
  if (Pattern->getOperator()->getName() == "set") {
    SrcPattern = Pattern->getChild(Pattern->getNumChildren() - 1).clone();
  } else {
    // Not a set (store or something?)
    SrcPattern = Pattern;
  }

  // Create and insert the instruction.
  // FIXME: InstImpResults should not be part of DAGInstruction.
  DAGInsts.try_emplace(I.getRecord(), std::move(Results), std::move(Operands),
                       std::move(InstImpResults), SrcPattern, ResultPattern);

  LLVM_DEBUG(I.dump());
}

/// ParseInstructions - Parse all of the instructions, inlining and resolving
/// any fragments involved.  This populates the Instructions list with fully
/// resolved instructions.
void CodeGenDAGPatterns::ParseInstructions() {
  for (const Record *Instr : Records.getAllDerivedDefinitions("Instruction")) {
    const ListInit *LI = nullptr;

    if (isa<ListInit>(Instr->getValueInit("Pattern")))
      LI = Instr->getValueAsListInit("Pattern");

    // If there is no pattern, only collect minimal information about the
    // instruction for its operand list.  We have to assume that there is one
    // result, as we have no detailed info. A pattern which references the
    // null_frag operator is as-if no pattern were specified. Normally this
    // is from a multiclass expansion w/ a SDPatternOperator passed in as
    // null_frag.
    if (!LI || LI->empty() || hasNullFragReference(LI)) {
      std::vector<const Record *> Results;
      std::vector<const Record *> Operands;

      const CodeGenInstruction &InstInfo = Target.getInstruction(Instr);

      if (InstInfo.Operands.size() != 0) {
        for (unsigned j = 0, e = InstInfo.Operands.NumDefs; j < e; ++j)
          Results.push_back(InstInfo.Operands[j].Rec);

        // The rest are inputs.
        for (unsigned j = InstInfo.Operands.NumDefs,
                      e = InstInfo.Operands.size();
             j < e; ++j)
          Operands.push_back(InstInfo.Operands[j].Rec);
      }

      // Create and insert the instruction.
      Instructions.try_emplace(Instr, std::move(Results), std::move(Operands),
                               std::vector<const Record *>());
      continue; // no pattern.
    }

    const CodeGenInstruction &CGI = Target.getInstruction(Instr);
    parseInstructionPattern(CGI, LI, Instructions);
  }

  // If we can, convert the instructions to be patterns that are matched!
  for (const auto &[Instr, TheInst] : Instructions) {
    TreePatternNodePtr SrcPattern = TheInst.getSrcPattern();
    TreePatternNodePtr ResultPattern = TheInst.getResultPattern();

    if (SrcPattern && ResultPattern) {
      TreePattern Pattern(Instr, SrcPattern, true, *this);
      TreePattern Result(Instr, ResultPattern, false, *this);
      ParseOnePattern(Instr, Pattern, Result, TheInst.getImpResults());
    }
  }
}

using NameRecord = std::pair<TreePatternNode *, unsigned>;

static void FindNames(TreePatternNode &P,
                      std::map<StringRef, NameRecord> &Names,
                      TreePattern *PatternTop) {
  if (!P.getName().empty()) {
    NameRecord &Rec = Names[P.getName()];
    // If this is the first instance of the name, remember the node.
    if (Rec.second++ == 0)
      Rec.first = &P;
    else if (Rec.first->getExtTypes() != P.getExtTypes())
      PatternTop->error("repetition of value: $" + P.getName() +
                        " where different uses have different types!");
  }

  if (!P.isLeaf()) {
    for (TreePatternNode &Child : P.children())
      FindNames(Child, Names, PatternTop);
  }
}

void CodeGenDAGPatterns::AddPatternToMatch(TreePattern *Pattern,
                                           PatternToMatch &&PTM) {
  // Do some sanity checking on the pattern we're about to match.
  std::string Reason;
  if (!PTM.getSrcPattern().canPatternMatch(Reason, *this)) {
    PrintWarning(Pattern->getRecord()->getLoc(),
                 Twine("Pattern can never match: ") + Reason);
    return;
  }

  // If the source pattern's root is a complex pattern, that complex pattern
  // must specify the nodes it can potentially match.
  if (const ComplexPattern *CP =
          PTM.getSrcPattern().getComplexPatternInfo(*this))
    if (CP->getRootNodes().empty())
      Pattern->error("ComplexPattern at root must specify list of opcodes it"
                     " could match");

  // Find all of the named values in the input and output, ensure they have the
  // same type.
  std::map<StringRef, NameRecord> SrcNames, DstNames;
  FindNames(PTM.getSrcPattern(), SrcNames, Pattern);
  FindNames(PTM.getDstPattern(), DstNames, Pattern);

  // Scan all of the named values in the destination pattern, rejecting them if
  // they don't exist in the input pattern.
  for (const auto &Entry : DstNames) {
    if (SrcNames[Entry.first].first == nullptr)
      Pattern->error("Pattern has input without matching name in output: $" +
                     Entry.first);
  }

  // Scan all of the named values in the source pattern, rejecting them if the
  // name isn't used in the dest, and isn't used to tie two values together.
  for (const auto &Entry : SrcNames)
    if (DstNames[Entry.first].first == nullptr &&
        SrcNames[Entry.first].second == 1)
      Pattern->error("Pattern has dead named input: $" + Entry.first);

  PatternsToMatch.push_back(std::move(PTM));
}

void CodeGenDAGPatterns::InferInstructionFlags() {
  ArrayRef<const CodeGenInstruction *> Instructions = Target.getInstructions();

  unsigned Errors = 0;

  // Try to infer flags from all patterns in PatternToMatch.  These include
  // both the primary instruction patterns (which always come first) and
  // patterns defined outside the instruction.
  for (const PatternToMatch &PTM : ptms()) {
    // We can only infer from single-instruction patterns, otherwise we won't
    // know which instruction should get the flags.
    SmallVector<const Record *, 8> PatInstrs;
    getInstructionsInTree(PTM.getDstPattern(), PatInstrs);
    if (PatInstrs.size() != 1)
      continue;

    // Get the single instruction.
    CodeGenInstruction &InstInfo = Target.getInstruction(PatInstrs.front());

    // Only infer properties from the first pattern. We'll verify the others.
    if (InstInfo.InferredFrom)
      continue;

    InstAnalyzer PatInfo(*this);
    PatInfo.Analyze(PTM);
    Errors += InferFromPattern(InstInfo, PatInfo, PTM.getSrcRecord());
  }

  if (Errors)
    PrintFatalError("pattern conflicts");

  // If requested by the target, guess any undefined properties.
  if (Target.guessInstructionProperties()) {
    for (const CodeGenInstruction *InstInfo : Instructions) {
      if (InstInfo->InferredFrom)
        continue;
      // The mayLoad and mayStore flags default to false.
      // Conservatively assume hasSideEffects if it wasn't explicit.
      if (InstInfo->hasSideEffects_Unset)
        const_cast<CodeGenInstruction *>(InstInfo)->hasSideEffects = true;
    }
    return;
  }

  // Complain about any flags that are still undefined.
  for (const CodeGenInstruction *InstInfo : Instructions) {
    if (InstInfo->InferredFrom)
      continue;
    if (InstInfo->hasSideEffects_Unset)
      PrintError(InstInfo->TheDef->getLoc(),
                 "Can't infer hasSideEffects from patterns");
    if (InstInfo->mayStore_Unset)
      PrintError(InstInfo->TheDef->getLoc(),
                 "Can't infer mayStore from patterns");
    if (InstInfo->mayLoad_Unset)
      PrintError(InstInfo->TheDef->getLoc(),
                 "Can't infer mayLoad from patterns");
  }
}

/// Verify instruction flags against pattern node properties.
void CodeGenDAGPatterns::VerifyInstructionFlags() {
  unsigned Errors = 0;
  for (const PatternToMatch &PTM : ptms()) {
    SmallVector<const Record *, 8> Instrs;
    getInstructionsInTree(PTM.getDstPattern(), Instrs);
    if (Instrs.empty())
      continue;

    // Count the number of instructions with each flag set.
    unsigned NumSideEffects = 0;
    unsigned NumStores = 0;
    unsigned NumLoads = 0;
    for (const Record *Instr : Instrs) {
      const CodeGenInstruction &InstInfo = Target.getInstruction(Instr);
      NumSideEffects += InstInfo.hasSideEffects;
      NumStores += InstInfo.mayStore;
      NumLoads += InstInfo.mayLoad;
    }

    // Analyze the source pattern.
    InstAnalyzer PatInfo(*this);
    PatInfo.Analyze(PTM);

    // Collect error messages.
    SmallVector<std::string, 4> Msgs;

    // Check for missing flags in the output.
    // Permit extra flags for now at least.
    if (PatInfo.hasSideEffects && !NumSideEffects)
      Msgs.push_back("pattern has side effects, but hasSideEffects isn't set");

    // Don't verify store flags on instructions with side effects. At least for
    // intrinsics, side effects implies mayStore.
    if (!PatInfo.hasSideEffects && PatInfo.mayStore && !NumStores)
      Msgs.push_back("pattern may store, but mayStore isn't set");

    // Similarly, mayStore implies mayLoad on intrinsics.
    if (!PatInfo.mayStore && PatInfo.mayLoad && !NumLoads)
      Msgs.push_back("pattern may load, but mayLoad isn't set");

    // Print error messages.
    if (Msgs.empty())
      continue;
    ++Errors;

    for (const std::string &Msg : Msgs)
      PrintError(
          PTM.getSrcRecord()->getLoc(),
          Twine(Msg) + " on the " +
              (Instrs.size() == 1 ? "instruction" : "output instructions"));
    // Provide the location of the relevant instruction definitions.
    for (const Record *Instr : Instrs) {
      if (Instr != PTM.getSrcRecord())
        PrintError(Instr->getLoc(), "defined here");
      const CodeGenInstruction &InstInfo = Target.getInstruction(Instr);
      if (InstInfo.InferredFrom && InstInfo.InferredFrom != InstInfo.TheDef &&
          InstInfo.InferredFrom != PTM.getSrcRecord())
        PrintError(InstInfo.InferredFrom->getLoc(), "inferred from pattern");
    }
  }
  if (Errors)
    PrintFatalError("Errors in DAG patterns");
}

/// Given a pattern result with an unresolved type, see if we can find one
/// instruction with an unresolved result type.  Force this result type to an
/// arbitrary element if it's possible types to converge results.
static bool ForceArbitraryInstResultType(TreePatternNode &N, TreePattern &TP) {
  if (N.isLeaf())
    return false;

  // Analyze children.
  for (TreePatternNode &Child : N.children())
    if (ForceArbitraryInstResultType(Child, TP))
      return true;

  if (!N.getOperator()->isSubClassOf("Instruction"))
    return false;

  // If this type is already concrete or completely unknown we can't do
  // anything.
  TypeInfer &TI = TP.getInfer();
  for (unsigned i = 0, e = N.getNumTypes(); i != e; ++i) {
    if (N.getExtType(i).empty() || TI.isConcrete(N.getExtType(i), false))
      continue;

    // Otherwise, force its type to an arbitrary choice.
    if (TI.forceArbitrary(N.getExtType(i)))
      return true;
  }

  return false;
}

// Promote xform function to be an explicit node wherever set.
static TreePatternNodePtr PromoteXForms(TreePatternNodePtr N) {
  if (const Record *Xform = N->getTransformFn()) {
    N->setTransformFn(nullptr);
    std::vector<TreePatternNodePtr> Children;
    Children.push_back(PromoteXForms(N));
    return makeIntrusiveRefCnt<TreePatternNode>(Xform, std::move(Children),
                                                N->getNumTypes());
  }

  if (!N->isLeaf())
    for (unsigned i = 0, e = N->getNumChildren(); i != e; ++i) {
      TreePatternNodePtr Child = N->getChildShared(i);
      N->setChild(i, PromoteXForms(Child));
    }
  return N;
}

void CodeGenDAGPatterns::ParseOnePattern(
    const Record *TheDef, TreePattern &Pattern, TreePattern &Result,
    ArrayRef<const Record *> InstImpResults, bool ShouldIgnore) {
  // Inline pattern fragments and expand multiple alternatives.
  Pattern.InlinePatternFragments();
  Result.InlinePatternFragments();

  if (Result.getNumTrees() != 1) {
    Result.error("Cannot use multi-alternative fragments in result pattern!");
    return;
  }

  // Infer types.
  bool IterateInference;
  bool InferredAllPatternTypes, InferredAllResultTypes;
  do {
    // Infer as many types as possible.  If we cannot infer all of them, we
    // can never do anything with this pattern: report it to the user.
    InferredAllPatternTypes =
        Pattern.InferAllTypes(&Pattern.getNamedNodesMap());

    // Infer as many types as possible.  If we cannot infer all of them, we
    // can never do anything with this pattern: report it to the user.
    InferredAllResultTypes = Result.InferAllTypes(&Pattern.getNamedNodesMap());

    IterateInference = false;

    // Apply the type of the result to the source pattern.  This helps us
    // resolve cases where the input type is known to be a pointer type (which
    // is considered resolved), but the result knows it needs to be 32- or
    // 64-bits.  Infer the other way for good measure.
    for (const auto &T : Pattern.getTrees())
      for (unsigned i = 0, e = std::min(Result.getOnlyTree()->getNumTypes(),
                                        T->getNumTypes());
           i != e; ++i) {
        IterateInference |=
            T->UpdateNodeType(i, Result.getOnlyTree()->getExtType(i), Result);
        IterateInference |=
            Result.getOnlyTree()->UpdateNodeType(i, T->getExtType(i), Result);
      }

    // If our iteration has converged and the input pattern's types are fully
    // resolved but the result pattern is not fully resolved, we may have a
    // situation where we have two instructions in the result pattern and
    // the instructions require a common register class, but don't care about
    // what actual MVT is used.  This is actually a bug in our modelling:
    // output patterns should have register classes, not MVTs.
    //
    // In any case, to handle this, we just go through and disambiguate some
    // arbitrary types to the result pattern's nodes.
    if (!IterateInference && InferredAllPatternTypes && !InferredAllResultTypes)
      IterateInference =
          ForceArbitraryInstResultType(*Result.getTree(0), Result);
  } while (IterateInference);

  // Verify that we inferred enough types that we can do something with the
  // pattern and result.  If these fire the user has to add type casts.
  if (!InferredAllPatternTypes)
    Pattern.error("Could not infer all types in pattern!");
  if (!InferredAllResultTypes) {
    Pattern.dump();
    Result.error("Could not infer all types in pattern result!");
  }

  // Promote xform function to be an explicit node wherever set.
  TreePatternNodePtr DstShared = PromoteXForms(Result.getOnlyTree());

  TreePattern Temp(Result.getRecord(), DstShared, false, *this);
  Temp.InferAllTypes();

  const ListInit *Preds = TheDef->getValueAsListInit("Predicates");
  int Complexity = TheDef->getValueAsInt("AddedComplexity");

  if (PatternRewriter)
    PatternRewriter(&Pattern);

  // A pattern may end up with an "impossible" type, i.e. a situation
  // where all types have been eliminated for some node in this pattern.
  // This could occur for intrinsics that only make sense for a specific
  // value type, and use a specific register class. If, for some mode,
  // that register class does not accept that type, the type inference
  // will lead to a contradiction, which is not an error however, but
  // a sign that this pattern will simply never match.
  if (Temp.getOnlyTree()->hasPossibleType()) {
    for (const auto &T : Pattern.getTrees()) {
      if (T->hasPossibleType())
        AddPatternToMatch(&Pattern,
                          PatternToMatch(TheDef, Preds, T, Temp.getOnlyTree(),
                                         InstImpResults, Complexity,
                                         TheDef->getID(), ShouldIgnore));
    }
  } else {
    // Show a message about a dropped pattern with some info to make it
    // easier to identify it in the .td files.
    LLVM_DEBUG({
      dbgs() << "Dropping: ";
      Pattern.dump();
      Temp.getOnlyTree()->dump();
      dbgs() << "\n";
    });
  }
}

void CodeGenDAGPatterns::ParsePatterns() {
  for (const Record *CurPattern : Records.getAllDerivedDefinitions("Pattern")) {
    const DagInit *Tree = CurPattern->getValueAsDag("PatternToMatch");

    // If the pattern references the null_frag, there's nothing to do.
    if (hasNullFragReference(Tree))
      continue;

    TreePattern Pattern(CurPattern, Tree, true, *this);

    const ListInit *LI = CurPattern->getValueAsListInit("ResultInstrs");
    if (LI->empty())
      continue; // no pattern.

    // Parse the instruction.
    TreePattern Result(CurPattern, LI, false, *this);

    if (Result.getNumTrees() != 1)
      Result.error("Cannot handle instructions producing instructions "
                   "with temporaries yet!");

    // Validate that the input pattern is correct.
    InstInputsTy InstInputs;
    InstResultsTy InstResults;
    std::vector<const Record *> InstImpResults;
    for (unsigned j = 0, ee = Pattern.getNumTrees(); j != ee; ++j)
      FindPatternInputsAndOutputs(Pattern, Pattern.getTree(j), InstInputs,
                                  InstResults, InstImpResults);

    ParseOnePattern(CurPattern, Pattern, Result, InstImpResults,
                    CurPattern->getValueAsBit("GISelShouldIgnore"));
  }
}

static void collectModes(std::set<unsigned> &Modes, const TreePatternNode &N) {
  for (const TypeSetByHwMode &VTS : N.getExtTypes())
    for (const auto &I : VTS)
      Modes.insert(I.first);

  for (const TreePatternNode &Child : N.children())
    collectModes(Modes, Child);
}

void CodeGenDAGPatterns::ExpandHwModeBasedTypes() {
  const CodeGenHwModes &CGH = getTargetInfo().getHwModes();
  if (CGH.getNumModeIds() == 1)
    return;

  std::vector<PatternToMatch> Copy;
  PatternsToMatch.swap(Copy);

  auto AppendPattern = [this](PatternToMatch &P, unsigned Mode,
                              StringRef Check) {
    TreePatternNodePtr NewSrc = P.getSrcPattern().clone();
    TreePatternNodePtr NewDst = P.getDstPattern().clone();
    if (!NewSrc->setDefaultMode(Mode) || !NewDst->setDefaultMode(Mode)) {
      return;
    }

    PatternsToMatch.emplace_back(P.getSrcRecord(), P.getPredicates(),
                                 std::move(NewSrc), std::move(NewDst),
                                 P.getDstRegs(), P.getAddedComplexity(),
                                 getNewUID(), P.getGISelShouldIgnore(), Check);
  };

  for (PatternToMatch &P : Copy) {
    const TreePatternNode *SrcP = nullptr, *DstP = nullptr;
    if (P.getSrcPattern().hasProperTypeByHwMode())
      SrcP = &P.getSrcPattern();
    if (P.getDstPattern().hasProperTypeByHwMode())
      DstP = &P.getDstPattern();
    if (!SrcP && !DstP) {
      PatternsToMatch.push_back(P);
      continue;
    }

    std::set<unsigned> Modes;
    if (SrcP)
      collectModes(Modes, *SrcP);
    if (DstP)
      collectModes(Modes, *DstP);

    // The predicate for the default mode needs to be constructed for each
    // pattern separately.
    // Since not all modes must be present in each pattern, if a mode m is
    // absent, then there is no point in constructing a check for m. If such
    // a check was created, it would be equivalent to checking the default
    // mode, except not all modes' predicates would be a part of the checking
    // code. The subsequently generated check for the default mode would then
    // have the exact same patterns, but a different predicate code. To avoid
    // duplicated patterns with different predicate checks, construct the
    // default check as a negation of all predicates that are actually present
    // in the source/destination patterns.
    SmallString<128> DefaultCheck;

    for (unsigned M : Modes) {
      if (M == DefaultMode)
        continue;

      // Fill the map entry for this mode.
      const HwMode &HM = CGH.getMode(M);

      SmallString<128> PredicateCheck;
      raw_svector_ostream PS(PredicateCheck);
      SubtargetFeatureInfo::emitPredicateCheck(PS, HM.Predicates);
      AppendPattern(P, M, PredicateCheck);

      // Add negations of the HM's predicates to the default predicate.
      if (!DefaultCheck.empty())
        DefaultCheck += " && ";
      DefaultCheck += "!(";
      DefaultCheck.append(PredicateCheck);
      DefaultCheck += ")";
    }

    bool HasDefault = Modes.count(DefaultMode);
    if (HasDefault)
      AppendPattern(P, DefaultMode, DefaultCheck);
  }
}

/// Dependent variable map for CodeGenDAGPattern variant generation
using DepVarMap = StringMap<int>;

static void FindDepVarsOf(TreePatternNode &N, DepVarMap &DepMap) {
  if (N.isLeaf()) {
    if (N.hasName() && isa<DefInit>(N.getLeafValue()))
      DepMap[N.getName()]++;
  } else {
    for (TreePatternNode &Child : N.children())
      FindDepVarsOf(Child, DepMap);
  }
}

/// Find dependent variables within child patterns
static void FindDepVars(TreePatternNode &N, MultipleUseVarSet &DepVars) {
  DepVarMap depcounts;
  FindDepVarsOf(N, depcounts);
  for (const auto &Pair : depcounts) {
    if (Pair.getValue() > 1)
      DepVars.insert(Pair.getKey());
  }
}

#ifndef NDEBUG
/// Dump the dependent variable set:
static void DumpDepVars(MultipleUseVarSet &DepVars) {
  if (DepVars.empty()) {
    LLVM_DEBUG(errs() << "<empty set>");
  } else {
    LLVM_DEBUG(errs() << "[ ");
    for (const auto &DepVar : DepVars) {
      LLVM_DEBUG(errs() << DepVar.getKey() << " ");
    }
    LLVM_DEBUG(errs() << "]");
  }
}
#endif

/// CombineChildVariants - Given a bunch of permutations of each child of the
/// 'operator' node, put them together in all possible ways.
static void CombineChildVariants(
    TreePatternNodePtr Orig,
    const std::vector<std::vector<TreePatternNodePtr>> &ChildVariants,
    std::vector<TreePatternNodePtr> &OutVariants, CodeGenDAGPatterns &CDP,
    const MultipleUseVarSet &DepVars) {
  // Make sure that each operand has at least one variant to choose from.
  for (const auto &Variants : ChildVariants)
    if (Variants.empty())
      return;

  // The end result is an all-pairs construction of the resultant pattern.
  std::vector<unsigned> Idxs(ChildVariants.size());
  bool NotDone;
  do {
#ifndef NDEBUG
    LLVM_DEBUG(if (!Idxs.empty()) {
      errs() << Orig->getOperator()->getName() << ": Idxs = [ ";
      for (unsigned Idx : Idxs) {
        errs() << Idx << " ";
      }
      errs() << "]\n";
    });
#endif
    // Create the variant and add it to the output list.
    std::vector<TreePatternNodePtr> NewChildren;
    NewChildren.reserve(ChildVariants.size());
    for (unsigned i = 0, e = ChildVariants.size(); i != e; ++i)
      NewChildren.push_back(ChildVariants[i][Idxs[i]]);
    TreePatternNodePtr R = makeIntrusiveRefCnt<TreePatternNode>(
        Orig->getOperator(), std::move(NewChildren), Orig->getNumTypes());

    // Copy over properties.
    R->setName(Orig->getName());
    R->setNamesAsPredicateArg(Orig->getNamesAsPredicateArg());
    R->setPredicateCalls(Orig->getPredicateCalls());
    R->setGISelFlagsRecord(Orig->getGISelFlagsRecord());
    R->setTransformFn(Orig->getTransformFn());
    for (unsigned i = 0, e = Orig->getNumTypes(); i != e; ++i)
      R->setType(i, Orig->getExtType(i));

    // If this pattern cannot match, do not include it as a variant.
    std::string ErrString;
    // Scan to see if this pattern has already been emitted.  We can get
    // duplication due to things like commuting:
    //   (and GPRC:$a, GPRC:$b) -> (and GPRC:$b, GPRC:$a)
    // which are the same pattern.  Ignore the dups.
    if (R->canPatternMatch(ErrString, CDP) &&
        none_of(OutVariants, [&](TreePatternNodePtr Variant) {
          return R->isIsomorphicTo(*Variant, DepVars);
        }))
      OutVariants.push_back(R);

    // Increment indices to the next permutation by incrementing the
    // indices from last index backward, e.g., generate the sequence
    // [0, 0], [0, 1], [1, 0], [1, 1].
    int IdxsIdx;
    for (IdxsIdx = Idxs.size() - 1; IdxsIdx >= 0; --IdxsIdx) {
      if (++Idxs[IdxsIdx] == ChildVariants[IdxsIdx].size())
        Idxs[IdxsIdx] = 0;
      else
        break;
    }
    NotDone = (IdxsIdx >= 0);
  } while (NotDone);
}

/// CombineChildVariants - A helper function for binary operators.
///
static void CombineChildVariants(TreePatternNodePtr Orig,
                                 const std::vector<TreePatternNodePtr> &LHS,
                                 const std::vector<TreePatternNodePtr> &RHS,
                                 std::vector<TreePatternNodePtr> &OutVariants,
                                 CodeGenDAGPatterns &CDP,
                                 const MultipleUseVarSet &DepVars) {
  std::vector<std::vector<TreePatternNodePtr>> ChildVariants;
  ChildVariants.push_back(LHS);
  ChildVariants.push_back(RHS);
  CombineChildVariants(Orig, ChildVariants, OutVariants, CDP, DepVars);
}

static void
GatherChildrenOfAssociativeOpcode(TreePatternNodePtr N,
                                  std::vector<TreePatternNodePtr> &Children) {
  assert(N->getNumChildren() == 2 &&
         "Associative but doesn't have 2 children!");
  const Record *Operator = N->getOperator();

  // Only permit raw nodes.
  if (!N->getName().empty() || !N->getPredicateCalls().empty() ||
      N->getTransformFn()) {
    Children.push_back(N);
    return;
  }

  if (N->getChild(0).isLeaf() || N->getChild(0).getOperator() != Operator)
    Children.push_back(N->getChildShared(0));
  else
    GatherChildrenOfAssociativeOpcode(N->getChildShared(0), Children);

  if (N->getChild(1).isLeaf() || N->getChild(1).getOperator() != Operator)
    Children.push_back(N->getChildShared(1));
  else
    GatherChildrenOfAssociativeOpcode(N->getChildShared(1), Children);
}

/// GenerateVariantsOf - Given a pattern N, generate all permutations we can of
/// the (potentially recursive) pattern by using algebraic laws.
///
static void GenerateVariantsOf(TreePatternNodePtr N,
                               std::vector<TreePatternNodePtr> &OutVariants,
                               CodeGenDAGPatterns &CDP,
                               const MultipleUseVarSet &DepVars) {
  // We cannot permute leaves or ComplexPattern uses.
  if (N->isLeaf() || N->getOperator()->isSubClassOf("ComplexPattern")) {
    OutVariants.push_back(N);
    return;
  }

  // Look up interesting info about the node.
  const SDNodeInfo &NodeInfo = CDP.getSDNodeInfo(N->getOperator());

  // If this node is associative, re-associate.
  if (NodeInfo.hasProperty(SDNPAssociative)) {
    // Re-associate by pulling together all of the linked operators
    std::vector<TreePatternNodePtr> MaximalChildren;
    GatherChildrenOfAssociativeOpcode(N, MaximalChildren);

    // Only handle child sizes of 3.  Otherwise we'll end up trying too many
    // permutations.
    if (MaximalChildren.size() == 3) {
      // Find the variants of all of our maximal children.
      std::vector<TreePatternNodePtr> AVariants, BVariants, CVariants;
      GenerateVariantsOf(MaximalChildren[0], AVariants, CDP, DepVars);
      GenerateVariantsOf(MaximalChildren[1], BVariants, CDP, DepVars);
      GenerateVariantsOf(MaximalChildren[2], CVariants, CDP, DepVars);

      // There are only two ways we can permute the tree:
      //   (A op B) op C    and    A op (B op C)
      // Within these forms, we can also permute A/B/C.

      // Generate legal pair permutations of A/B/C.
      std::vector<TreePatternNodePtr> ABVariants;
      std::vector<TreePatternNodePtr> BAVariants;
      std::vector<TreePatternNodePtr> ACVariants;
      std::vector<TreePatternNodePtr> CAVariants;
      std::vector<TreePatternNodePtr> BCVariants;
      std::vector<TreePatternNodePtr> CBVariants;
      CombineChildVariants(N, AVariants, BVariants, ABVariants, CDP, DepVars);
      CombineChildVariants(N, BVariants, AVariants, BAVariants, CDP, DepVars);
      CombineChildVariants(N, AVariants, CVariants, ACVariants, CDP, DepVars);
      CombineChildVariants(N, CVariants, AVariants, CAVariants, CDP, DepVars);
      CombineChildVariants(N, BVariants, CVariants, BCVariants, CDP, DepVars);
      CombineChildVariants(N, CVariants, BVariants, CBVariants, CDP, DepVars);

      // Combine those into the result: (x op x) op x
      CombineChildVariants(N, ABVariants, CVariants, OutVariants, CDP, DepVars);
      CombineChildVariants(N, BAVariants, CVariants, OutVariants, CDP, DepVars);
      CombineChildVariants(N, ACVariants, BVariants, OutVariants, CDP, DepVars);
      CombineChildVariants(N, CAVariants, BVariants, OutVariants, CDP, DepVars);
      CombineChildVariants(N, BCVariants, AVariants, OutVariants, CDP, DepVars);
      CombineChildVariants(N, CBVariants, AVariants, OutVariants, CDP, DepVars);

      // Combine those into the result: x op (x op x)
      CombineChildVariants(N, CVariants, ABVariants, OutVariants, CDP, DepVars);
      CombineChildVariants(N, CVariants, BAVariants, OutVariants, CDP, DepVars);
      CombineChildVariants(N, BVariants, ACVariants, OutVariants, CDP, DepVars);
      CombineChildVariants(N, BVariants, CAVariants, OutVariants, CDP, DepVars);
      CombineChildVariants(N, AVariants, BCVariants, OutVariants, CDP, DepVars);
      CombineChildVariants(N, AVariants, CBVariants, OutVariants, CDP, DepVars);
      return;
    }
  }

  // Compute permutations of all children.
  std::vector<std::vector<TreePatternNodePtr>> ChildVariants(
      N->getNumChildren());
  for (unsigned i = 0, e = N->getNumChildren(); i != e; ++i)
    GenerateVariantsOf(N->getChildShared(i), ChildVariants[i], CDP, DepVars);

  // Build all permutations based on how the children were formed.
  CombineChildVariants(N, ChildVariants, OutVariants, CDP, DepVars);

  // If this node is commutative, consider the commuted order.
  bool isCommIntrinsic = N->isCommutativeIntrinsic(CDP);
  if (NodeInfo.hasProperty(SDNPCommutative) || isCommIntrinsic) {
    unsigned Skip = isCommIntrinsic ? 1 : 0; // First operand is intrinsic id.
    assert(N->getNumChildren() >= (2 + Skip) &&
           "Commutative but doesn't have 2 children!");
    // Don't allow commuting children which are actually register references.
    bool NoRegisters = true;
    unsigned i = 0 + Skip;
    unsigned e = 2 + Skip;
    for (; i != e; ++i) {
      TreePatternNode &Child = N->getChild(i);
      if (Child.isLeaf())
        if (const DefInit *DI = dyn_cast<DefInit>(Child.getLeafValue())) {
          const Record *RR = DI->getDef();
          if (RR->isSubClassOf("Register"))
            NoRegisters = false;
        }
    }
    // Consider the commuted order.
    if (NoRegisters) {
      // Swap the first two operands after the intrinsic id, if present.
      unsigned i = isCommIntrinsic ? 1 : 0;
      std::swap(ChildVariants[i], ChildVariants[i + 1]);
      CombineChildVariants(N, ChildVariants, OutVariants, CDP, DepVars);
    }
  }
}

// GenerateVariants - Generate variants.  For example, commutative patterns can
// match multiple ways.  Add them to PatternsToMatch as well.
void CodeGenDAGPatterns::GenerateVariants() {
  LLVM_DEBUG(errs() << "Generating instruction variants.\n");

  // Loop over all of the patterns we've collected, checking to see if we can
  // generate variants of the instruction, through the exploitation of
  // identities.  This permits the target to provide aggressive matching without
  // the .td file having to contain tons of variants of instructions.
  //
  // Note that this loop adds new patterns to the PatternsToMatch list, but we
  // intentionally do not reconsider these.  Any variants of added patterns have
  // already been added.
  //
  for (unsigned i = 0, e = PatternsToMatch.size(); i != e; ++i) {
    MultipleUseVarSet DepVars;
    std::vector<TreePatternNodePtr> Variants;
    FindDepVars(PatternsToMatch[i].getSrcPattern(), DepVars);
    LLVM_DEBUG(errs() << "Dependent/multiply used variables: ");
    LLVM_DEBUG(DumpDepVars(DepVars));
    LLVM_DEBUG(errs() << "\n");
    GenerateVariantsOf(PatternsToMatch[i].getSrcPatternShared(), Variants,
                       *this, DepVars);

    assert(PatternsToMatch[i].getHwModeFeatures().empty() &&
           "HwModes should not have been expanded yet!");

    assert(!Variants.empty() && "Must create at least original variant!");
    if (Variants.size() == 1) // No additional variants for this pattern.
      continue;

    LLVM_DEBUG(errs() << "FOUND VARIANTS OF: ";
               PatternsToMatch[i].getSrcPattern().dump(); errs() << "\n");

    for (unsigned v = 0, e = Variants.size(); v != e; ++v) {
      TreePatternNodePtr Variant = Variants[v];

      LLVM_DEBUG(errs() << "  VAR#" << v << ": "; Variant->dump();
                 errs() << "\n");

      // Scan to see if an instruction or explicit pattern already matches this.
      bool AlreadyExists = false;
      for (unsigned p = 0, e = PatternsToMatch.size(); p != e; ++p) {
        // Skip if the top level predicates do not match.
        if ((i != p) && (PatternsToMatch[i].getPredicates() !=
                         PatternsToMatch[p].getPredicates()))
          continue;
        // Check to see if this variant already exists.
        if (Variant->isIsomorphicTo(PatternsToMatch[p].getSrcPattern(),
                                    DepVars)) {
          LLVM_DEBUG(errs() << "  *** ALREADY EXISTS, ignoring variant.\n");
          AlreadyExists = true;
          break;
        }
      }
      // If we already have it, ignore the variant.
      if (AlreadyExists)
        continue;

      // Otherwise, add it to the list of patterns we have.
      PatternsToMatch.emplace_back(
          PatternsToMatch[i].getSrcRecord(), PatternsToMatch[i].getPredicates(),
          Variant, PatternsToMatch[i].getDstPatternShared(),
          PatternsToMatch[i].getDstRegs(),
          PatternsToMatch[i].getAddedComplexity(), getNewUID(),
          PatternsToMatch[i].getGISelShouldIgnore(),
          PatternsToMatch[i].getHwModeFeatures());
    }

    LLVM_DEBUG(errs() << "\n");
  }
}

unsigned CodeGenDAGPatterns::getNewUID() {
  RecordKeeper &MutableRC = const_cast<RecordKeeper &>(Records);
  return Record::getNewUID(MutableRC);
}
