//===- DAGISelMatcher.h - Representation of DAG pattern matcher -*- C++ -*-===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//

#ifndef LLVM_UTILS_TABLEGEN_DAGISELMATCHER_H
#define LLVM_UTILS_TABLEGEN_DAGISELMATCHER_H

#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/CodeGen/MachineValueType.h"
#include "llvm/Support/Casting.h"

namespace llvm {
  struct CodeGenRegister;
  class CodeGenDAGPatterns;
  class Matcher;
  class PatternToMatch;
  class raw_ostream;
  class ComplexPattern;
  class Record;
  class SDNodeInfo;
  class TreePredicateFn;
  class TreePattern;

Matcher *ConvertPatternToMatcher(const PatternToMatch &Pattern,unsigned Variant,
                                 const CodeGenDAGPatterns &CGP);
void OptimizeMatcher(std::unique_ptr<Matcher> &Matcher,
                     const CodeGenDAGPatterns &CGP);
void EmitMatcherTable(const Matcher *Matcher, const CodeGenDAGPatterns &CGP,
                      raw_ostream &OS);


/// Matcher - Base class for all the DAG ISel Matcher representation
/// nodes.
class Matcher {
  // The next matcher node that is executed after this one.  Null if this is the
  // last stage of a match.
  std::unique_ptr<Matcher> Next;
  virtual void anchor();
public:
  enum KindTy {
    // Matcher state manipulation.
    Scope,                // Push a checking scope.
    RecordNode,           // Record the current node.
    RecordChild,          // Record a child of the current node.
    RecordMemRef,         // Record the memref in the current node.
    CaptureGlueInput,     // If the current node has an input glue, save it.
    MoveChild,            // Move current node to specified child.
    MoveParent,           // Move current node to parent.

    // Predicate checking.
    CheckSame,            // Fail if not same as prev match.
    CheckChildSame,       // Fail if child not same as prev match.
    CheckPatternPredicate,
    CheckPredicate,       // Fail if node predicate fails.
    CheckOpcode,          // Fail if not opcode.
    SwitchOpcode,         // Dispatch based on opcode.
    CheckType,            // Fail if not correct type.
    SwitchType,           // Dispatch based on type.
    CheckChildType,       // Fail if child has wrong type.
    CheckInteger,         // Fail if wrong val.
    CheckChildInteger,    // Fail if child is wrong val.
    CheckCondCode,        // Fail if not condcode.
    CheckValueType,
    CheckComplexPat,
    CheckAndImm,
    CheckOrImm,
    CheckFoldableChainNode,

    // Node creation/emisssion.
    EmitInteger,          // Create a TargetConstant
    EmitStringInteger,    // Create a TargetConstant from a string.
    EmitRegister,         // Create a register.
    EmitConvertToTarget,  // Convert a imm/fpimm to target imm/fpimm
    EmitMergeInputChains, // Merge together a chains for an input.
    EmitCopyToReg,        // Emit a copytoreg into a physreg.
    EmitNode,             // Create a DAG node
    EmitNodeXForm,        // Run a SDNodeXForm
    MarkGlueResults,      // Indicate which interior nodes have glue results.
    CompleteMatch,        // Finish a match and update the results.
    MorphNodeTo           // Build a node, finish a match and update results.
  };
  const KindTy Kind;

protected:
  Matcher(KindTy K) : Kind(K) {}
public:
  virtual ~Matcher() {}

  KindTy getKind() const { return Kind; }

  Matcher *getNext() { return Next.get(); }
  const Matcher *getNext() const { return Next.get(); }
  void setNext(Matcher *C) { Next.reset(C); }
  Matcher *takeNext() { return Next.release(); }

  std::unique_ptr<Matcher> &getNextPtr() { return Next; }

  bool isEqual(const Matcher *M) const {
    if (getKind() != M->getKind()) return false;
    return isEqualImpl(M);
  }

  unsigned getHash() const {
    // Clear the high bit so we don't conflict with tombstones etc.
    return ((getHashImpl() << 4) ^ getKind()) & (~0U>>1);
  }

  /// isSafeToReorderWithPatternPredicate - Return true if it is safe to sink a
  /// PatternPredicate node past this one.
  virtual bool isSafeToReorderWithPatternPredicate() const {
    return false;
  }

  /// isSimplePredicateNode - Return true if this is a simple predicate that
  /// operates on the node or its children without potential side effects or a
  /// change of the current node.
  bool isSimplePredicateNode() const {
    switch (getKind()) {
    default: return false;
    case CheckSame:
    case CheckChildSame:
    case CheckPatternPredicate:
    case CheckPredicate:
    case CheckOpcode:
    case CheckType:
    case CheckChildType:
    case CheckInteger:
    case CheckChildInteger:
    case CheckCondCode:
    case CheckValueType:
    case CheckAndImm:
    case CheckOrImm:
    case CheckFoldableChainNode:
      return true;
    }
  }

  /// isSimplePredicateOrRecordNode - Return true if this is a record node or
  /// a simple predicate.
  bool isSimplePredicateOrRecordNode() const {
    return isSimplePredicateNode() ||
           getKind() == RecordNode || getKind() == RecordChild;
  }

  /// unlinkNode - Unlink the specified node from this chain.  If Other == this,
  /// we unlink the next pointer and return it.  Otherwise we unlink Other from
  /// the list and return this.
  Matcher *unlinkNode(Matcher *Other);

  /// canMoveBefore - Return true if this matcher is the same as Other, or if
  /// we can move this matcher past all of the nodes in-between Other and this
  /// node.  Other must be equal to or before this.
  bool canMoveBefore(const Matcher *Other) const;

