//===- GIMatchTree.h - A decision tree to match GIMatchDag's --------------===//
//
// 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
//
//===----------------------------------------------------------------------===//

#ifndef LLVM_UTILS_TABLEGEN_GIMATCHTREE_H
#define LLVM_UTILS_TABLEGEN_GIMATCHTREE_H

#include "GIMatchDag.h"
#include "llvm/ADT/BitVector.h"

namespace llvm {
class raw_ostream;

class GIMatchTreeBuilder;
class GIMatchTreePartitioner;

/// Describes the binding of a variable to the matched MIR
class GIMatchTreeVariableBinding {
  /// The name of the variable described by this binding.
  StringRef Name;
  // The matched instruction it is bound to. 
  unsigned InstrID;
  // The matched operand (if appropriate) it is bound to. 
  Optional<unsigned> OpIdx;

public:
  GIMatchTreeVariableBinding(StringRef Name, unsigned InstrID,
                             Optional<unsigned> OpIdx = None)
      : Name(Name), InstrID(InstrID), OpIdx(OpIdx) {}

  bool isInstr() const { return !OpIdx.hasValue(); }
  StringRef getName() const { return Name; }
  unsigned getInstrID() const { return InstrID; }
  unsigned getOpIdx() const {
    assert(OpIdx.hasValue() && "Is not an operand binding");
    return *OpIdx;
  }
};

/// Associates a matchable with a leaf of the decision tree.
class GIMatchTreeLeafInfo {
public:
  using const_var_binding_iterator =
      std::vector<GIMatchTreeVariableBinding>::const_iterator;
  using UntestedPredicatesTy = SmallVector<const GIMatchDagPredicate *, 1>;
  using const_untested_predicates_iterator = UntestedPredicatesTy::const_iterator;

protected:
  /// A name for the matchable. This is primarily for debugging.
  StringRef Name;
  /// Where rules have multiple roots, this is which root we're starting from.
  unsigned RootIdx;
  /// Opaque data the caller of the tree building code understands.
  void *Data;
  /// Has the decision tree covered every edge traversal? If it hasn't then this
  /// is an unrecoverable error indicating there's something wrong with the
  /// partitioners.
  bool IsFullyTraversed;
  /// Has the decision tree covered every predicate test? If it has, then
  /// subsequent matchables on the same leaf are unreachable. If it hasn't, the
  /// code that requested the GIMatchTree is responsible for finishing off any
  /// remaining predicates.
  bool IsFullyTested;
  /// The variable bindings associated with this leaf so far.
  std::vector<GIMatchTreeVariableBinding> VarBindings;
  /// Any predicates left untested by the time we reach this leaf.
  UntestedPredicatesTy UntestedPredicates;

public:
  GIMatchTreeLeafInfo() { llvm_unreachable("Cannot default-construct"); }
  GIMatchTreeLeafInfo(StringRef Name, unsigned RootIdx, void *Data)
      : Name(Name), RootIdx(RootIdx), Data(Data), IsFullyTraversed(false),
        IsFullyTested(false) {}

  StringRef getName() const { return Name; }
  unsigned getRootIdx() const { return RootIdx; }
  template <class Ty> Ty *getTargetData() const {
    return static_cast<Ty *>(Data);
  }
  bool isFullyTraversed() const { return IsFullyTraversed; }
  void setIsFullyTraversed(bool V) { IsFullyTraversed = V; }
  bool isFullyTested() const { return IsFullyTested; }
  void setIsFullyTested(bool V) { IsFullyTested = V; }

  void bindInstrVariable(StringRef Name, unsigned InstrID) {
    VarBindings.emplace_back(Name, InstrID);
  }
  void bindOperandVariable(StringRef Name, unsigned InstrID, unsigned OpIdx) {
    VarBindings.emplace_back(Name, InstrID, OpIdx);
  }

