109467b48Spatrick //===- GIMatchTree.cpp - A decision tree to match GIMatchDag's ------------===//
209467b48Spatrick //
309467b48Spatrick // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
409467b48Spatrick // See https://llvm.org/LICENSE.txt for license information.
509467b48Spatrick // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
609467b48Spatrick //
709467b48Spatrick //===----------------------------------------------------------------------===//
809467b48Spatrick
909467b48Spatrick #include "GIMatchTree.h"
10*d415bd75Srobert #include "GIMatchDagPredicate.h"
1109467b48Spatrick
1209467b48Spatrick #include "../CodeGenInstruction.h"
1309467b48Spatrick
14097a140dSpatrick #include "llvm/Support/Debug.h"
1509467b48Spatrick #include "llvm/Support/Format.h"
1609467b48Spatrick #include "llvm/Support/ScopedPrinter.h"
1709467b48Spatrick #include "llvm/Support/raw_ostream.h"
1809467b48Spatrick #include "llvm/TableGen/Error.h"
1909467b48Spatrick #include "llvm/TableGen/Record.h"
2009467b48Spatrick
2109467b48Spatrick #define DEBUG_TYPE "gimatchtree"
2209467b48Spatrick
2309467b48Spatrick using namespace llvm;
2409467b48Spatrick
writeDOTGraph(raw_ostream & OS) const2509467b48Spatrick void GIMatchTree::writeDOTGraph(raw_ostream &OS) const {
2609467b48Spatrick OS << "digraph \"matchtree\" {\n";
2709467b48Spatrick writeDOTGraphNode(OS);
2809467b48Spatrick OS << "}\n";
2909467b48Spatrick }
3009467b48Spatrick
writeDOTGraphNode(raw_ostream & OS) const3109467b48Spatrick void GIMatchTree::writeDOTGraphNode(raw_ostream &OS) const {
3209467b48Spatrick OS << format(" Node%p", this) << " [shape=record,label=\"{";
3309467b48Spatrick if (Partitioner) {
3409467b48Spatrick Partitioner->emitDescription(OS);
3509467b48Spatrick OS << "|" << Partitioner->getNumPartitions() << " partitions|";
3609467b48Spatrick } else
3709467b48Spatrick OS << "No partitioner|";
3809467b48Spatrick bool IsFullyTraversed = true;
3909467b48Spatrick bool IsFullyTested = true;
4009467b48Spatrick StringRef Separator = "";
4109467b48Spatrick for (const auto &Leaf : PossibleLeaves) {
4209467b48Spatrick OS << Separator << Leaf.getName();
4309467b48Spatrick Separator = ",";
4409467b48Spatrick if (!Leaf.isFullyTraversed())
4509467b48Spatrick IsFullyTraversed = false;
4609467b48Spatrick if (!Leaf.isFullyTested())
4709467b48Spatrick IsFullyTested = false;
4809467b48Spatrick }
4909467b48Spatrick if (!Partitioner && !IsFullyTraversed)
5009467b48Spatrick OS << "|Not fully traversed";
5109467b48Spatrick if (!Partitioner && !IsFullyTested) {
5209467b48Spatrick OS << "|Not fully tested";
5309467b48Spatrick if (IsFullyTraversed) {
5409467b48Spatrick for (const GIMatchTreeLeafInfo &Leaf : PossibleLeaves) {
5509467b48Spatrick if (Leaf.isFullyTested())
5609467b48Spatrick continue;
5709467b48Spatrick OS << "\\n" << Leaf.getName() << ": " << &Leaf;
5809467b48Spatrick for (const GIMatchDagPredicate *P : Leaf.untested_predicates())
5909467b48Spatrick OS << *P;
6009467b48Spatrick }
6109467b48Spatrick }
6209467b48Spatrick }
6309467b48Spatrick OS << "}\"";
6409467b48Spatrick if (!Partitioner &&
6509467b48Spatrick (!IsFullyTraversed || !IsFullyTested || PossibleLeaves.size() > 1))
6609467b48Spatrick OS << ",color=red";
6709467b48Spatrick OS << "]\n";
6809467b48Spatrick for (const auto &C : Children)
6909467b48Spatrick C.writeDOTGraphNode(OS);
7009467b48Spatrick writeDOTGraphEdges(OS);
7109467b48Spatrick }
7209467b48Spatrick
writeDOTGraphEdges(raw_ostream & OS) const7309467b48Spatrick void GIMatchTree::writeDOTGraphEdges(raw_ostream &OS) const {
7409467b48Spatrick for (const auto &Child : enumerate(Children)) {
7509467b48Spatrick OS << format(" Node%p", this) << " -> " << format("Node%p", &Child.value())
7609467b48Spatrick << " [label=\"#" << Child.index() << " ";
7709467b48Spatrick Partitioner->emitPartitionName(OS, Child.index());
7809467b48Spatrick OS << "\"]\n";
7909467b48Spatrick }
8009467b48Spatrick }
8109467b48Spatrick
GIMatchTreeBuilderLeafInfo(GIMatchTreeBuilder & Builder,StringRef Name,unsigned RootIdx,const GIMatchDag & MatchDag,void * Data)8209467b48Spatrick GIMatchTreeBuilderLeafInfo::GIMatchTreeBuilderLeafInfo(
8309467b48Spatrick GIMatchTreeBuilder &Builder, StringRef Name, unsigned RootIdx,
8409467b48Spatrick const GIMatchDag &MatchDag, void *Data)
8509467b48Spatrick : Builder(Builder), Info(Name, RootIdx, Data), MatchDag(MatchDag),
8609467b48Spatrick RemainingInstrNodes(BitVector(MatchDag.getNumInstrNodes(), true)),
8709467b48Spatrick RemainingEdges(BitVector(MatchDag.getNumEdges(), true)),
8809467b48Spatrick RemainingPredicates(BitVector(MatchDag.getNumPredicates(), true)),
8909467b48Spatrick TraversableEdges(MatchDag.getNumEdges()),
9009467b48Spatrick TestablePredicates(MatchDag.getNumPredicates()) {
9109467b48Spatrick // Number all the predicates in this DAG
9209467b48Spatrick for (auto &P : enumerate(MatchDag.predicates())) {
9309467b48Spatrick PredicateIDs.insert(std::make_pair(P.value(), P.index()));
9409467b48Spatrick }
9509467b48Spatrick
9609467b48Spatrick // Number all the predicate dependencies in this DAG and set up a bitvector
9709467b48Spatrick // for each predicate indicating the unsatisfied dependencies.
9809467b48Spatrick for (auto &Dep : enumerate(MatchDag.predicate_edges())) {
9909467b48Spatrick PredicateDepIDs.insert(std::make_pair(Dep.value(), Dep.index()));
10009467b48Spatrick }
10109467b48Spatrick UnsatisfiedPredDepsForPred.resize(MatchDag.getNumPredicates(),
10209467b48Spatrick BitVector(PredicateDepIDs.size()));
10309467b48Spatrick for (auto &Dep : enumerate(MatchDag.predicate_edges())) {
10409467b48Spatrick unsigned ID = PredicateIDs.lookup(Dep.value()->getPredicate());
10509467b48Spatrick UnsatisfiedPredDepsForPred[ID].set(Dep.index());
10609467b48Spatrick }
10709467b48Spatrick }
10809467b48Spatrick
declareInstr(const GIMatchDagInstr * Instr,unsigned ID)10909467b48Spatrick void GIMatchTreeBuilderLeafInfo::declareInstr(const GIMatchDagInstr *Instr, unsigned ID) {
11009467b48Spatrick // Record the assignment of this instr to the given ID.
11109467b48Spatrick auto InfoI = InstrNodeToInfo.insert(std::make_pair(
11209467b48Spatrick Instr, GIMatchTreeInstrInfo(ID, Instr)));
11309467b48Spatrick InstrIDToInfo.insert(std::make_pair(ID, &InfoI.first->second));
11409467b48Spatrick
11509467b48Spatrick if (Instr == nullptr)
11609467b48Spatrick return;
11709467b48Spatrick
11809467b48Spatrick if (!Instr->getUserAssignedName().empty())
11909467b48Spatrick Info.bindInstrVariable(Instr->getUserAssignedName(), ID);
12009467b48Spatrick for (const auto &VarBinding : Instr->user_assigned_operand_names())
12109467b48Spatrick Info.bindOperandVariable(VarBinding.second, ID, VarBinding.first);
12209467b48Spatrick
12309467b48Spatrick // Clear the bit indicating we haven't visited this instr.
12473471bf0Spatrick const auto &NodeI = find(MatchDag.instr_nodes(), Instr);
12509467b48Spatrick assert(NodeI != MatchDag.instr_nodes_end() && "Instr isn't in this DAG");
12609467b48Spatrick unsigned InstrIdx = MatchDag.getInstrNodeIdx(NodeI);
12709467b48Spatrick RemainingInstrNodes.reset(InstrIdx);
12809467b48Spatrick
12909467b48Spatrick // When we declare an instruction, we don't expose any traversable edges just
13009467b48Spatrick // yet. A partitioner has to check they exist and are registers before they
13109467b48Spatrick // are traversable.
13209467b48Spatrick
13309467b48Spatrick // When we declare an instruction, we potentially activate some predicates.
13409467b48Spatrick // Mark the dependencies that are now satisfied as a result of this
13509467b48Spatrick // instruction and mark any predicates whose dependencies are fully
13609467b48Spatrick // satisfied.
13709467b48Spatrick for (auto &Dep : enumerate(MatchDag.predicate_edges())) {
13809467b48Spatrick if (Dep.value()->getRequiredMI() == Instr &&
13909467b48Spatrick Dep.value()->getRequiredMO() == nullptr) {
14009467b48Spatrick for (auto &DepsFor : enumerate(UnsatisfiedPredDepsForPred)) {
14109467b48Spatrick DepsFor.value().reset(Dep.index());
14209467b48Spatrick if (DepsFor.value().none())
14309467b48Spatrick TestablePredicates.set(DepsFor.index());
14409467b48Spatrick }
14509467b48Spatrick }
14609467b48Spatrick }
14709467b48Spatrick }
14809467b48Spatrick
declareOperand(unsigned InstrID,unsigned OpIdx)14909467b48Spatrick void GIMatchTreeBuilderLeafInfo::declareOperand(unsigned InstrID,
15009467b48Spatrick unsigned OpIdx) {
15109467b48Spatrick const GIMatchDagInstr *Instr = InstrIDToInfo.lookup(InstrID)->getInstrNode();
15209467b48Spatrick
15309467b48Spatrick OperandIDToInfo.insert(std::make_pair(
15409467b48Spatrick std::make_pair(InstrID, OpIdx),
15509467b48Spatrick GIMatchTreeOperandInfo(Instr, OpIdx)));
15609467b48Spatrick
15709467b48Spatrick // When an operand becomes reachable, we potentially activate some traversals.
15809467b48Spatrick // Record the edges that can now be followed as a result of this
15909467b48Spatrick // instruction.
16009467b48Spatrick for (auto &E : enumerate(MatchDag.edges())) {
16109467b48Spatrick if (E.value()->getFromMI() == Instr &&
16209467b48Spatrick E.value()->getFromMO()->getIdx() == OpIdx) {
16309467b48Spatrick TraversableEdges.set(E.index());
16409467b48Spatrick }
16509467b48Spatrick }
16609467b48Spatrick
16709467b48Spatrick // When an operand becomes reachable, we potentially activate some predicates.
16809467b48Spatrick // Clear the dependencies that are now satisfied as a result of this
16909467b48Spatrick // operand and activate any predicates whose dependencies are fully
17009467b48Spatrick // satisfied.
17109467b48Spatrick for (auto &Dep : enumerate(MatchDag.predicate_edges())) {
17209467b48Spatrick if (Dep.value()->getRequiredMI() == Instr && Dep.value()->getRequiredMO() &&
17309467b48Spatrick Dep.value()->getRequiredMO()->getIdx() == OpIdx) {
17409467b48Spatrick for (auto &DepsFor : enumerate(UnsatisfiedPredDepsForPred)) {
17509467b48Spatrick DepsFor.value().reset(Dep.index());
17609467b48Spatrick if (DepsFor.value().none())
17709467b48Spatrick TestablePredicates.set(DepsFor.index());
17809467b48Spatrick }
17909467b48Spatrick }
18009467b48Spatrick }
18109467b48Spatrick }
18209467b48Spatrick
addPartitionersForInstr(unsigned InstrIdx)18309467b48Spatrick void GIMatchTreeBuilder::addPartitionersForInstr(unsigned InstrIdx) {
18409467b48Spatrick // Find the partitioners that can be used now that this node is
18509467b48Spatrick // uncovered. Our choices are:
18609467b48Spatrick // - Test the opcode
18709467b48Spatrick addPartitioner(std::make_unique<GIMatchTreeOpcodePartitioner>(InstrIdx));
18809467b48Spatrick }
18909467b48Spatrick
addPartitionersForOperand(unsigned InstrID,unsigned OpIdx)19009467b48Spatrick void GIMatchTreeBuilder::addPartitionersForOperand(unsigned InstrID,
19109467b48Spatrick unsigned OpIdx) {
19209467b48Spatrick LLVM_DEBUG(dbgs() << "Add partitioners for Instrs[" << InstrID
19309467b48Spatrick << "].getOperand(" << OpIdx << ")\n");
19409467b48Spatrick addPartitioner(
19509467b48Spatrick std::make_unique<GIMatchTreeVRegDefPartitioner>(InstrID, OpIdx));
19609467b48Spatrick }
19709467b48Spatrick
filterRedundantPartitioners()19809467b48Spatrick void GIMatchTreeBuilder::filterRedundantPartitioners() {
19909467b48Spatrick // TODO: Filter partitioners for facts that are already known
20009467b48Spatrick // - If we know the opcode, we can elide the num operand check so long as
20109467b48Spatrick // the instruction has a fixed number of operands.
20209467b48Spatrick // - If we know an exact number of operands then we can elide further number
20309467b48Spatrick // of operand checks.
20409467b48Spatrick // - If the current min number of operands exceeds the one we want to check
20509467b48Spatrick // then we can elide it.
20609467b48Spatrick }
20709467b48Spatrick
evaluatePartitioners()20809467b48Spatrick void GIMatchTreeBuilder::evaluatePartitioners() {
20909467b48Spatrick // Determine the partitioning the partitioner would produce
21009467b48Spatrick for (auto &Partitioner : Partitioners) {
21109467b48Spatrick LLVM_DEBUG(dbgs() << " Weighing up ";
21209467b48Spatrick Partitioner->emitDescription(dbgs()); dbgs() << "\n");
21309467b48Spatrick Partitioner->repartition(Leaves);
21409467b48Spatrick LLVM_DEBUG(Partitioner->emitPartitionResults(dbgs()));
21509467b48Spatrick }
21609467b48Spatrick }
21709467b48Spatrick
runStep()21809467b48Spatrick void GIMatchTreeBuilder::runStep() {
21909467b48Spatrick LLVM_DEBUG(dbgs() << "Building match tree node for " << TreeNode << "\n");
22009467b48Spatrick LLVM_DEBUG(dbgs() << " Rules reachable at this node:\n");
22109467b48Spatrick for (const auto &Leaf : Leaves) {
22209467b48Spatrick LLVM_DEBUG(dbgs() << " " << Leaf.getName() << " (" << &Leaf.getInfo() << "\n");
22309467b48Spatrick TreeNode->addPossibleLeaf(Leaf.getInfo(), Leaf.isFullyTraversed(),
22409467b48Spatrick Leaf.isFullyTested());
22509467b48Spatrick }
22609467b48Spatrick
22709467b48Spatrick LLVM_DEBUG(dbgs() << " Partitioners available at this node:\n");
22809467b48Spatrick #ifndef NDEBUG
22909467b48Spatrick for (const auto &Partitioner : Partitioners)
23009467b48Spatrick LLVM_DEBUG(dbgs() << " "; Partitioner->emitDescription(dbgs());
23109467b48Spatrick dbgs() << "\n");
23209467b48Spatrick #endif // ifndef NDEBUG
23309467b48Spatrick
23409467b48Spatrick // Check for unreachable rules. Rules are unreachable if they are preceeded by
23509467b48Spatrick // a fully tested rule.
23609467b48Spatrick // Note: This is only true for the current algorithm, if we allow the
23709467b48Spatrick // algorithm to compare equally valid rules then they will become
23809467b48Spatrick // reachable.
23909467b48Spatrick {
24009467b48Spatrick auto FullyTestedLeafI = Leaves.end();
24109467b48Spatrick for (auto LeafI = Leaves.begin(), LeafE = Leaves.end();
24209467b48Spatrick LeafI != LeafE; ++LeafI) {
24309467b48Spatrick if (LeafI->isFullyTraversed() && LeafI->isFullyTested())
24409467b48Spatrick FullyTestedLeafI = LeafI;
24509467b48Spatrick else if (FullyTestedLeafI != Leaves.end()) {
24609467b48Spatrick PrintError("Leaf " + LeafI->getName() + " is unreachable");
24709467b48Spatrick PrintNote("Leaf " + FullyTestedLeafI->getName() +
24809467b48Spatrick " will have already matched");
24909467b48Spatrick }
25009467b48Spatrick }
25109467b48Spatrick }
25209467b48Spatrick
25309467b48Spatrick LLVM_DEBUG(dbgs() << " Eliminating redundant partitioners:\n");
25409467b48Spatrick filterRedundantPartitioners();
25509467b48Spatrick LLVM_DEBUG(dbgs() << " Partitioners remaining:\n");
25609467b48Spatrick #ifndef NDEBUG
25709467b48Spatrick for (const auto &Partitioner : Partitioners)
25809467b48Spatrick LLVM_DEBUG(dbgs() << " "; Partitioner->emitDescription(dbgs());
25909467b48Spatrick dbgs() << "\n");
26009467b48Spatrick #endif // ifndef NDEBUG
26109467b48Spatrick
26209467b48Spatrick if (Partitioners.empty()) {
26309467b48Spatrick // Nothing left to do but check we really did identify a single rule.
26409467b48Spatrick if (Leaves.size() > 1) {
26509467b48Spatrick LLVM_DEBUG(dbgs() << "Leaf contains multiple rules, drop after the first "
26609467b48Spatrick "fully tested rule\n");
26709467b48Spatrick auto FirstFullyTested =
26873471bf0Spatrick llvm::find_if(Leaves, [](const GIMatchTreeBuilderLeafInfo &X) {
26909467b48Spatrick return X.isFullyTraversed() && X.isFullyTested() &&
27009467b48Spatrick !X.getMatchDag().hasPostMatchPredicate();
27109467b48Spatrick });
27209467b48Spatrick if (FirstFullyTested != Leaves.end())
27309467b48Spatrick FirstFullyTested++;
27409467b48Spatrick
27509467b48Spatrick #ifndef NDEBUG
27609467b48Spatrick for (auto &Leaf : make_range(Leaves.begin(), FirstFullyTested))
27709467b48Spatrick LLVM_DEBUG(dbgs() << " Kept " << Leaf.getName() << "\n");
27809467b48Spatrick for (const auto &Leaf : make_range(FirstFullyTested, Leaves.end()))
27909467b48Spatrick LLVM_DEBUG(dbgs() << " Dropped " << Leaf.getName() << "\n");
28009467b48Spatrick #endif // ifndef NDEBUG
28109467b48Spatrick TreeNode->dropLeavesAfter(
28209467b48Spatrick std::distance(Leaves.begin(), FirstFullyTested));
28309467b48Spatrick }
28409467b48Spatrick for (const auto &Leaf : Leaves) {
28509467b48Spatrick if (!Leaf.isFullyTraversed()) {
28609467b48Spatrick PrintError("Leaf " + Leaf.getName() + " is not fully traversed");
28709467b48Spatrick PrintNote("This indicates a missing partitioner within tblgen");
28809467b48Spatrick Leaf.dump(errs());
28909467b48Spatrick for (unsigned InstrIdx : Leaf.untested_instrs())
29009467b48Spatrick PrintNote("Instr " + llvm::to_string(*Leaf.getInstr(InstrIdx)));
29109467b48Spatrick for (unsigned EdgeIdx : Leaf.untested_edges())
29209467b48Spatrick PrintNote("Edge " + llvm::to_string(*Leaf.getEdge(EdgeIdx)));
29309467b48Spatrick }
29409467b48Spatrick }
29509467b48Spatrick
29609467b48Spatrick // Copy out information about untested predicates so the user of the tree
29709467b48Spatrick // can deal with them.
29809467b48Spatrick for (auto LeafPair : zip(Leaves, TreeNode->possible_leaves())) {
29909467b48Spatrick const GIMatchTreeBuilderLeafInfo &BuilderLeaf = std::get<0>(LeafPair);
30009467b48Spatrick GIMatchTreeLeafInfo &TreeLeaf = std::get<1>(LeafPair);
30109467b48Spatrick if (!BuilderLeaf.isFullyTested())
30209467b48Spatrick for (unsigned PredicateIdx : BuilderLeaf.untested_predicates())
30309467b48Spatrick TreeLeaf.addUntestedPredicate(BuilderLeaf.getPredicate(PredicateIdx));
30409467b48Spatrick }
30509467b48Spatrick return;
30609467b48Spatrick }
30709467b48Spatrick
30809467b48Spatrick LLVM_DEBUG(dbgs() << " Weighing up partitioners:\n");
30909467b48Spatrick evaluatePartitioners();
31009467b48Spatrick
31109467b48Spatrick // Select the best partitioner by its ability to partition
31209467b48Spatrick // - Prefer partitioners that don't distinguish between partitions. This
31309467b48Spatrick // is to fail early on decisions that must go a single way.
31409467b48Spatrick auto PartitionerI = std::max_element(
31509467b48Spatrick Partitioners.begin(), Partitioners.end(),
31609467b48Spatrick [](const std::unique_ptr<GIMatchTreePartitioner> &A,
31709467b48Spatrick const std::unique_ptr<GIMatchTreePartitioner> &B) {
31809467b48Spatrick // We generally want partitioners that subdivide the
31909467b48Spatrick // ruleset as much as possible since these take fewer
32009467b48Spatrick // checks to converge on a particular rule. However,
32109467b48Spatrick // it's important to note that one leaf can end up in
32209467b48Spatrick // multiple partitions if the check isn't mutually
32309467b48Spatrick // exclusive (e.g. getVRegDef() vs isReg()).
32409467b48Spatrick // We therefore minimize average leaves per partition.
32509467b48Spatrick return (double)A->getNumLeavesWithDupes() / A->getNumPartitions() >
32609467b48Spatrick (double)B->getNumLeavesWithDupes() / B->getNumPartitions();
32709467b48Spatrick });
32809467b48Spatrick
32909467b48Spatrick // Select a partitioner and partition the ruleset
33009467b48Spatrick // Note that it's possible for a single rule to end up in multiple
33109467b48Spatrick // partitions. For example, an opcode test on a rule without an opcode
33209467b48Spatrick // predicate will result in it being passed to all partitions.
33309467b48Spatrick std::unique_ptr<GIMatchTreePartitioner> Partitioner = std::move(*PartitionerI);
33409467b48Spatrick Partitioners.erase(PartitionerI);
33509467b48Spatrick LLVM_DEBUG(dbgs() << " Selected partitioner: ";
33609467b48Spatrick Partitioner->emitDescription(dbgs()); dbgs() << "\n");
33709467b48Spatrick
33809467b48Spatrick assert(Partitioner->getNumPartitions() > 0 &&
33909467b48Spatrick "Must always partition into at least one partition");
34009467b48Spatrick
34109467b48Spatrick TreeNode->setNumChildren(Partitioner->getNumPartitions());
34209467b48Spatrick for (auto &C : enumerate(TreeNode->children())) {
34309467b48Spatrick SubtreeBuilders.emplace_back(&C.value(), NextInstrID);
34409467b48Spatrick Partitioner->applyForPartition(C.index(), *this, SubtreeBuilders.back());
34509467b48Spatrick }
34609467b48Spatrick
34709467b48Spatrick TreeNode->setPartitioner(std::move(Partitioner));
34809467b48Spatrick
34909467b48Spatrick // Recurse into the subtree builders. Each one must get a copy of the
35009467b48Spatrick // remaining partitioners as each path has to check everything.
35109467b48Spatrick for (auto &SubtreeBuilder : SubtreeBuilders) {
35209467b48Spatrick for (const auto &Partitioner : Partitioners)
35309467b48Spatrick SubtreeBuilder.addPartitioner(Partitioner->clone());
35409467b48Spatrick SubtreeBuilder.runStep();
35509467b48Spatrick }
35609467b48Spatrick }
35709467b48Spatrick
run()35809467b48Spatrick std::unique_ptr<GIMatchTree> GIMatchTreeBuilder::run() {
35909467b48Spatrick unsigned NewInstrID = allocInstrID();
36009467b48Spatrick // Start by recording the root instruction as instr #0 and set up the initial
36109467b48Spatrick // partitioners.
36209467b48Spatrick for (auto &Leaf : Leaves) {
36309467b48Spatrick LLVM_DEBUG(Leaf.getMatchDag().writeDOTGraph(dbgs(), Leaf.getName()));
36409467b48Spatrick GIMatchDagInstr *Root =
36509467b48Spatrick *(Leaf.getMatchDag().roots().begin() + Leaf.getRootIdx());
36609467b48Spatrick Leaf.declareInstr(Root, NewInstrID);
36709467b48Spatrick }
36809467b48Spatrick
36909467b48Spatrick addPartitionersForInstr(NewInstrID);
37009467b48Spatrick
37109467b48Spatrick std::unique_ptr<GIMatchTree> TreeRoot = std::make_unique<GIMatchTree>();
37209467b48Spatrick TreeNode = TreeRoot.get();
37309467b48Spatrick runStep();
37409467b48Spatrick
37509467b48Spatrick return TreeRoot;
37609467b48Spatrick }
37709467b48Spatrick
emitPartitionName(raw_ostream & OS,unsigned Idx) const37809467b48Spatrick void GIMatchTreeOpcodePartitioner::emitPartitionName(raw_ostream &OS, unsigned Idx) const {
37909467b48Spatrick if (PartitionToInstr[Idx] == nullptr) {
38009467b48Spatrick OS << "* or nullptr";
38109467b48Spatrick return;
38209467b48Spatrick }
38309467b48Spatrick OS << PartitionToInstr[Idx]->Namespace
38409467b48Spatrick << "::" << PartitionToInstr[Idx]->TheDef->getName();
38509467b48Spatrick }
38609467b48Spatrick
repartition(GIMatchTreeBuilder::LeafVec & Leaves)38709467b48Spatrick void GIMatchTreeOpcodePartitioner::repartition(
38809467b48Spatrick GIMatchTreeBuilder::LeafVec &Leaves) {
38909467b48Spatrick Partitions.clear();
39009467b48Spatrick InstrToPartition.clear();
39109467b48Spatrick PartitionToInstr.clear();
39209467b48Spatrick TestedPredicates.clear();
39309467b48Spatrick
39409467b48Spatrick for (const auto &Leaf : enumerate(Leaves)) {
39509467b48Spatrick bool AllOpcodes = true;
39609467b48Spatrick GIMatchTreeInstrInfo *InstrInfo = Leaf.value().getInstrInfo(InstrID);
39709467b48Spatrick BitVector TestedPredicatesForLeaf(
39809467b48Spatrick Leaf.value().getMatchDag().getNumPredicates());
39909467b48Spatrick
40009467b48Spatrick // If the instruction isn't declared then we don't care about it. Ignore
40109467b48Spatrick // it for now and add it to all partitions later once we know what
40209467b48Spatrick // partitions we have.
40309467b48Spatrick if (!InstrInfo) {
40409467b48Spatrick LLVM_DEBUG(dbgs() << " " << Leaf.value().getName()
40509467b48Spatrick << " doesn't care about Instr[" << InstrID << "]\n");
40609467b48Spatrick assert(TestedPredicatesForLeaf.size() == Leaf.value().getMatchDag().getNumPredicates());
40709467b48Spatrick TestedPredicates.push_back(TestedPredicatesForLeaf);
40809467b48Spatrick continue;
40909467b48Spatrick }
41009467b48Spatrick
41109467b48Spatrick // If the opcode is available to test then any opcode predicates will have
41209467b48Spatrick // been enabled too.
41309467b48Spatrick for (unsigned PIdx : Leaf.value().TestablePredicates.set_bits()) {
41409467b48Spatrick const auto &P = Leaf.value().getPredicate(PIdx);
41509467b48Spatrick SmallVector<const CodeGenInstruction *, 1> OpcodesForThisPredicate;
41609467b48Spatrick if (const auto *OpcodeP = dyn_cast<const GIMatchDagOpcodePredicate>(P)) {
41709467b48Spatrick // We've found _an_ opcode predicate, but we don't know if it's
41809467b48Spatrick // checking this instruction yet.
41909467b48Spatrick bool IsThisPredicate = false;
42009467b48Spatrick for (const auto &PDep : Leaf.value().getMatchDag().predicate_edges()) {
42109467b48Spatrick if (PDep->getRequiredMI() == InstrInfo->getInstrNode() &&
42209467b48Spatrick PDep->getRequiredMO() == nullptr && PDep->getPredicate() == P) {
42309467b48Spatrick IsThisPredicate = true;
42409467b48Spatrick break;
42509467b48Spatrick }
42609467b48Spatrick }
42709467b48Spatrick if (!IsThisPredicate)
42809467b48Spatrick continue;
42909467b48Spatrick
43009467b48Spatrick // If we get here twice then we've somehow ended up with two opcode
43109467b48Spatrick // predicates for one instruction in the same DAG. That should be
43209467b48Spatrick // impossible.
43309467b48Spatrick assert(AllOpcodes && "Conflicting opcode predicates");
43409467b48Spatrick const CodeGenInstruction *Expected = OpcodeP->getInstr();
43509467b48Spatrick OpcodesForThisPredicate.push_back(Expected);
43609467b48Spatrick }
43709467b48Spatrick
43809467b48Spatrick if (const auto *OpcodeP =
43909467b48Spatrick dyn_cast<const GIMatchDagOneOfOpcodesPredicate>(P)) {
44009467b48Spatrick // We've found _an_ oneof(opcodes) predicate, but we don't know if it's
44109467b48Spatrick // checking this instruction yet.
44209467b48Spatrick bool IsThisPredicate = false;
44309467b48Spatrick for (const auto &PDep : Leaf.value().getMatchDag().predicate_edges()) {
44409467b48Spatrick if (PDep->getRequiredMI() == InstrInfo->getInstrNode() &&
44509467b48Spatrick PDep->getRequiredMO() == nullptr && PDep->getPredicate() == P) {
44609467b48Spatrick IsThisPredicate = true;
44709467b48Spatrick break;
44809467b48Spatrick }
44909467b48Spatrick }
45009467b48Spatrick if (!IsThisPredicate)
45109467b48Spatrick continue;
45209467b48Spatrick
45309467b48Spatrick // If we get here twice then we've somehow ended up with two opcode
45409467b48Spatrick // predicates for one instruction in the same DAG. That should be
45509467b48Spatrick // impossible.
45609467b48Spatrick assert(AllOpcodes && "Conflicting opcode predicates");
45773471bf0Spatrick append_range(OpcodesForThisPredicate, OpcodeP->getInstrs());
45809467b48Spatrick }
45909467b48Spatrick
46009467b48Spatrick for (const CodeGenInstruction *Expected : OpcodesForThisPredicate) {
46109467b48Spatrick // Mark this predicate as one we're testing.
46209467b48Spatrick TestedPredicatesForLeaf.set(PIdx);
46309467b48Spatrick
46409467b48Spatrick // Partitions must be numbered 0, 1, .., N but instructions don't meet
46509467b48Spatrick // that requirement. Assign a partition number to each opcode if we
46609467b48Spatrick // lack one ...
46709467b48Spatrick auto Partition = InstrToPartition.find(Expected);
46809467b48Spatrick if (Partition == InstrToPartition.end()) {
46909467b48Spatrick BitVector Contents(Leaves.size());
47009467b48Spatrick Partition = InstrToPartition
47109467b48Spatrick .insert(std::make_pair(Expected, Partitions.size()))
47209467b48Spatrick .first;
47309467b48Spatrick PartitionToInstr.push_back(Expected);
47409467b48Spatrick Partitions.insert(std::make_pair(Partitions.size(), Contents));
47509467b48Spatrick }
47609467b48Spatrick // ... and mark this leaf as being in that partition.
47709467b48Spatrick Partitions.find(Partition->second)->second.set(Leaf.index());
47809467b48Spatrick AllOpcodes = false;
47909467b48Spatrick LLVM_DEBUG(dbgs() << " " << Leaf.value().getName()
48009467b48Spatrick << " is in partition " << Partition->second << "\n");
48109467b48Spatrick }
48209467b48Spatrick
48309467b48Spatrick // TODO: This is where we would handle multiple choices of opcode
48409467b48Spatrick // the end result will be that this leaf ends up in multiple
48509467b48Spatrick // partitions similarly to AllOpcodes.
48609467b48Spatrick }
48709467b48Spatrick
48809467b48Spatrick // If we never check the opcode, add it to every partition.
48909467b48Spatrick if (AllOpcodes) {
49009467b48Spatrick // Add a partition for the default case if we don't already have one.
49109467b48Spatrick if (InstrToPartition.insert(std::make_pair(nullptr, 0)).second) {
49209467b48Spatrick PartitionToInstr.push_back(nullptr);
49309467b48Spatrick BitVector Contents(Leaves.size());
49409467b48Spatrick Partitions.insert(std::make_pair(Partitions.size(), Contents));
49509467b48Spatrick }
49609467b48Spatrick LLVM_DEBUG(dbgs() << " " << Leaf.value().getName()
49709467b48Spatrick << " is in all partitions (opcode not checked)\n");
49809467b48Spatrick for (auto &Partition : Partitions)
49909467b48Spatrick Partition.second.set(Leaf.index());
50009467b48Spatrick }
50109467b48Spatrick
50209467b48Spatrick assert(TestedPredicatesForLeaf.size() == Leaf.value().getMatchDag().getNumPredicates());
50309467b48Spatrick TestedPredicates.push_back(TestedPredicatesForLeaf);
50409467b48Spatrick }
50509467b48Spatrick
50609467b48Spatrick if (Partitions.size() == 0) {
50709467b48Spatrick // Add a partition for the default case if we don't already have one.
50809467b48Spatrick if (InstrToPartition.insert(std::make_pair(nullptr, 0)).second) {
50909467b48Spatrick PartitionToInstr.push_back(nullptr);
51009467b48Spatrick BitVector Contents(Leaves.size());
51109467b48Spatrick Partitions.insert(std::make_pair(Partitions.size(), Contents));
51209467b48Spatrick }
51309467b48Spatrick }
51409467b48Spatrick
51509467b48Spatrick // Add any leaves that don't care about this instruction to all partitions.
51609467b48Spatrick for (const auto &Leaf : enumerate(Leaves)) {
51709467b48Spatrick GIMatchTreeInstrInfo *InstrInfo = Leaf.value().getInstrInfo(InstrID);
51809467b48Spatrick if (!InstrInfo) {
51909467b48Spatrick // Add a partition for the default case if we don't already have one.
52009467b48Spatrick if (InstrToPartition.insert(std::make_pair(nullptr, 0)).second) {
52109467b48Spatrick PartitionToInstr.push_back(nullptr);
52209467b48Spatrick BitVector Contents(Leaves.size());
52309467b48Spatrick Partitions.insert(std::make_pair(Partitions.size(), Contents));
52409467b48Spatrick }
52509467b48Spatrick for (auto &Partition : Partitions)
52609467b48Spatrick Partition.second.set(Leaf.index());
52709467b48Spatrick }
52809467b48Spatrick }
52909467b48Spatrick
53009467b48Spatrick }
53109467b48Spatrick
applyForPartition(unsigned PartitionIdx,GIMatchTreeBuilder & Builder,GIMatchTreeBuilder & SubBuilder)53209467b48Spatrick void GIMatchTreeOpcodePartitioner::applyForPartition(
53309467b48Spatrick unsigned PartitionIdx, GIMatchTreeBuilder &Builder, GIMatchTreeBuilder &SubBuilder) {
53409467b48Spatrick LLVM_DEBUG(dbgs() << " Making partition " << PartitionIdx << "\n");
53509467b48Spatrick const CodeGenInstruction *CGI = PartitionToInstr[PartitionIdx];
53609467b48Spatrick
53709467b48Spatrick BitVector PossibleLeaves = getPossibleLeavesForPartition(PartitionIdx);
53809467b48Spatrick // Consume any predicates we handled.
53909467b48Spatrick for (auto &EnumeratedLeaf : enumerate(Builder.getPossibleLeaves())) {
54009467b48Spatrick if (!PossibleLeaves[EnumeratedLeaf.index()])
54109467b48Spatrick continue;
54209467b48Spatrick
54309467b48Spatrick auto &Leaf = EnumeratedLeaf.value();
54409467b48Spatrick const auto &TestedPredicatesForLeaf =
54509467b48Spatrick TestedPredicates[EnumeratedLeaf.index()];
54609467b48Spatrick
54709467b48Spatrick for (unsigned PredIdx : TestedPredicatesForLeaf.set_bits()) {
54809467b48Spatrick LLVM_DEBUG(dbgs() << " " << Leaf.getName() << " tested predicate #"
54909467b48Spatrick << PredIdx << " of " << TestedPredicatesForLeaf.size()
55009467b48Spatrick << " " << *Leaf.getPredicate(PredIdx) << "\n");
55109467b48Spatrick Leaf.RemainingPredicates.reset(PredIdx);
55209467b48Spatrick Leaf.TestablePredicates.reset(PredIdx);
55309467b48Spatrick }
55409467b48Spatrick SubBuilder.addLeaf(Leaf);
55509467b48Spatrick }
55609467b48Spatrick
55709467b48Spatrick // Nothing to do, we don't know anything about this instruction as a result
55809467b48Spatrick // of this partitioner.
55909467b48Spatrick if (CGI == nullptr)
56009467b48Spatrick return;
56109467b48Spatrick
56209467b48Spatrick GIMatchTreeBuilder::LeafVec &NewLeaves = SubBuilder.getPossibleLeaves();
56309467b48Spatrick // Find all the operands we know to exist and are referenced. This will
56409467b48Spatrick // usually be all the referenced operands but there are some cases where
56509467b48Spatrick // instructions are variadic. Such operands must be handled by partitioners
56609467b48Spatrick // that check the number of operands.
56709467b48Spatrick BitVector ReferencedOperands(1);
56809467b48Spatrick for (auto &Leaf : NewLeaves) {
56909467b48Spatrick GIMatchTreeInstrInfo *InstrInfo = Leaf.getInstrInfo(InstrID);
57009467b48Spatrick // Skip any leaves that don't care about this instruction.
57109467b48Spatrick if (!InstrInfo)
57209467b48Spatrick continue;
57309467b48Spatrick const GIMatchDagInstr *Instr = InstrInfo->getInstrNode();
57409467b48Spatrick for (auto &E : enumerate(Leaf.getMatchDag().edges())) {
57509467b48Spatrick if (E.value()->getFromMI() == Instr &&
57609467b48Spatrick E.value()->getFromMO()->getIdx() < CGI->Operands.size()) {
57709467b48Spatrick ReferencedOperands.resize(E.value()->getFromMO()->getIdx() + 1);
57809467b48Spatrick ReferencedOperands.set(E.value()->getFromMO()->getIdx());
57909467b48Spatrick }
58009467b48Spatrick }
58109467b48Spatrick }
58209467b48Spatrick for (auto &Leaf : NewLeaves) {
583*d415bd75Srobert // Skip any leaves that don't care about this instruction.
584*d415bd75Srobert if (!Leaf.getInstrInfo(InstrID))
585*d415bd75Srobert continue;
586*d415bd75Srobert
58709467b48Spatrick for (unsigned OpIdx : ReferencedOperands.set_bits()) {
58809467b48Spatrick Leaf.declareOperand(InstrID, OpIdx);
58909467b48Spatrick }
59009467b48Spatrick }
59109467b48Spatrick for (unsigned OpIdx : ReferencedOperands.set_bits()) {
59209467b48Spatrick SubBuilder.addPartitionersForOperand(InstrID, OpIdx);
59309467b48Spatrick }
59409467b48Spatrick }
59509467b48Spatrick
emitPartitionResults(raw_ostream & OS) const59609467b48Spatrick void GIMatchTreeOpcodePartitioner::emitPartitionResults(
59709467b48Spatrick raw_ostream &OS) const {
59809467b48Spatrick OS << "Partitioning by opcode would produce " << Partitions.size()
59909467b48Spatrick << " partitions\n";
60009467b48Spatrick for (const auto &Partition : InstrToPartition) {
60109467b48Spatrick if (Partition.first == nullptr)
60209467b48Spatrick OS << "Default: ";
60309467b48Spatrick else
60409467b48Spatrick OS << Partition.first->TheDef->getName() << ": ";
60509467b48Spatrick StringRef Separator = "";
60609467b48Spatrick for (unsigned I : Partitions.find(Partition.second)->second.set_bits()) {
60709467b48Spatrick OS << Separator << I;
60809467b48Spatrick Separator = ", ";
60909467b48Spatrick }
61009467b48Spatrick OS << "\n";
61109467b48Spatrick }
61209467b48Spatrick }
61309467b48Spatrick
generatePartitionSelectorCode(raw_ostream & OS,StringRef Indent) const61409467b48Spatrick void GIMatchTreeOpcodePartitioner::generatePartitionSelectorCode(
61509467b48Spatrick raw_ostream &OS, StringRef Indent) const {
616097a140dSpatrick // Make sure not to emit empty switch or switch with just default
617097a140dSpatrick if (PartitionToInstr.size() == 1 && PartitionToInstr[0] == nullptr) {
618097a140dSpatrick OS << Indent << "Partition = 0;\n";
619097a140dSpatrick } else if (PartitionToInstr.size()) {
62009467b48Spatrick OS << Indent << "Partition = -1;\n"
62109467b48Spatrick << Indent << "switch (MIs[" << InstrID << "]->getOpcode()) {\n";
62209467b48Spatrick for (const auto &EnumInstr : enumerate(PartitionToInstr)) {
62309467b48Spatrick if (EnumInstr.value() == nullptr)
62409467b48Spatrick OS << Indent << "default:";
62509467b48Spatrick else
62609467b48Spatrick OS << Indent << "case " << EnumInstr.value()->Namespace
62709467b48Spatrick << "::" << EnumInstr.value()->TheDef->getName() << ":";
62809467b48Spatrick OS << " Partition = " << EnumInstr.index() << "; break;\n";
62909467b48Spatrick }
630097a140dSpatrick OS << Indent << "}\n";
631097a140dSpatrick }
632097a140dSpatrick OS << Indent
63309467b48Spatrick << "// Default case but without conflicting with potential default case "
63409467b48Spatrick "in selection.\n"
63509467b48Spatrick << Indent << "if (Partition == -1) return false;\n";
63609467b48Spatrick }
63709467b48Spatrick
addToPartition(bool Result,unsigned LeafIdx)63809467b48Spatrick void GIMatchTreeVRegDefPartitioner::addToPartition(bool Result,
63909467b48Spatrick unsigned LeafIdx) {
64009467b48Spatrick auto I = ResultToPartition.find(Result);
64109467b48Spatrick if (I == ResultToPartition.end()) {
64209467b48Spatrick ResultToPartition.insert(std::make_pair(Result, PartitionToResult.size()));
64309467b48Spatrick PartitionToResult.push_back(Result);
64409467b48Spatrick }
64509467b48Spatrick I = ResultToPartition.find(Result);
64609467b48Spatrick auto P = Partitions.find(I->second);
64709467b48Spatrick if (P == Partitions.end())
64809467b48Spatrick P = Partitions.insert(std::make_pair(I->second, BitVector())).first;
64909467b48Spatrick P->second.resize(LeafIdx + 1);
65009467b48Spatrick P->second.set(LeafIdx);
65109467b48Spatrick }
65209467b48Spatrick
repartition(GIMatchTreeBuilder::LeafVec & Leaves)65309467b48Spatrick void GIMatchTreeVRegDefPartitioner::repartition(
65409467b48Spatrick GIMatchTreeBuilder::LeafVec &Leaves) {
65509467b48Spatrick Partitions.clear();
65609467b48Spatrick
65709467b48Spatrick for (const auto &Leaf : enumerate(Leaves)) {
65809467b48Spatrick GIMatchTreeInstrInfo *InstrInfo = Leaf.value().getInstrInfo(InstrID);
65909467b48Spatrick BitVector TraversedEdgesForLeaf(Leaf.value().getMatchDag().getNumEdges());
66009467b48Spatrick
66109467b48Spatrick // If the instruction isn't declared then we don't care about it. Ignore
66209467b48Spatrick // it for now and add it to all partitions later once we know what
66309467b48Spatrick // partitions we have.
66409467b48Spatrick if (!InstrInfo) {
66509467b48Spatrick TraversedEdges.push_back(TraversedEdgesForLeaf);
66609467b48Spatrick continue;
66709467b48Spatrick }
66809467b48Spatrick
66909467b48Spatrick // If this node has an use -> def edge from this operand then this
67009467b48Spatrick // instruction must be in partition 1 (isVRegDef()).
67109467b48Spatrick bool WantsEdge = false;
67209467b48Spatrick for (unsigned EIdx : Leaf.value().TraversableEdges.set_bits()) {
67309467b48Spatrick const auto &E = Leaf.value().getEdge(EIdx);
67409467b48Spatrick if (E->getFromMI() != InstrInfo->getInstrNode() ||
67509467b48Spatrick E->getFromMO()->getIdx() != OpIdx || E->isDefToUse())
67609467b48Spatrick continue;
67709467b48Spatrick
67809467b48Spatrick // We're looking at the right edge. This leaf wants a vreg def so we'll
67909467b48Spatrick // put it in partition 1.
68009467b48Spatrick addToPartition(true, Leaf.index());
68109467b48Spatrick TraversedEdgesForLeaf.set(EIdx);
68209467b48Spatrick WantsEdge = true;
68309467b48Spatrick }
68409467b48Spatrick
68509467b48Spatrick bool isNotReg = false;
68609467b48Spatrick if (!WantsEdge && isNotReg) {
68709467b48Spatrick // If this leaf doesn't have an edge and we _don't_ want a register,
68809467b48Spatrick // then add it to partition 0.
68909467b48Spatrick addToPartition(false, Leaf.index());
69009467b48Spatrick } else if (!WantsEdge) {
69109467b48Spatrick // If this leaf doesn't have an edge and we don't know what we want,
69209467b48Spatrick // then add it to partition 0 and 1.
69309467b48Spatrick addToPartition(false, Leaf.index());
69409467b48Spatrick addToPartition(true, Leaf.index());
69509467b48Spatrick }
69609467b48Spatrick
69709467b48Spatrick TraversedEdges.push_back(TraversedEdgesForLeaf);
69809467b48Spatrick }
69909467b48Spatrick
70009467b48Spatrick // Add any leaves that don't care about this instruction to all partitions.
70109467b48Spatrick for (const auto &Leaf : enumerate(Leaves)) {
70209467b48Spatrick GIMatchTreeInstrInfo *InstrInfo = Leaf.value().getInstrInfo(InstrID);
70309467b48Spatrick if (!InstrInfo)
704*d415bd75Srobert for (auto &Partition : Partitions) {
705*d415bd75Srobert Partition.second.resize(Leaf.index() + 1);
70609467b48Spatrick Partition.second.set(Leaf.index());
70709467b48Spatrick }
70809467b48Spatrick }
709*d415bd75Srobert }
71009467b48Spatrick
applyForPartition(unsigned PartitionIdx,GIMatchTreeBuilder & Builder,GIMatchTreeBuilder & SubBuilder)71109467b48Spatrick void GIMatchTreeVRegDefPartitioner::applyForPartition(
71209467b48Spatrick unsigned PartitionIdx, GIMatchTreeBuilder &Builder,
71309467b48Spatrick GIMatchTreeBuilder &SubBuilder) {
71409467b48Spatrick BitVector PossibleLeaves = getPossibleLeavesForPartition(PartitionIdx);
71509467b48Spatrick
71609467b48Spatrick std::vector<BitVector> TraversedEdgesByNewLeaves;
71709467b48Spatrick // Consume any edges we handled.
71809467b48Spatrick for (auto &EnumeratedLeaf : enumerate(Builder.getPossibleLeaves())) {
71909467b48Spatrick if (!PossibleLeaves[EnumeratedLeaf.index()])
72009467b48Spatrick continue;
72109467b48Spatrick
72209467b48Spatrick auto &Leaf = EnumeratedLeaf.value();
72309467b48Spatrick const auto &TraversedEdgesForLeaf = TraversedEdges[EnumeratedLeaf.index()];
72409467b48Spatrick TraversedEdgesByNewLeaves.push_back(TraversedEdgesForLeaf);
72509467b48Spatrick Leaf.RemainingEdges.reset(TraversedEdgesForLeaf);
72609467b48Spatrick Leaf.TraversableEdges.reset(TraversedEdgesForLeaf);
72709467b48Spatrick SubBuilder.addLeaf(Leaf);
72809467b48Spatrick }
72909467b48Spatrick
73009467b48Spatrick // Nothing to do. The only thing we know is that it isn't a vreg-def.
73109467b48Spatrick if (PartitionToResult[PartitionIdx] == false)
73209467b48Spatrick return;
73309467b48Spatrick
73409467b48Spatrick NewInstrID = SubBuilder.allocInstrID();
73509467b48Spatrick
73609467b48Spatrick GIMatchTreeBuilder::LeafVec &NewLeaves = SubBuilder.getPossibleLeaves();
73709467b48Spatrick for (const auto I : zip(NewLeaves, TraversedEdgesByNewLeaves)) {
73809467b48Spatrick auto &Leaf = std::get<0>(I);
73909467b48Spatrick auto &TraversedEdgesForLeaf = std::get<1>(I);
74009467b48Spatrick GIMatchTreeInstrInfo *InstrInfo = Leaf.getInstrInfo(InstrID);
74109467b48Spatrick // Skip any leaves that don't care about this instruction.
74209467b48Spatrick if (!InstrInfo)
74309467b48Spatrick continue;
74409467b48Spatrick for (unsigned EIdx : TraversedEdgesForLeaf.set_bits()) {
74509467b48Spatrick const GIMatchDagEdge *E = Leaf.getEdge(EIdx);
74609467b48Spatrick Leaf.declareInstr(E->getToMI(), NewInstrID);
74709467b48Spatrick }
74809467b48Spatrick }
74909467b48Spatrick SubBuilder.addPartitionersForInstr(NewInstrID);
75009467b48Spatrick }
75109467b48Spatrick
emitPartitionResults(raw_ostream & OS) const75209467b48Spatrick void GIMatchTreeVRegDefPartitioner::emitPartitionResults(
75309467b48Spatrick raw_ostream &OS) const {
75409467b48Spatrick OS << "Partitioning by vreg-def would produce " << Partitions.size()
75509467b48Spatrick << " partitions\n";
75609467b48Spatrick for (const auto &Partition : Partitions) {
75709467b48Spatrick OS << Partition.first << " (";
75809467b48Spatrick emitPartitionName(OS, Partition.first);
75909467b48Spatrick OS << "): ";
76009467b48Spatrick StringRef Separator = "";
76109467b48Spatrick for (unsigned I : Partition.second.set_bits()) {
76209467b48Spatrick OS << Separator << I;
76309467b48Spatrick Separator = ", ";
76409467b48Spatrick }
76509467b48Spatrick OS << "\n";
76609467b48Spatrick }
76709467b48Spatrick }
76809467b48Spatrick
generatePartitionSelectorCode(raw_ostream & OS,StringRef Indent) const76909467b48Spatrick void GIMatchTreeVRegDefPartitioner::generatePartitionSelectorCode(
77009467b48Spatrick raw_ostream &OS, StringRef Indent) const {
771*d415bd75Srobert OS << Indent << "Partition = -1;\n"
772*d415bd75Srobert << Indent << "if (MIs.size() <= " << NewInstrID << ") MIs.resize("
773*d415bd75Srobert << (NewInstrID + 1) << ");\n"
77409467b48Spatrick << Indent << "MIs[" << NewInstrID << "] = nullptr;\n"
775*d415bd75Srobert << Indent << "if (MIs[" << InstrID << "]->getOperand(" << OpIdx
776*d415bd75Srobert << ").isReg())\n"
77709467b48Spatrick << Indent << " MIs[" << NewInstrID << "] = MRI.getVRegDef(MIs[" << InstrID
778*d415bd75Srobert << "]->getOperand(" << OpIdx << ").getReg());\n";
77909467b48Spatrick
78009467b48Spatrick for (const auto &Pair : ResultToPartition)
78109467b48Spatrick OS << Indent << "if (MIs[" << NewInstrID << "] "
782*d415bd75Srobert << (Pair.first ? "!=" : "==")
78309467b48Spatrick << " nullptr) Partition = " << Pair.second << ";\n";
78409467b48Spatrick
78509467b48Spatrick OS << Indent << "if (Partition == -1) return false;\n";
78609467b48Spatrick }
787