  /// canMoveBeforeNode - Return true if it is safe to move the current matcher
  /// across the specified one.
  bool canMoveBeforeNode(const Matcher *Other) const;

  /// isContradictory - Return true of these two matchers could never match on
  /// the same node.
  bool isContradictory(const Matcher *Other) const {
    // Since this predicate is reflexive, we canonicalize the ordering so that
    // we always match a node against nodes with kinds that are greater or equal
    // to them.  For example, we'll pass in a CheckType node as an argument to
    // the CheckOpcode method, not the other way around.
    if (getKind() < Other->getKind())
      return isContradictoryImpl(Other);
    return Other->isContradictoryImpl(this);
  }

  void print(raw_ostream &OS, unsigned indent = 0) const;
  void printOne(raw_ostream &OS) const;
  void dump() const;
protected:
  virtual void printImpl(raw_ostream &OS, unsigned indent) const = 0;
  virtual bool isEqualImpl(const Matcher *M) const = 0;
  virtual unsigned getHashImpl() const = 0;
  virtual bool isContradictoryImpl(const Matcher *M) const { return false; }
};

/// ScopeMatcher - This attempts to match each of its children to find the first
/// one that successfully matches.  If one child fails, it tries the next child.
/// If none of the children match then this check fails.  It never has a 'next'.
class ScopeMatcher : public Matcher {
  SmallVector<Matcher*, 4> Children;
public:
  ScopeMatcher(ArrayRef<Matcher *> children)
    : Matcher(Scope), Children(children.begin(), children.end()) {
  }
  ~ScopeMatcher() override;

  unsigned getNumChildren() const { return Children.size(); }

  Matcher *getChild(unsigned i) { return Children[i]; }
  const Matcher *getChild(unsigned i) const { return Children[i]; }

  void resetChild(unsigned i, Matcher *N) {
    delete Children[i];
    Children[i] = N;
  }

  Matcher *takeChild(unsigned i) {
    Matcher *Res = Children[i];
    Children[i] = nullptr;
    return Res;
  }

  void setNumChildren(unsigned NC) {
    if (NC < Children.size()) {
      // delete any children we're about to lose pointers to.
      for (unsigned i = NC, e = Children.size(); i != e; ++i)
        delete Children[i];
    }
    Children.resize(NC);
  }

  static inline bool classof(const Matcher *N) {
    return N->getKind() == Scope;
  }

private:
  void printImpl(raw_ostream &OS, unsigned indent) const override;
  bool isEqualImpl(const Matcher *M) const override { return false; }
  unsigned getHashImpl() const override { return 12312; }
};

/// RecordMatcher - Save the current node in the operand list.
class RecordMatcher : public Matcher {
  /// WhatFor - This is a string indicating why we're recording this.  This
  /// should only be used for comment generation not anything semantic.
  std::string WhatFor;

  /// ResultNo - The slot number in the RecordedNodes vector that this will be,
  /// just printed as a comment.
  unsigned ResultNo;
public:
  RecordMatcher(const std::string &whatfor, unsigned resultNo)
    : Matcher(RecordNode), WhatFor(whatfor), ResultNo(resultNo) {}

  const std::string &getWhatFor() const { return WhatFor; }
  unsigned getResultNo() const { return ResultNo; }

  static inline bool classof(const Matcher *N) {
    return N->getKind() == RecordNode;
  }

  bool isSafeToReorderWithPatternPredicate() const override { return true; }
private:
  void printImpl(raw_ostream &OS, unsigned indent) const override;
  bool isEqualImpl(const Matcher *M) const override { return true; }
  unsigned getHashImpl() const override { return 0; }
};

/// RecordChildMatcher - Save a numbered child of the current node, or fail
/// the match if it doesn't exist.  This is logically equivalent to:
///    MoveChild N + RecordNode + MoveParent.
class RecordChildMatcher : public Matcher {
  unsigned ChildNo;

  /// WhatFor - This is a string indicating why we're recording this.  This
  /// should only be used for comment generation not anything semantic.
  std::string WhatFor;

  /// ResultNo - The slot number in the RecordedNodes vector that this will be,
  /// just printed as a comment.
  unsigned ResultNo;
public:
  RecordChildMatcher(unsigned childno, const std::string &whatfor,
                     unsigned resultNo)
  : Matcher(RecordChild), ChildNo(childno), WhatFor(whatfor),
    ResultNo(resultNo) {}

  unsigned getChildNo() const { return ChildNo; }
  const std::string &getWhatFor() const { return WhatFor; }
  unsigned getResultNo() const { return ResultNo; }

  static inline bool classof(const Matcher *N) {
    return N->getKind() == RecordChild;
  }

  bool isSafeToReorderWithPatternPredicate() const override { return true; }

private:
  void printImpl(raw_ostream &OS, unsigned indent) const override;
  bool isEqualImpl(const Matcher *M) const override {
    return cast<RecordChildMatcher>(M)->getChildNo() == getChildNo();
  }
  unsigned getHashImpl() const override { return getChildNo(); }
};

/// RecordMemRefMatcher - Save the current node's memref.
class RecordMemRefMatcher : public Matcher {
public:
  RecordMemRefMatcher() : Matcher(RecordMemRef) {}

  static inline bool classof(const Matcher *N) {
    return N->getKind() == RecordMemRef;
  }

