#include "Record.h"
#include "llvm/ADT/StringExtras.h"
#include "llvm/Support/Debug.h"
-#include "llvm/Support/Streams.h"
#include <set>
#include <algorithm>
+#include <iostream>
using namespace llvm;
//===----------------------------------------------------------------------===//
}
static inline bool isInteger(MVT::SimpleValueType VT) {
- return MVT(VT).isInteger();
+ return EVT(VT).isInteger();
}
static inline bool isFloatingPoint(MVT::SimpleValueType VT) {
- return MVT(VT).isFloatingPoint();
+ return EVT(VT).isFloatingPoint();
}
static inline bool isVector(MVT::SimpleValueType VT) {
- return MVT(VT).isVector();
+ return EVT(VT).isVector();
}
static bool LHSIsSubsetOfRHS(const std::vector<unsigned char> &LHS,
return true;
}
-/// isExtIntegerVT - Return true if the specified extended value type vector
-/// contains isInt or an integer value type.
namespace llvm {
-namespace EMVT {
+namespace EEVT {
+/// isExtIntegerInVTs - Return true if the specified extended value type vector
+/// contains iAny or an integer value type.
bool isExtIntegerInVTs(const std::vector<unsigned char> &EVTs) {
assert(!EVTs.empty() && "Cannot check for integer in empty ExtVT list!");
- return EVTs[0] == isInt || !(FilterEVTs(EVTs, isInteger).empty());
+ return EVTs[0] == MVT::iAny || !(FilterEVTs(EVTs, isInteger).empty());
}
-/// isExtFloatingPointVT - Return true if the specified extended value type
-/// vector contains isFP or a FP value type.
+/// isExtFloatingPointInVTs - Return true if the specified extended value type
+/// vector contains fAny or a FP value type.
bool isExtFloatingPointInVTs(const std::vector<unsigned char> &EVTs) {
- assert(!EVTs.empty() && "Cannot check for integer in empty ExtVT list!");
- return EVTs[0] == isFP || !(FilterEVTs(EVTs, isFloatingPoint).empty());
+ assert(!EVTs.empty() && "Cannot check for FP in empty ExtVT list!");
+ return EVTs[0] == MVT::fAny || !(FilterEVTs(EVTs, isFloatingPoint).empty());
+}
+
+/// isExtVectorInVTs - Return true if the specified extended value type
+/// vector contains vAny or a vector value type.
+bool isExtVectorInVTs(const std::vector<unsigned char> &EVTs) {
+ assert(!EVTs.empty() && "Cannot check for vector in empty ExtVT list!");
+ return EVTs[0] == MVT::vAny || !(FilterEVTs(EVTs, isVector).empty());
}
-} // end namespace EMVT.
+} // end namespace EEVT.
} // end namespace llvm.
+bool RecordPtrCmp::operator()(const Record *LHS, const Record *RHS) const {
+ return LHS->getID() < RHS->getID();
+}
/// Dependent variable map for CodeGenDAGPattern variant generation
typedef std::map<std::string, int> DepVarMap;
//! Dump the dependent variable set:
void DumpDepVars(MultipleUseVarSet &DepVars) {
if (DepVars.empty()) {
- DOUT << "<empty set>";
+ DEBUG(errs() << "<empty set>");
} else {
- DOUT << "[ ";
+ DEBUG(errs() << "[ ");
for (MultipleUseVarSet::const_iterator i = DepVars.begin(), e = DepVars.end();
i != e; ++i) {
- DOUT << (*i) << " ";
+ DEBUG(errs() << (*i) << " ");
}
- DOUT << "]";
+ DEBUG(errs() << "]");
}
}
}
+//===----------------------------------------------------------------------===//
+// PatternToMatch implementation
+//
+
+/// getPredicateCheck - Return a single string containing all of this
+/// pattern's predicates concatenated with "&&" operators.
+///
+std::string PatternToMatch::getPredicateCheck() const {
+ 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") + ")";
+ }
+ }
+
+ return PredicateCheck;
+}
+
//===----------------------------------------------------------------------===//
// SDTypeConstraint implementation
//
ConstraintType = SDTCisInt;
} else if (R->isSubClassOf("SDTCisFP")) {
ConstraintType = SDTCisFP;
+ } else if (R->isSubClassOf("SDTCisVec")) {
+ ConstraintType = SDTCisVec;
} else if (R->isSubClassOf("SDTCisSameAs")) {
ConstraintType = SDTCisSameAs;
x.SDTCisSameAs_Info.OtherOperandNum = R->getValueAsInt("OtherOperandNum");
ConstraintType = SDTCisOpSmallerThanOp;
x.SDTCisOpSmallerThanOp_Info.BigOperandNum =
R->getValueAsInt("BigOperandNum");
- } else if (R->isSubClassOf("SDTCisIntVectorOfSameSize")) {
- ConstraintType = SDTCisIntVectorOfSameSize;
- x.SDTCisIntVectorOfSameSize_Info.OtherOperandNum =
- R->getValueAsInt("OtherOpNum");
} else if (R->isSubClassOf("SDTCisEltOfVec")) {
ConstraintType = SDTCisEltOfVec;
x.SDTCisEltOfVec_Info.OtherOperandNum =
R->getValueAsInt("OtherOpNum");
} else {
- cerr << "Unrecognized SDTypeConstraint '" << R->getName() << "'!\n";
+ errs() << "Unrecognized SDTypeConstraint '" << R->getName() << "'!\n";
exit(1);
}
}
"We only work with nodes with zero or one result so far!");
if (OpNo >= (NumResults + N->getNumChildren())) {
- cerr << "Invalid operand number " << OpNo << " ";
+ errs() << "Invalid operand number " << OpNo << " ";
N->dump();
- cerr << '\n';
+ errs() << '\n';
exit(1);
}
// If we found exactly one supported integer type, apply it.
if (IntVTs.size() == 1)
return NodeToApply->UpdateNodeType(IntVTs[0], TP);
- return NodeToApply->UpdateNodeType(EMVT::isInt, TP);
+ return NodeToApply->UpdateNodeType(MVT::iAny, TP);
}
case SDTCisFP: {
// If there is only one FP type supported, this must be it.
// If we found exactly one supported FP type, apply it.
if (FPVTs.size() == 1)
return NodeToApply->UpdateNodeType(FPVTs[0], TP);
- return NodeToApply->UpdateNodeType(EMVT::isFP, TP);
+ return NodeToApply->UpdateNodeType(MVT::fAny, TP);
+ }
+ case SDTCisVec: {
+ // If there is only one vector type supported, this must be it.
+ std::vector<MVT::SimpleValueType> VecVTs =
+ FilterVTs(CGT.getLegalValueTypes(), isVector);
+
+ // If we found exactly one supported vector type, apply it.
+ if (VecVTs.size() == 1)
+ return NodeToApply->UpdateNodeType(VecVTs[0], TP);
+ return NodeToApply->UpdateNodeType(MVT::vAny, TP);
}
case SDTCisSameAs: {
TreePatternNode *OtherNode =
// It must be integer.
bool MadeChange = false;
- MadeChange |= OtherNode->UpdateNodeType(EMVT::isInt, TP);
+ MadeChange |= OtherNode->UpdateNodeType(MVT::iAny, TP);
// This code only handles nodes that have one type set. Assert here so
// that we can change this if we ever need to deal with multiple value
// This code does not currently handle nodes which have multiple types,
// where some types are integer, and some are fp. Assert that this is not
// the case.
- assert(!(EMVT::isExtIntegerInVTs(NodeToApply->getExtTypes()) &&
- EMVT::isExtFloatingPointInVTs(NodeToApply->getExtTypes())) &&
- !(EMVT::isExtIntegerInVTs(BigOperand->getExtTypes()) &&
- EMVT::isExtFloatingPointInVTs(BigOperand->getExtTypes())) &&
+ assert(!(EEVT::isExtIntegerInVTs(NodeToApply->getExtTypes()) &&
+ EEVT::isExtFloatingPointInVTs(NodeToApply->getExtTypes())) &&
+ !(EEVT::isExtIntegerInVTs(BigOperand->getExtTypes()) &&
+ EEVT::isExtFloatingPointInVTs(BigOperand->getExtTypes())) &&
"SDTCisOpSmallerThanOp does not handle mixed int/fp types!");
- if (EMVT::isExtIntegerInVTs(NodeToApply->getExtTypes()))
- MadeChange |= BigOperand->UpdateNodeType(EMVT::isInt, TP);
- else if (EMVT::isExtFloatingPointInVTs(NodeToApply->getExtTypes()))
- MadeChange |= BigOperand->UpdateNodeType(EMVT::isFP, TP);
- if (EMVT::isExtIntegerInVTs(BigOperand->getExtTypes()))
- MadeChange |= NodeToApply->UpdateNodeType(EMVT::isInt, TP);
- else if (EMVT::isExtFloatingPointInVTs(BigOperand->getExtTypes()))
- MadeChange |= NodeToApply->UpdateNodeType(EMVT::isFP, TP);
+ if (EEVT::isExtIntegerInVTs(NodeToApply->getExtTypes()))
+ MadeChange |= BigOperand->UpdateNodeType(MVT::iAny, TP);
+ else if (EEVT::isExtFloatingPointInVTs(NodeToApply->getExtTypes()))
+ MadeChange |= BigOperand->UpdateNodeType(MVT::fAny, TP);
+ if (EEVT::isExtIntegerInVTs(BigOperand->getExtTypes()))
+ MadeChange |= NodeToApply->UpdateNodeType(MVT::iAny, TP);
+ else if (EEVT::isExtFloatingPointInVTs(BigOperand->getExtTypes()))
+ MadeChange |= NodeToApply->UpdateNodeType(MVT::fAny, TP);
std::vector<MVT::SimpleValueType> VTs = CGT.getLegalValueTypes();
- if (EMVT::isExtIntegerInVTs(NodeToApply->getExtTypes())) {
+ if (EEVT::isExtIntegerInVTs(NodeToApply->getExtTypes())) {
VTs = FilterVTs(VTs, isInteger);
- } else if (EMVT::isExtFloatingPointInVTs(NodeToApply->getExtTypes())) {
+ } else if (EEVT::isExtFloatingPointInVTs(NodeToApply->getExtTypes())) {
VTs = FilterVTs(VTs, isFloatingPoint);
} else {
VTs.clear();
default: // Too many VT's to pick from.
case 0: break; // No info yet.
case 1:
- // Only one VT of this flavor. Cannot ever satisify the constraints.
+ // Only one VT of this flavor. Cannot ever satisfy the constraints.
return NodeToApply->UpdateNodeType(MVT::Other, TP); // throw
case 2:
// If we have exactly two possible types, the little operand must be the
}
return MadeChange;
}
- case SDTCisIntVectorOfSameSize: {
- TreePatternNode *OtherOperand =
- getOperandNum(x.SDTCisIntVectorOfSameSize_Info.OtherOperandNum,
- N, NumResults);
- if (OtherOperand->hasTypeSet()) {
- if (!isVector(OtherOperand->getTypeNum(0)))
- TP.error(N->getOperator()->getName() + " VT operand must be a vector!");
- MVT IVT = OtherOperand->getTypeNum(0);
- unsigned NumElements = IVT.getVectorNumElements();
- IVT = MVT::getIntVectorWithNumElements(NumElements);
- return NodeToApply->UpdateNodeType(IVT.getSimpleVT(), TP);
- }
- return false;
- }
case SDTCisEltOfVec: {
TreePatternNode *OtherOperand =
- getOperandNum(x.SDTCisIntVectorOfSameSize_Info.OtherOperandNum,
+ getOperandNum(x.SDTCisEltOfVec_Info.OtherOperandNum,
N, NumResults);
if (OtherOperand->hasTypeSet()) {
if (!isVector(OtherOperand->getTypeNum(0)))
TP.error(N->getOperator()->getName() + " VT operand must be a vector!");
- MVT IVT = OtherOperand->getTypeNum(0);
+ EVT IVT = OtherOperand->getTypeNum(0);
IVT = IVT.getVectorElementType();
- return NodeToApply->UpdateNodeType(IVT.getSimpleVT(), TP);
+ return NodeToApply->UpdateNodeType(IVT.getSimpleVT().SimpleTy, TP);
}
return false;
}
} else if (PropList[i]->getName() == "SDNPMemOperand") {
Properties |= 1 << SDNPMemOperand;
} else {
- cerr << "Unknown SD Node property '" << PropList[i]->getName()
- << "' on node '" << R->getName() << "'!\n";
+ errs() << "Unknown SD Node property '" << PropList[i]->getName()
+ << "' on node '" << R->getName() << "'!\n";
exit(1);
}
}
TreePattern &TP) {
assert(!ExtVTs.empty() && "Cannot update node type with empty type vector!");
- if (ExtVTs[0] == EMVT::isUnknown || LHSIsSubsetOfRHS(getExtTypes(), ExtVTs))
+ if (ExtVTs[0] == EEVT::isUnknown || LHSIsSubsetOfRHS(getExtTypes(), ExtVTs))
return false;
if (isTypeCompletelyUnknown() || LHSIsSubsetOfRHS(ExtVTs, getExtTypes())) {
setTypes(ExtVTs);
return true;
}
- if (getExtTypeNum(0) == MVT::iPTR) {
- if (ExtVTs[0] == MVT::iPTR || ExtVTs[0] == EMVT::isInt)
+ if (getExtTypeNum(0) == MVT::iPTR || getExtTypeNum(0) == MVT::iPTRAny) {
+ if (ExtVTs[0] == MVT::iPTR || ExtVTs[0] == MVT::iPTRAny ||
+ ExtVTs[0] == MVT::iAny)
return false;
- if (EMVT::isExtIntegerInVTs(ExtVTs)) {
+ if (EEVT::isExtIntegerInVTs(ExtVTs)) {
std::vector<unsigned char> FVTs = FilterEVTs(ExtVTs, isInteger);
if (FVTs.size()) {
setTypes(ExtVTs);
}
}
}
-
- if (ExtVTs[0] == EMVT::isInt && EMVT::isExtIntegerInVTs(getExtTypes())) {
+
+ // Merge vAny with iAny/fAny. The latter include vector types so keep them
+ // as the more specific information.
+ if (ExtVTs[0] == MVT::vAny &&
+ (getExtTypeNum(0) == MVT::iAny || getExtTypeNum(0) == MVT::fAny))
+ return false;
+ if (getExtTypeNum(0) == MVT::vAny &&
+ (ExtVTs[0] == MVT::iAny || ExtVTs[0] == MVT::fAny)) {
+ setTypes(ExtVTs);
+ return true;
+ }
+
+ if (ExtVTs[0] == MVT::iAny &&
+ EEVT::isExtIntegerInVTs(getExtTypes())) {
assert(hasTypeSet() && "should be handled above!");
std::vector<unsigned char> FVTs = FilterEVTs(getExtTypes(), isInteger);
if (getExtTypes() == FVTs)
setTypes(FVTs);
return true;
}
- if (ExtVTs[0] == MVT::iPTR && EMVT::isExtIntegerInVTs(getExtTypes())) {
+ if ((ExtVTs[0] == MVT::iPTR || ExtVTs[0] == MVT::iPTRAny) &&
+ EEVT::isExtIntegerInVTs(getExtTypes())) {
//assert(hasTypeSet() && "should be handled above!");
std::vector<unsigned char> FVTs = FilterEVTs(getExtTypes(), isInteger);
if (getExtTypes() == FVTs)
return true;
}
}
- if (ExtVTs[0] == EMVT::isFP && EMVT::isExtFloatingPointInVTs(getExtTypes())) {
+ if (ExtVTs[0] == MVT::fAny &&
+ EEVT::isExtFloatingPointInVTs(getExtTypes())) {
assert(hasTypeSet() && "should be handled above!");
std::vector<unsigned char> FVTs =
FilterEVTs(getExtTypes(), isFloatingPoint);
setTypes(FVTs);
return true;
}
-
- // If we know this is an int or fp type, and we are told it is a specific one,
- // take the advice.
+ if (ExtVTs[0] == MVT::vAny &&
+ EEVT::isExtVectorInVTs(getExtTypes())) {
+ assert(hasTypeSet() && "should be handled above!");
+ std::vector<unsigned char> FVTs = FilterEVTs(getExtTypes(), isVector);
+ if (getExtTypes() == FVTs)
+ return false;
+ setTypes(FVTs);
+ return true;
+ }
+
+ // If we know this is an int, FP, or vector type, and we are told it is a
+ // specific one, take the advice.
//
// Similarly, we should probably set the type here to the intersection of
- // {isInt|isFP} and ExtVTs
- if ((getExtTypeNum(0) == EMVT::isInt &&
- EMVT::isExtIntegerInVTs(ExtVTs)) ||
- (getExtTypeNum(0) == EMVT::isFP &&
- EMVT::isExtFloatingPointInVTs(ExtVTs))) {
+ // {iAny|fAny|vAny} and ExtVTs
+ if ((getExtTypeNum(0) == MVT::iAny &&
+ EEVT::isExtIntegerInVTs(ExtVTs)) ||
+ (getExtTypeNum(0) == MVT::fAny &&
+ EEVT::isExtFloatingPointInVTs(ExtVTs)) ||
+ (getExtTypeNum(0) == MVT::vAny &&
+ EEVT::isExtVectorInVTs(ExtVTs))) {
setTypes(ExtVTs);
return true;
}
- if (getExtTypeNum(0) == EMVT::isInt && ExtVTs[0] == MVT::iPTR) {
+ if (getExtTypeNum(0) == MVT::iAny &&
+ (ExtVTs[0] == MVT::iPTR || ExtVTs[0] == MVT::iPTRAny)) {
setTypes(ExtVTs);
return true;
}
if (isLeaf()) {
dump();
- cerr << " ";
+ errs() << " ";
TP.error("Type inference contradiction found in node!");
} else {
TP.error("Type inference contradiction found in node " +
}
-void TreePatternNode::print(std::ostream &OS) const {
+void TreePatternNode::print(raw_ostream &OS) const {
if (isLeaf()) {
OS << *getLeafValue();
} else {
// nodes that are multiply typed.
switch (getExtTypeNum(0)) {
case MVT::Other: OS << ":Other"; break;
- case EMVT::isInt: OS << ":isInt"; break;
- case EMVT::isFP : OS << ":isFP"; break;
- case EMVT::isUnknown: ; /*OS << ":?";*/ break;
+ case MVT::iAny: OS << ":iAny"; break;
+ case MVT::fAny : OS << ":fAny"; break;
+ case MVT::vAny: OS << ":vAny"; break;
+ case EEVT::isUnknown: ; /*OS << ":?";*/ break;
case MVT::iPTR: OS << ":iPTR"; break;
+ case MVT::iPTRAny: OS << ":iPTRAny"; break;
default: {
std::string VTName = llvm::getName(getTypeNum(0));
- // Strip off MVT:: prefix if present.
+ // Strip off EVT:: prefix if present.
if (VTName.substr(0,5) == "MVT::")
VTName = VTName.substr(5);
OS << ":" << VTName;
OS << ")";
}
- if (!PredicateFn.empty())
- OS << "<<P:" << PredicateFn << ">>";
+ for (unsigned i = 0, e = PredicateFns.size(); i != e; ++i)
+ OS << "<<P:" << PredicateFns[i] << ">>";
if (TransformFn)
OS << "<<X:" << TransformFn->getName() << ">>";
if (!getName().empty())
}
void TreePatternNode::dump() const {
- print(*cerr.stream());
+ print(errs());
}
/// isIsomorphicTo - Return true if this node is recursively
const MultipleUseVarSet &DepVars) const {
if (N == this) return true;
if (N->isLeaf() != isLeaf() || getExtTypes() != N->getExtTypes() ||
- getPredicateFn() != N->getPredicateFn() ||
+ getPredicateFns() != N->getPredicateFns() ||
getTransformFn() != N->getTransformFn())
return false;
}
New->setName(getName());
New->setTypes(getExtTypes());
- New->setPredicateFn(getPredicateFn());
+ New->setPredicateFns(getPredicateFns());
New->setTransformFn(getTransformFn());
return New;
}
if (dynamic_cast<DefInit*>(Val) &&
static_cast<DefInit*>(Val)->getDef()->getName() == "node") {
// We found a use of a formal argument, replace it with its value.
- Child = ArgMap[Child->getName()];
- assert(Child && "Couldn't find formal argument!");
- setChild(i, Child);
+ TreePatternNode *NewChild = ArgMap[Child->getName()];
+ assert(NewChild && "Couldn't find formal argument!");
+ assert((Child->getPredicateFns().empty() ||
+ NewChild->getPredicateFns() == Child->getPredicateFns()) &&
+ "Non-empty child predicate clobbered!");
+ setChild(i, NewChild);
}
} else {
getChild(i)->SubstituteFormalArguments(ArgMap);
if (!Op->isSubClassOf("PatFrag")) {
// Just recursively inline children nodes.
- for (unsigned i = 0, e = getNumChildren(); i != e; ++i)
- setChild(i, getChild(i)->InlinePatternFragments(TP));
+ for (unsigned i = 0, e = getNumChildren(); i != e; ++i) {
+ TreePatternNode *Child = getChild(i);
+ TreePatternNode *NewChild = Child->InlinePatternFragments(TP);
+
+ assert((Child->getPredicateFns().empty() ||
+ NewChild->getPredicateFns() == Child->getPredicateFns()) &&
+ "Non-empty child predicate clobbered!");
+
+ setChild(i, NewChild);
+ }
return this;
}
TreePatternNode *FragTree = Frag->getOnlyTree()->clone();
+ std::string Code = Op->getValueAsCode("Predicate");
+ if (!Code.empty())
+ FragTree->addPredicateFn("Predicate_"+Op->getName());
+
// Resolve formal arguments to their actual value.
if (Frag->getNumArgs()) {
// Compute the map of formal to actual arguments.
FragTree->setName(getName());
FragTree->UpdateNodeType(getExtTypes(), TP);
-
+
+ // Transfer in the old predicates.
+ for (unsigned i = 0, e = getPredicateFns().size(); i != e; ++i)
+ FragTree->addPredicateFn(getPredicateFns()[i]);
+
// Get a new copy of this fragment to stitch into here.
//delete this; // FIXME: implement refcounting!
- return FragTree;
+
+ // The fragment we inlined could have recursive inlining that is needed. See
+ // if there are any pattern fragments in it and inline them as needed.
+ return FragTree->InlinePatternFragments(TP);
}
/// getImplicitType - Check to see if the specified record has an implicit
-/// type which should be applied to it. This infer the type of register
+/// type which should be applied to it. This will infer the type of register
/// references from the register file information, for example.
///
static std::vector<unsigned char> getImplicitType(Record *R, bool NotRegisters,
TreePattern &TP) {
// Some common return values
- std::vector<unsigned char> Unknown(1, EMVT::isUnknown);
+ std::vector<unsigned char> Unknown(1, EEVT::isUnknown);
std::vector<unsigned char> Other(1, MVT::Other);
// Check to see if this is a register or a register class...
std::vector<unsigned char>
ComplexPat(1, TP.getDAGPatterns().getComplexPattern(R).getValueType());
return ComplexPat;
- } else if (R->getName() == "ptr_rc") {
+ } else if (R->isSubClassOf("PointerLikeRegClass")) {
Other[0] = MVT::iPTR;
return Other;
} else if (R->getName() == "node" || R->getName() == "srcvalue" ||
}
-/// ApplyTypeConstraints - Apply all of the type constraints relevent to
+/// ApplyTypeConstraints - Apply all of the type constraints relevant to
/// this node and its children in the tree. This returns true if it makes a
/// change, false otherwise. If a type contradiction is found, throw an
/// exception.
return UpdateNodeType(getImplicitType(DI->getDef(), NotRegisters, TP),TP);
} else if (IntInit *II = dynamic_cast<IntInit*>(getLeafValue())) {
// Int inits are always integers. :)
- bool MadeChange = UpdateNodeType(EMVT::isInt, TP);
+ bool MadeChange = UpdateNodeType(MVT::iAny, TP);
if (hasTypeSet()) {
// At some point, it may make sense for this tree pattern to have
assert(getTypeNum(i) == VT && "TreePattern has too many types!");
VT = getTypeNum(0);
- if (VT != MVT::iPTR) {
- unsigned Size = MVT(VT).getSizeInBits();
+ if (VT != MVT::iPTR && VT != MVT::iPTRAny) {
+ unsigned Size = EVT(VT).getSizeInBits();
// Make sure that the value is representable for this type.
if (Size < 32) {
int Val = (II->getValue() << (32-Size)) >> (32-Size);
// If sign-extended doesn't fit, does it fit as unsigned?
unsigned ValueMask;
unsigned UnsignedVal;
- ValueMask = unsigned(MVT(VT).getIntegerVTBitMask());
+ ValueMask = unsigned(~uint32_t(0UL) >> (32-Size));
UnsignedVal = unsigned(II->getValue());
if ((ValueMask & UnsignedVal) != UnsignedVal) {
getEnumName(getTypeNum(0)) + "'!");
}
}
- }
- }
+ }
+ }
}
return MadeChange;
MadeChange = getChild(i)->ApplyTypeConstraints(TP, NotRegisters);
MadeChange |= UpdateNodeType(MVT::isVoid, TP);
return MadeChange;
+ } else if (getOperator()->getName() == "COPY_TO_REGCLASS") {
+ bool MadeChange = false;
+ MadeChange |= getChild(0)->ApplyTypeConstraints(TP, NotRegisters);
+ MadeChange |= getChild(1)->ApplyTypeConstraints(TP, NotRegisters);
+ return MadeChange;
} else if (const CodeGenIntrinsic *Int = getIntrinsicInfo(CDP)) {
bool MadeChange = false;
// Apply the result type to the node.
- MadeChange = UpdateNodeType(Int->ArgVTs[0], TP);
+ unsigned NumRetVTs = Int->IS.RetVTs.size();
+ unsigned NumParamVTs = Int->IS.ParamVTs.size();
+
+ for (unsigned i = 0, e = NumRetVTs; i != e; ++i)
+ MadeChange |= UpdateNodeType(Int->IS.RetVTs[i], TP);
- if (getNumChildren() != Int->ArgVTs.size())
+ if (getNumChildren() != NumParamVTs + NumRetVTs)
TP.error("Intrinsic '" + Int->Name + "' expects " +
- utostr(Int->ArgVTs.size()-1) + " operands, not " +
- utostr(getNumChildren()-1) + " operands!");
+ utostr(NumParamVTs + NumRetVTs - 1) + " operands, not " +
+ utostr(getNumChildren() - 1) + " operands!");
// Apply type info to the intrinsic ID.
MadeChange |= getChild(0)->UpdateNodeType(MVT::iPTR, TP);
- for (unsigned i = 1, e = getNumChildren(); i != e; ++i) {
- MVT::SimpleValueType OpVT = Int->ArgVTs[i];
+ for (unsigned i = NumRetVTs, e = getNumChildren(); i != e; ++i) {
+ MVT::SimpleValueType OpVT = Int->IS.ParamVTs[i - NumRetVTs];
MadeChange |= getChild(i)->UpdateNodeType(OpVT, TP);
MadeChange |= getChild(i)->ApplyTypeConstraints(TP, NotRegisters);
}
if (NI.getNumResults() == 0)
MadeChange |= UpdateNodeType(MVT::isVoid, TP);
- // If this is a vector_shuffle operation, apply types to the build_vector
- // operation. The types of the integers don't matter, but this ensures they
- // won't get checked.
- if (getOperator()->getName() == "vector_shuffle" &&
- getChild(2)->getOperator()->getName() == "build_vector") {
- TreePatternNode *BV = getChild(2);
- const std::vector<MVT::SimpleValueType> &LegalVTs
- = CDP.getTargetInfo().getLegalValueTypes();
- MVT::SimpleValueType LegalIntVT = MVT::Other;
- for (unsigned i = 0, e = LegalVTs.size(); i != e; ++i)
- if (isInteger(LegalVTs[i]) && !isVector(LegalVTs[i])) {
- LegalIntVT = LegalVTs[i];
- break;
- }
- assert(LegalIntVT != MVT::Other && "No legal integer VT?");
-
- for (unsigned i = 0, e = BV->getNumChildren(); i != e; ++i)
- MadeChange |= BV->getChild(i)->UpdateNodeType(LegalIntVT, TP);
- }
return MadeChange;
} else if (getOperator()->isSubClassOf("Instruction")) {
const DAGInstruction &Inst = CDP.getInstruction(getOperator());
} else {
Record *ResultNode = Inst.getResult(0);
- if (ResultNode->getName() == "ptr_rc") {
+ if (ResultNode->isSubClassOf("PointerLikeRegClass")) {
std::vector<unsigned char> VT;
VT.push_back(MVT::iPTR);
MadeChange = UpdateNodeType(VT, TP);
} else if (ResultNode->getName() == "unknown") {
std::vector<unsigned char> VT;
- VT.push_back(EMVT::isUnknown);
+ VT.push_back(EEVT::isUnknown);
MadeChange = UpdateNodeType(VT, TP);
} else {
assert(ResultNode->isSubClassOf("RegisterClass") &&
} else if (OperandNode->isSubClassOf("Operand")) {
VT = getValueType(OperandNode->getValueAsDef("Type"));
MadeChange |= Child->UpdateNodeType(VT, TP);
- } else if (OperandNode->getName() == "ptr_rc") {
+ } else if (OperandNode->isSubClassOf("PointerLikeRegClass")) {
MadeChange |= Child->UpdateNodeType(MVT::iPTR, TP);
} else if (OperandNode->getName() == "unknown") {
- MadeChange |= Child->UpdateNodeType(EMVT::isUnknown, TP);
+ MadeChange |= Child->UpdateNodeType(EEVT::isUnknown, TP);
} else {
assert(0 && "Unknown operand type!");
abort();
/// 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
+/// used as a sanity check for .td files (to prevent people from writing stuff
/// that can never possibly work), and to prevent the pattern permuter from
/// generating stuff that is useless.
bool TreePatternNode::canPatternMatch(std::string &Reason,
void TreePattern::error(const std::string &Msg) const {
dump();
- throw "In " + TheRecord->getName() + ": " + Msg;
+ throw TGError(TheRecord->getLoc(), "In " + TheRecord->getName() + ": " + Msg);
}
TreePatternNode *TreePattern::ParseTreePattern(DagInit *Dag) {
if (DefInit *DI = dynamic_cast<DefInit*>(Arg)) {
Record *R = DI->getDef();
if (R->isSubClassOf("SDNode") || R->isSubClassOf("PatFrag")) {
- Dag->setArg(0, new DagInit(DI,
+ Dag->setArg(0, new DagInit(DI, "",
std::vector<std::pair<Init*, std::string> >()));
return ParseTreePattern(Dag);
}
// Apply the type cast.
New->UpdateNodeType(getValueType(Operator), *this);
- New->setName(Dag->getArgName(0));
+ if (New->getNumChildren() == 0)
+ New->setName(Dag->getArgName(0));
return New;
}
// Verify that this is something that makes sense for an operator.
- if (!Operator->isSubClassOf("PatFrag") && !Operator->isSubClassOf("SDNode") &&
+ if (!Operator->isSubClassOf("PatFrag") &&
+ !Operator->isSubClassOf("SDNode") &&
!Operator->isSubClassOf("Instruction") &&
!Operator->isSubClassOf("SDNodeXForm") &&
!Operator->isSubClassOf("Intrinsic") &&
// Direct reference to a leaf DagNode or PatFrag? Turn it into a
// TreePatternNode if its own.
if (R->isSubClassOf("SDNode") || R->isSubClassOf("PatFrag")) {
- Dag->setArg(i, new DagInit(DefI,
+ Dag->setArg(i, new DagInit(DefI, "",
std::vector<std::pair<Init*, std::string> >()));
--i; // Revisit this node...
} else {
error("Constant int argument should not have a name!");
Children.push_back(Node);
} else {
- cerr << '"';
+ errs() << '"';
Arg->dump();
- cerr << "\": ";
+ errs() << "\": ";
error("Unknown leaf value for tree pattern!");
}
}
// If this intrinsic returns void, it must have side-effects and thus a
// chain.
- if (Int.ArgVTs[0] == MVT::isVoid) {
+ if (Int.IS.RetVTs[0] == MVT::isVoid) {
Operator = getDAGPatterns().get_intrinsic_void_sdnode();
} else if (Int.ModRef != CodeGenIntrinsic::NoMem) {
// Has side-effects, requires chain.
Children.insert(Children.begin(), IIDNode);
}
- return new TreePatternNode(Operator, Children);
+ TreePatternNode *Result = new TreePatternNode(Operator, Children);
+ Result->setName(Dag->getName());
+ return Result;
}
/// InferAllTypes - Infer/propagate as many types throughout the expression
-/// patterns as possible. Return true if all types are infered, false
+/// patterns as possible. Return true if all types are inferred, false
/// otherwise. Throw an exception if a type contradiction is found.
bool TreePattern::InferAllTypes() {
bool MadeChange = true;
return !HasUnresolvedTypes;
}
-void TreePattern::print(std::ostream &OS) const {
+void TreePattern::print(raw_ostream &OS) const {
OS << getRecord()->getName();
if (!Args.empty()) {
OS << "(" << Args[0];
OS << "]\n";
}
-void TreePattern::dump() const { print(*cerr.stream()); }
+void TreePattern::dump() const { print(errs()); }
//===----------------------------------------------------------------------===//
// CodeGenDAGPatterns implementation
// FIXME: REMOVE OSTREAM ARGUMENT
CodeGenDAGPatterns::CodeGenDAGPatterns(RecordKeeper &R) : Records(R) {
- Intrinsics = LoadIntrinsics(Records);
+ Intrinsics = LoadIntrinsics(Records, false);
+ TgtIntrinsics = LoadIntrinsics(Records, true);
ParseNodeInfo();
ParseNodeTransforms();
ParseComplexPatterns();
}
CodeGenDAGPatterns::~CodeGenDAGPatterns() {
- for (std::map<Record*, TreePattern*>::iterator I = PatternFragments.begin(),
+ for (pf_iterator I = PatternFragments.begin(),
E = PatternFragments.end(); I != E; ++I)
delete I->second;
}
Record *CodeGenDAGPatterns::getSDNodeNamed(const std::string &Name) const {
Record *N = Records.getDef(Name);
if (!N || !N->isSubClassOf("SDNode")) {
- cerr << "Error getting SDNode '" << Name << "'!\n";
+ errs() << "Error getting SDNode '" << Name << "'!\n";
exit(1);
}
return N;
Nodes.pop_back();
}
- // Get the buildin intrinsic nodes.
+ // Get the builtin intrinsic nodes.
intrinsic_void_sdnode = getSDNodeNamed("intrinsic_void");
intrinsic_w_chain_sdnode = getSDNodeNamed("intrinsic_w_chain");
intrinsic_wo_chain_sdnode = getSDNodeNamed("intrinsic_wo_chain");
DagInit *OpsList = Fragments[i]->getValueAsDag("Operands");
DefInit *OpsOp = dynamic_cast<DefInit*>(OpsList->getOperator());
// Special cases: ops == outs == ins. Different names are used to
- // improve readibility.
+ // improve readability.
if (!OpsOp ||
(OpsOp->getDef()->getName() != "ops" &&
OpsOp->getDef()->getName() != "outs" &&
// this fragment uses it.
std::string Code = Fragments[i]->getValueAsCode("Predicate");
if (!Code.empty())
- P->getOnlyTree()->setPredicateFn("Predicate_"+Fragments[i]->getName());
+ P->getOnlyTree()->addPredicateFn("Predicate_"+Fragments[i]->getName());
// If there is a node transformation corresponding to this, keep track of
// it.
// Now that we've parsed all of the tree fragments, do a closure on them so
// that there are not references to PatFrags left inside of them.
- for (std::map<Record*, TreePattern*>::iterator I = PatternFragments.begin(),
- E = PatternFragments.end(); I != E; ++I) {
- TreePattern *ThePat = I->second;
+ for (unsigned i = 0, e = Fragments.size(); i != e; ++i) {
+ TreePattern *ThePat = PatternFragments[Fragments[i]];
ThePat->InlinePatternFragments();
// Infer as many types as possible. Don't worry about it if we don't infer
for (unsigned op = 0, e = DefaultInfo->getNumArgs(); op != e; ++op)
Ops.push_back(std::make_pair(DefaultInfo->getArg(op),
DefaultInfo->getArgName(op)));
- DagInit *DI = new DagInit(SomeSDNode, Ops);
+ DagInit *DI = new DagInit(SomeSDNode, "", Ops);
// Create a TreePattern to parse this.
TreePattern P(DefaultOps[iter][i], DI, false, *this);
I->error("Input " + DI->getDef()->getName() + " must be named!");
else if (DI && DI->getDef()->isSubClassOf("Register"))
InstImpInputs.push_back(DI->getDef());
- ;
}
return false;
}
if (!DI) I->error("Input $" + Pat->getName() + " must be an identifier!");
Rec = DI->getDef();
} else {
- assert(Pat->getNumChildren() == 0 && "can't be a use with children!");
Rec = Pat->getOperator();
}
// If this is a non-leaf node with no children, treat it basically as if
// it were a leaf. This handles nodes like (imm).
- bool isUse = false;
- if (Pat->getNumChildren() == 0)
- isUse = HandleUse(I, Pat, InstInputs, InstImpInputs);
+ bool isUse = HandleUse(I, Pat, InstInputs, InstImpInputs);
if (!isUse && Pat->getTransformFn())
I->error("Cannot specify a transform function for a non-input value!");
I->error("set destination should be a register!");
if (Val->getDef()->isSubClassOf("RegisterClass") ||
- Val->getDef()->getName() == "ptr_rc") {
+ Val->getDef()->isSubClassOf("PointerLikeRegClass")) {
if (Dest->getName().empty())
I->error("set destination must have a name!");
if (InstResults.count(Dest->getName()))
TreePatternNode *OpNode = InVal->clone();
// No predicate is useful on the result.
- OpNode->setPredicateFn("");
+ OpNode->clearPredicateFns();
// Promote the xform function to be an explicit node if set.
if (Record *Xform = OpNode->getTransformFn()) {
}
// If we can, convert the instructions to be patterns that are matched!
- for (std::map<Record*, DAGInstruction>::iterator II = Instructions.begin(),
+ for (std::map<Record*, DAGInstruction, RecordPtrCmp>::iterator II =
+ Instructions.begin(),
E = Instructions.end(); II != E; ++II) {
DAGInstruction &TheInst = II->second;
const TreePattern *I = TheInst.getPattern();
Pattern = new TreePattern(Patterns[i], Tree, true, *this);
else {
std::vector<Init*> Values;
- for (unsigned j = 0, ee = Tree->getNumArgs(); j != ee; ++j)
+ RecTy *ListTy = 0;
+ for (unsigned j = 0, ee = Tree->getNumArgs(); j != ee; ++j) {
Values.push_back(Tree->getArg(j));
- ListInit *LI = new ListInit(Values);
+ TypedInit *TArg = dynamic_cast<TypedInit*>(Tree->getArg(j));
+ if (TArg == 0) {
+ errs() << "In dag: " << Tree->getAsString();
+ errs() << " -- Untyped argument in pattern\n";
+ assert(0 && "Untyped argument in pattern");
+ }
+ if (ListTy != 0) {
+ ListTy = resolveTypes(ListTy, TArg->getType());
+ if (ListTy == 0) {
+ errs() << "In dag: " << Tree->getAsString();
+ errs() << " -- Incompatible types in pattern arguments\n";
+ assert(0 && "Incompatible types in pattern arguments");
+ }
+ }
+ else {
+ ListTy = TArg->getType();
+ }
+ }
+ ListInit *LI = new ListInit(Values, new ListRecTy(ListTy));
Pattern = new TreePattern(Patterns[i], LI, true, *this);
}
IterateInference |= Result->getTree(0)->
UpdateNodeType(Pattern->getTree(0)->getExtTypes(), *Result);
} while (IterateInference);
-
+
// Verify that we inferred enough types that we can do something with the
// pattern and result. If these fire the user has to add type casts.
if (!InferredAllPatternTypes)
do {
#ifndef NDEBUG
if (DebugFlag && !Idxs.empty()) {
- cerr << Orig->getOperator()->getName() << ": Idxs = [ ";
+ errs() << Orig->getOperator()->getName() << ": Idxs = [ ";
for (unsigned i = 0; i < Idxs.size(); ++i) {
- cerr << Idxs[i] << " ";
+ errs() << Idxs[i] << " ";
}
- cerr << "]\n";
+ errs() << "]\n";
}
#endif
// Create the variant and add it to the output list.
// Copy over properties.
R->setName(Orig->getName());
- R->setPredicateFn(Orig->getPredicateFn());
+ R->setPredicateFns(Orig->getPredicateFns());
R->setTransformFn(Orig->getTransformFn());
R->setTypes(Orig->getExtTypes());
Record *Operator = N->getOperator();
// Only permit raw nodes.
- if (!N->getName().empty() || !N->getPredicateFn().empty() ||
+ if (!N->getName().empty() || !N->getPredicateFns().empty() ||
N->getTransformFn()) {
Children.push_back(N);
return;
// Look up interesting info about the node.
const SDNodeInfo &NodeInfo = CDP.getSDNodeInfo(N->getOperator());
- // If this node is associative, reassociate.
+ // If this node is associative, re-associate.
if (NodeInfo.hasProperty(SDNPAssociative)) {
- // Reassociate by pulling together all of the linked operators
+ // Re-associate by pulling together all of the linked operators
std::vector<TreePatternNode*> MaximalChildren;
GatherChildrenOfAssociativeOpcode(N, MaximalChildren);
// GenerateVariants - Generate variants. For example, commutative patterns can
// match multiple ways. Add them to PatternsToMatch as well.
void CodeGenDAGPatterns::GenerateVariants() {
- DOUT << "Generating instruction variants.\n";
+ DEBUG(errs() << "Generating instruction variants.\n");
// Loop over all of the patterns we've collected, checking to see if we can
// generate variants of the instruction, through the exploitation of
- // identities. This permits the target to provide agressive matching without
+ // identities. This permits the target to provide aggressive matching without
// the .td file having to contain tons of variants of instructions.
//
// Note that this loop adds new patterns to the PatternsToMatch list, but we
MultipleUseVarSet DepVars;
std::vector<TreePatternNode*> Variants;
FindDepVars(PatternsToMatch[i].getSrcPattern(), DepVars);
- DOUT << "Dependent/multiply used variables: ";
+ DEBUG(errs() << "Dependent/multiply used variables: ");
DEBUG(DumpDepVars(DepVars));
- DOUT << "\n";
+ DEBUG(errs() << "\n");
GenerateVariantsOf(PatternsToMatch[i].getSrcPattern(), Variants, *this, DepVars);
assert(!Variants.empty() && "Must create at least original variant!");
if (Variants.empty()) // No variants for this pattern.
continue;
- DOUT << "FOUND VARIANTS OF: ";
- DEBUG(PatternsToMatch[i].getSrcPattern()->dump());
- DOUT << "\n";
+ DEBUG(errs() << "FOUND VARIANTS OF: ";
+ PatternsToMatch[i].getSrcPattern()->dump();
+ errs() << "\n");
for (unsigned v = 0, e = Variants.size(); v != e; ++v) {
TreePatternNode *Variant = Variants[v];
- DOUT << " VAR#" << v << ": ";
- DEBUG(Variant->dump());
- DOUT << "\n";
+ DEBUG(errs() << " VAR#" << v << ": ";
+ Variant->dump();
+ errs() << "\n");
// Scan to see if an instruction or explicit pattern already matches this.
bool AlreadyExists = false;
for (unsigned p = 0, e = PatternsToMatch.size(); p != e; ++p) {
+ // Skip if the top level predicates do not match.
+ if (PatternsToMatch[i].getPredicates() !=
+ PatternsToMatch[p].getPredicates())
+ continue;
// Check to see if this variant already exists.
if (Variant->isIsomorphicTo(PatternsToMatch[p].getSrcPattern(), DepVars)) {
- DOUT << " *** ALREADY EXISTS, ignoring variant.\n";
+ DEBUG(errs() << " *** ALREADY EXISTS, ignoring variant.\n");
AlreadyExists = true;
break;
}
PatternsToMatch[i].getAddedComplexity()));
}
- DOUT << "\n";
+ DEBUG(errs() << "\n");
}
}