  const_var_binding_iterator var_bindings_begin() const {
    return VarBindings.begin();
  }
  const_var_binding_iterator var_bindings_end() const {
    return VarBindings.end();
  }
  iterator_range<const_var_binding_iterator> var_bindings() const {
    return make_range(VarBindings.begin(), VarBindings.end());
  }
  iterator_range<const_untested_predicates_iterator> untested_predicates() const {
    return make_range(UntestedPredicates.begin(), UntestedPredicates.end());
  }
  void addUntestedPredicate(const GIMatchDagPredicate *P) {
    UntestedPredicates.push_back(P);
  }
};

/// The nodes of a decision tree used to perform the match.
/// This will be used to generate the C++ code or state machine equivalent.
///
/// It should be noted that some nodes of this tree (most notably nodes handling
/// def -> use edges) will need to iterate over several possible matches. As
/// such, code generated from this will sometimes need to support backtracking.
class GIMatchTree {
  using LeafVector = std::vector<GIMatchTreeLeafInfo>;

  /// The partitioner that has been chosen for this node. This may be nullptr if
  /// a partitioner hasn't been chosen yet or if the node is a leaf.
  std::unique_ptr<GIMatchTreePartitioner> Partitioner;
  /// All the leaves that are possible for this node of the tree.
  /// Note: This should be emptied after the tree is built when there are
  /// children but this currently isn't done to aid debuggability of the DOT
  /// graph for the decision tree.
  LeafVector PossibleLeaves;
  /// The children of this node. The index into this array must match the index
  /// chosen by the partitioner.
  std::vector<GIMatchTree> Children;

  void writeDOTGraphNode(raw_ostream &OS) const;
  void writeDOTGraphEdges(raw_ostream &OS) const;

public:
  void writeDOTGraph(raw_ostream &OS) const;

  void setNumChildren(unsigned Num) { Children.resize(Num); }
  void addPossibleLeaf(const GIMatchTreeLeafInfo &V, bool IsFullyTraversed,
                       bool IsFullyTested) {
    PossibleLeaves.push_back(V);
    PossibleLeaves.back().setIsFullyTraversed(IsFullyTraversed);
    PossibleLeaves.back().setIsFullyTested(IsFullyTested);
  }
  void dropLeavesAfter(size_t Length) {
    if (PossibleLeaves.size() > Length)
      PossibleLeaves.resize(Length);
  }
  void setPartitioner(std::unique_ptr<GIMatchTreePartitioner> &&V) {
    Partitioner = std::move(V);
  }
  GIMatchTreePartitioner *getPartitioner() const { return Partitioner.get(); }

  std::vector<GIMatchTree>::iterator children_begin() {
    return Children.begin();
  }
  std::vector<GIMatchTree>::iterator children_end() { return Children.end(); }
  iterator_range<std::vector<GIMatchTree>::iterator> children() {
    return make_range(children_begin(), children_end());
  }
  std::vector<GIMatchTree>::const_iterator children_begin() const {
    return Children.begin();
  }
  std::vector<GIMatchTree>::const_iterator children_end() const {
    return Children.end();
  }
  iterator_range<std::vector<GIMatchTree>::const_iterator> children() const {
    return make_range(children_begin(), children_end());
  }