  bool isSafeToReorderWithPatternPredicate() const override { return true; }

private:
  void printImpl(raw_ostream &OS, unsigned indent) const override;
  bool isEqualImpl(const Matcher *M) const override { return true; }
  unsigned getHashImpl() const override { return 0; }
};


/// CaptureGlueInputMatcher - If the current record has a glue input, record
/// it so that it is used as an input to the generated code.
class CaptureGlueInputMatcher : public Matcher {
public:
  CaptureGlueInputMatcher() : Matcher(CaptureGlueInput) {}

  static inline bool classof(const Matcher *N) {
    return N->getKind() == CaptureGlueInput;
  }

  bool isSafeToReorderWithPatternPredicate() const override { return true; }

private:
  void printImpl(raw_ostream &OS, unsigned indent) const override;
  bool isEqualImpl(const Matcher *M) const override { return true; }
  unsigned getHashImpl() const override { return 0; }
};

/// MoveChildMatcher - This tells the interpreter to move into the
/// specified child node.
class MoveChildMatcher : public Matcher {
  unsigned ChildNo;
public:
  MoveChildMatcher(unsigned childNo) : Matcher(MoveChild), ChildNo(childNo) {}

  unsigned getChildNo() const { return ChildNo; }

  static inline bool classof(const Matcher *N) {
    return N->getKind() == MoveChild;
  }

  bool isSafeToReorderWithPatternPredicate() const override { return true; }

private:
  void printImpl(raw_ostream &OS, unsigned indent) const override;
  bool isEqualImpl(const Matcher *M) const override {
    return cast<MoveChildMatcher>(M)->getChildNo() == getChildNo();
  }
  unsigned getHashImpl() const override { return getChildNo(); }
};

/// MoveParentMatcher - This tells the interpreter to move to the parent
/// of the current node.
class MoveParentMatcher : public Matcher {
public:
  MoveParentMatcher() : Matcher(MoveParent) {}

  static inline bool classof(const Matcher *N) {
    return N->getKind() == MoveParent;
  }

  bool isSafeToReorderWithPatternPredicate() const override { return true; }

private:
  void printImpl(raw_ostream &OS, unsigned indent) const override;
  bool isEqualImpl(const Matcher *M) const override { return true; }
  unsigned getHashImpl() const override { return 0; }
};

/// CheckSameMatcher - This checks to see if this node is exactly the same
/// node as the specified match that was recorded with 'Record'.  This is used
/// when patterns have the same name in them, like '(mul GPR:$in, GPR:$in)'.
class CheckSameMatcher : public Matcher {
  unsigned MatchNumber;
public:
  CheckSameMatcher(unsigned matchnumber)
    : Matcher(CheckSame), MatchNumber(matchnumber) {}

  unsigned getMatchNumber() const { return MatchNumber; }

  static inline bool classof(const Matcher *N) {
    return N->getKind() == CheckSame;
  }

  bool isSafeToReorderWithPatternPredicate() const override { return true; }

private:
  void printImpl(raw_ostream &OS, unsigned indent) const override;
  bool isEqualImpl(const Matcher *M) const override {
    return cast<CheckSameMatcher>(M)->getMatchNumber() == getMatchNumber();
  }
  unsigned getHashImpl() const override { return getMatchNumber(); }
};

/// CheckChildSameMatcher - This checks to see if child node is exactly the same
/// node as the specified match that was recorded with 'Record'.  This is used
/// when patterns have the same name in them, like '(mul GPR:$in, GPR:$in)'.
class CheckChildSameMatcher : public Matcher {
  unsigned ChildNo;
  unsigned MatchNumber;
public:
  CheckChildSameMatcher(unsigned childno, unsigned matchnumber)
    : Matcher(CheckChildSame), ChildNo(childno), MatchNumber(matchnumber) {}

  unsigned getChildNo() const { return ChildNo; }
  unsigned getMatchNumber() const { return MatchNumber; }

  static inline bool classof(const Matcher *N) {
    return N->getKind() == CheckChildSame;
  }

  bool isSafeToReorderWithPatternPredicate() const override { return true; }

private:
  void printImpl(raw_ostream &OS, unsigned indent) const override;
  bool isEqualImpl(const Matcher *M) const override {
    return cast<CheckChildSameMatcher>(M)->ChildNo == ChildNo &&
           cast<CheckChildSameMatcher>(M)->MatchNumber == MatchNumber;
  }
  unsigned getHashImpl() const override { return (MatchNumber << 2) | ChildNo; }
};

/// CheckPatternPredicateMatcher - This checks the target-specific predicate
/// to see if the entire pattern is capable of matching.  This predicate does
/// not take a node as input.  This is used for subtarget feature checks etc.
class CheckPatternPredicateMatcher : public Matcher {
  std::string Predicate;
public:
  CheckPatternPredicateMatcher(StringRef predicate)
    : Matcher(CheckPatternPredicate), Predicate(predicate) {}

  StringRef getPredicate() const { return Predicate; }

  static inline bool classof(const Matcher *N) {
    return N->getKind() == CheckPatternPredicate;
  }

  bool isSafeToReorderWithPatternPredicate() const override { return true; }

private:
  void printImpl(raw_ostream &OS, unsigned indent) const override;
  bool isEqualImpl(const Matcher *M) const override {
    return cast<CheckPatternPredicateMatcher>(M)->getPredicate() == Predicate;
  }
  unsigned getHashImpl() const override;
};

/// CheckPredicateMatcher - This checks the target-specific predicate to
/// see if the node is acceptable.
class CheckPredicateMatcher : public Matcher {
  TreePattern *Pred;
public:
  CheckPredicateMatcher(const TreePredicateFn &pred);

  TreePredicateFn getPredicate() const;

