10b57cec5SDimitry Andric //===- DAGISelMatcherOpt.cpp - Optimize a DAG Matcher ---------------------===//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric //
90b57cec5SDimitry Andric // This file implements the DAG Matcher optimizer.
100b57cec5SDimitry Andric //
110b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
120b57cec5SDimitry Andric
13*0fca6ea1SDimitry Andric #include "Basic/SDNodeProperties.h"
14*0fca6ea1SDimitry Andric #include "Common/CodeGenDAGPatterns.h"
15*0fca6ea1SDimitry Andric #include "Common/DAGISelMatcher.h"
160b57cec5SDimitry Andric #include "llvm/ADT/StringSet.h"
170b57cec5SDimitry Andric #include "llvm/Support/Debug.h"
180b57cec5SDimitry Andric #include "llvm/Support/raw_ostream.h"
190b57cec5SDimitry Andric using namespace llvm;
200b57cec5SDimitry Andric
210b57cec5SDimitry Andric #define DEBUG_TYPE "isel-opt"
220b57cec5SDimitry Andric
230b57cec5SDimitry Andric /// ContractNodes - Turn multiple matcher node patterns like 'MoveChild+Record'
240b57cec5SDimitry Andric /// into single compound nodes like RecordChild.
ContractNodes(std::unique_ptr<Matcher> & MatcherPtr,const CodeGenDAGPatterns & CGP)250b57cec5SDimitry Andric static void ContractNodes(std::unique_ptr<Matcher> &MatcherPtr,
260b57cec5SDimitry Andric const CodeGenDAGPatterns &CGP) {
270b57cec5SDimitry Andric // If we reached the end of the chain, we're done.
280b57cec5SDimitry Andric Matcher *N = MatcherPtr.get();
2906c3fb27SDimitry Andric if (!N)
3006c3fb27SDimitry Andric return;
310b57cec5SDimitry Andric
320b57cec5SDimitry Andric // If we have a scope node, walk down all of the children.
330b57cec5SDimitry Andric if (ScopeMatcher *Scope = dyn_cast<ScopeMatcher>(N)) {
340b57cec5SDimitry Andric for (unsigned i = 0, e = Scope->getNumChildren(); i != e; ++i) {
350b57cec5SDimitry Andric std::unique_ptr<Matcher> Child(Scope->takeChild(i));
360b57cec5SDimitry Andric ContractNodes(Child, CGP);
370b57cec5SDimitry Andric Scope->resetChild(i, Child.release());
380b57cec5SDimitry Andric }
390b57cec5SDimitry Andric return;
400b57cec5SDimitry Andric }
410b57cec5SDimitry Andric
420b57cec5SDimitry Andric // If we found a movechild node with a node that comes in a 'foochild' form,
430b57cec5SDimitry Andric // transform it.
440b57cec5SDimitry Andric if (MoveChildMatcher *MC = dyn_cast<MoveChildMatcher>(N)) {
450b57cec5SDimitry Andric Matcher *New = nullptr;
460b57cec5SDimitry Andric if (RecordMatcher *RM = dyn_cast<RecordMatcher>(MC->getNext()))
470b57cec5SDimitry Andric if (MC->getChildNo() < 8) // Only have RecordChild0...7
480b57cec5SDimitry Andric New = new RecordChildMatcher(MC->getChildNo(), RM->getWhatFor(),
490b57cec5SDimitry Andric RM->getResultNo());
500b57cec5SDimitry Andric
510b57cec5SDimitry Andric if (CheckTypeMatcher *CT = dyn_cast<CheckTypeMatcher>(MC->getNext()))
520b57cec5SDimitry Andric if (MC->getChildNo() < 8 && // Only have CheckChildType0...7
530b57cec5SDimitry Andric CT->getResNo() == 0) // CheckChildType checks res #0
540b57cec5SDimitry Andric New = new CheckChildTypeMatcher(MC->getChildNo(), CT->getType());
550b57cec5SDimitry Andric
560b57cec5SDimitry Andric if (CheckSameMatcher *CS = dyn_cast<CheckSameMatcher>(MC->getNext()))
570b57cec5SDimitry Andric if (MC->getChildNo() < 4) // Only have CheckChildSame0...3
580b57cec5SDimitry Andric New = new CheckChildSameMatcher(MC->getChildNo(), CS->getMatchNumber());
590b57cec5SDimitry Andric
600b57cec5SDimitry Andric if (CheckIntegerMatcher *CI = dyn_cast<CheckIntegerMatcher>(MC->getNext()))
610b57cec5SDimitry Andric if (MC->getChildNo() < 5) // Only have CheckChildInteger0...4
620b57cec5SDimitry Andric New = new CheckChildIntegerMatcher(MC->getChildNo(), CI->getValue());
630b57cec5SDimitry Andric
640b57cec5SDimitry Andric if (auto *CCC = dyn_cast<CheckCondCodeMatcher>(MC->getNext()))
650b57cec5SDimitry Andric if (MC->getChildNo() == 2) // Only have CheckChild2CondCode
660b57cec5SDimitry Andric New = new CheckChild2CondCodeMatcher(CCC->getCondCodeName());
670b57cec5SDimitry Andric
680b57cec5SDimitry Andric if (New) {
690b57cec5SDimitry Andric // Insert the new node.
700b57cec5SDimitry Andric New->setNext(MatcherPtr.release());
710b57cec5SDimitry Andric MatcherPtr.reset(New);
720b57cec5SDimitry Andric // Remove the old one.
730b57cec5SDimitry Andric MC->setNext(MC->getNext()->takeNext());
740b57cec5SDimitry Andric return ContractNodes(MatcherPtr, CGP);
750b57cec5SDimitry Andric }
760b57cec5SDimitry Andric }
770b57cec5SDimitry Andric
780b57cec5SDimitry Andric // Zap movechild -> moveparent.
790b57cec5SDimitry Andric if (MoveChildMatcher *MC = dyn_cast<MoveChildMatcher>(N))
8006c3fb27SDimitry Andric if (MoveParentMatcher *MP = dyn_cast<MoveParentMatcher>(MC->getNext())) {
810b57cec5SDimitry Andric MatcherPtr.reset(MP->takeNext());
820b57cec5SDimitry Andric return ContractNodes(MatcherPtr, CGP);
830b57cec5SDimitry Andric }
840b57cec5SDimitry Andric
850b57cec5SDimitry Andric // Turn EmitNode->CompleteMatch into MorphNodeTo if we can.
860b57cec5SDimitry Andric if (EmitNodeMatcher *EN = dyn_cast<EmitNodeMatcher>(N))
870b57cec5SDimitry Andric if (CompleteMatchMatcher *CM =
880b57cec5SDimitry Andric dyn_cast<CompleteMatchMatcher>(EN->getNext())) {
890b57cec5SDimitry Andric // We can only use MorphNodeTo if the result values match up.
900b57cec5SDimitry Andric unsigned RootResultFirst = EN->getFirstResultSlot();
910b57cec5SDimitry Andric bool ResultsMatch = true;
920b57cec5SDimitry Andric for (unsigned i = 0, e = CM->getNumResults(); i != e; ++i)
930b57cec5SDimitry Andric if (CM->getResult(i) != RootResultFirst + i)
940b57cec5SDimitry Andric ResultsMatch = false;
950b57cec5SDimitry Andric
960b57cec5SDimitry Andric // If the selected node defines a subset of the glue/chain results, we
970b57cec5SDimitry Andric // can't use MorphNodeTo. For example, we can't use MorphNodeTo if the
980b57cec5SDimitry Andric // matched pattern has a chain but the root node doesn't.
990b57cec5SDimitry Andric const PatternToMatch &Pattern = CM->getPattern();
1000b57cec5SDimitry Andric
1010b57cec5SDimitry Andric if (!EN->hasChain() &&
102*0fca6ea1SDimitry Andric Pattern.getSrcPattern().NodeHasProperty(SDNPHasChain, CGP))
1030b57cec5SDimitry Andric ResultsMatch = false;
1040b57cec5SDimitry Andric
1050b57cec5SDimitry Andric // If the matched node has glue and the output root doesn't, we can't
1060b57cec5SDimitry Andric // use MorphNodeTo.
1070b57cec5SDimitry Andric //
1080b57cec5SDimitry Andric // NOTE: Strictly speaking, we don't have to check for glue here
1090b57cec5SDimitry Andric // because the code in the pattern generator doesn't handle it right. We
1100b57cec5SDimitry Andric // do it anyway for thoroughness.
11106c3fb27SDimitry Andric if (!EN->hasOutGlue() &&
112*0fca6ea1SDimitry Andric Pattern.getSrcPattern().NodeHasProperty(SDNPOutGlue, CGP))
1130b57cec5SDimitry Andric ResultsMatch = false;
1140b57cec5SDimitry Andric
11506c3fb27SDimitry Andric #if 0
1160b57cec5SDimitry Andric // If the root result node defines more results than the source root node
1170b57cec5SDimitry Andric // *and* has a chain or glue input, then we can't match it because it
1180b57cec5SDimitry Andric // would end up replacing the extra result with the chain/glue.
1190b57cec5SDimitry Andric if ((EN->hasGlue() || EN->hasChain()) &&
1200b57cec5SDimitry Andric EN->getNumNonChainGlueVTs() > ... need to get no results reliably ...)
1210b57cec5SDimitry Andric ResultMatch = false;
1220b57cec5SDimitry Andric #endif
1230b57cec5SDimitry Andric
1240b57cec5SDimitry Andric if (ResultsMatch) {
1250b57cec5SDimitry Andric const SmallVectorImpl<MVT::SimpleValueType> &VTs = EN->getVTList();
1260b57cec5SDimitry Andric const SmallVectorImpl<unsigned> &Operands = EN->getOperandList();
12706c3fb27SDimitry Andric MatcherPtr.reset(new MorphNodeToMatcher(
12806c3fb27SDimitry Andric EN->getInstruction(), VTs, Operands, EN->hasChain(),
12906c3fb27SDimitry Andric EN->hasInGlue(), EN->hasOutGlue(), EN->hasMemRefs(),
13006c3fb27SDimitry Andric EN->getNumFixedArityOperands(), Pattern));
1310b57cec5SDimitry Andric return;
1320b57cec5SDimitry Andric }
1330b57cec5SDimitry Andric
1340b57cec5SDimitry Andric // FIXME2: Kill off all the SelectionDAG::SelectNodeTo and getMachineNode
1350b57cec5SDimitry Andric // variants.
1360b57cec5SDimitry Andric }
1370b57cec5SDimitry Andric
1380b57cec5SDimitry Andric ContractNodes(N->getNextPtr(), CGP);
1390b57cec5SDimitry Andric
1400b57cec5SDimitry Andric // If we have a CheckType/CheckChildType/Record node followed by a
1410b57cec5SDimitry Andric // CheckOpcode, invert the two nodes. We prefer to do structural checks
1420b57cec5SDimitry Andric // before type checks, as this opens opportunities for factoring on targets
1430b57cec5SDimitry Andric // like X86 where many operations are valid on multiple types.
1440b57cec5SDimitry Andric if ((isa<CheckTypeMatcher>(N) || isa<CheckChildTypeMatcher>(N) ||
1450b57cec5SDimitry Andric isa<RecordMatcher>(N)) &&
1460b57cec5SDimitry Andric isa<CheckOpcodeMatcher>(N->getNext())) {
1470b57cec5SDimitry Andric // Unlink the two nodes from the list.
1480b57cec5SDimitry Andric Matcher *CheckType = MatcherPtr.release();
1490b57cec5SDimitry Andric Matcher *CheckOpcode = CheckType->takeNext();
1500b57cec5SDimitry Andric Matcher *Tail = CheckOpcode->takeNext();
1510b57cec5SDimitry Andric
1520b57cec5SDimitry Andric // Relink them.
1530b57cec5SDimitry Andric MatcherPtr.reset(CheckOpcode);
1540b57cec5SDimitry Andric CheckOpcode->setNext(CheckType);
1550b57cec5SDimitry Andric CheckType->setNext(Tail);
1560b57cec5SDimitry Andric return ContractNodes(MatcherPtr, CGP);
1570b57cec5SDimitry Andric }
1585f757f3fSDimitry Andric
1595f757f3fSDimitry Andric // If we have a MoveParent followed by a MoveChild, we convert it to
1605f757f3fSDimitry Andric // MoveSibling.
1615f757f3fSDimitry Andric if (auto *MP = dyn_cast<MoveParentMatcher>(N)) {
1625f757f3fSDimitry Andric if (auto *MC = dyn_cast<MoveChildMatcher>(MP->getNext())) {
1635f757f3fSDimitry Andric auto *MS = new MoveSiblingMatcher(MC->getChildNo());
1645f757f3fSDimitry Andric MS->setNext(MC->takeNext());
1655f757f3fSDimitry Andric MatcherPtr.reset(MS);
1665f757f3fSDimitry Andric return ContractNodes(MatcherPtr, CGP);
1675f757f3fSDimitry Andric }
1685f757f3fSDimitry Andric if (auto *RC = dyn_cast<RecordChildMatcher>(MP->getNext())) {
1695f757f3fSDimitry Andric if (auto *MC = dyn_cast<MoveChildMatcher>(RC->getNext())) {
1705f757f3fSDimitry Andric if (RC->getChildNo() == MC->getChildNo()) {
1715f757f3fSDimitry Andric auto *MS = new MoveSiblingMatcher(MC->getChildNo());
1725f757f3fSDimitry Andric auto *RM = new RecordMatcher(RC->getWhatFor(), RC->getResultNo());
1735f757f3fSDimitry Andric // Insert the new node.
1745f757f3fSDimitry Andric RM->setNext(MC->takeNext());
1755f757f3fSDimitry Andric MS->setNext(RM);
1765f757f3fSDimitry Andric MatcherPtr.reset(MS);
1775f757f3fSDimitry Andric return ContractNodes(MatcherPtr, CGP);
1785f757f3fSDimitry Andric }
1795f757f3fSDimitry Andric }
1805f757f3fSDimitry Andric }
1815f757f3fSDimitry Andric }
1820b57cec5SDimitry Andric }
1830b57cec5SDimitry Andric
1840b57cec5SDimitry Andric /// FindNodeWithKind - Scan a series of matchers looking for a matcher with a
1850b57cec5SDimitry Andric /// specified kind. Return null if we didn't find one otherwise return the
1860b57cec5SDimitry Andric /// matcher.
FindNodeWithKind(Matcher * M,Matcher::KindTy Kind)1870b57cec5SDimitry Andric static Matcher *FindNodeWithKind(Matcher *M, Matcher::KindTy Kind) {
1880b57cec5SDimitry Andric for (; M; M = M->getNext())
1890b57cec5SDimitry Andric if (M->getKind() == Kind)
1900b57cec5SDimitry Andric return M;
1910b57cec5SDimitry Andric return nullptr;
1920b57cec5SDimitry Andric }
1930b57cec5SDimitry Andric
1940b57cec5SDimitry Andric /// FactorNodes - Turn matches like this:
1950b57cec5SDimitry Andric /// Scope
1960b57cec5SDimitry Andric /// OPC_CheckType i32
1970b57cec5SDimitry Andric /// ABC
1980b57cec5SDimitry Andric /// OPC_CheckType i32
1990b57cec5SDimitry Andric /// XYZ
2000b57cec5SDimitry Andric /// into:
2010b57cec5SDimitry Andric /// OPC_CheckType i32
2020b57cec5SDimitry Andric /// Scope
2030b57cec5SDimitry Andric /// ABC
2040b57cec5SDimitry Andric /// XYZ
2050b57cec5SDimitry Andric ///
FactorNodes(std::unique_ptr<Matcher> & InputMatcherPtr)2060b57cec5SDimitry Andric static void FactorNodes(std::unique_ptr<Matcher> &InputMatcherPtr) {
2070b57cec5SDimitry Andric // Look for a push node. Iterates instead of recurses to reduce stack usage.
2080b57cec5SDimitry Andric ScopeMatcher *Scope = nullptr;
2090b57cec5SDimitry Andric std::unique_ptr<Matcher> *RebindableMatcherPtr = &InputMatcherPtr;
2100b57cec5SDimitry Andric while (!Scope) {
2110b57cec5SDimitry Andric // If we reached the end of the chain, we're done.
2120b57cec5SDimitry Andric Matcher *N = RebindableMatcherPtr->get();
21306c3fb27SDimitry Andric if (!N)
21406c3fb27SDimitry Andric return;
2150b57cec5SDimitry Andric
2160b57cec5SDimitry Andric // If this is not a push node, just scan for one.
2170b57cec5SDimitry Andric Scope = dyn_cast<ScopeMatcher>(N);
2180b57cec5SDimitry Andric if (!Scope)
2190b57cec5SDimitry Andric RebindableMatcherPtr = &(N->getNextPtr());
2200b57cec5SDimitry Andric }
2210b57cec5SDimitry Andric std::unique_ptr<Matcher> &MatcherPtr = *RebindableMatcherPtr;
2220b57cec5SDimitry Andric
2230b57cec5SDimitry Andric // Okay, pull together the children of the scope node into a vector so we can
2240b57cec5SDimitry Andric // inspect it more easily.
2250b57cec5SDimitry Andric SmallVector<Matcher *, 32> OptionsToMatch;
2260b57cec5SDimitry Andric
2270b57cec5SDimitry Andric for (unsigned i = 0, e = Scope->getNumChildren(); i != e; ++i) {
2280b57cec5SDimitry Andric // Factor the subexpression.
2290b57cec5SDimitry Andric std::unique_ptr<Matcher> Child(Scope->takeChild(i));
2300b57cec5SDimitry Andric FactorNodes(Child);
2310b57cec5SDimitry Andric
2320b57cec5SDimitry Andric // If the child is a ScopeMatcher we can just merge its contents.
2330b57cec5SDimitry Andric if (auto *SM = dyn_cast<ScopeMatcher>(Child.get())) {
2340b57cec5SDimitry Andric for (unsigned j = 0, e = SM->getNumChildren(); j != e; ++j)
2350b57cec5SDimitry Andric OptionsToMatch.push_back(SM->takeChild(j));
2360b57cec5SDimitry Andric } else {
2370b57cec5SDimitry Andric OptionsToMatch.push_back(Child.release());
2380b57cec5SDimitry Andric }
2390b57cec5SDimitry Andric }
2400b57cec5SDimitry Andric
2410b57cec5SDimitry Andric // Loop over options to match, merging neighboring patterns with identical
2420b57cec5SDimitry Andric // starting nodes into a shared matcher.
24306c3fb27SDimitry Andric auto E = OptionsToMatch.end();
24406c3fb27SDimitry Andric for (auto I = OptionsToMatch.begin(); I != E; ++I) {
24506c3fb27SDimitry Andric // If there are no other matchers left, there's nothing to merge with.
24606c3fb27SDimitry Andric auto J = std::next(I);
24706c3fb27SDimitry Andric if (J == E)
24806c3fb27SDimitry Andric break;
2490b57cec5SDimitry Andric
25006c3fb27SDimitry Andric // Remember where we started. We'll use this to move non-equal elements.
25106c3fb27SDimitry Andric auto K = J;
25206c3fb27SDimitry Andric
25306c3fb27SDimitry Andric // Find the set of matchers that start with this node.
25406c3fb27SDimitry Andric Matcher *Optn = *I;
2550b57cec5SDimitry Andric
2560b57cec5SDimitry Andric // See if the next option starts with the same matcher. If the two
2570b57cec5SDimitry Andric // neighbors *do* start with the same matcher, we can factor the matcher out
2580b57cec5SDimitry Andric // of at least these two patterns. See what the maximal set we can merge
2590b57cec5SDimitry Andric // together is.
2600b57cec5SDimitry Andric SmallVector<Matcher *, 8> EqualMatchers;
2610b57cec5SDimitry Andric EqualMatchers.push_back(Optn);
2620b57cec5SDimitry Andric
2630b57cec5SDimitry Andric // Factor all of the known-equal matchers after this one into the same
2640b57cec5SDimitry Andric // group.
26506c3fb27SDimitry Andric while (J != E && (*J)->isEqual(Optn))
26606c3fb27SDimitry Andric EqualMatchers.push_back(*J++);
2670b57cec5SDimitry Andric
2680b57cec5SDimitry Andric // If we found a non-equal matcher, see if it is contradictory with the
2690b57cec5SDimitry Andric // current node. If so, we know that the ordering relation between the
2700b57cec5SDimitry Andric // current sets of nodes and this node don't matter. Look past it to see if
2710b57cec5SDimitry Andric // we can merge anything else into this matching group.
27206c3fb27SDimitry Andric while (J != E) {
27306c3fb27SDimitry Andric Matcher *ScanMatcher = *J;
2740b57cec5SDimitry Andric
2750b57cec5SDimitry Andric // If we found an entry that matches out matcher, merge it into the set to
2760b57cec5SDimitry Andric // handle.
2770b57cec5SDimitry Andric if (Optn->isEqual(ScanMatcher)) {
27806c3fb27SDimitry Andric // It is equal after all, add the option to EqualMatchers.
2790b57cec5SDimitry Andric EqualMatchers.push_back(ScanMatcher);
28006c3fb27SDimitry Andric ++J;
2810b57cec5SDimitry Andric continue;
2820b57cec5SDimitry Andric }
2830b57cec5SDimitry Andric
2840b57cec5SDimitry Andric // If the option we're checking for contradicts the start of the list,
28506c3fb27SDimitry Andric // move it earlier in OptionsToMatch for the next iteration of the outer
28606c3fb27SDimitry Andric // loop. Then continue searching for equal or contradictory matchers.
2870b57cec5SDimitry Andric if (Optn->isContradictory(ScanMatcher)) {
28806c3fb27SDimitry Andric *K++ = *J++;
2890b57cec5SDimitry Andric continue;
2900b57cec5SDimitry Andric }
2910b57cec5SDimitry Andric
2920b57cec5SDimitry Andric // If we're scanning for a simple node, see if it occurs later in the
2930b57cec5SDimitry Andric // sequence. If so, and if we can move it up, it might be contradictory
2940b57cec5SDimitry Andric // or the same as what we're looking for. If so, reorder it.
2950b57cec5SDimitry Andric if (Optn->isSimplePredicateOrRecordNode()) {
2960b57cec5SDimitry Andric Matcher *M2 = FindNodeWithKind(ScanMatcher, Optn->getKind());
29706c3fb27SDimitry Andric if (M2 && M2 != ScanMatcher && M2->canMoveBefore(ScanMatcher) &&
2980b57cec5SDimitry Andric (M2->isEqual(Optn) || M2->isContradictory(Optn))) {
2990b57cec5SDimitry Andric Matcher *MatcherWithoutM2 = ScanMatcher->unlinkNode(M2);
3000b57cec5SDimitry Andric M2->setNext(MatcherWithoutM2);
30106c3fb27SDimitry Andric *J = M2;
3020b57cec5SDimitry Andric continue;
3030b57cec5SDimitry Andric }
3040b57cec5SDimitry Andric }
3050b57cec5SDimitry Andric
3060b57cec5SDimitry Andric // Otherwise, we don't know how to handle this entry, we have to bail.
3070b57cec5SDimitry Andric break;
3080b57cec5SDimitry Andric }
3090b57cec5SDimitry Andric
31006c3fb27SDimitry Andric if (J != E &&
31106c3fb27SDimitry Andric // Don't print if it's obvious nothing extract could be merged anyway.
31206c3fb27SDimitry Andric std::next(J) != E) {
3130b57cec5SDimitry Andric LLVM_DEBUG(errs() << "Couldn't merge this:\n"; Optn->print(errs(), 4);
314*0fca6ea1SDimitry Andric errs() << "into this:\n"; (*J)->print(errs(), 4);
31506c3fb27SDimitry Andric (*std::next(J))->printOne(errs());
31606c3fb27SDimitry Andric if (std::next(J, 2) != E)(*std::next(J, 2))->printOne(errs());
3170b57cec5SDimitry Andric errs() << "\n");
3180b57cec5SDimitry Andric }
3190b57cec5SDimitry Andric
32006c3fb27SDimitry Andric // If we removed any equal matchers, we may need to slide the rest of the
32106c3fb27SDimitry Andric // elements down for the next iteration of the outer loop.
32206c3fb27SDimitry Andric if (J != K) {
32306c3fb27SDimitry Andric while (J != E)
32406c3fb27SDimitry Andric *K++ = *J++;
32506c3fb27SDimitry Andric
32606c3fb27SDimitry Andric // Update end pointer for outer loop.
32706c3fb27SDimitry Andric E = K;
32806c3fb27SDimitry Andric }
32906c3fb27SDimitry Andric
3300b57cec5SDimitry Andric // If we only found one option starting with this matcher, no factoring is
33106c3fb27SDimitry Andric // possible. Put the Matcher back in OptionsToMatch.
3320b57cec5SDimitry Andric if (EqualMatchers.size() == 1) {
33306c3fb27SDimitry Andric *I = EqualMatchers[0];
3340b57cec5SDimitry Andric continue;
3350b57cec5SDimitry Andric }
3360b57cec5SDimitry Andric
3370b57cec5SDimitry Andric // Factor these checks by pulling the first node off each entry and
3380b57cec5SDimitry Andric // discarding it. Take the first one off the first entry to reuse.
3390b57cec5SDimitry Andric Matcher *Shared = Optn;
3400b57cec5SDimitry Andric Optn = Optn->takeNext();
3410b57cec5SDimitry Andric EqualMatchers[0] = Optn;
3420b57cec5SDimitry Andric
3430b57cec5SDimitry Andric // Remove and delete the first node from the other matchers we're factoring.
3440b57cec5SDimitry Andric for (unsigned i = 1, e = EqualMatchers.size(); i != e; ++i) {
3450b57cec5SDimitry Andric Matcher *Tmp = EqualMatchers[i]->takeNext();
3460b57cec5SDimitry Andric delete EqualMatchers[i];
3470b57cec5SDimitry Andric EqualMatchers[i] = Tmp;
34806c3fb27SDimitry Andric assert(!Optn == !Tmp && "Expected all to be null if any are null");
3490b57cec5SDimitry Andric }
3500b57cec5SDimitry Andric
35106c3fb27SDimitry Andric if (EqualMatchers[0]) {
35206c3fb27SDimitry Andric Shared->setNext(new ScopeMatcher(std::move(EqualMatchers)));
3530b57cec5SDimitry Andric
3540b57cec5SDimitry Andric // Recursively factor the newly created node.
3550b57cec5SDimitry Andric FactorNodes(Shared->getNextPtr());
3560b57cec5SDimitry Andric }
3570b57cec5SDimitry Andric
35806c3fb27SDimitry Andric // Put the new Matcher where we started in OptionsToMatch.
35906c3fb27SDimitry Andric *I = Shared;
36006c3fb27SDimitry Andric }
36106c3fb27SDimitry Andric
36206c3fb27SDimitry Andric // Trim the array to match the updated end.
36306c3fb27SDimitry Andric if (E != OptionsToMatch.end())
36406c3fb27SDimitry Andric OptionsToMatch.erase(E, OptionsToMatch.end());
36506c3fb27SDimitry Andric
3660b57cec5SDimitry Andric // If we're down to a single pattern to match, then we don't need this scope
3670b57cec5SDimitry Andric // anymore.
36806c3fb27SDimitry Andric if (OptionsToMatch.size() == 1) {
36906c3fb27SDimitry Andric MatcherPtr.reset(OptionsToMatch[0]);
3700b57cec5SDimitry Andric return;
3710b57cec5SDimitry Andric }
3720b57cec5SDimitry Andric
37306c3fb27SDimitry Andric if (OptionsToMatch.empty()) {
3740b57cec5SDimitry Andric MatcherPtr.reset();
3750b57cec5SDimitry Andric return;
3760b57cec5SDimitry Andric }
3770b57cec5SDimitry Andric
3780b57cec5SDimitry Andric // If our factoring failed (didn't achieve anything) see if we can simplify in
3790b57cec5SDimitry Andric // other ways.
3800b57cec5SDimitry Andric
3810b57cec5SDimitry Andric // Check to see if all of the leading entries are now opcode checks. If so,
3820b57cec5SDimitry Andric // we can convert this Scope to be a OpcodeSwitch instead.
3830b57cec5SDimitry Andric bool AllOpcodeChecks = true, AllTypeChecks = true;
38406c3fb27SDimitry Andric for (unsigned i = 0, e = OptionsToMatch.size(); i != e; ++i) {
3850b57cec5SDimitry Andric // Check to see if this breaks a series of CheckOpcodeMatchers.
38606c3fb27SDimitry Andric if (AllOpcodeChecks && !isa<CheckOpcodeMatcher>(OptionsToMatch[i])) {
3870b57cec5SDimitry Andric #if 0
3880b57cec5SDimitry Andric if (i > 3) {
3890b57cec5SDimitry Andric errs() << "FAILING OPC #" << i << "\n";
39006c3fb27SDimitry Andric OptionsToMatch[i]->dump();
3910b57cec5SDimitry Andric }
3920b57cec5SDimitry Andric #endif
3930b57cec5SDimitry Andric AllOpcodeChecks = false;
3940b57cec5SDimitry Andric }
3950b57cec5SDimitry Andric
3960b57cec5SDimitry Andric // Check to see if this breaks a series of CheckTypeMatcher's.
3970b57cec5SDimitry Andric if (AllTypeChecks) {
39806c3fb27SDimitry Andric CheckTypeMatcher *CTM = cast_or_null<CheckTypeMatcher>(
39906c3fb27SDimitry Andric FindNodeWithKind(OptionsToMatch[i], Matcher::CheckType));
4000b57cec5SDimitry Andric if (!CTM ||
4010b57cec5SDimitry Andric // iPTR checks could alias any other case without us knowing, don't
4020b57cec5SDimitry Andric // bother with them.
4030b57cec5SDimitry Andric CTM->getType() == MVT::iPTR ||
4040b57cec5SDimitry Andric // SwitchType only works for result #0.
4050b57cec5SDimitry Andric CTM->getResNo() != 0 ||
4060b57cec5SDimitry Andric // If the CheckType isn't at the start of the list, see if we can move
4070b57cec5SDimitry Andric // it there.
40806c3fb27SDimitry Andric !CTM->canMoveBefore(OptionsToMatch[i])) {
4090b57cec5SDimitry Andric #if 0
4100b57cec5SDimitry Andric if (i > 3 && AllTypeChecks) {
4110b57cec5SDimitry Andric errs() << "FAILING TYPE #" << i << "\n";
41206c3fb27SDimitry Andric OptionsToMatch[i]->dump();
4130b57cec5SDimitry Andric }
4140b57cec5SDimitry Andric #endif
4150b57cec5SDimitry Andric AllTypeChecks = false;
4160b57cec5SDimitry Andric }
4170b57cec5SDimitry Andric }
4180b57cec5SDimitry Andric }
4190b57cec5SDimitry Andric
4200b57cec5SDimitry Andric // If all the options are CheckOpcode's, we can form the SwitchOpcode, woot.
4210b57cec5SDimitry Andric if (AllOpcodeChecks) {
4220b57cec5SDimitry Andric StringSet<> Opcodes;
4230b57cec5SDimitry Andric SmallVector<std::pair<const SDNodeInfo *, Matcher *>, 8> Cases;
42406c3fb27SDimitry Andric for (unsigned i = 0, e = OptionsToMatch.size(); i != e; ++i) {
42506c3fb27SDimitry Andric CheckOpcodeMatcher *COM = cast<CheckOpcodeMatcher>(OptionsToMatch[i]);
4260b57cec5SDimitry Andric assert(Opcodes.insert(COM->getOpcode().getEnumName()).second &&
4270b57cec5SDimitry Andric "Duplicate opcodes not factored?");
428*0fca6ea1SDimitry Andric Cases.push_back(std::pair(&COM->getOpcode(), COM->takeNext()));
4290b57cec5SDimitry Andric delete COM;
4300b57cec5SDimitry Andric }
4310b57cec5SDimitry Andric
43206c3fb27SDimitry Andric MatcherPtr.reset(new SwitchOpcodeMatcher(std::move(Cases)));
4330b57cec5SDimitry Andric return;
4340b57cec5SDimitry Andric }
4350b57cec5SDimitry Andric
4360b57cec5SDimitry Andric // If all the options are CheckType's, we can form the SwitchType, woot.
4370b57cec5SDimitry Andric if (AllTypeChecks) {
4380b57cec5SDimitry Andric DenseMap<unsigned, unsigned> TypeEntry;
4390b57cec5SDimitry Andric SmallVector<std::pair<MVT::SimpleValueType, Matcher *>, 8> Cases;
44006c3fb27SDimitry Andric for (unsigned i = 0, e = OptionsToMatch.size(); i != e; ++i) {
44106c3fb27SDimitry Andric Matcher *M = FindNodeWithKind(OptionsToMatch[i], Matcher::CheckType);
4428bcb0991SDimitry Andric assert(M && isa<CheckTypeMatcher>(M) && "Unknown Matcher type");
4438bcb0991SDimitry Andric
4448bcb0991SDimitry Andric auto *CTM = cast<CheckTypeMatcher>(M);
44506c3fb27SDimitry Andric Matcher *MatcherWithoutCTM = OptionsToMatch[i]->unlinkNode(CTM);
4460b57cec5SDimitry Andric MVT::SimpleValueType CTMTy = CTM->getType();
4470b57cec5SDimitry Andric delete CTM;
4480b57cec5SDimitry Andric
4490b57cec5SDimitry Andric unsigned &Entry = TypeEntry[CTMTy];
4500b57cec5SDimitry Andric if (Entry != 0) {
4510b57cec5SDimitry Andric // If we have unfactored duplicate types, then we should factor them.
4520b57cec5SDimitry Andric Matcher *PrevMatcher = Cases[Entry - 1].second;
4530b57cec5SDimitry Andric if (ScopeMatcher *SM = dyn_cast<ScopeMatcher>(PrevMatcher)) {
4540b57cec5SDimitry Andric SM->setNumChildren(SM->getNumChildren() + 1);
4550b57cec5SDimitry Andric SM->resetChild(SM->getNumChildren() - 1, MatcherWithoutCTM);
4560b57cec5SDimitry Andric continue;
4570b57cec5SDimitry Andric }
4580b57cec5SDimitry Andric
45906c3fb27SDimitry Andric SmallVector<Matcher *, 2> Entries = {PrevMatcher, MatcherWithoutCTM};
46006c3fb27SDimitry Andric Cases[Entry - 1].second = new ScopeMatcher(std::move(Entries));
4610b57cec5SDimitry Andric continue;
4620b57cec5SDimitry Andric }
4630b57cec5SDimitry Andric
4640b57cec5SDimitry Andric Entry = Cases.size() + 1;
465*0fca6ea1SDimitry Andric Cases.push_back(std::pair(CTMTy, MatcherWithoutCTM));
4660b57cec5SDimitry Andric }
4670b57cec5SDimitry Andric
4680b57cec5SDimitry Andric // Make sure we recursively factor any scopes we may have created.
4690b57cec5SDimitry Andric for (auto &M : Cases) {
4700b57cec5SDimitry Andric if (ScopeMatcher *SM = dyn_cast<ScopeMatcher>(M.second)) {
4710b57cec5SDimitry Andric std::unique_ptr<Matcher> Scope(SM);
4720b57cec5SDimitry Andric FactorNodes(Scope);
4730b57cec5SDimitry Andric M.second = Scope.release();
4740b57cec5SDimitry Andric assert(M.second && "null matcher");
4750b57cec5SDimitry Andric }
4760b57cec5SDimitry Andric }
4770b57cec5SDimitry Andric
4780b57cec5SDimitry Andric if (Cases.size() != 1) {
47906c3fb27SDimitry Andric MatcherPtr.reset(new SwitchTypeMatcher(std::move(Cases)));
4800b57cec5SDimitry Andric } else {
4810b57cec5SDimitry Andric // If we factored and ended up with one case, create it now.
4820b57cec5SDimitry Andric MatcherPtr.reset(new CheckTypeMatcher(Cases[0].first, 0));
4830b57cec5SDimitry Andric MatcherPtr->setNext(Cases[0].second);
4840b57cec5SDimitry Andric }
4850b57cec5SDimitry Andric return;
4860b57cec5SDimitry Andric }
4870b57cec5SDimitry Andric
4880b57cec5SDimitry Andric // Reassemble the Scope node with the adjusted children.
48906c3fb27SDimitry Andric Scope->setNumChildren(OptionsToMatch.size());
49006c3fb27SDimitry Andric for (unsigned i = 0, e = OptionsToMatch.size(); i != e; ++i)
49106c3fb27SDimitry Andric Scope->resetChild(i, OptionsToMatch[i]);
4920b57cec5SDimitry Andric }
4930b57cec5SDimitry Andric
OptimizeMatcher(std::unique_ptr<Matcher> & MatcherPtr,const CodeGenDAGPatterns & CGP)49406c3fb27SDimitry Andric void llvm::OptimizeMatcher(std::unique_ptr<Matcher> &MatcherPtr,
4950b57cec5SDimitry Andric const CodeGenDAGPatterns &CGP) {
4960b57cec5SDimitry Andric ContractNodes(MatcherPtr, CGP);
4970b57cec5SDimitry Andric FactorNodes(MatcherPtr);
4980b57cec5SDimitry Andric }
499