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:
Chris Lattner 2003-08-10 23:51:52 +00:00
parent 990db46e9a
commit 053a205d63
4 changed files with 354 additions and 70 deletions

View File

@ -55,8 +55,8 @@ bool TreePatternNode::updateNodeType(MVT::ValueType VT,
/// ///
void TreePatternNode::InstantiateNonterminals(InstrSelectorEmitter &ISE) { void TreePatternNode::InstantiateNonterminals(InstrSelectorEmitter &ISE) {
if (!isLeaf()) { if (!isLeaf()) {
for (unsigned i = 0, e = Children.size(); i != e; ++i) for (unsigned i = 0, e = getNumChildren(); i != e; ++i)
Children[i]->InstantiateNonterminals(ISE); getChild(i)->InstantiateNonterminals(ISE);
return; return;
} }
@ -82,9 +82,10 @@ TreePatternNode *TreePatternNode::clone() const {
if (isLeaf()) { if (isLeaf()) {
New = new TreePatternNode(Value); New = new TreePatternNode(Value);
} else { } else {
std::vector<TreePatternNode*> CChildren(Children.size()); std::vector<std::pair<TreePatternNode*, std::string> > CChildren;
for (unsigned i = 0, e = Children.size(); i != e; ++i) CChildren.reserve(Children.size());
CChildren[i] = Children[i]->clone(); 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 = new TreePatternNode(Operator, CChildren);
} }
New->setType(Type); New->setType(Type);
@ -97,11 +98,10 @@ std::ostream &operator<<(std::ostream &OS, const TreePatternNode &N) {
OS << "(" << N.getType() << ":"; OS << "(" << N.getType() << ":";
OS << N.getOperator()->getName(); OS << N.getOperator()->getName();
const std::vector<TreePatternNode*> &Children = N.getChildren(); if (N.getNumChildren() != 0) {
if (!Children.empty()) { OS << " " << *N.getChild(0);
OS << " " << *Children[0]; for (unsigned i = 1, e = N.getNumChildren(); i != e; ++i)
for (unsigned i = 1, e = Children.size(); i != e; ++i) OS << ", " << *N.getChild(i);
OS << ", " << *Children[i];
} }
return OS << ")"; 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. // Check to see if we have a top-level (set) of a register.
if (Tree->getOperator()->getName() == "set") { 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()) if (!Tree->getChild(0)->isLeaf())
error("Arg #0 of set should be a register or register class!"); error("Arg #0 of set should be a register or register class!");
Result = Tree->getChild(0)->getValueRecord(); Result = Tree->getChild(0)->getValueRecord();
Tree = Tree->getChild(1); Tree = Tree->getChild(1);
} }
} }
calculateArgs(Tree, "");
} }
void Pattern::error(const std::string &Msg) const { 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; 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 /// getIntrinsicType - Check to see if the specified record has an intrinsic
/// type which should be applied to it. This infer the type of register /// type which should be applied to it. This infer the type of register
/// references from the register file information, for example. /// references from the register file information, for example.
@ -199,12 +214,13 @@ TreePatternNode *Pattern::ParseTreePattern(DagInit *Dag) {
if (!ISE.getNodeTypes().count(Operator)) if (!ISE.getNodeTypes().count(Operator))
error("Unrecognized node '" + Operator->getName() + "'!"); 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) { for (unsigned i = 0, e = Dag->getNumArgs(); i != e; ++i) {
Init *Arg = Dag->getArg(i); Init *Arg = Dag->getArg(i);
if (DagInit *DI = dynamic_cast<DagInit*>(Arg)) { 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)) { } else if (DefInit *DefI = dynamic_cast<DefInit*>(Arg)) {
Record *R = DefI->getDef(); Record *R = DefI->getDef();
// Direct reference to a leaf DagNode? Turn it into a DagNode if its own. // 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> >())); std::vector<std::pair<Init*, std::string> >()));
--i; // Revisit this node... --i; // Revisit this node...
} else { } 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. // If it's a regclass or something else known, set the type.
Children.back()->setType(getIntrinsicType(R)); Children.back().first->setType(getIntrinsicType(R));
} }
} else { } else {
Arg->dump(); 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 // Check to see if we can infer anything about the argument types from the
// return types... // return types...
const std::vector<TreePatternNode*> &Children = N->getChildren(); if (N->getNumChildren() != NT.ArgTypes.size())
if (Children.size() != NT.ArgTypes.size())
error("Incorrect number of children for " + Operator->getName() + " node!"); error("Incorrect number of children for " + Operator->getName() + " node!");
for (unsigned i = 0, e = Children.size(); i != e; ++i) { for (unsigned i = 0, e = N->getNumChildren(); i != e; ++i) {
TreePatternNode *Child = Children[i]; TreePatternNode *Child = N->getChild(i);
AnyUnset |= InferTypes(Child, MadeChange); AnyUnset |= InferTypes(Child, MadeChange);
switch (NT.ArgTypes[i]) { switch (NT.ArgTypes[i]) {
case NodeType::Arg0: case NodeType::Arg0:
MadeChange |= Child->updateNodeType(Children[0]->getType(), MadeChange |= Child->updateNodeType(N->getChild(0)->getType(),
TheRecord->getName()); TheRecord->getName());
break; break;
case NodeType::Val: case NodeType::Val:
@ -279,7 +295,7 @@ bool Pattern::InferTypes(TreePatternNode *N, bool &MadeChange) {
MadeChange |= N->updateNodeType(MVT::isVoid, TheRecord->getName()); MadeChange |= N->updateNodeType(MVT::isVoid, TheRecord->getName());
break; break;
case NodeType::Arg0: case NodeType::Arg0:
MadeChange |= N->updateNodeType(Children[0]->getType(), MadeChange |= N->updateNodeType(N->getChild(0)->getType(),
TheRecord->getName()); TheRecord->getName());
break; break;
@ -647,10 +663,9 @@ void InstrSelectorEmitter::EmitMatchCosters(std::ostream &OS,
OS << "\n" << Indent << "// Operand matching costs...\n"; OS << "\n" << Indent << "// Operand matching costs...\n";
std::set<std::string> ComputedValues; // Avoid duplicate computations... std::set<std::string> ComputedValues; // Avoid duplicate computations...
for (unsigned i = 0, e = Patterns.size(); i != e; ++i) { for (unsigned i = 0, e = Patterns.size(); i != e; ++i) {
const std::vector<TreePatternNode*> &Children = TreePatternNode *NParent = Patterns[i].second;
Patterns[i].second->getChildren(); for (unsigned c = 0, e = NParent->getNumChildren(); c != e; ++c) {
for (unsigned c = 0, e = Children.size(); c != e; ++c) { TreePatternNode *N = NParent->getChild(c);
TreePatternNode *N = Children[c];
if (N->isLeaf()) { if (N->isLeaf()) {
Record *VR = N->getValueRecord(); Record *VR = N->getValueRecord();
const std::string &LeafName = VR->getName(); 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) { void InstrSelectorEmitter::run(std::ostream &OS) {
// Type-check all of the node types to ensure we "understand" them. // Type-check all of the node types to ensure we "understand" them.
ReadNodeTypes(); ReadNodeTypes();
@ -1074,6 +1143,7 @@ void InstrSelectorEmitter::run(std::ostream &OS) {
// pattern that this is... // pattern that this is...
switch (P->getPatternType()) { switch (P->getPatternType()) {
case Pattern::Instruction: case Pattern::Instruction:
// Instruction patterns just emit a single MachineInstr, using BuildMI
OS << " BuildMI(MBB, " << Target.getName() << "::" OS << " BuildMI(MBB, " << Target.getName() << "::"
<< P->getRecord()->getName() << ", " << Operands.size(); << P->getRecord()->getName() << ", " << Operands.size();
if (P->getResult()) OS << ", NewReg"; if (P->getResult()) OS << ", NewReg";
@ -1089,10 +1159,49 @@ void InstrSelectorEmitter::run(std::ostream &OS) {
OS << ".addZImm(" << Operands[i].second << "->Val)"; OS << ".addZImm(" << Operands[i].second << "->Val)";
} }
OS << ";\n"; 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; break;
case Pattern::Expander: }
break;
default: default:
assert(0 && "Reduction of this type of pattern not implemented!"); assert(0 && "Reduction of this type of pattern not implemented!");
} }

View File

@ -57,13 +57,14 @@ class TreePatternNode {
/// Children - If this is not a leaf (Operator != 0), this is the subtrees /// Children - If this is not a leaf (Operator != 0), this is the subtrees
/// that we contain. /// 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. /// Value - If this node is a leaf, this indicates what the thing is.
/// ///
Init *Value; Init *Value;
public: 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) {} : Operator(o), Type(MVT::Other), Children(c), Value(0) {}
TreePatternNode(Init *V) : Operator(0), Type(MVT::Other), Value(V) {} TreePatternNode(Init *V) : Operator(0), Type(MVT::Other), Value(V) {}
@ -76,14 +77,16 @@ public:
bool isLeaf() const { return Operator == 0; } 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(); } unsigned getNumChildren() const { return Children.size(); }
TreePatternNode *getChild(unsigned c) const { TreePatternNode *getChild(unsigned c) const {
assert(Operator != 0 && "This is a leaf node!");
assert(c < Children.size() && "Child access out of range!"); 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 { Init *getValue() const {
@ -151,6 +154,10 @@ private:
/// ///
bool Resolved; 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. /// ISE - the instruction selector emitter coordinating this madness.
/// ///
InstrSelectorEmitter &ISE; InstrSelectorEmitter &ISE;
@ -164,7 +171,9 @@ public:
/// Pattern - Constructor used for cloning nonterminal patterns /// Pattern - Constructor used for cloning nonterminal patterns
Pattern(TreePatternNode *tree, Record *rec, bool res, Pattern(TreePatternNode *tree, Record *rec, bool res,
InstrSelectorEmitter &ise) : PTy(Nonterminal), Tree(tree), Result(0), 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 /// getPatternType - Return what flavor of Record this pattern originated from
/// ///
@ -181,6 +190,19 @@ public:
/// ///
Record *getRecord() const { return TheRecord; } 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; } bool isResolved() const { return Resolved; }
/// InferAllTypes - Runs the type inference engine on the current pattern, /// InferAllTypes - Runs the type inference engine on the current pattern,
@ -211,6 +233,7 @@ public:
void dump() const; void dump() const;
private: private:
void calculateArgs(TreePatternNode *N, const std::string &Name);
MVT::ValueType getIntrinsicType(Record *R) const; MVT::ValueType getIntrinsicType(Record *R) const;
TreePatternNode *ParseTreePattern(DagInit *DI); TreePatternNode *ParseTreePattern(DagInit *DI);
bool InferTypes(TreePatternNode *N, bool &MadeChange); bool InferTypes(TreePatternNode *N, bool &MadeChange);
@ -338,6 +361,16 @@ private:
void EmitMatchCosters(std::ostream &OS, void EmitMatchCosters(std::ostream &OS,
const std::vector<std::pair<Pattern*, TreePatternNode*> > &Patterns, const std::vector<std::pair<Pattern*, TreePatternNode*> > &Patterns,
const std::string &VarPrefix, unsigned Indent); 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 #endif

View File

@ -55,8 +55,8 @@ bool TreePatternNode::updateNodeType(MVT::ValueType VT,
/// ///
void TreePatternNode::InstantiateNonterminals(InstrSelectorEmitter &ISE) { void TreePatternNode::InstantiateNonterminals(InstrSelectorEmitter &ISE) {
if (!isLeaf()) { if (!isLeaf()) {
for (unsigned i = 0, e = Children.size(); i != e; ++i) for (unsigned i = 0, e = getNumChildren(); i != e; ++i)
Children[i]->InstantiateNonterminals(ISE); getChild(i)->InstantiateNonterminals(ISE);
return; return;
} }
@ -82,9 +82,10 @@ TreePatternNode *TreePatternNode::clone() const {
if (isLeaf()) { if (isLeaf()) {
New = new TreePatternNode(Value); New = new TreePatternNode(Value);
} else { } else {
std::vector<TreePatternNode*> CChildren(Children.size()); std::vector<std::pair<TreePatternNode*, std::string> > CChildren;
for (unsigned i = 0, e = Children.size(); i != e; ++i) CChildren.reserve(Children.size());
CChildren[i] = Children[i]->clone(); 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 = new TreePatternNode(Operator, CChildren);
} }
New->setType(Type); New->setType(Type);
@ -97,11 +98,10 @@ std::ostream &operator<<(std::ostream &OS, const TreePatternNode &N) {
OS << "(" << N.getType() << ":"; OS << "(" << N.getType() << ":";
OS << N.getOperator()->getName(); OS << N.getOperator()->getName();
const std::vector<TreePatternNode*> &Children = N.getChildren(); if (N.getNumChildren() != 0) {
if (!Children.empty()) { OS << " " << *N.getChild(0);
OS << " " << *Children[0]; for (unsigned i = 1, e = N.getNumChildren(); i != e; ++i)
for (unsigned i = 1, e = Children.size(); i != e; ++i) OS << ", " << *N.getChild(i);
OS << ", " << *Children[i];
} }
return OS << ")"; 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. // Check to see if we have a top-level (set) of a register.
if (Tree->getOperator()->getName() == "set") { 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()) if (!Tree->getChild(0)->isLeaf())
error("Arg #0 of set should be a register or register class!"); error("Arg #0 of set should be a register or register class!");
Result = Tree->getChild(0)->getValueRecord(); Result = Tree->getChild(0)->getValueRecord();
Tree = Tree->getChild(1); Tree = Tree->getChild(1);
} }
} }
calculateArgs(Tree, "");
} }
void Pattern::error(const std::string &Msg) const { 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; 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 /// getIntrinsicType - Check to see if the specified record has an intrinsic
/// type which should be applied to it. This infer the type of register /// type which should be applied to it. This infer the type of register
/// references from the register file information, for example. /// references from the register file information, for example.
@ -199,12 +214,13 @@ TreePatternNode *Pattern::ParseTreePattern(DagInit *Dag) {
if (!ISE.getNodeTypes().count(Operator)) if (!ISE.getNodeTypes().count(Operator))
error("Unrecognized node '" + Operator->getName() + "'!"); 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) { for (unsigned i = 0, e = Dag->getNumArgs(); i != e; ++i) {
Init *Arg = Dag->getArg(i); Init *Arg = Dag->getArg(i);
if (DagInit *DI = dynamic_cast<DagInit*>(Arg)) { 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)) { } else if (DefInit *DefI = dynamic_cast<DefInit*>(Arg)) {
Record *R = DefI->getDef(); Record *R = DefI->getDef();
// Direct reference to a leaf DagNode? Turn it into a DagNode if its own. // 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> >())); std::vector<std::pair<Init*, std::string> >()));
--i; // Revisit this node... --i; // Revisit this node...
} else { } 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. // If it's a regclass or something else known, set the type.
Children.back()->setType(getIntrinsicType(R)); Children.back().first->setType(getIntrinsicType(R));
} }
} else { } else {
Arg->dump(); 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 // Check to see if we can infer anything about the argument types from the
// return types... // return types...
const std::vector<TreePatternNode*> &Children = N->getChildren(); if (N->getNumChildren() != NT.ArgTypes.size())
if (Children.size() != NT.ArgTypes.size())
error("Incorrect number of children for " + Operator->getName() + " node!"); error("Incorrect number of children for " + Operator->getName() + " node!");
for (unsigned i = 0, e = Children.size(); i != e; ++i) { for (unsigned i = 0, e = N->getNumChildren(); i != e; ++i) {
TreePatternNode *Child = Children[i]; TreePatternNode *Child = N->getChild(i);
AnyUnset |= InferTypes(Child, MadeChange); AnyUnset |= InferTypes(Child, MadeChange);
switch (NT.ArgTypes[i]) { switch (NT.ArgTypes[i]) {
case NodeType::Arg0: case NodeType::Arg0:
MadeChange |= Child->updateNodeType(Children[0]->getType(), MadeChange |= Child->updateNodeType(N->getChild(0)->getType(),
TheRecord->getName()); TheRecord->getName());
break; break;
case NodeType::Val: case NodeType::Val:
@ -279,7 +295,7 @@ bool Pattern::InferTypes(TreePatternNode *N, bool &MadeChange) {
MadeChange |= N->updateNodeType(MVT::isVoid, TheRecord->getName()); MadeChange |= N->updateNodeType(MVT::isVoid, TheRecord->getName());
break; break;
case NodeType::Arg0: case NodeType::Arg0:
MadeChange |= N->updateNodeType(Children[0]->getType(), MadeChange |= N->updateNodeType(N->getChild(0)->getType(),
TheRecord->getName()); TheRecord->getName());
break; break;
@ -647,10 +663,9 @@ void InstrSelectorEmitter::EmitMatchCosters(std::ostream &OS,
OS << "\n" << Indent << "// Operand matching costs...\n"; OS << "\n" << Indent << "// Operand matching costs...\n";
std::set<std::string> ComputedValues; // Avoid duplicate computations... std::set<std::string> ComputedValues; // Avoid duplicate computations...
for (unsigned i = 0, e = Patterns.size(); i != e; ++i) { for (unsigned i = 0, e = Patterns.size(); i != e; ++i) {
const std::vector<TreePatternNode*> &Children = TreePatternNode *NParent = Patterns[i].second;
Patterns[i].second->getChildren(); for (unsigned c = 0, e = NParent->getNumChildren(); c != e; ++c) {
for (unsigned c = 0, e = Children.size(); c != e; ++c) { TreePatternNode *N = NParent->getChild(c);
TreePatternNode *N = Children[c];
if (N->isLeaf()) { if (N->isLeaf()) {
Record *VR = N->getValueRecord(); Record *VR = N->getValueRecord();
const std::string &LeafName = VR->getName(); 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) { void InstrSelectorEmitter::run(std::ostream &OS) {
// Type-check all of the node types to ensure we "understand" them. // Type-check all of the node types to ensure we "understand" them.
ReadNodeTypes(); ReadNodeTypes();
@ -1074,6 +1143,7 @@ void InstrSelectorEmitter::run(std::ostream &OS) {
// pattern that this is... // pattern that this is...
switch (P->getPatternType()) { switch (P->getPatternType()) {
case Pattern::Instruction: case Pattern::Instruction:
// Instruction patterns just emit a single MachineInstr, using BuildMI
OS << " BuildMI(MBB, " << Target.getName() << "::" OS << " BuildMI(MBB, " << Target.getName() << "::"
<< P->getRecord()->getName() << ", " << Operands.size(); << P->getRecord()->getName() << ", " << Operands.size();
if (P->getResult()) OS << ", NewReg"; if (P->getResult()) OS << ", NewReg";
@ -1089,10 +1159,49 @@ void InstrSelectorEmitter::run(std::ostream &OS) {
OS << ".addZImm(" << Operands[i].second << "->Val)"; OS << ".addZImm(" << Operands[i].second << "->Val)";
} }
OS << ";\n"; 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; break;
case Pattern::Expander: }
break;
default: default:
assert(0 && "Reduction of this type of pattern not implemented!"); assert(0 && "Reduction of this type of pattern not implemented!");
} }

View File

@ -57,13 +57,14 @@ class TreePatternNode {
/// Children - If this is not a leaf (Operator != 0), this is the subtrees /// Children - If this is not a leaf (Operator != 0), this is the subtrees
/// that we contain. /// 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. /// Value - If this node is a leaf, this indicates what the thing is.
/// ///
Init *Value; Init *Value;
public: 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) {} : Operator(o), Type(MVT::Other), Children(c), Value(0) {}
TreePatternNode(Init *V) : Operator(0), Type(MVT::Other), Value(V) {} TreePatternNode(Init *V) : Operator(0), Type(MVT::Other), Value(V) {}
@ -76,14 +77,16 @@ public:
bool isLeaf() const { return Operator == 0; } 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(); } unsigned getNumChildren() const { return Children.size(); }
TreePatternNode *getChild(unsigned c) const { TreePatternNode *getChild(unsigned c) const {
assert(Operator != 0 && "This is a leaf node!");
assert(c < Children.size() && "Child access out of range!"); 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 { Init *getValue() const {
@ -151,6 +154,10 @@ private:
/// ///
bool Resolved; 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. /// ISE - the instruction selector emitter coordinating this madness.
/// ///
InstrSelectorEmitter &ISE; InstrSelectorEmitter &ISE;
@ -164,7 +171,9 @@ public:
/// Pattern - Constructor used for cloning nonterminal patterns /// Pattern - Constructor used for cloning nonterminal patterns
Pattern(TreePatternNode *tree, Record *rec, bool res, Pattern(TreePatternNode *tree, Record *rec, bool res,
InstrSelectorEmitter &ise) : PTy(Nonterminal), Tree(tree), Result(0), 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 /// getPatternType - Return what flavor of Record this pattern originated from
/// ///
@ -181,6 +190,19 @@ public:
/// ///
Record *getRecord() const { return TheRecord; } 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; } bool isResolved() const { return Resolved; }
/// InferAllTypes - Runs the type inference engine on the current pattern, /// InferAllTypes - Runs the type inference engine on the current pattern,
@ -211,6 +233,7 @@ public:
void dump() const; void dump() const;
private: private:
void calculateArgs(TreePatternNode *N, const std::string &Name);
MVT::ValueType getIntrinsicType(Record *R) const; MVT::ValueType getIntrinsicType(Record *R) const;
TreePatternNode *ParseTreePattern(DagInit *DI); TreePatternNode *ParseTreePattern(DagInit *DI);
bool InferTypes(TreePatternNode *N, bool &MadeChange); bool InferTypes(TreePatternNode *N, bool &MadeChange);
@ -338,6 +361,16 @@ private:
void EmitMatchCosters(std::ostream &OS, void EmitMatchCosters(std::ostream &OS,
const std::vector<std::pair<Pattern*, TreePatternNode*> > &Patterns, const std::vector<std::pair<Pattern*, TreePatternNode*> > &Patterns,
const std::string &VarPrefix, unsigned Indent); 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 #endif