  static inline bool classof(const Matcher *N) {
    return N->getKind() == CheckPredicate;
  }

  // TODO: Ok?
  //virtual bool isSafeToReorderWithPatternPredicate() const { return true; }

private:
  void printImpl(raw_ostream &OS, unsigned indent) const override;
  bool isEqualImpl(const Matcher *M) const override {
    return cast<CheckPredicateMatcher>(M)->Pred == Pred;
  }
  unsigned getHashImpl() const override;
};


/// CheckOpcodeMatcher - This checks to see if the current node has the
/// specified opcode, if not it fails to match.
class CheckOpcodeMatcher : public Matcher {
  const SDNodeInfo &Opcode;
public:
  CheckOpcodeMatcher(const SDNodeInfo &opcode)
    : Matcher(CheckOpcode), Opcode(opcode) {}

  const SDNodeInfo &getOpcode() const { return Opcode; }

  static inline bool classof(const Matcher *N) {
    return N->getKind() == CheckOpcode;
  }

  bool isSafeToReorderWithPatternPredicate() const override { return true; }

private:
  void printImpl(raw_ostream &OS, unsigned indent) const override;
  bool isEqualImpl(const Matcher *M) const override;
  unsigned getHashImpl() const override;
  bool isContradictoryImpl(const Matcher *M) const override;
};

/// SwitchOpcodeMatcher - Switch based on the current node's opcode, dispatching
/// to one matcher per opcode.  If the opcode doesn't match any of the cases,
/// then the match fails.  This is semantically equivalent to a Scope node where
/// every child does a CheckOpcode, but is much faster.
class SwitchOpcodeMatcher : public Matcher {
  SmallVector<std::pair<const SDNodeInfo*, Matcher*>, 8> Cases;
public:
  SwitchOpcodeMatcher(ArrayRef<std::pair<const SDNodeInfo*, Matcher*> > cases)
    : Matcher(SwitchOpcode), Cases(cases.begin(), cases.end()) {}
  ~SwitchOpcodeMatcher() override;

  static inline bool classof(const Matcher *N) {
    return N->getKind() == SwitchOpcode;
  }

  unsigned getNumCases() const { return Cases.size(); }

  const SDNodeInfo &getCaseOpcode(unsigned i) const { return *Cases[i].first; }
  Matcher *getCaseMatcher(unsigned i) { return Cases[i].second; }
  const Matcher *getCaseMatcher(unsigned i) const { return Cases[i].second; }

private:
  void printImpl(raw_ostream &OS, unsigned indent) const override;
  bool isEqualImpl(const Matcher *M) const override { return false; }
  unsigned getHashImpl() const override { return 4123; }
};

/// CheckTypeMatcher - This checks to see if the current node has the
/// specified type at the specified result, if not it fails to match.
class CheckTypeMatcher : public Matcher {
  MVT::SimpleValueType Type;
  unsigned ResNo;
public:
  CheckTypeMatcher(MVT::SimpleValueType type, unsigned resno)
    : Matcher(CheckType), Type(type), ResNo(resno) {}

  MVT::SimpleValueType getType() const { return Type; }
  unsigned getResNo() const { return ResNo; }

  static inline bool classof(const Matcher *N) {
    return N->getKind() == CheckType;
  }

  bool isSafeToReorderWithPatternPredicate() const override { return true; }

private:
  void printImpl(raw_ostream &OS, unsigned indent) const override;
  bool isEqualImpl(const Matcher *M) const override {
    return cast<CheckTypeMatcher>(M)->Type == Type;
  }
  unsigned getHashImpl() const override { return Type; }
  bool isContradictoryImpl(const Matcher *M) const override;
};

/// SwitchTypeMatcher - Switch based on the current node's type, dispatching
/// to one matcher per case.  If the type doesn't match any of the cases,
/// then the match fails.  This is semantically equivalent to a Scope node where
/// every child does a CheckType, but is much faster.
class SwitchTypeMatcher : public Matcher {
  SmallVector<std::pair<MVT::SimpleValueType, Matcher*>, 8> Cases;
public:
  SwitchTypeMatcher(ArrayRef<std::pair<MVT::SimpleValueType, Matcher*> > cases)
  : Matcher(SwitchType), Cases(cases.begin(), cases.end()) {}
  ~SwitchTypeMatcher() override;

  static inline bool classof(const Matcher *N) {
    return N->getKind() == SwitchType;
  }

  unsigned getNumCases() const { return Cases.size(); }

  MVT::SimpleValueType getCaseType(unsigned i) const { return Cases[i].first; }
  Matcher *getCaseMatcher(unsigned i) { return Cases[i].second; }
  const Matcher *getCaseMatcher(unsigned i) const { return Cases[i].second; }

private:
  void printImpl(raw_ostream &OS, unsigned indent) const override;
  bool isEqualImpl(const Matcher *M) const override { return false; }
  unsigned getHashImpl() const override { return 4123; }
};


/// CheckChildTypeMatcher - This checks to see if a child node has the
/// specified type, if not it fails to match.
class CheckChildTypeMatcher : public Matcher {
  unsigned ChildNo;
  MVT::SimpleValueType Type;
public:
  CheckChildTypeMatcher(unsigned childno, MVT::SimpleValueType type)
    : Matcher(CheckChildType), ChildNo(childno), Type(type) {}

  unsigned getChildNo() const { return ChildNo; }
  MVT::SimpleValueType getType() const { return Type; }

  static inline bool classof(const Matcher *N) {
    return N->getKind() == CheckChildType;
  }