  LeafVector::const_iterator possible_leaves_begin() const {
    return PossibleLeaves.begin();
  }
  LeafVector::const_iterator possible_leaves_end() const {
    return PossibleLeaves.end();
  }
  iterator_range<LeafVector::const_iterator>
  possible_leaves() const {
    return make_range(possible_leaves_begin(), possible_leaves_end());
  }
  LeafVector::iterator possible_leaves_begin() {
    return PossibleLeaves.begin();
  }
  LeafVector::iterator possible_leaves_end() {
    return PossibleLeaves.end();
  }
  iterator_range<LeafVector::iterator> possible_leaves() {
    return make_range(possible_leaves_begin(), possible_leaves_end());
  }
};

/// Record information that is known about the instruction bound to this ID and
/// GIMatchDagInstrNode. Every rule gets its own set of
/// GIMatchTreeInstrInfo to bind the shared IDs to an instr node in its
/// DAG.
///
/// For example, if we know that there are 3 operands. We can record it here to
/// elide duplicate checks.
class GIMatchTreeInstrInfo {
  /// The instruction ID for the matched instruction.
  unsigned ID;
  /// The corresponding instruction node in the MatchDAG.
  const GIMatchDagInstr *InstrNode;

public:
  GIMatchTreeInstrInfo(unsigned ID, const GIMatchDagInstr *InstrNode)
      : ID(ID), InstrNode(InstrNode) {}

  unsigned getID() const { return ID; }
  const GIMatchDagInstr *getInstrNode() const { return InstrNode; }
};

/// Record information that is known about the operand bound to this ID, OpIdx,
/// and GIMatchDagInstrNode. Every rule gets its own set of
/// GIMatchTreeOperandInfo to bind the shared IDs to an operand of an
/// instr node from its DAG.
///
/// For example, if we know that there the operand is a register. We can record
/// it here to elide duplicate checks.
class GIMatchTreeOperandInfo {
  /// The corresponding instruction node in the MatchDAG that the operand
  /// belongs to.
  const GIMatchDagInstr *InstrNode;
  unsigned OpIdx;

public:
  GIMatchTreeOperandInfo(const GIMatchDagInstr *InstrNode, unsigned OpIdx)
      : InstrNode(InstrNode), OpIdx(OpIdx) {}

  const GIMatchDagInstr *getInstrNode() const { return InstrNode; }
  unsigned getOpIdx() const { return OpIdx; }
};

/// Represent a leaf of the match tree and any working data we need to build the
/// tree.
///
/// It's important to note that each rule can have multiple
/// GIMatchTreeBuilderLeafInfo's since the partitioners do not always partition
/// into mutually-exclusive partitions. For example:
///   R1: (FOO ..., ...)
///   R2: (oneof(FOO, BAR) ..., ...)
/// will partition by opcode into two partitions FOO=>[R1, R2], and BAR=>[R2]
///
/// As an optimization, all instructions, edges, and predicates in the DAGs are
/// numbered and tracked in BitVectors. As such, the GIMatchDAG must not be
/// modified once construction of the tree has begun.
class GIMatchTreeBuilderLeafInfo {
protected:
  GIMatchTreeBuilder &Builder;
  GIMatchTreeLeafInfo Info;
  const GIMatchDag &MatchDag;
  /// The association between GIMatchDagInstr* and GIMatchTreeInstrInfo.
  /// The primary reason for this members existence is to allow the use of
  /// InstrIDToInfo.lookup() since that requires that the value is
  /// default-constructible.
  DenseMap<const GIMatchDagInstr *, GIMatchTreeInstrInfo> InstrNodeToInfo;
  /// The instruction information for a given ID in the context of this
  /// particular leaf.
  DenseMap<unsigned, GIMatchTreeInstrInfo *> InstrIDToInfo;
  /// The operand information for a given ID and OpIdx in the context of this
  /// particular leaf.
  DenseMap<std::pair<unsigned, unsigned>, GIMatchTreeOperandInfo>
      OperandIDToInfo;

public:
  /// The remaining instrs/edges/predicates to visit
  BitVector RemainingInstrNodes;
  BitVector RemainingEdges;
  BitVector RemainingPredicates;

  // The remaining predicate dependencies for each predicate
  std::vector<BitVector> UnsatisfiedPredDepsForPred;

  /// The edges/predicates we can visit as a result of the declare*() calls we
  /// have already made. We don't need an instrs version since edges imply the
  /// instr.
  BitVector TraversableEdges;
  BitVector TestablePredicates;

