2005-09-07 23:44:43 +00:00
|
|
|
//===- DAGISelEmitter.cpp - Generate an instruction selector --------------===//
|
|
|
|
//
|
|
|
|
// The LLVM Compiler Infrastructure
|
|
|
|
//
|
|
|
|
// This file was developed by Chris Lattner and is distributed under
|
|
|
|
// the University of Illinois Open Source License. See LICENSE.TXT for details.
|
|
|
|
//
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
//
|
|
|
|
// This tablegen backend emits a DAG instruction selector.
|
|
|
|
//
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
|
|
|
#include "DAGISelEmitter.h"
|
|
|
|
#include "Record.h"
|
|
|
|
#include "llvm/ADT/StringExtras.h"
|
|
|
|
#include "llvm/Support/Debug.h"
|
2005-09-25 19:04:43 +00:00
|
|
|
#include <algorithm>
|
2005-09-07 23:44:43 +00:00
|
|
|
#include <set>
|
|
|
|
using namespace llvm;
|
|
|
|
|
2005-09-08 21:27:15 +00:00
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
// SDTypeConstraint implementation
|
|
|
|
//
|
|
|
|
|
|
|
|
SDTypeConstraint::SDTypeConstraint(Record *R) {
|
|
|
|
OperandNo = R->getValueAsInt("OperandNum");
|
|
|
|
|
|
|
|
if (R->isSubClassOf("SDTCisVT")) {
|
|
|
|
ConstraintType = SDTCisVT;
|
|
|
|
x.SDTCisVT_Info.VT = getValueType(R->getValueAsDef("VT"));
|
|
|
|
} else if (R->isSubClassOf("SDTCisInt")) {
|
|
|
|
ConstraintType = SDTCisInt;
|
|
|
|
} else if (R->isSubClassOf("SDTCisFP")) {
|
|
|
|
ConstraintType = SDTCisFP;
|
|
|
|
} else if (R->isSubClassOf("SDTCisSameAs")) {
|
|
|
|
ConstraintType = SDTCisSameAs;
|
|
|
|
x.SDTCisSameAs_Info.OtherOperandNum = R->getValueAsInt("OtherOperandNum");
|
|
|
|
} else if (R->isSubClassOf("SDTCisVTSmallerThanOp")) {
|
|
|
|
ConstraintType = SDTCisVTSmallerThanOp;
|
|
|
|
x.SDTCisVTSmallerThanOp_Info.OtherOperandNum =
|
|
|
|
R->getValueAsInt("OtherOperandNum");
|
|
|
|
} else {
|
|
|
|
std::cerr << "Unrecognized SDTypeConstraint '" << R->getName() << "'!\n";
|
|
|
|
exit(1);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
Implement a complete type inference system for dag patterns, based on the
constraints defined in the DAG node definitions in the .td files. This
allows us to infer (and check!) the types for all nodes in the current
ppc .td file. For example, instead of:
Inst pattern EQV: (set GPRC:i32:$rT, (xor (xor GPRC:i32:$rA, GPRC:i32:$rB), (imm)<<Predicate_immAllOnes>>))
we now fully infer:
Inst pattern EQV: (set:void GPRC:i32:$rT, (xor:i32 (xor:i32 GPRC:i32:$rA, GPRC:i32:$rB), (imm:i32)<<Predicate_immAllOnes>>))
from: (set GPRC:$rT, (not (xor GPRC:$rA, GPRC:$rB)))
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@23284 91177308-0d34-0410-b5e6-96231b3b80d8
2005-09-08 23:22:48 +00:00
|
|
|
/// getOperandNum - Return the node corresponding to operand #OpNo in tree
|
|
|
|
/// N, which has NumResults results.
|
|
|
|
TreePatternNode *SDTypeConstraint::getOperandNum(unsigned OpNo,
|
|
|
|
TreePatternNode *N,
|
|
|
|
unsigned NumResults) const {
|
|
|
|
assert(NumResults == 1 && "We only work with single result nodes so far!");
|
|
|
|
|
|
|
|
if (OpNo < NumResults)
|
|
|
|
return N; // FIXME: need value #
|
|
|
|
else
|
|
|
|
return N->getChild(OpNo-NumResults);
|
|
|
|
}
|
|
|
|
|
|
|
|
/// ApplyTypeConstraint - Given a node in a pattern, apply this type
|
|
|
|
/// constraint to the nodes operands. This returns true if it makes a
|
|
|
|
/// change, false otherwise. If a type contradiction is found, throw an
|
|
|
|
/// exception.
|
|
|
|
bool SDTypeConstraint::ApplyTypeConstraint(TreePatternNode *N,
|
|
|
|
const SDNodeInfo &NodeInfo,
|
|
|
|
TreePattern &TP) const {
|
|
|
|
unsigned NumResults = NodeInfo.getNumResults();
|
|
|
|
assert(NumResults == 1 && "We only work with single result nodes so far!");
|
|
|
|
|
|
|
|
// Check that the number of operands is sane.
|
|
|
|
if (NodeInfo.getNumOperands() >= 0) {
|
|
|
|
if (N->getNumChildren() != (unsigned)NodeInfo.getNumOperands())
|
|
|
|
TP.error(N->getOperator()->getName() + " node requires exactly " +
|
|
|
|
itostr(NodeInfo.getNumOperands()) + " operands!");
|
|
|
|
}
|
|
|
|
|
|
|
|
TreePatternNode *NodeToApply = getOperandNum(OperandNo, N, NumResults);
|
|
|
|
|
|
|
|
switch (ConstraintType) {
|
|
|
|
default: assert(0 && "Unknown constraint type!");
|
|
|
|
case SDTCisVT:
|
|
|
|
// Operand must be a particular type.
|
|
|
|
return NodeToApply->UpdateNodeType(x.SDTCisVT_Info.VT, TP);
|
|
|
|
case SDTCisInt:
|
|
|
|
if (NodeToApply->hasTypeSet() && !MVT::isInteger(NodeToApply->getType()))
|
|
|
|
NodeToApply->UpdateNodeType(MVT::i1, TP); // throw an error.
|
|
|
|
|
|
|
|
// FIXME: can tell from the target if there is only one Int type supported.
|
|
|
|
return false;
|
|
|
|
case SDTCisFP:
|
|
|
|
if (NodeToApply->hasTypeSet() &&
|
|
|
|
!MVT::isFloatingPoint(NodeToApply->getType()))
|
|
|
|
NodeToApply->UpdateNodeType(MVT::f32, TP); // throw an error.
|
|
|
|
// FIXME: can tell from the target if there is only one FP type supported.
|
|
|
|
return false;
|
|
|
|
case SDTCisSameAs: {
|
|
|
|
TreePatternNode *OtherNode =
|
|
|
|
getOperandNum(x.SDTCisSameAs_Info.OtherOperandNum, N, NumResults);
|
|
|
|
return NodeToApply->UpdateNodeType(OtherNode->getType(), TP) |
|
|
|
|
OtherNode->UpdateNodeType(NodeToApply->getType(), TP);
|
|
|
|
}
|
|
|
|
case SDTCisVTSmallerThanOp: {
|
|
|
|
// The NodeToApply must be a leaf node that is a VT. OtherOperandNum must
|
|
|
|
// have an integer type that is smaller than the VT.
|
|
|
|
if (!NodeToApply->isLeaf() ||
|
|
|
|
!dynamic_cast<DefInit*>(NodeToApply->getLeafValue()) ||
|
|
|
|
!static_cast<DefInit*>(NodeToApply->getLeafValue())->getDef()
|
|
|
|
->isSubClassOf("ValueType"))
|
|
|
|
TP.error(N->getOperator()->getName() + " expects a VT operand!");
|
|
|
|
MVT::ValueType VT =
|
|
|
|
getValueType(static_cast<DefInit*>(NodeToApply->getLeafValue())->getDef());
|
|
|
|
if (!MVT::isInteger(VT))
|
|
|
|
TP.error(N->getOperator()->getName() + " VT operand must be integer!");
|
|
|
|
|
|
|
|
TreePatternNode *OtherNode =
|
|
|
|
getOperandNum(x.SDTCisVTSmallerThanOp_Info.OtherOperandNum, N,NumResults);
|
|
|
|
if (OtherNode->hasTypeSet() &&
|
|
|
|
(!MVT::isInteger(OtherNode->getType()) ||
|
|
|
|
OtherNode->getType() <= VT))
|
|
|
|
OtherNode->UpdateNodeType(MVT::Other, TP); // Throw an error.
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2005-09-08 21:03:01 +00:00
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
// SDNodeInfo implementation
|
|
|
|
//
|
|
|
|
SDNodeInfo::SDNodeInfo(Record *R) : Def(R) {
|
|
|
|
EnumName = R->getValueAsString("Opcode");
|
|
|
|
SDClassName = R->getValueAsString("SDClass");
|
2005-09-08 21:27:15 +00:00
|
|
|
Record *TypeProfile = R->getValueAsDef("TypeProfile");
|
|
|
|
NumResults = TypeProfile->getValueAsInt("NumResults");
|
|
|
|
NumOperands = TypeProfile->getValueAsInt("NumOperands");
|
|
|
|
|
|
|
|
// Parse the type constraints.
|
|
|
|
ListInit *Constraints = TypeProfile->getValueAsListInit("Constraints");
|
|
|
|
for (unsigned i = 0, e = Constraints->getSize(); i != e; ++i) {
|
|
|
|
assert(dynamic_cast<DefInit*>(Constraints->getElement(i)) &&
|
|
|
|
"Constraints list should contain constraint definitions!");
|
|
|
|
Record *Constraint =
|
|
|
|
static_cast<DefInit*>(Constraints->getElement(i))->getDef();
|
|
|
|
TypeConstraints.push_back(Constraint);
|
|
|
|
}
|
2005-09-08 21:03:01 +00:00
|
|
|
}
|
2005-09-07 23:44:43 +00:00
|
|
|
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
// TreePatternNode implementation
|
|
|
|
//
|
|
|
|
|
|
|
|
TreePatternNode::~TreePatternNode() {
|
|
|
|
#if 0 // FIXME: implement refcounted tree nodes!
|
|
|
|
for (unsigned i = 0, e = getNumChildren(); i != e; ++i)
|
|
|
|
delete getChild(i);
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
Implement a complete type inference system for dag patterns, based on the
constraints defined in the DAG node definitions in the .td files. This
allows us to infer (and check!) the types for all nodes in the current
ppc .td file. For example, instead of:
Inst pattern EQV: (set GPRC:i32:$rT, (xor (xor GPRC:i32:$rA, GPRC:i32:$rB), (imm)<<Predicate_immAllOnes>>))
we now fully infer:
Inst pattern EQV: (set:void GPRC:i32:$rT, (xor:i32 (xor:i32 GPRC:i32:$rA, GPRC:i32:$rB), (imm:i32)<<Predicate_immAllOnes>>))
from: (set GPRC:$rT, (not (xor GPRC:$rA, GPRC:$rB)))
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@23284 91177308-0d34-0410-b5e6-96231b3b80d8
2005-09-08 23:22:48 +00:00
|
|
|
/// UpdateNodeType - Set the node type of N to VT if VT contains
|
|
|
|
/// information. If N already contains a conflicting type, then throw an
|
|
|
|
/// exception. This returns true if any information was updated.
|
|
|
|
///
|
|
|
|
bool TreePatternNode::UpdateNodeType(MVT::ValueType VT, TreePattern &TP) {
|
|
|
|
if (VT == MVT::LAST_VALUETYPE || getType() == VT) return false;
|
|
|
|
if (getType() == MVT::LAST_VALUETYPE) {
|
|
|
|
setType(VT);
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
TP.error("Type inference contradiction found in node " +
|
|
|
|
getOperator()->getName() + "!");
|
|
|
|
return true; // unreachable
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2005-09-07 23:44:43 +00:00
|
|
|
void TreePatternNode::print(std::ostream &OS) const {
|
|
|
|
if (isLeaf()) {
|
|
|
|
OS << *getLeafValue();
|
|
|
|
} else {
|
|
|
|
OS << "(" << getOperator()->getName();
|
|
|
|
}
|
|
|
|
|
|
|
|
if (getType() == MVT::Other)
|
|
|
|
OS << ":Other";
|
|
|
|
else if (getType() == MVT::LAST_VALUETYPE)
|
|
|
|
;//OS << ":?";
|
|
|
|
else
|
|
|
|
OS << ":" << getType();
|
|
|
|
|
|
|
|
if (!isLeaf()) {
|
|
|
|
if (getNumChildren() != 0) {
|
|
|
|
OS << " ";
|
|
|
|
getChild(0)->print(OS);
|
|
|
|
for (unsigned i = 1, e = getNumChildren(); i != e; ++i) {
|
|
|
|
OS << ", ";
|
|
|
|
getChild(i)->print(OS);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
OS << ")";
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!PredicateFn.empty())
|
2005-09-13 21:51:00 +00:00
|
|
|
OS << "<<P:" << PredicateFn << ">>";
|
2005-09-14 22:55:26 +00:00
|
|
|
if (TransformFn)
|
|
|
|
OS << "<<X:" << TransformFn->getName() << ">>";
|
2005-09-07 23:44:43 +00:00
|
|
|
if (!getName().empty())
|
|
|
|
OS << ":$" << getName();
|
|
|
|
|
|
|
|
}
|
|
|
|
void TreePatternNode::dump() const {
|
|
|
|
print(std::cerr);
|
|
|
|
}
|
|
|
|
|
|
|
|
/// clone - Make a copy of this tree and all of its children.
|
|
|
|
///
|
|
|
|
TreePatternNode *TreePatternNode::clone() const {
|
|
|
|
TreePatternNode *New;
|
|
|
|
if (isLeaf()) {
|
|
|
|
New = new TreePatternNode(getLeafValue());
|
|
|
|
} else {
|
|
|
|
std::vector<TreePatternNode*> CChildren;
|
|
|
|
CChildren.reserve(Children.size());
|
|
|
|
for (unsigned i = 0, e = getNumChildren(); i != e; ++i)
|
|
|
|
CChildren.push_back(getChild(i)->clone());
|
|
|
|
New = new TreePatternNode(getOperator(), CChildren);
|
|
|
|
}
|
|
|
|
New->setName(getName());
|
|
|
|
New->setType(getType());
|
|
|
|
New->setPredicateFn(getPredicateFn());
|
2005-09-13 21:51:00 +00:00
|
|
|
New->setTransformFn(getTransformFn());
|
2005-09-07 23:44:43 +00:00
|
|
|
return New;
|
|
|
|
}
|
|
|
|
|
Implement a complete type inference system for dag patterns, based on the
constraints defined in the DAG node definitions in the .td files. This
allows us to infer (and check!) the types for all nodes in the current
ppc .td file. For example, instead of:
Inst pattern EQV: (set GPRC:i32:$rT, (xor (xor GPRC:i32:$rA, GPRC:i32:$rB), (imm)<<Predicate_immAllOnes>>))
we now fully infer:
Inst pattern EQV: (set:void GPRC:i32:$rT, (xor:i32 (xor:i32 GPRC:i32:$rA, GPRC:i32:$rB), (imm:i32)<<Predicate_immAllOnes>>))
from: (set GPRC:$rT, (not (xor GPRC:$rA, GPRC:$rB)))
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@23284 91177308-0d34-0410-b5e6-96231b3b80d8
2005-09-08 23:22:48 +00:00
|
|
|
/// SubstituteFormalArguments - Replace the formal arguments in this tree
|
|
|
|
/// with actual values specified by ArgMap.
|
2005-09-07 23:44:43 +00:00
|
|
|
void TreePatternNode::
|
|
|
|
SubstituteFormalArguments(std::map<std::string, TreePatternNode*> &ArgMap) {
|
|
|
|
if (isLeaf()) return;
|
|
|
|
|
|
|
|
for (unsigned i = 0, e = getNumChildren(); i != e; ++i) {
|
|
|
|
TreePatternNode *Child = getChild(i);
|
|
|
|
if (Child->isLeaf()) {
|
|
|
|
Init *Val = Child->getLeafValue();
|
|
|
|
if (dynamic_cast<DefInit*>(Val) &&
|
|
|
|
static_cast<DefInit*>(Val)->getDef()->getName() == "node") {
|
|
|
|
// We found a use of a formal argument, replace it with its value.
|
|
|
|
Child = ArgMap[Child->getName()];
|
|
|
|
assert(Child && "Couldn't find formal argument!");
|
|
|
|
setChild(i, Child);
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
getChild(i)->SubstituteFormalArguments(ArgMap);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/// InlinePatternFragments - If this pattern refers to any pattern
|
|
|
|
/// fragments, inline them into place, giving us a pattern without any
|
|
|
|
/// PatFrag references.
|
|
|
|
TreePatternNode *TreePatternNode::InlinePatternFragments(TreePattern &TP) {
|
|
|
|
if (isLeaf()) return this; // nothing to do.
|
|
|
|
Record *Op = getOperator();
|
|
|
|
|
|
|
|
if (!Op->isSubClassOf("PatFrag")) {
|
|
|
|
// Just recursively inline children nodes.
|
|
|
|
for (unsigned i = 0, e = getNumChildren(); i != e; ++i)
|
|
|
|
setChild(i, getChild(i)->InlinePatternFragments(TP));
|
|
|
|
return this;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Otherwise, we found a reference to a fragment. First, look up its
|
|
|
|
// TreePattern record.
|
|
|
|
TreePattern *Frag = TP.getDAGISelEmitter().getPatternFragment(Op);
|
|
|
|
|
|
|
|
// Verify that we are passing the right number of operands.
|
|
|
|
if (Frag->getNumArgs() != Children.size())
|
|
|
|
TP.error("'" + Op->getName() + "' fragment requires " +
|
|
|
|
utostr(Frag->getNumArgs()) + " operands!");
|
|
|
|
|
2005-09-09 01:15:01 +00:00
|
|
|
TreePatternNode *FragTree = Frag->getOnlyTree()->clone();
|
2005-09-07 23:44:43 +00:00
|
|
|
|
|
|
|
// Resolve formal arguments to their actual value.
|
|
|
|
if (Frag->getNumArgs()) {
|
|
|
|
// Compute the map of formal to actual arguments.
|
|
|
|
std::map<std::string, TreePatternNode*> ArgMap;
|
|
|
|
for (unsigned i = 0, e = Frag->getNumArgs(); i != e; ++i)
|
|
|
|
ArgMap[Frag->getArgName(i)] = getChild(i)->InlinePatternFragments(TP);
|
|
|
|
|
|
|
|
FragTree->SubstituteFormalArguments(ArgMap);
|
|
|
|
}
|
|
|
|
|
2005-09-08 17:45:12 +00:00
|
|
|
FragTree->setName(getName());
|
|
|
|
|
2005-09-07 23:44:43 +00:00
|
|
|
// Get a new copy of this fragment to stitch into here.
|
|
|
|
//delete this; // FIXME: implement refcounting!
|
|
|
|
return FragTree;
|
|
|
|
}
|
|
|
|
|
Implement a complete type inference system for dag patterns, based on the
constraints defined in the DAG node definitions in the .td files. This
allows us to infer (and check!) the types for all nodes in the current
ppc .td file. For example, instead of:
Inst pattern EQV: (set GPRC:i32:$rT, (xor (xor GPRC:i32:$rA, GPRC:i32:$rB), (imm)<<Predicate_immAllOnes>>))
we now fully infer:
Inst pattern EQV: (set:void GPRC:i32:$rT, (xor:i32 (xor:i32 GPRC:i32:$rA, GPRC:i32:$rB), (imm:i32)<<Predicate_immAllOnes>>))
from: (set GPRC:$rT, (not (xor GPRC:$rA, GPRC:$rB)))
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@23284 91177308-0d34-0410-b5e6-96231b3b80d8
2005-09-08 23:22:48 +00:00
|
|
|
/// ApplyTypeConstraints - Apply all of the type constraints relevent to
|
|
|
|
/// this node and its children in the tree. This returns true if it makes a
|
|
|
|
/// change, false otherwise. If a type contradiction is found, throw an
|
|
|
|
/// exception.
|
|
|
|
bool TreePatternNode::ApplyTypeConstraints(TreePattern &TP) {
|
|
|
|
if (isLeaf()) return false;
|
|
|
|
|
|
|
|
// special handling for set, which isn't really an SDNode.
|
|
|
|
if (getOperator()->getName() == "set") {
|
|
|
|
assert (getNumChildren() == 2 && "Only handle 2 operand set's for now!");
|
|
|
|
bool MadeChange = getChild(0)->ApplyTypeConstraints(TP);
|
|
|
|
MadeChange |= getChild(1)->ApplyTypeConstraints(TP);
|
|
|
|
|
|
|
|
// Types of operands must match.
|
|
|
|
MadeChange |= getChild(0)->UpdateNodeType(getChild(1)->getType(), TP);
|
|
|
|
MadeChange |= getChild(1)->UpdateNodeType(getChild(0)->getType(), TP);
|
|
|
|
MadeChange |= UpdateNodeType(MVT::isVoid, TP);
|
|
|
|
return MadeChange;
|
2005-09-15 21:42:00 +00:00
|
|
|
} else if (getOperator()->isSubClassOf("SDNode")) {
|
|
|
|
const SDNodeInfo &NI = TP.getDAGISelEmitter().getSDNodeInfo(getOperator());
|
|
|
|
|
|
|
|
bool MadeChange = NI.ApplyTypeConstraints(this, TP);
|
|
|
|
for (unsigned i = 0, e = getNumChildren(); i != e; ++i)
|
|
|
|
MadeChange |= getChild(i)->ApplyTypeConstraints(TP);
|
|
|
|
return MadeChange;
|
2005-09-15 22:23:50 +00:00
|
|
|
} else if (getOperator()->isSubClassOf("Instruction")) {
|
2005-09-15 21:57:35 +00:00
|
|
|
const DAGInstruction &Inst =
|
|
|
|
TP.getDAGISelEmitter().getInstruction(getOperator());
|
|
|
|
|
2005-09-15 22:23:50 +00:00
|
|
|
assert(Inst.getNumResults() == 1 && "Only supports one result instrs!");
|
|
|
|
// Apply the result type to the node
|
|
|
|
bool MadeChange = UpdateNodeType(Inst.getResultType(0), TP);
|
|
|
|
|
|
|
|
if (getNumChildren() != Inst.getNumOperands())
|
|
|
|
TP.error("Instruction '" + getOperator()->getName() + " expects " +
|
|
|
|
utostr(Inst.getNumOperands()) + " operands, not " +
|
|
|
|
utostr(getNumChildren()) + " operands!");
|
|
|
|
for (unsigned i = 0, e = getNumChildren(); i != e; ++i) {
|
|
|
|
MadeChange |= getChild(i)->UpdateNodeType(Inst.getOperandType(i), TP);
|
|
|
|
MadeChange |= getChild(i)->ApplyTypeConstraints(TP);
|
|
|
|
}
|
|
|
|
return MadeChange;
|
|
|
|
} else {
|
|
|
|
assert(getOperator()->isSubClassOf("SDNodeXForm") && "Unknown node type!");
|
|
|
|
|
|
|
|
// Node transforms always take one operand, and take and return the same
|
|
|
|
// type.
|
|
|
|
if (getNumChildren() != 1)
|
|
|
|
TP.error("Node transform '" + getOperator()->getName() +
|
|
|
|
"' requires one operand!");
|
|
|
|
bool MadeChange = UpdateNodeType(getChild(0)->getType(), TP);
|
|
|
|
MadeChange |= getChild(0)->UpdateNodeType(getType(), TP);
|
|
|
|
return MadeChange;
|
Implement a complete type inference system for dag patterns, based on the
constraints defined in the DAG node definitions in the .td files. This
allows us to infer (and check!) the types for all nodes in the current
ppc .td file. For example, instead of:
Inst pattern EQV: (set GPRC:i32:$rT, (xor (xor GPRC:i32:$rA, GPRC:i32:$rB), (imm)<<Predicate_immAllOnes>>))
we now fully infer:
Inst pattern EQV: (set:void GPRC:i32:$rT, (xor:i32 (xor:i32 GPRC:i32:$rA, GPRC:i32:$rB), (imm:i32)<<Predicate_immAllOnes>>))
from: (set GPRC:$rT, (not (xor GPRC:$rA, GPRC:$rB)))
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@23284 91177308-0d34-0410-b5e6-96231b3b80d8
2005-09-08 23:22:48 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2005-09-07 23:44:43 +00:00
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
// TreePattern implementation
|
|
|
|
//
|
|
|
|
|
2005-09-15 22:23:50 +00:00
|
|
|
TreePattern::TreePattern(Record *TheRec, ListInit *RawPat,
|
2005-09-13 21:20:49 +00:00
|
|
|
DAGISelEmitter &ise) : TheRecord(TheRec), ISE(ise) {
|
2005-09-15 22:23:50 +00:00
|
|
|
for (unsigned i = 0, e = RawPat->getSize(); i != e; ++i)
|
|
|
|
Trees.push_back(ParseTreePattern((DagInit*)RawPat->getElement(i)));
|
|
|
|
}
|
2005-09-07 23:44:43 +00:00
|
|
|
|
2005-09-15 22:23:50 +00:00
|
|
|
TreePattern::TreePattern(Record *TheRec, DagInit *Pat,
|
|
|
|
DAGISelEmitter &ise) : TheRecord(TheRec), ISE(ise) {
|
|
|
|
Trees.push_back(ParseTreePattern(Pat));
|
2005-09-07 23:44:43 +00:00
|
|
|
}
|
|
|
|
|
2005-09-15 22:23:50 +00:00
|
|
|
TreePattern::TreePattern(Record *TheRec, TreePatternNode *Pat,
|
|
|
|
DAGISelEmitter &ise) : TheRecord(TheRec), ISE(ise) {
|
|
|
|
Trees.push_back(Pat);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
2005-09-07 23:44:43 +00:00
|
|
|
void TreePattern::error(const std::string &Msg) const {
|
2005-09-14 20:53:42 +00:00
|
|
|
dump();
|
2005-09-13 21:20:49 +00:00
|
|
|
throw "In " + TheRecord->getName() + ": " + Msg;
|
2005-09-07 23:44:43 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/// 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.
|
|
|
|
///
|
|
|
|
MVT::ValueType TreePattern::getIntrinsicType(Record *R) const {
|
|
|
|
// Check to see if this is a register or a register class...
|
|
|
|
if (R->isSubClassOf("RegisterClass"))
|
|
|
|
return getValueType(R->getValueAsDef("RegType"));
|
|
|
|
else if (R->isSubClassOf("PatFrag")) {
|
2005-09-09 01:15:01 +00:00
|
|
|
// Pattern fragment types will be resolved when they are inlined.
|
2005-09-07 23:44:43 +00:00
|
|
|
return MVT::LAST_VALUETYPE;
|
|
|
|
} else if (R->isSubClassOf("Register")) {
|
|
|
|
assert(0 && "Explicit registers not handled here yet!\n");
|
|
|
|
return MVT::LAST_VALUETYPE;
|
|
|
|
} else if (R->isSubClassOf("ValueType")) {
|
|
|
|
// Using a VTSDNode.
|
|
|
|
return MVT::Other;
|
|
|
|
} else if (R->getName() == "node") {
|
|
|
|
// Placeholder.
|
|
|
|
return MVT::LAST_VALUETYPE;
|
|
|
|
}
|
|
|
|
|
2005-09-24 00:40:24 +00:00
|
|
|
error("Unknown node flavor used in pattern: " + R->getName());
|
2005-09-07 23:44:43 +00:00
|
|
|
return MVT::Other;
|
|
|
|
}
|
|
|
|
|
|
|
|
TreePatternNode *TreePattern::ParseTreePattern(DagInit *Dag) {
|
|
|
|
Record *Operator = Dag->getNodeType();
|
|
|
|
|
|
|
|
if (Operator->isSubClassOf("ValueType")) {
|
|
|
|
// If the operator is a ValueType, then this must be "type cast" of a leaf
|
|
|
|
// node.
|
|
|
|
if (Dag->getNumArgs() != 1)
|
|
|
|
error("Type cast only valid for a leaf node!");
|
|
|
|
|
|
|
|
Init *Arg = Dag->getArg(0);
|
|
|
|
TreePatternNode *New;
|
|
|
|
if (DefInit *DI = dynamic_cast<DefInit*>(Arg)) {
|
2005-09-24 00:40:24 +00:00
|
|
|
Record *R = DI->getDef();
|
|
|
|
if (R->isSubClassOf("SDNode") || R->isSubClassOf("PatFrag")) {
|
|
|
|
Dag->setArg(0, new DagInit(R,
|
|
|
|
std::vector<std::pair<Init*, std::string> >()));
|
|
|
|
TreePatternNode *TPN = ParseTreePattern(Dag);
|
|
|
|
TPN->setName(Dag->getArgName(0));
|
|
|
|
return TPN;
|
|
|
|
}
|
|
|
|
|
2005-09-07 23:44:43 +00:00
|
|
|
New = new TreePatternNode(DI);
|
|
|
|
// If it's a regclass or something else known, set the type.
|
|
|
|
New->setType(getIntrinsicType(DI->getDef()));
|
|
|
|
} else if (DagInit *DI = dynamic_cast<DagInit*>(Arg)) {
|
|
|
|
New = ParseTreePattern(DI);
|
|
|
|
} else {
|
|
|
|
Arg->dump();
|
|
|
|
error("Unknown leaf value for tree pattern!");
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
Implement a complete type inference system for dag patterns, based on the
constraints defined in the DAG node definitions in the .td files. This
allows us to infer (and check!) the types for all nodes in the current
ppc .td file. For example, instead of:
Inst pattern EQV: (set GPRC:i32:$rT, (xor (xor GPRC:i32:$rA, GPRC:i32:$rB), (imm)<<Predicate_immAllOnes>>))
we now fully infer:
Inst pattern EQV: (set:void GPRC:i32:$rT, (xor:i32 (xor:i32 GPRC:i32:$rA, GPRC:i32:$rB), (imm:i32)<<Predicate_immAllOnes>>))
from: (set GPRC:$rT, (not (xor GPRC:$rA, GPRC:$rB)))
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@23284 91177308-0d34-0410-b5e6-96231b3b80d8
2005-09-08 23:22:48 +00:00
|
|
|
// Apply the type cast.
|
|
|
|
New->UpdateNodeType(getValueType(Operator), *this);
|
2005-09-07 23:44:43 +00:00
|
|
|
return New;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Verify that this is something that makes sense for an operator.
|
|
|
|
if (!Operator->isSubClassOf("PatFrag") && !Operator->isSubClassOf("SDNode") &&
|
2005-09-15 21:42:00 +00:00
|
|
|
!Operator->isSubClassOf("Instruction") &&
|
|
|
|
!Operator->isSubClassOf("SDNodeXForm") &&
|
2005-09-07 23:44:43 +00:00
|
|
|
Operator->getName() != "set")
|
|
|
|
error("Unrecognized node '" + Operator->getName() + "'!");
|
|
|
|
|
|
|
|
std::vector<TreePatternNode*> 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.back()->setName(Dag->getArgName(i));
|
|
|
|
} else if (DefInit *DefI = dynamic_cast<DefInit*>(Arg)) {
|
|
|
|
Record *R = DefI->getDef();
|
|
|
|
// Direct reference to a leaf DagNode or PatFrag? Turn it into a
|
|
|
|
// TreePatternNode if its own.
|
|
|
|
if (R->isSubClassOf("SDNode") || R->isSubClassOf("PatFrag")) {
|
|
|
|
Dag->setArg(i, new DagInit(R,
|
|
|
|
std::vector<std::pair<Init*, std::string> >()));
|
|
|
|
--i; // Revisit this node...
|
|
|
|
} else {
|
|
|
|
TreePatternNode *Node = new TreePatternNode(DefI);
|
|
|
|
Node->setName(Dag->getArgName(i));
|
|
|
|
Children.push_back(Node);
|
|
|
|
|
|
|
|
// If it's a regclass or something else known, set the type.
|
|
|
|
Node->setType(getIntrinsicType(R));
|
|
|
|
|
|
|
|
// Input argument?
|
|
|
|
if (R->getName() == "node") {
|
|
|
|
if (Dag->getArgName(i).empty())
|
|
|
|
error("'node' argument requires a name to match with operand list");
|
|
|
|
Args.push_back(Dag->getArgName(i));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
Arg->dump();
|
|
|
|
error("Unknown leaf value for tree pattern!");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return new TreePatternNode(Operator, Children);
|
|
|
|
}
|
|
|
|
|
Implement a complete type inference system for dag patterns, based on the
constraints defined in the DAG node definitions in the .td files. This
allows us to infer (and check!) the types for all nodes in the current
ppc .td file. For example, instead of:
Inst pattern EQV: (set GPRC:i32:$rT, (xor (xor GPRC:i32:$rA, GPRC:i32:$rB), (imm)<<Predicate_immAllOnes>>))
we now fully infer:
Inst pattern EQV: (set:void GPRC:i32:$rT, (xor:i32 (xor:i32 GPRC:i32:$rA, GPRC:i32:$rB), (imm:i32)<<Predicate_immAllOnes>>))
from: (set GPRC:$rT, (not (xor GPRC:$rA, GPRC:$rB)))
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@23284 91177308-0d34-0410-b5e6-96231b3b80d8
2005-09-08 23:22:48 +00:00
|
|
|
/// InferAllTypes - Infer/propagate as many types throughout the expression
|
|
|
|
/// patterns as possible. Return true if all types are infered, false
|
|
|
|
/// otherwise. Throw an exception if a type contradiction is found.
|
|
|
|
bool TreePattern::InferAllTypes() {
|
|
|
|
bool MadeChange = true;
|
|
|
|
while (MadeChange) {
|
|
|
|
MadeChange = false;
|
|
|
|
for (unsigned i = 0, e = Trees.size(); i != e; ++i)
|
|
|
|
MadeChange |= Trees[i]->ApplyTypeConstraints(*this);
|
|
|
|
}
|
|
|
|
|
|
|
|
bool HasUnresolvedTypes = false;
|
|
|
|
for (unsigned i = 0, e = Trees.size(); i != e; ++i)
|
|
|
|
HasUnresolvedTypes |= Trees[i]->ContainsUnresolvedType();
|
|
|
|
return !HasUnresolvedTypes;
|
|
|
|
}
|
|
|
|
|
2005-09-07 23:44:43 +00:00
|
|
|
void TreePattern::print(std::ostream &OS) const {
|
|
|
|
OS << getRecord()->getName();
|
|
|
|
if (!Args.empty()) {
|
|
|
|
OS << "(" << Args[0];
|
|
|
|
for (unsigned i = 1, e = Args.size(); i != e; ++i)
|
|
|
|
OS << ", " << Args[i];
|
|
|
|
OS << ")";
|
|
|
|
}
|
|
|
|
OS << ": ";
|
|
|
|
|
|
|
|
if (Trees.size() > 1)
|
|
|
|
OS << "[\n";
|
|
|
|
for (unsigned i = 0, e = Trees.size(); i != e; ++i) {
|
|
|
|
OS << "\t";
|
|
|
|
Trees[i]->print(OS);
|
|
|
|
OS << "\n";
|
|
|
|
}
|
|
|
|
|
|
|
|
if (Trees.size() > 1)
|
|
|
|
OS << "]\n";
|
|
|
|
}
|
|
|
|
|
|
|
|
void TreePattern::dump() const { print(std::cerr); }
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
// DAGISelEmitter implementation
|
|
|
|
//
|
|
|
|
|
2005-09-08 21:03:01 +00:00
|
|
|
// Parse all of the SDNode definitions for the target, populating SDNodes.
|
|
|
|
void DAGISelEmitter::ParseNodeInfo() {
|
|
|
|
std::vector<Record*> Nodes = Records.getAllDerivedDefinitions("SDNode");
|
|
|
|
while (!Nodes.empty()) {
|
|
|
|
SDNodes.insert(std::make_pair(Nodes.back(), Nodes.back()));
|
|
|
|
Nodes.pop_back();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2005-09-13 21:51:00 +00:00
|
|
|
/// ParseNodeTransforms - Parse all SDNodeXForm instances into the SDNodeXForms
|
|
|
|
/// map, and emit them to the file as functions.
|
|
|
|
void DAGISelEmitter::ParseNodeTransforms(std::ostream &OS) {
|
|
|
|
OS << "\n// Node transformations.\n";
|
|
|
|
std::vector<Record*> Xforms = Records.getAllDerivedDefinitions("SDNodeXForm");
|
|
|
|
while (!Xforms.empty()) {
|
|
|
|
Record *XFormNode = Xforms.back();
|
|
|
|
Record *SDNode = XFormNode->getValueAsDef("Opcode");
|
|
|
|
std::string Code = XFormNode->getValueAsCode("XFormFunction");
|
|
|
|
SDNodeXForms.insert(std::make_pair(XFormNode,
|
|
|
|
std::make_pair(SDNode, Code)));
|
|
|
|
|
2005-09-13 22:03:37 +00:00
|
|
|
if (!Code.empty()) {
|
2005-09-13 21:51:00 +00:00
|
|
|
std::string ClassName = getSDNodeInfo(SDNode).getSDClassName();
|
|
|
|
const char *C2 = ClassName == "SDNode" ? "N" : "inN";
|
|
|
|
|
2005-09-13 22:03:37 +00:00
|
|
|
OS << "inline SDOperand Transform_" << XFormNode->getName()
|
2005-09-13 21:51:00 +00:00
|
|
|
<< "(SDNode *" << C2 << ") {\n";
|
|
|
|
if (ClassName != "SDNode")
|
|
|
|
OS << " " << ClassName << " *N = cast<" << ClassName << ">(inN);\n";
|
|
|
|
OS << Code << "\n}\n";
|
|
|
|
}
|
|
|
|
|
|
|
|
Xforms.pop_back();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
2005-09-15 02:38:02 +00:00
|
|
|
/// ParsePatternFragments - Parse all of the PatFrag definitions in the .td
|
|
|
|
/// file, building up the PatternFragments map. After we've collected them all,
|
|
|
|
/// inline fragments together as necessary, so that there are no references left
|
|
|
|
/// inside a pattern fragment to a pattern fragment.
|
2005-09-07 23:44:43 +00:00
|
|
|
///
|
|
|
|
/// This also emits all of the predicate functions to the output file.
|
|
|
|
///
|
2005-09-15 02:38:02 +00:00
|
|
|
void DAGISelEmitter::ParsePatternFragments(std::ostream &OS) {
|
2005-09-07 23:44:43 +00:00
|
|
|
std::vector<Record*> Fragments = Records.getAllDerivedDefinitions("PatFrag");
|
|
|
|
|
|
|
|
// First step, parse all of the fragments and emit predicate functions.
|
|
|
|
OS << "\n// Predicate functions.\n";
|
|
|
|
for (unsigned i = 0, e = Fragments.size(); i != e; ++i) {
|
2005-09-15 22:23:50 +00:00
|
|
|
DagInit *Tree = Fragments[i]->getValueAsDag("Fragment");
|
|
|
|
TreePattern *P = new TreePattern(Fragments[i], Tree, *this);
|
2005-09-07 23:44:43 +00:00
|
|
|
PatternFragments[Fragments[i]] = P;
|
2005-09-13 21:20:49 +00:00
|
|
|
|
|
|
|
// Validate the argument list, converting it to map, to discard duplicates.
|
|
|
|
std::vector<std::string> &Args = P->getArgList();
|
|
|
|
std::set<std::string> OperandsMap(Args.begin(), Args.end());
|
|
|
|
|
|
|
|
if (OperandsMap.count(""))
|
|
|
|
P->error("Cannot have unnamed 'node' values in pattern fragment!");
|
|
|
|
|
|
|
|
// Parse the operands list.
|
|
|
|
DagInit *OpsList = Fragments[i]->getValueAsDag("Operands");
|
|
|
|
if (OpsList->getNodeType()->getName() != "ops")
|
|
|
|
P->error("Operands list should start with '(ops ... '!");
|
|
|
|
|
|
|
|
// Copy over the arguments.
|
|
|
|
Args.clear();
|
|
|
|
for (unsigned j = 0, e = OpsList->getNumArgs(); j != e; ++j) {
|
|
|
|
if (!dynamic_cast<DefInit*>(OpsList->getArg(j)) ||
|
|
|
|
static_cast<DefInit*>(OpsList->getArg(j))->
|
|
|
|
getDef()->getName() != "node")
|
|
|
|
P->error("Operands list should all be 'node' values.");
|
|
|
|
if (OpsList->getArgName(j).empty())
|
|
|
|
P->error("Operands list should have names for each operand!");
|
|
|
|
if (!OperandsMap.count(OpsList->getArgName(j)))
|
|
|
|
P->error("'" + OpsList->getArgName(j) +
|
|
|
|
"' does not occur in pattern or was multiply specified!");
|
|
|
|
OperandsMap.erase(OpsList->getArgName(j));
|
|
|
|
Args.push_back(OpsList->getArgName(j));
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!OperandsMap.empty())
|
|
|
|
P->error("Operands list does not contain an entry for operand '" +
|
|
|
|
*OperandsMap.begin() + "'!");
|
2005-09-07 23:44:43 +00:00
|
|
|
|
|
|
|
// If there is a code init for this fragment, emit the predicate code and
|
|
|
|
// keep track of the fact that this fragment uses it.
|
2005-09-13 21:51:00 +00:00
|
|
|
std::string Code = Fragments[i]->getValueAsCode("Predicate");
|
|
|
|
if (!Code.empty()) {
|
2005-09-09 01:15:01 +00:00
|
|
|
assert(!P->getOnlyTree()->isLeaf() && "Can't be a leaf!");
|
2005-09-07 23:44:43 +00:00
|
|
|
std::string ClassName =
|
2005-09-09 01:15:01 +00:00
|
|
|
getSDNodeInfo(P->getOnlyTree()->getOperator()).getSDClassName();
|
2005-09-07 23:44:43 +00:00
|
|
|
const char *C2 = ClassName == "SDNode" ? "N" : "inN";
|
|
|
|
|
2005-09-13 22:03:37 +00:00
|
|
|
OS << "inline bool Predicate_" << Fragments[i]->getName()
|
2005-09-07 23:44:43 +00:00
|
|
|
<< "(SDNode *" << C2 << ") {\n";
|
|
|
|
if (ClassName != "SDNode")
|
|
|
|
OS << " " << ClassName << " *N = cast<" << ClassName << ">(inN);\n";
|
2005-09-13 21:51:00 +00:00
|
|
|
OS << Code << "\n}\n";
|
2005-09-09 01:15:01 +00:00
|
|
|
P->getOnlyTree()->setPredicateFn("Predicate_"+Fragments[i]->getName());
|
2005-09-07 23:44:43 +00:00
|
|
|
}
|
2005-09-13 21:59:15 +00:00
|
|
|
|
|
|
|
// If there is a node transformation corresponding to this, keep track of
|
|
|
|
// it.
|
|
|
|
Record *Transform = Fragments[i]->getValueAsDef("OperandTransform");
|
|
|
|
if (!getSDNodeTransform(Transform).second.empty()) // not noop xform?
|
2005-09-14 22:55:26 +00:00
|
|
|
P->getOnlyTree()->setTransformFn(Transform);
|
2005-09-07 23:44:43 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
OS << "\n\n";
|
|
|
|
|
|
|
|
// Now that we've parsed all of the tree fragments, do a closure on them so
|
|
|
|
// that there are not references to PatFrags left inside of them.
|
|
|
|
for (std::map<Record*, TreePattern*>::iterator I = PatternFragments.begin(),
|
|
|
|
E = PatternFragments.end(); I != E; ++I) {
|
Implement a complete type inference system for dag patterns, based on the
constraints defined in the DAG node definitions in the .td files. This
allows us to infer (and check!) the types for all nodes in the current
ppc .td file. For example, instead of:
Inst pattern EQV: (set GPRC:i32:$rT, (xor (xor GPRC:i32:$rA, GPRC:i32:$rB), (imm)<<Predicate_immAllOnes>>))
we now fully infer:
Inst pattern EQV: (set:void GPRC:i32:$rT, (xor:i32 (xor:i32 GPRC:i32:$rA, GPRC:i32:$rB), (imm:i32)<<Predicate_immAllOnes>>))
from: (set GPRC:$rT, (not (xor GPRC:$rA, GPRC:$rB)))
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@23284 91177308-0d34-0410-b5e6-96231b3b80d8
2005-09-08 23:22:48 +00:00
|
|
|
TreePattern *ThePat = I->second;
|
|
|
|
ThePat->InlinePatternFragments();
|
2005-09-13 21:20:49 +00:00
|
|
|
|
Implement a complete type inference system for dag patterns, based on the
constraints defined in the DAG node definitions in the .td files. This
allows us to infer (and check!) the types for all nodes in the current
ppc .td file. For example, instead of:
Inst pattern EQV: (set GPRC:i32:$rT, (xor (xor GPRC:i32:$rA, GPRC:i32:$rB), (imm)<<Predicate_immAllOnes>>))
we now fully infer:
Inst pattern EQV: (set:void GPRC:i32:$rT, (xor:i32 (xor:i32 GPRC:i32:$rA, GPRC:i32:$rB), (imm:i32)<<Predicate_immAllOnes>>))
from: (set GPRC:$rT, (not (xor GPRC:$rA, GPRC:$rB)))
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@23284 91177308-0d34-0410-b5e6-96231b3b80d8
2005-09-08 23:22:48 +00:00
|
|
|
// Infer as many types as possible. Don't worry about it if we don't infer
|
|
|
|
// all of them, some may depend on the inputs of the pattern.
|
|
|
|
try {
|
|
|
|
ThePat->InferAllTypes();
|
|
|
|
} catch (...) {
|
|
|
|
// If this pattern fragment is not supported by this target (no types can
|
|
|
|
// satisfy its constraints), just ignore it. If the bogus pattern is
|
|
|
|
// actually used by instructions, the type consistency error will be
|
|
|
|
// reported there.
|
|
|
|
}
|
|
|
|
|
2005-09-07 23:44:43 +00:00
|
|
|
// If debugging, print out the pattern fragment result.
|
Implement a complete type inference system for dag patterns, based on the
constraints defined in the DAG node definitions in the .td files. This
allows us to infer (and check!) the types for all nodes in the current
ppc .td file. For example, instead of:
Inst pattern EQV: (set GPRC:i32:$rT, (xor (xor GPRC:i32:$rA, GPRC:i32:$rB), (imm)<<Predicate_immAllOnes>>))
we now fully infer:
Inst pattern EQV: (set:void GPRC:i32:$rT, (xor:i32 (xor:i32 GPRC:i32:$rA, GPRC:i32:$rB), (imm:i32)<<Predicate_immAllOnes>>))
from: (set GPRC:$rT, (not (xor GPRC:$rA, GPRC:$rB)))
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@23284 91177308-0d34-0410-b5e6-96231b3b80d8
2005-09-08 23:22:48 +00:00
|
|
|
DEBUG(ThePat->dump());
|
2005-09-07 23:44:43 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2005-09-14 20:53:42 +00:00
|
|
|
/// HandleUse - Given "Pat" a leaf in the pattern, check to see if it is an
|
2005-09-14 23:05:13 +00:00
|
|
|
/// instruction input. Return true if this is a real use.
|
|
|
|
static bool HandleUse(TreePattern *I, TreePatternNode *Pat,
|
2005-09-14 20:53:42 +00:00
|
|
|
std::map<std::string, TreePatternNode*> &InstInputs) {
|
|
|
|
// No name -> not interesting.
|
2005-09-14 22:06:36 +00:00
|
|
|
if (Pat->getName().empty()) {
|
|
|
|
if (Pat->isLeaf()) {
|
|
|
|
DefInit *DI = dynamic_cast<DefInit*>(Pat->getLeafValue());
|
|
|
|
if (DI && DI->getDef()->isSubClassOf("RegisterClass"))
|
|
|
|
I->error("Input " + DI->getDef()->getName() + " must be named!");
|
|
|
|
|
|
|
|
}
|
2005-09-14 23:05:13 +00:00
|
|
|
return false;
|
2005-09-14 22:06:36 +00:00
|
|
|
}
|
2005-09-14 20:53:42 +00:00
|
|
|
|
|
|
|
Record *Rec;
|
|
|
|
if (Pat->isLeaf()) {
|
|
|
|
DefInit *DI = dynamic_cast<DefInit*>(Pat->getLeafValue());
|
|
|
|
if (!DI) I->error("Input $" + Pat->getName() + " must be an identifier!");
|
|
|
|
Rec = DI->getDef();
|
|
|
|
} else {
|
|
|
|
assert(Pat->getNumChildren() == 0 && "can't be a use with children!");
|
|
|
|
Rec = Pat->getOperator();
|
|
|
|
}
|
|
|
|
|
|
|
|
TreePatternNode *&Slot = InstInputs[Pat->getName()];
|
|
|
|
if (!Slot) {
|
|
|
|
Slot = Pat;
|
|
|
|
} else {
|
|
|
|
Record *SlotRec;
|
|
|
|
if (Slot->isLeaf()) {
|
2005-09-16 00:29:46 +00:00
|
|
|
SlotRec = dynamic_cast<DefInit*>(Slot->getLeafValue())->getDef();
|
2005-09-14 20:53:42 +00:00
|
|
|
} else {
|
|
|
|
assert(Slot->getNumChildren() == 0 && "can't be a use with children!");
|
|
|
|
SlotRec = Slot->getOperator();
|
|
|
|
}
|
|
|
|
|
|
|
|
// Ensure that the inputs agree if we've already seen this input.
|
|
|
|
if (Rec != SlotRec)
|
|
|
|
I->error("All $" + Pat->getName() + " inputs must agree with each other");
|
|
|
|
if (Slot->getType() != Pat->getType())
|
|
|
|
I->error("All $" + Pat->getName() + " inputs must agree with each other");
|
|
|
|
}
|
2005-09-14 23:05:13 +00:00
|
|
|
return true;
|
2005-09-14 20:53:42 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/// FindPatternInputsAndOutputs - Scan the specified TreePatternNode (which is
|
|
|
|
/// part of "I", the instruction), computing the set of inputs and outputs of
|
|
|
|
/// the pattern. Report errors if we see anything naughty.
|
|
|
|
void DAGISelEmitter::
|
|
|
|
FindPatternInputsAndOutputs(TreePattern *I, TreePatternNode *Pat,
|
|
|
|
std::map<std::string, TreePatternNode*> &InstInputs,
|
|
|
|
std::map<std::string, Record*> &InstResults) {
|
|
|
|
if (Pat->isLeaf()) {
|
2005-09-14 23:05:13 +00:00
|
|
|
bool isUse = HandleUse(I, Pat, InstInputs);
|
|
|
|
if (!isUse && Pat->getTransformFn())
|
|
|
|
I->error("Cannot specify a transform function for a non-input value!");
|
2005-09-14 20:53:42 +00:00
|
|
|
return;
|
|
|
|
} else if (Pat->getOperator()->getName() != "set") {
|
|
|
|
// If this is not a set, verify that the children nodes are not void typed,
|
|
|
|
// and recurse.
|
|
|
|
for (unsigned i = 0, e = Pat->getNumChildren(); i != e; ++i) {
|
|
|
|
if (Pat->getChild(i)->getType() == MVT::isVoid)
|
|
|
|
I->error("Cannot have void nodes inside of patterns!");
|
|
|
|
FindPatternInputsAndOutputs(I, Pat->getChild(i), InstInputs, InstResults);
|
|
|
|
}
|
|
|
|
|
|
|
|
// If this is a non-leaf node with no children, treat it basically as if
|
|
|
|
// it were a leaf. This handles nodes like (imm).
|
2005-09-14 23:05:13 +00:00
|
|
|
bool isUse = false;
|
2005-09-14 20:53:42 +00:00
|
|
|
if (Pat->getNumChildren() == 0)
|
2005-09-14 23:05:13 +00:00
|
|
|
isUse = HandleUse(I, Pat, InstInputs);
|
2005-09-14 20:53:42 +00:00
|
|
|
|
2005-09-14 23:05:13 +00:00
|
|
|
if (!isUse && Pat->getTransformFn())
|
|
|
|
I->error("Cannot specify a transform function for a non-input value!");
|
2005-09-14 20:53:42 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Otherwise, this is a set, validate and collect instruction results.
|
|
|
|
if (Pat->getNumChildren() == 0)
|
|
|
|
I->error("set requires operands!");
|
|
|
|
else if (Pat->getNumChildren() & 1)
|
|
|
|
I->error("set requires an even number of operands");
|
|
|
|
|
2005-09-14 23:05:13 +00:00
|
|
|
if (Pat->getTransformFn())
|
|
|
|
I->error("Cannot specify a transform function on a set node!");
|
|
|
|
|
2005-09-14 20:53:42 +00:00
|
|
|
// Check the set destinations.
|
|
|
|
unsigned NumValues = Pat->getNumChildren()/2;
|
|
|
|
for (unsigned i = 0; i != NumValues; ++i) {
|
|
|
|
TreePatternNode *Dest = Pat->getChild(i);
|
|
|
|
if (!Dest->isLeaf())
|
|
|
|
I->error("set destination should be a virtual register!");
|
|
|
|
|
|
|
|
DefInit *Val = dynamic_cast<DefInit*>(Dest->getLeafValue());
|
|
|
|
if (!Val)
|
|
|
|
I->error("set destination should be a virtual register!");
|
|
|
|
|
|
|
|
if (!Val->getDef()->isSubClassOf("RegisterClass"))
|
|
|
|
I->error("set destination should be a virtual register!");
|
|
|
|
if (Dest->getName().empty())
|
|
|
|
I->error("set destination must have a name!");
|
|
|
|
if (InstResults.count(Dest->getName()))
|
|
|
|
I->error("cannot set '" + Dest->getName() +"' multiple times");
|
|
|
|
InstResults[Dest->getName()] = Val->getDef();
|
|
|
|
|
|
|
|
// Verify and collect info from the computation.
|
|
|
|
FindPatternInputsAndOutputs(I, Pat->getChild(i+NumValues),
|
|
|
|
InstInputs, InstResults);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2005-09-15 02:38:02 +00:00
|
|
|
/// ParseInstructions - Parse all of the instructions, inlining and resolving
|
|
|
|
/// any fragments involved. This populates the Instructions list with fully
|
|
|
|
/// resolved instructions.
|
|
|
|
void DAGISelEmitter::ParseInstructions() {
|
2005-09-07 23:44:43 +00:00
|
|
|
std::vector<Record*> Instrs = Records.getAllDerivedDefinitions("Instruction");
|
|
|
|
|
|
|
|
for (unsigned i = 0, e = Instrs.size(); i != e; ++i) {
|
|
|
|
if (!dynamic_cast<ListInit*>(Instrs[i]->getValueInit("Pattern")))
|
|
|
|
continue; // no pattern yet, ignore it.
|
|
|
|
|
|
|
|
ListInit *LI = Instrs[i]->getValueAsListInit("Pattern");
|
|
|
|
if (LI->getSize() == 0) continue; // no pattern.
|
|
|
|
|
|
|
|
// Parse the instruction.
|
2005-09-15 22:23:50 +00:00
|
|
|
TreePattern *I = new TreePattern(Instrs[i], LI, *this);
|
2005-09-07 23:44:43 +00:00
|
|
|
// Inline pattern fragments into it.
|
Implement a complete type inference system for dag patterns, based on the
constraints defined in the DAG node definitions in the .td files. This
allows us to infer (and check!) the types for all nodes in the current
ppc .td file. For example, instead of:
Inst pattern EQV: (set GPRC:i32:$rT, (xor (xor GPRC:i32:$rA, GPRC:i32:$rB), (imm)<<Predicate_immAllOnes>>))
we now fully infer:
Inst pattern EQV: (set:void GPRC:i32:$rT, (xor:i32 (xor:i32 GPRC:i32:$rA, GPRC:i32:$rB), (imm:i32)<<Predicate_immAllOnes>>))
from: (set GPRC:$rT, (not (xor GPRC:$rA, GPRC:$rB)))
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@23284 91177308-0d34-0410-b5e6-96231b3b80d8
2005-09-08 23:22:48 +00:00
|
|
|
I->InlinePatternFragments();
|
|
|
|
|
2005-09-08 23:26:30 +00:00
|
|
|
// Infer as many types as possible. If we cannot infer all of them, we can
|
|
|
|
// never do anything with this instruction pattern: report it to the user.
|
2005-09-15 21:42:00 +00:00
|
|
|
if (!I->InferAllTypes())
|
Implement a complete type inference system for dag patterns, based on the
constraints defined in the DAG node definitions in the .td files. This
allows us to infer (and check!) the types for all nodes in the current
ppc .td file. For example, instead of:
Inst pattern EQV: (set GPRC:i32:$rT, (xor (xor GPRC:i32:$rA, GPRC:i32:$rB), (imm)<<Predicate_immAllOnes>>))
we now fully infer:
Inst pattern EQV: (set:void GPRC:i32:$rT, (xor:i32 (xor:i32 GPRC:i32:$rA, GPRC:i32:$rB), (imm:i32)<<Predicate_immAllOnes>>))
from: (set GPRC:$rT, (not (xor GPRC:$rA, GPRC:$rB)))
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@23284 91177308-0d34-0410-b5e6-96231b3b80d8
2005-09-08 23:22:48 +00:00
|
|
|
I->error("Could not infer all types in pattern!");
|
2005-09-09 01:11:44 +00:00
|
|
|
|
2005-09-14 20:53:42 +00:00
|
|
|
// InstInputs - Keep track of all of the inputs of the instruction, along
|
|
|
|
// with the record they are declared as.
|
|
|
|
std::map<std::string, TreePatternNode*> InstInputs;
|
|
|
|
|
|
|
|
// InstResults - Keep track of all the virtual registers that are 'set'
|
2005-09-14 02:11:12 +00:00
|
|
|
// in the instruction, including what reg class they are.
|
2005-09-14 20:53:42 +00:00
|
|
|
std::map<std::string, Record*> InstResults;
|
|
|
|
|
2005-09-14 00:09:24 +00:00
|
|
|
// Verify that the top-level forms in the instruction are of void type, and
|
2005-09-14 20:53:42 +00:00
|
|
|
// fill in the InstResults map.
|
2005-09-14 00:09:24 +00:00
|
|
|
for (unsigned j = 0, e = I->getNumTrees(); j != e; ++j) {
|
|
|
|
TreePatternNode *Pat = I->getTree(j);
|
|
|
|
if (Pat->getType() != MVT::isVoid) {
|
2005-09-09 01:11:44 +00:00
|
|
|
I->dump();
|
|
|
|
I->error("Top-level forms in instruction pattern should have"
|
|
|
|
" void types");
|
|
|
|
}
|
2005-09-14 20:53:42 +00:00
|
|
|
|
|
|
|
// Find inputs and outputs, and verify the structure of the uses/defs.
|
|
|
|
FindPatternInputsAndOutputs(I, Pat, InstInputs, InstResults);
|
2005-09-14 00:09:24 +00:00
|
|
|
}
|
2005-09-14 02:11:12 +00:00
|
|
|
|
2005-09-14 20:53:42 +00:00
|
|
|
// Now that we have inputs and outputs of the pattern, inspect the operands
|
|
|
|
// list for the instruction. This determines the order that operands are
|
|
|
|
// added to the machine instruction the node corresponds to.
|
|
|
|
unsigned NumResults = InstResults.size();
|
2005-09-14 18:19:25 +00:00
|
|
|
|
|
|
|
// Parse the operands list from the (ops) list, validating it.
|
|
|
|
std::vector<std::string> &Args = I->getArgList();
|
|
|
|
assert(Args.empty() && "Args list should still be empty here!");
|
|
|
|
CodeGenInstruction &CGI = Target.getInstruction(Instrs[i]->getName());
|
|
|
|
|
|
|
|
// Check that all of the results occur first in the list.
|
2005-09-15 21:51:12 +00:00
|
|
|
std::vector<MVT::ValueType> ResultTypes;
|
2005-09-14 18:19:25 +00:00
|
|
|
for (unsigned i = 0; i != NumResults; ++i) {
|
2005-09-14 21:04:12 +00:00
|
|
|
if (i == CGI.OperandList.size())
|
2005-09-14 20:53:42 +00:00
|
|
|
I->error("'" + InstResults.begin()->first +
|
|
|
|
"' set but does not appear in operand list!");
|
2005-09-14 18:19:25 +00:00
|
|
|
const std::string &OpName = CGI.OperandList[i].Name;
|
|
|
|
|
2005-09-14 20:53:42 +00:00
|
|
|
// Check that it exists in InstResults.
|
|
|
|
Record *R = InstResults[OpName];
|
2005-09-14 18:19:25 +00:00
|
|
|
if (R == 0)
|
|
|
|
I->error("Operand $" + OpName + " should be a set destination: all "
|
|
|
|
"outputs must occur before inputs in operand list!");
|
|
|
|
|
|
|
|
if (CGI.OperandList[i].Rec != R)
|
|
|
|
I->error("Operand $" + OpName + " class mismatch!");
|
|
|
|
|
2005-09-15 21:51:12 +00:00
|
|
|
// Remember the return type.
|
|
|
|
ResultTypes.push_back(CGI.OperandList[i].Ty);
|
|
|
|
|
2005-09-14 18:19:25 +00:00
|
|
|
// Okay, this one checks out.
|
2005-09-14 20:53:42 +00:00
|
|
|
InstResults.erase(OpName);
|
2005-09-14 18:19:25 +00:00
|
|
|
}
|
2005-09-14 02:11:12 +00:00
|
|
|
|
2005-09-14 21:59:34 +00:00
|
|
|
// Loop over the inputs next. Make a copy of InstInputs so we can destroy
|
|
|
|
// the copy while we're checking the inputs.
|
|
|
|
std::map<std::string, TreePatternNode*> InstInputsCheck(InstInputs);
|
2005-09-14 22:55:26 +00:00
|
|
|
|
|
|
|
std::vector<TreePatternNode*> ResultNodeOperands;
|
2005-09-15 21:51:12 +00:00
|
|
|
std::vector<MVT::ValueType> OperandTypes;
|
2005-09-14 20:53:42 +00:00
|
|
|
for (unsigned i = NumResults, e = CGI.OperandList.size(); i != e; ++i) {
|
|
|
|
const std::string &OpName = CGI.OperandList[i].Name;
|
|
|
|
if (OpName.empty())
|
|
|
|
I->error("Operand #" + utostr(i) + " in operands list has no name!");
|
|
|
|
|
2005-09-14 21:59:34 +00:00
|
|
|
if (!InstInputsCheck.count(OpName))
|
2005-09-14 20:53:42 +00:00
|
|
|
I->error("Operand $" + OpName +
|
|
|
|
" does not appear in the instruction pattern");
|
2005-09-14 21:59:34 +00:00
|
|
|
TreePatternNode *InVal = InstInputsCheck[OpName];
|
2005-09-14 22:55:26 +00:00
|
|
|
InstInputsCheck.erase(OpName); // It occurred, remove from map.
|
2005-09-14 20:53:42 +00:00
|
|
|
if (CGI.OperandList[i].Ty != InVal->getType())
|
|
|
|
I->error("Operand $" + OpName +
|
|
|
|
"'s type disagrees between the operand and pattern");
|
2005-09-15 21:51:12 +00:00
|
|
|
OperandTypes.push_back(InVal->getType());
|
2005-09-14 22:55:26 +00:00
|
|
|
|
2005-09-14 23:01:59 +00:00
|
|
|
// Construct the result for the dest-pattern operand list.
|
|
|
|
TreePatternNode *OpNode = InVal->clone();
|
|
|
|
|
|
|
|
// No predicate is useful on the result.
|
|
|
|
OpNode->setPredicateFn("");
|
|
|
|
|
|
|
|
// Promote the xform function to be an explicit node if set.
|
|
|
|
if (Record *Xform = OpNode->getTransformFn()) {
|
|
|
|
OpNode->setTransformFn(0);
|
|
|
|
std::vector<TreePatternNode*> Children;
|
|
|
|
Children.push_back(OpNode);
|
|
|
|
OpNode = new TreePatternNode(Xform, Children);
|
|
|
|
}
|
|
|
|
|
|
|
|
ResultNodeOperands.push_back(OpNode);
|
2005-09-14 20:53:42 +00:00
|
|
|
}
|
|
|
|
|
2005-09-14 21:59:34 +00:00
|
|
|
if (!InstInputsCheck.empty())
|
|
|
|
I->error("Input operand $" + InstInputsCheck.begin()->first +
|
|
|
|
" occurs in pattern but not in operands list!");
|
2005-09-14 22:55:26 +00:00
|
|
|
|
|
|
|
TreePatternNode *ResultPattern =
|
|
|
|
new TreePatternNode(I->getRecord(), ResultNodeOperands);
|
2005-09-15 22:23:50 +00:00
|
|
|
|
|
|
|
// Create and insert the instruction.
|
|
|
|
DAGInstruction TheInst(I, ResultTypes, OperandTypes);
|
|
|
|
Instructions.insert(std::make_pair(I->getRecord(), TheInst));
|
|
|
|
|
|
|
|
// Use a temporary tree pattern to infer all types and make sure that the
|
|
|
|
// constructed result is correct. This depends on the instruction already
|
|
|
|
// being inserted into the Instructions map.
|
|
|
|
TreePattern Temp(I->getRecord(), ResultPattern, *this);
|
|
|
|
Temp.InferAllTypes();
|
|
|
|
|
|
|
|
DAGInstruction &TheInsertedInst = Instructions.find(I->getRecord())->second;
|
|
|
|
TheInsertedInst.setResultPattern(Temp.getOnlyTree());
|
2005-09-14 22:55:26 +00:00
|
|
|
|
Implement a complete type inference system for dag patterns, based on the
constraints defined in the DAG node definitions in the .td files. This
allows us to infer (and check!) the types for all nodes in the current
ppc .td file. For example, instead of:
Inst pattern EQV: (set GPRC:i32:$rT, (xor (xor GPRC:i32:$rA, GPRC:i32:$rB), (imm)<<Predicate_immAllOnes>>))
we now fully infer:
Inst pattern EQV: (set:void GPRC:i32:$rT, (xor:i32 (xor:i32 GPRC:i32:$rA, GPRC:i32:$rB), (imm:i32)<<Predicate_immAllOnes>>))
from: (set GPRC:$rT, (not (xor GPRC:$rA, GPRC:$rB)))
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@23284 91177308-0d34-0410-b5e6-96231b3b80d8
2005-09-08 23:22:48 +00:00
|
|
|
DEBUG(I->dump());
|
2005-09-07 23:44:43 +00:00
|
|
|
}
|
2005-09-14 00:09:24 +00:00
|
|
|
|
2005-09-14 20:53:42 +00:00
|
|
|
// If we can, convert the instructions to be patterns that are matched!
|
2005-09-15 21:57:35 +00:00
|
|
|
for (std::map<Record*, DAGInstruction>::iterator II = Instructions.begin(),
|
|
|
|
E = Instructions.end(); II != E; ++II) {
|
|
|
|
TreePattern *I = II->second.getPattern();
|
2005-09-14 00:09:24 +00:00
|
|
|
|
|
|
|
if (I->getNumTrees() != 1) {
|
|
|
|
std::cerr << "CANNOT HANDLE: " << I->getRecord()->getName() << " yet!";
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
TreePatternNode *Pattern = I->getTree(0);
|
|
|
|
if (Pattern->getOperator()->getName() != "set")
|
|
|
|
continue; // Not a set (store or something?)
|
|
|
|
|
|
|
|
if (Pattern->getNumChildren() != 2)
|
|
|
|
continue; // Not a set of a single value (not handled so far)
|
|
|
|
|
|
|
|
TreePatternNode *SrcPattern = Pattern->getChild(1)->clone();
|
2005-09-15 21:57:35 +00:00
|
|
|
TreePatternNode *DstPattern = II->second.getResultPattern();
|
2005-09-14 00:09:24 +00:00
|
|
|
PatternsToMatch.push_back(std::make_pair(SrcPattern, DstPattern));
|
|
|
|
}
|
2005-09-07 23:44:43 +00:00
|
|
|
}
|
|
|
|
|
2005-09-15 02:38:02 +00:00
|
|
|
void DAGISelEmitter::ParsePatterns() {
|
2005-09-15 21:42:00 +00:00
|
|
|
std::vector<Record*> Patterns = Records.getAllDerivedDefinitions("Pattern");
|
2005-09-15 02:38:02 +00:00
|
|
|
|
2005-09-15 21:42:00 +00:00
|
|
|
for (unsigned i = 0, e = Patterns.size(); i != e; ++i) {
|
2005-09-15 22:23:50 +00:00
|
|
|
DagInit *Tree = Patterns[i]->getValueAsDag("PatternToMatch");
|
|
|
|
TreePattern *Pattern = new TreePattern(Patterns[i], Tree, *this);
|
2005-09-15 02:38:02 +00:00
|
|
|
|
2005-09-15 21:42:00 +00:00
|
|
|
// Inline pattern fragments into it.
|
|
|
|
Pattern->InlinePatternFragments();
|
|
|
|
|
|
|
|
// Infer as many types as possible. If we cannot infer all of them, we can
|
|
|
|
// never do anything with this pattern: report it to the user.
|
|
|
|
if (!Pattern->InferAllTypes())
|
|
|
|
Pattern->error("Could not infer all types in pattern!");
|
|
|
|
|
|
|
|
ListInit *LI = Patterns[i]->getValueAsListInit("ResultInstrs");
|
|
|
|
if (LI->getSize() == 0) continue; // no pattern.
|
|
|
|
|
|
|
|
// Parse the instruction.
|
2005-09-15 22:23:50 +00:00
|
|
|
TreePattern *Result = new TreePattern(Patterns[i], LI, *this);
|
2005-09-15 21:42:00 +00:00
|
|
|
|
|
|
|
// Inline pattern fragments into it.
|
|
|
|
Result->InlinePatternFragments();
|
|
|
|
|
|
|
|
// Infer as many types as possible. If we cannot infer all of them, we can
|
|
|
|
// never do anything with this pattern: report it to the user.
|
|
|
|
if (!Result->InferAllTypes())
|
2005-09-15 21:57:35 +00:00
|
|
|
Result->error("Could not infer all types in pattern result!");
|
2005-09-15 21:42:00 +00:00
|
|
|
|
|
|
|
if (Result->getNumTrees() != 1)
|
|
|
|
Result->error("Cannot handle instructions producing instructions "
|
|
|
|
"with temporaries yet!");
|
|
|
|
PatternsToMatch.push_back(std::make_pair(Pattern->getOnlyTree(),
|
|
|
|
Result->getOnlyTree()));
|
|
|
|
}
|
2005-09-15 02:38:02 +00:00
|
|
|
|
|
|
|
DEBUG(std::cerr << "\n\nPARSED PATTERNS TO MATCH:\n\n";
|
|
|
|
for (unsigned i = 0, e = PatternsToMatch.size(); i != e; ++i) {
|
|
|
|
std::cerr << "PATTERN: "; PatternsToMatch[i].first->dump();
|
|
|
|
std::cerr << "\nRESULT: ";PatternsToMatch[i].second->dump();
|
|
|
|
std::cerr << "\n";
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
2005-09-23 21:33:23 +00:00
|
|
|
/// EmitMatchForPattern - Emit a matcher for N, going to the label for PatternNo
|
|
|
|
/// if the match fails. At this point, we already know that the opcode for N
|
|
|
|
/// matches, and the SDNode for the result has the RootName specified name.
|
|
|
|
void DAGISelEmitter::EmitMatchForPattern(TreePatternNode *N,
|
2005-09-23 23:16:51 +00:00
|
|
|
const std::string &RootName,
|
|
|
|
std::map<std::string,std::string> &VarMap,
|
2005-09-23 21:33:23 +00:00
|
|
|
unsigned PatternNo, std::ostream &OS) {
|
|
|
|
assert(!N->isLeaf() && "Cannot match against a leaf!");
|
2005-09-24 00:40:24 +00:00
|
|
|
|
|
|
|
// If this node has a name associated with it, capture it in VarMap. If
|
|
|
|
// we already saw this in the pattern, emit code to verify dagness.
|
|
|
|
if (!N->getName().empty()) {
|
|
|
|
std::string &VarMapEntry = VarMap[N->getName()];
|
|
|
|
if (VarMapEntry.empty()) {
|
|
|
|
VarMapEntry = RootName;
|
|
|
|
} else {
|
|
|
|
// If we get here, this is a second reference to a specific name. Since
|
|
|
|
// we already have checked that the first reference is valid, we don't
|
|
|
|
// have to recursively match it, just check that it's the same as the
|
|
|
|
// previously named thing.
|
|
|
|
OS << " if (" << VarMapEntry << " != " << RootName
|
|
|
|
<< ") goto P" << PatternNo << "Fail;\n";
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2005-09-23 21:33:23 +00:00
|
|
|
// Emit code to load the child nodes and match their contents recursively.
|
|
|
|
for (unsigned i = 0, e = N->getNumChildren(); i != e; ++i) {
|
2005-09-23 21:53:45 +00:00
|
|
|
OS << " SDOperand " << RootName << i <<" = " << RootName
|
|
|
|
<< ".getOperand(" << i << ");\n";
|
2005-09-23 21:33:23 +00:00
|
|
|
TreePatternNode *Child = N->getChild(i);
|
2005-09-23 23:16:51 +00:00
|
|
|
|
2005-09-23 21:33:23 +00:00
|
|
|
if (!Child->isLeaf()) {
|
|
|
|
// If it's not a leaf, recursively match.
|
|
|
|
const SDNodeInfo &CInfo = getSDNodeInfo(Child->getOperator());
|
2005-09-23 21:53:45 +00:00
|
|
|
OS << " if (" << RootName << i << ".getOpcode() != "
|
2005-09-23 21:33:23 +00:00
|
|
|
<< CInfo.getEnumName() << ") goto P" << PatternNo << "Fail;\n";
|
2005-09-23 23:16:51 +00:00
|
|
|
EmitMatchForPattern(Child, RootName + utostr(i), VarMap, PatternNo, OS);
|
2005-09-23 21:33:23 +00:00
|
|
|
} else {
|
2005-09-24 00:40:24 +00:00
|
|
|
// If this child has a name associated with it, capture it in VarMap. If
|
|
|
|
// we already saw this in the pattern, emit code to verify dagness.
|
|
|
|
if (!Child->getName().empty()) {
|
|
|
|
std::string &VarMapEntry = VarMap[Child->getName()];
|
|
|
|
if (VarMapEntry.empty()) {
|
|
|
|
VarMapEntry = RootName + utostr(i);
|
|
|
|
} else {
|
|
|
|
// If we get here, this is a second reference to a specific name. Since
|
|
|
|
// we already have checked that the first reference is valid, we don't
|
|
|
|
// have to recursively match it, just check that it's the same as the
|
|
|
|
// previously named thing.
|
|
|
|
OS << " if (" << VarMapEntry << " != " << RootName << i
|
|
|
|
<< ") goto P" << PatternNo << "Fail;\n";
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2005-09-23 21:33:23 +00:00
|
|
|
// Handle leaves of various types.
|
|
|
|
Init *LeafVal = Child->getLeafValue();
|
|
|
|
Record *LeafRec = dynamic_cast<DefInit*>(LeafVal)->getDef();
|
|
|
|
if (LeafRec->isSubClassOf("RegisterClass")) {
|
|
|
|
// Handle register references. Nothing to do here.
|
|
|
|
} else if (LeafRec->isSubClassOf("ValueType")) {
|
|
|
|
// Make sure this is the specified value type.
|
|
|
|
OS << " if (cast<VTSDNode>(" << RootName << i << ")->getVT() != "
|
|
|
|
<< "MVT::" << LeafRec->getName() << ") goto P" << PatternNo
|
|
|
|
<< "Fail;\n";
|
|
|
|
} else {
|
|
|
|
Child->dump();
|
|
|
|
assert(0 && "Unknown leaf type!");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// If there is a node predicate for this, emit the call.
|
|
|
|
if (!N->getPredicateFn().empty())
|
|
|
|
OS << " if (!" << N->getPredicateFn() << "(" << RootName
|
2005-09-23 21:53:45 +00:00
|
|
|
<< ".Val)) goto P" << PatternNo << "Fail;\n";
|
2005-09-23 21:33:23 +00:00
|
|
|
}
|
|
|
|
|
2005-09-26 21:53:26 +00:00
|
|
|
/// CodeGenPatternResult - Emit the action for a pattern. Now that it has
|
|
|
|
/// matched, we actually have to build a DAG!
|
2005-09-24 00:40:24 +00:00
|
|
|
unsigned DAGISelEmitter::
|
|
|
|
CodeGenPatternResult(TreePatternNode *N, unsigned &Ctr,
|
|
|
|
std::map<std::string,std::string> &VariableMap,
|
2005-09-26 21:53:26 +00:00
|
|
|
std::ostream &OS) {
|
2005-09-24 00:40:24 +00:00
|
|
|
// This is something selected from the pattern we matched.
|
|
|
|
if (!N->getName().empty()) {
|
2005-09-26 21:53:26 +00:00
|
|
|
std::string &Val = VariableMap[N->getName()];
|
2005-09-24 00:40:24 +00:00
|
|
|
assert(!Val.empty() &&
|
|
|
|
"Variable referenced but not defined and not caught earlier!");
|
|
|
|
if (Val[0] == 'T' && Val[1] == 'm' && Val[2] == 'p') {
|
|
|
|
// Already selected this operand, just return the tmpval.
|
2005-09-26 21:53:26 +00:00
|
|
|
return atoi(Val.c_str()+3);
|
2005-09-28 16:58:06 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
unsigned ResNo = Ctr++;
|
|
|
|
if (!N->isLeaf() && N->getOperator()->getName() == "imm") {
|
|
|
|
switch (N->getType()) {
|
|
|
|
default: assert(0 && "Unknown type for constant node!");
|
|
|
|
case MVT::i1: OS << " bool Tmp"; break;
|
|
|
|
case MVT::i8: OS << " unsigned char Tmp"; break;
|
|
|
|
case MVT::i16: OS << " unsigned short Tmp"; break;
|
|
|
|
case MVT::i32: OS << " unsigned Tmp"; break;
|
|
|
|
case MVT::i64: OS << " uint64_t Tmp"; break;
|
|
|
|
}
|
|
|
|
OS << ResNo << "C = cast<ConstantSDNode>(" << Val << ")->getValue();\n";
|
|
|
|
OS << " SDOperand Tmp" << ResNo << " = CurDAG->getTargetConstant(Tmp"
|
|
|
|
<< ResNo << "C, MVT::" << getEnumName(N->getType()) << ");\n";
|
2005-09-24 00:40:24 +00:00
|
|
|
} else {
|
|
|
|
OS << " SDOperand Tmp" << ResNo << " = Select(" << Val << ");\n";
|
|
|
|
}
|
2005-09-28 16:58:06 +00:00
|
|
|
// Add Tmp<ResNo> to VariableMap, so that we don't multiply select this
|
|
|
|
// value if used multiple times by this pattern result.
|
|
|
|
Val = "Tmp"+utostr(ResNo);
|
|
|
|
return ResNo;
|
2005-09-24 00:40:24 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if (N->isLeaf()) {
|
|
|
|
N->dump();
|
|
|
|
assert(0 && "Unknown leaf type!");
|
|
|
|
return ~0U;
|
|
|
|
}
|
|
|
|
|
|
|
|
Record *Op = N->getOperator();
|
|
|
|
if (Op->isSubClassOf("Instruction")) {
|
|
|
|
// Emit all of the operands.
|
|
|
|
std::vector<unsigned> Ops;
|
|
|
|
for (unsigned i = 0, e = N->getNumChildren(); i != e; ++i)
|
|
|
|
Ops.push_back(CodeGenPatternResult(N->getChild(i), Ctr, VariableMap, OS));
|
|
|
|
|
|
|
|
CodeGenInstruction &II = Target.getInstruction(Op->getName());
|
|
|
|
unsigned ResNo = Ctr++;
|
|
|
|
|
|
|
|
OS << " SDOperand Tmp" << ResNo << " = CurDAG->getTargetNode("
|
|
|
|
<< II.Namespace << "::" << II.TheDef->getName() << ", MVT::"
|
|
|
|
<< getEnumName(N->getType());
|
|
|
|
for (unsigned i = 0, e = Ops.size(); i != e; ++i)
|
|
|
|
OS << ", Tmp" << Ops[i];
|
|
|
|
OS << ");\n";
|
|
|
|
return ResNo;
|
|
|
|
} else if (Op->isSubClassOf("SDNodeXForm")) {
|
|
|
|
assert(N->getNumChildren() == 1 && "node xform should have one child!");
|
|
|
|
unsigned OpVal = CodeGenPatternResult(N->getChild(0), Ctr, VariableMap, OS);
|
|
|
|
|
|
|
|
unsigned ResNo = Ctr++;
|
|
|
|
OS << " SDOperand Tmp" << ResNo << " = Transform_" << Op->getName()
|
|
|
|
<< "(Tmp" << OpVal << ".Val);\n";
|
|
|
|
return ResNo;
|
|
|
|
} else {
|
|
|
|
N->dump();
|
|
|
|
assert(0 && "Unknown node in result pattern!");
|
2005-09-25 19:04:43 +00:00
|
|
|
return ~0U;
|
2005-09-24 00:40:24 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2005-09-23 21:33:23 +00:00
|
|
|
/// EmitCodeForPattern - Given a pattern to match, emit code to the specified
|
|
|
|
/// stream to match the pattern, and generate the code for the match if it
|
|
|
|
/// succeeds.
|
2005-09-23 20:52:47 +00:00
|
|
|
void DAGISelEmitter::EmitCodeForPattern(PatternToMatch &Pattern,
|
|
|
|
std::ostream &OS) {
|
2005-09-23 21:33:23 +00:00
|
|
|
static unsigned PatternCount = 0;
|
|
|
|
unsigned PatternNo = PatternCount++;
|
|
|
|
OS << " { // Pattern #" << PatternNo << ": ";
|
2005-09-23 20:52:47 +00:00
|
|
|
Pattern.first->print(OS);
|
|
|
|
OS << "\n";
|
2005-09-23 21:33:23 +00:00
|
|
|
|
2005-09-23 23:16:51 +00:00
|
|
|
// Emit the matcher, capturing named arguments in VariableMap.
|
|
|
|
std::map<std::string,std::string> VariableMap;
|
|
|
|
EmitMatchForPattern(Pattern.first, "N", VariableMap, PatternNo, OS);
|
2005-09-23 20:52:47 +00:00
|
|
|
|
2005-09-23 21:33:23 +00:00
|
|
|
OS << " // Emit: ";
|
|
|
|
Pattern.second->print(OS);
|
|
|
|
OS << "\n";
|
2005-09-23 20:52:47 +00:00
|
|
|
|
2005-09-24 00:40:24 +00:00
|
|
|
unsigned TmpNo = 0;
|
|
|
|
unsigned Res = CodeGenPatternResult(Pattern.second, TmpNo, VariableMap, OS);
|
2005-09-24 00:50:51 +00:00
|
|
|
|
|
|
|
// Add the result to the map if it has multiple uses.
|
|
|
|
OS << " if (!N.Val->hasOneUse()) CodeGenMap[N] = Tmp" << Res << ";\n";
|
2005-09-24 00:40:24 +00:00
|
|
|
OS << " return Tmp" << Res << ";\n";
|
2005-09-23 21:33:23 +00:00
|
|
|
OS << " }\n P" << PatternNo << "Fail:\n";
|
2005-09-23 20:52:47 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/// getPatternSize - Return the 'size' of this pattern. We want to match large
|
|
|
|
/// patterns before small ones. This is used to determine the size of a
|
|
|
|
/// pattern.
|
|
|
|
static unsigned getPatternSize(TreePatternNode *P) {
|
|
|
|
assert(MVT::isInteger(P->getType()) || MVT::isFloatingPoint(P->getType()) &&
|
|
|
|
"Not a valid pattern node to size!");
|
|
|
|
unsigned Size = 1; // The node itself.
|
|
|
|
|
|
|
|
// Count children in the count if they are also nodes.
|
|
|
|
for (unsigned i = 0, e = P->getNumChildren(); i != e; ++i) {
|
|
|
|
TreePatternNode *Child = P->getChild(i);
|
|
|
|
if (!Child->isLeaf() && Child->getType() != MVT::Other)
|
|
|
|
Size += getPatternSize(Child);
|
|
|
|
}
|
|
|
|
|
|
|
|
return Size;
|
|
|
|
}
|
|
|
|
|
|
|
|
// PatternSortingPredicate - return true if we prefer to match LHS before RHS.
|
|
|
|
// In particular, we want to match maximal patterns first and lowest cost within
|
|
|
|
// a particular complexity first.
|
|
|
|
struct PatternSortingPredicate {
|
|
|
|
bool operator()(DAGISelEmitter::PatternToMatch *LHS,
|
|
|
|
DAGISelEmitter::PatternToMatch *RHS) {
|
|
|
|
unsigned LHSSize = getPatternSize(LHS->first);
|
|
|
|
unsigned RHSSize = getPatternSize(RHS->first);
|
|
|
|
if (LHSSize > RHSSize) return true; // LHS -> bigger -> less cost
|
|
|
|
if (LHSSize < RHSSize) return false;
|
|
|
|
|
|
|
|
// If they are equal, compare cost.
|
|
|
|
// FIXME: Compute cost!
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2005-09-26 21:59:35 +00:00
|
|
|
|
|
|
|
namespace {
|
|
|
|
/// CompareByRecordName - An ordering predicate that implements less-than by
|
|
|
|
/// comparing the names records.
|
|
|
|
struct CompareByRecordName {
|
|
|
|
bool operator()(const Record *LHS, const Record *RHS) const {
|
|
|
|
// Sort by name first.
|
|
|
|
if (LHS->getName() < RHS->getName()) return true;
|
|
|
|
// If both names are equal, sort by pointer.
|
|
|
|
return LHS->getName() == RHS->getName() && LHS < RHS;
|
|
|
|
}
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
2005-09-07 23:44:43 +00:00
|
|
|
void DAGISelEmitter::EmitInstructionSelector(std::ostream &OS) {
|
|
|
|
// Emit boilerplate.
|
|
|
|
OS << "// The main instruction selector code.\n"
|
2005-09-23 21:53:45 +00:00
|
|
|
<< "SDOperand SelectCode(SDOperand N) {\n"
|
|
|
|
<< " if (N.getOpcode() >= ISD::BUILTIN_OP_END &&\n"
|
|
|
|
<< " N.getOpcode() < PPCISD::FIRST_NUMBER)\n"
|
|
|
|
<< " return N; // Already selected.\n\n"
|
2005-09-24 00:50:51 +00:00
|
|
|
<< " if (!N.Val->hasOneUse()) {\n"
|
|
|
|
<< " std::map<SDOperand, SDOperand>::iterator CGMI = CodeGenMap.find(N);\n"
|
|
|
|
<< " if (CGMI != CodeGenMap.end()) return CGMI->second;\n"
|
|
|
|
<< " }\n"
|
2005-09-23 21:53:45 +00:00
|
|
|
<< " switch (N.getOpcode()) {\n"
|
2005-09-07 23:44:43 +00:00
|
|
|
<< " default: break;\n"
|
|
|
|
<< " case ISD::EntryToken: // These leaves remain the same.\n"
|
2005-09-23 21:53:45 +00:00
|
|
|
<< " return N;\n"
|
2005-09-07 23:44:43 +00:00
|
|
|
<< " case ISD::AssertSext:\n"
|
2005-09-26 22:10:24 +00:00
|
|
|
<< " case ISD::AssertZext: {\n"
|
|
|
|
<< " SDOperand Tmp0 = Select(N.getOperand(0));\n"
|
|
|
|
<< " if (!N.Val->hasOneUse()) CodeGenMap[N] = Tmp0;\n"
|
|
|
|
<< " return Tmp0;\n"
|
|
|
|
<< " }\n";
|
2005-09-07 23:44:43 +00:00
|
|
|
|
2005-09-23 19:36:15 +00:00
|
|
|
// Group the patterns by their top-level opcodes.
|
2005-09-26 21:59:35 +00:00
|
|
|
std::map<Record*, std::vector<PatternToMatch*>,
|
|
|
|
CompareByRecordName> PatternsByOpcode;
|
2005-09-23 19:36:15 +00:00
|
|
|
for (unsigned i = 0, e = PatternsToMatch.size(); i != e; ++i)
|
|
|
|
PatternsByOpcode[PatternsToMatch[i].first->getOperator()]
|
|
|
|
.push_back(&PatternsToMatch[i]);
|
|
|
|
|
2005-09-23 20:52:47 +00:00
|
|
|
// Loop over all of the case statements.
|
2005-09-26 21:59:35 +00:00
|
|
|
for (std::map<Record*, std::vector<PatternToMatch*>,
|
|
|
|
CompareByRecordName>::iterator PBOI = PatternsByOpcode.begin(),
|
|
|
|
E = PatternsByOpcode.end(); PBOI != E; ++PBOI) {
|
2005-09-23 19:36:15 +00:00
|
|
|
const SDNodeInfo &OpcodeInfo = getSDNodeInfo(PBOI->first);
|
|
|
|
std::vector<PatternToMatch*> &Patterns = PBOI->second;
|
|
|
|
|
|
|
|
OS << " case " << OpcodeInfo.getEnumName() << ":\n";
|
2005-09-23 20:52:47 +00:00
|
|
|
|
|
|
|
// We want to emit all of the matching code now. However, we want to emit
|
|
|
|
// the matches in order of minimal cost. Sort the patterns so the least
|
|
|
|
// cost one is at the start.
|
2005-09-23 21:33:23 +00:00
|
|
|
std::stable_sort(Patterns.begin(), Patterns.end(),
|
|
|
|
PatternSortingPredicate());
|
2005-09-23 19:36:15 +00:00
|
|
|
|
2005-09-23 20:52:47 +00:00
|
|
|
for (unsigned i = 0, e = Patterns.size(); i != e; ++i)
|
|
|
|
EmitCodeForPattern(*Patterns[i], OS);
|
2005-09-23 21:33:23 +00:00
|
|
|
OS << " break;\n\n";
|
2005-09-23 19:36:15 +00:00
|
|
|
}
|
2005-09-07 23:44:43 +00:00
|
|
|
|
2005-09-23 19:36:15 +00:00
|
|
|
|
2005-09-07 23:44:43 +00:00
|
|
|
OS << " } // end of big switch.\n\n"
|
|
|
|
<< " std::cerr << \"Cannot yet select: \";\n"
|
2005-09-23 21:53:45 +00:00
|
|
|
<< " N.Val->dump();\n"
|
2005-09-07 23:44:43 +00:00
|
|
|
<< " std::cerr << '\\n';\n"
|
|
|
|
<< " abort();\n"
|
|
|
|
<< "}\n";
|
|
|
|
}
|
|
|
|
|
|
|
|
void DAGISelEmitter::run(std::ostream &OS) {
|
|
|
|
EmitSourceFileHeader("DAG Instruction Selector for the " + Target.getName() +
|
|
|
|
" target", OS);
|
|
|
|
|
2005-09-14 00:09:24 +00:00
|
|
|
OS << "// *** NOTE: This file is #included into the middle of the target\n"
|
|
|
|
<< "// *** instruction selector class. These functions are really "
|
|
|
|
<< "methods.\n\n";
|
2005-09-16 00:29:46 +00:00
|
|
|
|
2005-09-24 00:50:51 +00:00
|
|
|
OS << "// Instance var to keep track of multiply used nodes that have \n"
|
|
|
|
<< "// already been selected.\n"
|
|
|
|
<< "std::map<SDOperand, SDOperand> CodeGenMap;\n";
|
|
|
|
|
2005-09-08 21:03:01 +00:00
|
|
|
ParseNodeInfo();
|
2005-09-13 21:51:00 +00:00
|
|
|
ParseNodeTransforms(OS);
|
2005-09-15 02:38:02 +00:00
|
|
|
ParsePatternFragments(OS);
|
|
|
|
ParseInstructions();
|
|
|
|
ParsePatterns();
|
2005-09-23 20:52:47 +00:00
|
|
|
|
|
|
|
// FIXME: Generate variants. For example, commutative patterns can match
|
|
|
|
// multiple ways. Add them to PatternsToMatch as well.
|
2005-09-15 02:38:02 +00:00
|
|
|
|
2005-09-16 00:29:46 +00:00
|
|
|
// At this point, we have full information about the 'Patterns' we need to
|
|
|
|
// parse, both implicitly from instructions as well as from explicit pattern
|
|
|
|
// definitions.
|
2005-09-07 23:44:43 +00:00
|
|
|
|
|
|
|
EmitInstructionSelector(OS);
|
|
|
|
|
|
|
|
for (std::map<Record*, TreePattern*>::iterator I = PatternFragments.begin(),
|
|
|
|
E = PatternFragments.end(); I != E; ++I)
|
|
|
|
delete I->second;
|
|
|
|
PatternFragments.clear();
|
|
|
|
|
|
|
|
Instructions.clear();
|
|
|
|
}
|