  bool isSafeToReorderWithPatternPredicate() const override { return true; }

private:
  void printImpl(raw_ostream &OS, unsigned indent) const override;
  bool isEqualImpl(const Matcher *M) const override {
    return cast<CheckChildTypeMatcher>(M)->ChildNo == ChildNo &&
           cast<CheckChildTypeMatcher>(M)->Type == Type;
  }
  unsigned getHashImpl() const override { return (Type << 3) | ChildNo; }
  bool isContradictoryImpl(const Matcher *M) const override;
};


/// CheckIntegerMatcher - This checks to see if the current node is a
/// ConstantSDNode with the specified integer value, if not it fails to match.
class CheckIntegerMatcher : public Matcher {
  int64_t Value;
public:
  CheckIntegerMatcher(int64_t value)
    : Matcher(CheckInteger), Value(value) {}

  int64_t getValue() const { return Value; }

  static inline bool classof(const Matcher *N) {
    return N->getKind() == CheckInteger;
  }

  bool isSafeToReorderWithPatternPredicate() const override { return true; }

private:
  void printImpl(raw_ostream &OS, unsigned indent) const override;
  bool isEqualImpl(const Matcher *M) const override {
    return cast<CheckIntegerMatcher>(M)->Value == Value;
  }
  unsigned getHashImpl() const override { return Value; }
  bool isContradictoryImpl(const Matcher *M) const override;
};

/// CheckChildIntegerMatcher - This checks to see if the child node is a
/// ConstantSDNode with a specified integer value, if not it fails to match.
class CheckChildIntegerMatcher : public Matcher {
  unsigned ChildNo;
  int64_t Value;
public:
  CheckChildIntegerMatcher(unsigned childno, int64_t value)
    : Matcher(CheckChildInteger), ChildNo(childno), Value(value) {}

  unsigned getChildNo() const { return ChildNo; }
  int64_t getValue() const { return Value; }

  static inline bool classof(const Matcher *N) {
    return N->getKind() == CheckChildInteger;
  }

  bool isSafeToReorderWithPatternPredicate() const override { return true; }

private:
  void printImpl(raw_ostream &OS, unsigned indent) const override;
  bool isEqualImpl(const Matcher *M) const override {
    return cast<CheckChildIntegerMatcher>(M)->ChildNo == ChildNo &&
           cast<CheckChildIntegerMatcher>(M)->Value == Value;
  }
  unsigned getHashImpl() const override { return (Value << 3) | ChildNo; }
  bool isContradictoryImpl(const Matcher *M) const override;
};

/// CheckCondCodeMatcher - This checks to see if the current node is a
/// CondCodeSDNode with the specified condition, if not it fails to match.
class CheckCondCodeMatcher : public Matcher {
  StringRef CondCodeName;
public:
  CheckCondCodeMatcher(StringRef condcodename)
    : Matcher(CheckCondCode), CondCodeName(condcodename) {}

  StringRef getCondCodeName() const { return CondCodeName; }

  static inline bool classof(const Matcher *N) {
    return N->getKind() == CheckCondCode;
  }

  bool isSafeToReorderWithPatternPredicate() const override { return true; }

private:
  void printImpl(raw_ostream &OS, unsigned indent) const override;
  bool isEqualImpl(const Matcher *M) const override {
    return cast<CheckCondCodeMatcher>(M)->CondCodeName == CondCodeName;
  }
  unsigned getHashImpl() const override;
};

/// CheckValueTypeMatcher - This checks to see if the current node is a
/// VTSDNode with the specified type, if not it fails to match.
class CheckValueTypeMatcher : public Matcher {
  StringRef TypeName;
public:
  CheckValueTypeMatcher(StringRef type_name)
    : Matcher(CheckValueType), TypeName(type_name) {}

  StringRef getTypeName() const { return TypeName; }

  static inline bool classof(const Matcher *N) {
    return N->getKind() == CheckValueType;
  }

  bool isSafeToReorderWithPatternPredicate() const override { return true; }

private:
  void printImpl(raw_ostream &OS, unsigned indent) const override;
  bool isEqualImpl(const Matcher *M) const override {
    return cast<CheckValueTypeMatcher>(M)->TypeName == TypeName;
  }
  unsigned getHashImpl() const override;
  bool isContradictoryImpl(const Matcher *M) const override;
};



/// CheckComplexPatMatcher - This node runs the specified ComplexPattern on
/// the current node.
class CheckComplexPatMatcher : public Matcher {
  const ComplexPattern &Pattern;

  /// MatchNumber - This is the recorded nodes slot that contains the node we
  /// want to match against.
  unsigned MatchNumber;

  /// Name - The name of the node we're matching, for comment emission.
  std::string Name;

  /// FirstResult - This is the first slot in the RecordedNodes list that the
  /// result of the match populates.
  unsigned FirstResult;
public:
  CheckComplexPatMatcher(const ComplexPattern &pattern, unsigned matchnumber,
                         const std::string &name, unsigned firstresult)
    : Matcher(CheckComplexPat), Pattern(pattern), MatchNumber(matchnumber),
      Name(name), FirstResult(firstresult) {}

  const ComplexPattern &getPattern() const { return Pattern; }
  unsigned getMatchNumber() const { return MatchNumber; }

  const std::string getName() const { return Name; }
  unsigned getFirstResult() const { return FirstResult; }

  static inline bool classof(const Matcher *N) {
    return N->getKind() == CheckComplexPat;
  }