  /// Map predicates from the DAG to their position in the DAG predicate
  /// iterators.
  DenseMap<GIMatchDagPredicate *, unsigned> PredicateIDs;
  /// Map predicate dependency edges from the DAG to their position in the DAG
  /// predicate dependency iterators.
  DenseMap<GIMatchDagPredicateDependencyEdge *, unsigned> PredicateDepIDs;

public:
  GIMatchTreeBuilderLeafInfo(GIMatchTreeBuilder &Builder, StringRef Name,
                             unsigned RootIdx, const GIMatchDag &MatchDag,
                             void *Data);

  StringRef getName() const { return Info.getName(); }
  GIMatchTreeLeafInfo &getInfo() { return Info; }
  const GIMatchTreeLeafInfo &getInfo() const { return Info; }
  const GIMatchDag &getMatchDag() const { return MatchDag; }
  unsigned getRootIdx() const { return Info.getRootIdx(); }

  /// Has this DAG been fully traversed. This must be true by the time the tree
  /// builder finishes.
  bool isFullyTraversed() const {
    // We don't need UnsatisfiedPredDepsForPred because RemainingPredicates
    // can't be all-zero without satisfying all the dependencies. The same is
    // almost true for Edges and Instrs but it's possible to have Instrs without
    // Edges.
    return RemainingInstrNodes.none() && RemainingEdges.none();
  }

  /// Has this DAG been fully tested. This hould be true by the time the tree
  /// builder finishes but clients can finish any untested predicates left over
  /// if it's not true.
  bool isFullyTested() const {
    // We don't need UnsatisfiedPredDepsForPred because RemainingPredicates
    // can't be all-zero without satisfying all the dependencies. The same is
    // almost true for Edges and Instrs but it's possible to have Instrs without
    // Edges.
    return RemainingInstrNodes.none() && RemainingEdges.none() &&
           RemainingPredicates.none();
  }

  const GIMatchDagInstr *getInstr(unsigned Idx) const {
    return *(MatchDag.instr_nodes_begin() + Idx);
  }
  const GIMatchDagEdge *getEdge(unsigned Idx) const {
    return *(MatchDag.edges_begin() + Idx);
  }
  GIMatchDagEdge *getEdge(unsigned Idx) {
    return *(MatchDag.edges_begin() + Idx);
  }
  const GIMatchDagPredicate *getPredicate(unsigned Idx) const {
    return *(MatchDag.predicates_begin() + Idx);
  }
  iterator_range<llvm::BitVector::const_set_bits_iterator>
  untested_instrs() const {
    return RemainingInstrNodes.set_bits();
  }
  iterator_range<llvm::BitVector::const_set_bits_iterator>
  untested_edges() const {
    return RemainingEdges.set_bits();
  }
  iterator_range<llvm::BitVector::const_set_bits_iterator>
  untested_predicates() const {
    return RemainingPredicates.set_bits();
  }

  /// Bind an instr node to the given ID and clear any blocking dependencies
  /// that were waiting for it.
  void declareInstr(const GIMatchDagInstr *Instr, unsigned ID);

  /// Bind an operand to the given ID and OpIdx and clear any blocking
  /// dependencies that were waiting for it.
  void declareOperand(unsigned InstrID, unsigned OpIdx);

  GIMatchTreeInstrInfo *getInstrInfo(unsigned ID) const {
    return InstrIDToInfo.lookup(ID);
  }

