- Clean up tablegen dag isel generator code.

- Clean up the code generated by tablegen:
  * AddToISelQueue now takes one argument.
  * ComplexPattern matching condition can now be shared.
  * Eliminate passing unnecessary arguments to emit routines.
  * Eliminate some unneeded SDOperand declarations in select routines.
  * Other minor clean ups.
- This reduces foot print slightly: X86ISelDAGToDAG.o is reduced from 971k
  to 823k.

llvm-svn: 29892
This commit is contained in:
Evan Cheng 2006-08-26 00:59:04 +00:00
parent 26bde5d791
commit b96b719724
2 changed files with 241 additions and 238 deletions

View File

@ -1909,7 +1909,6 @@ void DAGISelEmitter::GenerateVariants() {
}
}
// NodeIsComplexPattern - return true if N is a leaf node and a subclass of
// ComplexPattern.
static bool NodeIsComplexPattern(TreePatternNode *N)
@ -2120,11 +2119,11 @@ private:
std::vector<std::pair<std::string, unsigned> > FoldedChains;
std::set<std::string> Duplicates;
/// GeneratedCode - This is the buffer that we emit code to. The first bool
/// GeneratedCode - This is the buffer that we emit code to. The first int
/// indicates whether this is an exit predicate (something that should be
/// tested, and if true, the match fails) [when true] or normal code to emit
/// [when false].
std::vector<std::pair<bool, std::string> > &GeneratedCode;
/// tested, and if true, the match fails) [when 1], or normal code to emit
/// [when 0], or initialization code to emit [when 2].
std::vector<std::pair<unsigned, std::string> > &GeneratedCode;
/// GeneratedDecl - This is the set of all SDOperand declarations needed for
/// the set of patterns for each top-level opcode.
std::set<std::pair<unsigned, std::string> > &GeneratedDecl;
@ -2140,11 +2139,15 @@ private:
void emitCheck(const std::string &S) {
if (!S.empty())
GeneratedCode.push_back(std::make_pair(true, S));
GeneratedCode.push_back(std::make_pair(1, S));
}
void emitCode(const std::string &S) {
if (!S.empty())
GeneratedCode.push_back(std::make_pair(false, S));
GeneratedCode.push_back(std::make_pair(0, S));
}
void emitInit(const std::string &S) {
if (!S.empty())
GeneratedCode.push_back(std::make_pair(2, S));
}
void emitDecl(const std::string &S, unsigned T=0) {
assert(!S.empty() && "Invalid declaration");
@ -2161,12 +2164,13 @@ private:
public:
PatternCodeEmitter(DAGISelEmitter &ise, ListInit *preds,
TreePatternNode *pattern, TreePatternNode *instr,
std::vector<std::pair<bool, std::string> > &gc,
std::vector<std::pair<unsigned, std::string> > &gc,
std::set<std::pair<unsigned, std::string> > &gd,
std::vector<std::string> &to,
std::vector<std::string> &tv)
: ISE(ise), Predicates(preds), Pattern(pattern), Instruction(instr),
GeneratedCode(gc), GeneratedDecl(gd), TargetOpcodes(to), TargetVTs(tv),
GeneratedCode(gc), GeneratedDecl(gd),
TargetOpcodes(to), TargetVTs(tv),
TmpNo(0), OpcNo(0), VTNo(0) {}
/// EmitMatchCode - Emit a matcher for N, going to the label for PatternNo
@ -2290,8 +2294,7 @@ public:
else
FoundChain = true;
ChainName = "Chain" + ChainSuffix;
emitDecl(ChainName);
emitCode(ChainName + " = " + RootName +
emitInit("SDOperand " + ChainName + " = " + RootName +
".getOperand(0);");
}
}
@ -2312,12 +2315,12 @@ public:
}
}
const ComplexPattern *CP;
for (unsigned i = 0, e = N->getNumChildren(); i != e; ++i, ++OpNo) {
emitDecl(RootName + utostr(OpNo));
emitCode(RootName + utostr(OpNo) + " = " +
emitInit("SDOperand " + RootName + utostr(OpNo) + " = " +
RootName + ".getOperand(" +utostr(OpNo) + ");");
TreePatternNode *Child = N->getChild(i);
TreePatternNode *Child = N->getChild(i);
if (!Child->isLeaf()) {
// If it's not a leaf, recursively match.
const SDNodeInfo &CInfo = ISE.getSDNodeInfo(Child->getOperator());
@ -2354,7 +2357,19 @@ public:
} else if (LeafRec->isSubClassOf("Register")) {
// Handle register references.
} else if (LeafRec->isSubClassOf("ComplexPattern")) {
// Handle complex pattern. Nothing to do here.
// Handle complex pattern.
CP = NodeGetComplexPattern(Child, ISE);
std::string Fn = CP->getSelectFunc();
unsigned NumOps = CP->getNumOperands();
for (unsigned i = 0; i < NumOps; ++i) {
emitDecl("CPTmp" + utostr(i));
emitCode("SDOperand CPTmp" + utostr(i) + ";");
}
std::string Code = Fn + "(" + RootName + utostr(OpNo);
for (unsigned i = 0; i < NumOps; i++)
Code += ", CPTmp" + utostr(i);
emitCheck(Code + ")");
} else if (LeafRec->getName() == "srcvalue") {
// Place holder for SRCVALUE nodes. Nothing to do here.
} else if (LeafRec->isSubClassOf("ValueType")) {
@ -2389,6 +2404,21 @@ public:
}
}
// Handle cases when root is a complex pattern.
if (isRoot && N->isLeaf() && (CP = NodeGetComplexPattern(N, ISE))) {
std::string Fn = CP->getSelectFunc();
unsigned NumOps = CP->getNumOperands();
for (unsigned i = 0; i < NumOps; ++i) {
emitDecl("CPTmp" + utostr(i));
emitCode("SDOperand CPTmp" + utostr(i) + ";");
}
std::string Code = Fn + "(" + RootName;
for (unsigned i = 0; i < NumOps; i++)
Code += ", CPTmp" + utostr(i);
emitCheck(Code + ")");
}
// If there is a node predicate for this, emit the call.
if (!N->getPredicateFn().empty())
emitCheck(N->getPredicateFn() + "(" + RootName + ".Val)");
@ -2396,9 +2426,12 @@ public:
/// EmitResultCode - Emit the action for a pattern. Now that it has matched
/// we actually have to build a DAG!
std::pair<unsigned, unsigned>
EmitResultCode(TreePatternNode *N, bool &RetSelected, bool LikeLeaf = false,
bool isRoot = false) {
std::vector<std::string>
EmitResultCode(TreePatternNode *N, bool RetSelected,
bool InFlagDecled, bool ResNodeDecled,
bool LikeLeaf = false, bool isRoot = false) {
// List of arguments of getTargetNode() or SelectNodeTo().
std::vector<std::string> NodeOps;
// This is something selected from the pattern we matched.
if (!N->getName().empty()) {
std::string &Val = VariableMap[N->getName()];
@ -2406,12 +2439,12 @@ public:
"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.
return std::make_pair(1, atoi(Val.c_str()+3));
NodeOps.push_back(Val);
return NodeOps;
}
const ComplexPattern *CP;
unsigned ResNo = TmpNo++;
unsigned NumRes = 1;
if (!N->isLeaf() && N->getOperator()->getName() == "imm") {
assert(N->getExtTypes().size() == 1 && "Multiple types not handled!");
std::string CastType;
@ -2423,107 +2456,101 @@ public:
case MVT::i32: CastType = "unsigned"; break;
case MVT::i64: CastType = "uint64_t"; break;
}
emitDecl("Tmp" + utostr(ResNo));
emitCode("Tmp" + utostr(ResNo) +
emitCode("SDOperand Tmp" + utostr(ResNo) +
" = CurDAG->getTargetConstant(((" + CastType +
") cast<ConstantSDNode>(" + Val + ")->getValue()), " +
getEnumName(N->getTypeNum(0)) + ");");
NodeOps.push_back("Tmp" + utostr(ResNo));
// 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);
} else if (!N->isLeaf() && N->getOperator()->getName() == "texternalsym"){
Record *Op = OperatorMap[N->getName()];
// Transform ExternalSymbol to TargetExternalSymbol
if (Op && Op->getName() == "externalsym") {
emitDecl("Tmp" + utostr(ResNo));
emitCode("Tmp" + utostr(ResNo) + " = CurDAG->getTarget"
emitCode("SDOperand Tmp" + utostr(ResNo) + " = CurDAG->getTarget"
"ExternalSymbol(cast<ExternalSymbolSDNode>(" +
Val + ")->getSymbol(), " +
getEnumName(N->getTypeNum(0)) + ");");
NodeOps.push_back("Tmp" + utostr(ResNo));
// 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);
} else {
emitDecl("Tmp" + utostr(ResNo));
emitCode("Tmp" + utostr(ResNo) + " = " + Val + ";");
NodeOps.push_back(Val);
}
} else if (!N->isLeaf() && N->getOperator()->getName() == "tglobaladdr") {
Record *Op = OperatorMap[N->getName()];
// Transform GlobalAddress to TargetGlobalAddress
if (Op && Op->getName() == "globaladdr") {
emitDecl("Tmp" + utostr(ResNo));
emitCode("Tmp" + utostr(ResNo) + " = CurDAG->getTarget"
emitCode("SDOperand Tmp" + utostr(ResNo) + " = CurDAG->getTarget"
"GlobalAddress(cast<GlobalAddressSDNode>(" + Val +
")->getGlobal(), " + getEnumName(N->getTypeNum(0)) +
");");
} else {
emitDecl("Tmp" + utostr(ResNo));
emitCode("Tmp" + utostr(ResNo) + " = " + Val + ";");
}
} else if (!N->isLeaf() && N->getOperator()->getName() == "texternalsym"){
emitDecl("Tmp" + utostr(ResNo));
emitCode("Tmp" + utostr(ResNo) + " = " + Val + ";");
} else if (!N->isLeaf() && N->getOperator()->getName() == "tconstpool") {
emitDecl("Tmp" + utostr(ResNo));
emitCode("Tmp" + utostr(ResNo) + " = " + Val + ";");
} else if (N->isLeaf() && (CP = NodeGetComplexPattern(N, ISE))) {
std::string Fn = CP->getSelectFunc();
NumRes = CP->getNumOperands();
for (unsigned i = 0; i < NumRes; ++i)
emitDecl("CPTmp" + utostr(i+ResNo));
std::string Code = Fn + "(" + Val;
for (unsigned i = 0; i < NumRes; i++)
Code += ", CPTmp" + utostr(i + ResNo);
emitCheck(Code + ")");
for (unsigned i = 0; i < NumRes; ++i) {
emitDecl("Tmp" + utostr(i+ResNo));
emitCode("AddToQueue(Tmp" + utostr(i+ResNo) + ", CPTmp" +
utostr(i+ResNo) + ");");
}
TmpNo = ResNo + NumRes;
} else {
emitDecl("Tmp" + utostr(ResNo));
// This node, probably wrapped in a SDNodeXForms, behaves like a leaf
// node even if it isn't one. Don't select it.
if (LikeLeaf)
emitCode("Tmp" + utostr(ResNo) + " = " + Val + ";");
else {
emitCode("AddToQueue(Tmp" + utostr(ResNo) + ", " + Val + ");");
if (isRoot && N->isLeaf()) {
emitCode("ReplaceUses(N, Tmp" + utostr(ResNo) + ");");
emitCode("Result = Tmp" + utostr(ResNo) + ";");
emitCode("return NULL;");
}
}
}
NodeOps.push_back("Tmp" + utostr(ResNo));
// 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 std::make_pair(NumRes, ResNo);
} else {
NodeOps.push_back(Val);
}
} else if (!N->isLeaf() && N->getOperator()->getName() == "texternalsym"){
NodeOps.push_back(Val);
// 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);
} else if (!N->isLeaf() && N->getOperator()->getName() == "tconstpool") {
NodeOps.push_back(Val);
// 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);
} 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));
}
} else {
// This node, probably wrapped in a SDNodeXForm, behaves like a leaf
// node even if it isn't one. Don't select it.
if (!LikeLeaf) {
emitCode("AddToISelQueue(" + Val + ");");
if (isRoot && N->isLeaf()) {
emitCode("ReplaceUses(N, " + Val + ");");
emitCode("Result = " + Val + ";");
emitCode("return NULL;");
}
}
NodeOps.push_back(Val);
}
return NodeOps;
}
if (N->isLeaf()) {
// If this is an explicit register reference, handle it.
if (DefInit *DI = dynamic_cast<DefInit*>(N->getLeafValue())) {
unsigned ResNo = TmpNo++;
if (DI->getDef()->isSubClassOf("Register")) {
emitDecl("Tmp" + utostr(ResNo));
emitCode("Tmp" + utostr(ResNo) + " = CurDAG->getRegister(" +
emitCode("SDOperand Tmp" + utostr(ResNo) + " = CurDAG->getRegister(" +
ISE.getQualifiedName(DI->getDef()) + ", " +
getEnumName(N->getTypeNum(0)) + ");");
return std::make_pair(1, ResNo);
NodeOps.push_back("Tmp" + utostr(ResNo));
return NodeOps;
}
} else if (IntInit *II = dynamic_cast<IntInit*>(N->getLeafValue())) {
unsigned ResNo = TmpNo++;
assert(N->getExtTypes().size() == 1 && "Multiple types not handled!");
emitDecl("Tmp" + utostr(ResNo));
emitCode("Tmp" + utostr(ResNo) +
emitCode("SDOperand Tmp" + utostr(ResNo) +
" = CurDAG->getTargetConstant(" + itostr(II->getValue()) +
", " + getEnumName(N->getTypeNum(0)) + ");");
return std::make_pair(1, ResNo);
NodeOps.push_back("Tmp" + utostr(ResNo));
return NodeOps;
}
#ifndef NDEBUG
N->dump();
#endif
assert(0 && "Unknown leaf type!");
return std::make_pair(1, ~0U);
return NodeOps;
}
Record *Op = N->getOperator();
@ -2552,11 +2579,8 @@ public:
bool InputHasChain = isRoot &&
NodeHasProperty(Pattern, SDNodeInfo::SDNPHasChain, ISE);
if (NodeHasInFlag || NodeHasOutFlag || NodeHasOptInFlag || HasImpInputs)
emitDecl("InFlag");
if (NodeHasOptInFlag) {
emitDecl("HasInFlag", 2);
emitCode("HasInFlag = "
emitCode("bool HasInFlag = "
"(N.getOperand(N.getNumOperands()-1).getValueType() == MVT::Flag);");
}
if (HasVarOps)
@ -2570,47 +2594,29 @@ public:
PatResults++;
}
// Determine operand emission order. Complex pattern first.
std::vector<std::pair<unsigned, TreePatternNode*> > EmitOrder;
std::vector<std::pair<unsigned, TreePatternNode*> >::iterator OI;
std::vector<std::string> AllOps;
for (unsigned i = 0, e = N->getNumChildren(); i != e; ++i) {
TreePatternNode *Child = N->getChild(i);
if (i == 0) {
EmitOrder.push_back(std::make_pair(i, Child));
OI = EmitOrder.begin();
} else if (NodeIsComplexPattern(Child)) {
OI = EmitOrder.insert(OI, std::make_pair(i, Child));
} else {
EmitOrder.push_back(std::make_pair(i, Child));
}
}
// Emit all of the operands.
std::vector<std::pair<unsigned, unsigned> > NumTemps(EmitOrder.size());
for (unsigned i = 0, e = EmitOrder.size(); i != e; ++i) {
unsigned OpOrder = EmitOrder[i].first;
TreePatternNode *Child = EmitOrder[i].second;
std::pair<unsigned, unsigned> NumTemp =
EmitResultCode(Child, RetSelected);
NumTemps[OpOrder] = NumTemp;
}
// List all the operands in the right order.
std::vector<unsigned> Ops;
for (unsigned i = 0, e = NumTemps.size(); i != e; i++) {
for (unsigned j = 0; j < NumTemps[i].first; j++)
Ops.push_back(NumTemps[i].second + j);
std::vector<std::string> Ops = EmitResultCode(N->getChild(i),
RetSelected, InFlagDecled, ResNodeDecled);
AllOps.insert(AllOps.end(), Ops.begin(), Ops.end());
}
// Emit all the chain and CopyToReg stuff.
bool ChainEmitted = NodeHasChain;
if (NodeHasChain)
emitCode("AddToQueue(" + ChainName + ", " + ChainName + ");");
emitCode("AddToISelQueue(" + ChainName + ");");
if (NodeHasInFlag || HasImpInputs)
EmitInFlagSelectCode(Pattern, "N", ChainEmitted, true);
EmitInFlagSelectCode(Pattern, "N", ChainEmitted,
InFlagDecled, ResNodeDecled, true);
if (NodeHasOptInFlag) {
emitCode("if (HasInFlag)");
emitCode(" AddToQueue(InFlag, N.getOperand(N.getNumOperands()-1));");
if (!InFlagDecled) {
emitCode("SDOperand InFlag(0, 0);");
InFlagDecled = true;
}
emitCode("if (HasInFlag) {");
emitCode(" InFlag = N.getOperand(N.getNumOperands()-1);");
emitCode(" AddToISelQueue(InFlag);");
emitCode("}");
}
unsigned NumResults = Inst.getNumResults();
@ -2622,11 +2628,12 @@ public:
std::string NodeName;
if (!isRoot) {
NodeName = "Tmp" + utostr(ResNo);
emitDecl(NodeName);
Code2 = NodeName + " = SDOperand(";
Code2 = "SDOperand " + NodeName + " = SDOperand(";
} else {
NodeName = "ResNode";
emitDecl(NodeName, true);
if (!ResNodeDecled)
Code2 = "SDNode *" + NodeName + " = ";
else
Code2 = NodeName + " = ";
}
Code = "CurDAG->getTargetNode(Opc" + utostr(OpcNo);
@ -2644,12 +2651,14 @@ public:
Code += ", MVT::Flag";
// Inputs.
for (unsigned i = 0, e = Ops.size(); i != e; ++i) {
for (unsigned i = 0, e = AllOps.size(); i != e; ++i) {
std::string OpName = AllOps[i];
if (HasVarOps)
emitCode("Ops.push_back(Tmp" + utostr(Ops[i]) + ");");
emitCode("Ops.push_back(" + OpName + ");");
else
Code += ", Tmp" + utostr(Ops[i]);
Code += ", " + OpName;
}
//AllOps.clear();
if (HasVarOps) {
if (NodeHasInFlag || HasImpInputs)
@ -2661,9 +2670,8 @@ public:
else
emitCode("for (unsigned i = 2, e = N.getNumOperands(); "
"i != e; ++i) {");
emitCode(" SDOperand VarOp(0, 0);");
emitCode(" AddToQueue(VarOp, N.getOperand(i));");
emitCode(" Ops.push_back(VarOp);");
emitCode(" AddToISelQueue(N.getOperand(i));");
emitCode(" Ops.push_back(N.getOperand(i));");
emitCode("}");
}
@ -2674,19 +2682,28 @@ public:
Code += ", " + ChainName;
}
if (NodeHasInFlag || HasImpInputs) {
if (HasVarOps)
if (!InFlagDecled) {
emitCode("SDOperand InFlag(0, 0);");
InFlagDecled = true;
}
if (HasVarOps) {
emitCode("Ops.push_back(InFlag);");
else
} else
Code += ", InFlag";
} else if (NodeHasOptInFlag && HasVarOps) {
if (!InFlagDecled) {
emitCode("SDOperand InFlag(0, 0);");
InFlagDecled = true;
}
emitCode("if (HasInFlag)");
emitCode(" Ops.push_back(InFlag);");
}
if (HasVarOps)
Code += ", &Ops[0], Ops.size()";
else if (NodeHasOptInFlag)
else if (NodeHasOptInFlag) {
Code = "HasInFlag ? " + Code + ", InFlag) : " + Code;
}
if (!isRoot)
Code += "), 0";
@ -2701,15 +2718,23 @@ public:
emitCode(ChainName + " = SDOperand(" + NodeName +
", " + utostr(PatResults) + ");");
if (!isRoot)
return std::make_pair(1, ResNo);
if (!isRoot) {
NodeOps.push_back("Tmp" + utostr(ResNo));
return NodeOps;
}
bool NeedReplace = false;
if (NodeHasOutFlag)
if (NodeHasOutFlag) {
if (!InFlagDecled) {
emitCode("SDOperand InFlag = SDOperand(ResNode, " +
utostr(NumResults + (unsigned)NodeHasChain) + ");");
InFlagDecled = true;
} else
emitCode("InFlag = SDOperand(ResNode, " +
utostr(NumResults + (unsigned)NodeHasChain) + ");");
}
if (HasImpResults && EmitCopyFromRegs(N, ChainEmitted)) {
if (HasImpResults && EmitCopyFromRegs(N, ResNodeDecled, ChainEmitted)) {
emitCode("ReplaceUses(SDOperand(N.Val, 0), SDOperand(ResNode, 0));");
NumResults = 1;
}
@ -2780,56 +2805,41 @@ public:
else
emitCode("return NULL;");
} else {
// If this instruction is the root, and if there is only one use of it,
// use SelectNodeTo instead of getTargetNode to avoid an allocation.
emitCode("if (N.Val->hasOneUse()) {");
std::string Code = " Result = CurDAG->SelectNodeTo(N.Val, Opc" +
std::string Code = "Result = CurDAG->SelectNodeTo(N.Val, Opc" +
utostr(OpcNo);
if (N->getTypeNum(0) != MVT::isVoid)
Code += ", VT" + utostr(VTNo);
if (NodeHasOutFlag)
Code += ", MVT::Flag";
for (unsigned i = 0, e = Ops.size(); i != e; ++i)
Code += ", Tmp" + utostr(Ops[i]);
for (unsigned i = 0, e = AllOps.size(); i != e; ++i)
Code += ", " + AllOps[i];
//AllOps.clear();
if (NodeHasInFlag || HasImpInputs)
Code += ", InFlag";
emitCode(Code + ");");
emitCode("} else {");
emitDecl("ResNode", 1);
Code = " ResNode = CurDAG->getTargetNode(Opc" + utostr(OpcNo);
emitCode("return Result.Val;");
emitOpcode(II.Namespace + "::" + II.TheDef->getName());
if (N->getTypeNum(0) != MVT::isVoid) {
Code += ", VT" + utostr(VTNo);
if (N->getTypeNum(0) != MVT::isVoid)
emitVT(getEnumName(N->getTypeNum(0)));
}
if (NodeHasOutFlag)
Code += ", MVT::Flag";
for (unsigned i = 0, e = Ops.size(); i != e; ++i)
Code += ", Tmp" + utostr(Ops[i]);
if (NodeHasInFlag || HasImpInputs)
Code += ", InFlag";
emitCode(Code + ");");
emitCode(" Result = SDOperand(ResNode, 0);");
emitCode("}");
emitCode("return Result.Val;");
}
return std::make_pair(1, ResNo);
return NodeOps;
} else if (Op->isSubClassOf("SDNodeXForm")) {
assert(N->getNumChildren() == 1 && "node xform should have one child!");
// PatLeaf node - the operand may or may not be a leaf node. But it should
// behave like one.
unsigned OpVal = EmitResultCode(N->getChild(0), RetSelected, true).second;
std::vector<std::string> Ops =
EmitResultCode(N->getChild(0), RetSelected, InFlagDecled,
ResNodeDecled, true);
unsigned ResNo = TmpNo++;
emitDecl("Tmp" + utostr(ResNo));
emitCode("Tmp" + utostr(ResNo) + " = Transform_" + Op->getName()
+ "(Tmp" + utostr(OpVal) + ".Val);");
emitCode("SDOperand Tmp" + utostr(ResNo) + " = Transform_" + Op->getName()
+ "(" + Ops.back() + ".Val);");
NodeOps.push_back("Tmp" + utostr(ResNo));
if (isRoot) {
//emitCode("ReplaceUses(N, Tmp" + utostr(ResNo) + ");");
emitCode("Result = Tmp" + utostr(ResNo) + ";");
emitCode("return Result.Val;");
}
return std::make_pair(1, ResNo);
return NodeOps;
} else {
N->dump();
std::cerr << "\n";
@ -2867,7 +2877,8 @@ private:
/// EmitInFlagSelectCode - Emit the flag operands for the DAG that is
/// being built.
void EmitInFlagSelectCode(TreePatternNode *N, const std::string &RootName,
bool &ChainEmitted, bool isRoot = false) {
bool &ChainEmitted, bool &InFlagDecled,
bool &ResNodeDecled, bool isRoot = false) {
const CodeGenTarget &T = ISE.getTargetInfo();
unsigned OpNo =
(unsigned) NodeHasProperty(N, SDNodeInfo::SDNPHasChain, ISE);
@ -2875,7 +2886,8 @@ private:
for (unsigned i = 0, e = N->getNumChildren(); i != e; ++i, ++OpNo) {
TreePatternNode *Child = N->getChild(i);
if (!Child->isLeaf()) {
EmitInFlagSelectCode(Child, RootName + utostr(OpNo), ChainEmitted);
EmitInFlagSelectCode(Child, RootName + utostr(OpNo), ChainEmitted,
InFlagDecled, ResNodeDecled);
} else {
if (DefInit *DI = dynamic_cast<DefInit*>(Child->getLeafValue())) {
if (!Child->getName().empty()) {
@ -2889,20 +2901,29 @@ private:
if (RR->isSubClassOf("Register")) {
MVT::ValueType RVT = getRegisterValueType(RR, T);
if (RVT == MVT::Flag) {
emitCode("AddToQueue(InFlag, " + RootName + utostr(OpNo) + ");");
if (!InFlagDecled) {
emitCode("SDOperand InFlag = " + RootName + utostr(OpNo) + ";");
InFlagDecled = true;
} else
emitCode("InFlag = " + RootName + utostr(OpNo) + ";");
emitCode("AddToISelQueue(InFlag);");
} else {
if (!ChainEmitted) {
emitDecl("Chain");
emitCode("Chain = CurDAG->getEntryNode();");
emitCode("SDOperand Chain = CurDAG->getEntryNode();");
ChainName = "Chain";
ChainEmitted = true;
}
emitCode("AddToQueue(" + RootName + utostr(OpNo) + ", " +
RootName + utostr(OpNo) + ");");
emitCode("ResNode = CurDAG->getCopyToReg(" + ChainName +
emitCode("AddToISelQueue(" + RootName + utostr(OpNo) + ");");
if (!InFlagDecled) {
emitCode("SDOperand InFlag(0, 0);");
InFlagDecled = true;
}
std::string Decl = (!ResNodeDecled) ? "SDNode *" : "";
emitCode(Decl + "ResNode = CurDAG->getCopyToReg(" + ChainName +
", CurDAG->getRegister(" + ISE.getQualifiedName(RR) +
", " + getEnumName(RVT) + "), " +
RootName + utostr(OpNo) + ", InFlag).Val;");
ResNodeDecled = true;
emitCode(ChainName + " = SDOperand(ResNode, 0);");
emitCode("InFlag = SDOperand(ResNode, 1);");
}
@ -2911,15 +2932,23 @@ private:
}
}
if (HasInFlag)
emitCode("AddToQueue(InFlag, " + RootName +
".getOperand(" + utostr(OpNo) + "));");
if (HasInFlag) {
if (!InFlagDecled) {
emitCode("SDOperand InFlag = " + RootName +
".getOperand(" + utostr(OpNo) + ");");
InFlagDecled = true;
} else
emitCode("InFlag = " + RootName +
".getOperand(" + utostr(OpNo) + ");");
emitCode("AddToISelQueue(InFlag);");
}
}
/// EmitCopyFromRegs - Emit code to copy result to physical registers
/// as specified by the instruction. It returns true if any copy is
/// emitted.
bool EmitCopyFromRegs(TreePatternNode *N, bool &ChainEmitted) {
bool EmitCopyFromRegs(TreePatternNode *N, bool &ResNodeDecled,
bool &ChainEmitted) {
bool RetVal = false;
Record *Op = N->getOperator();
if (Op->isSubClassOf("Instruction")) {
@ -2932,14 +2961,15 @@ private:
MVT::ValueType RVT = getRegisterValueType(RR, CGT);
if (RVT != MVT::Flag) {
if (!ChainEmitted) {
emitDecl("Chain");
emitCode("Chain = CurDAG->getEntryNode();");
emitCode("SDOperand Chain = CurDAG->getEntryNode();");
ChainEmitted = true;
ChainName = "Chain";
}
emitCode("ResNode = CurDAG->getCopyFromReg(" + ChainName +
std::string Decl = (!ResNodeDecled) ? "SDNode *" : "";
emitCode(Decl + "ResNode = CurDAG->getCopyFromReg(" + ChainName +
", " + ISE.getQualifiedName(RR) + ", " + getEnumName(RVT) +
", InFlag).Val;");
ResNodeDecled = true;
emitCode(ChainName + " = SDOperand(ResNode, 1);");
emitCode("InFlag = SDOperand(ResNode, 2);");
RetVal = true;
@ -2955,7 +2985,7 @@ private:
/// stream to match the pattern, and generate the code for the match if it
/// succeeds. Returns true if the pattern is not guaranteed to match.
void DAGISelEmitter::GenerateCodeForPattern(PatternToMatch &Pattern,
std::vector<std::pair<bool, std::string> > &GeneratedCode,
std::vector<std::pair<unsigned, std::string> > &GeneratedCode,
std::set<std::pair<unsigned, std::string> > &GeneratedDecl,
std::vector<std::string> &TargetOpcodes,
std::vector<std::string> &TargetVTs) {
@ -3005,8 +3035,8 @@ void DAGISelEmitter::GenerateCodeForPattern(PatternToMatch &Pattern,
// otherwise we are done.
} while (Emitter.InsertOneTypeCheck(Pat, Pattern.getSrcPattern(), "N", true));
bool RetSelected = false;
Emitter.EmitResultCode(Pattern.getDstPattern(), RetSelected, false, true);
Emitter.EmitResultCode(Pattern.getDstPattern(),
false, false, false, false, true);
delete Pat;
}
@ -3014,7 +3044,7 @@ void DAGISelEmitter::GenerateCodeForPattern(PatternToMatch &Pattern,
/// a line causes any of them to be empty, remove them and return true when
/// done.
static bool EraseCodeLine(std::vector<std::pair<PatternToMatch*,
std::vector<std::pair<bool, std::string> > > >
std::vector<std::pair<unsigned, std::string> > > >
&Patterns) {
bool ErasedPatterns = false;
for (unsigned i = 0, e = Patterns.size(); i != e; ++i) {
@ -3031,10 +3061,10 @@ static bool EraseCodeLine(std::vector<std::pair<PatternToMatch*,
/// EmitPatterns - Emit code for at least one pattern, but try to group common
/// code together between the patterns.
void DAGISelEmitter::EmitPatterns(std::vector<std::pair<PatternToMatch*,
std::vector<std::pair<bool, std::string> > > >
std::vector<std::pair<unsigned, std::string> > > >
&Patterns, unsigned Indent,
std::ostream &OS) {
typedef std::pair<bool, std::string> CodeLine;
typedef std::pair<unsigned, std::string> CodeLine;
typedef std::vector<CodeLine> CodeList;
typedef std::vector<std::pair<PatternToMatch*, CodeList> > PatternList;
@ -3070,12 +3100,12 @@ void DAGISelEmitter::EmitPatterns(std::vector<std::pair<PatternToMatch*,
<< " size = "
<< getResultPatternSize(Pattern.getDstPattern(), *this) << "\n";
}
if (!FirstCodeLine.first) {
if (FirstCodeLine.first != 1) {
OS << std::string(Indent, ' ') << "{\n";
Indent += 2;
}
EmitPatterns(Shared, Indent, OS);
if (!FirstCodeLine.first) {
if (FirstCodeLine.first != 1) {
Indent -= 2;
OS << std::string(Indent, ' ') << "}\n";
}
@ -3102,7 +3132,7 @@ void DAGISelEmitter::EmitPatterns(std::vector<std::pair<PatternToMatch*,
// Remove this code from all of the patterns that share it.
bool ErasedPatterns = EraseCodeLine(Patterns);
bool isPredicate = FirstCodeLine.first;
bool isPredicate = FirstCodeLine.first == 1;
// Otherwise, every pattern in the list has this line. Emit it.
if (!isPredicate) {
@ -3114,7 +3144,7 @@ void DAGISelEmitter::EmitPatterns(std::vector<std::pair<PatternToMatch*,
// If the next code line is another predicate, and if all of the pattern
// in this group share the same next line, emit it inline now. Do this
// until we run out of common predicates.
while (!ErasedPatterns && Patterns.back().second.back().first) {
while (!ErasedPatterns && Patterns.back().second.back().first == 1) {
// Check that all of fhe patterns in Patterns end with the same predicate.
bool AllEndWithSamePredicate = true;
for (unsigned i = 0, e = Patterns.size(); i != e; ++i)
@ -3238,14 +3268,13 @@ void DAGISelEmitter::EmitInstructionSelector(std::ostream &OS) {
++II) {
MVT::ValueType OpVT = II->first;
std::vector<PatternToMatch*> &Patterns = II->second;
typedef std::vector<std::pair<bool, std::string> > CodeList;
typedef std::vector<std::pair<bool, std::string> >::iterator CodeListI;
typedef std::vector<std::pair<unsigned, std::string> > CodeList;
typedef std::vector<std::pair<unsigned, std::string> >::iterator CodeListI;
std::vector<std::pair<PatternToMatch*, CodeList> > CodeForPatterns;
std::vector<std::vector<std::string> > PatternOpcodes;
std::vector<std::vector<std::string> > PatternVTs;
std::vector<std::set<std::pair<unsigned, std::string> > > PatternDecls;
std::set<std::pair<unsigned, std::string> > AllGenDecls;
for (unsigned i = 0, e = Patterns.size(); i != e; ++i) {
CodeList GeneratedCode;
std::set<std::pair<unsigned, std::string> > GeneratedDecl;
@ -3253,9 +3282,6 @@ void DAGISelEmitter::EmitInstructionSelector(std::ostream &OS) {
std::vector<std::string> TargetVTs;
GenerateCodeForPattern(*Patterns[i], GeneratedCode, GeneratedDecl,
TargetOpcodes, TargetVTs);
for (std::set<std::pair<unsigned, std::string> >::iterator
si = GeneratedDecl.begin(), se = GeneratedDecl.end(); si!=se; ++si)
AllGenDecls.insert(*si);
CodeForPatterns.push_back(std::make_pair(Patterns[i], GeneratedCode));
PatternDecls.push_back(GeneratedDecl);
PatternOpcodes.push_back(TargetOpcodes);
@ -3270,7 +3296,7 @@ void DAGISelEmitter::EmitInstructionSelector(std::ostream &OS) {
mightNotMatch = false;
for (unsigned j = 0, e = GeneratedCode.size(); j != e; ++j) {
if (GeneratedCode[j].first) { // predicate.
if (GeneratedCode[j].first == 1) { // predicate.
mightNotMatch = true;
break;
}
@ -3280,7 +3306,7 @@ void DAGISelEmitter::EmitInstructionSelector(std::ostream &OS) {
// patterns after it CANNOT ever match. Error out.
if (mightNotMatch == false && i != CodeForPatterns.size()-1) {
std::cerr << "Pattern '";
CodeForPatterns[i+1].first->getSrcPattern()->print(std::cerr);
CodeForPatterns[i].first->getSrcPattern()->print(std::cerr);
std::cerr << "' is impossible to select!\n";
exit(1);
}
@ -3294,16 +3320,16 @@ void DAGISelEmitter::EmitInstructionSelector(std::ostream &OS) {
std::vector<std::string> &TargetOpcodes = PatternOpcodes[i];
std::vector<std::string> &TargetVTs = PatternVTs[i];
std::set<std::pair<unsigned, std::string> > Decls = PatternDecls[i];
std::vector<std::string> AddedInits;
int CodeSize = (int)GeneratedCode.size();
int LastPred = -1;
for (int j = CodeSize-1; j >= 0; --j) {
if (GeneratedCode[j].first) {
if (LastPred == -1 && GeneratedCode[j].first == 1)
LastPred = j;
break;
}
else if (LastPred != -1 && GeneratedCode[j].first == 2)
AddedInits.push_back(GeneratedCode[j].second);
}
std::string CalleeDecls;
std::string CalleeCode = "(SDOperand &Result, const SDOperand &N";
std::string CallerCode = "(Result, N";
for (unsigned j = 0, e = TargetOpcodes.size(); j != e; ++j) {
@ -3317,35 +3343,25 @@ void DAGISelEmitter::EmitInstructionSelector(std::ostream &OS) {
for (std::set<std::pair<unsigned, std::string> >::iterator
I = Decls.begin(), E = Decls.end(); I != E; ++I) {
std::string Name = I->second;
if (I->first == 0) {
if (Name == "InFlag" ||
(Name.size() > 3 &&
Name[0] == 'T' && Name[1] == 'm' && Name[2] == 'p')) {
CalleeDecls += " SDOperand " + Name + "(0, 0);\n";
continue;
}
CalleeCode += ", SDOperand &" + Name;
CallerCode += ", " + Name;
} else if (I->first == 1) {
if (Name == "ResNode") {
CalleeDecls += " SDNode *" + Name + " = NULL;\n";
continue;
}
CalleeCode += ", SDNode *" + Name;
CallerCode += ", " + Name;
} else {
CalleeCode += ", bool " + Name;
CallerCode += ", " + Name;
}
}
CallerCode += ");";
CalleeCode += ") ";
// Prevent emission routines from being inlined to reduce selection
// routines stack frame sizes.
CalleeCode += "NOINLINE ";
CalleeCode += "{\n" + CalleeDecls;
for (int j = LastPred+1; j < CodeSize; ++j)
CalleeCode += " " + GeneratedCode[j].second + '\n';
CalleeCode += "{\n";
for (std::vector<std::string>::const_reverse_iterator
I = AddedInits.rbegin(), E = AddedInits.rend(); I != E; ++I)
CalleeCode += " " + *I + "\n";
for (int j = LastPred+1; j < CodeSize; ++j) {
std::string code = GeneratedCode[j].second;
// if (!AddedDecls.count(code))
CalleeCode += " " + code + "\n";
}
for (int j = LastPred+1; j < CodeSize; ++j)
GeneratedCode.pop_back();
CalleeCode += "}\n";
@ -3383,16 +3399,6 @@ void DAGISelEmitter::EmitInstructionSelector(std::ostream &OS) {
OS << "SDNode *Select_" << OpName << (OpVTStr != "" ? "_" : "")
<< OpVTStr << "(SDOperand &Result, const SDOperand &N) {\n";
// Print all declarations.
for (std::set<std::pair<unsigned, std::string> >::iterator
I = AllGenDecls.begin(), E = AllGenDecls.end(); I != E; ++I)
if (I->first == 0)
OS << " SDOperand " << I->second << "(0, 0);\n";
else if (I->first == 1)
OS << " SDNode *" << I->second << " = NULL;\n";
else
OS << " bool " << I->second << " = false;\n";
// Loop through and reverse all of the CodeList vectors, as we will be
// accessing them from their logical front, but accessing the end of a
// vector is more efficient.
@ -3432,10 +3438,10 @@ void DAGISelEmitter::EmitInstructionSelector(std::ostream &OS) {
// Emit boilerplate.
OS << "SDNode *Select_INLINEASM(SDOperand& Result, SDOperand N) {\n"
<< " std::vector<SDOperand> Ops(N.Val->op_begin(), N.Val->op_end());\n"
<< " AddToQueue(Ops[0], N.getOperand(0)); // Select the chain.\n\n"
<< " AddToISelQueue(N.getOperand(0)); // Select the chain.\n\n"
<< " // Select the flag operand.\n"
<< " if (Ops.back().getValueType() == MVT::Flag)\n"
<< " AddToQueue(Ops.back(), Ops.back());\n"
<< " AddToISelQueue(Ops.back());\n"
<< " SelectInlineAsmMemoryOperands(Ops, *CurDAG);\n"
<< " std::vector<MVT::ValueType> VTs;\n"
<< " VTs.push_back(MVT::Other);\n"
@ -3470,17 +3476,15 @@ void DAGISelEmitter::EmitInstructionSelector(std::ostream &OS) {
<< " }\n"
<< " case ISD::AssertSext:\n"
<< " case ISD::AssertZext: {\n"
<< " AddToQueue(Result, N.getOperand(0));\n"
<< " ReplaceUses(N, Result);\n"
<< " AddToISelQueue(N.getOperand(0));\n"
<< " ReplaceUses(N, N.getOperand(0));\n"
<< " return NULL;\n"
<< " }\n"
<< " case ISD::TokenFactor:\n"
<< " case ISD::CopyFromReg:\n"
<< " case ISD::CopyToReg: {\n"
<< " for (unsigned i = 0, e = N.getNumOperands(); i != e; ++i) {\n"
<< " SDOperand Dummy;\n"
<< " AddToQueue(Dummy, N.getOperand(i));\n"
<< " }\n"
<< " for (unsigned i = 0, e = N.getNumOperands(); i != e; ++i)\n"
<< " AddToISelQueue(N.getOperand(i));\n"
<< " Result = N;\n"
<< " return NULL;\n"
<< " }\n"
@ -3601,8 +3605,7 @@ void DAGISelEmitter::run(std::ostream &OS) {
OS << " return ISelSelected[Id / 8] & (1 << (Id % 8));\n";
OS << "}\n\n";
OS << "void AddToQueue(SDOperand &Result, SDOperand N) NOINLINE {\n";
OS << " Result = N;\n";
OS << "void AddToISelQueue(SDOperand N) NOINLINE {\n";
OS << " int Id = N.Val->getNodeId();\n";
OS << " if (Id != -1 && !isQueued(Id)) {\n";
OS << " ISelQueue.push_back(N.Val);\n";

View File

@ -520,12 +520,12 @@ private:
std::vector<Record*> &InstImpInputs,
std::vector<Record*> &InstImpResults);
void GenerateCodeForPattern(PatternToMatch &Pattern,
std::vector<std::pair<bool, std::string> > &GeneratedCode,
std::vector<std::pair<unsigned, std::string> > &GeneratedCode,
std::set<std::pair<unsigned, std::string> > &GeneratedDecl,
std::vector<std::string> &TargetOpcodes,
std::vector<std::string> &TargetVTs);
void EmitPatterns(std::vector<std::pair<PatternToMatch*,
std::vector<std::pair<bool, std::string> > > > &Patterns,
std::vector<std::pair<unsigned, std::string> > > > &Patterns,
unsigned Indent, std::ostream &OS);
void EmitInstructionSelector(std::ostream &OS);
};