  // Not safe to move a pattern predicate past a complex pattern.
  bool isSafeToReorderWithPatternPredicate() const override { return false; }

private:
  void printImpl(raw_ostream &OS, unsigned indent) const override;
  bool isEqualImpl(const Matcher *M) const override {
    return &cast<CheckComplexPatMatcher>(M)->Pattern == &Pattern &&
           cast<CheckComplexPatMatcher>(M)->MatchNumber == MatchNumber;
  }
  unsigned getHashImpl() const override {
    return (unsigned)(intptr_t)&Pattern ^ MatchNumber;
  }
};

/// CheckAndImmMatcher - This checks to see if the current node is an 'and'
/// with something equivalent to the specified immediate.
class CheckAndImmMatcher : public Matcher {
  int64_t Value;
public:
  CheckAndImmMatcher(int64_t value)
    : Matcher(CheckAndImm), Value(value) {}

  int64_t getValue() const { return Value; }

  static inline bool classof(const Matcher *N) {
    return N->getKind() == CheckAndImm;
  }

  bool isSafeToReorderWithPatternPredicate() const override { return true; }

private:
  void printImpl(raw_ostream &OS, unsigned indent) const override;
  bool isEqualImpl(const Matcher *M) const override {
    return cast<CheckAndImmMatcher>(M)->Value == Value;
  }
  unsigned getHashImpl() const override { return Value; }
};

/// CheckOrImmMatcher - This checks to see if the current node is an 'and'
/// with something equivalent to the specified immediate.
class CheckOrImmMatcher : public Matcher {
  int64_t Value;
public:
  CheckOrImmMatcher(int64_t value)
    : Matcher(CheckOrImm), Value(value) {}

  int64_t getValue() const { return Value; }

  static inline bool classof(const Matcher *N) {
    return N->getKind() == CheckOrImm;
  }

  bool isSafeToReorderWithPatternPredicate() const override { return true; }

private:
  void printImpl(raw_ostream &OS, unsigned indent) const override;
  bool isEqualImpl(const Matcher *M) const override {
    return cast<CheckOrImmMatcher>(M)->Value == Value;
  }
  unsigned getHashImpl() const override { return Value; }
};

/// CheckFoldableChainNodeMatcher - This checks to see if the current node
/// (which defines a chain operand) is safe to fold into a larger pattern.
class CheckFoldableChainNodeMatcher : public Matcher {
public:
  CheckFoldableChainNodeMatcher()
    : Matcher(CheckFoldableChainNode) {}

  static inline bool classof(const Matcher *N) {
    return N->getKind() == CheckFoldableChainNode;
  }

  bool isSafeToReorderWithPatternPredicate() const override { return true; }

private:
  void printImpl(raw_ostream &OS, unsigned indent) const override;
  bool isEqualImpl(const Matcher *M) const override { return true; }
  unsigned getHashImpl() const override { return 0; }
};

/// EmitIntegerMatcher - This creates a new TargetConstant.
class EmitIntegerMatcher : public Matcher {
  int64_t Val;
  MVT::SimpleValueType VT;
public:
  EmitIntegerMatcher(int64_t val, MVT::SimpleValueType vt)
    : Matcher(EmitInteger), Val(val), VT(vt) {}

  int64_t getValue() const { return Val; }
  MVT::SimpleValueType getVT() const { return VT; }

  static inline bool classof(const Matcher *N) {
    return N->getKind() == EmitInteger;
  }

private:
  void printImpl(raw_ostream &OS, unsigned indent) const override;
  bool isEqualImpl(const Matcher *M) const override {
    return cast<EmitIntegerMatcher>(M)->Val == Val &&
           cast<EmitIntegerMatcher>(M)->VT == VT;
  }
  unsigned getHashImpl() const override { return (Val << 4) | VT; }
};

/// EmitStringIntegerMatcher - A target constant whose value is represented
/// by a string.
class EmitStringIntegerMatcher : public Matcher {
  std::string Val;
  MVT::SimpleValueType VT;
public:
  EmitStringIntegerMatcher(const std::string &val, MVT::SimpleValueType vt)
    : Matcher(EmitStringInteger), Val(val), VT(vt) {}

  const std::string &getValue() const { return Val; }
  MVT::SimpleValueType getVT() const { return VT; }

  static inline bool classof(const Matcher *N) {
    return N->getKind() == EmitStringInteger;
  }

private:
  void printImpl(raw_ostream &OS, unsigned indent) const override;
  bool isEqualImpl(const Matcher *M) const override {
    return cast<EmitStringIntegerMatcher>(M)->Val == Val &&
           cast<EmitStringIntegerMatcher>(M)->VT == VT;
  }
  unsigned getHashImpl() const override;
};

/// EmitRegisterMatcher - This creates a new TargetConstant.
class EmitRegisterMatcher : public Matcher {
  /// Reg - The def for the register that we're emitting.  If this is null, then
  /// this is a reference to zero_reg.
  const CodeGenRegister *Reg;
  MVT::SimpleValueType VT;
public:
  EmitRegisterMatcher(const CodeGenRegister *reg, MVT::SimpleValueType vt)
    : Matcher(EmitRegister), Reg(reg), VT(vt) {}

  const CodeGenRegister *getReg() const { return Reg; }
  MVT::SimpleValueType getVT() const { return VT; }

  static inline bool classof(const Matcher *N) {
    return N->getKind() == EmitRegister;
  }

private:
  void printImpl(raw_ostream &OS, unsigned indent) const override;
  bool isEqualImpl(const Matcher *M) const override {
    return cast<EmitRegisterMatcher>(M)->Reg == Reg &&
           cast<EmitRegisterMatcher>(M)->VT == VT;
  }
  unsigned getHashImpl() const override {
    return ((unsigned)(intptr_t)Reg) << 4 | VT;
  }
};

/// EmitConvertToTargetMatcher - Emit an operation that reads a specified
/// recorded node and converts it from being a ISD::Constant to
/// ISD::TargetConstant, likewise for ConstantFP.
class EmitConvertToTargetMatcher : public Matcher {
  unsigned Slot;
public:
  EmitConvertToTargetMatcher(unsigned slot)
    : Matcher(EmitConvertToTarget), Slot(slot) {}