  void dump(raw_ostream &OS) const {
    OS << "Leaf " << getName() << " for root #" << getRootIdx() << "\n";
    MatchDag.print(OS);
    for (const auto &I : InstrIDToInfo)
      OS << "Declared Instr #" << I.first << "\n";
    for (const auto &I : OperandIDToInfo)
      OS << "Declared Instr #" << I.first.first << ", Op #" << I.first.second
         << "\n";
    OS << RemainingInstrNodes.count() << " untested instrs of "
       << RemainingInstrNodes.size() << "\n";
    OS << RemainingEdges.count() << " untested edges of "
       << RemainingEdges.size() << "\n";
    OS << RemainingPredicates.count() << " untested predicates of "
       << RemainingPredicates.size() << "\n";

    OS << TraversableEdges.count() << " edges could be traversed\n";
    OS << TestablePredicates.count() << " predicates could be tested\n";
  }
};

/// The tree builder has a fairly tough job. It's purpose is to merge all the
/// DAGs from the ruleset into a decision tree that walks all of them
/// simultaneously and identifies the rule that was matched. In addition to
/// that, it also needs to find the most efficient order to make decisions
/// without violating any dependencies and ensure that every DAG covers every
/// instr/edge/predicate.
class GIMatchTreeBuilder {
public:
  using LeafVec = std::vector<GIMatchTreeBuilderLeafInfo>;

protected:
  /// The leaves that the resulting decision tree will distinguish.
  LeafVec Leaves;
  /// The tree node being constructed.
  GIMatchTree *TreeNode;
  /// The builders for each subtree resulting from the current decision.
  std::vector<GIMatchTreeBuilder> SubtreeBuilders;
  /// The possible partitioners we could apply right now.
  std::vector<std::unique_ptr<GIMatchTreePartitioner>> Partitioners;
  /// The next instruction ID to allocate when requested by the chosen
  /// Partitioner.
  unsigned NextInstrID;

  /// Use any context we have stored to cull partitioners that only test things
  /// we already know. At the time of writing, there's no need to do anything
  /// here but it will become important once, for example, there is a
  /// num-operands and an opcode partitioner. This is because applying an opcode
  /// partitioner (usually) makes the number of operands known which makes
  /// additional checking pointless.
  void filterRedundantPartitioners();

  /// Evaluate the available partioners and select the best one at the moment.
  void evaluatePartitioners();

  /// Construct the current tree node.
  void runStep();

public:
  GIMatchTreeBuilder(unsigned NextInstrID) : NextInstrID(NextInstrID) {}
  GIMatchTreeBuilder(GIMatchTree *TreeNode, unsigned NextInstrID)
      : TreeNode(TreeNode), NextInstrID(NextInstrID) {}

  void addLeaf(StringRef Name, unsigned RootIdx, const GIMatchDag &MatchDag,
               void *Data) {
    Leaves.emplace_back(*this, Name, RootIdx, MatchDag, Data);
  }
  void addLeaf(const GIMatchTreeBuilderLeafInfo &L) { Leaves.push_back(L); }
  void addPartitioner(std::unique_ptr<GIMatchTreePartitioner> P) {
    Partitioners.push_back(std::move(P));
  }
  void addPartitionersForInstr(unsigned InstrIdx);
  void addPartitionersForOperand(unsigned InstrID, unsigned OpIdx);

  LeafVec &getPossibleLeaves() { return Leaves; }

  unsigned allocInstrID() { return NextInstrID++; }

  /// Construct the decision tree.
  std::unique_ptr<GIMatchTree> run();
};

/// Partitioners are the core of the tree builder and are unfortunately rather
/// tricky to write.
class GIMatchTreePartitioner {
protected:
  /// The partitions resulting from applying the partitioner to the possible
  /// leaves. The keys must be consecutive integers starting from 0. This can
  /// lead to some unfortunate situations where partitioners test a predicate
  /// and use 0 for success and 1 for failure if the ruleset encounters a
  /// success case first but is necessary to assign the partition to one of the
  /// tree nodes children. As a result, you usually need some kind of
  /// indirection to map the natural keys (e.g. ptrs/bools) to this linear
  /// sequence. The values are a bitvector indicating which leaves belong to
  /// this partition.
  DenseMap<unsigned, BitVector> Partitions;

public:
  virtual ~GIMatchTreePartitioner() {}
  virtual std::unique_ptr<GIMatchTreePartitioner> clone() const = 0;

