From 8bc7472a0cce53ea3047da4fc4859eb6b34f8565 Mon Sep 17 00:00:00 2001 From: Chris Lattner Date: Sun, 29 Jan 2006 04:25:26 +0000 Subject: [PATCH] Factor matching code that is common between patterns. This works around GCC not jump-threading across this common code, and produces far nicer output. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@25762 91177308-0d34-0410-b5e6-96231b3b80d8 --- utils/TableGen/DAGISelEmitter.cpp | 142 +++++++++++++++++++++++------- utils/TableGen/DAGISelEmitter.h | 5 +- 2 files changed, 112 insertions(+), 35 deletions(-) diff --git a/utils/TableGen/DAGISelEmitter.cpp b/utils/TableGen/DAGISelEmitter.cpp index 91605c8026d..7301221435b 100644 --- a/utils/TableGen/DAGISelEmitter.cpp +++ b/utils/TableGen/DAGISelEmitter.cpp @@ -2032,9 +2032,12 @@ public: } } else if (IntInit *II = dynamic_cast(Child->getLeafValue())) { - emitCheck("isa(" + RootName + utostr(OpNo) + - ") && cast(" + RootName + utostr(OpNo) + - ")->getSignExtended() == " + itostr(II->getValue())); + emitCheck("isa(" + RootName + utostr(OpNo) + ")"); + unsigned CTmp = TmpNo++; + emitCode("int CN"+utostr(CTmp)+" = cast("+ + RootName + utostr(OpNo) + ")->getSignExtended();"); + + emitCheck("CN" + utostr(CTmp) + " == " +itostr(II->getValue())); } else { Child->dump(); assert(0 && "Unknown leaf type!"); @@ -2530,7 +2533,7 @@ private: /// EmitCodeForPattern - Given a pattern to match, emit code to the specified /// stream to match the pattern, and generate the code for the match if it /// succeeds. Returns true if the pattern is not guaranteed to match. -void DAGISelEmitter::EmitCodeForPattern(PatternToMatch &Pattern, +void DAGISelEmitter::GenerateCodeForPattern(PatternToMatch &Pattern, std::vector > &GeneratedCode) { PatternCodeEmitter Emitter(*this, Pattern.getPredicates(), Pattern.getSrcPattern(), Pattern.getDstPattern(), @@ -2581,6 +2584,95 @@ void DAGISelEmitter::EmitCodeForPattern(PatternToMatch &Pattern, delete Pat; } +/// EmitPatterns - Emit code for at least one pattern, but try to group common +/// code together between the patterns. +void DAGISelEmitter::EmitPatterns(std::vector > > > + &Patterns, unsigned Indent, + std::ostream &OS) { + typedef std::pair CodeLine; + typedef std::vector CodeList; + typedef std::vector > PatternList; + + if (Patterns.empty()) return; + + // Figure out how many patterns share the next code line: + const CodeLine &FirstCodeLine = Patterns.back().second.back(); + unsigned LastMatch = Patterns.size()-1; + while (LastMatch != 0 && Patterns[LastMatch-1].second.back() == FirstCodeLine) + --LastMatch; + + // If not all patterns share this line, split the list into two pieces. The + // first chunk will use this line, the second chunk won't. + if (LastMatch != 0) { + PatternList Shared(Patterns.begin()+LastMatch, Patterns.end()); + PatternList Other(Patterns.begin(), Patterns.begin()+LastMatch); + + // FIXME: Emit braces? + if (Shared.size() == 1) { + PatternToMatch &Pattern = *Shared.back().first; + OS << "\n" << std::string(Indent, ' ') << "// Pattern: "; + Pattern.getSrcPattern()->print(OS); + OS << "\n" << std::string(Indent, ' ') << "// Emits: "; + Pattern.getDstPattern()->print(OS); + OS << "\n"; + OS << std::string(Indent, ' ') << "// Pattern complexity = " + << getPatternSize(Pattern.getSrcPattern(), *this) << " cost = " + << getResultPatternCost(Pattern.getDstPattern()) << "\n"; + } + if (!FirstCodeLine.first) { + OS << std::string(Indent, ' ') << "{\n"; + Indent += 2; + } + EmitPatterns(Shared, Indent, OS); + if (!FirstCodeLine.first) { + Indent -= 2; + OS << std::string(Indent, ' ') << "}\n"; + } + + if (Other.size() == 1) { + PatternToMatch &Pattern = *Other.back().first; + OS << "\n" << std::string(Indent, ' ') << "// Pattern: "; + Pattern.getSrcPattern()->print(OS); + OS << "\n" << std::string(Indent, ' ') << "// Emits: "; + Pattern.getDstPattern()->print(OS); + OS << "\n"; + OS << std::string(Indent, ' ') << "// Pattern complexity = " + << getPatternSize(Pattern.getSrcPattern(), *this) << " cost = " + << getResultPatternCost(Pattern.getDstPattern()) << "\n"; + } + EmitPatterns(Other, Indent, OS); + return; + } + + bool isPredicate = FirstCodeLine.first; + + // Otherwise, every pattern in the list has this line. Emit it. + if (!isPredicate) { + // Normal code. + OS << std::string(Indent, ' ') << FirstCodeLine.second << "\n"; + } else { + OS << std::string(Indent, ' ') + << "if (" << FirstCodeLine.second << ") {\n"; + Indent += 2; + } + + // Remove this code from all of the patterns that share it. + for (unsigned i = 0, e = Patterns.size(); i != e; ++i) { + Patterns[i].second.pop_back(); + if (Patterns[i].second.empty()) { + Patterns.erase(Patterns.begin()+i); + --i; --e; + } + } + + EmitPatterns(Patterns, Indent, OS); + + if (isPredicate) + OS << std::string(Indent-2, ' ') << "}\n"; +} + + namespace { /// CompareByRecordName - An ordering predicate that implements less-than by @@ -2652,7 +2744,7 @@ void DAGISelEmitter::EmitInstructionSelector(std::ostream &OS) { std::vector > CodeForPatterns; for (unsigned i = 0, e = Patterns.size(); i != e; ++i) { CodeList GeneratedCode; - EmitCodeForPattern(*Patterns[i], GeneratedCode); + GenerateCodeForPattern(*Patterns[i], GeneratedCode); CodeForPatterns.push_back(std::make_pair(Patterns[i], GeneratedCode)); } @@ -2679,39 +2771,21 @@ void DAGISelEmitter::EmitInstructionSelector(std::ostream &OS) { exit(1); } } - + + // Loop through and reverse all of the CodeList vectors, as we will be + // accessing them from their logical front, but accessing the end of a + // vector is more efficient. for (unsigned i = 0, e = CodeForPatterns.size(); i != e; ++i) { CodeList &GeneratedCode = CodeForPatterns[i].second; - PatternToMatch &Pattern = *CodeForPatterns[i].first; - OS << " { // Pattern: "; - Pattern.getSrcPattern()->print(OS); - OS << "\n // Emits: "; - Pattern.getDstPattern()->print(OS); - OS << "\n"; - OS << " // Pattern complexity = " - << getPatternSize(Pattern.getSrcPattern(), *this) << " cost = " - << getResultPatternCost(Pattern.getDstPattern()) << "\n"; - - // Actually output the generated code now. - mightNotMatch = false; - unsigned Indent = 4; - for (unsigned j = 0, e = GeneratedCode.size(); j != e; ++j) { - if (!GeneratedCode[j].first) { - // Normal code. - OS << std::string(Indent, ' ') << GeneratedCode[j].second << "\n"; - } else { - mightNotMatch = true; - OS << std::string(Indent, ' ') - << "if (" << GeneratedCode[j].second << ") {\n"; - Indent += 2; - } - } - for (; Indent != 4; Indent -= 2) - OS << std::string(Indent-2, ' ') << "}\n"; - - OS << " }\n"; + std::reverse(GeneratedCode.begin(), GeneratedCode.end()); } + // Next, reverse the list of patterns itself for the same reason. + std::reverse(CodeForPatterns.begin(), CodeForPatterns.end()); + + // Emit all of the patterns now, grouped together to share code. + EmitPatterns(CodeForPatterns, 2, OS); + // If the last pattern has predicates (which could fail) emit code to catch // the case where nothing handles a pattern. if (mightNotMatch) diff --git a/utils/TableGen/DAGISelEmitter.h b/utils/TableGen/DAGISelEmitter.h index 3d45f2156a3..04a87b7ba4d 100644 --- a/utils/TableGen/DAGISelEmitter.h +++ b/utils/TableGen/DAGISelEmitter.h @@ -470,8 +470,11 @@ private: std::map &InstResults, std::vector &InstImpInputs, std::vector &InstImpResults); - void EmitCodeForPattern(PatternToMatch &Pattern, + void GenerateCodeForPattern(PatternToMatch &Pattern, std::vector > &GeneratedCode); + void EmitPatterns(std::vector > > > &Patterns, + unsigned Indent, std::ostream &OS); void EmitInstructionSelector(std::ostream &OS); };