mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2025-01-12 17:32:19 +00:00
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
This commit is contained in:
parent
91c6a822ba
commit
19b5a7590b
@ -221,6 +221,8 @@ GetVBR(unsigned Val, const unsigned char *MatcherTable, unsigned &Idx) {
|
|||||||
enum BuiltinOpcodes {
|
enum BuiltinOpcodes {
|
||||||
OPC_Push, OPC_Push2,
|
OPC_Push, OPC_Push2,
|
||||||
OPC_RecordNode,
|
OPC_RecordNode,
|
||||||
|
OPC_RecordChild0, OPC_RecordChild1, OPC_RecordChild2, OPC_RecordChild3,
|
||||||
|
OPC_RecordChild4, OPC_RecordChild5, OPC_RecordChild6, OPC_RecordChild7,
|
||||||
OPC_RecordMemRef,
|
OPC_RecordMemRef,
|
||||||
OPC_CaptureFlagInput,
|
OPC_CaptureFlagInput,
|
||||||
OPC_MoveChild,
|
OPC_MoveChild,
|
||||||
@ -365,7 +367,8 @@ SDNode *SelectCodeCommon(SDNode *NodeToMatch, const unsigned char *MatcherTable,
|
|||||||
unsigned MatcherIndex = 0;
|
unsigned MatcherIndex = 0;
|
||||||
while (1) {
|
while (1) {
|
||||||
assert(MatcherIndex < TableSize && "Invalid index");
|
assert(MatcherIndex < TableSize && "Invalid index");
|
||||||
switch ((BuiltinOpcodes)MatcherTable[MatcherIndex++]) {
|
BuiltinOpcodes Opcode = (BuiltinOpcodes)MatcherTable[MatcherIndex++];
|
||||||
|
switch (Opcode) {
|
||||||
case OPC_Push: {
|
case OPC_Push: {
|
||||||
unsigned NumToSkip = MatcherTable[MatcherIndex++];
|
unsigned NumToSkip = MatcherTable[MatcherIndex++];
|
||||||
MatchScope NewEntry;
|
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.
|
// Remember this node, it may end up being an operand in the pattern.
|
||||||
RecordedNodes.push_back(N);
|
RecordedNodes.push_back(N);
|
||||||
continue;
|
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:
|
case OPC_RecordMemRef:
|
||||||
MatchedMemRefs.push_back(cast<MemSDNode>(N)->getMemOperand());
|
MatchedMemRefs.push_back(cast<MemSDNode>(N)->getMemOperand());
|
||||||
continue;
|
continue;
|
||||||
@ -410,10 +425,10 @@ SDNode *SelectCodeCommon(SDNode *NodeToMatch, const unsigned char *MatcherTable,
|
|||||||
continue;
|
continue;
|
||||||
|
|
||||||
case OPC_MoveChild: {
|
case OPC_MoveChild: {
|
||||||
unsigned Child = MatcherTable[MatcherIndex++];
|
unsigned ChildNo = MatcherTable[MatcherIndex++];
|
||||||
if (Child >= N.getNumOperands())
|
if (ChildNo >= N.getNumOperands())
|
||||||
break; // Match fails if out of range child #.
|
break; // Match fails if out of range child #.
|
||||||
N = N.getOperand(Child);
|
N = N.getOperand(ChildNo);
|
||||||
NodeStack.push_back(N);
|
NodeStack.push_back(N);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
@ -1983,7 +1983,7 @@ void DAGISelEmitter::run(raw_ostream &OS) {
|
|||||||
Matcher = new PushMatcherNode(N, Matcher);
|
Matcher = new PushMatcherNode(N, Matcher);
|
||||||
}
|
}
|
||||||
|
|
||||||
OptimizeMatcher(Matcher);
|
Matcher = OptimizeMatcher(Matcher);
|
||||||
//Matcher->dump();
|
//Matcher->dump();
|
||||||
EmitMatcherTable(Matcher, OS);
|
EmitMatcherTable(Matcher, OS);
|
||||||
delete Matcher;
|
delete Matcher;
|
||||||
|
@ -35,6 +35,11 @@ void RecordMatcherNode::print(raw_ostream &OS, unsigned indent) const {
|
|||||||
printNext(OS, indent);
|
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 {
|
void RecordMemRefMatcherNode::print(raw_ostream &OS, unsigned indent) const {
|
||||||
OS.indent(indent) << "RecordMemRef\n";
|
OS.indent(indent) << "RecordMemRef\n";
|
||||||
printNext(OS, indent);
|
printNext(OS, indent);
|
||||||
|
@ -26,7 +26,7 @@ namespace llvm {
|
|||||||
|
|
||||||
MatcherNode *ConvertPatternToMatcher(const PatternToMatch &Pattern,
|
MatcherNode *ConvertPatternToMatcher(const PatternToMatch &Pattern,
|
||||||
const CodeGenDAGPatterns &CGP);
|
const CodeGenDAGPatterns &CGP);
|
||||||
void OptimizeMatcher(const MatcherNode *Matcher);
|
MatcherNode *OptimizeMatcher(MatcherNode *Matcher);
|
||||||
void EmitMatcherTable(const MatcherNode *Matcher, raw_ostream &OS);
|
void EmitMatcherTable(const MatcherNode *Matcher, raw_ostream &OS);
|
||||||
|
|
||||||
|
|
||||||
@ -41,6 +41,7 @@ public:
|
|||||||
// Matcher state manipulation.
|
// Matcher state manipulation.
|
||||||
Push, // Push a checking scope.
|
Push, // Push a checking scope.
|
||||||
RecordNode, // Record the current node.
|
RecordNode, // Record the current node.
|
||||||
|
RecordChild, // Record a child of the current node.
|
||||||
RecordMemRef, // Record the memref in the current node.
|
RecordMemRef, // Record the memref in the current node.
|
||||||
CaptureFlagInput, // If the current node has an input flag, save it.
|
CaptureFlagInput, // If the current node has an input flag, save it.
|
||||||
MoveChild, // Move current node to specified child.
|
MoveChild, // Move current node to specified child.
|
||||||
@ -86,6 +87,9 @@ public:
|
|||||||
MatcherNode *getNext() { return Next.get(); }
|
MatcherNode *getNext() { return Next.get(); }
|
||||||
const MatcherNode *getNext() const { return Next.get(); }
|
const MatcherNode *getNext() const { return Next.get(); }
|
||||||
void setNext(MatcherNode *C) { Next.reset(C); }
|
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; }
|
static inline bool classof(const MatcherNode *) { return true; }
|
||||||
|
|
||||||
@ -109,6 +113,7 @@ public:
|
|||||||
MatcherNode *getFailure() { return Failure.get(); }
|
MatcherNode *getFailure() { return Failure.get(); }
|
||||||
const MatcherNode *getFailure() const { return Failure.get(); }
|
const MatcherNode *getFailure() const { return Failure.get(); }
|
||||||
void setFailure(MatcherNode *N) { Failure.reset(N); }
|
void setFailure(MatcherNode *N) { Failure.reset(N); }
|
||||||
|
OwningPtr<MatcherNode> &getFailurePtr() { return Failure; }
|
||||||
|
|
||||||
static inline bool classof(const MatcherNode *N) {
|
static inline bool classof(const MatcherNode *N) {
|
||||||
return N->getKind() == Push;
|
return N->getKind() == Push;
|
||||||
@ -135,6 +140,29 @@ public:
|
|||||||
virtual void print(raw_ostream &OS, unsigned indent = 0) const;
|
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.
|
/// RecordMemRefMatcherNode - Save the current node's memref.
|
||||||
class RecordMemRefMatcherNode : public MatcherNode {
|
class RecordMemRefMatcherNode : public MatcherNode {
|
||||||
public:
|
public:
|
||||||
|
@ -160,6 +160,13 @@ EmitMatcher(const MatcherNode *N, unsigned Indent, formatted_raw_ostream &OS) {
|
|||||||
<< cast<RecordMatcherNode>(N)->getWhatFor() << '\n';
|
<< cast<RecordMatcherNode>(N)->getWhatFor() << '\n';
|
||||||
return 1;
|
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:
|
case MatcherNode::RecordMemRef:
|
||||||
OS << "OPC_RecordMemRef,\n";
|
OS << "OPC_RecordMemRef,\n";
|
||||||
return 1;
|
return 1;
|
||||||
|
@ -14,6 +14,35 @@
|
|||||||
#include "DAGISelMatcher.h"
|
#include "DAGISelMatcher.h"
|
||||||
using namespace llvm;
|
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();
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user