  /// Determines which partitions the given leaves belong to. A leaf may belong
  /// to multiple partitions in which case it will be duplicated during
  /// applyForPartition().
  ///
  /// This function can be rather complicated. A few particular things to be
  /// aware of include:
  /// * One leaf can be assigned to multiple partitions when there's some
  ///   ambiguity.
  /// * Not all DAG's for the leaves may be able to perform the test. For
  ///   example, the opcode partitiioner must account for one DAG being a
  ///   superset of another such as [(ADD ..., ..., ...)], and [(MUL t, ...,
  ///   ...), (ADD ..., t, ...)]
  /// * Attaching meaning to a particular partition index will generally not
  ///   work due to the '0, 1, ..., n' requirement. You might encounter cases
  ///   where only partition 1 is seen, leaving a missing 0.
  /// * Finding a specific predicate such as the opcode predicate for a specific
  ///   instruction is non-trivial. It's often O(NumPredicates), leading to
  ///   O(NumPredicates*NumRules) when applied to the whole ruleset. The good
  ///   news there is that n is typically small thanks to predicate dependencies
  ///   limiting how many are testable at once. Also, with opcode and type
  ///   predicates being so frequent the value of m drops very fast too. It
  ///   wouldn't be terribly surprising to see a 10k ruleset drop down to an
  ///   average of 100 leaves per partition after a single opcode partitioner.
  /// * The same goes for finding specific edges. The need to traverse them in
  ///   dependency order dramatically limits the search space at any given
  ///   moment.
  /// * If you need to add a leaf to all partitions, make sure you don't forget
  ///   them when adding partitions later.
  virtual void repartition(GIMatchTreeBuilder::LeafVec &Leaves) = 0;

  /// Delegate the leaves for a given partition to the corresponding subbuilder,
  /// update any recorded context for this partition (e.g. allocate instr id's
  /// for instrs recorder by the current node), and clear any blocking
  /// dependencies this partitioner resolved.
  virtual void applyForPartition(unsigned PartitionIdx,
                                 GIMatchTreeBuilder &Builder,
                                 GIMatchTreeBuilder &SubBuilder) = 0;

  /// Return a BitVector indicating which leaves should be transferred to the
  /// specified partition. Note that the same leaf can be indicated for multiple
  /// partitions.
  BitVector getPossibleLeavesForPartition(unsigned Idx) {
    const auto &I = Partitions.find(Idx);
    assert(I != Partitions.end() && "Requested non-existant partition");
    return I->second;
  }

  size_t getNumPartitions() const { return Partitions.size(); }
  size_t getNumLeavesWithDupes() const {
    size_t S = 0;
    for (const auto &P : Partitions)
      S += P.second.size();
    return S;
  }

  /// Emit a brief description of the partitioner suitable for debug printing or
  /// use in a DOT graph.
  virtual void emitDescription(raw_ostream &OS) const = 0;
  /// Emit a label for the given partition suitable for debug printing or use in
  /// a DOT graph.
  virtual void emitPartitionName(raw_ostream &OS, unsigned Idx) const = 0;

  /// Emit a long description of how the partitioner partitions the leaves.
  virtual void emitPartitionResults(raw_ostream &OS) const = 0;

