#include "Record.h"
#include "llvm/ADT/StringExtras.h"
#include "llvm/Support/Debug.h"
+#include "llvm/Support/MathExtras.h"
#include <algorithm>
#include <set>
using namespace llvm;
if (OperandNode->isSubClassOf("RegisterClass")) {
const CodeGenRegisterClass &RC =
ISE.getTargetInfo().getRegisterClass(OperandNode);
- //VT = RC.getValueTypeNum(0);
MadeChange |=getChild(i)->UpdateNodeType(ConvertVTs(RC.getValueTypes()),
TP);
} else if (OperandNode->isSubClassOf("Operand")) {
}
}
+/// OnlyOnRHSOfCommutative - Return true if this value is only allowed on the
+/// RHS of a commutative operation, not the on LHS.
+static bool OnlyOnRHSOfCommutative(TreePatternNode *N) {
+ if (!N->isLeaf() && N->getOperator()->getName() == "imm")
+ return true;
+ if (N->isLeaf() && dynamic_cast<IntInit*>(N->getLeafValue()))
+ return true;
+ return false;
+}
+
+
/// canPatternMatch - If it is impossible for this pattern to match on this
/// target, fill in Reason and return false. Otherwise, return true. This is
/// used as a santity check for .td files (to prevent people from writing stuff
// If this node is a commutative operator, check that the LHS isn't an
// immediate.
const SDNodeInfo &NodeInfo = ISE.getSDNodeInfo(getOperator());
- if (NodeInfo.hasProperty(SDNodeInfo::SDNPCommutative)) {
+ if (NodeInfo.hasProperty(SDNPCommutative)) {
// Scan all of the operands of the node and make sure that only the last one
- // is a constant node.
- for (unsigned i = 0, e = getNumChildren()-1; i != e; ++i)
- if (!getChild(i)->isLeaf() &&
- getChild(i)->getOperator()->getName() == "imm") {
- Reason = "Immediate value must be on the RHS of commutative operators!";
- return false;
- }
+ // is a constant node, unless the RHS also is.
+ if (!OnlyOnRHSOfCommutative(getChild(getNumChildren()-1))) {
+ for (unsigned i = 0, e = getNumChildren()-1; i != e; ++i)
+ if (OnlyOnRHSOfCommutative(getChild(i))) {
+ Reason="Immediate value must be on the RHS of commutative operators!";
+ return false;
+ }
+ }
}
return true;
// keep track of the fact that this fragment uses it.
std::string Code = Fragments[i]->getValueAsCode("Predicate");
if (!Code.empty()) {
- assert(!P->getOnlyTree()->isLeaf() && "Can't be a leaf!");
- std::string ClassName =
- getSDNodeInfo(P->getOnlyTree()->getOperator()).getSDClassName();
- const char *C2 = ClassName == "SDNode" ? "N" : "inN";
+ if (P->getOnlyTree()->isLeaf())
+ OS << "inline bool Predicate_" << Fragments[i]->getName()
+ << "(SDNode *N) {\n";
+ else {
+ std::string ClassName =
+ getSDNodeInfo(P->getOnlyTree()->getOperator()).getSDClassName();
+ const char *C2 = ClassName == "SDNode" ? "N" : "inN";
- OS << "inline bool Predicate_" << Fragments[i]->getName()
- << "(SDNode *" << C2 << ") {\n";
- if (ClassName != "SDNode")
- OS << " " << ClassName << " *N = cast<" << ClassName << ">(inN);\n";
+ OS << "inline bool Predicate_" << Fragments[i]->getName()
+ << "(SDNode *" << C2 << ") {\n";
+ if (ClassName != "SDNode")
+ OS << " " << ClassName << " *N = cast<" << ClassName << ">(inN);\n";
+ }
OS << Code << "\n}\n";
P->getOnlyTree()->setPredicateFn("Predicate_"+Fragments[i]->getName());
}
// can never do anything with this pattern: report it to the user.
InferredAllPatternTypes = Pattern->InferAllTypes();
- // Infer as many types as possible. If we cannot infer all of them, we can
- // never do anything with this pattern: report it to the user.
+ // Infer as many types as possible. If we cannot infer all of them, we
+ // can never do anything with this pattern: report it to the user.
InferredAllResultTypes = Result->InferAllTypes();
// Apply the type of the result to the source pattern. This helps us
const SDNodeInfo &NodeInfo = ISE.getSDNodeInfo(N->getOperator());
// If this node is associative, reassociate.
- if (NodeInfo.hasProperty(SDNodeInfo::SDNPAssociative)) {
+ if (NodeInfo.hasProperty(SDNPAssociative)) {
// Reassociate by pulling together all of the linked operators
std::vector<TreePatternNode*> MaximalChildren;
GatherChildrenOfAssociativeOpcode(N, MaximalChildren);
CombineChildVariants(N, ChildVariants, OutVariants, ISE);
// If this node is commutative, consider the commuted order.
- if (NodeInfo.hasProperty(SDNodeInfo::SDNPCommutative)) {
+ if (NodeInfo.hasProperty(SDNPCommutative)) {
assert(N->getNumChildren()==2 &&"Commutative but doesn't have 2 children!");
// Don't count children which are actually register references.
unsigned NC = 0;
P->getExtTypeNum(0) == MVT::Flag ||
P->getExtTypeNum(0) == MVT::iPTR) &&
"Not a valid pattern node to size!");
- unsigned Size = 2; // The node itself.
+ unsigned Size = 3; // The node itself.
// If the root node is a ConstantSDNode, increases its size.
// e.g. (set R32:$dst, 0).
if (P->isLeaf() && dynamic_cast<IntInit*>(P->getLeafValue()))
- Size++;
+ Size += 2;
// FIXME: This is a hack to statically increase the priority of patterns
// which maps a sub-dag to a complex pattern. e.g. favors LEA over ADD.
// calculate the complexity of all patterns a dag can potentially map to.
const ComplexPattern *AM = NodeGetComplexPattern(P, ISE);
if (AM)
- Size += AM->getNumOperands() * 2;
+ Size += AM->getNumOperands() * 3;
// If this node has some predicate function that must match, it adds to the
// complexity of this node.
Size += getPatternSize(Child, ISE);
else if (Child->isLeaf()) {
if (dynamic_cast<IntInit*>(Child->getLeafValue()))
- Size += 3; // Matches a ConstantSDNode (+2) and a specific value (+1).
+ Size += 5; // Matches a ConstantSDNode (+3) and a specific value (+2).
else if (NodeIsComplexPattern(Child))
Size += getPatternSize(Child, ISE);
else if (!Child->getPredicateFn().empty())
/// NodeHasProperty - return true if TreePatternNode has the specified
/// property.
-static bool NodeHasProperty(TreePatternNode *N, SDNodeInfo::SDNP Property,
+static bool NodeHasProperty(TreePatternNode *N, SDNP Property,
DAGISelEmitter &ISE)
{
- if (N->isLeaf()) return false;
+ if (N->isLeaf()) {
+ const ComplexPattern *CP = NodeGetComplexPattern(N, ISE);
+ if (CP)
+ return CP->hasProperty(Property);
+ return false;
+ }
Record *Operator = N->getOperator();
if (!Operator->isSubClassOf("SDNode")) return false;
return NodeInfo.hasProperty(Property);
}
-static bool PatternHasProperty(TreePatternNode *N, SDNodeInfo::SDNP Property,
+static bool PatternHasProperty(TreePatternNode *N, SDNP Property,
DAGISelEmitter &ISE)
{
if (NodeHasProperty(N, Property, ISE))
std::map<std::string, Record*> OperatorMap;
// Names of all the folded nodes which produce chains.
std::vector<std::pair<std::string, unsigned> > FoldedChains;
+ // Original input chain(s).
+ std::vector<std::pair<std::string, std::string> > OrigChains;
std::set<std::string> Duplicates;
/// GeneratedCode - This is the buffer that we emit code to. The first int
/// if the match fails. At this point, we already know that the opcode for N
/// matches, and the SDNode for the result has the RootName specified name.
void EmitMatchCode(TreePatternNode *N, TreePatternNode *P,
- const std::string &RootName, const std::string &ParentName,
- const std::string &ChainSuffix, bool &FoundChain) {
+ const std::string &RootName, const std::string &ChainSuffix,
+ bool &FoundChain) {
bool isRoot = (P == NULL);
// Emit instruction predicates. Each predicate is just a string for now.
if (isRoot) {
assert(0 && "Unknown predicate type!");
}
if (!PredicateCheck.empty())
- PredicateCheck += " || ";
+ PredicateCheck += " && ";
PredicateCheck += "(" + Def->getValueAsString("CondString") + ")";
}
}
// Emit code to load the child nodes and match their contents recursively.
unsigned OpNo = 0;
- bool NodeHasChain = NodeHasProperty (N, SDNodeInfo::SDNPHasChain, ISE);
- bool HasChain = PatternHasProperty(N, SDNodeInfo::SDNPHasChain, ISE);
- bool HasOutFlag = PatternHasProperty(N, SDNodeInfo::SDNPOutFlag, ISE);
+ bool NodeHasChain = NodeHasProperty (N, SDNPHasChain, ISE);
+ bool HasChain = PatternHasProperty(N, SDNPHasChain, ISE);
bool EmittedUseCheck = false;
if (HasChain) {
if (NodeHasChain)
OpNo = 1;
if (!isRoot) {
- const SDNodeInfo &CInfo = ISE.getSDNodeInfo(N->getOperator());
// Multiple uses of actual result?
emitCheck(RootName + ".hasOneUse()");
EmittedUseCheck = true;
if (NodeHasChain) {
- // FIXME: Don't fold if 1) the parent node writes a flag, 2) the node
- // has a chain use.
- // This a workaround for this problem:
- //
- // [ch, r : ld]
- // ^ ^
- // | |
- // [XX]--/ \- [flag : cmp]
- // ^ ^
- // | |
- // \---[br flag]-
- //
- // cmp + br should be considered as a single node as they are flagged
- // together. So, if the ld is folded into the cmp, the XX node in the
- // graph is now both an operand and a use of the ld/cmp/br node.
- if (NodeHasProperty(P, SDNodeInfo::SDNPOutFlag, ISE))
- emitCheck(ParentName + ".Val->isOnlyUse(" + RootName + ".Val)");
-
// If the immediate use can somehow reach this node through another
// path, then can't fold it either or it will create a cycle.
// e.g. In the following diagram, XX can reach ld through YY. If
// / [YY]
// | ^
// [XX]-------|
- const SDNodeInfo &PInfo = ISE.getSDNodeInfo(P->getOperator());
- if (PInfo.getNumOperands() > 1 ||
- PInfo.hasProperty(SDNodeInfo::SDNPHasChain) ||
- PInfo.hasProperty(SDNodeInfo::SDNPInFlag) ||
- PInfo.hasProperty(SDNodeInfo::SDNPOptInFlag))
+ bool NeedCheck = false;
+ if (P != Pattern)
+ NeedCheck = true;
+ else {
+ const SDNodeInfo &PInfo = ISE.getSDNodeInfo(P->getOperator());
+ NeedCheck =
+ P->getOperator() == ISE.get_intrinsic_void_sdnode() ||
+ P->getOperator() == ISE.get_intrinsic_w_chain_sdnode() ||
+ P->getOperator() == ISE.get_intrinsic_wo_chain_sdnode() ||
+ PInfo.getNumOperands() > 1 ||
+ PInfo.hasProperty(SDNPHasChain) ||
+ PInfo.hasProperty(SDNPInFlag) ||
+ PInfo.hasProperty(SDNPOptInFlag);
+ }
+
+ if (NeedCheck) {
+ std::string ParentName(RootName.begin(), RootName.end()-1);
emitCheck("CanBeFoldedBy(" + RootName + ".Val, " + ParentName +
- ".Val)");
+ ".Val, N.Val)");
+ }
}
}
if (NodeHasChain) {
- if (FoundChain)
- emitCheck("Chain.Val == " + RootName + ".Val");
- else
+ if (FoundChain) {
+ emitCheck("(" + ChainName + ".Val == " + RootName + ".Val || "
+ "IsChainCompatible(" + ChainName + ".Val, " +
+ RootName + ".Val))");
+ OrigChains.push_back(std::make_pair(ChainName, RootName));
+ } else
FoundChain = true;
ChainName = "Chain" + ChainSuffix;
emitInit("SDOperand " + ChainName + " = " + RootName +
// FIXME: If the optional incoming flag does not exist. Then it is ok to
// fold it.
if (!isRoot &&
- (PatternHasProperty(N, SDNodeInfo::SDNPInFlag, ISE) ||
- PatternHasProperty(N, SDNodeInfo::SDNPOptInFlag, ISE) ||
- PatternHasProperty(N, SDNodeInfo::SDNPOutFlag, ISE))) {
- const SDNodeInfo &CInfo = ISE.getSDNodeInfo(N->getOperator());
+ (PatternHasProperty(N, SDNPInFlag, ISE) ||
+ PatternHasProperty(N, SDNPOptInFlag, ISE) ||
+ PatternHasProperty(N, SDNPOutFlag, ISE))) {
if (!EmittedUseCheck) {
// Multiple uses of actual result?
emitCheck(RootName + ".hasOneUse()");
}
}
- const ComplexPattern *CP;
+ // If there is a node predicate for this, emit the call.
+ if (!N->getPredicateFn().empty())
+ emitCheck(N->getPredicateFn() + "(" + RootName + ".Val)");
+
+
+ // 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
+ // handling of certain large constants (e.g. alpha with it's 8/16/32-bit
+ // handling stuff). Using these instructions is often far more efficient
+ // than materializing the constant. Unfortunately, both the instcombiner
+ // and the dag combiner can often infer that bits are dead, and thus drop
+ // them from the mask in the dag. For example, it might turn 'AND X, 255'
+ // into 'AND X, 254' if it knows the low bit is set. Emit code that checks
+ // to handle this.
+ if (!N->isLeaf() &&
+ (N->getOperator()->getName() == "and" ||
+ N->getOperator()->getName() == "or") &&
+ N->getChild(1)->isLeaf() &&
+ N->getChild(1)->getPredicateFn().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" + " = " +
+ RootName + ".getOperand(" + utostr(0) + ");");
+ emitInit("SDOperand " + RootName + "1" + " = " +
+ RootName + ".getOperand(" + utostr(1) + ");");
+
+ emitCheck("isa<ConstantSDNode>(" + RootName + "1)");
+ const char *MaskPredicate = N->getOperator()->getName() == "or"
+ ? "CheckOrMask(" : "CheckAndMask(";
+ emitCheck(MaskPredicate + RootName + "0, cast<ConstantSDNode>(" +
+ RootName + "1), " + itostr(II->getValue()) + ")");
+
+ 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("SDOperand " + RootName + utostr(OpNo) + " = " +
RootName + ".getOperand(" +utostr(OpNo) + ");");
- TreePatternNode *Child = N->getChild(i);
- if (!Child->isLeaf()) {
- // If it's not a leaf, recursively match.
- const SDNodeInfo &CInfo = ISE.getSDNodeInfo(Child->getOperator());
- emitCheck(RootName + utostr(OpNo) + ".getOpcode() == " +
- CInfo.getEnumName());
- EmitMatchCode(Child, N, RootName + utostr(OpNo), RootName,
- ChainSuffix + utostr(OpNo), FoundChain);
- if (NodeHasProperty(Child, SDNodeInfo::SDNPHasChain, ISE))
- FoldedChains.push_back(std::make_pair(RootName + utostr(OpNo),
- CInfo.getNumResults()));
- } else {
- // If this child has a name associated with it, capture it in VarMap. If
- // we already saw this in the pattern, emit code to verify dagness.
- if (!Child->getName().empty()) {
- std::string &VarMapEntry = VariableMap[Child->getName()];
- if (VarMapEntry.empty()) {
- VarMapEntry = RootName + utostr(OpNo);
- } 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 + utostr(OpNo));
- Duplicates.insert(RootName + utostr(OpNo));
- continue;
- }
- }
-
- // Handle leaves of various types.
- if (DefInit *DI = dynamic_cast<DefInit*>(Child->getLeafValue())) {
- Record *LeafRec = DI->getDef();
- if (LeafRec->isSubClassOf("RegisterClass")) {
- // Handle register references. Nothing to do here.
- } else if (LeafRec->isSubClassOf("Register")) {
- // Handle register references.
- } else if (LeafRec->isSubClassOf("ComplexPattern")) {
- // Handle complex pattern.
- CP = NodeGetComplexPattern(Child, ISE);
- std::string Fn = CP->getSelectFunc();
- unsigned NumOps = CP->getNumOperands();
- for (unsigned i = 0; i < NumOps; ++i) {
- emitDecl("CPTmp" + utostr(i));
- emitCode("SDOperand CPTmp" + utostr(i) + ";");
- }
-
- std::string Code = Fn + "(" + RootName + utostr(OpNo);
- for (unsigned i = 0; i < NumOps; i++)
- Code += ", CPTmp" + utostr(i);
- emitCheck(Code + ")");
- } else if (LeafRec->getName() == "srcvalue") {
- // Place holder for SRCVALUE nodes. Nothing to do here.
- } else if (LeafRec->isSubClassOf("ValueType")) {
- // Make sure this is the specified value type.
- emitCheck("cast<VTSDNode>(" + RootName + utostr(OpNo) +
- ")->getVT() == MVT::" + LeafRec->getName());
- } else if (LeafRec->isSubClassOf("CondCode")) {
- // Make sure this is the specified cond code.
- emitCheck("cast<CondCodeSDNode>(" + RootName + utostr(OpNo) +
- ")->get() == ISD::" + LeafRec->getName());
- } else {
-#ifndef NDEBUG
- Child->dump();
- std::cerr << " ";
-#endif
- assert(0 && "Unknown leaf type!");
- }
- } else if (IntInit *II =
- dynamic_cast<IntInit*>(Child->getLeafValue())) {
- emitCheck("isa<ConstantSDNode>(" + RootName + utostr(OpNo) + ")");
- unsigned CTmp = TmpNo++;
- emitCode("int64_t CN"+utostr(CTmp)+" = cast<ConstantSDNode>("+
- RootName + utostr(OpNo) + ")->getSignExtended();");
-
- emitCheck("CN" + utostr(CTmp) + " == " +itostr(II->getValue()));
- } else {
-#ifndef NDEBUG
- Child->dump();
-#endif
- assert(0 && "Unknown leaf type!");
- }
- }
+ EmitChildMatchCode(N->getChild(i), N, RootName + utostr(OpNo),
+ ChainSuffix + utostr(OpNo), FoundChain);
}
// Handle cases when root is a complex pattern.
+ const ComplexPattern *CP;
if (isRoot && N->isLeaf() && (CP = NodeGetComplexPattern(N, ISE))) {
std::string Fn = CP->getSelectFunc();
unsigned NumOps = CP->getNumOperands();
emitDecl("CPTmp" + utostr(i));
emitCode("SDOperand CPTmp" + utostr(i) + ";");
}
+ if (CP->hasProperty(SDNPHasChain)) {
+ emitDecl("CPInChain");
+ emitDecl("Chain" + ChainSuffix);
+ emitCode("SDOperand CPInChain;");
+ emitCode("SDOperand Chain" + ChainSuffix + ";");
+ }
std::string Code = Fn + "(" + RootName;
for (unsigned i = 0; i < NumOps; i++)
Code += ", CPTmp" + utostr(i);
+ if (CP->hasProperty(SDNPHasChain)) {
+ ChainName = "Chain" + ChainSuffix;
+ Code += ", CPInChain, Chain" + ChainSuffix;
+ }
emitCheck(Code + ")");
}
+ }
- // If there is a node predicate for this, emit the call.
- if (!N->getPredicateFn().empty())
- emitCheck(N->getPredicateFn() + "(" + RootName + ".Val)");
+ void EmitChildMatchCode(TreePatternNode *Child, TreePatternNode *Parent,
+ const std::string &RootName,
+ const std::string &ChainSuffix, bool &FoundChain) {
+ if (!Child->isLeaf()) {
+ // If it's not a leaf, recursively match.
+ const SDNodeInfo &CInfo = ISE.getSDNodeInfo(Child->getOperator());
+ emitCheck(RootName + ".getOpcode() == " +
+ CInfo.getEnumName());
+ EmitMatchCode(Child, Parent, RootName, ChainSuffix, FoundChain);
+ if (NodeHasProperty(Child, SDNPHasChain, ISE))
+ FoldedChains.push_back(std::make_pair(RootName, CInfo.getNumResults()));
+ } else {
+ // If this child has a name associated with it, capture it in VarMap. If
+ // we already saw this in the pattern, emit code to verify dagness.
+ if (!Child->getName().empty()) {
+ std::string &VarMapEntry = VariableMap[Child->getName()];
+ if (VarMapEntry.empty()) {
+ VarMapEntry = RootName;
+ } else {
+ // If we get here, this is a second reference to a specific name.
+ // Since we already have checked that the first reference is valid,
+ // we don't have to recursively match it, just check that it's the
+ // same as the previously named thing.
+ emitCheck(VarMapEntry + " == " + RootName);
+ Duplicates.insert(RootName);
+ return;
+ }
+ }
+
+ // Handle leaves of various types.
+ if (DefInit *DI = dynamic_cast<DefInit*>(Child->getLeafValue())) {
+ Record *LeafRec = DI->getDef();
+ if (LeafRec->isSubClassOf("RegisterClass")) {
+ // Handle register references. Nothing to do here.
+ } else if (LeafRec->isSubClassOf("Register")) {
+ // Handle register references.
+ } else if (LeafRec->isSubClassOf("ComplexPattern")) {
+ // Handle complex pattern.
+ const ComplexPattern *CP = NodeGetComplexPattern(Child, ISE);
+ std::string Fn = CP->getSelectFunc();
+ unsigned NumOps = CP->getNumOperands();
+ for (unsigned i = 0; i < NumOps; ++i) {
+ emitDecl("CPTmp" + utostr(i));
+ emitCode("SDOperand CPTmp" + utostr(i) + ";");
+ }
+ if (CP->hasProperty(SDNPHasChain)) {
+ const SDNodeInfo &PInfo = ISE.getSDNodeInfo(Parent->getOperator());
+ FoldedChains.push_back(std::make_pair("CPInChain",
+ PInfo.getNumResults()));
+ ChainName = "Chain" + ChainSuffix;
+ emitDecl("CPInChain");
+ emitDecl(ChainName);
+ emitCode("SDOperand CPInChain;");
+ emitCode("SDOperand " + ChainName + ";");
+ }
+
+ std::string Code = Fn + "(";
+ if (CP->hasProperty(SDNPHasChain)) {
+ std::string ParentName(RootName.begin(), RootName.end()-1);
+ Code += "N, " + ParentName + ", ";
+ }
+ Code += RootName;
+ for (unsigned i = 0; i < NumOps; i++)
+ Code += ", CPTmp" + utostr(i);
+ if (CP->hasProperty(SDNPHasChain))
+ Code += ", CPInChain, Chain" + ChainSuffix;
+ emitCheck(Code + ")");
+ } else if (LeafRec->getName() == "srcvalue") {
+ // Place holder for SRCVALUE nodes. Nothing to do here.
+ } else if (LeafRec->isSubClassOf("ValueType")) {
+ // Make sure this is the specified value type.
+ emitCheck("cast<VTSDNode>(" + RootName +
+ ")->getVT() == MVT::" + LeafRec->getName());
+ } else if (LeafRec->isSubClassOf("CondCode")) {
+ // Make sure this is the specified cond code.
+ emitCheck("cast<CondCodeSDNode>(" + RootName +
+ ")->get() == ISD::" + LeafRec->getName());
+ } else {
+#ifndef NDEBUG
+ Child->dump();
+ std::cerr << " ";
+#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)");
+ } else if (IntInit *II =
+ dynamic_cast<IntInit*>(Child->getLeafValue())) {
+ emitCheck("isa<ConstantSDNode>(" + RootName + ")");
+ unsigned CTmp = TmpNo++;
+ emitCode("int64_t CN"+utostr(CTmp)+" = cast<ConstantSDNode>("+
+ RootName + ")->getSignExtended();");
+
+ emitCheck("CN" + utostr(CTmp) + " == " +itostr(II->getValue()));
+ } else {
+#ifndef NDEBUG
+ Child->dump();
+#endif
+ assert(0 && "Unknown leaf type!");
+ }
+ }
}
/// EmitResultCode - Emit the action for a pattern. Now that it has matched
Val + ")->getSymbol(), " +
getEnumName(N->getTypeNum(0)) + ");");
NodeOps.push_back("Tmp" + utostr(ResNo));
- // Add Tmp<ResNo> to VariableMap, so that we don't multiply select this
- // value if used multiple times by this pattern result.
+ // Add Tmp<ResNo> to VariableMap, so that we don't multiply select
+ // this value if used multiple times by this pattern result.
Val = "Tmp"+utostr(ResNo);
} else {
NodeOps.push_back(Val);
")->getGlobal(), " + getEnumName(N->getTypeNum(0)) +
");");
NodeOps.push_back("Tmp" + utostr(ResNo));
- // Add Tmp<ResNo> to VariableMap, so that we don't multiply select this
- // value if used multiple times by this pattern result.
+ // Add Tmp<ResNo> to VariableMap, so that we don't multiply select
+ // this value if used multiple times by this pattern result.
Val = "Tmp"+utostr(ResNo);
} else {
NodeOps.push_back(Val);
bool HasImpInputs = isRoot && Inst.getNumImpOperands() > 0;
bool HasImpResults = isRoot && Inst.getNumImpResults() > 0;
bool NodeHasOptInFlag = isRoot &&
- PatternHasProperty(Pattern, SDNodeInfo::SDNPOptInFlag, ISE);
+ PatternHasProperty(Pattern, SDNPOptInFlag, ISE);
bool NodeHasInFlag = isRoot &&
- PatternHasProperty(Pattern, SDNodeInfo::SDNPInFlag, ISE);
+ PatternHasProperty(Pattern, SDNPInFlag, ISE);
bool NodeHasOutFlag = HasImpResults || (isRoot &&
- PatternHasProperty(Pattern, SDNodeInfo::SDNPOutFlag, ISE));
+ PatternHasProperty(Pattern, SDNPOutFlag, ISE));
bool NodeHasChain = InstPatNode &&
- PatternHasProperty(InstPatNode, SDNodeInfo::SDNPHasChain, ISE);
+ PatternHasProperty(InstPatNode, SDNPHasChain, ISE);
bool InputHasChain = isRoot &&
- NodeHasProperty(Pattern, SDNodeInfo::SDNPHasChain, ISE);
+ NodeHasProperty(Pattern, SDNPHasChain, ISE);
if (NodeHasOptInFlag) {
emitCode("bool HasInFlag = "
"(N.getOperand(N.getNumOperands()-1).getValueType() == MVT::Flag);");
}
if (HasVarOps)
- emitCode("SmallVector<SDOperand, 8> Ops;");
+ emitCode("SmallVector<SDOperand, 8> Ops" + utostr(OpcNo) + ";");
// How many results is this pattern expected to produce?
unsigned PatResults = 0;
PatResults++;
}
+ if (OrigChains.size() > 0) {
+ // The original input chain is being ignored. If it is not just
+ // pointing to the op that's being folded, we should create a
+ // TokenFactor with it and the chain of the folded op as the new chain.
+ // We could potentially be doing multiple levels of folding, in that
+ // case, the TokenFactor can have more operands.
+ emitCode("SmallVector<SDOperand, 8> InChains;");
+ for (unsigned i = 0, e = OrigChains.size(); i < e; ++i) {
+ emitCode("if (" + OrigChains[i].first + ".Val != " +
+ OrigChains[i].second + ".Val) {");
+ emitCode(" AddToISelQueue(" + OrigChains[i].first + ");");
+ emitCode(" InChains.push_back(" + OrigChains[i].first + ");");
+ emitCode("}");
+ }
+ emitCode("AddToISelQueue(" + ChainName + ");");
+ emitCode("InChains.push_back(" + ChainName + ");");
+ emitCode(ChainName + " = CurDAG->getNode(ISD::TokenFactor, MVT::Other, "
+ "&InChains[0], InChains.size());");
+ }
+
std::vector<std::string> AllOps;
for (unsigned i = 0, e = N->getNumChildren(); i != e; ++i) {
std::vector<std::string> Ops = EmitResultCode(N->getChild(i),
if (NodeHasInFlag || HasImpInputs)
EmitInFlagSelectCode(Pattern, "N", ChainEmitted,
InFlagDecled, ResNodeDecled, true);
- if (NodeHasOptInFlag) {
+ if (NodeHasOptInFlag || NodeHasInFlag || HasImpInputs) {
if (!InFlagDecled) {
emitCode("SDOperand InFlag(0, 0);");
InFlagDecled = true;
}
- emitCode("if (HasInFlag) {");
- emitCode(" InFlag = N.getOperand(N.getNumOperands()-1);");
- emitCode(" AddToISelQueue(InFlag);");
- emitCode("}");
+ if (NodeHasOptInFlag) {
+ emitCode("if (HasInFlag) {");
+ emitCode(" InFlag = N.getOperand(N.getNumOperands()-1);");
+ emitCode(" AddToISelQueue(InFlag);");
+ emitCode("}");
+ }
}
unsigned NumResults = Inst.getNumResults();
else
Code2 = NodeName + " = ";
}
+
Code = "CurDAG->getTargetNode(Opc" + utostr(OpcNo);
+ unsigned OpsNo = OpcNo;
emitOpcode(II.Namespace + "::" + II.TheDef->getName());
// Output order: results, chain, flags
Code += ", MVT::Flag";
// Inputs.
- for (unsigned i = 0, e = AllOps.size(); i != e; ++i) {
- std::string OpName = AllOps[i];
- if (HasVarOps)
- emitCode("Ops.push_back(" + OpName + ");");
- else
- Code += ", " + OpName;
+ if (HasVarOps) {
+ for (unsigned i = 0, e = AllOps.size(); i != e; ++i)
+ emitCode("Ops" + utostr(OpsNo) + ".push_back(" + AllOps[i] + ");");
+ AllOps.clear();
}
if (HasVarOps) {
emitCode("for (unsigned i = 2, e = N.getNumOperands(); "
"i != e; ++i) {");
emitCode(" AddToISelQueue(N.getOperand(i));");
- emitCode(" Ops.push_back(N.getOperand(i));");
+ emitCode(" Ops" + utostr(OpsNo) + ".push_back(N.getOperand(i));");
emitCode("}");
}
if (NodeHasChain) {
if (HasVarOps)
- emitCode("Ops.push_back(" + ChainName + ");");
+ emitCode("Ops" + utostr(OpsNo) + ".push_back(" + ChainName + ");");
else
- Code += ", " + ChainName;
+ AllOps.push_back(ChainName);
}
- if (NodeHasInFlag || HasImpInputs) {
- if (!InFlagDecled) {
- emitCode("SDOperand InFlag(0, 0);");
- InFlagDecled = true;
+
+ 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);");
}
- if (HasVarOps) {
- emitCode("Ops.push_back(InFlag);");
- } else
- Code += ", InFlag";
- } else if (NodeHasOptInFlag && HasVarOps) {
- if (!InFlagDecled) {
- emitCode("SDOperand InFlag(0, 0);");
- InFlagDecled = true;
+ 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);
}
- emitCode("if (HasInFlag)");
- emitCode(" Ops.push_back(InFlag);");
}
-
- if (HasVarOps)
- Code += ", &Ops[0], Ops.size()";
- else if (NodeHasOptInFlag) {
- Code = "HasInFlag ? " + Code + ", InFlag) : " + Code;
- }
-
+
if (!isRoot)
Code += "), 0";
emitCode(Code2 + Code + ");");
utostr(i) + "), SDOperand(ResNode, " + utostr(i) + "));");
if (InputHasChain)
emitCode("ReplaceUses(SDOperand(N.Val, " +
- utostr(PatResults) + "), SDOperand(" + ChainName + ".Val, " +
- ChainName + ".ResNo" + "));");
- } else {
+ utostr(PatResults) + "), SDOperand(" + ChainName + ".Val, "
+ + ChainName + ".ResNo" + "));");
+ } else
RetSelected = true;
- }
// User does not expect the instruction would produce a chain!
if ((!InputHasChain && NodeHasChain) && NodeHasOutFlag) {
Code += ", VT" + utostr(VTNo);
if (NodeHasOutFlag)
Code += ", MVT::Flag";
- for (unsigned i = 0, e = AllOps.size(); i != e; ++i)
- Code += ", " + AllOps[i];
- if (NodeHasInFlag || HasImpInputs)
- Code += ", InFlag";
- emitCode(Code + ").Val;");
+
+ 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);
+ }
+ }
+ emitCode(Code + ");");
emitOpcode(II.Namespace + "::" + II.TheDef->getName());
if (N->getTypeNum(0) != MVT::isVoid)
emitVT(getEnumName(N->getTypeNum(0)));
}
unsigned OpNo =
- (unsigned) NodeHasProperty(Pat, SDNodeInfo::SDNPHasChain, ISE);
+ (unsigned) NodeHasProperty(Pat, SDNPHasChain, ISE);
for (unsigned i = 0, e = Pat->getNumChildren(); i != e; ++i, ++OpNo)
if (InsertOneTypeCheck(Pat->getChild(i), Other->getChild(i),
Prefix + utostr(OpNo)))
bool &ResNodeDecled, bool isRoot = false) {
const CodeGenTarget &T = ISE.getTargetInfo();
unsigned OpNo =
- (unsigned) NodeHasProperty(N, SDNodeInfo::SDNPHasChain, ISE);
- bool HasInFlag = NodeHasProperty(N, SDNodeInfo::SDNPInFlag, ISE);
+ (unsigned) NodeHasProperty(N, SDNPHasChain, ISE);
+ bool HasInFlag = NodeHasProperty(N, SDNPInFlag, ISE);
for (unsigned i = 0, e = N->getNumChildren(); i != e; ++i, ++OpNo) {
TreePatternNode *Child = N->getChild(i);
if (!Child->isLeaf()) {
}
std::string Decl = (!ResNodeDecled) ? "SDNode *" : "";
emitCode(Decl + "ResNode = CurDAG->getCopyToReg(" + ChainName +
- ", CurDAG->getRegister(" + ISE.getQualifiedName(RR) +
- ", " + getEnumName(RVT) + "), " +
- RootName + utostr(OpNo) + ", InFlag).Val;");
+ ", " + ISE.getQualifiedName(RR) +
+ ", " + RootName + utostr(OpNo) + ", InFlag).Val;");
ResNodeDecled = true;
emitCode(ChainName + " = SDOperand(ResNode, 0);");
emitCode("InFlag = SDOperand(ResNode, 1);");
// Emit the matcher, capturing named arguments in VariableMap.
bool FoundChain = false;
- Emitter.EmitMatchCode(Pattern.getSrcPattern(), NULL, "N", "", "",
- FoundChain);
+ Emitter.EmitMatchCode(Pattern.getSrcPattern(), NULL, "N", "", FoundChain);
// TP - Get *SOME* tree pattern, we don't care which.
TreePattern &TP = *PatternFragments.begin()->second;
PatternsByOpcode[Node->getOperator()].push_back(&PatternsToMatch[i]);
} else {
const ComplexPattern *CP;
- if (IntInit *II =
- dynamic_cast<IntInit*>(Node->getLeafValue())) {
+ if (dynamic_cast<IntInit*>(Node->getLeafValue())) {
PatternsByOpcode[getSDNodeNamed("imm")].push_back(&PatternsToMatch[i]);
- } else if ((CP = NodeGetComplexPattern(Node, *this))) {
+ } else if (NodeGetComplexPattern(Node, *this)) {
std::vector<Record*> OpNodes = CP->getRootNodes();
for (unsigned j = 0, e = OpNodes.size(); j != e; j++) {
PatternsByOpcode[OpNodes[j]]
++II) {
MVT::ValueType OpVT = II->first;
std::vector<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::vector<std::pair<unsigned,std::string> > CodeList;
+ typedef std::vector<std::pair<unsigned,std::string> >::iterator CodeListI;
std::vector<std::pair<PatternToMatch*, CodeList> > CodeForPatterns;
std::vector<std::vector<std::string> > PatternOpcodes;
CalleeCode += ") ";
// Prevent emission routines from being inlined to reduce selection
// routines stack frame sizes.
- CalleeCode += "NOINLINE ";
+ CalleeCode += "DISABLE_INLINE ";
CalleeCode += "{\n";
for (std::vector<std::string>::const_reverse_iterator
// 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 the last pattern has predicates (which could fail) emit code to
+ // catch the case where nothing handles a pattern.
if (mightNotMatch) {
OS << " std::cerr << \"Cannot yet select: \";\n";
if (OpcodeInfo.getEnumName() != "ISD::INTRINSIC_W_CHAIN" &&
} else {
if (OpcodeInfo.getNumResults())
OS << " MVT::ValueType NVT = N.Val->getValueType(0);\n";
- else if (OpcodeInfo.hasProperty(SDNodeInfo::SDNPHasChain))
+ else if (OpcodeInfo.hasProperty(SDNPHasChain))
OS << " MVT::ValueType NVT = (N.getNumOperands() > 1) ?"
<< " N.getOperand(1).Val->getValueType(0) : MVT::isVoid;\n";
else
<< "// *** instruction selector class. These functions are really "
<< "methods.\n\n";
- OS << "#if defined(__GNUC__) && \\\n";
- OS << " ((__GNUC__ > 3) || ((__GNUC__ == 3) && (__GNUC_MINOR__ >= 4)))\n";
- OS << "#define NOINLINE __attribute__((noinline))\n";
- OS << "#else\n";
- OS << "#define NOINLINE\n";
- OS << "#endif\n\n";
+ OS << "#include \"llvm/Support/Compiler.h\"\n";
OS << "// Instruction selector priority queue:\n"
<< "std::vector<SDNode*> ISelQueue;\n";
OS << "/// Dummy parameter to ReplaceAllUsesOfValueWith().\n"
<< "std::vector<SDNode*> ISelKilled;\n\n";
+ OS << "/// IsChainCompatible - Returns true if Chain is Op or Chain does\n";
+ OS << "/// not reach Op.\n";
+ OS << "static bool IsChainCompatible(SDNode *Chain, SDNode *Op) {\n";
+ OS << " if (Chain->getOpcode() == ISD::EntryToken)\n";
+ OS << " return true;\n";
+ OS << " else if (Chain->getOpcode() == ISD::TokenFactor)\n";
+ OS << " return false;\n";
+ OS << " else if (Chain->getNumOperands() > 0) {\n";
+ OS << " SDOperand C0 = Chain->getOperand(0);\n";
+ OS << " if (C0.getValueType() == MVT::Other)\n";
+ OS << " return C0.Val != Op && IsChainCompatible(C0.Val, Op);\n";
+ OS << " }\n";
+ OS << " return true;\n";
+ OS << "}\n";
+
OS << "/// Sorting functions for the selection queue.\n"
<< "struct isel_sort : public std::binary_function"
<< "<SDNode*, SDNode*, bool> {\n"
OS << " return ISelSelected[Id / 8] & (1 << (Id % 8));\n";
OS << "}\n\n";
- OS << "void AddToISelQueue(SDOperand N) NOINLINE {\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 << " if (NumKilled) {\n";
OS << " for (unsigned i = 0; i != NumKilled; ++i) {\n";
OS << " SDNode *Temp = ISelKilled[i];\n";
- OS << " std::remove(ISelQueue.begin(), ISelQueue.end(), Temp);\n";
+ OS << " ISelQueue.erase(std::remove(ISelQueue.begin(), ISelQueue.end(), "
+ << "Temp), ISelQueue.end());\n";
OS << " };\n";
OS << " std::make_heap(ISelQueue.begin(), ISelQueue.end(), isel_sort());\n";
OS << " ISelKilled.clear();\n";
OS << " }\n";
OS << "}\n\n";
- OS << "void ReplaceUses(SDOperand F, SDOperand T) NOINLINE {\n";
+ OS << "void ReplaceUses(SDOperand F, SDOperand T) DISABLE_INLINE {\n";
OS << " CurDAG->ReplaceAllUsesOfValueWith(F, T, ISelKilled);\n";
OS << " setSelected(F.Val->getNodeId());\n";
OS << " RemoveKilled();\n";
OS << " ISelQueue.pop_back();\n";
OS << " if (!isSelected(Node->getNodeId())) {\n";
OS << " SDNode *ResNode = Select(SDOperand(Node, 0));\n";
- OS << " if (ResNode && ResNode != Node) ReplaceUses(Node, ResNode);\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 << " CurDAG->RemoveDeadNode(Node, ISelKilled);\n";
+ OS << " RemoveKilled();\n";
+ OS << " }\n";
+ OS << " }\n";
OS << " }\n";
OS << " }\n";
OS << "\n";