#include "CodeGenDAGPatterns.h"
#include "llvm/ADT/STLExtras.h"
+#include "llvm/ADT/SmallString.h"
#include "llvm/ADT/StringExtras.h"
#include "llvm/ADT/Twine.h"
#include "llvm/Support/Debug.h"
// the size of the smallest type.
{
TypeSet InputSet(Other);
- MVT Smallest = TypeVec[0];
+ MVT Smallest = *std::min_element(TypeVec.begin(), TypeVec.end(),
+ [](MVT A, MVT B) {
+ return A.getScalarSizeInBits() < B.getScalarSizeInBits() ||
+ (A.getScalarSizeInBits() == B.getScalarSizeInBits() &&
+ A.getSizeInBits() < B.getSizeInBits());
+ });
+
auto I = std::remove_if(Other.TypeVec.begin(), Other.TypeVec.end(),
[Smallest](MVT OtherVT) {
// Don't compare vector and non-vector types.
// the size of the largest type.
{
TypeSet InputSet(*this);
- MVT Largest = Other.TypeVec[Other.TypeVec.size()-1];
+ MVT Largest = *std::max_element(Other.TypeVec.begin(), Other.TypeVec.end(),
+ [](MVT A, MVT B) {
+ return A.getScalarSizeInBits() < B.getScalarSizeInBits() ||
+ (A.getScalarSizeInBits() == B.getScalarSizeInBits() &&
+ A.getSizeInBits() < B.getSizeInBits());
+ });
auto I = std::remove_if(TypeVec.begin(), TypeVec.end(),
[Largest](MVT OtherVT) {
// Don't compare vector and non-vector types.
return MadeChange;
}
+/// EnforceSameSize - 'this' is now constrained to be same size as VTOperand.
+bool EEVT::TypeSet::EnforceSameSize(EEVT::TypeSet &VTOperand,
+ TreePattern &TP) {
+ if (TP.hasError())
+ return false;
+
+ bool MadeChange = false;
+
+ // If we know one of the types, it forces the other type agree.
+ if (isConcrete()) {
+ MVT IVT = getConcrete();
+ unsigned Size = IVT.getSizeInBits();
+
+ // Only keep types that have the same size as 'this'.
+ TypeSet InputSet(VTOperand);
+
+ auto I = std::remove_if(VTOperand.TypeVec.begin(), VTOperand.TypeVec.end(),
+ [&](MVT VT) {
+ return VT.getSizeInBits() != Size;
+ });
+ MadeChange |= I != VTOperand.TypeVec.end();
+ VTOperand.TypeVec.erase(I, VTOperand.TypeVec.end());
+
+ if (VTOperand.TypeVec.empty()) { // FIXME: Really want an SMLoc here!
+ TP.error("Type inference contradiction found, forcing '" +
+ InputSet.getName() + "' to have same size as '" +
+ getName() + "'");
+ return false;
+ }
+ } else if (VTOperand.isConcrete()) {
+ MVT IVT = VTOperand.getConcrete();
+ unsigned Size = IVT.getSizeInBits();
+
+ // Only keep types that have the same size as VTOperand.
+ TypeSet InputSet(*this);
+
+ auto I = std::remove_if(TypeVec.begin(), TypeVec.end(),
+ [&](MVT VT) {
+ return VT.getSizeInBits() != Size;
+ });
+ MadeChange |= I != TypeVec.end();
+ TypeVec.erase(I, TypeVec.end());
+
+ if (TypeVec.empty()) { // FIXME: Really want an SMLoc here!
+ TP.error("Type inference contradiction found, forcing '" +
+ InputSet.getName() + "' to have same size as '" +
+ VTOperand.getName() + "'");
+ return false;
+ }
+ }
+
+ return MadeChange;
+}
+
//===----------------------------------------------------------------------===//
// Helpers for working with extended types.
/// pattern's predicates concatenated with "&&" operators.
///
std::string PatternToMatch::getPredicateCheck() const {
- std::string PredicateCheck;
+ SmallVector<Record *, 4> PredicateRecs;
for (Init *I : Predicates->getValues()) {
if (DefInit *Pred = dyn_cast<DefInit>(I)) {
Record *Def = Pred->getDef();
#endif
llvm_unreachable("Unknown predicate type!");
}
- if (!PredicateCheck.empty())
- PredicateCheck += " && ";
- PredicateCheck += "(" + Def->getValueAsString("CondString") + ")";
+ PredicateRecs.push_back(Def);
}
}
+ // Sort so that different orders get canonicalized to the same string.
+ std::sort(PredicateRecs.begin(), PredicateRecs.end(), LessRecord());
+
+ SmallString<128> PredicateCheck;
+ for (Record *Pred : PredicateRecs) {
+ if (!PredicateCheck.empty())
+ PredicateCheck += " && ";
+ PredicateCheck += "(" + Pred->getValueAsString("CondString") + ")";
+ }
- return PredicateCheck;
+ return PredicateCheck.str();
}
//===----------------------------------------------------------------------===//
ConstraintType = SDTCisSameNumEltsAs;
x.SDTCisSameNumEltsAs_Info.OtherOperandNum =
R->getValueAsInt("OtherOperandNum");
+ } else if (R->isSubClassOf("SDTCisSameSizeAs")) {
+ ConstraintType = SDTCisSameSizeAs;
+ x.SDTCisSameSizeAs_Info.OtherOperandNum =
+ R->getValueAsInt("OtherOperandNum");
} else {
PrintFatalError("Unrecognized SDTypeConstraint '" + R->getName() + "'!\n");
}
return OtherNode->getExtType(OResNo).
EnforceVectorSameNumElts(NodeToApply->getExtType(ResNo), TP);
}
+ case SDTCisSameSizeAs: {
+ unsigned OResNo = 0;
+ TreePatternNode *OtherNode =
+ getOperandNum(x.SDTCisSameSizeAs_Info.OtherOperandNum,
+ N, NodeInfo, OResNo);
+ return OtherNode->getExtType(OResNo).
+ EnforceSameSize(NodeToApply->getExtType(ResNo), TP);
+ }
}
llvm_unreachable("Invalid ConstraintType!");
}