  /// Generate code to select between partitions based on the MIR being matched.
  /// This is typically a switch statement that picks a partition index.
  virtual void generatePartitionSelectorCode(raw_ostream &OS,
                                             StringRef Indent) const = 0;
};

/// Partition according to the opcode of the instruction.
///
/// Numbers CodeGenInstr ptrs for use as partition ID's. One special partition,
/// nullptr, represents the case where the instruction isn't known.
///
/// * If the opcode can be tested and is a single opcode, create the partition
///   for that opcode and assign the leaf to it. This partition no longer needs
///   to test the opcode, and many details about the instruction will usually
///   become known (e.g. number of operands for non-variadic instrs) via the
///   CodeGenInstr ptr.
/// * (not implemented yet) If the opcode can be tested and is a choice of
///   opcodes, then the leaf can be treated like the single-opcode case but must
///   be added to all relevant partitions and not quite as much becomes known as
///   a result. That said, multiple-choice opcodes are likely similar enough
///   (because if they aren't then handling them together makes little sense)
///   that plenty still becomes known. The main implementation issue with this
///   is having a description to represent the commonality between instructions.
/// * If the opcode is not tested, the leaf must be added to all partitions
///   including the wildcard nullptr partition. What becomes known as a result
///   varies between partitions.
/// * If the instruction to be tested is not declared then add the leaf to all
///   partitions. This occurs when we encounter one rule that is a superset of
///   the other and we are still matching the remainder of the superset. The
///   result is that the cases that don't match the superset will match the
///   subset rule, while the ones that do match the superset will match either
///   (which one is algorithm dependent but will usually be the superset).
class GIMatchTreeOpcodePartitioner : public GIMatchTreePartitioner {
  unsigned InstrID;
  DenseMap<const CodeGenInstruction *, unsigned> InstrToPartition;
  std::vector<const CodeGenInstruction *> PartitionToInstr;
  std::vector<BitVector> TestedPredicates;

public:
  GIMatchTreeOpcodePartitioner(unsigned InstrID) : InstrID(InstrID) {}

  std::unique_ptr<GIMatchTreePartitioner> clone() const override {
    return std::make_unique<GIMatchTreeOpcodePartitioner>(*this);
  }

  void emitDescription(raw_ostream &OS) const override {
    OS << "MI[" << InstrID << "].getOpcode()";
  }

  void emitPartitionName(raw_ostream &OS, unsigned Idx) const override;

  void repartition(GIMatchTreeBuilder::LeafVec &Leaves) override;
  void applyForPartition(unsigned Idx, GIMatchTreeBuilder &SubBuilder,
                         GIMatchTreeBuilder &Builder) override;

  void emitPartitionResults(raw_ostream &OS) const override;

  void generatePartitionSelectorCode(raw_ostream &OS,
                                     StringRef Indent) const override;
};

class GIMatchTreeVRegDefPartitioner : public GIMatchTreePartitioner {
  unsigned NewInstrID = -1;
  unsigned InstrID;
  unsigned OpIdx;
  std::vector<BitVector> TraversedEdges;
  DenseMap<unsigned, unsigned> ResultToPartition;
  std::vector<bool> PartitionToResult;

  void addToPartition(bool Result, unsigned LeafIdx);

public:
  GIMatchTreeVRegDefPartitioner(unsigned InstrID, unsigned OpIdx)
      : InstrID(InstrID), OpIdx(OpIdx) {}

  std::unique_ptr<GIMatchTreePartitioner> clone() const override {
    return std::make_unique<GIMatchTreeVRegDefPartitioner>(*this);
  }

  void emitDescription(raw_ostream &OS) const override {
    OS << "MI[" << NewInstrID << "] = getVRegDef(MI[" << InstrID
       << "].getOperand(" << OpIdx << "))";
  }

  void emitPartitionName(raw_ostream &OS, unsigned Idx) const override {
    bool Result = PartitionToResult[Idx];
    if (Result)
      OS << "true";
    else
      OS << "false";
  }

  void repartition(GIMatchTreeBuilder::LeafVec &Leaves) override;
  void applyForPartition(unsigned PartitionIdx, GIMatchTreeBuilder &Builder,
                         GIMatchTreeBuilder &SubBuilder) override;
  void emitPartitionResults(raw_ostream &OS) const override;

  void generatePartitionSelectorCode(raw_ostream &OS,
                                     StringRef Indent) const override;
};

} // end namespace llvm
#endif // ifndef LLVM_UTILS_TABLEGEN_GIMATCHTREE_H