  unsigned getSlot() const { return Slot; }

  static inline bool classof(const Matcher *N) {
    return N->getKind() == EmitConvertToTarget;
  }

private:
  void printImpl(raw_ostream &OS, unsigned indent) const override;
  bool isEqualImpl(const Matcher *M) const override {
    return cast<EmitConvertToTargetMatcher>(M)->Slot == Slot;
  }
  unsigned getHashImpl() const override { return Slot; }
};

/// EmitMergeInputChainsMatcher - Emit a node that merges a list of input
/// chains together with a token factor.  The list of nodes are the nodes in the
/// matched pattern that have chain input/outputs.  This node adds all input
/// chains of these nodes if they are not themselves a node in the pattern.
class EmitMergeInputChainsMatcher : public Matcher {
  SmallVector<unsigned, 3> ChainNodes;
public:
  EmitMergeInputChainsMatcher(ArrayRef<unsigned> nodes)
    : Matcher(EmitMergeInputChains), ChainNodes(nodes.begin(), nodes.end()) {}

  unsigned getNumNodes() const { return ChainNodes.size(); }

  unsigned getNode(unsigned i) const {
    assert(i < ChainNodes.size());
    return ChainNodes[i];
  }

  static inline bool classof(const Matcher *N) {
    return N->getKind() == EmitMergeInputChains;
  }

private:
  void printImpl(raw_ostream &OS, unsigned indent) const override;
  bool isEqualImpl(const Matcher *M) const override {
    return cast<EmitMergeInputChainsMatcher>(M)->ChainNodes == ChainNodes;
  }
  unsigned getHashImpl() const override;
};

/// EmitCopyToRegMatcher - Emit a CopyToReg node from a value to a physreg,
/// pushing the chain and glue results.
///
class EmitCopyToRegMatcher : public Matcher {
  unsigned SrcSlot; // Value to copy into the physreg.
  Record *DestPhysReg;
public:
  EmitCopyToRegMatcher(unsigned srcSlot, Record *destPhysReg)
    : Matcher(EmitCopyToReg), SrcSlot(srcSlot), DestPhysReg(destPhysReg) {}

  unsigned getSrcSlot() const { return SrcSlot; }
  Record *getDestPhysReg() const { return DestPhysReg; }

  static inline bool classof(const Matcher *N) {
    return N->getKind() == EmitCopyToReg;
  }

private:
  void printImpl(raw_ostream &OS, unsigned indent) const override;
  bool isEqualImpl(const Matcher *M) const override {
    return cast<EmitCopyToRegMatcher>(M)->SrcSlot == SrcSlot &&
           cast<EmitCopyToRegMatcher>(M)->DestPhysReg == DestPhysReg;
  }
  unsigned getHashImpl() const override {
    return SrcSlot ^ ((unsigned)(intptr_t)DestPhysReg << 4);
  }
};



/// EmitNodeXFormMatcher - Emit an operation that runs an SDNodeXForm on a
/// recorded node and records the result.
class EmitNodeXFormMatcher : public Matcher {
  unsigned Slot;
  Record *NodeXForm;
public:
  EmitNodeXFormMatcher(unsigned slot, Record *nodeXForm)
    : Matcher(EmitNodeXForm), Slot(slot), NodeXForm(nodeXForm) {}

  unsigned getSlot() const { return Slot; }
  Record *getNodeXForm() const { return NodeXForm; }

  static inline bool classof(const Matcher *N) {
    return N->getKind() == EmitNodeXForm;
  }

private:
  void printImpl(raw_ostream &OS, unsigned indent) const override;
  bool isEqualImpl(const Matcher *M) const override {
    return cast<EmitNodeXFormMatcher>(M)->Slot == Slot &&
           cast<EmitNodeXFormMatcher>(M)->NodeXForm == NodeXForm;
  }
  unsigned getHashImpl() const override {
    return Slot ^ ((unsigned)(intptr_t)NodeXForm << 4);
  }
};

/// EmitNodeMatcherCommon - Common class shared between EmitNode and
/// MorphNodeTo.
class EmitNodeMatcherCommon : public Matcher {
  std::string OpcodeName;
  const SmallVector<MVT::SimpleValueType, 3> VTs;
  const SmallVector<unsigned, 6> Operands;
  bool HasChain, HasInGlue, HasOutGlue, HasMemRefs;

  /// NumFixedArityOperands - If this is a fixed arity node, this is set to -1.
  /// If this is a varidic node, this is set to the number of fixed arity
  /// operands in the root of the pattern.  The rest are appended to this node.
  int NumFixedArityOperands;
public:
  EmitNodeMatcherCommon(const std::string &opcodeName,
                        ArrayRef<MVT::SimpleValueType> vts,
                        ArrayRef<unsigned> operands,
                        bool hasChain, bool hasInGlue, bool hasOutGlue,
                        bool hasmemrefs,
                        int numfixedarityoperands, bool isMorphNodeTo)
    : Matcher(isMorphNodeTo ? MorphNodeTo : EmitNode), OpcodeName(opcodeName),
      VTs(vts.begin(), vts.end()), Operands(operands.begin(), operands.end()),
      HasChain(hasChain), HasInGlue(hasInGlue), HasOutGlue(hasOutGlue),
      HasMemRefs(hasmemrefs), NumFixedArityOperands(numfixedarityoperands) {}

