10b57cec5SDimitry Andric //===- DAGISelEmitter.cpp - Generate an instruction selector --------------===// 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 tablegen backend emits a DAG instruction selector. 100b57cec5SDimitry Andric // 110b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 120b57cec5SDimitry Andric 13*0fca6ea1SDimitry Andric #include "Common/CodeGenDAGPatterns.h" 14*0fca6ea1SDimitry Andric #include "Common/CodeGenInstruction.h" 15*0fca6ea1SDimitry Andric #include "Common/CodeGenTarget.h" 16*0fca6ea1SDimitry Andric #include "Common/DAGISelMatcher.h" 170b57cec5SDimitry Andric #include "llvm/Support/Debug.h" 180b57cec5SDimitry Andric #include "llvm/TableGen/Record.h" 190b57cec5SDimitry Andric #include "llvm/TableGen/TableGenBackend.h" 200b57cec5SDimitry Andric using namespace llvm; 210b57cec5SDimitry Andric 220b57cec5SDimitry Andric #define DEBUG_TYPE "dag-isel-emitter" 230b57cec5SDimitry Andric 240b57cec5SDimitry Andric namespace { 250b57cec5SDimitry Andric /// DAGISelEmitter - The top-level class which coordinates construction 260b57cec5SDimitry Andric /// and emission of the instruction selector. 270b57cec5SDimitry Andric class DAGISelEmitter { 28e8d8bef9SDimitry Andric RecordKeeper &Records; // Just so we can get at the timing functions. 290b57cec5SDimitry Andric CodeGenDAGPatterns CGP; 30*0fca6ea1SDimitry Andric 310b57cec5SDimitry Andric public: 32e8d8bef9SDimitry Andric explicit DAGISelEmitter(RecordKeeper &R) : Records(R), CGP(R) {} 330b57cec5SDimitry Andric void run(raw_ostream &OS); 340b57cec5SDimitry Andric }; 350b57cec5SDimitry Andric } // End anonymous namespace 360b57cec5SDimitry Andric 370b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 380b57cec5SDimitry Andric // DAGISelEmitter Helper methods 390b57cec5SDimitry Andric // 400b57cec5SDimitry Andric 41*0fca6ea1SDimitry Andric /// Compute the number of instructions for this pattern. 420b57cec5SDimitry Andric /// This is a temporary hack. We should really include the instruction 430b57cec5SDimitry Andric /// latencies in this calculation. 44*0fca6ea1SDimitry Andric static unsigned getResultPatternCost(TreePatternNode &P, 45*0fca6ea1SDimitry Andric const CodeGenDAGPatterns &CGP) { 46*0fca6ea1SDimitry Andric if (P.isLeaf()) 47*0fca6ea1SDimitry Andric return 0; 480b57cec5SDimitry Andric 490b57cec5SDimitry Andric unsigned Cost = 0; 50*0fca6ea1SDimitry Andric Record *Op = P.getOperator(); 510b57cec5SDimitry Andric if (Op->isSubClassOf("Instruction")) { 520b57cec5SDimitry Andric Cost++; 530b57cec5SDimitry Andric CodeGenInstruction &II = CGP.getTargetInfo().getInstruction(Op); 540b57cec5SDimitry Andric if (II.usesCustomInserter) 550b57cec5SDimitry Andric Cost += 10; 560b57cec5SDimitry Andric } 57*0fca6ea1SDimitry Andric for (unsigned i = 0, e = P.getNumChildren(); i != e; ++i) 58*0fca6ea1SDimitry Andric Cost += getResultPatternCost(P.getChild(i), CGP); 590b57cec5SDimitry Andric return Cost; 600b57cec5SDimitry Andric } 610b57cec5SDimitry Andric 620b57cec5SDimitry Andric /// getResultPatternCodeSize - Compute the code size of instructions for this 630b57cec5SDimitry Andric /// pattern. 64*0fca6ea1SDimitry Andric static unsigned getResultPatternSize(TreePatternNode &P, 65*0fca6ea1SDimitry Andric const CodeGenDAGPatterns &CGP) { 66*0fca6ea1SDimitry Andric if (P.isLeaf()) 67*0fca6ea1SDimitry Andric return 0; 680b57cec5SDimitry Andric 690b57cec5SDimitry Andric unsigned Cost = 0; 70*0fca6ea1SDimitry Andric Record *Op = P.getOperator(); 710b57cec5SDimitry Andric if (Op->isSubClassOf("Instruction")) { 720b57cec5SDimitry Andric Cost += Op->getValueAsInt("CodeSize"); 730b57cec5SDimitry Andric } 74*0fca6ea1SDimitry Andric for (unsigned i = 0, e = P.getNumChildren(); i != e; ++i) 75*0fca6ea1SDimitry Andric Cost += getResultPatternSize(P.getChild(i), CGP); 760b57cec5SDimitry Andric return Cost; 770b57cec5SDimitry Andric } 780b57cec5SDimitry Andric 790b57cec5SDimitry Andric namespace { 800b57cec5SDimitry Andric // PatternSortingPredicate - return true if we prefer to match LHS before RHS. 810b57cec5SDimitry Andric // In particular, we want to match maximal patterns first and lowest cost within 820b57cec5SDimitry Andric // a particular complexity first. 830b57cec5SDimitry Andric struct PatternSortingPredicate { 840b57cec5SDimitry Andric PatternSortingPredicate(CodeGenDAGPatterns &cgp) : CGP(cgp) {} 850b57cec5SDimitry Andric CodeGenDAGPatterns &CGP; 860b57cec5SDimitry Andric 870b57cec5SDimitry Andric bool operator()(const PatternToMatch *LHS, const PatternToMatch *RHS) { 88*0fca6ea1SDimitry Andric const TreePatternNode < = LHS->getSrcPattern(); 89*0fca6ea1SDimitry Andric const TreePatternNode &RT = RHS->getSrcPattern(); 900b57cec5SDimitry Andric 91*0fca6ea1SDimitry Andric MVT LHSVT = LT.getNumTypes() != 0 ? LT.getSimpleType(0) : MVT::Other; 92*0fca6ea1SDimitry Andric MVT RHSVT = RT.getNumTypes() != 0 ? RT.getSimpleType(0) : MVT::Other; 930b57cec5SDimitry Andric if (LHSVT.isVector() != RHSVT.isVector()) 940b57cec5SDimitry Andric return RHSVT.isVector(); 950b57cec5SDimitry Andric 960b57cec5SDimitry Andric if (LHSVT.isFloatingPoint() != RHSVT.isFloatingPoint()) 970b57cec5SDimitry Andric return RHSVT.isFloatingPoint(); 980b57cec5SDimitry Andric 990b57cec5SDimitry Andric // Otherwise, if the patterns might both match, sort based on complexity, 1000b57cec5SDimitry Andric // which means that we prefer to match patterns that cover more nodes in the 1010b57cec5SDimitry Andric // input over nodes that cover fewer. 1020b57cec5SDimitry Andric int LHSSize = LHS->getPatternComplexity(CGP); 1030b57cec5SDimitry Andric int RHSSize = RHS->getPatternComplexity(CGP); 104*0fca6ea1SDimitry Andric if (LHSSize > RHSSize) 105*0fca6ea1SDimitry Andric return true; // LHS -> bigger -> less cost 106*0fca6ea1SDimitry Andric if (LHSSize < RHSSize) 107*0fca6ea1SDimitry Andric return false; 1080b57cec5SDimitry Andric 1090b57cec5SDimitry Andric // If the patterns have equal complexity, compare generated instruction cost 1100b57cec5SDimitry Andric unsigned LHSCost = getResultPatternCost(LHS->getDstPattern(), CGP); 1110b57cec5SDimitry Andric unsigned RHSCost = getResultPatternCost(RHS->getDstPattern(), CGP); 112*0fca6ea1SDimitry Andric if (LHSCost < RHSCost) 113*0fca6ea1SDimitry Andric return true; 114*0fca6ea1SDimitry Andric if (LHSCost > RHSCost) 115*0fca6ea1SDimitry Andric return false; 1160b57cec5SDimitry Andric 1170b57cec5SDimitry Andric unsigned LHSPatSize = getResultPatternSize(LHS->getDstPattern(), CGP); 1180b57cec5SDimitry Andric unsigned RHSPatSize = getResultPatternSize(RHS->getDstPattern(), CGP); 119*0fca6ea1SDimitry Andric if (LHSPatSize < RHSPatSize) 120*0fca6ea1SDimitry Andric return true; 121*0fca6ea1SDimitry Andric if (LHSPatSize > RHSPatSize) 122*0fca6ea1SDimitry Andric return false; 1230b57cec5SDimitry Andric 1240b57cec5SDimitry Andric // Sort based on the UID of the pattern, to reflect source order. 1250b57cec5SDimitry Andric // Note that this is not guaranteed to be unique, since a single source 1260b57cec5SDimitry Andric // pattern may have been resolved into multiple match patterns due to 1270b57cec5SDimitry Andric // alternative fragments. To ensure deterministic output, always use 1280b57cec5SDimitry Andric // std::stable_sort with this predicate. 129fe6060f1SDimitry Andric return LHS->getID() < RHS->getID(); 1300b57cec5SDimitry Andric } 1310b57cec5SDimitry Andric }; 1320b57cec5SDimitry Andric } // End anonymous namespace 1330b57cec5SDimitry Andric 1340b57cec5SDimitry Andric void DAGISelEmitter::run(raw_ostream &OS) { 13506c3fb27SDimitry Andric Records.startTimer("Parse patterns"); 1360b57cec5SDimitry Andric emitSourceFileHeader("DAG Instruction Selector for the " + 137*0fca6ea1SDimitry Andric CGP.getTargetInfo().getName().str() + " target", 138*0fca6ea1SDimitry Andric OS); 1390b57cec5SDimitry Andric 1400b57cec5SDimitry Andric OS << "// *** NOTE: This file is #included into the middle of the target\n" 1410b57cec5SDimitry Andric << "// *** instruction selector class. These functions are really " 1420b57cec5SDimitry Andric << "methods.\n\n"; 1430b57cec5SDimitry Andric 1440b57cec5SDimitry Andric OS << "// If GET_DAGISEL_DECL is #defined with any value, only function\n" 1450b57cec5SDimitry Andric "// declarations will be included when this file is included.\n" 1460b57cec5SDimitry Andric "// If GET_DAGISEL_BODY is #defined, its value should be the name of\n" 1470b57cec5SDimitry Andric "// the instruction selector class. Function bodies will be emitted\n" 1480b57cec5SDimitry Andric "// and each function's name will be qualified with the name of the\n" 1490b57cec5SDimitry Andric "// class.\n" 1500b57cec5SDimitry Andric "//\n" 1510b57cec5SDimitry Andric "// When neither of the GET_DAGISEL* macros is defined, the functions\n" 1520b57cec5SDimitry Andric "// are emitted inline.\n\n"; 1530b57cec5SDimitry Andric 1540b57cec5SDimitry Andric LLVM_DEBUG(errs() << "\n\nALL PATTERNS TO MATCH:\n\n"; 1550b57cec5SDimitry Andric for (CodeGenDAGPatterns::ptm_iterator I = CGP.ptm_begin(), 1560b57cec5SDimitry Andric E = CGP.ptm_end(); 1570b57cec5SDimitry Andric I != E; ++I) { 1580b57cec5SDimitry Andric errs() << "PATTERN: "; 159*0fca6ea1SDimitry Andric I->getSrcPattern().dump(); 1600b57cec5SDimitry Andric errs() << "\nRESULT: "; 161*0fca6ea1SDimitry Andric I->getDstPattern().dump(); 1620b57cec5SDimitry Andric errs() << "\n"; 1630b57cec5SDimitry Andric }); 1640b57cec5SDimitry Andric 1650b57cec5SDimitry Andric // Add all the patterns to a temporary list so we can sort them. 166e8d8bef9SDimitry Andric Records.startTimer("Sort patterns"); 1670b57cec5SDimitry Andric std::vector<const PatternToMatch *> Patterns; 168fe6060f1SDimitry Andric for (const PatternToMatch &PTM : CGP.ptms()) 169fe6060f1SDimitry Andric Patterns.push_back(&PTM); 1700b57cec5SDimitry Andric 1710b57cec5SDimitry Andric // We want to process the matches in order of minimal cost. Sort the patterns 1720b57cec5SDimitry Andric // so the least cost one is at the start. 173e8d8bef9SDimitry Andric llvm::stable_sort(Patterns, PatternSortingPredicate(CGP)); 1740b57cec5SDimitry Andric 1750b57cec5SDimitry Andric // Convert each variant of each pattern into a Matcher. 176e8d8bef9SDimitry Andric Records.startTimer("Convert to matchers"); 17706c3fb27SDimitry Andric SmallVector<Matcher *, 0> PatternMatchers; 178fe6060f1SDimitry Andric for (const PatternToMatch *PTM : Patterns) { 1790b57cec5SDimitry Andric for (unsigned Variant = 0;; ++Variant) { 180fe6060f1SDimitry Andric if (Matcher *M = ConvertPatternToMatcher(*PTM, Variant, CGP)) 1810b57cec5SDimitry Andric PatternMatchers.push_back(M); 1820b57cec5SDimitry Andric else 1830b57cec5SDimitry Andric break; 1840b57cec5SDimitry Andric } 1850b57cec5SDimitry Andric } 1860b57cec5SDimitry Andric 1870b57cec5SDimitry Andric std::unique_ptr<Matcher> TheMatcher = 18806c3fb27SDimitry Andric std::make_unique<ScopeMatcher>(std::move(PatternMatchers)); 1890b57cec5SDimitry Andric 190e8d8bef9SDimitry Andric Records.startTimer("Optimize matchers"); 1910b57cec5SDimitry Andric OptimizeMatcher(TheMatcher, CGP); 192e8d8bef9SDimitry Andric 1930b57cec5SDimitry Andric // Matcher->dump(); 194e8d8bef9SDimitry Andric 195e8d8bef9SDimitry Andric Records.startTimer("Emit matcher table"); 1960b57cec5SDimitry Andric EmitMatcherTable(TheMatcher.get(), CGP, OS); 1970b57cec5SDimitry Andric } 1980b57cec5SDimitry Andric 19906c3fb27SDimitry Andric static TableGen::Emitter::OptClass<DAGISelEmitter> 20006c3fb27SDimitry Andric X("gen-dag-isel", "Generate a DAG instruction selector"); 201