#include "llvm/ADT/StringExtras.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/MathExtras.h"
+#include "llvm/Support/Streams.h"
#include <algorithm>
#include <set>
using namespace llvm;
x.SDTCisIntVectorOfSameSize_Info.OtherOperandNum =
R->getValueAsInt("OtherOpNum");
} else {
- std::cerr << "Unrecognized SDTypeConstraint '" << R->getName() << "'!\n";
+ cerr << "Unrecognized SDTypeConstraint '" << R->getName() << "'!\n";
exit(1);
}
}
"We only work with nodes with zero or one result so far!");
if (OpNo >= (NumResults + N->getNumChildren())) {
- std::cerr << "Invalid operand number " << OpNo << " ";
+ cerr << "Invalid operand number " << OpNo << " ";
N->dump();
- std::cerr << '\n';
+ cerr << '\n';
exit(1);
}
} else if (PropList[i]->getName() == "SDNPOptInFlag") {
Properties |= 1 << SDNPOptInFlag;
} else {
- std::cerr << "Unknown SD Node property '" << PropList[i]->getName()
- << "' on node '" << R->getName() << "'!\n";
+ cerr << "Unknown SD Node property '" << PropList[i]->getName()
+ << "' on node '" << R->getName() << "'!\n";
exit(1);
}
}
if (isLeaf()) {
dump();
- std::cerr << " ";
+ cerr << " ";
TP.error("Type inference contradiction found in node!");
} else {
TP.error("Type inference contradiction found in node " +
}
void TreePatternNode::dump() const {
- print(std::cerr);
+ print(*cerr.stream());
}
/// isIsomorphicTo - Return true if this node is recursively isomorphic to
std::vector<unsigned char>
ComplexPat(1, TP.getDAGISelEmitter().getComplexPattern(R).getValueType());
return ComplexPat;
+ } else if (R->getName() == "ptr_rc") {
+ Other[0] = MVT::iPTR;
+ return Other;
} else if (R->getName() == "node" || R->getName() == "srcvalue") {
// Placeholder.
return Unknown;
CodeGenInstruction &InstInfo =
ISE.getTargetInfo().getInstruction(getOperator()->getName());
// Apply the result type to the node
- if (NumResults == 0 || InstInfo.noResults) { // FIXME: temporary hack...
+ if (NumResults == 0 || InstInfo.noResults) { // FIXME: temporary hack.
MadeChange = UpdateNodeType(MVT::isVoid, TP);
} else {
Record *ResultNode = Inst.getResult(0);
- assert(ResultNode->isSubClassOf("RegisterClass") &&
- "Operands should be register classes!");
+
+ if (ResultNode->getName() == "ptr_rc") {
+ std::vector<unsigned char> VT;
+ VT.push_back(MVT::iPTR);
+ MadeChange = UpdateNodeType(VT, TP);
+ } else {
+ assert(ResultNode->isSubClassOf("RegisterClass") &&
+ "Operands should be register classes!");
- const CodeGenRegisterClass &RC =
- ISE.getTargetInfo().getRegisterClass(ResultNode);
- MadeChange = UpdateNodeType(ConvertVTs(RC.getValueTypes()), TP);
+ const CodeGenRegisterClass &RC =
+ ISE.getTargetInfo().getRegisterClass(ResultNode);
+ MadeChange = UpdateNodeType(ConvertVTs(RC.getValueTypes()), 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) {
+ unsigned ChildNo = 0;
+ for (unsigned i = 0, e = Inst.getNumOperands(); i != e; ++i) {
Record *OperandNode = Inst.getOperand(i);
+
+ // If the instruction expects a predicate operand, we codegen this by
+ // setting the predicate to it's "execute always" value.
+ if (OperandNode->isSubClassOf("PredicateOperand"))
+ continue;
+
+ // Verify that we didn't run out of provided operands.
+ if (ChildNo >= getNumChildren())
+ TP.error("Instruction '" + getOperator()->getName() +
+ "' expects more operands than were provided.");
+
MVT::ValueType VT;
+ TreePatternNode *Child = getChild(ChildNo++);
if (OperandNode->isSubClassOf("RegisterClass")) {
const CodeGenRegisterClass &RC =
ISE.getTargetInfo().getRegisterClass(OperandNode);
- MadeChange |=getChild(i)->UpdateNodeType(ConvertVTs(RC.getValueTypes()),
- TP);
+ MadeChange |= Child->UpdateNodeType(ConvertVTs(RC.getValueTypes()), TP);
} else if (OperandNode->isSubClassOf("Operand")) {
VT = getValueType(OperandNode->getValueAsDef("Type"));
- MadeChange |= getChild(i)->UpdateNodeType(VT, TP);
+ MadeChange |= Child->UpdateNodeType(VT, TP);
+ } else if (OperandNode->getName() == "ptr_rc") {
+ MadeChange |= Child->UpdateNodeType(MVT::iPTR, TP);
} else {
assert(0 && "Unknown operand type!");
abort();
}
- MadeChange |= getChild(i)->ApplyTypeConstraints(TP, NotRegisters);
+ MadeChange |= Child->ApplyTypeConstraints(TP, NotRegisters);
}
+
+ if (ChildNo != getNumChildren())
+ TP.error("Instruction '" + getOperator()->getName() +
+ "' was provided too many operands!");
+
return MadeChange;
} else {
assert(getOperator()->isSubClassOf("SDNodeXForm") && "Unknown node type!");
// If this node is a commutative operator, check that the LHS isn't an
// immediate.
const SDNodeInfo &NodeInfo = ISE.getSDNodeInfo(getOperator());
- if (NodeInfo.hasProperty(SDNodeInfo::SDNPCommutative)) {
+ if (NodeInfo.hasProperty(SDNPCommutative)) {
// Scan all of the operands of the node and make sure that only the last one
// is a constant node, unless the RHS also is.
if (!OnlyOnRHSOfCommutative(getChild(getNumChildren()-1))) {
error("Constant int argument should not have a name!");
Children.push_back(Node);
} else {
- std::cerr << '"';
+ cerr << '"';
Arg->dump();
- std::cerr << "\": ";
+ cerr << "\": ";
error("Unknown leaf value for tree pattern!");
}
}
OS << "]\n";
}
-void TreePattern::dump() const { print(std::cerr); }
+void TreePattern::dump() const { print(*cerr.stream()); }
}
}
+void DAGISelEmitter::ParsePredicateOperands() {
+ std::vector<Record*> PredOps =
+ Records.getAllDerivedDefinitions("PredicateOperand");
+
+ // Find some SDNode.
+ assert(!SDNodes.empty() && "No SDNodes parsed?");
+ Init *SomeSDNode = new DefInit(SDNodes.begin()->first);
+
+ for (unsigned i = 0, e = PredOps.size(); i != e; ++i) {
+ DagInit *AlwaysInfo = PredOps[i]->getValueAsDag("ExecuteAlways");
+
+ // Clone the AlwaysInfo dag node, changing the operator from 'ops' to
+ // SomeSDnode so that we can parse this.
+ std::vector<std::pair<Init*, std::string> > Ops;
+ for (unsigned op = 0, e = AlwaysInfo->getNumArgs(); op != e; ++op)
+ Ops.push_back(std::make_pair(AlwaysInfo->getArg(op),
+ AlwaysInfo->getArgName(op)));
+ DagInit *DI = new DagInit(SomeSDNode, Ops);
+
+ // Create a TreePattern to parse this.
+ TreePattern P(PredOps[i], DI, false, *this);
+ assert(P.getNumTrees() == 1 && "This ctor can only produce one tree!");
+
+ // Copy the operands over into a DAGPredicateOperand.
+ DAGPredicateOperand PredOpInfo;
+
+ TreePatternNode *T = P.getTree(0);
+ for (unsigned op = 0, e = T->getNumChildren(); op != e; ++op) {
+ TreePatternNode *TPN = T->getChild(op);
+ while (TPN->ApplyTypeConstraints(P, false))
+ /* Resolve all types */;
+
+ if (TPN->ContainsUnresolvedType())
+ throw "Value #" + utostr(i) + " of PredicateOperand '" +
+ PredOps[i]->getName() + "' doesn't have a concrete type!";
+
+ PredOpInfo.AlwaysOps.push_back(TPN);
+ }
+
+ // Insert it into the PredicateOperands map so we can find it later.
+ PredicateOperands[PredOps[i]] = PredOpInfo;
+ }
+}
+
/// HandleUse - Given "Pat" a leaf in the pattern, check to see if it is an
/// instruction input. Return true if this is a real use.
static bool HandleUse(TreePattern *I, TreePatternNode *Pat,
if (!Val)
I->error("set destination should be a register!");
- if (Val->getDef()->isSubClassOf("RegisterClass")) {
+ if (Val->getDef()->isSubClassOf("RegisterClass") ||
+ Val->getDef()->getName() == "ptr_rc") {
if (Dest->getName().empty())
I->error("set destination must have a name!");
if (InstResults.count(Dest->getName()))
std::vector<TreePatternNode*> ResultNodeOperands;
std::vector<Record*> Operands;
for (unsigned i = NumResults, e = CGI.OperandList.size(); i != e; ++i) {
- const std::string &OpName = CGI.OperandList[i].Name;
+ CodeGenInstruction::OperandInfo &Op = CGI.OperandList[i];
+ const std::string &OpName = Op.Name;
if (OpName.empty())
I->error("Operand #" + utostr(i) + " in operands list has no name!");
- if (!InstInputsCheck.count(OpName))
+ if (!InstInputsCheck.count(OpName)) {
+ // If this is an predicate operand with an ExecuteAlways set filled in,
+ // we can ignore this. When we codegen it, we will do so as always
+ // executed.
+ if (Op.Rec->isSubClassOf("PredicateOperand")) {
+ // Does it have a non-empty ExecuteAlways field? If so, ignore this
+ // operand.
+ if (!getPredicateOperand(Op.Rec).AlwaysOps.empty())
+ continue;
+ }
I->error("Operand $" + OpName +
" does not appear in the instruction pattern");
+ }
TreePatternNode *InVal = InstInputsCheck[OpName];
InstInputsCheck.erase(OpName); // It occurred, remove from map.
if (InVal->isLeaf() &&
dynamic_cast<DefInit*>(InVal->getLeafValue())) {
Record *InRec = static_cast<DefInit*>(InVal->getLeafValue())->getDef();
- if (CGI.OperandList[i].Rec != InRec &&
- !InRec->isSubClassOf("ComplexPattern"))
+ if (Op.Rec != InRec && !InRec->isSubClassOf("ComplexPattern"))
I->error("Operand $" + OpName + "'s register class disagrees"
" between the operand and pattern");
}
- Operands.push_back(CGI.OperandList[i].Rec);
+ Operands.push_back(Op.Rec);
// Construct the result for the dest-pattern operand list.
TreePatternNode *OpNode = InVal->clone();
if (I == 0) continue; // No pattern.
if (I->getNumTrees() != 1) {
- std::cerr << "CANNOT HANDLE: " << I->getRecord()->getName() << " yet!";
+ cerr << "CANNOT HANDLE: " << I->getRecord()->getName() << " yet!";
continue;
}
TreePatternNode *Pattern = I->getTree(0);
const SDNodeInfo &NodeInfo = ISE.getSDNodeInfo(N->getOperator());
// If this node is associative, reassociate.
- if (NodeInfo.hasProperty(SDNodeInfo::SDNPAssociative)) {
+ if (NodeInfo.hasProperty(SDNPAssociative)) {
// Reassociate by pulling together all of the linked operators
std::vector<TreePatternNode*> MaximalChildren;
GatherChildrenOfAssociativeOpcode(N, MaximalChildren);
CombineChildVariants(N, ChildVariants, OutVariants, ISE);
// If this node is commutative, consider the commuted order.
- if (NodeInfo.hasProperty(SDNodeInfo::SDNPCommutative)) {
+ if (NodeInfo.hasProperty(SDNPCommutative)) {
assert(N->getNumChildren()==2 &&"Commutative but doesn't have 2 children!");
// Don't count children which are actually register references.
unsigned NC = 0;
// match multiple ways. Add them to PatternsToMatch as well.
void DAGISelEmitter::GenerateVariants() {
- DEBUG(std::cerr << "Generating instruction variants.\n");
+ DOUT << "Generating instruction variants.\n";
// Loop over all of the patterns we've collected, checking to see if we can
// generate variants of the instruction, through the exploitation of
if (Variants.empty()) // No variants for this pattern.
continue;
- DEBUG(std::cerr << "FOUND VARIANTS OF: ";
- PatternsToMatch[i].getSrcPattern()->dump();
- std::cerr << "\n");
+ DOUT << "FOUND VARIANTS OF: ";
+ DEBUG(PatternsToMatch[i].getSrcPattern()->dump());
+ DOUT << "\n";
for (unsigned v = 0, e = Variants.size(); v != e; ++v) {
TreePatternNode *Variant = Variants[v];
- DEBUG(std::cerr << " VAR#" << v << ": ";
- Variant->dump();
- std::cerr << "\n");
+ DOUT << " VAR#" << v << ": ";
+ DEBUG(Variant->dump());
+ DOUT << "\n";
// Scan to see if an instruction or explicit pattern already matches this.
bool AlreadyExists = false;
for (unsigned p = 0, e = PatternsToMatch.size(); p != e; ++p) {
// Check to see if this variant already exists.
if (Variant->isIsomorphicTo(PatternsToMatch[p].getSrcPattern())) {
- DEBUG(std::cerr << " *** ALREADY EXISTS, ignoring variant.\n");
+ DOUT << " *** ALREADY EXISTS, ignoring variant.\n";
AlreadyExists = true;
break;
}
PatternsToMatch[i].getAddedComplexity()));
}
- DEBUG(std::cerr << "\n");
+ DOUT << "\n";
}
}
Record *DAGISelEmitter::getSDNodeNamed(const std::string &Name) const {
Record *N = Records.getDef(Name);
if (!N || !N->isSubClassOf("SDNode")) {
- std::cerr << "Error getting SDNode '" << Name << "'!\n";
+ cerr << "Error getting SDNode '" << Name << "'!\n";
exit(1);
}
return N;
/// NodeHasProperty - return true if TreePatternNode has the specified
/// property.
-static bool NodeHasProperty(TreePatternNode *N, SDNodeInfo::SDNP Property,
+static bool NodeHasProperty(TreePatternNode *N, SDNP Property,
DAGISelEmitter &ISE)
{
- if (N->isLeaf()) return false;
+ if (N->isLeaf()) {
+ const ComplexPattern *CP = NodeGetComplexPattern(N, ISE);
+ if (CP)
+ return CP->hasProperty(Property);
+ return false;
+ }
Record *Operator = N->getOperator();
if (!Operator->isSubClassOf("SDNode")) return false;
return NodeInfo.hasProperty(Property);
}
-static bool PatternHasProperty(TreePatternNode *N, SDNodeInfo::SDNP Property,
+static bool PatternHasProperty(TreePatternNode *N, SDNP Property,
DAGISelEmitter &ISE)
{
if (NodeHasProperty(N, Property, ISE))
std::map<std::string, Record*> OperatorMap;
// Names of all the folded nodes which produce chains.
std::vector<std::pair<std::string, unsigned> > FoldedChains;
+ // Original input chain(s).
+ std::vector<std::pair<std::string, std::string> > OrigChains;
std::set<std::string> Duplicates;
/// GeneratedCode - This is the buffer that we emit code to. The first int
/// 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 EmitMatchCode(TreePatternNode *N, TreePatternNode *P,
- const std::string &RootName,
- const std::string &ChainSuffix, bool &FoundChain) {
+ const std::string &RootName, const std::string &ChainSuffix,
+ bool &FoundChain) {
bool isRoot = (P == NULL);
// Emit instruction predicates. Each predicate is just a string for now.
if (isRoot) {
// Emit code to load the child nodes and match their contents recursively.
unsigned OpNo = 0;
- bool NodeHasChain = NodeHasProperty (N, SDNodeInfo::SDNPHasChain, ISE);
- bool HasChain = PatternHasProperty(N, SDNodeInfo::SDNPHasChain, ISE);
- bool HasOutFlag = PatternHasProperty(N, SDNodeInfo::SDNPOutFlag, ISE);
+ bool NodeHasChain = NodeHasProperty (N, SDNPHasChain, ISE);
+ bool HasChain = PatternHasProperty(N, SDNPHasChain, ISE);
bool EmittedUseCheck = false;
if (HasChain) {
if (NodeHasChain)
OpNo = 1;
if (!isRoot) {
- const SDNodeInfo &CInfo = ISE.getSDNodeInfo(N->getOperator());
// Multiple uses of actual result?
emitCheck(RootName + ".hasOneUse()");
EmittedUseCheck = true;
// / [YY]
// | ^
// [XX]-------|
- const SDNodeInfo &PInfo = ISE.getSDNodeInfo(P->getOperator());
- if (PInfo.getNumOperands() > 1 ||
- PInfo.hasProperty(SDNodeInfo::SDNPHasChain) ||
- PInfo.hasProperty(SDNodeInfo::SDNPInFlag) ||
- PInfo.hasProperty(SDNodeInfo::SDNPOptInFlag)) {
+ bool NeedCheck = false;
+ if (P != Pattern)
+ NeedCheck = true;
+ else {
+ const SDNodeInfo &PInfo = ISE.getSDNodeInfo(P->getOperator());
+ NeedCheck =
+ P->getOperator() == ISE.get_intrinsic_void_sdnode() ||
+ P->getOperator() == ISE.get_intrinsic_w_chain_sdnode() ||
+ P->getOperator() == ISE.get_intrinsic_wo_chain_sdnode() ||
+ PInfo.getNumOperands() > 1 ||
+ PInfo.hasProperty(SDNPHasChain) ||
+ PInfo.hasProperty(SDNPInFlag) ||
+ PInfo.hasProperty(SDNPOptInFlag);
+ }
+
+ if (NeedCheck) {
std::string ParentName(RootName.begin(), RootName.end()-1);
emitCheck("CanBeFoldedBy(" + RootName + ".Val, " + ParentName +
- ".Val)");
+ ".Val, N.Val)");
}
}
}
if (NodeHasChain) {
- if (FoundChain)
- emitCheck("Chain.Val == " + RootName + ".Val");
- else
+ if (FoundChain) {
+ emitCheck("(" + ChainName + ".Val == " + RootName + ".Val || "
+ "IsChainCompatible(" + ChainName + ".Val, " +
+ RootName + ".Val))");
+ OrigChains.push_back(std::make_pair(ChainName, RootName));
+ } else
FoundChain = true;
ChainName = "Chain" + ChainSuffix;
emitInit("SDOperand " + ChainName + " = " + RootName +
// FIXME: If the optional incoming flag does not exist. Then it is ok to
// fold it.
if (!isRoot &&
- (PatternHasProperty(N, SDNodeInfo::SDNPInFlag, ISE) ||
- PatternHasProperty(N, SDNodeInfo::SDNPOptInFlag, ISE) ||
- PatternHasProperty(N, SDNodeInfo::SDNPOutFlag, ISE))) {
- const SDNodeInfo &CInfo = ISE.getSDNodeInfo(N->getOperator());
+ (PatternHasProperty(N, SDNPInFlag, ISE) ||
+ PatternHasProperty(N, SDNPOptInFlag, ISE) ||
+ PatternHasProperty(N, SDNPOutFlag, ISE))) {
if (!EmittedUseCheck) {
// Multiple uses of actual result?
emitCheck(RootName + ".hasOneUse()");
emitDecl("CPTmp" + utostr(i));
emitCode("SDOperand CPTmp" + utostr(i) + ";");
}
+ if (CP->hasProperty(SDNPHasChain)) {
+ emitDecl("CPInChain");
+ emitDecl("Chain" + ChainSuffix);
+ emitCode("SDOperand CPInChain;");
+ emitCode("SDOperand Chain" + ChainSuffix + ";");
+ }
- std::string Code = Fn + "(" + RootName;
+ std::string Code = Fn + "(" + RootName + ", " + RootName;
for (unsigned i = 0; i < NumOps; i++)
Code += ", CPTmp" + utostr(i);
+ if (CP->hasProperty(SDNPHasChain)) {
+ ChainName = "Chain" + ChainSuffix;
+ Code += ", CPInChain, Chain" + ChainSuffix;
+ }
emitCheck(Code + ")");
}
}
emitCheck(RootName + ".getOpcode() == " +
CInfo.getEnumName());
EmitMatchCode(Child, Parent, RootName, ChainSuffix, FoundChain);
- if (NodeHasProperty(Child, SDNodeInfo::SDNPHasChain, ISE))
+ if (NodeHasProperty(Child, SDNPHasChain, ISE))
FoldedChains.push_back(std::make_pair(RootName, CInfo.getNumResults()));
} else {
// If this child has a name associated with it, capture it in VarMap. If
// Handle leaves of various types.
if (DefInit *DI = dynamic_cast<DefInit*>(Child->getLeafValue())) {
Record *LeafRec = DI->getDef();
- if (LeafRec->isSubClassOf("RegisterClass")) {
+ if (LeafRec->isSubClassOf("RegisterClass") ||
+ LeafRec->getName() == "ptr_rc") {
// Handle register references. Nothing to do here.
} else if (LeafRec->isSubClassOf("Register")) {
// Handle register references.
emitDecl("CPTmp" + utostr(i));
emitCode("SDOperand CPTmp" + utostr(i) + ";");
}
+ if (CP->hasProperty(SDNPHasChain)) {
+ const SDNodeInfo &PInfo = ISE.getSDNodeInfo(Parent->getOperator());
+ FoldedChains.push_back(std::make_pair("CPInChain",
+ PInfo.getNumResults()));
+ ChainName = "Chain" + ChainSuffix;
+ emitDecl("CPInChain");
+ emitDecl(ChainName);
+ emitCode("SDOperand CPInChain;");
+ emitCode("SDOperand " + ChainName + ";");
+ }
- std::string Code = Fn + "(" + RootName;
+ std::string Code = Fn + "(N, ";
+ if (CP->hasProperty(SDNPHasChain)) {
+ std::string ParentName(RootName.begin(), RootName.end()-1);
+ Code += ParentName + ", ";
+ }
+ Code += RootName;
for (unsigned i = 0; i < NumOps; i++)
Code += ", CPTmp" + utostr(i);
+ if (CP->hasProperty(SDNPHasChain))
+ Code += ", CPInChain, Chain" + ChainSuffix;
emitCheck(Code + ")");
} else if (LeafRec->getName() == "srcvalue") {
// Place holder for SRCVALUE nodes. Nothing to do here.
} else {
#ifndef NDEBUG
Child->dump();
- std::cerr << " ";
+ cerr << " ";
#endif
assert(0 && "Unknown leaf type!");
}
// value if used multiple times by this pattern result.
Val = "Tmp"+utostr(ResNo);
} else if (N->isLeaf() && (CP = NodeGetComplexPattern(N, ISE))) {
- std::string Fn = CP->getSelectFunc();
for (unsigned i = 0; i < CP->getNumOperands(); ++i) {
emitCode("AddToISelQueue(CPTmp" + utostr(i) + ");");
NodeOps.push_back("CPTmp" + utostr(i));
bool HasImpInputs = isRoot && Inst.getNumImpOperands() > 0;
bool HasImpResults = isRoot && Inst.getNumImpResults() > 0;
bool NodeHasOptInFlag = isRoot &&
- PatternHasProperty(Pattern, SDNodeInfo::SDNPOptInFlag, ISE);
+ PatternHasProperty(Pattern, SDNPOptInFlag, ISE);
bool NodeHasInFlag = isRoot &&
- PatternHasProperty(Pattern, SDNodeInfo::SDNPInFlag, ISE);
+ PatternHasProperty(Pattern, SDNPInFlag, ISE);
bool NodeHasOutFlag = HasImpResults || (isRoot &&
- PatternHasProperty(Pattern, SDNodeInfo::SDNPOutFlag, ISE));
+ PatternHasProperty(Pattern, SDNPOutFlag, ISE));
bool NodeHasChain = InstPatNode &&
- PatternHasProperty(InstPatNode, SDNodeInfo::SDNPHasChain, ISE);
+ PatternHasProperty(InstPatNode, SDNPHasChain, ISE);
bool InputHasChain = isRoot &&
- NodeHasProperty(Pattern, SDNodeInfo::SDNPHasChain, ISE);
+ NodeHasProperty(Pattern, SDNPHasChain, ISE);
+ unsigned NumResults = Inst.getNumResults();
if (NodeHasOptInFlag) {
emitCode("bool HasInFlag = "
PatResults++;
}
+ if (OrigChains.size() > 0) {
+ // The original input chain is being ignored. If it is not just
+ // pointing to the op that's being folded, we should create a
+ // TokenFactor with it and the chain of the folded op as the new chain.
+ // We could potentially be doing multiple levels of folding, in that
+ // case, the TokenFactor can have more operands.
+ emitCode("SmallVector<SDOperand, 8> InChains;");
+ for (unsigned i = 0, e = OrigChains.size(); i < e; ++i) {
+ emitCode("if (" + OrigChains[i].first + ".Val != " +
+ OrigChains[i].second + ".Val) {");
+ emitCode(" AddToISelQueue(" + OrigChains[i].first + ");");
+ emitCode(" InChains.push_back(" + OrigChains[i].first + ");");
+ emitCode("}");
+ }
+ emitCode("AddToISelQueue(" + ChainName + ");");
+ emitCode("InChains.push_back(" + ChainName + ");");
+ emitCode(ChainName + " = CurDAG->getNode(ISD::TokenFactor, MVT::Other, "
+ "&InChains[0], InChains.size());");
+ }
+
+ // Loop over all of the operands of the instruction pattern, emitting code
+ // to fill them all in. The node 'N' usually has number children equal to
+ // the number of input operands of the instruction. However, in cases
+ // where there are predicate operands for an instruction, we need to fill
+ // in the 'execute always' values. Match up the node operands to the
+ // instruction operands to do this.
std::vector<std::string> AllOps;
- for (unsigned i = 0, e = N->getNumChildren(); i != e; ++i) {
- std::vector<std::string> Ops = EmitResultCode(N->getChild(i),
- RetSelected, InFlagDecled, ResNodeDecled);
- AllOps.insert(AllOps.end(), Ops.begin(), Ops.end());
+ for (unsigned ChildNo = 0, InstOpNo = NumResults;
+ InstOpNo != II.OperandList.size(); ++InstOpNo) {
+ std::vector<std::string> Ops;
+
+ // If this is a normal operand, emit it.
+ if (!II.OperandList[InstOpNo].Rec->isSubClassOf("PredicateOperand")) {
+ Ops = EmitResultCode(N->getChild(ChildNo), RetSelected,
+ InFlagDecled, ResNodeDecled);
+ AllOps.insert(AllOps.end(), Ops.begin(), Ops.end());
+ ++ChildNo;
+ } else {
+ // Otherwise, this is a predicate operand, emit the 'execute always'
+ // operands.
+ const DAGPredicateOperand &Pred =
+ ISE.getPredicateOperand(II.OperandList[InstOpNo].Rec);
+ for (unsigned i = 0, e = Pred.AlwaysOps.size(); i != e; ++i) {
+ Ops = EmitResultCode(Pred.AlwaysOps[i], RetSelected,
+ InFlagDecled, ResNodeDecled);
+ AllOps.insert(AllOps.end(), Ops.begin(), Ops.end());
+ }
+ }
}
// Emit all the chain and CopyToReg stuff.
}
}
- unsigned NumResults = Inst.getNumResults();
unsigned ResNo = TmpNo++;
if (!isRoot || InputHasChain || NodeHasChain || NodeHasOutFlag ||
NodeHasOptInFlag) {
if (NodeHasOutFlag)
Code += ", MVT::Flag";
+ // Figure out how many fixed inputs the node has. This is important to
+ // know which inputs are the variable ones if present.
+ unsigned NumInputs = AllOps.size();
+ NumInputs += NodeHasChain;
+
// Inputs.
if (HasVarOps) {
for (unsigned i = 0, e = AllOps.size(); i != e; ++i)
}
if (HasVarOps) {
+ // Figure out whether any operands at the end of the op list are not
+ // part of the variable section.
+ std::string EndAdjust;
if (NodeHasInFlag || HasImpInputs)
- emitCode("for (unsigned i = 2, e = N.getNumOperands()-1; "
- "i != e; ++i) {");
- else if (NodeHasOptInFlag)
- emitCode("for (unsigned i = 2, e = N.getNumOperands()-"
- "(HasInFlag?1:0); i != e; ++i) {");
- else
- emitCode("for (unsigned i = 2, e = N.getNumOperands(); "
- "i != e; ++i) {");
+ EndAdjust = "-1"; // Always has one flag.
+ else if (NodeHasOptInFlag)
+ EndAdjust = "-(HasInFlag?1:0)"; // May have a flag.
+
+ emitCode("for (unsigned i = " + utostr(NumInputs) +
+ ", e = N.getNumOperands()" + EndAdjust + "; i != e; ++i) {");
+
emitCode(" AddToISelQueue(N.getOperand(i));");
emitCode(" Ops" + utostr(OpsNo) + ".push_back(N.getOperand(i));");
emitCode("}");
return NodeOps;
} else {
N->dump();
- std::cerr << "\n";
+ cerr << "\n";
throw std::string("Unknown node in result pattern!");
}
}
}
unsigned OpNo =
- (unsigned) NodeHasProperty(Pat, SDNodeInfo::SDNPHasChain, ISE);
+ (unsigned) NodeHasProperty(Pat, SDNPHasChain, ISE);
for (unsigned i = 0, e = Pat->getNumChildren(); i != e; ++i, ++OpNo)
if (InsertOneTypeCheck(Pat->getChild(i), Other->getChild(i),
Prefix + utostr(OpNo)))
bool &ResNodeDecled, bool isRoot = false) {
const CodeGenTarget &T = ISE.getTargetInfo();
unsigned OpNo =
- (unsigned) NodeHasProperty(N, SDNodeInfo::SDNPHasChain, ISE);
- bool HasInFlag = NodeHasProperty(N, SDNodeInfo::SDNPInFlag, ISE);
+ (unsigned) NodeHasProperty(N, SDNPHasChain, ISE);
+ bool HasInFlag = NodeHasProperty(N, SDNPInFlag, ISE);
for (unsigned i = 0, e = N->getNumChildren(); i != e; ++i, ++OpNo) {
TreePatternNode *Child = N->getChild(i);
if (!Child->isLeaf()) {
OS << std::string(Indent-2, ' ') << "}\n";
}
+static std::string getOpcodeName(Record *Op, DAGISelEmitter &ISE) {
+ const SDNodeInfo &OpcodeInfo = ISE.getSDNodeInfo(Op);
+ return OpcodeInfo.getEnumName();
+}
-
-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;
- }
- };
+static std::string getLegalCName(std::string OpName) {
+ std::string::size_type pos = OpName.find("::");
+ if (pos != std::string::npos)
+ OpName.replace(pos, 2, "_");
+ return OpName;
}
void DAGISelEmitter::EmitInstructionSelector(std::ostream &OS) {
- std::string InstNS = Target.inst_begin()->second.Namespace;
+ // Get the namespace to insert instructions into. Make sure not to pick up
+ // "TargetInstrInfo" by accidentally getting the namespace off the PHI
+ // instruction or something.
+ std::string InstNS;
+ for (CodeGenTarget::inst_iterator i = Target.inst_begin(),
+ e = Target.inst_end(); i != e; ++i) {
+ InstNS = i->second.Namespace;
+ if (InstNS != "TargetInstrInfo")
+ break;
+ }
+
if (!InstNS.empty()) InstNS += "::";
// Group the patterns by their top-level opcodes.
- std::map<Record*, std::vector<PatternToMatch*>,
- CompareByRecordName> PatternsByOpcode;
+ std::map<std::string, std::vector<PatternToMatch*> > PatternsByOpcode;
// All unique target node emission functions.
std::map<std::string, unsigned> EmitFunctions;
for (unsigned i = 0, e = PatternsToMatch.size(); i != e; ++i) {
TreePatternNode *Node = PatternsToMatch[i].getSrcPattern();
if (!Node->isLeaf()) {
- PatternsByOpcode[Node->getOperator()].push_back(&PatternsToMatch[i]);
+ PatternsByOpcode[getOpcodeName(Node->getOperator(), *this)].
+ push_back(&PatternsToMatch[i]);
} else {
const ComplexPattern *CP;
- if (IntInit *II =
- dynamic_cast<IntInit*>(Node->getLeafValue())) {
- PatternsByOpcode[getSDNodeNamed("imm")].push_back(&PatternsToMatch[i]);
+ if (dynamic_cast<IntInit*>(Node->getLeafValue())) {
+ PatternsByOpcode[getOpcodeName(getSDNodeNamed("imm"), *this)].
+ push_back(&PatternsToMatch[i]);
} else if ((CP = NodeGetComplexPattern(Node, *this))) {
std::vector<Record*> OpNodes = CP->getRootNodes();
for (unsigned j = 0, e = OpNodes.size(); j != e; j++) {
- PatternsByOpcode[OpNodes[j]]
- .insert(PatternsByOpcode[OpNodes[j]].begin(), &PatternsToMatch[i]);
+ PatternsByOpcode[getOpcodeName(OpNodes[j], *this)]
+ .insert(PatternsByOpcode[getOpcodeName(OpNodes[j], *this)].begin(),
+ &PatternsToMatch[i]);
}
} else {
- std::cerr << "Unrecognized opcode '";
+ cerr << "Unrecognized opcode '";
Node->dump();
- std::cerr << "' on tree pattern '";
- std::cerr <<
- PatternsToMatch[i].getDstPattern()->getOperator()->getName();
- std::cerr << "'!\n";
+ cerr << "' on tree pattern '";
+ cerr << PatternsToMatch[i].getDstPattern()->getOperator()->getName();
+ cerr << "'!\n";
exit(1);
}
}
// Emit one Select_* method for each top-level opcode. We do this instead of
// emitting one giant switch statement to support compilers where this will
// result in the recursive functions taking less stack space.
- for (std::map<Record*, std::vector<PatternToMatch*>,
- CompareByRecordName>::iterator PBOI = PatternsByOpcode.begin(),
- E = PatternsByOpcode.end(); PBOI != E; ++PBOI) {
- const std::string &OpName = PBOI->first->getName();
- const SDNodeInfo &OpcodeInfo = getSDNodeInfo(PBOI->first);
+ for (std::map<std::string, std::vector<PatternToMatch*> >::iterator
+ PBOI = PatternsByOpcode.begin(), E = PatternsByOpcode.end();
+ PBOI != E; ++PBOI) {
+ const std::string &OpName = PBOI->first;
std::vector<PatternToMatch*> &PatternsOfOp = PBOI->second;
assert(!PatternsOfOp.empty() && "No patterns but map has entry?");
for (unsigned i = 0, e = PatternsOfOp.size(); i != e; ++i) {
PatternToMatch *Pat = PatternsOfOp[i];
TreePatternNode *SrcPat = Pat->getSrcPattern();
- if (OpcodeInfo.getNumResults() == 0 && SrcPat->getNumChildren() > 0)
- SrcPat = SrcPat->getChild(0);
MVT::ValueType VT = SrcPat->getTypeNum(0);
std::map<MVT::ValueType, std::vector<PatternToMatch*> >::iterator TI =
PatternsByType.find(VT);
// If this pattern definitely matches, and if it isn't the last one, the
// patterns after it CANNOT ever match. Error out.
if (mightNotMatch == false && i != CodeForPatterns.size()-1) {
- std::cerr << "Pattern '";
- CodeForPatterns[i].first->getSrcPattern()->print(std::cerr);
- std::cerr << "' is impossible to select!\n";
+ cerr << "Pattern '";
+ CodeForPatterns[i].first->getSrcPattern()->print(*cerr.stream());
+ cerr << "' is impossible to select!\n";
exit(1);
}
}
}
// Print function.
- std::string OpVTStr = (OpVT != MVT::isVoid && OpVT != MVT::iPTR)
- ? getEnumName(OpVT).substr(5) : "" ;
+ std::string OpVTStr;
+ if (OpVT == MVT::iPTR) {
+ OpVTStr = "_iPTR";
+ } else if (OpVT == MVT::isVoid) {
+ // Nodes with a void result actually have a first result type of either
+ // Other (a chain) or Flag. Since there is no one-to-one mapping from
+ // void to this case, we handle it specially here.
+ } else {
+ OpVTStr = "_" + getEnumName(OpVT).substr(5); // Skip 'MVT::'
+ }
std::map<std::string, std::vector<std::string> >::iterator OpVTI =
OpcodeVTMap.find(OpName);
if (OpVTI == OpcodeVTMap.end()) {
} else
OpVTI->second.push_back(OpVTStr);
- OS << "SDNode *Select_" << OpName << (OpVTStr != "" ? "_" : "")
+ OS << "SDNode *Select_" << getLegalCName(OpName)
<< OpVTStr << "(const SDOperand &N) {\n";
// Loop through and reverse all of the CodeList vectors, as we will be
// If the last pattern has predicates (which could fail) emit code to
// catch the case where nothing handles a pattern.
if (mightNotMatch) {
- OS << " std::cerr << \"Cannot yet select: \";\n";
- if (OpcodeInfo.getEnumName() != "ISD::INTRINSIC_W_CHAIN" &&
- OpcodeInfo.getEnumName() != "ISD::INTRINSIC_WO_CHAIN" &&
- OpcodeInfo.getEnumName() != "ISD::INTRINSIC_VOID") {
+ OS << " cerr << \"Cannot yet select: \";\n";
+ if (OpName != "ISD::INTRINSIC_W_CHAIN" &&
+ OpName != "ISD::INTRINSIC_WO_CHAIN" &&
+ OpName != "ISD::INTRINSIC_VOID") {
OS << " N.Val->dump(CurDAG);\n";
} else {
OS << " unsigned iid = cast<ConstantSDNode>(N.getOperand("
"N.getOperand(0).getValueType() == MVT::Other))->getValue();\n"
- << " std::cerr << \"intrinsic %\"<< "
+ << " cerr << \"intrinsic %\"<< "
"Intrinsic::getName((Intrinsic::ID)iid);\n";
}
- OS << " std::cerr << '\\n';\n"
+ OS << " cerr << '\\n';\n"
<< " abort();\n"
<< " return NULL;\n";
}
<< "INSTRUCTION_LIST_END)) {\n"
<< " return NULL; // Already selected.\n"
<< " }\n\n"
+ << " MVT::ValueType NVT = N.Val->getValueType(0);\n"
<< " switch (N.getOpcode()) {\n"
<< " default: break;\n"
<< " case ISD::EntryToken: // These leaves remain the same.\n"
// Loop over all of the case statements, emiting a call to each method we
// emitted above.
- for (std::map<Record*, std::vector<PatternToMatch*>,
- CompareByRecordName>::iterator PBOI = PatternsByOpcode.begin(),
- E = PatternsByOpcode.end(); PBOI != E; ++PBOI) {
- const SDNodeInfo &OpcodeInfo = getSDNodeInfo(PBOI->first);
- const std::string &OpName = PBOI->first->getName();
+ for (std::map<std::string, std::vector<PatternToMatch*> >::iterator
+ PBOI = PatternsByOpcode.begin(), E = PatternsByOpcode.end();
+ PBOI != E; ++PBOI) {
+ const std::string &OpName = PBOI->first;
// Potentially multiple versions of select for this opcode. One for each
// ValueType of the node (or its first true operand if it doesn't produce a
// result.
std::map<std::string, std::vector<std::string> >::iterator OpVTI =
OpcodeVTMap.find(OpName);
std::vector<std::string> &OpVTs = OpVTI->second;
- OS << " case " << OpcodeInfo.getEnumName() << ": {\n";
+ OS << " case " << OpName << ": {\n";
if (OpVTs.size() == 1) {
std::string &VTStr = OpVTs[0];
- OS << " return Select_" << OpName
- << (VTStr != "" ? "_" : "") << VTStr << "(N);\n";
+ OS << " return Select_" << getLegalCName(OpName)
+ << VTStr << "(N);\n";
} else {
- if (OpcodeInfo.getNumResults())
- OS << " MVT::ValueType NVT = N.Val->getValueType(0);\n";
- else if (OpcodeInfo.hasProperty(SDNodeInfo::SDNPHasChain))
- OS << " MVT::ValueType NVT = (N.getNumOperands() > 1) ?"
- << " N.getOperand(1).Val->getValueType(0) : MVT::isVoid;\n";
- else
- OS << " MVT::ValueType NVT = (N.getNumOperands() > 0) ?"
- << " N.getOperand(0).Val->getValueType(0) : MVT::isVoid;\n";
- int Default = -1;
+ // Keep track of whether we see a pattern that has an iPtr result.
+ bool HasPtrPattern = false;
+ bool HasDefaultPattern = false;
+
OS << " switch (NVT) {\n";
for (unsigned i = 0, e = OpVTs.size(); i < e; ++i) {
std::string &VTStr = OpVTs[i];
- if (VTStr == "") {
- Default = i;
+ if (VTStr.empty()) {
+ HasDefaultPattern = true;
+ continue;
+ }
+
+ // If this is a match on iPTR: don't emit it directly, we need special
+ // code.
+ if (VTStr == "_iPTR") {
+ HasPtrPattern = true;
continue;
}
- OS << " case MVT::" << VTStr << ":\n"
- << " return Select_" << OpName
- << "_" << VTStr << "(N);\n";
+ OS << " case MVT::" << VTStr.substr(1) << ":\n"
+ << " return Select_" << getLegalCName(OpName)
+ << VTStr << "(N);\n";
}
OS << " default:\n";
- if (Default != -1)
- OS << " return Select_" << OpName << "(N);\n";
- else
- OS << " break;\n";
+
+ // If there is an iPTR result version of this pattern, emit it here.
+ if (HasPtrPattern) {
+ OS << " if (NVT == TLI.getPointerTy())\n";
+ OS << " return Select_" << getLegalCName(OpName) <<"_iPTR(N);\n";
+ }
+ if (HasDefaultPattern) {
+ OS << " return Select_" << getLegalCName(OpName) << "(N);\n";
+ }
+ OS << " break;\n";
OS << " }\n";
OS << " break;\n";
}
}
OS << " } // end of big switch.\n\n"
- << " std::cerr << \"Cannot yet select: \";\n"
+ << " cerr << \"Cannot yet select: \";\n"
<< " if (N.getOpcode() != ISD::INTRINSIC_W_CHAIN &&\n"
<< " N.getOpcode() != ISD::INTRINSIC_WO_CHAIN &&\n"
<< " N.getOpcode() != ISD::INTRINSIC_VOID) {\n"
<< " } else {\n"
<< " unsigned iid = cast<ConstantSDNode>(N.getOperand("
"N.getOperand(0).getValueType() == MVT::Other))->getValue();\n"
- << " std::cerr << \"intrinsic %\"<< "
- "Intrinsic::getName((Intrinsic::ID)iid);\n"
+ << " cerr << \"intrinsic %\"<< "
+ "Intrinsic::getName((Intrinsic::ID)iid);\n"
<< " }\n"
- << " std::cerr << '\\n';\n"
+ << " cerr << '\\n';\n"
<< " abort();\n"
<< " return NULL;\n"
<< "}\n";
OS << "/// Dummy parameter to ReplaceAllUsesOfValueWith().\n"
<< "std::vector<SDNode*> ISelKilled;\n\n";
+ OS << "/// IsChainCompatible - Returns true if Chain is Op or Chain does\n";
+ OS << "/// not reach Op.\n";
+ OS << "static bool IsChainCompatible(SDNode *Chain, SDNode *Op) {\n";
+ OS << " if (Chain->getOpcode() == ISD::EntryToken)\n";
+ OS << " return true;\n";
+ OS << " else if (Chain->getOpcode() == ISD::TokenFactor)\n";
+ OS << " return false;\n";
+ OS << " else if (Chain->getNumOperands() > 0) {\n";
+ OS << " SDOperand C0 = Chain->getOperand(0);\n";
+ OS << " if (C0.getValueType() == MVT::Other)\n";
+ OS << " return C0.Val != Op && IsChainCompatible(C0.Val, Op);\n";
+ OS << " }\n";
+ OS << " return true;\n";
+ OS << "}\n";
+
OS << "/// Sorting functions for the selection queue.\n"
<< "struct isel_sort : public std::binary_function"
<< "<SDNode*, SDNode*, bool> {\n"
OS << " if (NumKilled) {\n";
OS << " for (unsigned i = 0; i != NumKilled; ++i) {\n";
OS << " SDNode *Temp = ISelKilled[i];\n";
- OS << " std::remove(ISelQueue.begin(), ISelQueue.end(), Temp);\n";
+ OS << " ISelQueue.erase(std::remove(ISelQueue.begin(), ISelQueue.end(), "
+ << "Temp), ISelQueue.end());\n";
OS << " };\n";
OS << " std::make_heap(ISelQueue.begin(), ISelQueue.end(), isel_sort());\n";
OS << " ISelKilled.clear();\n";
OS << " RemoveKilled();\n";
OS << "}\n\n";
- OS << "void DeleteNode(SDNode *N) {\n";
- OS << " CurDAG->DeleteNode(N);\n";
- OS << " for (SDNode::op_iterator I = N->op_begin(), E = N->op_end(); "
- << "I != E; ++I) {\n";
- OS << " SDNode *Operand = I->Val;\n";
- OS << " if (Operand->use_empty())\n";
- OS << " DeleteNode(Operand);\n";
- OS << " }\n";
- OS << "}\n";
-
OS << "// SelectRoot - Top level entry to DAG isel.\n";
OS << "SDOperand SelectRoot(SDOperand Root) {\n";
OS << " SelectRootInit();\n";
OS << " if (ResNode != Node) {\n";
OS << " if (ResNode)\n";
OS << " ReplaceUses(Node, ResNode);\n";
- OS << " if (Node->use_empty()) // Don't delete EntryToken, etc.\n";
- OS << " DeleteNode(Node);\n";
+ OS << " if (Node->use_empty()) { // Don't delete EntryToken, etc.\n";
+ OS << " CurDAG->RemoveDeadNode(Node, ISelKilled);\n";
+ OS << " RemoveKilled();\n";
+ OS << " }\n";
OS << " }\n";
OS << " }\n";
OS << " }\n";
ParseNodeTransforms(OS);
ParseComplexPatterns();
ParsePatternFragments(OS);
+ ParsePredicateOperands();
ParseInstructions();
ParsePatterns();
// multiple ways. Add them to PatternsToMatch as well.
GenerateVariants();
-
- DEBUG(std::cerr << "\n\nALL PATTERNS TO MATCH:\n\n";
- for (unsigned i = 0, e = PatternsToMatch.size(); i != e; ++i) {
- std::cerr << "PATTERN: "; PatternsToMatch[i].getSrcPattern()->dump();
- std::cerr << "\nRESULT: ";PatternsToMatch[i].getDstPattern()->dump();
- std::cerr << "\n";
- });
+ DOUT << "\n\nALL PATTERNS TO MATCH:\n\n";
+ for (unsigned i = 0, e = PatternsToMatch.size(); i != e; ++i) {
+ DOUT << "PATTERN: "; DEBUG(PatternsToMatch[i].getSrcPattern()->dump());
+ DOUT << "\nRESULT: "; DEBUG(PatternsToMatch[i].getDstPattern()->dump());
+ DOUT << "\n";
+ }
// At this point, we have full information about the 'Patterns' we need to
// parse, both implicitly from instructions as well as from explicit pattern