  const std::string &getOpcodeName() const { return OpcodeName; }

  unsigned getNumVTs() const { return VTs.size(); }
  MVT::SimpleValueType getVT(unsigned i) const {
    assert(i < VTs.size());
    return VTs[i];
  }

  unsigned getNumOperands() const { return Operands.size(); }
  unsigned getOperand(unsigned i) const {
    assert(i < Operands.size());
    return Operands[i];
  }

  const SmallVectorImpl<MVT::SimpleValueType> &getVTList() const { return VTs; }
  const SmallVectorImpl<unsigned> &getOperandList() const { return Operands; }


  bool hasChain() const { return HasChain; }
  bool hasInFlag() const { return HasInGlue; }
  bool hasOutFlag() const { return HasOutGlue; }
  bool hasMemRefs() const { return HasMemRefs; }
  int getNumFixedArityOperands() const { return NumFixedArityOperands; }

  static inline bool classof(const Matcher *N) {
    return N->getKind() == EmitNode || N->getKind() == MorphNodeTo;
  }

private:
  void printImpl(raw_ostream &OS, unsigned indent) const override;
  bool isEqualImpl(const Matcher *M) const override;
  unsigned getHashImpl() const override;
};

/// EmitNodeMatcher - This signals a successful match and generates a node.
class EmitNodeMatcher : public EmitNodeMatcherCommon {
  void anchor() override;
  unsigned FirstResultSlot;
public:
  EmitNodeMatcher(const std::string &opcodeName,
                  ArrayRef<MVT::SimpleValueType> vts,
                  ArrayRef<unsigned> operands,
                  bool hasChain, bool hasInFlag, bool hasOutFlag,
                  bool hasmemrefs,
                  int numfixedarityoperands, unsigned firstresultslot)
  : EmitNodeMatcherCommon(opcodeName, vts, operands, hasChain,
                          hasInFlag, hasOutFlag, hasmemrefs,
                          numfixedarityoperands, false),
    FirstResultSlot(firstresultslot) {}

  unsigned getFirstResultSlot() const { return FirstResultSlot; }

  static inline bool classof(const Matcher *N) {
    return N->getKind() == EmitNode;
  }

};

class MorphNodeToMatcher : public EmitNodeMatcherCommon {
  void anchor() override;
  const PatternToMatch &Pattern;
public:
  MorphNodeToMatcher(const std::string &opcodeName,
                     ArrayRef<MVT::SimpleValueType> vts,
                     ArrayRef<unsigned> operands,
                     bool hasChain, bool hasInFlag, bool hasOutFlag,
                     bool hasmemrefs,
                     int numfixedarityoperands, const PatternToMatch &pattern)
    : EmitNodeMatcherCommon(opcodeName, vts, operands, hasChain,
                            hasInFlag, hasOutFlag, hasmemrefs,
                            numfixedarityoperands, true),
      Pattern(pattern) {
  }

  const PatternToMatch &getPattern() const { return Pattern; }

  static inline bool classof(const Matcher *N) {
    return N->getKind() == MorphNodeTo;
  }
};

/// MarkGlueResultsMatcher - This node indicates which non-root nodes in the
/// pattern produce glue.  This allows CompleteMatchMatcher to update them
/// with the output glue of the resultant code.
class MarkGlueResultsMatcher : public Matcher {
  SmallVector<unsigned, 3> GlueResultNodes;
public:
  MarkGlueResultsMatcher(ArrayRef<unsigned> nodes)
    : Matcher(MarkGlueResults), GlueResultNodes(nodes.begin(), nodes.end()) {}

  unsigned getNumNodes() const { return GlueResultNodes.size(); }

  unsigned getNode(unsigned i) const {
    assert(i < GlueResultNodes.size());
    return GlueResultNodes[i];
  }

  static inline bool classof(const Matcher *N) {
    return N->getKind() == MarkGlueResults;
  }

private:
  void printImpl(raw_ostream &OS, unsigned indent) const override;
  bool isEqualImpl(const Matcher *M) const override {
    return cast<MarkGlueResultsMatcher>(M)->GlueResultNodes == GlueResultNodes;
  }
  unsigned getHashImpl() const override;
};

/// CompleteMatchMatcher - Complete a match by replacing the results of the
/// pattern with the newly generated nodes.  This also prints a comment
/// indicating the source and dest patterns.
class CompleteMatchMatcher : public Matcher {
  SmallVector<unsigned, 2> Results;
  const PatternToMatch &Pattern;
public:
  CompleteMatchMatcher(ArrayRef<unsigned> results,
                       const PatternToMatch &pattern)
  : Matcher(CompleteMatch), Results(results.begin(), results.end()),
    Pattern(pattern) {}

  unsigned getNumResults() const { return Results.size(); }
  unsigned getResult(unsigned R) const { return Results[R]; }
  const PatternToMatch &getPattern() const { return Pattern; }

  static inline bool classof(const Matcher *N) {
    return N->getKind() == CompleteMatch;
  }

private:
  void printImpl(raw_ostream &OS, unsigned indent) const override;
  bool isEqualImpl(const Matcher *M) const override {
    return cast<CompleteMatchMatcher>(M)->Results == Results &&
          &cast<CompleteMatchMatcher>(M)->Pattern == &Pattern;
  }
  unsigned getHashImpl() const override;
};

} // end namespace llvm

#endif
