summaryrefslogtreecommitdiff
path: root/utils
diff options
context:
space:
mode:
authorChris Lattner <sabre@nondot.org>2003-08-10 23:51:52 +0000
committerChris Lattner <sabre@nondot.org>2003-08-10 23:51:52 +0000
commit053a205d63df7a786d0e5624e9c507532136a150 (patch)
treeecb2c8c56392c490ca00fc57fa02024dfab566ba /utils
parent990db46e9ae7faa742a152ca4126d0bee9f1df9c (diff)
downloadllvm-053a205d63df7a786d0e5624e9c507532136a150.tar.gz
llvm-053a205d63df7a786d0e5624e9c507532136a150.tar.bz2
llvm-053a205d63df7a786d0e5624e9c507532136a150.tar.xz
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
Diffstat (limited to 'utils')
-rw-r--r--utils/TableGen/InstrSelectorEmitter.cpp163
-rw-r--r--utils/TableGen/InstrSelectorEmitter.h49
2 files changed, 177 insertions, 35 deletions
diff --git a/utils/TableGen/InstrSelectorEmitter.cpp b/utils/TableGen/InstrSelectorEmitter.cpp
index 99f22f07b9..61b9f81305 100644
--- a/utils/TableGen/InstrSelectorEmitter.cpp
+++ b/utils/TableGen/InstrSelectorEmitter.cpp
@@ -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:
+ 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;
+ }
default:
assert(0 && "Reduction of this type of pattern not implemented!");
}
diff --git a/utils/TableGen/InstrSelectorEmitter.h b/utils/TableGen/InstrSelectorEmitter.h
index ec0231ad12..20e800bf73 100644
--- a/utils/TableGen/InstrSelectorEmitter.h
+++ b/utils/TableGen/InstrSelectorEmitter.h
@@ -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