summaryrefslogtreecommitdiff
path: root/utils/TableGen
diff options
context:
space:
mode:
authorChris Lattner <sabre@nondot.org>2010-02-28 20:49:53 +0000
committerChris Lattner <sabre@nondot.org>2010-02-28 20:49:53 +0000
commitc78f2a39945339752a163949a2d7c27f28635d99 (patch)
tree52a5514af685d5c021e7859f031602936acf290f /utils/TableGen
parentb65c5f2ec347db8342cb7e42d072b0088b74fa73 (diff)
downloadllvm-c78f2a39945339752a163949a2d7c27f28635d99.tar.gz
llvm-c78f2a39945339752a163949a2d7c27f28635d99.tar.bz2
llvm-c78f2a39945339752a163949a2d7c27f28635d99.tar.xz
enhance the new isel to use SelectNodeTo for most patterns,
even some the old isel didn't. There are several parts of this that make me feel dirty, but it's no worse than the old isel. I'll clean up the parts I can do without ripping out the old one next. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@97415 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'utils/TableGen')
-rw-r--r--utils/TableGen/DAGISelEmitter.cpp2
-rw-r--r--utils/TableGen/DAGISelMatcher.cpp8
-rw-r--r--utils/TableGen/DAGISelMatcher.h19
-rw-r--r--utils/TableGen/DAGISelMatcherEmitter.cpp17
-rw-r--r--utils/TableGen/DAGISelMatcherGen.cpp9
-rw-r--r--utils/TableGen/DAGISelMatcherOpt.cpp73
6 files changed, 100 insertions, 28 deletions
diff --git a/utils/TableGen/DAGISelEmitter.cpp b/utils/TableGen/DAGISelEmitter.cpp
index 5e2b07d0d4..2ea8bf0336 100644
--- a/utils/TableGen/DAGISelEmitter.cpp
+++ b/utils/TableGen/DAGISelEmitter.cpp
@@ -1966,7 +1966,7 @@ void DAGISelEmitter::run(raw_ostream &OS) {
Matcher *TheMatcher = new ScopeMatcher(&PatternMatchers[0],
PatternMatchers.size());
- TheMatcher = OptimizeMatcher(TheMatcher);
+ TheMatcher = OptimizeMatcher(TheMatcher, CGP);
//Matcher->dump();
EmitMatcherTable(TheMatcher, OS);
delete TheMatcher;
diff --git a/utils/TableGen/DAGISelMatcher.cpp b/utils/TableGen/DAGISelMatcher.cpp
index d939edb563..085682fd1b 100644
--- a/utils/TableGen/DAGISelMatcher.cpp
+++ b/utils/TableGen/DAGISelMatcher.cpp
@@ -39,8 +39,12 @@ ScopeMatcher::~ScopeMatcher() {
void ScopeMatcher::printImpl(raw_ostream &OS, unsigned indent) const {
OS.indent(indent) << "Scope\n";
- for (unsigned i = 0, e = getNumChildren(); i != e; ++i)
- getChild(i)->print(OS, indent+2);
+ for (unsigned i = 0, e = getNumChildren(); i != e; ++i) {
+ if (getChild(i) == 0)
+ OS.indent(indent+1) << "NULL POINTER\n";
+ else
+ getChild(i)->print(OS, indent+2);
+ }
}
void RecordMatcher::printImpl(raw_ostream &OS, unsigned indent) const {
diff --git a/utils/TableGen/DAGISelMatcher.h b/utils/TableGen/DAGISelMatcher.h
index b91b591cee..0d674c574e 100644
--- a/utils/TableGen/DAGISelMatcher.h
+++ b/utils/TableGen/DAGISelMatcher.h
@@ -27,7 +27,7 @@ namespace llvm {
Matcher *ConvertPatternToMatcher(const PatternToMatch &Pattern,
const CodeGenDAGPatterns &CGP);
-Matcher *OptimizeMatcher(Matcher *Matcher);
+Matcher *OptimizeMatcher(Matcher *Matcher, const CodeGenDAGPatterns &CGP);
void EmitMatcherTable(const Matcher *Matcher, raw_ostream &OS);
@@ -900,12 +900,25 @@ public:
assert(i < VTs.size());
return VTs[i];
}
+
+ /// getNumNonChainFlagVTs - Return the number of normal results that this node
+ /// will have, ignoring flag and chain results.
+ unsigned getNumNonChainFlagVTs() const {
+ for (unsigned i = 0, e = getNumVTs(); i != e; ++i)
+ if (VTs[i] == MVT::Flag || VTs[i] == MVT::Other)
+ return i;
+ return getNumVTs();
+ }
unsigned getNumOperands() const { return Operands.size(); }
unsigned getOperand(unsigned i) const {
assert(i < Operands.size());
return Operands[i];
- }
+ }
+
+ const SmallVectorImpl<MVT::SimpleValueType> &getVTList() const { return VTs; }
+ const SmallVectorImpl<unsigned> &getOperandList() const { return Operands; }
+
bool hasChain() const { return HasChain; }
bool hasFlag() const { return HasFlag; }
@@ -999,7 +1012,7 @@ class CompleteMatchMatcher : public Matcher {
const PatternToMatch &Pattern;
public:
CompleteMatchMatcher(const unsigned *results, unsigned numresults,
- const PatternToMatch &pattern)
+ const PatternToMatch &pattern)
: Matcher(CompleteMatch), Results(results, results+numresults),
Pattern(pattern) {}
diff --git a/utils/TableGen/DAGISelMatcherEmitter.cpp b/utils/TableGen/DAGISelMatcherEmitter.cpp
index 942a61225e..aec1e18aa7 100644
--- a/utils/TableGen/DAGISelMatcherEmitter.cpp
+++ b/utils/TableGen/DAGISelMatcherEmitter.cpp
@@ -416,18 +416,23 @@ EmitMatcher(const Matcher *N, unsigned Indent, unsigned CurrentIdx,
// Print the result #'s for EmitNode.
if (const EmitNodeMatcher *E = dyn_cast<EmitNodeMatcher>(EN)) {
- if (EN->getVT(0) != MVT::Flag && EN->getVT(0) != MVT::Other) {
+ if (unsigned NumResults = EN->getNumNonChainFlagVTs()) {
OS.PadToColumn(CommentIndent) << "// Results = ";
unsigned First = E->getFirstResultSlot();
- for (unsigned i = 0, e = EN->getNumVTs(); i != e; ++i) {
- if (EN->getVT(0) == MVT::Flag || EN->getVT(0) == MVT::Other)
- break;
+ for (unsigned i = 0; i != NumResults; ++i)
OS << "#" << First+i << " ";
- }
}
}
-
OS << '\n';
+
+ if (const SelectNodeToMatcher *SNT = dyn_cast<SelectNodeToMatcher>(N)) {
+ OS.PadToColumn(Indent*2) << "// Src: "
+ << *SNT->getPattern().getSrcPattern() << '\n';
+ OS.PadToColumn(Indent*2) << "// Dst: "
+ << *SNT->getPattern().getDstPattern() << '\n';
+
+ }
+
return 6+EN->getNumVTs()+NumOperandBytes;
}
case Matcher::MarkFlagResults: {
diff --git a/utils/TableGen/DAGISelMatcherGen.cpp b/utils/TableGen/DAGISelMatcherGen.cpp
index 18735de0e2..c558eba9fd 100644
--- a/utils/TableGen/DAGISelMatcherGen.cpp
+++ b/utils/TableGen/DAGISelMatcherGen.cpp
@@ -741,10 +741,6 @@ EmitResultInstructionAsOperand(const TreePatternNode *N,
bool NodeHasMemRefs =
isRoot && Pattern.getSrcPattern()->TreeHasProperty(SDNPMemOperand, CGP);
- // FIXME: Eventually add a SelectNodeTo form. It works if the new node has a
- // superset of the results of the old node, in the same places. E.g. turning
- // (add (load)) -> add32rm is ok because result #0 is the result and result #1
- // is new.
AddMatcher(new EmitNodeMatcher(II.Namespace+"::"+II.TheDef->getName(),
ResultVTs.data(), ResultVTs.size(),
InstOps.data(), InstOps.size(),
@@ -757,9 +753,6 @@ EmitResultInstructionAsOperand(const TreePatternNode *N,
if (ResultVTs[i] == MVT::Other || ResultVTs[i] == MVT::Flag) break;
OutputOps.push_back(NextRecordedOperandNo++);
}
-
- // FIXME2: Kill off all the SelectionDAG::SelectNodeTo and getMachineNode
- // variants. Call MorphNodeTo instead of SelectNodeTo.
}
void MatcherGen::
@@ -851,7 +844,7 @@ void MatcherGen::EmitResultCode() {
Matcher *llvm::ConvertPatternToMatcher(const PatternToMatch &Pattern,
- const CodeGenDAGPatterns &CGP) {
+ const CodeGenDAGPatterns &CGP) {
MatcherGen Gen(Pattern, CGP);
// Generate the code for the matcher.
diff --git a/utils/TableGen/DAGISelMatcherOpt.cpp b/utils/TableGen/DAGISelMatcherOpt.cpp
index 12c4c1b079..2ea178f11b 100644
--- a/utils/TableGen/DAGISelMatcherOpt.cpp
+++ b/utils/TableGen/DAGISelMatcherOpt.cpp
@@ -13,6 +13,7 @@
#define DEBUG_TYPE "isel-opt"
#include "DAGISelMatcher.h"
+#include "CodeGenDAGPatterns.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/raw_ostream.h"
@@ -21,7 +22,8 @@ using namespace llvm;
/// ContractNodes - Turn multiple matcher node patterns like 'MoveChild+Record'
/// into single compound nodes like RecordChild.
-static void ContractNodes(OwningPtr<Matcher> &MatcherPtr) {
+static void ContractNodes(OwningPtr<Matcher> &MatcherPtr,
+ const CodeGenDAGPatterns &CGP) {
// If we reached the end of the chain, we're done.
Matcher *N = MatcherPtr.get();
if (N == 0) return;
@@ -30,7 +32,7 @@ static void ContractNodes(OwningPtr<Matcher> &MatcherPtr) {
if (ScopeMatcher *Scope = dyn_cast<ScopeMatcher>(N)) {
for (unsigned i = 0, e = Scope->getNumChildren(); i != e; ++i) {
OwningPtr<Matcher> Child(Scope->takeChild(i));
- ContractNodes(Child);
+ ContractNodes(Child, CGP);
Scope->resetChild(i, Child.take());
}
return;
@@ -52,7 +54,7 @@ static void ContractNodes(OwningPtr<Matcher> &MatcherPtr) {
MatcherPtr.reset(New);
// Remove the old one.
MC->setNext(MC->getNext()->takeNext());
- return ContractNodes(MatcherPtr);
+ return ContractNodes(MatcherPtr, CGP);
}
}
@@ -61,17 +63,69 @@ static void ContractNodes(OwningPtr<Matcher> &MatcherPtr) {
if (MoveParentMatcher *MP =
dyn_cast<MoveParentMatcher>(MC->getNext())) {
MatcherPtr.reset(MP->takeNext());
- return ContractNodes(MatcherPtr);
+ return ContractNodes(MatcherPtr, CGP);
}
// Turn EmitNode->CompleteMatch into SelectNodeTo if we can.
if (EmitNodeMatcher *EN = dyn_cast<EmitNodeMatcher>(N))
if (CompleteMatchMatcher *CM =
dyn_cast<CompleteMatchMatcher>(EN->getNext())) {
- (void)CM;
+ // We can only use SelectNodeTo if the result values match up.
+ unsigned RootResultFirst = EN->getFirstResultSlot();
+ bool ResultsMatch = true;
+ for (unsigned i = 0, e = CM->getNumResults(); i != e; ++i)
+ if (CM->getResult(i) != RootResultFirst+i)
+ ResultsMatch = false;
+
+ // If the selected node defines a subset of the flag/chain results, we
+ // can't use SelectNodeTo. For example, we can't use SelectNodeTo if the
+ // matched pattern has a chain but the root node doesn't.
+ const PatternToMatch &Pattern = CM->getPattern();
+
+ if (!EN->hasChain() &&
+ Pattern.getSrcPattern()->NodeHasProperty(SDNPHasChain, CGP))
+ ResultsMatch = false;
+
+ // If the matched node has a flag and the output root doesn't, we can't
+ // use SelectNodeTo.
+ //
+ // NOTE: Strictly speaking, we don't have to check for the flag here
+ // because the code in the pattern generator doesn't handle it right. We
+ // do it anyway for thoroughness.
+ if (!EN->hasFlag() &&
+ Pattern.getSrcPattern()->NodeHasProperty(SDNPOutFlag, CGP))
+ ResultsMatch = false;
+
+
+ // If the root result node defines more results than the source root node
+ // *and* has a chain or flag input, then we can't match it because it
+ // would end up replacing the extra result with the chain/flag.
+#if 0
+ if ((EN->hasFlag() || EN->hasChain()) &&
+ EN->getNumNonChainFlagVTs() > ... need to get no results reliably ...)
+ ResultMatch = false;
+#endif
+
+ if (ResultsMatch) {
+ const SmallVectorImpl<MVT::SimpleValueType> &VTs = EN->getVTList();
+ const SmallVectorImpl<unsigned> &Operands = EN->getOperandList();
+ MatcherPtr.reset(new SelectNodeToMatcher(EN->getOpcodeName(),
+ &VTs[0], VTs.size(),
+ Operands.data(), Operands.size(),
+ EN->hasChain(), EN->hasFlag(),
+ EN->hasMemRefs(),
+ EN->getNumFixedArityOperands(),
+ Pattern));
+ return;
+ }
+
+ // FIXME: Handle OPC_MarkFlagResults.
+
+ // FIXME2: Kill off all the SelectionDAG::SelectNodeTo and getMachineNode
+ // variants. Call MorphNodeTo instead of SelectNodeTo.
}
- ContractNodes(N->getNextPtr());
+ ContractNodes(N->getNextPtr(), CGP);
}
/// SinkPatternPredicates - Pattern predicates can be checked at any level of
@@ -253,6 +307,8 @@ static void FactorNodes(OwningPtr<Matcher> &MatcherPtr) {
// Reassemble a new Scope node.
assert(!NewOptionsToMatch.empty() && "where'd all our children go?");
+ if (NewOptionsToMatch.empty())
+ MatcherPtr.reset(0);
if (NewOptionsToMatch.size() == 1)
MatcherPtr.reset(NewOptionsToMatch[0]);
else {
@@ -262,9 +318,10 @@ static void FactorNodes(OwningPtr<Matcher> &MatcherPtr) {
}
}
-Matcher *llvm::OptimizeMatcher(Matcher *TheMatcher) {
+Matcher *llvm::OptimizeMatcher(Matcher *TheMatcher,
+ const CodeGenDAGPatterns &CGP) {
OwningPtr<Matcher> MatcherPtr(TheMatcher);
- ContractNodes(MatcherPtr);
+ ContractNodes(MatcherPtr, CGP);
SinkPatternPredicates(MatcherPtr);
FactorNodes(MatcherPtr);
return MatcherPtr.take();