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. 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. 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 /// 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 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