summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChris Lattner <sabre@nondot.org>2010-02-24 07:31:45 +0000
committerChris Lattner <sabre@nondot.org>2010-02-24 07:31:45 +0000
commit19b5a7590b784f19875b9880ea8838c393431656 (patch)
treea72bfb5c816b6e8751d7e9b76b904b1ff53f4871
parent91c6a822baaba3cb2def94224115e57b84805347 (diff)
downloadllvm-19b5a7590b784f19875b9880ea8838c393431656.tar.gz
llvm-19b5a7590b784f19875b9880ea8838c393431656.tar.bz2
llvm-19b5a7590b784f19875b9880ea8838c393431656.tar.xz
implement a simple proof-of-concept optimization for
the new isel: fold movechild+record+moveparent into a single recordchild N node. This shrinks the X86 table from 125443 to 117502 bytes. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@97031 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r--include/llvm/CodeGen/DAGISelHeader.h23
-rw-r--r--utils/TableGen/DAGISelEmitter.cpp2
-rw-r--r--utils/TableGen/DAGISelMatcher.cpp5
-rw-r--r--utils/TableGen/DAGISelMatcher.h30
-rw-r--r--utils/TableGen/DAGISelMatcherEmitter.cpp7
-rw-r--r--utils/TableGen/DAGISelMatcherOpt.cpp33
6 files changed, 92 insertions, 8 deletions
diff --git a/include/llvm/CodeGen/DAGISelHeader.h b/include/llvm/CodeGen/DAGISelHeader.h
index 7a6c1962f7..88c1a66d4f 100644
--- a/include/llvm/CodeGen/DAGISelHeader.h
+++ b/include/llvm/CodeGen/DAGISelHeader.h
@@ -221,6 +221,8 @@ GetVBR(unsigned Val, const unsigned char *MatcherTable, unsigned &Idx) {
enum BuiltinOpcodes {
OPC_Push, OPC_Push2,
OPC_RecordNode,
+ OPC_RecordChild0, OPC_RecordChild1, OPC_RecordChild2, OPC_RecordChild3,
+ OPC_RecordChild4, OPC_RecordChild5, OPC_RecordChild6, OPC_RecordChild7,
OPC_RecordMemRef,
OPC_CaptureFlagInput,
OPC_MoveChild,
@@ -365,7 +367,8 @@ SDNode *SelectCodeCommon(SDNode *NodeToMatch, const unsigned char *MatcherTable,
unsigned MatcherIndex = 0;
while (1) {
assert(MatcherIndex < TableSize && "Invalid index");
- switch ((BuiltinOpcodes)MatcherTable[MatcherIndex++]) {
+ BuiltinOpcodes Opcode = (BuiltinOpcodes)MatcherTable[MatcherIndex++];
+ switch (Opcode) {
case OPC_Push: {
unsigned NumToSkip = MatcherTable[MatcherIndex++];
MatchScope NewEntry;
@@ -398,6 +401,18 @@ SDNode *SelectCodeCommon(SDNode *NodeToMatch, const unsigned char *MatcherTable,
// Remember this node, it may end up being an operand in the pattern.
RecordedNodes.push_back(N);
continue;
+
+ case OPC_RecordChild0: case OPC_RecordChild1:
+ case OPC_RecordChild2: case OPC_RecordChild3:
+ case OPC_RecordChild4: case OPC_RecordChild5:
+ case OPC_RecordChild6: case OPC_RecordChild7: {
+ unsigned ChildNo = Opcode-OPC_RecordChild0;
+ if (ChildNo >= N.getNumOperands())
+ break; // Match fails if out of range child #.
+
+ RecordedNodes.push_back(N->getOperand(ChildNo));
+ continue;
+ }
case OPC_RecordMemRef:
MatchedMemRefs.push_back(cast<MemSDNode>(N)->getMemOperand());
continue;
@@ -410,10 +425,10 @@ SDNode *SelectCodeCommon(SDNode *NodeToMatch, const unsigned char *MatcherTable,
continue;
case OPC_MoveChild: {
- unsigned Child = MatcherTable[MatcherIndex++];
- if (Child >= N.getNumOperands())
+ unsigned ChildNo = MatcherTable[MatcherIndex++];
+ if (ChildNo >= N.getNumOperands())
break; // Match fails if out of range child #.
- N = N.getOperand(Child);
+ N = N.getOperand(ChildNo);
NodeStack.push_back(N);
continue;
}
diff --git a/utils/TableGen/DAGISelEmitter.cpp b/utils/TableGen/DAGISelEmitter.cpp
index 2d2ab3e707..7a01caab85 100644
--- a/utils/TableGen/DAGISelEmitter.cpp
+++ b/utils/TableGen/DAGISelEmitter.cpp
@@ -1983,7 +1983,7 @@ void DAGISelEmitter::run(raw_ostream &OS) {
Matcher = new PushMatcherNode(N, Matcher);
}
- OptimizeMatcher(Matcher);
+ Matcher = OptimizeMatcher(Matcher);
//Matcher->dump();
EmitMatcherTable(Matcher, OS);
delete Matcher;
diff --git a/utils/TableGen/DAGISelMatcher.cpp b/utils/TableGen/DAGISelMatcher.cpp
index 6fb417cf96..9bb8fd5150 100644
--- a/utils/TableGen/DAGISelMatcher.cpp
+++ b/utils/TableGen/DAGISelMatcher.cpp
@@ -35,6 +35,11 @@ void RecordMatcherNode::print(raw_ostream &OS, unsigned indent) const {
printNext(OS, indent);
}
+void RecordChildMatcherNode::print(raw_ostream &OS, unsigned indent) const {
+ OS.indent(indent) << "RecordChild: " << ChildNo << '\n';
+ printNext(OS, indent);
+}
+
void RecordMemRefMatcherNode::print(raw_ostream &OS, unsigned indent) const {
OS.indent(indent) << "RecordMemRef\n";
printNext(OS, indent);
diff --git a/utils/TableGen/DAGISelMatcher.h b/utils/TableGen/DAGISelMatcher.h
index 4dcbc8f55f..ab84168bd8 100644
--- a/utils/TableGen/DAGISelMatcher.h
+++ b/utils/TableGen/DAGISelMatcher.h
@@ -26,7 +26,7 @@ namespace llvm {
MatcherNode *ConvertPatternToMatcher(const PatternToMatch &Pattern,
const CodeGenDAGPatterns &CGP);
-void OptimizeMatcher(const MatcherNode *Matcher);
+MatcherNode *OptimizeMatcher(MatcherNode *Matcher);
void EmitMatcherTable(const MatcherNode *Matcher, raw_ostream &OS);
@@ -41,6 +41,7 @@ public:
// Matcher state manipulation.
Push, // Push a checking scope.
RecordNode, // Record the current node.
+ RecordChild, // Record a child of the current node.
RecordMemRef, // Record the memref in the current node.
CaptureFlagInput, // If the current node has an input flag, save it.
MoveChild, // Move current node to specified child.
@@ -86,6 +87,9 @@ public:
MatcherNode *getNext() { return Next.get(); }
const MatcherNode *getNext() const { return Next.get(); }
void setNext(MatcherNode *C) { Next.reset(C); }
+ MatcherNode *takeNext() { return Next.take(); }
+
+ OwningPtr<MatcherNode> &getNextPtr() { return Next; }
static inline bool classof(const MatcherNode *) { return true; }
@@ -109,6 +113,7 @@ public:
MatcherNode *getFailure() { return Failure.get(); }
const MatcherNode *getFailure() const { return Failure.get(); }
void setFailure(MatcherNode *N) { Failure.reset(N); }
+ OwningPtr<MatcherNode> &getFailurePtr() { return Failure; }
static inline bool classof(const MatcherNode *N) {
return N->getKind() == Push;
@@ -135,6 +140,29 @@ public:
virtual void print(raw_ostream &OS, unsigned indent = 0) const;
};
+/// RecordChildMatcherNode - Save a numbered child of the current node, or fail
+/// the match if it doesn't exist. This is logically equivalent to:
+/// MoveChild N + RecordNode + MoveParent.
+class RecordChildMatcherNode : public MatcherNode {
+ unsigned ChildNo;
+
+ /// WhatFor - This is a string indicating why we're recording this. This
+ /// should only be used for comment generation not anything semantic.
+ std::string WhatFor;
+public:
+ RecordChildMatcherNode(unsigned childno, const std::string &whatfor)
+ : MatcherNode(RecordChild), ChildNo(childno), WhatFor(whatfor) {}
+
+ unsigned getChildNo() const { return ChildNo; }
+ const std::string &getWhatFor() const { return WhatFor; }
+
+ static inline bool classof(const MatcherNode *N) {
+ return N->getKind() == RecordChild;
+ }
+
+ virtual void print(raw_ostream &OS, unsigned indent = 0) const;
+};
+
/// RecordMemRefMatcherNode - Save the current node's memref.
class RecordMemRefMatcherNode : public MatcherNode {
public:
diff --git a/utils/TableGen/DAGISelMatcherEmitter.cpp b/utils/TableGen/DAGISelMatcherEmitter.cpp
index ecc75c8c4c..e78be79119 100644
--- a/utils/TableGen/DAGISelMatcherEmitter.cpp
+++ b/utils/TableGen/DAGISelMatcherEmitter.cpp
@@ -159,6 +159,13 @@ EmitMatcher(const MatcherNode *N, unsigned Indent, formatted_raw_ostream &OS) {
OS.PadToColumn(CommentIndent) << "// "
<< cast<RecordMatcherNode>(N)->getWhatFor() << '\n';
return 1;
+
+ case MatcherNode::RecordChild:
+ OS << "OPC_RecordChild" << cast<RecordChildMatcherNode>(N)->getChildNo()
+ << ',';
+ OS.PadToColumn(CommentIndent) << "// "
+ << cast<RecordChildMatcherNode>(N)->getWhatFor() << '\n';
+ return 1;
case MatcherNode::RecordMemRef:
OS << "OPC_RecordMemRef,\n";
diff --git a/utils/TableGen/DAGISelMatcherOpt.cpp b/utils/TableGen/DAGISelMatcherOpt.cpp
index 7859f36eef..d3658202a6 100644
--- a/utils/TableGen/DAGISelMatcherOpt.cpp
+++ b/utils/TableGen/DAGISelMatcherOpt.cpp
@@ -14,6 +14,35 @@
#include "DAGISelMatcher.h"
using namespace llvm;
-void llvm::OptimizeMatcher(const MatcherNode *Matcher) {
- // Nothing yet.
+
+static void FormRecordChildNodes(OwningPtr<MatcherNode> &Matcher) {
+ // If we reached the end of the chain, we're done.
+ MatcherNode *N = Matcher.get();
+ if (N == 0) return;
+
+ // If we have a push node, walk down both edges.
+ if (PushMatcherNode *Push = dyn_cast<PushMatcherNode>(N))
+ FormRecordChildNodes(Push->getFailurePtr());
+
+ // If we found a movechild node, check to see if our pattern matches.
+ if (MoveChildMatcherNode *MC = dyn_cast<MoveChildMatcherNode>(N)) {
+ if (RecordMatcherNode *RM = dyn_cast<RecordMatcherNode>(MC->getNext()))
+ if (MoveParentMatcherNode *MP =
+ dyn_cast<MoveParentMatcherNode>(RM->getNext())) {
+ MatcherNode *New
+ = new RecordChildMatcherNode(MC->getChildNo(), RM->getWhatFor());
+ New->setNext(MP->takeNext());
+ Matcher.reset(New);
+ return FormRecordChildNodes(Matcher);
+ }
+ }
+
+ FormRecordChildNodes(N->getNextPtr());
+}
+
+
+MatcherNode *llvm::OptimizeMatcher(MatcherNode *Matcher) {
+ OwningPtr<MatcherNode> MatcherPtr(Matcher);
+ FormRecordChildNodes(MatcherPtr);
+ return MatcherPtr.take();
}