mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2025-03-26 07:34:14 +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) {
|
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!");
|
||||||
}
|
}
|
||||||
|
@ -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
|
||||||
|
@ -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!");
|
||||||
}
|
}
|
||||||
|
@ -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
|
||||||
|
Loading…
x
Reference in New Issue
Block a user