#include "llvm/Support/Debug.h"
#include "llvm/Support/MathExtras.h"
#include "llvm/Support/Debug.h"
-#include "llvm/Support/Streams.h"
#include <algorithm>
#include <deque>
+#include <iostream>
using namespace llvm;
-namespace {
- cl::opt<bool>
- GenDebug("gen-debug", cl::desc("Generate debug code"),
- cl::init(false));
-}
+static cl::opt<bool>
+GenDebug("gen-debug", cl::desc("Generate debug code"), cl::init(false));
//===----------------------------------------------------------------------===//
// DAGISelEmitter Helper methods
//
+/// getNodeName - The top level Select_* functions have an "SDNode* N"
+/// argument. When expanding the pattern-matching code, the intermediate
+/// variables have type SDValue. This function provides a uniform way to
+/// reference the underlying "SDNode *" for both cases.
+static std::string getNodeName(const std::string &S) {
+ if (S == "N") return S;
+ return S + ".getNode()";
+}
+
+/// getNodeValue - Similar to getNodeName, except it provides a uniform
+/// way to access the SDValue for both cases.
+static std::string getValueName(const std::string &S) {
+ if (S == "N") return "SDValue(N, 0)";
+ return S;
+}
+
/// NodeIsComplexPattern - return true if N is a leaf node and a subclass of
/// ComplexPattern.
static bool NodeIsComplexPattern(TreePatternNode *N) {
/// patterns before small ones. This is used to determine the size of a
/// pattern.
static unsigned getPatternSize(TreePatternNode *P, CodeGenDAGPatterns &CGP) {
- assert((EMVT::isExtIntegerInVTs(P->getExtTypes()) ||
- EMVT::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 ||
if (Op->isSubClassOf("Instruction")) {
Cost++;
CodeGenInstruction &II = CGP.getTargetInfo().getInstruction(Op->getName());
- if (II.usesCustomDAGSchedInserter)
+ if (II.usesCustomInserter)
Cost += 10;
}
for (unsigned i = 0, e = P->getNumChildren(); i != e; ++i)
}
};
-/// getRegisterValueType - Look up and return the first ValueType of specified
-/// RegisterClass record
+/// 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) {
- if (const CodeGenRegisterClass *RC = T.getRegisterClassForRegister(R))
- return RC->getValueTypeNum(0);
- return MVT::Other;
+ 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;
}
//===----------------------------------------------------------------------===//
// 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;
// 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
// Save loads/stores matched by a pattern.
if (!N->isLeaf() && N->getName().empty()) {
if (NodeHasProperty(N, SDNPMemOperand, CGP))
- LSI.push_back(RootName);
+ LSI.push_back(getNodeName(RootName));
}
bool isRoot = (P == NULL);
NumInputRootOps = N->getNumChildren();
if (DisablePatternForFastISel(N, CGP))
- emitCheck("!Fast");
+ emitCheck("OptLevel != CodeGenOpt::None");
emitCheck(PredicateCheck);
}
if (N->isLeaf()) {
if (IntInit *II = dynamic_cast<IntInit*>(N->getLeafValue())) {
- emitCheck("cast<ConstantSDNode>(" + RootName +
+ emitCheck("cast<ConstantSDNode>(" + getNodeName(RootName) +
")->getSExtValue() == INT64_C(" +
itostr(II->getValue()) + ")");
return;
OpNo = 1;
if (!isRoot) {
// Multiple uses of actual result?
- emitCheck(RootName + ".hasOneUse()");
+ emitCheck(getValueName(RootName) + ".hasOneUse()");
EmittedUseCheck = true;
if (NodeHasChain) {
// If the immediate use can somehow reach this node through another
if (NeedCheck) {
std::string ParentName(RootName.begin(), RootName.end()-1);
- emitCheck("IsLegalAndProfitableToFold(" + RootName +
- ".getNode(), " + ParentName + ".getNode(), N.getNode())");
+ emitCheck("IsLegalAndProfitableToFold(" + getNodeName(RootName) +
+ ", " + getNodeName(ParentName) + ", N)");
}
}
}
if (NodeHasChain) {
if (FoundChain) {
- emitCheck("(" + ChainName + ".getNode() == " + RootName + ".getNode() || "
+ emitCheck("(" + ChainName + ".getNode() == " +
+ getNodeName(RootName) + " || "
"IsChainCompatible(" + ChainName + ".getNode(), " +
- RootName + ".getNode()))");
- OrigChains.push_back(std::make_pair(ChainName, RootName));
+ getNodeName(RootName) + "))");
+ OrigChains.push_back(std::make_pair(ChainName,
+ getValueName(RootName)));
} else
FoundChain = true;
ChainName = "Chain" + ChainSuffix;
- emitInit("SDValue " + ChainName + " = " + RootName +
- ".getOperand(0);");
+ emitInit("SDValue " + ChainName + " = " + getNodeName(RootName) +
+ "->getOperand(0);");
}
}
PatternHasProperty(N, SDNPOutFlag, CGP))) {
if (!EmittedUseCheck) {
// Multiple uses of actual result?
- emitCheck(RootName + ".hasOneUse()");
+ emitCheck(getValueName(RootName) + ".hasOneUse()");
}
}
// 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())");
+ emitCheck(N->getPredicateFns()[i] + "(" + getNodeName(RootName) + ")");
// 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
if (IntInit *II = dynamic_cast<IntInit*>(N->getChild(1)->getLeafValue())) {
if (!isPowerOf2_32(II->getValue())) { // Don't bother with single bits.
emitInit("SDValue " + RootName + "0" + " = " +
- RootName + ".getOperand(" + utostr(0) + ");");
+ getNodeName(RootName) + "->getOperand(" + utostr(0) + ");");
emitInit("SDValue " + RootName + "1" + " = " +
- RootName + ".getOperand(" + utostr(1) + ");");
+ getNodeName(RootName) + "->getOperand(" + utostr(1) + ");");
unsigned NTmp = TmpNo++;
emitCode("ConstantSDNode *Tmp" + utostr(NTmp) +
- " = dyn_cast<ConstantSDNode>(" + RootName + "1);");
+ " = dyn_cast<ConstantSDNode>(" +
+ getNodeName(RootName + "1") + ");");
emitCheck("Tmp" + utostr(NTmp));
const char *MaskPredicate = N->getOperator()->getName() == "or"
? "CheckOrMask(" : "CheckAndMask(";
- emitCheck(MaskPredicate + RootName + "0, Tmp" + utostr(NTmp) +
+ emitCheck(MaskPredicate + getValueName(RootName + "0") +
+ ", Tmp" + utostr(NTmp) +
", INT64_C(" + itostr(II->getValue()) + "))");
- EmitChildMatchCode(N->getChild(0), N, RootName + utostr(0), RootName,
+ EmitChildMatchCode(N->getChild(0), N, RootName + utostr(0),
ChainSuffix + utostr(0), FoundChain);
return;
}
}
for (unsigned i = 0, e = N->getNumChildren(); i != e; ++i, ++OpNo) {
- emitInit("SDValue " + RootName + utostr(OpNo) + " = " +
- RootName + ".getOperand(" +utostr(OpNo) + ");");
+ emitInit("SDValue " + getValueName(RootName + utostr(OpNo)) + " = " +
+ getNodeName(RootName) + "->getOperand(" + utostr(OpNo) + ");");
- EmitChildMatchCode(N->getChild(i), N, RootName + utostr(OpNo), RootName,
+ EmitChildMatchCode(N->getChild(i), N, RootName + utostr(OpNo),
ChainSuffix + utostr(OpNo), FoundChain);
}
std::string Fn = CP->getSelectFunc();
unsigned NumOps = CP->getNumOperands();
for (unsigned i = 0; i < NumOps; ++i) {
- emitDecl("CPTmp" + utostr(i));
- emitCode("SDValue CPTmp" + utostr(i) + ";");
+ emitDecl("CPTmp" + RootName + "_" + utostr(i));
+ emitCode("SDValue CPTmp" + RootName + "_" + utostr(i) + ";");
}
if (CP->hasProperty(SDNPHasChain)) {
emitDecl("CPInChain");
emitCode("SDValue Chain" + ChainSuffix + ";");
}
- std::string Code = Fn + "(" + RootName + ", " + RootName;
+ std::string Code = Fn + "(" +
+ getNodeName(RootName) + ", " +
+ getValueName(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;
void EmitChildMatchCode(TreePatternNode *Child, TreePatternNode *Parent,
const std::string &RootName,
- const std::string &ParentRootName,
const std::string &ChainSuffix, bool &FoundChain) {
if (!Child->isLeaf()) {
// If it's not a leaf, recursively match.
const SDNodeInfo &CInfo = CGP.getSDNodeInfo(Child->getOperator());
- emitCheck(RootName + ".getOpcode() == " +
+ emitCheck(getNodeName(RootName) + "->getOpcode() == " +
CInfo.getEnumName());
EmitMatchCode(Child, Parent, RootName, ChainSuffix, FoundChain);
bool HasChain = false;
if (NodeHasProperty(Child, SDNPHasChain, CGP)) {
HasChain = true;
- FoldedChains.push_back(std::make_pair(RootName, CInfo.getNumResults()));
+ FoldedChains.push_back(std::make_pair(getValueName(RootName),
+ CInfo.getNumResults()));
}
if (NodeHasProperty(Child, SDNPOutFlag, CGP)) {
assert(FoldedFlag.first == "" && FoldedFlag.second == 0 &&
"Pattern folded multiple nodes which produce flags?");
- FoldedFlag = std::make_pair(RootName,
+ FoldedFlag = std::make_pair(getValueName(RootName),
CInfo.getNumResults() + (unsigned)HasChain);
}
} else {
if (!Child->getName().empty()) {
std::string &VarMapEntry = VariableMap[Child->getName()];
if (VarMapEntry.empty()) {
- VarMapEntry = RootName;
+ VarMapEntry = getValueName(RootName);
} else {
// If we get here, this is a second reference to a specific name.
// Since we already have checked that the first reference is valid,
// we don't have to recursively match it, just check that it's the
// same as the previously named thing.
- emitCheck(VarMapEntry + " == " + RootName);
- Duplicates.insert(RootName);
+ emitCheck(VarMapEntry + " == " + getValueName(RootName));
+ Duplicates.insert(getValueName(RootName));
return;
}
}
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("SDValue 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());
emitCode("SDValue " + ChainName + ";");
}
- std::string Code = Fn + "(";
- if (CP->hasAttribute(CPAttrParentAsRoot)) {
- Code += ParentRootName + ", ";
- } else {
- Code += "N, ";
- }
+ std::string Code = Fn + "(N, ";
if (CP->hasProperty(SDNPHasChain)) {
std::string ParentName(RootName.begin(), RootName.end()-1);
- Code += ParentName + ", ";
+ Code += getValueName(ParentName) + ", ";
}
- Code += RootName;
+ Code += getValueName(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 + ")");
// Place holder for SRCVALUE nodes. Nothing to do here.
} else if (LeafRec->isSubClassOf("ValueType")) {
// Make sure this is the specified value type.
- emitCheck("cast<VTSDNode>(" + RootName +
+ emitCheck("cast<VTSDNode>(" + getNodeName(RootName) +
")->getVT() == MVT::" + LeafRec->getName());
} else if (LeafRec->isSubClassOf("CondCode")) {
// Make sure this is the specified cond code.
- emitCheck("cast<CondCodeSDNode>(" + RootName +
+ emitCheck("cast<CondCodeSDNode>(" + getNodeName(RootName) +
")->get() == ISD::" + LeafRec->getName());
} else {
#ifndef NDEBUG
Child->dump();
- cerr << " ";
+ errs() << " ";
#endif
assert(0 && "Unknown leaf type!");
}
// 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())");
+ emitCheck(Child->getPredicateFns()[i] + "(" + getNodeName(RootName) +
+ ")");
} else if (IntInit *II =
dynamic_cast<IntInit*>(Child->getLeafValue())) {
unsigned NTmp = TmpNo++;
emitCode("ConstantSDNode *Tmp"+ utostr(NTmp) +
" = dyn_cast<ConstantSDNode>("+
- RootName + ");");
+ getNodeName(RootName) + ");");
emitCheck("Tmp" + utostr(NTmp));
unsigned CTmp = TmpNo++;
emitCode("int64_t CN"+ utostr(CTmp) +
EmitResultCode(TreePatternNode *N, std::vector<Record*> DstRegs,
bool InFlagDecled, bool ResNodeDecled,
bool LikeLeaf = false, bool isRoot = false) {
- // List of arguments of getTargetNode() or SelectNodeTo().
+ // List of arguments of getMachineNode() or SelectNodeTo().
std::vector<std::string> NodeOps;
// This is something selected from the pattern we matched.
if (!N->getName().empty()) {
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();
}
if (Val[0] == 'T' && Val[1] == 'm' && Val[2] == 'p') {
// Already selected this operand, just return the tmpval.
- NodeOps.push_back(Val);
+ NodeOps.push_back(getValueName(Val));
return NodeOps;
}
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;
// value if used multiple times by this pattern result.
Val = TmpVar;
ModifiedVal = true;
- NodeOps.push_back(Val);
+ NodeOps.push_back(getValueName(Val));
} else if (!N->isLeaf() && N->getOperator()->getName() == "fpimm") {
assert(N->getExtTypes().size() == 1 && "Multiple types not handled!");
std::string TmpVar = "Tmp" + utostr(ResNo);
// value if used multiple times by this pattern result.
Val = TmpVar;
ModifiedVal = true;
- NodeOps.push_back(Val);
+ NodeOps.push_back(getValueName(Val));
} else if (!N->isLeaf() && N->getOperator()->getName() == "texternalsym"){
Record *Op = OperatorMap[N->getName()];
// Transform ExternalSymbol to TargetExternalSymbol
Val = TmpVar;
ModifiedVal = true;
}
- NodeOps.push_back(Val);
+ NodeOps.push_back(getValueName(Val));
} else if (!N->isLeaf() && (N->getOperator()->getName() == "tglobaladdr"
|| N->getOperator()->getName() == "tglobaltlsaddr")) {
Record *Op = OperatorMap[N->getName()];
Val = TmpVar;
ModifiedVal = true;
}
- NodeOps.push_back(Val);
+ NodeOps.push_back(getValueName(Val));
} else if (!N->isLeaf()
&& (N->getOperator()->getName() == "texternalsym"
|| N->getOperator()->getName() == "tconstpool")) {
// Do not rewrite the variable name, since we don't generate a new
// temporary.
- NodeOps.push_back(Val);
+ NodeOps.push_back(getValueName(Val));
} else if (N->isLeaf() && (CP = NodeGetComplexPattern(N, CGP))) {
for (unsigned i = 0; i < CP->getNumOperands(); ++i) {
- NodeOps.push_back("CPTmp" + utostr(i));
+ NodeOps.push_back(getValueName("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) {
if (isRoot && N->isLeaf()) {
- emitCode("ReplaceUses(N, " + Val + ");");
+ emitCode("ReplaceUses(SDValue(N, 0), " + Val + ");");
emitCode("return NULL;");
}
}
- NodeOps.push_back(Val);
+ NodeOps.push_back(getValueName(Val));
}
if (ModifiedVal) {
emitCode("SDValue Tmp" + utostr(ResNo) + " = CurDAG->getRegister(" +
getQualifiedName(DI->getDef()) + ", " +
getEnumName(N->getTypeNum(0)) + ");");
- NodeOps.push_back("Tmp" + utostr(ResNo));
+ NodeOps.push_back(getValueName("Tmp" + utostr(ResNo)));
return NodeOps;
} else if (DI->getDef()->getName() == "zero_reg") {
emitCode("SDValue Tmp" + utostr(ResNo) +
" = CurDAG->getRegister(0, " +
getEnumName(N->getTypeNum(0)) + ");");
- NodeOps.push_back("Tmp" + utostr(ResNo));
+ NodeOps.push_back(getValueName("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(getValueName("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("SDValue Tmp" + utostr(ResNo) +
- " = CurDAG->getTargetConstant(0x" + itohexstr(II->getValue()) +
+ " = CurDAG->getTargetConstant(0x" +
+ utohexstr((uint64_t) II->getValue()) +
"ULL, " + getEnumName(N->getTypeNum(0)) + ");");
- NodeOps.push_back("Tmp" + utostr(ResNo));
+ NodeOps.push_back(getValueName("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 IsVariadic = isRoot && II.isVariadic;
if (NodeHasOptInFlag) {
emitCode("bool HasInFlag = "
- "(N.getOperand(N.getNumOperands()-1).getValueType() == MVT::Flag);");
+ "(N->getOperand(N->getNumOperands()-1).getValueType() == "
+ "MVT::Flag);");
}
if (IsVariadic)
emitCode("SmallVector<SDValue, 8> Ops" + utostr(OpcNo) + ";");
emitCode("}");
}
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\");");
}
if (NodeHasOptInFlag) {
emitCode("if (HasInFlag) {");
- emitCode(" InFlag = N.getOperand(N.getNumOperands()-1);");
+ emitCode(" InFlag = N->getOperand(N->getNumOperands()-1);");
emitCode("}");
}
}
std::string Code = "Opc" + utostr(OpcNo);
+ if (!isRoot || (InputHasChain && !NodeHasChain))
+ // For call to "getMachineNode()".
+ Code += ", N->getDebugLoc()";
+
emitOpcode(II.Namespace + "::" + II.TheDef->getName());
// Output order: results, chain, flags
EndAdjust = "-(HasInFlag?1:0)"; // May have a flag.
emitCode("for (unsigned i = NumInputRootOps + " + utostr(NodeHasChain) +
- ", e = N.getNumOperands()" + EndAdjust + "; i != e; ++i) {");
+ ", e = N->getNumOperands()" + EndAdjust + "; i != e; ++i) {");
- emitCode(" Ops" + utostr(OpsNo) + ".push_back(N.getOperand(i));");
+ emitCode(" Ops" + utostr(OpsNo) + ".push_back(N->getOperand(i));");
emitCode("}");
}
- // Generate MemOperandSDNodes nodes for each memory accesses covered by
+ // Populate MemRefs with entries 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(LSIName);
- }
+ if (isRoot && !LSI.empty()) {
+ std::string MemRefs = "MemRefs" + utostr(OpsNo);
+ emitCode("MachineSDNode::mmo_iterator " + MemRefs + " = "
+ "MF->allocateMemRefsArray(" + utostr(LSI.size()) + ");");
+ for (unsigned i = 0, e = LSI.size(); i != e; ++i)
+ emitCode(MemRefs + "[" + utostr(i) + "] = "
+ "cast<MemSDNode>(" + LSI[i] + ")->getMemOperand();");
+ After.push_back("cast<MachineSDNode>(ResNode)->setMemRefs(" +
+ MemRefs + ", " + MemRefs + " + " + utostr(LSI.size()) +
+ ");");
}
if (NodeHasChain) {
ReplaceTos.push_back("InFlag");
} else {
assert(NodeHasProperty(Pattern, SDNPOutFlag, CGP));
- ReplaceFroms.push_back("SDValue(N.getNode(), " +
+ ReplaceFroms.push_back("SDValue(N, " +
utostr(NumPatResults + (unsigned)InputHasChain)
+ ")");
ReplaceTos.push_back("InFlag");
}
if (!ReplaceFroms.empty() && InputHasChain) {
- ReplaceFroms.push_back("SDValue(N.getNode(), " +
+ ReplaceFroms.push_back("SDValue(N, " +
utostr(NumPatResults) + ")");
ReplaceTos.push_back("SDValue(" + ChainName + ".getNode(), " +
ChainName + ".getResNo()" + ")");
;
} else if (InputHasChain && !NodeHasChain) {
// One of the inner node produces a chain.
- if (NodeHasOutFlag) {
- ReplaceFroms.push_back("SDValue(N.getNode(), " +
- utostr(NumPatResults+1) +
- ")");
- ReplaceTos.push_back("SDValue(ResNode, N.getResNo()-1)");
- }
- ReplaceFroms.push_back("SDValue(N.getNode(), " +
+ assert(!NodeHasOutFlag && "Node has flag but not chain!");
+ ReplaceFroms.push_back("SDValue(N, " +
utostr(NumPatResults) + ")");
ReplaceTos.push_back(ChainName);
}
// 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
+ // We also don't use SelectNodeTo 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;
+ Code = "CurDAG->getMachineNode(" + Code;
} else {
- Code = "CurDAG->SelectNodeTo(N.getNode(), " + Code;
+ Code = "CurDAG->SelectNodeTo(N, " + Code;
}
if (isRoot) {
if (After.empty())
}
N->dump();
- cerr << "\n";
+ errs() << "\n";
throw std::string("Unknown node in result pattern!");
}
Pat->setTypes(Other->getExtTypes());
// The top level node type is checked outside of the select function.
if (!isRoot)
- emitCheck(Prefix + ".getNode()->getValueType(0) == " +
+ emitCheck(Prefix + ".getValueType() == " +
getName(Pat->getTypeNum(0)));
return true;
}
MVT::SimpleValueType RVT = getRegisterValueType(RR, T);
if (RVT == MVT::Flag) {
if (!InFlagDecled) {
- emitCode("SDValue InFlag = " + RootName + utostr(OpNo) + ";");
+ emitCode("SDValue InFlag = " +
+ getValueName(RootName + utostr(OpNo)) + ";");
InFlagDecled = true;
} else
- emitCode("InFlag = " + RootName + utostr(OpNo) + ";");
+ emitCode("InFlag = " +
+ getValueName(RootName + utostr(OpNo)) + ";");
} else {
if (!ChainEmitted) {
emitCode("SDValue Chain = CurDAG->getEntryNode();");
}
std::string Decl = (!ResNodeDecled) ? "SDNode *" : "";
emitCode(Decl + "ResNode = CurDAG->getCopyToReg(" + ChainName +
+ ", " + getNodeName(RootName) + "->getDebugLoc()" +
", " + getQualifiedName(RR) +
- ", " + RootName + utostr(OpNo) + ", InFlag).getNode();");
+ ", " + getValueName(RootName + utostr(OpNo)) +
+ ", InFlag).getNode();");
ResNodeDecled = true;
emitCode(ChainName + " = SDValue(ResNode, 0);");
emitCode("InFlag = SDValue(ResNode, 1);");
if (HasInFlag) {
if (!InFlagDecled) {
- emitCode("SDValue InFlag = " + RootName +
- ".getOperand(" + utostr(OpNo) + ");");
+ emitCode("SDValue InFlag = " + getNodeName(RootName) +
+ "->getOperand(" + utostr(OpNo) + ");");
InFlagDecled = true;
} else
- emitCode("InFlag = " + RootName +
- ".getOperand(" + utostr(OpNo) + ");");
+ emitCode("InFlag = " + getNodeName(RootName) +
+ "->getOperand(" + utostr(OpNo) + ");");
}
}
};
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()) {
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.
&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);
}
}
AddedInits.push_back(GeneratedCode[j].second);
}
- std::string CalleeCode = "(const SDValue &N";
+ std::string CalleeCode = "(SDNode *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 VT" + utostr(j);
+ CalleeCode += ", MVT::SimpleValueType VT" + utostr(j);
CallerCode += ", " + TargetVTs[j];
}
for (std::set<std::string>::iterator
}
CallerCode += ");";
- CalleeCode += ") ";
- // Prevent emission routines from being inlined to reduce selection
- // routines stack frame sizes.
- CalleeCode += "DISABLE_INLINE ";
- CalleeCode += "{\n";
+ CalleeCode += ") {\n";
for (std::vector<std::string>::const_reverse_iterator
I = AddedInits.rbegin(), E = AddedInits.rend(); I != E; ++I)
} else {
EmitFuncNum = EmitFunctions.size();
EmitFunctions.insert(std::make_pair(CalleeCode, EmitFuncNum));
+ // Prevent emission routines from being inlined to reduce selection
+ // routines stack frame sizes.
+ OS << "DISABLE_INLINE ";
OS << "SDNode *Emit_" << utostr(EmitFuncNum) << CalleeCode;
}
// Replace the emission code within selection routines with calls to the
// emission functions.
if (GenDebug) {
- GeneratedCode.push_back(std::make_pair(0, "CurDAG->setSubgraphColor(N.getNode(), \"red\");"));
+ GeneratedCode.push_back(std::make_pair(0, "CurDAG->setSubgraphColor(N, \"red\");"));
}
CallerCode = "SDNode *Result = Emit_" + utostr(EmitFuncNum) + CallerCode;
GeneratedCode.push_back(std::make_pair(3, CallerCode));
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, "CurDAG->setSubgraphColor(N, \"black\");"));
}
GeneratedCode.push_back(std::make_pair(0, "return Result;"));
}
} else
OpVTI->second.push_back(OpVTStr);
- OS << "SDNode *Select_" << getLegalCName(OpName)
- << OpVTStr << "(const SDValue &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.
// 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";
+ errs() << "Pattern '";
+ CodeForPatterns[i].first->getSrcPattern()->print(errs());
+ errs() << "' is impossible to select!\n";
exit(1);
}
}
// Next, reverse the list of patterns itself for the same reason.
std::reverse(CodeForPatterns.begin(), CodeForPatterns.end());
+ OS << "SDNode *Select_" << getLegalCName(OpName)
+ << OpVTStr << "(SDNode *N) {\n";
+
// Emit all of the patterns now, grouped together to share code.
EmitPatterns(CodeForPatterns, 2, OS);
}
}
- // Emit boilerplate.
- OS << "SDNode *Select_INLINEASM(SDValue N) {\n"
- << " std::vector<SDValue> Ops(N.getNode()->op_begin(), N.getNode()->op_end());\n"
- << " SelectInlineAsmMemoryOperands(Ops);\n\n"
-
- << " std::vector<MVT> VTs;\n"
- << " VTs.push_back(MVT::Other);\n"
- << " VTs.push_back(MVT::Flag);\n"
- << " SDValue New = CurDAG->getNode(ISD::INLINEASM, VTs, &Ops[0], "
- "Ops.size());\n"
- << " return New.getNode();\n"
- << "}\n\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_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_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 << "SDNode *Select_DECLARE(const SDValue &N) {\n"
- << " SDValue Chain = N.getOperand(0);\n"
- << " SDValue N1 = N.getOperand(1);\n"
- << " SDValue N2 = N.getOperand(2);\n"
- << " if (!isa<FrameIndexSDNode>(N1) || !isa<GlobalAddressSDNode>(N2)) {\n"
- << " CannotYetSelect(N);\n"
- << " }\n"
- << " int FI = cast<FrameIndexSDNode>(N1)->getIndex();\n"
- << " GlobalValue *GV = cast<GlobalAddressSDNode>(N2)->getGlobal();\n"
- << " SDValue Tmp1 = "
- << "CurDAG->getTargetFrameIndex(FI, TLI.getPointerTy());\n"
- << " SDValue Tmp2 = "
- << "CurDAG->getTargetGlobalAddress(GV, TLI.getPointerTy());\n"
- << " return CurDAG->SelectNodeTo(N.getNode(), TargetInstrInfo::DECLARE,\n"
- << " MVT::Other, Tmp1, Tmp2, Chain);\n"
- << "}\n\n";
-
- OS << "SDNode *Select_EXTRACT_SUBREG(const SDValue &N) {\n"
- << " SDValue N0 = N.getOperand(0);\n"
- << " SDValue N1 = N.getOperand(1);\n"
- << " unsigned C = cast<ConstantSDNode>(N1)->getZExtValue();\n"
- << " SDValue Tmp = CurDAG->getTargetConstant(C, MVT::i32);\n"
- << " return CurDAG->SelectNodeTo(N.getNode(), TargetInstrInfo::EXTRACT_SUBREG,\n"
- << " N.getValueType(), N0, Tmp);\n"
- << "}\n\n";
-
- OS << "SDNode *Select_INSERT_SUBREG(const SDValue &N) {\n"
- << " SDValue N0 = N.getOperand(0);\n"
- << " SDValue N1 = N.getOperand(1);\n"
- << " SDValue N2 = N.getOperand(2);\n"
- << " unsigned C = cast<ConstantSDNode>(N2)->getZExtValue();\n"
- << " SDValue Tmp = CurDAG->getTargetConstant(C, MVT::i32);\n"
- << " return CurDAG->SelectNodeTo(N.getNode(), TargetInstrInfo::INSERT_SUBREG,\n"
- << " N.getValueType(), N0, N1, Tmp);\n"
- << "}\n\n";
-
OS << "// The main instruction selector code.\n"
- << "SDNode *SelectCode(SDValue N) {\n"
- << " MVT::SimpleValueType NVT = N.getNode()->getValueType(0).getSimpleVT();\n"
- << " switch (N.getOpcode()) {\n"
+ << "SDNode *SelectCode(SDNode *N) {\n"
+ << " MVT::SimpleValueType NVT = N->getValueType(0).getSimpleVT().SimpleTy;\n"
+ << " switch (N->getOpcode()) {\n"
<< " default:\n"
- << " assert(!N.isMachineOpcode() && \"Node already selected!\");\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::TargetConstantPool:\n"
<< " case ISD::TargetFrameIndex:\n"
<< " case ISD::TargetExternalSymbol:\n"
+ << " case ISD::TargetBlockAddress:\n"
<< " case ISD::TargetJumpTable:\n"
<< " case ISD::TargetGlobalTLSAddress:\n"
<< " case ISD::TargetGlobalAddress:\n"
<< " }\n"
<< " case ISD::AssertSext:\n"
<< " case ISD::AssertZext: {\n"
- << " ReplaceUses(N, N.getOperand(0));\n"
+ << " ReplaceUses(SDValue(N, 0), N->getOperand(0));\n"
<< " return NULL;\n"
<< " }\n"
<< " case ISD::INLINEASM: return Select_INLINEASM(N);\n"
- << " case ISD::DBG_LABEL: return Select_DBG_LABEL(N);\n"
<< " case ISD::EH_LABEL: return Select_EH_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::UNDEF: return Select_UNDEF(N);\n";
// Loop over all of the case statements, emiting a call to each method we
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;
}
OS << " } // end of big switch.\n\n"
- << " if (N.getOpcode() != ISD::INTRINSIC_W_CHAIN &&\n"
- << " N.getOpcode() != ISD::INTRINSIC_WO_CHAIN &&\n"
- << " N.getOpcode() != ISD::INTRINSIC_VOID) {\n"
+ << " if (N->getOpcode() != ISD::INTRINSIC_W_CHAIN &&\n"
+ << " N->getOpcode() != ISD::INTRINSIC_WO_CHAIN &&\n"
+ << " N->getOpcode() != ISD::INTRINSIC_VOID) {\n"
<< " CannotYetSelect(N);\n"
<< " } else {\n"
<< " CannotYetSelectIntrinsic(N);\n"
<< " }\n"
<< " return NULL;\n"
<< "}\n\n";
-
- OS << "void CannotYetSelect(SDValue N) DISABLE_INLINE {\n"
- << " cerr << \"Cannot yet select: \";\n"
- << " N.getNode()->dump(CurDAG);\n"
- << " cerr << '\\n';\n"
- << " abort();\n"
- << "}\n\n";
-
- OS << "void CannotYetSelectIntrinsic(SDValue N) DISABLE_INLINE {\n"
- << " cerr << \"Cannot yet select: \";\n"
- << " unsigned iid = cast<ConstantSDNode>(N.getOperand("
- << "N.getOperand(0).getValueType() == MVT::Other))->getZExtValue();\n"
- << " cerr << \"intrinsic %\"<< "
- << "Intrinsic::getName((Intrinsic::ID)iid);\n"
- << " cerr << '\\n';\n"
- << " abort();\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 << "// Include standard, target-independent definitions and methods used\n"
<< "// by the instruction selector.\n";
- OS << "#include <llvm/CodeGen/DAGISelHeader.h>\n\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