#include "DAGISelEmitter.h"
#include "Record.h"
#include "llvm/ADT/StringExtras.h"
+#include "llvm/Support/CommandLine.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/MathExtras.h"
-#include "llvm/Support/Streams.h"
+#include "llvm/Support/Debug.h"
#include <algorithm>
+#include <deque>
+#include <iostream>
using namespace llvm;
+static cl::opt<bool>
+GenDebug("gen-debug", cl::desc("Generate debug code"), cl::init(false));
+
//===----------------------------------------------------------------------===//
// DAGISelEmitter Helper methods
//
/// patterns before small ones. This is used to determine the size of a
/// pattern.
static unsigned getPatternSize(TreePatternNode *P, CodeGenDAGPatterns &CGP) {
- assert((MVT::isExtIntegerInVTs(P->getExtTypes()) ||
- MVT::isExtFloatingPointInVTs(P->getExtTypes()) ||
+ assert((EEVT::isExtIntegerInVTs(P->getExtTypes()) ||
+ EEVT::isExtFloatingPointInVTs(P->getExtTypes()) ||
P->getExtTypeNum(0) == MVT::isVoid ||
P->getExtTypeNum(0) == MVT::Flag ||
- P->getExtTypeNum(0) == MVT::iPTR) &&
+ P->getExtTypeNum(0) == MVT::iPTR ||
+ P->getExtTypeNum(0) == MVT::iPTRAny) &&
"Not a valid pattern node to size!");
unsigned Size = 3; // The node itself.
// If the root node is a ConstantSDNode, increases its size.
// If this node has some predicate function that must match, it adds to the
// complexity of this node.
- if (!P->getPredicateFn().empty())
+ if (!P->getPredicateFns().empty())
++Size;
// Count children in the count if they are also nodes.
Size += 5; // Matches a ConstantSDNode (+3) and a specific value (+2).
else if (NodeIsComplexPattern(Child))
Size += getPatternSize(Child, CGP);
- else if (!Child->getPredicateFn().empty())
+ else if (!Child->getPredicateFns().empty())
++Size;
}
}
PatternSortingPredicate(CodeGenDAGPatterns &cgp) : CGP(cgp) {}
CodeGenDAGPatterns &CGP;
- bool operator()(const PatternToMatch *LHS,
- const PatternToMatch *RHS) {
+ typedef std::pair<unsigned, std::string> CodeLine;
+ typedef std::vector<CodeLine> CodeList;
+ typedef std::vector<std::pair<const PatternToMatch*, CodeList> > PatternList;
+
+ bool operator()(const std::pair<const PatternToMatch*, CodeList> &LHSPair,
+ const std::pair<const PatternToMatch*, CodeList> &RHSPair) {
+ const PatternToMatch *LHS = LHSPair.first;
+ const PatternToMatch *RHS = RHSPair.first;
+
unsigned LHSSize = getPatternSize(LHS->getSrcPattern(), CGP);
unsigned RHSSize = getPatternSize(RHS->getSrcPattern(), CGP);
LHSSize += LHS->getAddedComplexity();
}
};
-/// getRegisterValueType - Look up and return the first ValueType of specified
-/// RegisterClass record
-static MVT::ValueType getRegisterValueType(Record *R, const CodeGenTarget &T) {
- if (const CodeGenRegisterClass *RC = T.getRegisterClassForRegister(R))
- return RC->getValueTypeNum(0);
- return MVT::Other;
+/// getRegisterValueType - Look up and return the ValueType of the specified
+/// register. If the register is a member of multiple register classes which
+/// have different associated types, return MVT::Other.
+static MVT::SimpleValueType getRegisterValueType(Record *R, const CodeGenTarget &T) {
+ bool FoundRC = false;
+ MVT::SimpleValueType VT = MVT::Other;
+ const std::vector<CodeGenRegisterClass> &RCs = T.getRegisterClasses();
+ std::vector<CodeGenRegisterClass>::const_iterator RC;
+ std::vector<Record*>::const_iterator Element;
+
+ for (RC = RCs.begin() ; RC != RCs.end() ; RC++) {
+ Element = find((*RC).Elements.begin(), (*RC).Elements.end(), R);
+ if (Element != (*RC).Elements.end()) {
+ if (!FoundRC) {
+ FoundRC = true;
+ VT = (*RC).getValueTypeNum(0);
+ } else {
+ // In multiple RC's
+ if (VT != (*RC).getValueTypeNum(0)) {
+ // Types of the RC's do not agree. Return MVT::Other. The
+ // target is responsible for handling this.
+ return MVT::Other;
+ }
+ }
+ }
+ }
+ return VT;
}
return false;
}
+static std::string getOpcodeName(Record *Op, CodeGenDAGPatterns &CGP) {
+ return CGP.getSDNodeInfo(Op).getEnumName();
+}
+
+static
+bool DisablePatternForFastISel(TreePatternNode *N, CodeGenDAGPatterns &CGP) {
+ bool isStore = !N->isLeaf() &&
+ getOpcodeName(N->getOperator(), CGP) == "ISD::STORE";
+ if (!isStore && NodeHasProperty(N, SDNPHasChain, CGP))
+ return false;
+
+ bool HasChain = false;
+ for (unsigned i = 0, e = N->getNumChildren(); i != e; ++i) {
+ TreePatternNode *Child = N->getChild(i);
+ if (PatternHasProperty(Child, SDNPHasChain, CGP)) {
+ HasChain = true;
+ break;
+ }
+ }
+ return HasChain;
+}
+
//===----------------------------------------------------------------------===//
// Node Transformation emitter implementation.
//
-void DAGISelEmitter::EmitNodeTransforms(std::ostream &OS) {
+void DAGISelEmitter::EmitNodeTransforms(raw_ostream &OS) {
// Walk the pattern fragments, adding them to a map, which sorts them by
// name.
typedef std::map<std::string, CodeGenDAGPatterns::NodeXForm> NXsByNameTy;
std::string ClassName = CGP.getSDNodeInfo(SDNode).getSDClassName();
const char *C2 = ClassName == "SDNode" ? "N" : "inN";
- OS << "inline SDOperand Transform_" << I->first << "(SDNode *" << C2
+ OS << "inline SDValue Transform_" << I->first << "(SDNode *" << C2
<< ") {\n";
if (ClassName != "SDNode")
OS << " " << ClassName << " *N = cast<" << ClassName << ">(inN);\n";
// Predicate emitter implementation.
//
-void DAGISelEmitter::EmitPredicateFunctions(std::ostream &OS) {
+void DAGISelEmitter::EmitPredicateFunctions(raw_ostream &OS) {
OS << "\n// Predicate functions.\n";
// Walk the pattern fragments, adding them to a map, which sorts them by
CodeGenDAGPatterns &CGP;
// Predicates.
- ListInit *Predicates;
+ std::string PredicateCheck;
// Pattern cost.
unsigned Cost;
// Instruction selector pattern.
/// 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
+ /// GeneratedDecl - This is the set of all SDValue declarations needed for
/// the set of patterns for each top-level opcode.
std::set<std::string> &GeneratedDecl;
/// TargetOpcodes - The target specific opcodes used by the resulting
/// instructions.
std::vector<std::string> &TargetOpcodes;
std::vector<std::string> &TargetVTs;
+ /// OutputIsVariadic - Records whether the instruction output pattern uses
+ /// variable_ops. This requires that the Emit function be passed an
+ /// additional argument to indicate where the input varargs operands
+ /// begin.
+ bool &OutputIsVariadic;
+ /// NumInputRootOps - Records the number of operands the root node of the
+ /// input pattern has. This information is used in the generated code to
+ /// pass to Emit functions when variable_ops processing is needed.
+ unsigned &NumInputRootOps;
std::string ChainName;
unsigned TmpNo;
VTNo++;
}
public:
- PatternCodeEmitter(CodeGenDAGPatterns &cgp, ListInit *preds,
+ PatternCodeEmitter(CodeGenDAGPatterns &cgp, std::string predcheck,
TreePatternNode *pattern, TreePatternNode *instr,
std::vector<std::pair<unsigned, std::string> > &gc,
std::set<std::string> &gd,
std::vector<std::string> &to,
- std::vector<std::string> &tv)
- : CGP(cgp), Predicates(preds), Pattern(pattern), Instruction(instr),
+ std::vector<std::string> &tv,
+ bool &oiv,
+ unsigned &niro)
+ : CGP(cgp), PredicateCheck(predcheck), Pattern(pattern), Instruction(instr),
GeneratedCode(gc), GeneratedDecl(gd),
TargetOpcodes(to), TargetVTs(tv),
+ OutputIsVariadic(oiv), NumInputRootOps(niro),
TmpNo(0), OpcNo(0), VTNo(0) {}
/// EmitMatchCode - Emit a matcher for N, going to the label for PatternNo
// Save loads/stores matched by a pattern.
if (!N->isLeaf() && N->getName().empty()) {
- std::string EnumName = N->getOperator()->getValueAsString("Opcode");
- if (EnumName == "ISD::LOAD" ||
- EnumName == "ISD::STORE") {
+ if (NodeHasProperty(N, SDNPMemOperand, CGP))
LSI.push_back(RootName);
- }
}
bool isRoot = (P == NULL);
// Emit instruction predicates. Each predicate is just a string for now.
if (isRoot) {
- std::string PredicateCheck;
- for (unsigned i = 0, e = Predicates->getSize(); i != e; ++i) {
- if (DefInit *Pred = dynamic_cast<DefInit*>(Predicates->getElement(i))) {
- Record *Def = Pred->getDef();
- if (!Def->isSubClassOf("Predicate")) {
-#ifndef NDEBUG
- Def->dump();
-#endif
- assert(0 && "Unknown predicate type!");
- }
- if (!PredicateCheck.empty())
- PredicateCheck += " && ";
- PredicateCheck += "(" + Def->getValueAsString("CondString") + ")";
- }
- }
-
+ // Record input varargs info.
+ NumInputRootOps = N->getNumChildren();
+
+ if (DisablePatternForFastISel(N, CGP))
+ emitCheck("OptLevel != CodeGenOpt::None");
+
emitCheck(PredicateCheck);
}
if (N->isLeaf()) {
if (IntInit *II = dynamic_cast<IntInit*>(N->getLeafValue())) {
emitCheck("cast<ConstantSDNode>(" + RootName +
- ")->getSignExtended() == " + itostr(II->getValue()));
+ ")->getSExtValue() == INT64_C(" +
+ itostr(II->getValue()) + ")");
return;
} else if (!NodeIsComplexPattern(N)) {
assert(0 && "Cannot match this as a leaf value!");
// / [YY]
// | ^
// [XX]-------|
- bool NeedCheck = false;
- if (P != Pattern)
- NeedCheck = true;
- else {
+ bool NeedCheck = P != Pattern;
+ if (!NeedCheck) {
const SDNodeInfo &PInfo = CGP.getSDNodeInfo(P->getOperator());
NeedCheck =
P->getOperator() == CGP.get_intrinsic_void_sdnode() ||
if (NeedCheck) {
std::string ParentName(RootName.begin(), RootName.end()-1);
- emitCheck("CanBeFoldedBy(" + RootName + ".Val, " + ParentName +
- ".Val, N.Val)");
+ emitCheck("IsLegalAndProfitableToFold(" + RootName +
+ ".getNode(), " + ParentName + ".getNode(), N.getNode())");
}
}
}
if (NodeHasChain) {
if (FoundChain) {
- emitCheck("(" + ChainName + ".Val == " + RootName + ".Val || "
- "IsChainCompatible(" + ChainName + ".Val, " +
- RootName + ".Val))");
+ emitCheck("(" + ChainName + ".getNode() == " + RootName + ".getNode() || "
+ "IsChainCompatible(" + ChainName + ".getNode(), " +
+ RootName + ".getNode()))");
OrigChains.push_back(std::make_pair(ChainName, RootName));
} else
FoundChain = true;
ChainName = "Chain" + ChainSuffix;
- emitInit("SDOperand " + ChainName + " = " + RootName +
+ emitInit("SDValue " + ChainName + " = " + RootName +
".getOperand(0);");
}
}
}
}
- // If there is a node predicate for this, emit the call.
- if (!N->getPredicateFn().empty())
- emitCheck(N->getPredicateFn() + "(" + RootName + ".Val)");
+ // If there are node predicates for this, emit the calls.
+ for (unsigned i = 0, e = N->getPredicateFns().size(); i != e; ++i)
+ emitCheck(N->getPredicateFns()[i] + "(" + RootName + ".getNode())");
-
// If this is an 'and R, 1234' where the operation is AND/OR and the RHS is
// a constant without a predicate fn that has more that one bit set, handle
// this as a special case. This is usually for targets that have special
(N->getOperator()->getName() == "and" ||
N->getOperator()->getName() == "or") &&
N->getChild(1)->isLeaf() &&
- N->getChild(1)->getPredicateFn().empty()) {
+ N->getChild(1)->getPredicateFns().empty()) {
if (IntInit *II = dynamic_cast<IntInit*>(N->getChild(1)->getLeafValue())) {
if (!isPowerOf2_32(II->getValue())) { // Don't bother with single bits.
- emitInit("SDOperand " + RootName + "0" + " = " +
+ emitInit("SDValue " + RootName + "0" + " = " +
RootName + ".getOperand(" + utostr(0) + ");");
- emitInit("SDOperand " + RootName + "1" + " = " +
+ emitInit("SDValue " + RootName + "1" + " = " +
RootName + ".getOperand(" + utostr(1) + ");");
- emitCheck("isa<ConstantSDNode>(" + RootName + "1)");
+ unsigned NTmp = TmpNo++;
+ emitCode("ConstantSDNode *Tmp" + utostr(NTmp) +
+ " = dyn_cast<ConstantSDNode>(" + RootName + "1);");
+ emitCheck("Tmp" + utostr(NTmp));
const char *MaskPredicate = N->getOperator()->getName() == "or"
? "CheckOrMask(" : "CheckAndMask(";
- emitCheck(MaskPredicate + RootName + "0, cast<ConstantSDNode>(" +
- RootName + "1), " + itostr(II->getValue()) + ")");
+ emitCheck(MaskPredicate + RootName + "0, Tmp" + utostr(NTmp) +
+ ", INT64_C(" + itostr(II->getValue()) + "))");
EmitChildMatchCode(N->getChild(0), N, RootName + utostr(0), RootName,
ChainSuffix + utostr(0), FoundChain);
}
for (unsigned i = 0, e = N->getNumChildren(); i != e; ++i, ++OpNo) {
- emitInit("SDOperand " + RootName + utostr(OpNo) + " = " +
+ emitInit("SDValue " + RootName + utostr(OpNo) + " = " +
RootName + ".getOperand(" +utostr(OpNo) + ");");
EmitChildMatchCode(N->getChild(i), N, RootName + utostr(OpNo), RootName,
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) + ";");
+ emitDecl("CPTmp" + RootName + "_" + utostr(i));
+ emitCode("SDValue CPTmp" + RootName + "_" + utostr(i) + ";");
}
if (CP->hasProperty(SDNPHasChain)) {
emitDecl("CPInChain");
emitDecl("Chain" + ChainSuffix);
- emitCode("SDOperand CPInChain;");
- emitCode("SDOperand Chain" + ChainSuffix + ";");
+ emitCode("SDValue CPInChain;");
+ emitCode("SDValue Chain" + ChainSuffix + ";");
}
std::string Code = Fn + "(" + RootName + ", " + RootName;
for (unsigned i = 0; i < NumOps; i++)
- Code += ", CPTmp" + utostr(i);
+ Code += ", CPTmp" + RootName + "_" + utostr(i);
if (CP->hasProperty(SDNPHasChain)) {
ChainName = "Chain" + ChainSuffix;
Code += ", CPInChain, Chain" + ChainSuffix;
if (DefInit *DI = dynamic_cast<DefInit*>(Child->getLeafValue())) {
Record *LeafRec = DI->getDef();
if (LeafRec->isSubClassOf("RegisterClass") ||
- LeafRec->getName() == "ptr_rc") {
+ LeafRec->isSubClassOf("PointerLikeRegClass")) {
// Handle register references. Nothing to do here.
} else if (LeafRec->isSubClassOf("Register")) {
// Handle register references.
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) + ";");
+ emitDecl("CPTmp" + RootName + "_" + utostr(i));
+ emitCode("SDValue CPTmp" + RootName + "_" + utostr(i) + ";");
}
if (CP->hasProperty(SDNPHasChain)) {
const SDNodeInfo &PInfo = CGP.getSDNodeInfo(Parent->getOperator());
ChainName = "Chain" + ChainSuffix;
emitDecl("CPInChain");
emitDecl(ChainName);
- emitCode("SDOperand CPInChain;");
- emitCode("SDOperand " + ChainName + ";");
+ emitCode("SDValue CPInChain;");
+ emitCode("SDValue " + ChainName + ";");
}
std::string Code = Fn + "(";
}
Code += RootName;
for (unsigned i = 0; i < NumOps; i++)
- Code += ", CPTmp" + utostr(i);
+ Code += ", CPTmp" + RootName + "_" + utostr(i);
if (CP->hasProperty(SDNPHasChain))
Code += ", CPInChain, Chain" + ChainSuffix;
emitCheck(Code + ")");
} else {
#ifndef NDEBUG
Child->dump();
- cerr << " ";
+ errs() << " ";
#endif
assert(0 && "Unknown leaf type!");
}
- // If there is a node predicate for this, emit the call.
- if (!Child->getPredicateFn().empty())
- emitCheck(Child->getPredicateFn() + "(" + RootName +
- ".Val)");
+ // If there are node predicates for this, emit the calls.
+ for (unsigned i = 0, e = Child->getPredicateFns().size(); i != e; ++i)
+ emitCheck(Child->getPredicateFns()[i] + "(" + RootName +
+ ".getNode())");
} else if (IntInit *II =
dynamic_cast<IntInit*>(Child->getLeafValue())) {
- emitCheck("isa<ConstantSDNode>(" + RootName + ")");
+ unsigned NTmp = TmpNo++;
+ emitCode("ConstantSDNode *Tmp"+ utostr(NTmp) +
+ " = dyn_cast<ConstantSDNode>("+
+ RootName + ");");
+ emitCheck("Tmp" + utostr(NTmp));
unsigned CTmp = TmpNo++;
- emitCode("int64_t CN"+utostr(CTmp)+" = cast<ConstantSDNode>("+
- RootName + ")->getSignExtended();");
-
- emitCheck("CN" + utostr(CTmp) + " == " +itostr(II->getValue()));
+ emitCode("int64_t CN"+ utostr(CTmp) +
+ " = Tmp" + utostr(NTmp) + "->getSExtValue();");
+ emitCheck("CN" + utostr(CTmp) + " == "
+ "INT64_C(" +itostr(II->getValue()) + ")");
} else {
#ifndef NDEBUG
Child->dump();
std::string Val = VariableMap[VarName];
bool ModifiedVal = false;
if (Val.empty()) {
- cerr << "Variable '" << VarName << " referenced but not defined "
+ errs() << "Variable '" << VarName << " referenced but not defined "
<< "and not caught earlier!\n";
abort();
}
std::string TmpVar = "Tmp" + utostr(ResNo);
switch (N->getTypeNum(0)) {
default:
- cerr << "Cannot handle " << getEnumName(N->getTypeNum(0))
+ errs() << "Cannot handle " << getEnumName(N->getTypeNum(0))
<< " type as an immediate constant. Aborting\n";
abort();
case MVT::i1: CastType = "bool"; break;
case MVT::i32: CastType = "unsigned"; break;
case MVT::i64: CastType = "uint64_t"; break;
}
- emitCode("SDOperand " + TmpVar +
+ emitCode("SDValue " + TmpVar +
" = CurDAG->getTargetConstant(((" + CastType +
- ") cast<ConstantSDNode>(" + Val + ")->getValue()), " +
+ ") cast<ConstantSDNode>(" + Val + ")->getZExtValue()), " +
getEnumName(N->getTypeNum(0)) + ");");
// Add Tmp<ResNo> to VariableMap, so that we don't multiply select this
// value if used multiple times by this pattern result.
} else if (!N->isLeaf() && N->getOperator()->getName() == "fpimm") {
assert(N->getExtTypes().size() == 1 && "Multiple types not handled!");
std::string TmpVar = "Tmp" + utostr(ResNo);
- emitCode("SDOperand " + TmpVar +
- " = CurDAG->getTargetConstantFP(cast<ConstantFPSDNode>(" +
- Val + ")->getValueAPF(), cast<ConstantFPSDNode>(" + Val +
- ")->getValueType(0));");
+ emitCode("SDValue " + TmpVar +
+ " = CurDAG->getTargetConstantFP(*cast<ConstantFPSDNode>(" +
+ Val + ")->getConstantFPValue(), cast<ConstantFPSDNode>(" +
+ Val + ")->getValueType(0));");
// Add Tmp<ResNo> to VariableMap, so that we don't multiply select this
// value if used multiple times by this pattern result.
Val = TmpVar;
// Transform ExternalSymbol to TargetExternalSymbol
if (Op && Op->getName() == "externalsym") {
std::string TmpVar = "Tmp"+utostr(ResNo);
- emitCode("SDOperand " + TmpVar + " = CurDAG->getTarget"
+ emitCode("SDValue " + TmpVar + " = CurDAG->getTarget"
"ExternalSymbol(cast<ExternalSymbolSDNode>(" +
Val + ")->getSymbol(), " +
getEnumName(N->getTypeNum(0)) + ");");
if (Op && (Op->getName() == "globaladdr" ||
Op->getName() == "globaltlsaddr")) {
std::string TmpVar = "Tmp" + utostr(ResNo);
- emitCode("SDOperand " + TmpVar + " = CurDAG->getTarget"
+ emitCode("SDValue " + TmpVar + " = CurDAG->getTarget"
"GlobalAddress(cast<GlobalAddressSDNode>(" + Val +
")->getGlobal(), " + getEnumName(N->getTypeNum(0)) +
");");
NodeOps.push_back(Val);
} else if (N->isLeaf() && (CP = NodeGetComplexPattern(N, CGP))) {
for (unsigned i = 0; i < CP->getNumOperands(); ++i) {
- emitCode("AddToISelQueue(CPTmp" + utostr(i) + ");");
- NodeOps.push_back("CPTmp" + utostr(i));
+ NodeOps.push_back("CPTmp" + Val + "_" + 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("return NULL;");
if (DefInit *DI = dynamic_cast<DefInit*>(N->getLeafValue())) {
unsigned ResNo = TmpNo++;
if (DI->getDef()->isSubClassOf("Register")) {
- emitCode("SDOperand Tmp" + utostr(ResNo) + " = CurDAG->getRegister(" +
+ emitCode("SDValue Tmp" + utostr(ResNo) + " = CurDAG->getRegister(" +
getQualifiedName(DI->getDef()) + ", " +
getEnumName(N->getTypeNum(0)) + ");");
NodeOps.push_back("Tmp" + utostr(ResNo));
return NodeOps;
} else if (DI->getDef()->getName() == "zero_reg") {
- emitCode("SDOperand Tmp" + utostr(ResNo) +
+ emitCode("SDValue Tmp" + utostr(ResNo) +
" = CurDAG->getRegister(0, " +
getEnumName(N->getTypeNum(0)) + ");");
NodeOps.push_back("Tmp" + utostr(ResNo));
return NodeOps;
+ } else if (DI->getDef()->isSubClassOf("RegisterClass")) {
+ // Handle a reference to a register class. This is used
+ // in COPY_TO_SUBREG instructions.
+ emitCode("SDValue Tmp" + utostr(ResNo) +
+ " = CurDAG->getTargetConstant(" +
+ getQualifiedName(DI->getDef()) + "RegClassID, " +
+ "MVT::i32);");
+ 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!");
- emitCode("SDOperand Tmp" + utostr(ResNo) +
- " = CurDAG->getTargetConstant(0x" + itohexstr(II->getValue()) +
+ emitCode("SDValue Tmp" + utostr(ResNo) +
+ " = CurDAG->getTargetConstant(0x" +
+ utohexstr((uint64_t) II->getValue()) +
"ULL, " + getEnumName(N->getTypeNum(0)) + ");");
NodeOps.push_back("Tmp" + utostr(ResNo));
return NodeOps;
TreePatternNode *InstPatNode =
isRoot ? (InstPat ? InstPat->getTree(0) : Pattern)
: (InstPat ? InstPat->getTree(0) : NULL);
- if (InstPatNode && InstPatNode->getOperator()->getName() == "set") {
+ if (InstPatNode && !InstPatNode->isLeaf() &&
+ InstPatNode->getOperator()->getName() == "set") {
InstPatNode = InstPatNode->getChild(InstPatNode->getNumChildren()-1);
}
- bool HasVarOps = isRoot && II.isVariadic;
+ bool IsVariadic = isRoot && II.isVariadic;
// FIXME: fix how we deal with physical register operands.
bool HasImpInputs = isRoot && Inst.getNumImpOperands() > 0;
bool HasImpResults = isRoot && DstRegs.size() > 0;
unsigned NumResults = Inst.getNumResults();
unsigned NumDstRegs = HasImpResults ? DstRegs.size() : 0;
+ // Record output varargs info.
+ OutputIsVariadic = IsVariadic;
+
if (NodeHasOptInFlag) {
emitCode("bool HasInFlag = "
"(N.getOperand(N.getNumOperands()-1).getValueType() == MVT::Flag);");
}
- if (HasVarOps)
- emitCode("SmallVector<SDOperand, 8> Ops" + utostr(OpcNo) + ";");
+ if (IsVariadic)
+ emitCode("SmallVector<SDValue, 8> Ops" + utostr(OpcNo) + ";");
// How many results is this pattern expected to produce?
unsigned NumPatResults = 0;
for (unsigned i = 0, e = Pattern->getExtTypes().size(); i != e; i++) {
- MVT::ValueType VT = Pattern->getTypeNum(i);
+ MVT::SimpleValueType VT = Pattern->getTypeNum(i);
if (VT != MVT::isVoid && VT != MVT::Flag)
NumPatResults++;
}
// 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;");
+ emitCode("SmallVector<SDValue, 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("if (" + OrigChains[i].first + ".getNode() != " +
+ OrigChains[i].second + ".getNode()) {");
emitCode(" InChains.push_back(" + OrigChains[i].first + ");");
emitCode("}");
}
- emitCode("AddToISelQueue(" + ChainName + ");");
emitCode("InChains.push_back(" + ChainName + ");");
- emitCode(ChainName + " = CurDAG->getNode(ISD::TokenFactor, MVT::Other, "
+ emitCode(ChainName + " = CurDAG->getNode(ISD::TokenFactor, "
+ "N.getDebugLoc(), MVT::Other, "
"&InChains[0], InChains.size());");
+ if (GenDebug) {
+ emitCode("CurDAG->setSubgraphColor(" + ChainName +".getNode(), \"yellow\");");
+ emitCode("CurDAG->setSubgraphColor(" + ChainName +".getNode(), \"black\");");
+ }
}
// Loop over all of the operands of the instruction pattern, emitting code
// in the 'execute always' values. Match up the node operands to the
// instruction operands to do this.
std::vector<std::string> AllOps;
- unsigned NumEAInputs = 0; // # of synthesized 'execute always' inputs.
for (unsigned ChildNo = 0, InstOpNo = NumResults;
InstOpNo != II.OperandList.size(); ++InstOpNo) {
std::vector<std::string> Ops;
- // If this is a normal operand or a predicate operand without
- // 'execute always', emit it.
+ // Determine what to emit for this operand.
Record *OperandNode = II.OperandList[InstOpNo].Rec;
- if ((!OperandNode->isSubClassOf("PredicateOperand") &&
- !OperandNode->isSubClassOf("OptionalDefOperand")) ||
- CGP.getDefaultOperand(OperandNode).DefaultOps.empty()) {
- Ops = EmitResultCode(N->getChild(ChildNo), DstRegs,
- InFlagDecled, ResNodeDecled);
- AllOps.insert(AllOps.end(), Ops.begin(), Ops.end());
- ++ChildNo;
- } else {
- // Otherwise, this is a predicate or optional def operand, emit the
+ if ((OperandNode->isSubClassOf("PredicateOperand") ||
+ OperandNode->isSubClassOf("OptionalDefOperand")) &&
+ !CGP.getDefaultOperand(OperandNode).DefaultOps.empty()) {
+ // This is a predicate or optional def operand; emit the
// 'default ops' operands.
const DAGDefaultOperand &DefaultOp =
CGP.getDefaultOperand(II.OperandList[InstOpNo].Rec);
Ops = EmitResultCode(DefaultOp.DefaultOps[i], DstRegs,
InFlagDecled, ResNodeDecled);
AllOps.insert(AllOps.end(), Ops.begin(), Ops.end());
- NumEAInputs += Ops.size();
}
- }
- }
-
- // Generate MemOperandSDNodes nodes for each memory accesses covered by
- // this pattern.
- if (II.isSimpleLoad | II.mayLoad | II.mayStore) {
- std::vector<std::string>::const_iterator mi, mie;
- for (mi = LSI.begin(), mie = LSI.end(); mi != mie; ++mi) {
- emitCode("SDOperand LSI_" + *mi + " = "
- "CurDAG->getMemOperand(cast<LSBaseSDNode>(" +
- *mi + ")->getMemOperand());");
- AllOps.push_back("LSI_" + *mi);
+ } else {
+ // Otherwise this is a normal operand or a predicate operand without
+ // 'execute always'; emit it.
+ Ops = EmitResultCode(N->getChild(ChildNo), DstRegs,
+ InFlagDecled, ResNodeDecled);
+ AllOps.insert(AllOps.end(), Ops.begin(), Ops.end());
+ ++ChildNo;
}
}
// Emit all the chain and CopyToReg stuff.
bool ChainEmitted = NodeHasChain;
- if (NodeHasChain)
- emitCode("AddToISelQueue(" + ChainName + ");");
if (NodeHasInFlag || HasImpInputs)
EmitInFlagSelectCode(Pattern, "N", ChainEmitted,
InFlagDecled, ResNodeDecled, true);
if (NodeHasOptInFlag || NodeHasInFlag || HasImpInputs) {
if (!InFlagDecled) {
- emitCode("SDOperand InFlag(0, 0);");
+ emitCode("SDValue InFlag(0, 0);");
InFlagDecled = true;
}
if (NodeHasOptInFlag) {
emitCode("if (HasInFlag) {");
emitCode(" InFlag = N.getOperand(N.getNumOperands()-1);");
- emitCode(" AddToISelQueue(InFlag);");
emitCode("}");
}
}
unsigned ResNo = TmpNo++;
- if (!isRoot || InputHasChain || NodeHasChain || NodeHasOutFlag ||
- NodeHasOptInFlag || HasImpResults) {
- std::string Code;
- std::string Code2;
- std::string NodeName;
- if (!isRoot) {
- NodeName = "Tmp" + utostr(ResNo);
- Code2 = "SDOperand " + NodeName + "(";
- } else {
- NodeName = "ResNode";
- if (!ResNodeDecled) {
- Code2 = "SDNode *" + NodeName + " = ";
- ResNodeDecled = true;
- } else
- Code2 = NodeName + " = ";
- }
- Code += "CurDAG->getTargetNode(Opc" + utostr(OpcNo);
- unsigned OpsNo = OpcNo;
- emitOpcode(II.Namespace + "::" + II.TheDef->getName());
+ unsigned OpsNo = OpcNo;
+ std::string CodePrefix;
+ bool ChainAssignmentNeeded = NodeHasChain && !isRoot;
+ std::deque<std::string> After;
+ std::string NodeName;
+ if (!isRoot) {
+ NodeName = "Tmp" + utostr(ResNo);
+ CodePrefix = "SDValue " + NodeName + "(";
+ } else {
+ NodeName = "ResNode";
+ if (!ResNodeDecled) {
+ CodePrefix = "SDNode *" + NodeName + " = ";
+ ResNodeDecled = true;
+ } else
+ CodePrefix = NodeName + " = ";
+ }
- // Output order: results, chain, flags
- // Result types.
- if (NumResults > 0 && N->getTypeNum(0) != MVT::isVoid) {
- Code += ", VT" + utostr(VTNo);
- emitVT(getEnumName(N->getTypeNum(0)));
- }
- // Add types for implicit results in physical registers, scheduler will
- // care of adding copyfromreg nodes.
- for (unsigned i = 0; i < NumDstRegs; i++) {
- Record *RR = DstRegs[i];
- if (RR->isSubClassOf("Register")) {
- MVT::ValueType RVT = getRegisterValueType(RR, CGT);
- Code += ", " + getEnumName(RVT);
- }
- }
- if (NodeHasChain)
- Code += ", MVT::Other";
- 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)
- emitCode("Ops" + utostr(OpsNo) + ".push_back(" + AllOps[i] + ");");
- AllOps.clear();
- }
+ std::string Code = "Opc" + utostr(OpcNo);
- 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)
- EndAdjust = "-1"; // Always has one flag.
- else if (NodeHasOptInFlag)
- EndAdjust = "-(HasInFlag?1:0)"; // May have a flag.
+ if (!isRoot || (InputHasChain && !NodeHasChain))
+ // For call to "getTargetNode()".
+ Code += ", N.getDebugLoc()";
- emitCode("for (unsigned i = " + utostr(NumInputs - NumEAInputs) +
- ", e = N.getNumOperands()" + EndAdjust + "; i != e; ++i) {");
+ emitOpcode(II.Namespace + "::" + II.TheDef->getName());
- emitCode(" AddToISelQueue(N.getOperand(i));");
- emitCode(" Ops" + utostr(OpsNo) + ".push_back(N.getOperand(i));");
- emitCode("}");
+ // Output order: results, chain, flags
+ // Result types.
+ if (NumResults > 0 && N->getTypeNum(0) != MVT::isVoid) {
+ Code += ", VT" + utostr(VTNo);
+ emitVT(getEnumName(N->getTypeNum(0)));
+ }
+ // Add types for implicit results in physical registers, scheduler will
+ // care of adding copyfromreg nodes.
+ for (unsigned i = 0; i < NumDstRegs; i++) {
+ Record *RR = DstRegs[i];
+ if (RR->isSubClassOf("Register")) {
+ MVT::SimpleValueType RVT = getRegisterValueType(RR, CGT);
+ Code += ", " + getEnumName(RVT);
}
+ }
+ if (NodeHasChain)
+ Code += ", MVT::Other";
+ if (NodeHasOutFlag)
+ Code += ", MVT::Flag";
+
+ // Inputs.
+ if (IsVariadic) {
+ for (unsigned i = 0, e = AllOps.size(); i != e; ++i)
+ emitCode("Ops" + utostr(OpsNo) + ".push_back(" + AllOps[i] + ");");
+ AllOps.clear();
+
+ // 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)
+ EndAdjust = "-1"; // Always has one flag.
+ else if (NodeHasOptInFlag)
+ EndAdjust = "-(HasInFlag?1:0)"; // May have a flag.
+
+ emitCode("for (unsigned i = NumInputRootOps + " + utostr(NodeHasChain) +
+ ", e = N.getNumOperands()" + EndAdjust + "; i != e; ++i) {");
+
+ emitCode(" Ops" + utostr(OpsNo) + ".push_back(N.getOperand(i));");
+ emitCode("}");
+ }
- if (NodeHasChain) {
- if (HasVarOps)
- emitCode("Ops" + utostr(OpsNo) + ".push_back(" + ChainName + ");");
+ // Generate MemOperandSDNodes nodes for each memory accesses covered by
+ // this pattern.
+ if (II.mayLoad | II.mayStore) {
+ std::vector<std::string>::const_iterator mi, mie;
+ for (mi = LSI.begin(), mie = LSI.end(); mi != mie; ++mi) {
+ std::string LSIName = "LSI_" + *mi;
+ emitCode("SDValue " + LSIName + " = "
+ "CurDAG->getMemOperand(cast<MemSDNode>(" +
+ *mi + ")->getMemOperand());");
+ if (GenDebug) {
+ emitCode("CurDAG->setSubgraphColor(" + LSIName +".getNode(), \"yellow\");");
+ emitCode("CurDAG->setSubgraphColor(" + LSIName +".getNode(), \"black\");");
+ }
+ if (IsVariadic)
+ emitCode("Ops" + utostr(OpsNo) + ".push_back(" + LSIName + ");");
else
- AllOps.push_back(ChainName);
+ AllOps.push_back(LSIName);
}
+ }
- if (HasVarOps) {
- if (NodeHasInFlag || HasImpInputs)
- emitCode("Ops" + utostr(OpsNo) + ".push_back(InFlag);");
- else if (NodeHasOptInFlag) {
- emitCode("if (HasInFlag)");
- emitCode(" Ops" + utostr(OpsNo) + ".push_back(InFlag);");
- }
- Code += ", &Ops" + utostr(OpsNo) + "[0], Ops" + utostr(OpsNo) +
- ".size()";
- } else if (NodeHasInFlag || NodeHasOptInFlag || HasImpInputs)
- AllOps.push_back("InFlag");
-
- unsigned NumOps = AllOps.size();
- if (NumOps) {
- if (!NodeHasOptInFlag && NumOps < 4) {
- for (unsigned i = 0; i != NumOps; ++i)
- Code += ", " + AllOps[i];
- } else {
- std::string OpsCode = "SDOperand Ops" + utostr(OpsNo) + "[] = { ";
- for (unsigned i = 0; i != NumOps; ++i) {
- OpsCode += AllOps[i];
- if (i != NumOps-1)
- OpsCode += ", ";
- }
- emitCode(OpsCode + " };");
- Code += ", Ops" + utostr(OpsNo) + ", ";
- if (NodeHasOptInFlag) {
- Code += "HasInFlag ? ";
- Code += utostr(NumOps) + " : " + utostr(NumOps-1);
- } else
- Code += utostr(NumOps);
+ if (NodeHasChain) {
+ if (IsVariadic)
+ emitCode("Ops" + utostr(OpsNo) + ".push_back(" + ChainName + ");");
+ else
+ AllOps.push_back(ChainName);
+ }
+
+ if (IsVariadic) {
+ if (NodeHasInFlag || HasImpInputs)
+ emitCode("Ops" + utostr(OpsNo) + ".push_back(InFlag);");
+ else if (NodeHasOptInFlag) {
+ emitCode("if (HasInFlag)");
+ emitCode(" Ops" + utostr(OpsNo) + ".push_back(InFlag);");
+ }
+ Code += ", &Ops" + utostr(OpsNo) + "[0], Ops" + utostr(OpsNo) +
+ ".size()";
+ } else if (NodeHasInFlag || NodeHasOptInFlag || HasImpInputs)
+ AllOps.push_back("InFlag");
+
+ unsigned NumOps = AllOps.size();
+ if (NumOps) {
+ if (!NodeHasOptInFlag && NumOps < 4) {
+ for (unsigned i = 0; i != NumOps; ++i)
+ Code += ", " + AllOps[i];
+ } else {
+ std::string OpsCode = "SDValue Ops" + utostr(OpsNo) + "[] = { ";
+ for (unsigned i = 0; i != NumOps; ++i) {
+ OpsCode += AllOps[i];
+ if (i != NumOps-1)
+ OpsCode += ", ";
}
+ emitCode(OpsCode + " };");
+ Code += ", Ops" + utostr(OpsNo) + ", ";
+ if (NodeHasOptInFlag) {
+ Code += "HasInFlag ? ";
+ Code += utostr(NumOps) + " : " + utostr(NumOps-1);
+ } else
+ Code += utostr(NumOps);
}
-
- if (!isRoot)
- Code += "), 0";
- emitCode(Code2 + Code + ");");
+ }
+
+ if (!isRoot)
+ Code += "), 0";
- if (NodeHasChain) {
- // Remember which op produces the chain.
- if (!isRoot)
- emitCode(ChainName + " = SDOperand(" + NodeName +
- ".Val, " + utostr(NumResults+NumDstRegs) + ");");
- else
- emitCode(ChainName + " = SDOperand(" + NodeName +
- ", " + utostr(NumResults+NumDstRegs) + ");");
- }
+ std::vector<std::string> ReplaceFroms;
+ std::vector<std::string> ReplaceTos;
+ if (!isRoot) {
+ NodeOps.push_back("Tmp" + utostr(ResNo));
+ } else {
- if (!isRoot) {
- NodeOps.push_back("Tmp" + utostr(ResNo));
- return NodeOps;
- }
+ if (NodeHasOutFlag) {
+ if (!InFlagDecled) {
+ After.push_back("SDValue InFlag(ResNode, " +
+ utostr(NumResults+NumDstRegs+(unsigned)NodeHasChain) +
+ ");");
+ InFlagDecled = true;
+ } else
+ After.push_back("InFlag = SDValue(ResNode, " +
+ utostr(NumResults+NumDstRegs+(unsigned)NodeHasChain) +
+ ");");
+ }
- bool NeedReplace = false;
- if (NodeHasOutFlag) {
- if (!InFlagDecled) {
- emitCode("SDOperand InFlag(ResNode, " +
- utostr(NumResults+NumDstRegs+(unsigned)NodeHasChain) + ");");
- InFlagDecled = true;
- } else
- emitCode("InFlag = SDOperand(ResNode, " +
- utostr(NumResults+NumDstRegs+(unsigned)NodeHasChain) + ");");
- }
+ for (unsigned j = 0, e = FoldedChains.size(); j < e; j++) {
+ ReplaceFroms.push_back("SDValue(" +
+ FoldedChains[j].first + ".getNode(), " +
+ utostr(FoldedChains[j].second) +
+ ")");
+ ReplaceTos.push_back("SDValue(ResNode, " +
+ utostr(NumResults+NumDstRegs) + ")");
+ }
- if (FoldedChains.size() > 0) {
- std::string Code;
- for (unsigned j = 0, e = FoldedChains.size(); j < e; j++)
- emitCode("ReplaceUses(SDOperand(" +
- FoldedChains[j].first + ".Val, " +
- utostr(FoldedChains[j].second) + "), SDOperand(ResNode, " +
- utostr(NumResults+NumDstRegs) + "));");
- NeedReplace = true;
+ if (NodeHasOutFlag) {
+ if (FoldedFlag.first != "") {
+ ReplaceFroms.push_back("SDValue(" + FoldedFlag.first + ".getNode(), " +
+ utostr(FoldedFlag.second) + ")");
+ ReplaceTos.push_back("InFlag");
+ } else {
+ assert(NodeHasProperty(Pattern, SDNPOutFlag, CGP));
+ ReplaceFroms.push_back("SDValue(N.getNode(), " +
+ utostr(NumPatResults + (unsigned)InputHasChain)
+ + ")");
+ ReplaceTos.push_back("InFlag");
}
+ }
+
+ if (!ReplaceFroms.empty() && InputHasChain) {
+ ReplaceFroms.push_back("SDValue(N.getNode(), " +
+ utostr(NumPatResults) + ")");
+ ReplaceTos.push_back("SDValue(" + ChainName + ".getNode(), " +
+ ChainName + ".getResNo()" + ")");
+ ChainAssignmentNeeded |= NodeHasChain;
+ }
+ // User does not expect the instruction would produce a chain!
+ if ((!InputHasChain && NodeHasChain) && NodeHasOutFlag) {
+ ;
+ } else if (InputHasChain && !NodeHasChain) {
+ // One of the inner node produces a chain.
if (NodeHasOutFlag) {
- if (FoldedFlag.first != "") {
- emitCode("ReplaceUses(SDOperand(" + FoldedFlag.first + ".Val, " +
- utostr(FoldedFlag.second) + "), InFlag);");
- } else {
- assert(NodeHasProperty(Pattern, SDNPOutFlag, CGP));
- emitCode("ReplaceUses(SDOperand(N.Val, " +
- utostr(NumPatResults + (unsigned)InputHasChain)
- +"), InFlag);");
- }
- NeedReplace = true;
+ ReplaceFroms.push_back("SDValue(N.getNode(), " +
+ utostr(NumPatResults+1) +
+ ")");
+ ReplaceTos.push_back("SDValue(ResNode, N.getResNo()-1)");
}
+ ReplaceFroms.push_back("SDValue(N.getNode(), " +
+ utostr(NumPatResults) + ")");
+ ReplaceTos.push_back(ChainName);
+ }
+ }
- if (NeedReplace && InputHasChain)
- emitCode("ReplaceUses(SDOperand(N.Val, " +
- utostr(NumPatResults) + "), SDOperand(" + ChainName
- + ".Val, " + ChainName + ".ResNo" + "));");
-
- // User does not expect the instruction would produce a chain!
- if ((!InputHasChain && NodeHasChain) && NodeHasOutFlag) {
- ;
- } else if (InputHasChain && !NodeHasChain) {
- // One of the inner node produces a chain.
- if (NodeHasOutFlag)
- emitCode("ReplaceUses(SDOperand(N.Val, " + utostr(NumPatResults+1) +
- "), SDOperand(ResNode, N.ResNo-1));");
- emitCode("ReplaceUses(SDOperand(N.Val, " + utostr(NumPatResults) +
- "), " + ChainName + ");");
- }
+ if (ChainAssignmentNeeded) {
+ // Remember which op produces the chain.
+ std::string ChainAssign;
+ if (!isRoot)
+ ChainAssign = ChainName + " = SDValue(" + NodeName +
+ ".getNode(), " + utostr(NumResults+NumDstRegs) + ");";
+ else
+ ChainAssign = ChainName + " = SDValue(" + NodeName +
+ ", " + utostr(NumResults+NumDstRegs) + ");";
+
+ After.push_front(ChainAssign);
+ }
- emitCode("return ResNode;");
+ if (ReplaceFroms.size() == 1) {
+ After.push_back("ReplaceUses(" + ReplaceFroms[0] + ", " +
+ ReplaceTos[0] + ");");
+ } else if (!ReplaceFroms.empty()) {
+ After.push_back("const SDValue Froms[] = {");
+ for (unsigned i = 0, e = ReplaceFroms.size(); i != e; ++i)
+ After.push_back(" " + ReplaceFroms[i] + (i + 1 != e ? "," : ""));
+ After.push_back("};");
+ After.push_back("const SDValue Tos[] = {");
+ for (unsigned i = 0, e = ReplaceFroms.size(); i != e; ++i)
+ After.push_back(" " + ReplaceTos[i] + (i + 1 != e ? "," : ""));
+ After.push_back("};");
+ After.push_back("ReplaceUses(Froms, Tos, " +
+ itostr(ReplaceFroms.size()) + ");");
+ }
+
+ // We prefer to use SelectNodeTo since it avoids allocation when
+ // possible and it avoids CSE map recalculation for the node's
+ // users, however it's tricky to use in a non-root context.
+ //
+ // We also don't use if the pattern replacement is being used to
+ // jettison a chain result, since morphing the node in place
+ // would leave users of the chain dangling.
+ //
+ if (!isRoot || (InputHasChain && !NodeHasChain)) {
+ Code = "CurDAG->getTargetNode(" + Code;
} else {
- std::string Code = "return CurDAG->SelectNodeTo(N.Val, Opc" +
- utostr(OpcNo);
- if (N->getTypeNum(0) != MVT::isVoid)
- Code += ", VT" + utostr(VTNo);
- if (NodeHasOutFlag)
- Code += ", MVT::Flag";
-
- if (NodeHasInFlag || NodeHasOptInFlag || HasImpInputs)
- AllOps.push_back("InFlag");
-
- unsigned NumOps = AllOps.size();
- if (NumOps) {
- if (!NodeHasOptInFlag && NumOps < 4) {
- for (unsigned i = 0; i != NumOps; ++i)
- Code += ", " + AllOps[i];
- } else {
- std::string OpsCode = "SDOperand Ops" + utostr(OpcNo) + "[] = { ";
- for (unsigned i = 0; i != NumOps; ++i) {
- OpsCode += AllOps[i];
- if (i != NumOps-1)
- OpsCode += ", ";
- }
- emitCode(OpsCode + " };");
- Code += ", Ops" + utostr(OpcNo) + ", ";
- Code += utostr(NumOps);
- }
+ Code = "CurDAG->SelectNodeTo(N.getNode(), " + Code;
+ }
+ if (isRoot) {
+ if (After.empty())
+ CodePrefix = "return ";
+ else
+ After.push_back("return ResNode;");
+ }
+
+ emitCode(CodePrefix + Code + ");");
+
+ if (GenDebug) {
+ if (!isRoot) {
+ emitCode("CurDAG->setSubgraphColor(" + NodeName +".getNode(), \"yellow\");");
+ emitCode("CurDAG->setSubgraphColor(" + NodeName +".getNode(), \"black\");");
+ }
+ else {
+ emitCode("CurDAG->setSubgraphColor(" + NodeName +", \"yellow\");");
+ emitCode("CurDAG->setSubgraphColor(" + NodeName +", \"black\");");
}
- emitCode(Code + ");");
- emitOpcode(II.Namespace + "::" + II.TheDef->getName());
- if (N->getTypeNum(0) != MVT::isVoid)
- emitVT(getEnumName(N->getTypeNum(0)));
}
+ for (unsigned i = 0, e = After.size(); i != e; ++i)
+ emitCode(After[i]);
+
return NodeOps;
- } else if (Op->isSubClassOf("SDNodeXForm")) {
+ }
+ 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.
EmitResultCode(N->getChild(0), DstRegs, InFlagDecled,
ResNodeDecled, true);
unsigned ResNo = TmpNo++;
- emitCode("SDOperand Tmp" + utostr(ResNo) + " = Transform_" + Op->getName()
- + "(" + Ops.back() + ".Val);");
+ emitCode("SDValue Tmp" + utostr(ResNo) + " = Transform_" + Op->getName()
+ + "(" + Ops.back() + ".getNode());");
NodeOps.push_back("Tmp" + utostr(ResNo));
if (isRoot)
- emitCode("return Tmp" + utostr(ResNo) + ".Val;");
+ emitCode("return Tmp" + utostr(ResNo) + ".getNode();");
return NodeOps;
- } else {
- N->dump();
- cerr << "\n";
- throw std::string("Unknown node in result pattern!");
}
+
+ N->dump();
+ errs() << "\n";
+ throw std::string("Unknown node in result pattern!");
}
/// InsertOneTypeCheck - Insert a type-check for an unresolved type in 'Pat'
Pat->setTypes(Other->getExtTypes());
// The top level node type is checked outside of the select function.
if (!isRoot)
- emitCheck(Prefix + ".Val->getValueType(0) == " +
+ emitCheck(Prefix + ".getNode()->getValueType(0) == " +
getName(Pat->getTypeNum(0)));
return true;
}
Record *RR = DI->getDef();
if (RR->isSubClassOf("Register")) {
- MVT::ValueType RVT = getRegisterValueType(RR, T);
+ MVT::SimpleValueType RVT = getRegisterValueType(RR, T);
if (RVT == MVT::Flag) {
if (!InFlagDecled) {
- emitCode("SDOperand InFlag = " + RootName + utostr(OpNo) + ";");
+ emitCode("SDValue InFlag = " + RootName + utostr(OpNo) + ";");
InFlagDecled = true;
} else
emitCode("InFlag = " + RootName + utostr(OpNo) + ";");
- emitCode("AddToISelQueue(InFlag);");
} else {
if (!ChainEmitted) {
- emitCode("SDOperand Chain = CurDAG->getEntryNode();");
+ emitCode("SDValue Chain = CurDAG->getEntryNode();");
ChainName = "Chain";
ChainEmitted = true;
}
- emitCode("AddToISelQueue(" + RootName + utostr(OpNo) + ");");
if (!InFlagDecled) {
- emitCode("SDOperand InFlag(0, 0);");
+ emitCode("SDValue InFlag(0, 0);");
InFlagDecled = true;
}
std::string Decl = (!ResNodeDecled) ? "SDNode *" : "";
emitCode(Decl + "ResNode = CurDAG->getCopyToReg(" + ChainName +
+ ", " + RootName + ".getDebugLoc()" +
", " + getQualifiedName(RR) +
- ", " + RootName + utostr(OpNo) + ", InFlag).Val;");
+ ", " + RootName + utostr(OpNo) + ", InFlag).getNode();");
ResNodeDecled = true;
- emitCode(ChainName + " = SDOperand(ResNode, 0);");
- emitCode("InFlag = SDOperand(ResNode, 1);");
+ emitCode(ChainName + " = SDValue(ResNode, 0);");
+ emitCode("InFlag = SDValue(ResNode, 1);");
}
}
}
if (HasInFlag) {
if (!InFlagDecled) {
- emitCode("SDOperand InFlag = " + RootName +
+ emitCode("SDValue InFlag = " + RootName +
".getOperand(" + utostr(OpNo) + ");");
InFlagDecled = true;
} else
emitCode("InFlag = " + RootName +
".getOperand(" + utostr(OpNo) + ");");
- emitCode("AddToISelQueue(InFlag);");
}
}
};
std::vector<std::pair<unsigned, std::string> > &GeneratedCode,
std::set<std::string> &GeneratedDecl,
std::vector<std::string> &TargetOpcodes,
- std::vector<std::string> &TargetVTs) {
- PatternCodeEmitter Emitter(CGP, Pattern.getPredicates(),
+ std::vector<std::string> &TargetVTs,
+ bool &OutputIsVariadic,
+ unsigned &NumInputRootOps) {
+ OutputIsVariadic = false;
+ NumInputRootOps = 0;
+
+ PatternCodeEmitter Emitter(CGP, Pattern.getPredicateCheck(),
Pattern.getSrcPattern(), Pattern.getDstPattern(),
GeneratedCode, GeneratedDecl,
- TargetOpcodes, TargetVTs);
+ TargetOpcodes, TargetVTs,
+ OutputIsVariadic, NumInputRootOps);
// Emit the matcher, capturing named arguments in VariableMap.
bool FoundChain = false;
void DAGISelEmitter::EmitPatterns(std::vector<std::pair<const PatternToMatch*,
std::vector<std::pair<unsigned, std::string> > > >
&Patterns, unsigned Indent,
- std::ostream &OS) {
+ raw_ostream &OS) {
typedef std::pair<unsigned, std::string> CodeLine;
typedef std::vector<CodeLine> CodeList;
typedef std::vector<std::pair<const PatternToMatch*, CodeList> > PatternList;
// 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 == 1) {
- // Check that all of fhe patterns in Patterns end with the same predicate.
+ // Check that all of the patterns in Patterns end with the same predicate.
bool AllEndWithSamePredicate = true;
for (unsigned i = 0, e = Patterns.size(); i != e; ++i)
if (Patterns[i].second.back() != Patterns.back().second.back()) {
OS << std::string(Indent-2, ' ') << "}\n";
}
-static std::string getOpcodeName(Record *Op, CodeGenDAGPatterns &CGP) {
- return CGP.getSDNodeInfo(Op).getEnumName();
-}
-
static std::string getLegalCName(std::string OpName) {
std::string::size_type pos = OpName.find("::");
if (pos != std::string::npos)
return OpName;
}
-void DAGISelEmitter::EmitInstructionSelector(std::ostream &OS) {
+void DAGISelEmitter::EmitInstructionSelector(raw_ostream &OS) {
const CodeGenTarget &Target = CGP.getTargetInfo();
- // 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;
- }
-
+ // Get the namespace to insert instructions into.
+ std::string InstNS = Target.getInstNamespace();
if (!InstNS.empty()) InstNS += "::";
// Group the patterns by their top-level opcodes.
&Pattern);
}
} else {
- cerr << "Unrecognized opcode '";
+ errs() << "Unrecognized opcode '";
Node->dump();
- cerr << "' on tree pattern '";
- cerr << Pattern.getDstPattern()->getOperator()->getName() << "'!\n";
+ errs() << "' on tree pattern '";
+ errs() << Pattern.getDstPattern()->getOperator()->getName() << "'!\n";
exit(1);
}
}
std::vector<const PatternToMatch*> &PatternsOfOp = PBOI->second;
assert(!PatternsOfOp.empty() && "No patterns but map has entry?");
- // 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.
- std::stable_sort(PatternsOfOp.begin(), PatternsOfOp.end(),
- PatternSortingPredicate(CGP));
-
// Split them into groups by type.
- std::map<MVT::ValueType, std::vector<const PatternToMatch*> >PatternsByType;
+ std::map<MVT::SimpleValueType,
+ std::vector<const PatternToMatch*> > PatternsByType;
for (unsigned i = 0, e = PatternsOfOp.size(); i != e; ++i) {
const PatternToMatch *Pat = PatternsOfOp[i];
TreePatternNode *SrcPat = Pat->getSrcPattern();
- MVT::ValueType VT = SrcPat->getTypeNum(0);
- std::map<MVT::ValueType,
- std::vector<const PatternToMatch*> >::iterator TI =
- PatternsByType.find(VT);
- if (TI != PatternsByType.end())
- TI->second.push_back(Pat);
- else {
- std::vector<const PatternToMatch*> PVec;
- PVec.push_back(Pat);
- PatternsByType.insert(std::make_pair(VT, PVec));
- }
+ PatternsByType[SrcPat->getTypeNum(0)].push_back(Pat);
}
- for (std::map<MVT::ValueType, std::vector<const PatternToMatch*> >::iterator
+ for (std::map<MVT::SimpleValueType,
+ std::vector<const PatternToMatch*> >::iterator
II = PatternsByType.begin(), EE = PatternsByType.end(); II != EE;
++II) {
- MVT::ValueType OpVT = II->first;
+ MVT::SimpleValueType OpVT = II->first;
std::vector<const PatternToMatch*> &Patterns = II->second;
- typedef std::vector<std::pair<unsigned,std::string> > CodeList;
- typedef std::vector<std::pair<unsigned,std::string> >::iterator CodeListI;
+ typedef std::pair<unsigned, std::string> CodeLine;
+ typedef std::vector<CodeLine> CodeList;
+ typedef CodeList::iterator CodeListI;
std::vector<std::pair<const PatternToMatch*, CodeList> > CodeForPatterns;
std::vector<std::vector<std::string> > PatternOpcodes;
std::vector<std::vector<std::string> > PatternVTs;
std::vector<std::set<std::string> > PatternDecls;
+ std::vector<bool> OutputIsVariadicFlags;
+ std::vector<unsigned> NumInputRootOpsCounts;
for (unsigned i = 0, e = Patterns.size(); i != e; ++i) {
CodeList GeneratedCode;
std::set<std::string> GeneratedDecl;
std::vector<std::string> TargetOpcodes;
std::vector<std::string> TargetVTs;
+ bool OutputIsVariadic;
+ unsigned NumInputRootOps;
GenerateCodeForPattern(*Patterns[i], GeneratedCode, GeneratedDecl,
- TargetOpcodes, TargetVTs);
+ TargetOpcodes, TargetVTs,
+ OutputIsVariadic, NumInputRootOps);
CodeForPatterns.push_back(std::make_pair(Patterns[i], GeneratedCode));
PatternDecls.push_back(GeneratedDecl);
PatternOpcodes.push_back(TargetOpcodes);
PatternVTs.push_back(TargetVTs);
+ OutputIsVariadicFlags.push_back(OutputIsVariadic);
+ NumInputRootOpsCounts.push_back(NumInputRootOps);
}
- // Scan the code to see if all of the patterns are reachable and if it is
- // possible that the last one might not match.
- bool mightNotMatch = true;
- for (unsigned i = 0, e = CodeForPatterns.size(); i != e; ++i) {
- CodeList &GeneratedCode = CodeForPatterns[i].second;
- mightNotMatch = false;
-
- for (unsigned j = 0, e = GeneratedCode.size(); j != e; ++j) {
- if (GeneratedCode[j].first == 1) { // predicate.
- mightNotMatch = true;
- break;
- }
- }
-
- // 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) {
- cerr << "Pattern '";
- CodeForPatterns[i].first->getSrcPattern()->print(*cerr.stream());
- cerr << "' is impossible to select!\n";
- exit(1);
- }
- }
-
// Factor target node emission code (emitted by EmitResultCode) into
// separate functions. Uniquing and share them among all instruction
// selection routines.
std::vector<std::string> &TargetOpcodes = PatternOpcodes[i];
std::vector<std::string> &TargetVTs = PatternVTs[i];
std::set<std::string> Decls = PatternDecls[i];
+ bool OutputIsVariadic = OutputIsVariadicFlags[i];
+ unsigned NumInputRootOps = NumInputRootOpsCounts[i];
std::vector<std::string> AddedInits;
int CodeSize = (int)GeneratedCode.size();
int LastPred = -1;
AddedInits.push_back(GeneratedCode[j].second);
}
- std::string CalleeCode = "(const SDOperand &N";
+ std::string CalleeCode = "(const SDValue &N";
std::string CallerCode = "(N";
for (unsigned j = 0, e = TargetOpcodes.size(); j != e; ++j) {
CalleeCode += ", unsigned Opc" + utostr(j);
CallerCode += ", " + TargetOpcodes[j];
}
for (unsigned j = 0, e = TargetVTs.size(); j != e; ++j) {
- CalleeCode += ", MVT::ValueType VT" + utostr(j);
+ CalleeCode += ", MVT::SimpleValueType VT" + utostr(j);
CallerCode += ", " + TargetVTs[j];
}
for (std::set<std::string>::iterator
I = Decls.begin(), E = Decls.end(); I != E; ++I) {
std::string Name = *I;
- CalleeCode += ", SDOperand &" + Name;
+ CalleeCode += ", SDValue &" + Name;
CallerCode += ", " + Name;
}
+
+ if (OutputIsVariadic) {
+ CalleeCode += ", unsigned NumInputRootOps";
+ CallerCode += ", " + utostr(NumInputRootOps);
+ }
+
CallerCode += ");";
CalleeCode += ") ";
// Prevent emission routines from being inlined to reduce selection
// Replace the emission code within selection routines with calls to the
// emission functions.
- CallerCode = "return Emit_" + utostr(EmitFuncNum) + CallerCode;
- GeneratedCode.push_back(std::make_pair(false, CallerCode));
+ if (GenDebug) {
+ GeneratedCode.push_back(std::make_pair(0, "CurDAG->setSubgraphColor(N.getNode(), \"red\");"));
+ }
+ CallerCode = "SDNode *Result = Emit_" + utostr(EmitFuncNum) + CallerCode;
+ GeneratedCode.push_back(std::make_pair(3, CallerCode));
+ if (GenDebug) {
+ GeneratedCode.push_back(std::make_pair(0, "if(Result) {"));
+ GeneratedCode.push_back(std::make_pair(0, " CurDAG->setSubgraphColor(Result, \"yellow\");"));
+ GeneratedCode.push_back(std::make_pair(0, " CurDAG->setSubgraphColor(Result, \"black\");"));
+ GeneratedCode.push_back(std::make_pair(0, "}"));
+ //GeneratedCode.push_back(std::make_pair(0, "CurDAG->setSubgraphColor(N.getNode(), \"black\");"));
+ }
+ GeneratedCode.push_back(std::make_pair(0, "return Result;"));
}
// Print function.
std::string OpVTStr;
if (OpVT == MVT::iPTR) {
OpVTStr = "_iPTR";
+ } else if (OpVT == MVT::iPTRAny) {
+ OpVTStr = "_iPTRAny";
} 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
} else
OpVTI->second.push_back(OpVTStr);
- OS << "SDNode *Select_" << getLegalCName(OpName)
- << OpVTStr << "(const SDOperand &N) {\n";
+ // 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.
+ std::stable_sort(CodeForPatterns.begin(), CodeForPatterns.end(),
+ PatternSortingPredicate(CGP));
+
+ // Scan the code to see if all of the patterns are reachable and if it is
+ // possible that the last one might not match.
+ bool mightNotMatch = true;
+ for (unsigned i = 0, e = CodeForPatterns.size(); i != e; ++i) {
+ CodeList &GeneratedCode = CodeForPatterns[i].second;
+ mightNotMatch = false;
+
+ for (unsigned j = 0, e = GeneratedCode.size(); j != e; ++j) {
+ if (GeneratedCode[j].first == 1) { // predicate.
+ mightNotMatch = true;
+ break;
+ }
+ }
+
+ // 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) {
+ errs() << "Pattern '";
+ CodeForPatterns[i].first->getSrcPattern()->print(errs());
+ errs() << "' is impossible to select!\n";
+ exit(1);
+ }
+ }
// 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
// Next, reverse the list of patterns itself for the same reason.
std::reverse(CodeForPatterns.begin(), CodeForPatterns.end());
+ OS << "SDNode *Select_" << getLegalCName(OpName)
+ << OpVTStr << "(const SDValue &N) {\n";
+
// Emit all of the patterns now, grouped together to share code.
EmitPatterns(CodeForPatterns, 2, OS);
// If the last pattern has predicates (which could fail) emit code to
// catch the case where nothing handles a pattern.
if (mightNotMatch) {
- OS << " cerr << \"Cannot yet select: \";\n";
+ OS << "\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"
- << " cerr << \"intrinsic %\"<< "
- "Intrinsic::getName((Intrinsic::ID)iid);\n";
- }
- OS << " cerr << '\\n';\n"
- << " abort();\n"
- << " return NULL;\n";
+ OpName != "ISD::INTRINSIC_VOID")
+ OS << " CannotYetSelect(N);\n";
+ else
+ OS << " CannotYetSelectIntrinsic(N);\n";
+
+ OS << " return NULL;\n";
}
OS << "}\n\n";
}
}
// Emit boilerplate.
- OS << "SDNode *Select_INLINEASM(SDOperand N) {\n"
- << " std::vector<SDOperand> Ops(N.Val->op_begin(), N.Val->op_end());\n"
- << " SelectInlineAsmMemoryOperands(Ops, *CurDAG);\n\n"
+ OS << "SDNode *Select_INLINEASM(SDValue N) {\n"
+ << " std::vector<SDValue> Ops(N.getNode()->op_begin(), N.getNode()->op_end());\n"
+ << " SelectInlineAsmMemoryOperands(Ops);\n\n"
- << " // Ensure that the asm operands are themselves selected.\n"
- << " for (unsigned j = 0, e = Ops.size(); j != e; ++j)\n"
- << " AddToISelQueue(Ops[j]);\n\n"
-
- << " std::vector<MVT::ValueType> VTs;\n"
+ << " std::vector<EVT> VTs;\n"
<< " VTs.push_back(MVT::Other);\n"
<< " VTs.push_back(MVT::Flag);\n"
- << " SDOperand New = CurDAG->getNode(ISD::INLINEASM, VTs, &Ops[0], "
- "Ops.size());\n"
- << " return New.Val;\n"
- << "}\n\n";
-
- OS << "SDNode *Select_UNDEF(const SDOperand &N) {\n"
- << " return CurDAG->getTargetNode(TargetInstrInfo::IMPLICIT_DEF,\n"
- << " N.getValueType());\n"
+ << " SDValue New = CurDAG->getNode(ISD::INLINEASM, N.getDebugLoc(), "
+ "VTs, &Ops[0], Ops.size());\n"
+ << " return New.getNode();\n"
<< "}\n\n";
- OS << "SDNode *Select_LABEL(const SDOperand &N) {\n"
- << " SDOperand Chain = N.getOperand(0);\n"
- << " SDOperand N1 = N.getOperand(1);\n"
- << " SDOperand N2 = N.getOperand(2);\n"
- << " unsigned C1 = cast<ConstantSDNode>(N1)->getValue();\n"
- << " unsigned C2 = cast<ConstantSDNode>(N2)->getValue();\n"
- << " SDOperand Tmp1 = CurDAG->getTargetConstant(C1, MVT::i32);\n"
- << " SDOperand Tmp2 = CurDAG->getTargetConstant(C2, MVT::i32);\n"
- << " AddToISelQueue(Chain);\n"
- << " SDOperand Ops[] = { Tmp1, Tmp2, Chain };\n"
- << " return CurDAG->getTargetNode(TargetInstrInfo::LABEL,\n"
- << " MVT::Other, Ops, 3);\n"
+ OS << "SDNode *Select_UNDEF(const SDValue &N) {\n"
+ << " return CurDAG->SelectNodeTo(N.getNode(), TargetInstrInfo::IMPLICIT_DEF,\n"
+ << " N.getValueType());\n"
<< "}\n\n";
- OS << "SDNode *Select_DECLARE(const SDOperand &N) {\n"
- << " SDOperand Chain = N.getOperand(0);\n"
- << " SDOperand N1 = N.getOperand(1);\n"
- << " SDOperand N2 = N.getOperand(2);\n"
- << " if (!isa<FrameIndexSDNode>(N1) || !isa<GlobalAddressSDNode>(N2)) {\n"
- << " cerr << \"Cannot yet select llvm.dbg.declare: \";\n"
- << " N.Val->dump(CurDAG);\n"
- << " abort();\n"
- << " }\n"
- << " int FI = cast<FrameIndexSDNode>(N1)->getIndex();\n"
- << " GlobalValue *GV = cast<GlobalAddressSDNode>(N2)->getGlobal();\n"
- << " SDOperand Tmp1 = "
- << "CurDAG->getTargetFrameIndex(FI, TLI.getPointerTy());\n"
- << " SDOperand Tmp2 = "
- << "CurDAG->getTargetGlobalAddress(GV, TLI.getPointerTy());\n"
- << " AddToISelQueue(Chain);\n"
- << " SDOperand Ops[] = { Tmp1, Tmp2, Chain };\n"
- << " return CurDAG->getTargetNode(TargetInstrInfo::DECLARE,\n"
- << " MVT::Other, Ops, 3);\n"
+ OS << "SDNode *Select_DBG_LABEL(const SDValue &N) {\n"
+ << " SDValue Chain = N.getOperand(0);\n"
+ << " unsigned C = cast<LabelSDNode>(N)->getLabelID();\n"
+ << " SDValue Tmp = CurDAG->getTargetConstant(C, MVT::i32);\n"
+ << " return CurDAG->SelectNodeTo(N.getNode(), TargetInstrInfo::DBG_LABEL,\n"
+ << " MVT::Other, Tmp, Chain);\n"
<< "}\n\n";
- OS << "SDNode *Select_EXTRACT_SUBREG(const SDOperand &N) {\n"
- << " SDOperand N0 = N.getOperand(0);\n"
- << " SDOperand N1 = N.getOperand(1);\n"
- << " unsigned C = cast<ConstantSDNode>(N1)->getValue();\n"
- << " SDOperand Tmp = CurDAG->getTargetConstant(C, MVT::i32);\n"
- << " AddToISelQueue(N0);\n"
- << " SDOperand Ops[] = { N0, Tmp };\n"
- << " return CurDAG->getTargetNode(TargetInstrInfo::EXTRACT_SUBREG,\n"
- << " N.getValueType(), Ops, 2);\n"
- << "}\n\n";
-
- OS << "SDNode *Select_INSERT_SUBREG(const SDOperand &N) {\n"
- << " SDOperand N0 = N.getOperand(0);\n"
- << " SDOperand N1 = N.getOperand(1);\n"
- << " SDOperand N2 = N.getOperand(2);\n"
- << " unsigned C = cast<ConstantSDNode>(N2)->getValue();\n"
- << " SDOperand Tmp = CurDAG->getTargetConstant(C, MVT::i32);\n"
- << " AddToISelQueue(N1);\n"
- << " SDOperand Ops[] = { N0, N1, Tmp };\n"
- << " AddToISelQueue(N0);\n"
- << " return CurDAG->getTargetNode(TargetInstrInfo::INSERT_SUBREG,\n"
- << " N.getValueType(), Ops, 3);\n"
+ OS << "SDNode *Select_EH_LABEL(const SDValue &N) {\n"
+ << " SDValue Chain = N.getOperand(0);\n"
+ << " unsigned C = cast<LabelSDNode>(N)->getLabelID();\n"
+ << " SDValue Tmp = CurDAG->getTargetConstant(C, MVT::i32);\n"
+ << " return CurDAG->SelectNodeTo(N.getNode(), TargetInstrInfo::EH_LABEL,\n"
+ << " MVT::Other, Tmp, Chain);\n"
<< "}\n\n";
OS << "// The main instruction selector code.\n"
- << "SDNode *SelectCode(SDOperand N) {\n"
- << " if (N.getOpcode() >= ISD::BUILTIN_OP_END &&\n"
- << " N.getOpcode() < (ISD::BUILTIN_OP_END+" << InstNS
- << "INSTRUCTION_LIST_END)) {\n"
- << " return NULL; // Already selected.\n"
- << " }\n\n"
- << " MVT::ValueType NVT = N.Val->getValueType(0);\n"
+ << "SDNode *SelectCode(SDValue N) {\n"
+ << " MVT::SimpleValueType NVT = N.getNode()->getValueType(0).getSimpleVT().SimpleTy;\n"
<< " switch (N.getOpcode()) {\n"
- << " default: break;\n"
- << " case ISD::EntryToken: // These leaves remain the same.\n"
+ << " default:\n"
+ << " assert(!N.isMachineOpcode() && \"Node already selected!\");\n"
+ << " break;\n"
+ << " case ISD::EntryToken: // These nodes remain the same.\n"
+ << " case ISD::MEMOPERAND:\n"
<< " case ISD::BasicBlock:\n"
<< " case ISD::Register:\n"
<< " case ISD::HANDLENODE:\n"
<< " case ISD::TargetExternalSymbol:\n"
<< " case ISD::TargetJumpTable:\n"
<< " case ISD::TargetGlobalTLSAddress:\n"
- << " case ISD::TargetGlobalAddress: {\n"
+ << " case ISD::TargetGlobalAddress:\n"
+ << " case ISD::TokenFactor:\n"
+ << " case ISD::CopyFromReg:\n"
+ << " case ISD::CopyToReg: {\n"
<< " return NULL;\n"
<< " }\n"
<< " case ISD::AssertSext:\n"
<< " case ISD::AssertZext: {\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"
- << " AddToISelQueue(N.getOperand(i));\n"
- << " return NULL;\n"
- << " }\n"
<< " case ISD::INLINEASM: return Select_INLINEASM(N);\n"
- << " case ISD::LABEL: return Select_LABEL(N);\n"
- << " case ISD::DECLARE: return Select_DECLARE(N);\n"
- << " case ISD::EXTRACT_SUBREG: return Select_EXTRACT_SUBREG(N);\n"
- << " case ISD::INSERT_SUBREG: return Select_INSERT_SUBREG(N);\n"
+ << " case ISD::DBG_LABEL: return Select_DBG_LABEL(N);\n"
+ << " case ISD::EH_LABEL: return Select_EH_LABEL(N);\n"
<< " case ISD::UNDEF: return Select_UNDEF(N);\n";
-
// Loop over all of the case statements, emiting a call to each method we
// emitted above.
for (std::map<std::string, std::vector<const PatternToMatch*> >::iterator
OpcodeVTMap.find(OpName);
std::vector<std::string> &OpVTs = OpVTI->second;
OS << " case " << OpName << ": {\n";
+ // If we have only one variant and it's the default, elide the
+ // switch. Marginally faster, and makes MSVC happier.
+ if (OpVTs.size()==1 && OpVTs[0].empty()) {
+ OS << " return Select_" << getLegalCName(OpName) << "(N);\n";
+ OS << " break;\n";
+ OS << " }\n";
+ continue;
+ }
// Keep track of whether we see a pattern that has an iPtr result.
bool HasPtrPattern = false;
bool HasDefaultPattern = false;
// If there is an iPTR result version of this pattern, emit it here.
if (HasPtrPattern) {
- OS << " if (NVT == TLI.getPointerTy())\n";
+ OS << " if (TLI.getPointerTy() == NVT)\n";
OS << " return Select_" << getLegalCName(OpName) <<"_iPTR(N);\n";
}
if (HasDefaultPattern) {
}
OS << " } // end of big switch.\n\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"
- << " N.Val->dump(CurDAG);\n"
+ << " CannotYetSelect(N);\n"
<< " } else {\n"
- << " unsigned iid = cast<ConstantSDNode>(N.getOperand("
- "N.getOperand(0).getValueType() == MVT::Other))->getValue();\n"
- << " cerr << \"intrinsic %\"<< "
- "Intrinsic::getName((Intrinsic::ID)iid);\n"
+ << " CannotYetSelectIntrinsic(N);\n"
<< " }\n"
- << " cerr << '\\n';\n"
- << " abort();\n"
<< " return NULL;\n"
- << "}\n";
+ << "}\n\n";
+
+ OS << "void CannotYetSelect(SDValue N) DISABLE_INLINE {\n"
+ << " std::string msg;\n"
+ << " raw_string_ostream Msg(msg);\n"
+ << " Msg << \"Cannot yet select: \";\n"
+ << " N.getNode()->print(Msg, CurDAG);\n"
+ << " llvm_report_error(Msg.str());\n"
+ << "}\n\n";
+
+ OS << "void CannotYetSelectIntrinsic(SDValue N) DISABLE_INLINE {\n"
+ << " errs() << \"Cannot yet select: \";\n"
+ << " unsigned iid = cast<ConstantSDNode>(N.getOperand("
+ << "N.getOperand(0).getValueType() == MVT::Other))->getZExtValue();\n"
+ << " llvm_report_error(\"Cannot yet select: intrinsic %\" +\n"
+ << "Intrinsic::getName((Intrinsic::ID)iid));\n"
+ << "}\n\n";
}
-void DAGISelEmitter::run(std::ostream &OS) {
+void DAGISelEmitter::run(raw_ostream &OS) {
EmitSourceFileHeader("DAG Instruction Selector for the " +
CGP.getTargetInfo().getName() + " target", OS);
OS << "// *** NOTE: This file is #included into the middle of the target\n"
<< "// *** instruction selector class. These functions are really "
<< "methods.\n\n";
-
- OS << "// Instruction selector priority queue:\n"
- << "std::vector<SDNode*> ISelQueue;\n";
- OS << "/// Keep track of nodes which have already been added to queue.\n"
- << "unsigned char *ISelQueued;\n";
- OS << "/// Keep track of nodes which have already been selected.\n"
- << "unsigned char *ISelSelected;\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"
- << " bool operator()(const SDNode* left, const SDNode* right) "
- << "const {\n"
- << " return (left->getNodeId() > right->getNodeId());\n"
- << " }\n"
- << "};\n\n";
-
- OS << "inline void setQueued(int Id) {\n";
- OS << " ISelQueued[Id / 8] |= 1 << (Id % 8);\n";
- OS << "}\n";
- OS << "inline bool isQueued(int Id) {\n";
- OS << " return ISelQueued[Id / 8] & (1 << (Id % 8));\n";
- OS << "}\n";
- OS << "inline void setSelected(int Id) {\n";
- OS << " ISelSelected[Id / 8] |= 1 << (Id % 8);\n";
- OS << "}\n";
- OS << "inline bool isSelected(int Id) {\n";
- OS << " return ISelSelected[Id / 8] & (1 << (Id % 8));\n";
- OS << "}\n\n";
-
- OS << "void AddToISelQueue(SDOperand N) DISABLE_INLINE {\n";
- OS << " int Id = N.Val->getNodeId();\n";
- OS << " if (Id != -1 && !isQueued(Id)) {\n";
- OS << " ISelQueue.push_back(N.Val);\n";
- OS << " std::push_heap(ISelQueue.begin(), ISelQueue.end(), isel_sort());\n";
- OS << " setQueued(Id);\n";
- OS << " }\n";
- OS << "}\n\n";
-
- OS << "class VISIBILITY_HIDDEN ISelQueueUpdater :\n";
- OS << " public SelectionDAG::DAGUpdateListener {\n";
- OS << " std::vector<SDNode*> &ISelQueue;\n";
- OS << " bool HadDelete;\n";
- OS << " public:\n";
- OS << " explicit ISelQueueUpdater(std::vector<SDNode*> &isq)\n";
- OS << " : ISelQueue(isq), HadDelete(false) {}\n";
- OS << " \n";
- OS << " bool hadDelete() const { return HadDelete; }\n";
- OS << " \n";
- OS << " virtual void NodeDeleted(SDNode *N) {\n";
- OS << " ISelQueue.erase(std::remove(ISelQueue.begin(), ISelQueue.end(),";
- OS << " N),\n ISelQueue.end());\n";
- OS << " HadDelete = true;\n";
- OS << " }\n";
- OS << " \n";
- OS << " // Ignore updates.\n";
- OS << " virtual void NodeUpdated(SDNode *N) {}\n";
- OS << " };\n";
-
- OS << "inline void UpdateQueue(const ISelQueueUpdater &ISQU) {\n";
- OS << " if (ISQU.hadDelete())\n";
- OS << " std::make_heap(ISelQueue.begin(), ISelQueue.end(),isel_sort());\n";
- OS << "}\n\n";
-
- OS << "void ReplaceUses(SDOperand F, SDOperand T) DISABLE_INLINE {\n";
- OS << " ISelQueueUpdater ISQU(ISelQueue);\n";
- OS << " CurDAG->ReplaceAllUsesOfValueWith(F, T, &ISQU);\n";
- OS << " setSelected(F.Val->getNodeId());\n";
- OS << " UpdateQueue(ISQU);\n";
- OS << "}\n";
- OS << "void ReplaceUses(SDNode *F, SDNode *T) DISABLE_INLINE {\n";
- OS << " unsigned FNumVals = F->getNumValues();\n";
- OS << " unsigned TNumVals = T->getNumValues();\n";
- OS << " ISelQueueUpdater ISQU(ISelQueue);\n";
- OS << " if (FNumVals != TNumVals) {\n";
- OS << " for (unsigned i = 0, e = std::min(FNumVals, TNumVals); "
- << "i < e; ++i)\n";
- OS << " CurDAG->ReplaceAllUsesOfValueWith(SDOperand(F, i), "
- << "SDOperand(T, i), &ISQU);\n";
- OS << " } else {\n";
- OS << " CurDAG->ReplaceAllUsesWith(F, T, &ISQU);\n";
- OS << " }\n";
- OS << " setSelected(F->getNodeId());\n";
- OS << " UpdateQueue(ISQU);\n";
- OS << "}\n\n";
-
- OS << "// SelectRoot - Top level entry to DAG isel.\n";
- OS << "SDOperand SelectRoot(SDOperand Root) {\n";
- OS << " SelectRootInit();\n";
- OS << " unsigned NumBytes = (DAGSize + 7) / 8;\n";
- OS << " ISelQueued = new unsigned char[NumBytes];\n";
- OS << " ISelSelected = new unsigned char[NumBytes];\n";
- OS << " memset(ISelQueued, 0, NumBytes);\n";
- OS << " memset(ISelSelected, 0, NumBytes);\n";
- OS << "\n";
- OS << " // Create a dummy node (which is not added to allnodes), that adds\n"
- << " // a reference to the root node, preventing it from being deleted,\n"
- << " // and tracking any changes of the root.\n"
- << " HandleSDNode Dummy(CurDAG->getRoot());\n"
- << " ISelQueue.push_back(CurDAG->getRoot().Val);\n";
- OS << " while (!ISelQueue.empty()) {\n";
- OS << " SDNode *Node = ISelQueue.front();\n";
- OS << " std::pop_heap(ISelQueue.begin(), ISelQueue.end(), isel_sort());\n";
- OS << " ISelQueue.pop_back();\n";
- OS << " if (!isSelected(Node->getNodeId())) {\n";
- OS << " SDNode *ResNode = Select(SDOperand(Node, 0));\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 << " ISelQueueUpdater ISQU(ISelQueue);\n";
- OS << " CurDAG->RemoveDeadNode(Node, &ISQU);\n";
- OS << " UpdateQueue(ISQU);\n";
- OS << " }\n";
- OS << " }\n";
- OS << " }\n";
- OS << " }\n";
- OS << "\n";
- OS << " delete[] ISelQueued;\n";
- OS << " ISelQueued = NULL;\n";
- OS << " delete[] ISelSelected;\n";
- OS << " ISelSelected = NULL;\n";
- OS << " return Dummy.getValue();\n";
- OS << "}\n";
+ OS << "// Include standard, target-independent definitions and methods used\n"
+ << "// by the instruction selector.\n";
+ OS << "#include \"llvm/CodeGen/DAGISelHeader.h\"\n\n";
EmitNodeTransforms(OS);
EmitPredicateFunctions(OS);
- DOUT << "\n\nALL PATTERNS TO MATCH:\n\n";
+ DEBUG(errs() << "\n\nALL PATTERNS TO MATCH:\n\n");
for (CodeGenDAGPatterns::ptm_iterator I = CGP.ptm_begin(), E = CGP.ptm_end();
I != E; ++I) {
- DOUT << "PATTERN: "; DEBUG(I->getSrcPattern()->dump());
- DOUT << "\nRESULT: "; DEBUG(I->getDstPattern()->dump());
- DOUT << "\n";
+ DEBUG(errs() << "PATTERN: "; I->getSrcPattern()->dump());
+ DEBUG(errs() << "\nRESULT: "; I->getDstPattern()->dump());
+ DEBUG(errs() << "\n");
}
// At this point, we have full information about the 'Patterns' we need to