mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2025-02-27 17:31:33 +00:00
Add full support for code generating expanders!
This includes support for referencing named arguments. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@7715 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
990db46e9a
commit
053a205d63
@ -55,8 +55,8 @@ bool TreePatternNode::updateNodeType(MVT::ValueType VT,
|
||||
///
|
||||
void TreePatternNode::InstantiateNonterminals(InstrSelectorEmitter &ISE) {
|
||||
if (!isLeaf()) {
|
||||
for (unsigned i = 0, e = Children.size(); i != e; ++i)
|
||||
Children[i]->InstantiateNonterminals(ISE);
|
||||
for (unsigned i = 0, e = getNumChildren(); i != e; ++i)
|
||||
getChild(i)->InstantiateNonterminals(ISE);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -82,9 +82,10 @@ TreePatternNode *TreePatternNode::clone() const {
|
||||
if (isLeaf()) {
|
||||
New = new TreePatternNode(Value);
|
||||
} else {
|
||||
std::vector<TreePatternNode*> CChildren(Children.size());
|
||||
for (unsigned i = 0, e = Children.size(); i != e; ++i)
|
||||
CChildren[i] = Children[i]->clone();
|
||||
std::vector<std::pair<TreePatternNode*, std::string> > CChildren;
|
||||
CChildren.reserve(Children.size());
|
||||
for (unsigned i = 0, e = getNumChildren(); i != e; ++i)
|
||||
CChildren.push_back(std::make_pair(getChild(i)->clone(),getChildName(i)));
|
||||
New = new TreePatternNode(Operator, CChildren);
|
||||
}
|
||||
New->setType(Type);
|
||||
@ -97,11 +98,10 @@ std::ostream &operator<<(std::ostream &OS, const TreePatternNode &N) {
|
||||
OS << "(" << N.getType() << ":";
|
||||
OS << N.getOperator()->getName();
|
||||
|
||||
const std::vector<TreePatternNode*> &Children = N.getChildren();
|
||||
if (!Children.empty()) {
|
||||
OS << " " << *Children[0];
|
||||
for (unsigned i = 1, e = Children.size(); i != e; ++i)
|
||||
OS << ", " << *Children[i];
|
||||
if (N.getNumChildren() != 0) {
|
||||
OS << " " << *N.getChild(0);
|
||||
for (unsigned i = 1, e = N.getNumChildren(); i != e; ++i)
|
||||
OS << ", " << *N.getChild(i);
|
||||
}
|
||||
return OS << ")";
|
||||
}
|
||||
@ -133,13 +133,15 @@ Pattern::Pattern(PatternType pty, DagInit *RawPat, Record *TheRec,
|
||||
|
||||
// Check to see if we have a top-level (set) of a register.
|
||||
if (Tree->getOperator()->getName() == "set") {
|
||||
assert(Tree->getChildren().size() == 2 && "Set with != 2 arguments?");
|
||||
assert(Tree->getNumChildren() == 2 && "Set with != 2 arguments?");
|
||||
if (!Tree->getChild(0)->isLeaf())
|
||||
error("Arg #0 of set should be a register or register class!");
|
||||
Result = Tree->getChild(0)->getValueRecord();
|
||||
Tree = Tree->getChild(1);
|
||||
}
|
||||
}
|
||||
|
||||
calculateArgs(Tree, "");
|
||||
}
|
||||
|
||||
void Pattern::error(const std::string &Msg) const {
|
||||
@ -152,6 +154,19 @@ void Pattern::error(const std::string &Msg) const {
|
||||
throw M + TheRecord->getName() + ": " + Msg;
|
||||
}
|
||||
|
||||
/// calculateArgs - Compute the list of all of the arguments to this pattern,
|
||||
/// which are the non-void leaf nodes in this pattern.
|
||||
///
|
||||
void Pattern::calculateArgs(TreePatternNode *N, const std::string &Name) {
|
||||
if (N->isLeaf() || N->getNumChildren() == 0) {
|
||||
if (N->getType() != MVT::isVoid)
|
||||
Args.push_back(std::make_pair(N, Name));
|
||||
} else {
|
||||
for (unsigned i = 0, e = N->getNumChildren(); i != e; ++i)
|
||||
calculateArgs(N->getChild(i), N->getChildName(i));
|
||||
}
|
||||
}
|
||||
|
||||
/// getIntrinsicType - Check to see if the specified record has an intrinsic
|
||||
/// type which should be applied to it. This infer the type of register
|
||||
/// references from the register file information, for example.
|
||||
@ -199,12 +214,13 @@ TreePatternNode *Pattern::ParseTreePattern(DagInit *Dag) {
|
||||
if (!ISE.getNodeTypes().count(Operator))
|
||||
error("Unrecognized node '" + Operator->getName() + "'!");
|
||||
|
||||
std::vector<TreePatternNode*> Children;
|
||||
std::vector<std::pair<TreePatternNode*, std::string> > Children;
|
||||
|
||||
for (unsigned i = 0, e = Dag->getNumArgs(); i != e; ++i) {
|
||||
Init *Arg = Dag->getArg(i);
|
||||
if (DagInit *DI = dynamic_cast<DagInit*>(Arg)) {
|
||||
Children.push_back(ParseTreePattern(DI));
|
||||
Children.push_back(std::make_pair(ParseTreePattern(DI),
|
||||
Dag->getArgName(i)));
|
||||
} else if (DefInit *DefI = dynamic_cast<DefInit*>(Arg)) {
|
||||
Record *R = DefI->getDef();
|
||||
// Direct reference to a leaf DagNode? Turn it into a DagNode if its own.
|
||||
@ -213,9 +229,10 @@ TreePatternNode *Pattern::ParseTreePattern(DagInit *Dag) {
|
||||
std::vector<std::pair<Init*, std::string> >()));
|
||||
--i; // Revisit this node...
|
||||
} else {
|
||||
Children.push_back(new TreePatternNode(DefI));
|
||||
Children.push_back(std::make_pair(new TreePatternNode(DefI),
|
||||
Dag->getArgName(i)));
|
||||
// If it's a regclass or something else known, set the type.
|
||||
Children.back()->setType(getIntrinsicType(R));
|
||||
Children.back().first->setType(getIntrinsicType(R));
|
||||
}
|
||||
} else {
|
||||
Arg->dump();
|
||||
@ -248,17 +265,16 @@ bool Pattern::InferTypes(TreePatternNode *N, bool &MadeChange) {
|
||||
|
||||
// Check to see if we can infer anything about the argument types from the
|
||||
// return types...
|
||||
const std::vector<TreePatternNode*> &Children = N->getChildren();
|
||||
if (Children.size() != NT.ArgTypes.size())
|
||||
if (N->getNumChildren() != NT.ArgTypes.size())
|
||||
error("Incorrect number of children for " + Operator->getName() + " node!");
|
||||
|
||||
for (unsigned i = 0, e = Children.size(); i != e; ++i) {
|
||||
TreePatternNode *Child = Children[i];
|
||||
for (unsigned i = 0, e = N->getNumChildren(); i != e; ++i) {
|
||||
TreePatternNode *Child = N->getChild(i);
|
||||
AnyUnset |= InferTypes(Child, MadeChange);
|
||||
|
||||
switch (NT.ArgTypes[i]) {
|
||||
case NodeType::Arg0:
|
||||
MadeChange |= Child->updateNodeType(Children[0]->getType(),
|
||||
MadeChange |= Child->updateNodeType(N->getChild(0)->getType(),
|
||||
TheRecord->getName());
|
||||
break;
|
||||
case NodeType::Val:
|
||||
@ -279,7 +295,7 @@ bool Pattern::InferTypes(TreePatternNode *N, bool &MadeChange) {
|
||||
MadeChange |= N->updateNodeType(MVT::isVoid, TheRecord->getName());
|
||||
break;
|
||||
case NodeType::Arg0:
|
||||
MadeChange |= N->updateNodeType(Children[0]->getType(),
|
||||
MadeChange |= N->updateNodeType(N->getChild(0)->getType(),
|
||||
TheRecord->getName());
|
||||
break;
|
||||
|
||||
@ -647,10 +663,9 @@ void InstrSelectorEmitter::EmitMatchCosters(std::ostream &OS,
|
||||
OS << "\n" << Indent << "// Operand matching costs...\n";
|
||||
std::set<std::string> ComputedValues; // Avoid duplicate computations...
|
||||
for (unsigned i = 0, e = Patterns.size(); i != e; ++i) {
|
||||
const std::vector<TreePatternNode*> &Children =
|
||||
Patterns[i].second->getChildren();
|
||||
for (unsigned c = 0, e = Children.size(); c != e; ++c) {
|
||||
TreePatternNode *N = Children[c];
|
||||
TreePatternNode *NParent = Patterns[i].second;
|
||||
for (unsigned c = 0, e = NParent->getNumChildren(); c != e; ++c) {
|
||||
TreePatternNode *N = NParent->getChild(c);
|
||||
if (N->isLeaf()) {
|
||||
Record *VR = N->getValueRecord();
|
||||
const std::string &LeafName = VR->getName();
|
||||
@ -820,6 +835,60 @@ static void ReduceAllOperands(TreePatternNode *N, const std::string &Name,
|
||||
}
|
||||
}
|
||||
|
||||
/// PrintExpanderOperand - Print out Arg as part of the instruction emission
|
||||
/// process for the expander pattern P. This argument may be referencing some
|
||||
/// values defined in P, or may just be physical register references or
|
||||
/// something like that. If PrintArg is true, we are printing out arguments to
|
||||
/// the BuildMI call. If it is false, we are printing the result register
|
||||
/// name.
|
||||
void InstrSelectorEmitter::PrintExpanderOperand(Init *Arg,
|
||||
const std::string &NameVar,
|
||||
Record *ArgDecl,
|
||||
Pattern *P, bool PrintArg,
|
||||
std::ostream &OS) {
|
||||
if (DefInit *DI = dynamic_cast<DefInit*>(Arg)) {
|
||||
Record *Arg = DI->getDef();
|
||||
if (Arg->isSubClassOf("Register")) {
|
||||
// This is a physical register reference... make sure that the instruction
|
||||
// requested a register!
|
||||
if (!ArgDecl->isSubClassOf("RegisterClass"))
|
||||
P->error("Argument mismatch for instruction pattern!");
|
||||
|
||||
// FIXME: This should check to see if the register is in the specified
|
||||
// register class!
|
||||
if (PrintArg) OS << ".addReg(";
|
||||
OS << getQualifiedName(Arg);
|
||||
if (PrintArg) OS << ")";
|
||||
return;
|
||||
} else if (Arg->isSubClassOf("RegisterClass")) {
|
||||
// If this is a symbolic register class reference, we must be using a
|
||||
// named value.
|
||||
if (NameVar.empty()) P->error("Did not specify WHICH register to pass!");
|
||||
if (Arg != ArgDecl) P->error("Instruction pattern mismatch!");
|
||||
|
||||
if (PrintArg) OS << ".addReg(";
|
||||
OS << NameVar;
|
||||
if (PrintArg) OS << ")";
|
||||
return;
|
||||
}
|
||||
P->error("Unknown operand type '" + Arg->getName() + "' to expander!");
|
||||
}
|
||||
P->error("Unknown operand type to expander!");
|
||||
}
|
||||
|
||||
static std::string getArgName(Pattern *P, const std::string &ArgName,
|
||||
const std::vector<std::pair<TreePatternNode*, std::string> > &Operands) {
|
||||
assert(P->getNumArgs() == Operands.size() &&"Argument computation mismatch!");
|
||||
if (ArgName.empty()) return "";
|
||||
|
||||
for (unsigned i = 0, e = P->getNumArgs(); i != e; ++i)
|
||||
if (P->getArgName(i) == ArgName)
|
||||
return Operands[i].second + "->Val";
|
||||
P->error("Pattern does not define a value named $" + ArgName + "!");
|
||||
return "";
|
||||
}
|
||||
|
||||
|
||||
void InstrSelectorEmitter::run(std::ostream &OS) {
|
||||
// Type-check all of the node types to ensure we "understand" them.
|
||||
ReadNodeTypes();
|
||||
@ -1074,6 +1143,7 @@ void InstrSelectorEmitter::run(std::ostream &OS) {
|
||||
// pattern that this is...
|
||||
switch (P->getPatternType()) {
|
||||
case Pattern::Instruction:
|
||||
// Instruction patterns just emit a single MachineInstr, using BuildMI
|
||||
OS << " BuildMI(MBB, " << Target.getName() << "::"
|
||||
<< P->getRecord()->getName() << ", " << Operands.size();
|
||||
if (P->getResult()) OS << ", NewReg";
|
||||
@ -1089,10 +1159,49 @@ void InstrSelectorEmitter::run(std::ostream &OS) {
|
||||
OS << ".addZImm(" << Operands[i].second << "->Val)";
|
||||
}
|
||||
OS << ";\n";
|
||||
break;
|
||||
case Pattern::Expander: {
|
||||
// Expander patterns emit one machine instr for each instruction in
|
||||
// the list of instructions expanded to.
|
||||
ListInit *Insts = P->getRecord()->getValueAsListInit("Result");
|
||||
for (unsigned IN = 0, e = Insts->getSize(); IN != e; ++IN) {
|
||||
DagInit *DIInst = dynamic_cast<DagInit*>(Insts->getElement(IN));
|
||||
if (!DIInst) P->error("Result list must contain instructions!");
|
||||
Pattern *InstPat = getPattern(DIInst->getNodeType());
|
||||
if (!InstPat || InstPat->getPatternType() != Pattern::Instruction)
|
||||
P->error("Instruction list must contain Instruction patterns!");
|
||||
|
||||
bool hasResult = InstPat->getResult() != 0;
|
||||
if (InstPat->getNumArgs() != DIInst->getNumArgs()-hasResult) {
|
||||
P->error("Incorrect number of arguments specified for inst '" +
|
||||
InstPat->getRecord()->getName() + "' in result list!");
|
||||
}
|
||||
|
||||
// Start emission of the instruction...
|
||||
OS << " BuildMI(MBB, " << Target.getName() << "::"
|
||||
<< InstPat->getRecord()->getName() << ", "
|
||||
<< DIInst->getNumArgs()-hasResult;
|
||||
// Emit register result if necessary..
|
||||
if (Record *R = InstPat->getResult()) {
|
||||
std::string ArgNameVal =
|
||||
getArgName(P, DIInst->getArgName(0), Operands);
|
||||
PrintExpanderOperand(DIInst->getArg(0), ArgNameVal,
|
||||
R, P, false, OS << ", ");
|
||||
}
|
||||
OS << ")";
|
||||
|
||||
for (unsigned i = hasResult, e = DIInst->getNumArgs(); i != e; ++i){
|
||||
std::string ArgNameVal =
|
||||
getArgName(P, DIInst->getArgName(i), Operands);
|
||||
|
||||
PrintExpanderOperand(DIInst->getArg(i), ArgNameVal,
|
||||
InstPat->getArgRec(i-hasResult), P, true, OS);
|
||||
}
|
||||
|
||||
OS << ";\n";
|
||||
}
|
||||
break;
|
||||
case Pattern::Expander:
|
||||
break;
|
||||
}
|
||||
default:
|
||||
assert(0 && "Reduction of this type of pattern not implemented!");
|
||||
}
|
||||
|
@ -57,13 +57,14 @@ class TreePatternNode {
|
||||
|
||||
/// Children - If this is not a leaf (Operator != 0), this is the subtrees
|
||||
/// that we contain.
|
||||
std::vector<TreePatternNode*> Children;
|
||||
std::vector<std::pair<TreePatternNode*, std::string> > Children;
|
||||
|
||||
/// Value - If this node is a leaf, this indicates what the thing is.
|
||||
///
|
||||
Init *Value;
|
||||
public:
|
||||
TreePatternNode(Record *o, const std::vector<TreePatternNode*> &c)
|
||||
TreePatternNode(Record *o, const std::vector<std::pair<TreePatternNode*,
|
||||
std::string> > &c)
|
||||
: Operator(o), Type(MVT::Other), Children(c), Value(0) {}
|
||||
TreePatternNode(Init *V) : Operator(0), Type(MVT::Other), Value(V) {}
|
||||
|
||||
@ -76,14 +77,16 @@ public:
|
||||
|
||||
bool isLeaf() const { return Operator == 0; }
|
||||
|
||||
const std::vector<TreePatternNode*> &getChildren() const {
|
||||
assert(Operator != 0 && "This is a leaf node!");
|
||||
return Children;
|
||||
}
|
||||
unsigned getNumChildren() const { return Children.size(); }
|
||||
TreePatternNode *getChild(unsigned c) const {
|
||||
assert(Operator != 0 && "This is a leaf node!");
|
||||
assert(c < Children.size() && "Child access out of range!");
|
||||
return getChildren()[c];
|
||||
return Children[c].first;
|
||||
}
|
||||
const std::string &getChildName(unsigned c) const {
|
||||
assert(Operator != 0 && "This is a leaf node!");
|
||||
assert(c < Children.size() && "Child access out of range!");
|
||||
return Children[c].second;
|
||||
}
|
||||
|
||||
Init *getValue() const {
|
||||
@ -151,6 +154,10 @@ private:
|
||||
///
|
||||
bool Resolved;
|
||||
|
||||
/// Args - This is a list of all of the arguments to this pattern, which are
|
||||
/// the non-void leaf nodes in this pattern.
|
||||
std::vector<std::pair<TreePatternNode*, std::string> > Args;
|
||||
|
||||
/// ISE - the instruction selector emitter coordinating this madness.
|
||||
///
|
||||
InstrSelectorEmitter &ISE;
|
||||
@ -164,7 +171,9 @@ public:
|
||||
/// Pattern - Constructor used for cloning nonterminal patterns
|
||||
Pattern(TreePatternNode *tree, Record *rec, bool res,
|
||||
InstrSelectorEmitter &ise) : PTy(Nonterminal), Tree(tree), Result(0),
|
||||
TheRecord(rec), Resolved(res), ISE(ise){}
|
||||
TheRecord(rec), Resolved(res), ISE(ise) {
|
||||
calculateArgs(Tree, "");
|
||||
}
|
||||
|
||||
/// getPatternType - Return what flavor of Record this pattern originated from
|
||||
///
|
||||
@ -181,6 +190,19 @@ public:
|
||||
///
|
||||
Record *getRecord() const { return TheRecord; }
|
||||
|
||||
unsigned getNumArgs() const { return Args.size(); }
|
||||
TreePatternNode *getArg(unsigned i) const {
|
||||
assert(i < Args.size() && "Argument reference out of range!");
|
||||
return Args[i].first;
|
||||
}
|
||||
Record *getArgRec(unsigned i) const {
|
||||
return getArg(i)->getValueRecord();
|
||||
}
|
||||
const std::string &getArgName(unsigned i) const {
|
||||
assert(i < Args.size() && "Argument reference out of range!");
|
||||
return Args[i].second;
|
||||
}
|
||||
|
||||
bool isResolved() const { return Resolved; }
|
||||
|
||||
/// InferAllTypes - Runs the type inference engine on the current pattern,
|
||||
@ -211,6 +233,7 @@ public:
|
||||
void dump() const;
|
||||
|
||||
private:
|
||||
void calculateArgs(TreePatternNode *N, const std::string &Name);
|
||||
MVT::ValueType getIntrinsicType(Record *R) const;
|
||||
TreePatternNode *ParseTreePattern(DagInit *DI);
|
||||
bool InferTypes(TreePatternNode *N, bool &MadeChange);
|
||||
@ -338,6 +361,16 @@ private:
|
||||
void EmitMatchCosters(std::ostream &OS,
|
||||
const std::vector<std::pair<Pattern*, TreePatternNode*> > &Patterns,
|
||||
const std::string &VarPrefix, unsigned Indent);
|
||||
|
||||
/// PrintExpanderOperand - Print out Arg as part of the instruction emission
|
||||
/// process for the expander pattern P. This argument may be referencing some
|
||||
/// values defined in P, or may just be physical register references or
|
||||
/// something like that. If PrintArg is true, we are printing out arguments
|
||||
/// to the BuildMI call. If it is false, we are printing the result register
|
||||
/// name.
|
||||
void PrintExpanderOperand(Init *Arg, const std::string &NameVar,
|
||||
Record *ArgDecl, Pattern *P,
|
||||
bool PrintArg, std::ostream &OS);
|
||||
};
|
||||
|
||||
#endif
|
||||
|
@ -55,8 +55,8 @@ bool TreePatternNode::updateNodeType(MVT::ValueType VT,
|
||||
///
|
||||
void TreePatternNode::InstantiateNonterminals(InstrSelectorEmitter &ISE) {
|
||||
if (!isLeaf()) {
|
||||
for (unsigned i = 0, e = Children.size(); i != e; ++i)
|
||||
Children[i]->InstantiateNonterminals(ISE);
|
||||
for (unsigned i = 0, e = getNumChildren(); i != e; ++i)
|
||||
getChild(i)->InstantiateNonterminals(ISE);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -82,9 +82,10 @@ TreePatternNode *TreePatternNode::clone() const {
|
||||
if (isLeaf()) {
|
||||
New = new TreePatternNode(Value);
|
||||
} else {
|
||||
std::vector<TreePatternNode*> CChildren(Children.size());
|
||||
for (unsigned i = 0, e = Children.size(); i != e; ++i)
|
||||
CChildren[i] = Children[i]->clone();
|
||||
std::vector<std::pair<TreePatternNode*, std::string> > CChildren;
|
||||
CChildren.reserve(Children.size());
|
||||
for (unsigned i = 0, e = getNumChildren(); i != e; ++i)
|
||||
CChildren.push_back(std::make_pair(getChild(i)->clone(),getChildName(i)));
|
||||
New = new TreePatternNode(Operator, CChildren);
|
||||
}
|
||||
New->setType(Type);
|
||||
@ -97,11 +98,10 @@ std::ostream &operator<<(std::ostream &OS, const TreePatternNode &N) {
|
||||
OS << "(" << N.getType() << ":";
|
||||
OS << N.getOperator()->getName();
|
||||
|
||||
const std::vector<TreePatternNode*> &Children = N.getChildren();
|
||||
if (!Children.empty()) {
|
||||
OS << " " << *Children[0];
|
||||
for (unsigned i = 1, e = Children.size(); i != e; ++i)
|
||||
OS << ", " << *Children[i];
|
||||
if (N.getNumChildren() != 0) {
|
||||
OS << " " << *N.getChild(0);
|
||||
for (unsigned i = 1, e = N.getNumChildren(); i != e; ++i)
|
||||
OS << ", " << *N.getChild(i);
|
||||
}
|
||||
return OS << ")";
|
||||
}
|
||||
@ -133,13 +133,15 @@ Pattern::Pattern(PatternType pty, DagInit *RawPat, Record *TheRec,
|
||||
|
||||
// Check to see if we have a top-level (set) of a register.
|
||||
if (Tree->getOperator()->getName() == "set") {
|
||||
assert(Tree->getChildren().size() == 2 && "Set with != 2 arguments?");
|
||||
assert(Tree->getNumChildren() == 2 && "Set with != 2 arguments?");
|
||||
if (!Tree->getChild(0)->isLeaf())
|
||||
error("Arg #0 of set should be a register or register class!");
|
||||
Result = Tree->getChild(0)->getValueRecord();
|
||||
Tree = Tree->getChild(1);
|
||||
}
|
||||
}
|
||||
|
||||
calculateArgs(Tree, "");
|
||||
}
|
||||
|
||||
void Pattern::error(const std::string &Msg) const {
|
||||
@ -152,6 +154,19 @@ void Pattern::error(const std::string &Msg) const {
|
||||
throw M + TheRecord->getName() + ": " + Msg;
|
||||
}
|
||||
|
||||
/// calculateArgs - Compute the list of all of the arguments to this pattern,
|
||||
/// which are the non-void leaf nodes in this pattern.
|
||||
///
|
||||
void Pattern::calculateArgs(TreePatternNode *N, const std::string &Name) {
|
||||
if (N->isLeaf() || N->getNumChildren() == 0) {
|
||||
if (N->getType() != MVT::isVoid)
|
||||
Args.push_back(std::make_pair(N, Name));
|
||||
} else {
|
||||
for (unsigned i = 0, e = N->getNumChildren(); i != e; ++i)
|
||||
calculateArgs(N->getChild(i), N->getChildName(i));
|
||||
}
|
||||
}
|
||||
|
||||
/// getIntrinsicType - Check to see if the specified record has an intrinsic
|
||||
/// type which should be applied to it. This infer the type of register
|
||||
/// references from the register file information, for example.
|
||||
@ -199,12 +214,13 @@ TreePatternNode *Pattern::ParseTreePattern(DagInit *Dag) {
|
||||
if (!ISE.getNodeTypes().count(Operator))
|
||||
error("Unrecognized node '" + Operator->getName() + "'!");
|
||||
|
||||
std::vector<TreePatternNode*> Children;
|
||||
std::vector<std::pair<TreePatternNode*, std::string> > Children;
|
||||
|
||||
for (unsigned i = 0, e = Dag->getNumArgs(); i != e; ++i) {
|
||||
Init *Arg = Dag->getArg(i);
|
||||
if (DagInit *DI = dynamic_cast<DagInit*>(Arg)) {
|
||||
Children.push_back(ParseTreePattern(DI));
|
||||
Children.push_back(std::make_pair(ParseTreePattern(DI),
|
||||
Dag->getArgName(i)));
|
||||
} else if (DefInit *DefI = dynamic_cast<DefInit*>(Arg)) {
|
||||
Record *R = DefI->getDef();
|
||||
// Direct reference to a leaf DagNode? Turn it into a DagNode if its own.
|
||||
@ -213,9 +229,10 @@ TreePatternNode *Pattern::ParseTreePattern(DagInit *Dag) {
|
||||
std::vector<std::pair<Init*, std::string> >()));
|
||||
--i; // Revisit this node...
|
||||
} else {
|
||||
Children.push_back(new TreePatternNode(DefI));
|
||||
Children.push_back(std::make_pair(new TreePatternNode(DefI),
|
||||
Dag->getArgName(i)));
|
||||
// If it's a regclass or something else known, set the type.
|
||||
Children.back()->setType(getIntrinsicType(R));
|
||||
Children.back().first->setType(getIntrinsicType(R));
|
||||
}
|
||||
} else {
|
||||
Arg->dump();
|
||||
@ -248,17 +265,16 @@ bool Pattern::InferTypes(TreePatternNode *N, bool &MadeChange) {
|
||||
|
||||
// Check to see if we can infer anything about the argument types from the
|
||||
// return types...
|
||||
const std::vector<TreePatternNode*> &Children = N->getChildren();
|
||||
if (Children.size() != NT.ArgTypes.size())
|
||||
if (N->getNumChildren() != NT.ArgTypes.size())
|
||||
error("Incorrect number of children for " + Operator->getName() + " node!");
|
||||
|
||||
for (unsigned i = 0, e = Children.size(); i != e; ++i) {
|
||||
TreePatternNode *Child = Children[i];
|
||||
for (unsigned i = 0, e = N->getNumChildren(); i != e; ++i) {
|
||||
TreePatternNode *Child = N->getChild(i);
|
||||
AnyUnset |= InferTypes(Child, MadeChange);
|
||||
|
||||
switch (NT.ArgTypes[i]) {
|
||||
case NodeType::Arg0:
|
||||
MadeChange |= Child->updateNodeType(Children[0]->getType(),
|
||||
MadeChange |= Child->updateNodeType(N->getChild(0)->getType(),
|
||||
TheRecord->getName());
|
||||
break;
|
||||
case NodeType::Val:
|
||||
@ -279,7 +295,7 @@ bool Pattern::InferTypes(TreePatternNode *N, bool &MadeChange) {
|
||||
MadeChange |= N->updateNodeType(MVT::isVoid, TheRecord->getName());
|
||||
break;
|
||||
case NodeType::Arg0:
|
||||
MadeChange |= N->updateNodeType(Children[0]->getType(),
|
||||
MadeChange |= N->updateNodeType(N->getChild(0)->getType(),
|
||||
TheRecord->getName());
|
||||
break;
|
||||
|
||||
@ -647,10 +663,9 @@ void InstrSelectorEmitter::EmitMatchCosters(std::ostream &OS,
|
||||
OS << "\n" << Indent << "// Operand matching costs...\n";
|
||||
std::set<std::string> ComputedValues; // Avoid duplicate computations...
|
||||
for (unsigned i = 0, e = Patterns.size(); i != e; ++i) {
|
||||
const std::vector<TreePatternNode*> &Children =
|
||||
Patterns[i].second->getChildren();
|
||||
for (unsigned c = 0, e = Children.size(); c != e; ++c) {
|
||||
TreePatternNode *N = Children[c];
|
||||
TreePatternNode *NParent = Patterns[i].second;
|
||||
for (unsigned c = 0, e = NParent->getNumChildren(); c != e; ++c) {
|
||||
TreePatternNode *N = NParent->getChild(c);
|
||||
if (N->isLeaf()) {
|
||||
Record *VR = N->getValueRecord();
|
||||
const std::string &LeafName = VR->getName();
|
||||
@ -820,6 +835,60 @@ static void ReduceAllOperands(TreePatternNode *N, const std::string &Name,
|
||||
}
|
||||
}
|
||||
|
||||
/// PrintExpanderOperand - Print out Arg as part of the instruction emission
|
||||
/// process for the expander pattern P. This argument may be referencing some
|
||||
/// values defined in P, or may just be physical register references or
|
||||
/// something like that. If PrintArg is true, we are printing out arguments to
|
||||
/// the BuildMI call. If it is false, we are printing the result register
|
||||
/// name.
|
||||
void InstrSelectorEmitter::PrintExpanderOperand(Init *Arg,
|
||||
const std::string &NameVar,
|
||||
Record *ArgDecl,
|
||||
Pattern *P, bool PrintArg,
|
||||
std::ostream &OS) {
|
||||
if (DefInit *DI = dynamic_cast<DefInit*>(Arg)) {
|
||||
Record *Arg = DI->getDef();
|
||||
if (Arg->isSubClassOf("Register")) {
|
||||
// This is a physical register reference... make sure that the instruction
|
||||
// requested a register!
|
||||
if (!ArgDecl->isSubClassOf("RegisterClass"))
|
||||
P->error("Argument mismatch for instruction pattern!");
|
||||
|
||||
// FIXME: This should check to see if the register is in the specified
|
||||
// register class!
|
||||
if (PrintArg) OS << ".addReg(";
|
||||
OS << getQualifiedName(Arg);
|
||||
if (PrintArg) OS << ")";
|
||||
return;
|
||||
} else if (Arg->isSubClassOf("RegisterClass")) {
|
||||
// If this is a symbolic register class reference, we must be using a
|
||||
// named value.
|
||||
if (NameVar.empty()) P->error("Did not specify WHICH register to pass!");
|
||||
if (Arg != ArgDecl) P->error("Instruction pattern mismatch!");
|
||||
|
||||
if (PrintArg) OS << ".addReg(";
|
||||
OS << NameVar;
|
||||
if (PrintArg) OS << ")";
|
||||
return;
|
||||
}
|
||||
P->error("Unknown operand type '" + Arg->getName() + "' to expander!");
|
||||
}
|
||||
P->error("Unknown operand type to expander!");
|
||||
}
|
||||
|
||||
static std::string getArgName(Pattern *P, const std::string &ArgName,
|
||||
const std::vector<std::pair<TreePatternNode*, std::string> > &Operands) {
|
||||
assert(P->getNumArgs() == Operands.size() &&"Argument computation mismatch!");
|
||||
if (ArgName.empty()) return "";
|
||||
|
||||
for (unsigned i = 0, e = P->getNumArgs(); i != e; ++i)
|
||||
if (P->getArgName(i) == ArgName)
|
||||
return Operands[i].second + "->Val";
|
||||
P->error("Pattern does not define a value named $" + ArgName + "!");
|
||||
return "";
|
||||
}
|
||||
|
||||
|
||||
void InstrSelectorEmitter::run(std::ostream &OS) {
|
||||
// Type-check all of the node types to ensure we "understand" them.
|
||||
ReadNodeTypes();
|
||||
@ -1074,6 +1143,7 @@ void InstrSelectorEmitter::run(std::ostream &OS) {
|
||||
// pattern that this is...
|
||||
switch (P->getPatternType()) {
|
||||
case Pattern::Instruction:
|
||||
// Instruction patterns just emit a single MachineInstr, using BuildMI
|
||||
OS << " BuildMI(MBB, " << Target.getName() << "::"
|
||||
<< P->getRecord()->getName() << ", " << Operands.size();
|
||||
if (P->getResult()) OS << ", NewReg";
|
||||
@ -1089,10 +1159,49 @@ void InstrSelectorEmitter::run(std::ostream &OS) {
|
||||
OS << ".addZImm(" << Operands[i].second << "->Val)";
|
||||
}
|
||||
OS << ";\n";
|
||||
break;
|
||||
case Pattern::Expander: {
|
||||
// Expander patterns emit one machine instr for each instruction in
|
||||
// the list of instructions expanded to.
|
||||
ListInit *Insts = P->getRecord()->getValueAsListInit("Result");
|
||||
for (unsigned IN = 0, e = Insts->getSize(); IN != e; ++IN) {
|
||||
DagInit *DIInst = dynamic_cast<DagInit*>(Insts->getElement(IN));
|
||||
if (!DIInst) P->error("Result list must contain instructions!");
|
||||
Pattern *InstPat = getPattern(DIInst->getNodeType());
|
||||
if (!InstPat || InstPat->getPatternType() != Pattern::Instruction)
|
||||
P->error("Instruction list must contain Instruction patterns!");
|
||||
|
||||
bool hasResult = InstPat->getResult() != 0;
|
||||
if (InstPat->getNumArgs() != DIInst->getNumArgs()-hasResult) {
|
||||
P->error("Incorrect number of arguments specified for inst '" +
|
||||
InstPat->getRecord()->getName() + "' in result list!");
|
||||
}
|
||||
|
||||
// Start emission of the instruction...
|
||||
OS << " BuildMI(MBB, " << Target.getName() << "::"
|
||||
<< InstPat->getRecord()->getName() << ", "
|
||||
<< DIInst->getNumArgs()-hasResult;
|
||||
// Emit register result if necessary..
|
||||
if (Record *R = InstPat->getResult()) {
|
||||
std::string ArgNameVal =
|
||||
getArgName(P, DIInst->getArgName(0), Operands);
|
||||
PrintExpanderOperand(DIInst->getArg(0), ArgNameVal,
|
||||
R, P, false, OS << ", ");
|
||||
}
|
||||
OS << ")";
|
||||
|
||||
for (unsigned i = hasResult, e = DIInst->getNumArgs(); i != e; ++i){
|
||||
std::string ArgNameVal =
|
||||
getArgName(P, DIInst->getArgName(i), Operands);
|
||||
|
||||
PrintExpanderOperand(DIInst->getArg(i), ArgNameVal,
|
||||
InstPat->getArgRec(i-hasResult), P, true, OS);
|
||||
}
|
||||
|
||||
OS << ";\n";
|
||||
}
|
||||
break;
|
||||
case Pattern::Expander:
|
||||
break;
|
||||
}
|
||||
default:
|
||||
assert(0 && "Reduction of this type of pattern not implemented!");
|
||||
}
|
||||
|
@ -57,13 +57,14 @@ class TreePatternNode {
|
||||
|
||||
/// Children - If this is not a leaf (Operator != 0), this is the subtrees
|
||||
/// that we contain.
|
||||
std::vector<TreePatternNode*> Children;
|
||||
std::vector<std::pair<TreePatternNode*, std::string> > Children;
|
||||
|
||||
/// Value - If this node is a leaf, this indicates what the thing is.
|
||||
///
|
||||
Init *Value;
|
||||
public:
|
||||
TreePatternNode(Record *o, const std::vector<TreePatternNode*> &c)
|
||||
TreePatternNode(Record *o, const std::vector<std::pair<TreePatternNode*,
|
||||
std::string> > &c)
|
||||
: Operator(o), Type(MVT::Other), Children(c), Value(0) {}
|
||||
TreePatternNode(Init *V) : Operator(0), Type(MVT::Other), Value(V) {}
|
||||
|
||||
@ -76,14 +77,16 @@ public:
|
||||
|
||||
bool isLeaf() const { return Operator == 0; }
|
||||
|
||||
const std::vector<TreePatternNode*> &getChildren() const {
|
||||
assert(Operator != 0 && "This is a leaf node!");
|
||||
return Children;
|
||||
}
|
||||
unsigned getNumChildren() const { return Children.size(); }
|
||||
TreePatternNode *getChild(unsigned c) const {
|
||||
assert(Operator != 0 && "This is a leaf node!");
|
||||
assert(c < Children.size() && "Child access out of range!");
|
||||
return getChildren()[c];
|
||||
return Children[c].first;
|
||||
}
|
||||
const std::string &getChildName(unsigned c) const {
|
||||
assert(Operator != 0 && "This is a leaf node!");
|
||||
assert(c < Children.size() && "Child access out of range!");
|
||||
return Children[c].second;
|
||||
}
|
||||
|
||||
Init *getValue() const {
|
||||
@ -151,6 +154,10 @@ private:
|
||||
///
|
||||
bool Resolved;
|
||||
|
||||
/// Args - This is a list of all of the arguments to this pattern, which are
|
||||
/// the non-void leaf nodes in this pattern.
|
||||
std::vector<std::pair<TreePatternNode*, std::string> > Args;
|
||||
|
||||
/// ISE - the instruction selector emitter coordinating this madness.
|
||||
///
|
||||
InstrSelectorEmitter &ISE;
|
||||
@ -164,7 +171,9 @@ public:
|
||||
/// Pattern - Constructor used for cloning nonterminal patterns
|
||||
Pattern(TreePatternNode *tree, Record *rec, bool res,
|
||||
InstrSelectorEmitter &ise) : PTy(Nonterminal), Tree(tree), Result(0),
|
||||
TheRecord(rec), Resolved(res), ISE(ise){}
|
||||
TheRecord(rec), Resolved(res), ISE(ise) {
|
||||
calculateArgs(Tree, "");
|
||||
}
|
||||
|
||||
/// getPatternType - Return what flavor of Record this pattern originated from
|
||||
///
|
||||
@ -181,6 +190,19 @@ public:
|
||||
///
|
||||
Record *getRecord() const { return TheRecord; }
|
||||
|
||||
unsigned getNumArgs() const { return Args.size(); }
|
||||
TreePatternNode *getArg(unsigned i) const {
|
||||
assert(i < Args.size() && "Argument reference out of range!");
|
||||
return Args[i].first;
|
||||
}
|
||||
Record *getArgRec(unsigned i) const {
|
||||
return getArg(i)->getValueRecord();
|
||||
}
|
||||
const std::string &getArgName(unsigned i) const {
|
||||
assert(i < Args.size() && "Argument reference out of range!");
|
||||
return Args[i].second;
|
||||
}
|
||||
|
||||
bool isResolved() const { return Resolved; }
|
||||
|
||||
/// InferAllTypes - Runs the type inference engine on the current pattern,
|
||||
@ -211,6 +233,7 @@ public:
|
||||
void dump() const;
|
||||
|
||||
private:
|
||||
void calculateArgs(TreePatternNode *N, const std::string &Name);
|
||||
MVT::ValueType getIntrinsicType(Record *R) const;
|
||||
TreePatternNode *ParseTreePattern(DagInit *DI);
|
||||
bool InferTypes(TreePatternNode *N, bool &MadeChange);
|
||||
@ -338,6 +361,16 @@ private:
|
||||
void EmitMatchCosters(std::ostream &OS,
|
||||
const std::vector<std::pair<Pattern*, TreePatternNode*> > &Patterns,
|
||||
const std::string &VarPrefix, unsigned Indent);
|
||||
|
||||
/// PrintExpanderOperand - Print out Arg as part of the instruction emission
|
||||
/// process for the expander pattern P. This argument may be referencing some
|
||||
/// values defined in P, or may just be physical register references or
|
||||
/// something like that. If PrintArg is true, we are printing out arguments
|
||||
/// to the BuildMI call. If it is false, we are printing the result register
|
||||
/// name.
|
||||
void PrintExpanderOperand(Init *Arg, const std::string &NameVar,
|
||||
Record *ArgDecl, Pattern *P,
|
||||
bool PrintArg, std::ostream &OS);
|
||||
};
|
||||
|
||||
#endif
|
||||
|
Loading…
x
Reference in New Issue
Block a user