X-Git-Url: http://plrg.eecs.uci.edu/git/?p=oota-llvm.git;a=blobdiff_plain;f=utils%2FTableGen%2FCodeGenDAGPatterns.cpp;h=35b6bf4416b50d6b8c575da48f9e8c153ced98f7;hp=d4b02fbd2f335ca2124e28f5ff85b5f0be600796;hb=194e5aef9cbdd5ec76535da7d871767018214181;hpb=3cbcffc4e5990209ce80a54e615f55245fe3b824 diff --git a/utils/TableGen/CodeGenDAGPatterns.cpp b/utils/TableGen/CodeGenDAGPatterns.cpp index d4b02fbd2f3..35b6bf4416b 100644 --- a/utils/TableGen/CodeGenDAGPatterns.cpp +++ b/utils/TableGen/CodeGenDAGPatterns.cpp @@ -13,33 +13,35 @@ //===----------------------------------------------------------------------===// #include "CodeGenDAGPatterns.h" -#include "llvm/TableGen/Error.h" -#include "llvm/TableGen/Record.h" -#include "llvm/ADT/StringExtras.h" #include "llvm/ADT/STLExtras.h" +#include "llvm/ADT/StringExtras.h" #include "llvm/ADT/Twine.h" #include "llvm/Support/Debug.h" #include "llvm/Support/ErrorHandling.h" +#include "llvm/TableGen/Error.h" +#include "llvm/TableGen/Record.h" #include #include #include using namespace llvm; +#define DEBUG_TYPE "dag-patterns" + //===----------------------------------------------------------------------===// // EEVT::TypeSet Implementation //===----------------------------------------------------------------------===// static inline bool isInteger(MVT::SimpleValueType VT) { - return EVT(VT).isInteger(); + return MVT(VT).isInteger(); } static inline bool isFloatingPoint(MVT::SimpleValueType VT) { - return EVT(VT).isFloatingPoint(); + return MVT(VT).isFloatingPoint(); } static inline bool isVector(MVT::SimpleValueType VT) { - return EVT(VT).isVector(); + return MVT(VT).isVector(); } static inline bool isScalar(MVT::SimpleValueType VT) { - return !EVT(VT).isVector(); + return !MVT(VT).isVector(); } EEVT::TypeSet::TypeSet(MVT::SimpleValueType VT, TreePattern &TP) { @@ -51,13 +53,13 @@ EEVT::TypeSet::TypeSet(MVT::SimpleValueType VT, TreePattern &TP) { EnforceVector(TP); else { assert((VT < MVT::LAST_VALUETYPE || VT == MVT::iPTR || - VT == MVT::iPTRAny) && "Not a concrete type!"); + VT == MVT::iPTRAny || VT == MVT::Any) && "Not a concrete type!"); TypeVec.push_back(VT); } } -EEVT::TypeSet::TypeSet(const std::vector &VTList) { +EEVT::TypeSet::TypeSet(ArrayRef VTList) { assert(!VTList.empty() && "empty list?"); TypeVec.append(VTList.begin(), VTList.end()); @@ -76,17 +78,22 @@ bool EEVT::TypeSet::FillWithPossibleTypes(TreePattern &TP, bool (*Pred)(MVT::SimpleValueType), const char *PredicateName) { assert(isCompletelyUnknown()); - const std::vector &LegalTypes = + ArrayRef LegalTypes = TP.getDAGPatterns().getTargetInfo().getLegalValueTypes(); - for (unsigned i = 0, e = LegalTypes.size(); i != e; ++i) - if (Pred == 0 || Pred(LegalTypes[i])) - TypeVec.push_back(LegalTypes[i]); + if (TP.hasError()) + return false; + + for (MVT::SimpleValueType VT : LegalTypes) + if (!Pred || Pred(VT)) + TypeVec.push_back(VT); // If we have nothing that matches the predicate, bail out. - if (TypeVec.empty()) + if (TypeVec.empty()) { TP.error("Type inference contradiction found, no " + std::string(PredicateName) + " types found"); + return false; + } // No need to sort with one element. if (TypeVec.size() == 1) return true; @@ -100,28 +107,24 @@ bool EEVT::TypeSet::FillWithPossibleTypes(TreePattern &TP, /// hasIntegerTypes - Return true if this TypeSet contains iAny or an /// integer value type. bool EEVT::TypeSet::hasIntegerTypes() const { - for (unsigned i = 0, e = TypeVec.size(); i != e; ++i) - if (isInteger(TypeVec[i])) - return true; - return false; + return std::any_of(TypeVec.begin(), TypeVec.end(), isInteger); } /// hasFloatingPointTypes - Return true if this TypeSet contains an fAny or /// a floating point value type. bool EEVT::TypeSet::hasFloatingPointTypes() const { - for (unsigned i = 0, e = TypeVec.size(); i != e; ++i) - if (isFloatingPoint(TypeVec[i])) - return true; - return false; + return std::any_of(TypeVec.begin(), TypeVec.end(), isFloatingPoint); +} + +/// hasScalarTypes - Return true if this TypeSet contains a scalar value type. +bool EEVT::TypeSet::hasScalarTypes() const { + return std::any_of(TypeVec.begin(), TypeVec.end(), isScalar); } /// hasVectorTypes - Return true if this TypeSet contains a vAny or a vector /// value type. bool EEVT::TypeSet::hasVectorTypes() const { - for (unsigned i = 0, e = TypeVec.size(); i != e; ++i) - if (isVector(TypeVec[i])) - return true; - return false; + return std::any_of(TypeVec.begin(), TypeVec.end(), isVector); } @@ -146,9 +149,9 @@ std::string EEVT::TypeSet::getName() const { /// MergeInTypeInfo - This merges in type information from the specified /// argument. If 'this' changes, it returns true. If the two types are -/// contradictory (e.g. merge f32 into i32) then this throws an exception. +/// contradictory (e.g. merge f32 into i32) then this flags an error. bool EEVT::TypeSet::MergeInTypeInfo(const EEVT::TypeSet &InVT, TreePattern &TP){ - if (InVT.isCompletelyUnknown() || *this == InVT) + if (InVT.isCompletelyUnknown() || *this == InVT || TP.hasError()) return false; if (isCompletelyUnknown()) { @@ -156,7 +159,7 @@ bool EEVT::TypeSet::MergeInTypeInfo(const EEVT::TypeSet &InVT, TreePattern &TP){ return true; } - assert(TypeVec.size() >= 1 && InVT.TypeVec.size() >= 1 && "No unknowns"); + assert(!TypeVec.empty() && !InVT.TypeVec.empty() && "No unknowns"); // Handle the abstract cases, seeing if we can resolve them better. switch (TypeVec[0]) { @@ -191,8 +194,7 @@ bool EEVT::TypeSet::MergeInTypeInfo(const EEVT::TypeSet &InVT, TreePattern &TP){ // multiple different integer types, replace them with a single iPTR. if ((InVT.TypeVec[0] == MVT::iPTR || InVT.TypeVec[0] == MVT::iPTRAny) && TypeVec.size() != 1) { - TypeVec.resize(1); - TypeVec[0] = InVT.TypeVec[0]; + TypeVec.assign(1, InVT.TypeVec[0]); MadeChange = true; } @@ -201,55 +203,57 @@ bool EEVT::TypeSet::MergeInTypeInfo(const EEVT::TypeSet &InVT, TreePattern &TP){ // If this is a type list and the RHS is a typelist as well, eliminate entries // from this list that aren't in the other one. - bool MadeChange = false; TypeSet InputSet(*this); - for (unsigned i = 0; i != TypeVec.size(); ++i) { - bool InInVT = false; - for (unsigned j = 0, e = InVT.TypeVec.size(); j != e; ++j) - if (TypeVec[i] == InVT.TypeVec[j]) { - InInVT = true; - break; - } + TypeVec.clear(); + std::set_intersection(InputSet.TypeVec.begin(), InputSet.TypeVec.end(), + InVT.TypeVec.begin(), InVT.TypeVec.end(), + std::back_inserter(TypeVec)); - if (InInVT) continue; - TypeVec.erase(TypeVec.begin()+i--); - MadeChange = true; - } + // If the intersection is the same size as the original set then we're done. + if (TypeVec.size() == InputSet.TypeVec.size()) + return false; // If we removed all of our types, we have a type contradiction. if (!TypeVec.empty()) - return MadeChange; + return true; // FIXME: Really want an SMLoc here! TP.error("Type inference contradiction found, merging '" + InVT.getName() + "' into '" + InputSet.getName() + "'"); - return true; // unreachable + return false; } /// EnforceInteger - Remove all non-integer types from this set. bool EEVT::TypeSet::EnforceInteger(TreePattern &TP) { + if (TP.hasError()) + return false; // If we know nothing, then get the full set. if (TypeVec.empty()) return FillWithPossibleTypes(TP, isInteger, "integer"); + if (!hasFloatingPointTypes()) return false; TypeSet InputSet(*this); // Filter out all the fp types. - for (unsigned i = 0; i != TypeVec.size(); ++i) - if (!isInteger(TypeVec[i])) - TypeVec.erase(TypeVec.begin()+i--); + TypeVec.erase(std::remove_if(TypeVec.begin(), TypeVec.end(), + std::not1(std::ptr_fun(isInteger))), + TypeVec.end()); - if (TypeVec.empty()) + if (TypeVec.empty()) { TP.error("Type inference contradiction found, '" + InputSet.getName() + "' needs to be integer"); + return false; + } return true; } /// EnforceFloatingPoint - Remove all integer types from this set. bool EEVT::TypeSet::EnforceFloatingPoint(TreePattern &TP) { + if (TP.hasError()) + return false; // If we know nothing, then get the full set. if (TypeVec.empty()) return FillWithPossibleTypes(TP, isFloatingPoint, "floating point"); @@ -259,19 +263,24 @@ bool EEVT::TypeSet::EnforceFloatingPoint(TreePattern &TP) { TypeSet InputSet(*this); - // Filter out all the fp types. - for (unsigned i = 0; i != TypeVec.size(); ++i) - if (!isFloatingPoint(TypeVec[i])) - TypeVec.erase(TypeVec.begin()+i--); + // Filter out all the integer types. + TypeVec.erase(std::remove_if(TypeVec.begin(), TypeVec.end(), + std::not1(std::ptr_fun(isFloatingPoint))), + TypeVec.end()); - if (TypeVec.empty()) + if (TypeVec.empty()) { TP.error("Type inference contradiction found, '" + InputSet.getName() + "' needs to be floating point"); + return false; + } return true; } /// EnforceScalar - Remove all vector types from this. bool EEVT::TypeSet::EnforceScalar(TreePattern &TP) { + if (TP.hasError()) + return false; + // If we know nothing, then get the full set. if (TypeVec.empty()) return FillWithPossibleTypes(TP, isScalar, "scalar"); @@ -282,18 +291,23 @@ bool EEVT::TypeSet::EnforceScalar(TreePattern &TP) { TypeSet InputSet(*this); // Filter out all the vector types. - for (unsigned i = 0; i != TypeVec.size(); ++i) - if (!isScalar(TypeVec[i])) - TypeVec.erase(TypeVec.begin()+i--); + TypeVec.erase(std::remove_if(TypeVec.begin(), TypeVec.end(), + std::not1(std::ptr_fun(isScalar))), + TypeVec.end()); - if (TypeVec.empty()) + if (TypeVec.empty()) { TP.error("Type inference contradiction found, '" + InputSet.getName() + "' needs to be scalar"); + return false; + } return true; } /// EnforceVector - Remove all vector types from this. bool EEVT::TypeSet::EnforceVector(TreePattern &TP) { + if (TP.hasError()) + return false; + // If we know nothing, then get the full set. if (TypeVec.empty()) return FillWithPossibleTypes(TP, isVector, "vector"); @@ -302,23 +316,27 @@ bool EEVT::TypeSet::EnforceVector(TreePattern &TP) { bool MadeChange = false; // Filter out all the scalar types. - for (unsigned i = 0; i != TypeVec.size(); ++i) - if (!isVector(TypeVec[i])) { - TypeVec.erase(TypeVec.begin()+i--); - MadeChange = true; - } + TypeVec.erase(std::remove_if(TypeVec.begin(), TypeVec.end(), + std::not1(std::ptr_fun(isVector))), + TypeVec.end()); - if (TypeVec.empty()) + if (TypeVec.empty()) { TP.error("Type inference contradiction found, '" + InputSet.getName() + "' needs to be a vector"); + return false; + } return MadeChange; } -/// EnforceSmallerThan - 'this' must be a smaller VT than Other. Update -/// this an other based on this information. +/// EnforceSmallerThan - 'this' must be a smaller VT than Other. For vectors +/// this should be based on the element type. Update this and other based on +/// this information. bool EEVT::TypeSet::EnforceSmallerThan(EEVT::TypeSet &Other, TreePattern &TP) { + if (TP.hasError()) + return false; + // Both operands must be integer or FP, but we don't care which. bool MadeChange = false; @@ -345,165 +363,115 @@ bool EEVT::TypeSet::EnforceSmallerThan(EEVT::TypeSet &Other, TreePattern &TP) { // If one contains vectors but the other doesn't pull vectors out. if (!hasVectorTypes()) MadeChange |= Other.EnforceScalar(TP); - if (!hasVectorTypes()) + else if (!hasScalarTypes()) + MadeChange |= Other.EnforceVector(TP); + if (!Other.hasVectorTypes()) MadeChange |= EnforceScalar(TP); + else if (!Other.hasScalarTypes()) + MadeChange |= EnforceVector(TP); - if (TypeVec.size() == 1 && Other.TypeVec.size() == 1) { - // If we are down to concrete types, 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(!(hasIntegerTypes() && hasFloatingPointTypes()) && - !(Other.hasIntegerTypes() && Other.hasFloatingPointTypes()) && - "SDTCisOpSmallerThanOp does not handle mixed int/fp types!"); - - // Otherwise, if these are both vector types, either this vector - // must have a larger bitsize than the other, or this element type - // must be larger than the other. - EVT Type(TypeVec[0]); - EVT OtherType(Other.TypeVec[0]); - - if (hasVectorTypes() && Other.hasVectorTypes()) { - if (Type.getSizeInBits() >= OtherType.getSizeInBits()) - if (Type.getVectorElementType().getSizeInBits() - >= OtherType.getVectorElementType().getSizeInBits()) - TP.error("Type inference contradiction found, '" + - getName() + "' element type not smaller than '" + - Other.getName() +"'!"); - } - else - // For scalar types, the bitsize of this type must be larger - // than that of the other. - if (Type.getSizeInBits() >= OtherType.getSizeInBits()) - TP.error("Type inference contradiction found, '" + - getName() + "' is not smaller than '" + - Other.getName() +"'!"); + // 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(!(hasIntegerTypes() && hasFloatingPointTypes()) && + !(Other.hasIntegerTypes() && Other.hasFloatingPointTypes()) && + "SDTCisOpSmallerThanOp does not handle mixed int/fp types!"); - } - + if (TP.hasError()) + return false; - // Handle int and fp as disjoint sets. This won't work for patterns - // that have mixed fp/int types but those are likely rare and would - // not have been accepted by this code previously. - - // Okay, find the smallest type from the current set and remove it from the - // largest set. - MVT::SimpleValueType SmallestInt = MVT::LAST_VALUETYPE; - for (unsigned i = 0, e = TypeVec.size(); i != e; ++i) - if (isInteger(TypeVec[i])) { - SmallestInt = TypeVec[i]; - break; - } - for (unsigned i = 1, e = TypeVec.size(); i != e; ++i) - if (isInteger(TypeVec[i]) && TypeVec[i] < SmallestInt) - SmallestInt = TypeVec[i]; - - MVT::SimpleValueType SmallestFP = MVT::LAST_VALUETYPE; - for (unsigned i = 0, e = TypeVec.size(); i != e; ++i) - if (isFloatingPoint(TypeVec[i])) { - SmallestFP = TypeVec[i]; - break; - } - for (unsigned i = 1, e = TypeVec.size(); i != e; ++i) - if (isFloatingPoint(TypeVec[i]) && TypeVec[i] < SmallestFP) - SmallestFP = TypeVec[i]; - - int OtherIntSize = 0; - int OtherFPSize = 0; - for (SmallVector::iterator TVI = - Other.TypeVec.begin(); - TVI != Other.TypeVec.end(); - /* NULL */) { - if (isInteger(*TVI)) { - ++OtherIntSize; - if (*TVI == SmallestInt) { - TVI = Other.TypeVec.erase(TVI); - --OtherIntSize; - MadeChange = true; - continue; - } - } - else if (isFloatingPoint(*TVI)) { - ++OtherFPSize; - if (*TVI == SmallestFP) { - TVI = Other.TypeVec.erase(TVI); - --OtherFPSize; - MadeChange = true; - continue; - } + // Okay, find the smallest type from current set and remove anything the + // same or smaller from the other set. We need to ensure that the scalar + // type size is smaller than the scalar size of the smallest type. For + // vectors, we also need to make sure that the total size is no larger than + // the size of the smallest type. + TypeSet InputSet(Other); + MVT Smallest = TypeVec[0]; + for (unsigned i = 0; i != Other.TypeVec.size(); ++i) { + MVT OtherVT = Other.TypeVec[i]; + // Don't compare vector and non-vector types. + if (OtherVT.isVector() != Smallest.isVector()) + continue; + // The getSizeInBits() check here is only needed for vectors, but is + // a subset of the scalar check for scalars so no need to qualify. + if (OtherVT.getScalarSizeInBits() <= Smallest.getScalarSizeInBits() || + OtherVT.getSizeInBits() < Smallest.getSizeInBits()) { + Other.TypeVec.erase(Other.TypeVec.begin()+i--); + MadeChange = true; } - ++TVI; } - // If this is the only type in the large set, the constraint can never be - // satisfied. - if ((Other.hasIntegerTypes() && OtherIntSize == 0) - || (Other.hasFloatingPointTypes() && OtherFPSize == 0)) - TP.error("Type inference contradiction found, '" + - Other.getName() + "' has nothing larger than '" + getName() +"'!"); - - // Okay, find the largest type in the Other set and remove it from the - // current set. - MVT::SimpleValueType LargestInt = MVT::Other; - for (unsigned i = 0, e = Other.TypeVec.size(); i != e; ++i) - if (isInteger(Other.TypeVec[i])) { - LargestInt = Other.TypeVec[i]; - break; - } - for (unsigned i = 1, e = Other.TypeVec.size(); i != e; ++i) - if (isInteger(Other.TypeVec[i]) && Other.TypeVec[i] > LargestInt) - LargestInt = Other.TypeVec[i]; - - MVT::SimpleValueType LargestFP = MVT::Other; - for (unsigned i = 0, e = Other.TypeVec.size(); i != e; ++i) - if (isFloatingPoint(Other.TypeVec[i])) { - LargestFP = Other.TypeVec[i]; - break; - } - for (unsigned i = 1, e = Other.TypeVec.size(); i != e; ++i) - if (isFloatingPoint(Other.TypeVec[i]) && Other.TypeVec[i] > LargestFP) - LargestFP = Other.TypeVec[i]; - - int IntSize = 0; - int FPSize = 0; - for (SmallVector::iterator TVI = - TypeVec.begin(); - TVI != TypeVec.end(); - /* NULL */) { - if (isInteger(*TVI)) { - ++IntSize; - if (*TVI == LargestInt) { - TVI = TypeVec.erase(TVI); - --IntSize; - MadeChange = true; - continue; - } + if (Other.TypeVec.empty()) { + TP.error("Type inference contradiction found, '" + InputSet.getName() + + "' has nothing larger than '" + getName() +"'!"); + return false; + } + + // Okay, find the largest type from the other set and remove anything the + // same or smaller from the current set. We need to ensure that the scalar + // type size is larger than the scalar size of the largest type. For + // vectors, we also need to make sure that the total size is no smaller than + // the size of the largest type. + InputSet = TypeSet(*this); + MVT Largest = Other.TypeVec[Other.TypeVec.size()-1]; + for (unsigned i = 0; i != TypeVec.size(); ++i) { + MVT OtherVT = TypeVec[i]; + // Don't compare vector and non-vector types. + if (OtherVT.isVector() != Largest.isVector()) + continue; + // The getSizeInBits() check here is only needed for vectors, but is + // a subset of the scalar check for scalars so no need to qualify. + if (OtherVT.getScalarSizeInBits() >= Largest.getScalarSizeInBits() || + OtherVT.getSizeInBits() > Largest.getSizeInBits()) { + TypeVec.erase(TypeVec.begin()+i--); + MadeChange = true; } - else if (isFloatingPoint(*TVI)) { - ++FPSize; - if (*TVI == LargestFP) { - TVI = TypeVec.erase(TVI); - --FPSize; - MadeChange = true; - continue; - } + } + + if (TypeVec.empty()) { + TP.error("Type inference contradiction found, '" + InputSet.getName() + + "' has nothing smaller than '" + Other.getName() +"'!"); + return false; + } + + return MadeChange; +} + +/// EnforceVectorEltTypeIs - 'this' is now constrained to be a vector type +/// whose element is specified by VTOperand. +bool EEVT::TypeSet::EnforceVectorEltTypeIs(MVT::SimpleValueType VT, + TreePattern &TP) { + bool MadeChange = false; + + MadeChange |= EnforceVector(TP); + + TypeSet InputSet(*this); + + // Filter out all the types which don't have the right element type. + for (unsigned i = 0; i != TypeVec.size(); ++i) { + assert(isVector(TypeVec[i]) && "EnforceVector didn't work"); + if (MVT(TypeVec[i]).getVectorElementType().SimpleTy != VT) { + TypeVec.erase(TypeVec.begin()+i--); + MadeChange = true; } - ++TVI; } - // If this is the only type in the small set, the constraint can never be - // satisfied. - if ((hasIntegerTypes() && IntSize == 0) - || (hasFloatingPointTypes() && FPSize == 0)) - TP.error("Type inference contradiction found, '" + - getName() + "' has nothing smaller than '" + Other.getName()+"'!"); + if (TypeVec.empty()) { // FIXME: Really want an SMLoc here! + TP.error("Type inference contradiction found, forcing '" + + InputSet.getName() + "' to have a vector element"); + return false; + } return MadeChange; } -/// EnforceVectorEltTypeIs - 'this' is now constrainted to be a vector type +/// EnforceVectorEltTypeIs - 'this' is now constrained to be a vector type /// whose element is specified by VTOperand. bool EEVT::TypeSet::EnforceVectorEltTypeIs(EEVT::TypeSet &VTOperand, TreePattern &TP) { + if (TP.hasError()) + return false; + // "This" must be a vector and "VTOperand" must be a scalar. bool MadeChange = false; MadeChange |= EnforceVector(TP); @@ -511,10 +479,10 @@ bool EEVT::TypeSet::EnforceVectorEltTypeIs(EEVT::TypeSet &VTOperand, // If we know the vector type, it forces the scalar to agree. if (isConcrete()) { - EVT IVT = getConcrete(); + MVT IVT = getConcrete(); IVT = IVT.getVectorElementType(); return MadeChange | - VTOperand.MergeInTypeInfo(IVT.getSimpleVT().SimpleTy, TP); + VTOperand.MergeInTypeInfo(IVT.SimpleTy, TP); } // If the scalar type is known, filter out vector types whose element types @@ -529,64 +497,168 @@ bool EEVT::TypeSet::EnforceVectorEltTypeIs(EEVT::TypeSet &VTOperand, // Filter out all the types which don't have the right element type. for (unsigned i = 0; i != TypeVec.size(); ++i) { assert(isVector(TypeVec[i]) && "EnforceVector didn't work"); - if (EVT(TypeVec[i]).getVectorElementType().getSimpleVT().SimpleTy != VT) { + if (MVT(TypeVec[i]).getVectorElementType().SimpleTy != VT) { TypeVec.erase(TypeVec.begin()+i--); MadeChange = true; } } - if (TypeVec.empty()) // FIXME: Really want an SMLoc here! + if (TypeVec.empty()) { // FIXME: Really want an SMLoc here! TP.error("Type inference contradiction found, forcing '" + InputSet.getName() + "' to have a vector element"); + return false; + } return MadeChange; } -/// EnforceVectorSubVectorTypeIs - 'this' is now constrainted to be a +/// EnforceVectorSubVectorTypeIs - 'this' is now constrained to be a /// vector type specified by VTOperand. bool EEVT::TypeSet::EnforceVectorSubVectorTypeIs(EEVT::TypeSet &VTOperand, TreePattern &TP) { + if (TP.hasError()) + return false; + // "This" must be a vector and "VTOperand" must be a vector. bool MadeChange = false; MadeChange |= EnforceVector(TP); MadeChange |= VTOperand.EnforceVector(TP); - // "This" must be larger than "VTOperand." - MadeChange |= VTOperand.EnforceSmallerThan(*this, TP); + // If one side is known to be integer or known to be FP but the other side has + // no information, get at least the type integrality info in there. + if (!hasFloatingPointTypes()) + MadeChange |= VTOperand.EnforceInteger(TP); + else if (!hasIntegerTypes()) + MadeChange |= VTOperand.EnforceFloatingPoint(TP); + if (!VTOperand.hasFloatingPointTypes()) + MadeChange |= EnforceInteger(TP); + else if (!VTOperand.hasIntegerTypes()) + MadeChange |= EnforceFloatingPoint(TP); + + assert(!isCompletelyUnknown() && !VTOperand.isCompletelyUnknown() && + "Should have a type list now"); // If we know the vector type, it forces the scalar types to agree. + // Also force one vector to have more elements than the other. if (isConcrete()) { - EVT IVT = getConcrete(); + MVT IVT = getConcrete(); + unsigned NumElems = IVT.getVectorNumElements(); IVT = IVT.getVectorElementType(); - EEVT::TypeSet EltTypeSet(IVT.getSimpleVT().SimpleTy, TP); + EEVT::TypeSet EltTypeSet(IVT.SimpleTy, TP); MadeChange |= VTOperand.EnforceVectorEltTypeIs(EltTypeSet, TP); + + // Only keep types that have less elements than VTOperand. + TypeSet InputSet(VTOperand); + + for (unsigned i = 0; i != VTOperand.TypeVec.size(); ++i) { + assert(isVector(VTOperand.TypeVec[i]) && "EnforceVector didn't work"); + if (MVT(VTOperand.TypeVec[i]).getVectorNumElements() >= NumElems) { + VTOperand.TypeVec.erase(VTOperand.TypeVec.begin()+i--); + MadeChange = true; + } + } + if (VTOperand.TypeVec.empty()) { // FIXME: Really want an SMLoc here! + TP.error("Type inference contradiction found, forcing '" + + InputSet.getName() + "' to have less vector elements than '" + + getName() + "'"); + return false; + } } else if (VTOperand.isConcrete()) { - EVT IVT = VTOperand.getConcrete(); + MVT IVT = VTOperand.getConcrete(); + unsigned NumElems = IVT.getVectorNumElements(); IVT = IVT.getVectorElementType(); - EEVT::TypeSet EltTypeSet(IVT.getSimpleVT().SimpleTy, TP); + EEVT::TypeSet EltTypeSet(IVT.SimpleTy, TP); MadeChange |= EnforceVectorEltTypeIs(EltTypeSet, TP); + + // Only keep types that have more elements than 'this'. + TypeSet InputSet(*this); + + for (unsigned i = 0; i != TypeVec.size(); ++i) { + assert(isVector(TypeVec[i]) && "EnforceVector didn't work"); + if (MVT(TypeVec[i]).getVectorNumElements() <= NumElems) { + TypeVec.erase(TypeVec.begin()+i--); + MadeChange = true; + } + } + if (TypeVec.empty()) { // FIXME: Really want an SMLoc here! + TP.error("Type inference contradiction found, forcing '" + + InputSet.getName() + "' to have more vector elements than '" + + VTOperand.getName() + "'"); + return false; + } } return MadeChange; } -//===----------------------------------------------------------------------===// -// Helpers for working with extended types. +/// EnforceVectorSameNumElts - 'this' is now constrained to +/// be a vector with same num elements as VTOperand. +bool EEVT::TypeSet::EnforceVectorSameNumElts(EEVT::TypeSet &VTOperand, + TreePattern &TP) { + if (TP.hasError()) + return false; + + // "This" must be a vector and "VTOperand" must be a vector. + bool MadeChange = false; + MadeChange |= EnforceVector(TP); + MadeChange |= VTOperand.EnforceVector(TP); + + // If we know one of the vector types, it forces the other type to agree. + if (isConcrete()) { + MVT IVT = getConcrete(); + unsigned NumElems = IVT.getVectorNumElements(); + + // Only keep types that have same elements as VTOperand. + TypeSet InputSet(VTOperand); -bool RecordPtrCmp::operator()(const Record *LHS, const Record *RHS) const { - return LHS->getID() < RHS->getID(); + for (unsigned i = 0; i != VTOperand.TypeVec.size(); ++i) { + assert(isVector(VTOperand.TypeVec[i]) && "EnforceVector didn't work"); + if (MVT(VTOperand.TypeVec[i]).getVectorNumElements() != NumElems) { + VTOperand.TypeVec.erase(VTOperand.TypeVec.begin()+i--); + MadeChange = true; + } + } + if (VTOperand.TypeVec.empty()) { // FIXME: Really want an SMLoc here! + TP.error("Type inference contradiction found, forcing '" + + InputSet.getName() + "' to have same number elements as '" + + getName() + "'"); + return false; + } + } else if (VTOperand.isConcrete()) { + MVT IVT = VTOperand.getConcrete(); + unsigned NumElems = IVT.getVectorNumElements(); + + // Only keep types that have same elements as 'this'. + TypeSet InputSet(*this); + + for (unsigned i = 0; i != TypeVec.size(); ++i) { + assert(isVector(TypeVec[i]) && "EnforceVector didn't work"); + if (MVT(TypeVec[i]).getVectorNumElements() != NumElems) { + TypeVec.erase(TypeVec.begin()+i--); + MadeChange = true; + } + } + if (TypeVec.empty()) { // FIXME: Really want an SMLoc here! + TP.error("Type inference contradiction found, forcing '" + + InputSet.getName() + "' to have same number elements than '" + + VTOperand.getName() + "'"); + return false; + } + } + + return MadeChange; } +//===----------------------------------------------------------------------===// +// Helpers for working with extended types. + /// Dependent variable map for CodeGenDAGPattern variant generation typedef std::map DepVarMap; -/// Const iterator shorthand for DepVarMap -typedef DepVarMap::const_iterator DepVarMap_citer; - static void FindDepVarsOf(TreePatternNode *N, DepVarMap &DepMap) { if (N->isLeaf()) { - if (dynamic_cast(N->getLeafValue()) != NULL) + if (isa(N->getLeafValue())) DepMap[N->getName()]++; } else { for (size_t i = 0, e = N->getNumChildren(); i != e; ++i) @@ -598,9 +670,9 @@ static void FindDepVarsOf(TreePatternNode *N, DepVarMap &DepMap) { static void FindDepVars(TreePatternNode *N, MultipleUseVarSet &DepVars) { DepVarMap depcounts; FindDepVarsOf(N, depcounts); - for (DepVarMap_citer i = depcounts.begin(); i != depcounts.end(); ++i) { - if (i->second > 1) // std::pair - DepVars.insert(i->first); + for (const std::pair &Pair : depcounts) { + if (Pair.second > 1) + DepVars.insert(Pair.first); } } @@ -611,9 +683,8 @@ static void DumpDepVars(MultipleUseVarSet &DepVars) { DEBUG(errs() << ""); } else { DEBUG(errs() << "[ "); - for (MultipleUseVarSet::const_iterator i = DepVars.begin(), - e = DepVars.end(); i != e; ++i) { - DEBUG(errs() << (*i) << " "); + for (const std::string &DepVar : DepVars) { + DEBUG(errs() << DepVar << " "); } DEBUG(errs() << "]"); } @@ -677,7 +748,7 @@ std::string TreePredicateFn::getCodeToRunOnSDNode() const { if (ClassName == "SDNode") Result = " SDNode *N = Node;\n"; else - Result = " " + ClassName + "*N = cast<" + ClassName + ">(Node);\n"; + Result = " auto *N = cast<" + ClassName + ">(Node);\n"; return Result + getPredCode(); } @@ -695,7 +766,7 @@ static unsigned getPatternSize(const TreePatternNode *P, 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(P->getLeafValue())) + if (P->isLeaf() && isa(P->getLeafValue())) Size += 2; // FIXME: This is a hack to statically increase the priority of patterns @@ -704,9 +775,13 @@ static unsigned getPatternSize(const TreePatternNode *P, // specified. To get best possible pattern match we'll need to dynamically // calculate the complexity of all patterns a dag can potentially map to. const ComplexPattern *AM = P->getComplexPatternInfo(CGP); - if (AM) + if (AM) { Size += AM->getNumOperands() * 3; + // We don't want to count any children twice, so return early. + return Size; + } + // If this node has some predicate function that must match, it adds to the // complexity of this node. if (!P->getPredicateFns().empty()) @@ -719,7 +794,7 @@ static unsigned getPatternSize(const TreePatternNode *P, Child->getType(0) != MVT::Other) Size += getPatternSize(Child, CGP); else if (Child->isLeaf()) { - if (dynamic_cast(Child->getLeafValue())) + if (isa(Child->getLeafValue())) Size += 5; // Matches a ConstantSDNode (+3) and a specific value (+2). else if (Child->getComplexPatternInfo(CGP)) Size += getPatternSize(Child, CGP); @@ -733,7 +808,7 @@ static unsigned getPatternSize(const TreePatternNode *P, /// Compute the complexity metric for the input pattern. This roughly /// corresponds to the number of nodes that are covered. -unsigned PatternToMatch:: +int PatternToMatch:: getPatternComplexity(const CodeGenDAGPatterns &CGP) const { return getPatternSize(getSrcPattern(), CGP) + getAddedComplexity(); } @@ -744,8 +819,8 @@ getPatternComplexity(const CodeGenDAGPatterns &CGP) const { /// std::string PatternToMatch::getPredicateCheck() const { std::string PredicateCheck; - for (unsigned i = 0, e = Predicates->getSize(); i != e; ++i) { - if (DefInit *Pred = dynamic_cast(Predicates->getElement(i))) { + for (Init *I : Predicates->getValues()) { + if (DefInit *Pred = dyn_cast(I)) { Record *Def = Pred->getDef(); if (!Def->isSubClassOf("Predicate")) { #ifndef NDEBUG @@ -773,7 +848,7 @@ SDTypeConstraint::SDTypeConstraint(Record *R) { ConstraintType = SDTCisVT; x.SDTCisVT_Info.VT = getValueType(R->getValueAsDef("VT")); if (x.SDTCisVT_Info.VT == MVT::isVoid) - throw TGError(R->getLoc(), "Cannot use 'Void' as type to SDTCisVT"); + PrintFatalError(R->getLoc(), "Cannot use 'Void' as type to SDTCisVT"); } else if (R->isSubClassOf("SDTCisPtrTy")) { ConstraintType = SDTCisPtrTy; @@ -801,9 +876,21 @@ SDTypeConstraint::SDTypeConstraint(Record *R) { ConstraintType = SDTCisSubVecOfVec; x.SDTCisSubVecOfVec_Info.OtherOperandNum = R->getValueAsInt("OtherOpNum"); + } else if (R->isSubClassOf("SDTCVecEltisVT")) { + ConstraintType = SDTCVecEltisVT; + x.SDTCVecEltisVT_Info.VT = getValueType(R->getValueAsDef("VT")); + if (MVT(x.SDTCVecEltisVT_Info.VT).isVector()) + PrintFatalError(R->getLoc(), "Cannot use vector type as SDTCVecEltisVT"); + if (!MVT(x.SDTCVecEltisVT_Info.VT).isInteger() && + !MVT(x.SDTCVecEltisVT_Info.VT).isFloatingPoint()) + PrintFatalError(R->getLoc(), "Must use integer or floating point type " + "as SDTCVecEltisVT"); + } else if (R->isSubClassOf("SDTCisSameNumEltsAs")) { + ConstraintType = SDTCisSameNumEltsAs; + x.SDTCisSameNumEltsAs_Info.OtherOperandNum = + R->getValueAsInt("OtherOperandNum"); } else { - errs() << "Unrecognized SDTypeConstraint '" << R->getName() << "'!\n"; - exit(1); + PrintFatalError("Unrecognized SDTypeConstraint '" + R->getName() + "'!\n"); } } @@ -821,11 +908,12 @@ static TreePatternNode *getOperandNum(unsigned OpNo, TreePatternNode *N, OpNo -= NumResults; if (OpNo >= N->getNumChildren()) { - errs() << "Invalid operand number in type constraint " + std::string S; + raw_string_ostream OS(S); + OS << "Invalid operand number in type constraint " << (OpNo+NumResults) << " "; - N->dump(); - errs() << '\n'; - exit(1); + N->print(OS); + PrintFatalError(OS.str()); } return N->getChild(OpNo); @@ -833,11 +921,13 @@ static TreePatternNode *getOperandNum(unsigned OpNo, TreePatternNode *N, /// ApplyTypeConstraint - Given a node in a pattern, apply this type /// constraint to the nodes operands. This returns true if it makes a -/// change, false otherwise. If a type contradiction is found, throw an -/// exception. +/// change, false otherwise. If a type contradiction is found, flag an error. bool SDTypeConstraint::ApplyTypeConstraint(TreePatternNode *N, const SDNodeInfo &NodeInfo, TreePattern &TP) const { + if (TP.hasError()) + return false; + unsigned ResNo = 0; // The result number being referenced. TreePatternNode *NodeToApply = getOperandNum(OperandNo, N, NodeInfo, ResNo); @@ -861,17 +951,19 @@ bool SDTypeConstraint::ApplyTypeConstraint(TreePatternNode *N, unsigned OResNo = 0; TreePatternNode *OtherNode = getOperandNum(x.SDTCisSameAs_Info.OtherOperandNum, N, NodeInfo, OResNo); - return NodeToApply->UpdateNodeType(OResNo, OtherNode->getExtType(ResNo),TP)| - OtherNode->UpdateNodeType(ResNo,NodeToApply->getExtType(OResNo),TP); + return NodeToApply->UpdateNodeType(ResNo, OtherNode->getExtType(OResNo),TP)| + OtherNode->UpdateNodeType(OResNo,NodeToApply->getExtType(ResNo),TP); } case SDTCisVTSmallerThanOp: { // The NodeToApply must be a leaf node that is a VT. OtherOperandNum must // have an integer type that is smaller than the VT. if (!NodeToApply->isLeaf() || - !dynamic_cast(NodeToApply->getLeafValue()) || + !isa(NodeToApply->getLeafValue()) || !static_cast(NodeToApply->getLeafValue())->getDef() - ->isSubClassOf("ValueType")) + ->isSubClassOf("ValueType")) { TP.error(N->getOperator()->getName() + " expects a VT operand!"); + return false; + } MVT::SimpleValueType VT = getValueType(static_cast(NodeToApply->getLeafValue())->getDef()); @@ -914,10 +1006,56 @@ bool SDTypeConstraint::ApplyTypeConstraint(TreePatternNode *N, return BigVecOperand->getExtType(VResNo). EnforceVectorSubVectorTypeIs(NodeToApply->getExtType(ResNo), TP); } + case SDTCVecEltisVT: { + return NodeToApply->getExtType(ResNo). + EnforceVectorEltTypeIs(x.SDTCVecEltisVT_Info.VT, TP); + } + case SDTCisSameNumEltsAs: { + unsigned OResNo = 0; + TreePatternNode *OtherNode = + getOperandNum(x.SDTCisSameNumEltsAs_Info.OtherOperandNum, + N, NodeInfo, OResNo); + return OtherNode->getExtType(OResNo). + EnforceVectorSameNumElts(NodeToApply->getExtType(ResNo), TP); + } } llvm_unreachable("Invalid ConstraintType!"); } +// Update the node type to match an instruction operand or result as specified +// in the ins or outs lists on the instruction definition. Return true if the +// type was actually changed. +bool TreePatternNode::UpdateNodeTypeFromInst(unsigned ResNo, + Record *Operand, + TreePattern &TP) { + // The 'unknown' operand indicates that types should be inferred from the + // context. + if (Operand->isSubClassOf("unknown_class")) + return false; + + // The Operand class specifies a type directly. + if (Operand->isSubClassOf("Operand")) + return UpdateNodeType(ResNo, getValueType(Operand->getValueAsDef("Type")), + TP); + + // PointerLikeRegClass has a type that is determined at runtime. + if (Operand->isSubClassOf("PointerLikeRegClass")) + return UpdateNodeType(ResNo, MVT::iPTR, TP); + + // Both RegisterClass and RegisterOperand operands derive their types from a + // register class def. + Record *RC = nullptr; + if (Operand->isSubClassOf("RegisterClass")) + RC = Operand; + else if (Operand->isSubClassOf("RegisterOperand")) + RC = Operand->getValueAsDef("RegClass"); + + assert(RC && "Unknown operand type"); + CodeGenTarget &Tgt = TP.getDAGPatterns().getTargetInfo(); + return UpdateNodeType(ResNo, Tgt.getRegisterClass(RC).getValueTypes(), TP); +} + + //===----------------------------------------------------------------------===// // SDNodeInfo implementation // @@ -930,34 +1068,33 @@ SDNodeInfo::SDNodeInfo(Record *R) : Def(R) { // Parse the properties. Properties = 0; - std::vector PropList = R->getValueAsListOfDefs("Properties"); - for (unsigned i = 0, e = PropList.size(); i != e; ++i) { - if (PropList[i]->getName() == "SDNPCommutative") { + for (Record *Property : R->getValueAsListOfDefs("Properties")) { + if (Property->getName() == "SDNPCommutative") { Properties |= 1 << SDNPCommutative; - } else if (PropList[i]->getName() == "SDNPAssociative") { + } else if (Property->getName() == "SDNPAssociative") { Properties |= 1 << SDNPAssociative; - } else if (PropList[i]->getName() == "SDNPHasChain") { + } else if (Property->getName() == "SDNPHasChain") { Properties |= 1 << SDNPHasChain; - } else if (PropList[i]->getName() == "SDNPOutGlue") { + } else if (Property->getName() == "SDNPOutGlue") { Properties |= 1 << SDNPOutGlue; - } else if (PropList[i]->getName() == "SDNPInGlue") { + } else if (Property->getName() == "SDNPInGlue") { Properties |= 1 << SDNPInGlue; - } else if (PropList[i]->getName() == "SDNPOptInGlue") { + } else if (Property->getName() == "SDNPOptInGlue") { Properties |= 1 << SDNPOptInGlue; - } else if (PropList[i]->getName() == "SDNPMayStore") { + } else if (Property->getName() == "SDNPMayStore") { Properties |= 1 << SDNPMayStore; - } else if (PropList[i]->getName() == "SDNPMayLoad") { + } else if (Property->getName() == "SDNPMayLoad") { Properties |= 1 << SDNPMayLoad; - } else if (PropList[i]->getName() == "SDNPSideEffect") { + } else if (Property->getName() == "SDNPSideEffect") { Properties |= 1 << SDNPSideEffect; - } else if (PropList[i]->getName() == "SDNPMemOperand") { + } else if (Property->getName() == "SDNPMemOperand") { Properties |= 1 << SDNPMemOperand; - } else if (PropList[i]->getName() == "SDNPVariadic") { + } else if (Property->getName() == "SDNPVariadic") { Properties |= 1 << SDNPVariadic; } else { - errs() << "Unknown SD Node property '" << PropList[i]->getName() - << "' on node '" << R->getName() << "'!\n"; - exit(1); + PrintFatalError("Unknown SD Node property '" + + Property->getName() + "' on node '" + + R->getName() + "'!"); } } @@ -977,15 +1114,15 @@ MVT::SimpleValueType SDNodeInfo::getKnownType(unsigned ResNo) const { "We only work with nodes with zero or one result so far!"); assert(ResNo == 0 && "Only handles single result nodes so far"); - for (unsigned i = 0, e = TypeConstraints.size(); i != e; ++i) { + for (const SDTypeConstraint &Constraint : TypeConstraints) { // Make sure that this applies to the correct node result. - if (TypeConstraints[i].OperandNo >= NumResults) // FIXME: need value # + if (Constraint.OperandNo >= NumResults) // FIXME: need value # continue; - switch (TypeConstraints[i].ConstraintType) { + switch (Constraint.ConstraintType) { default: break; case SDTypeConstraint::SDTCisVT: - return TypeConstraints[i].x.SDTCisVT_Info.VT; + return Constraint.x.SDTCisVT_Info.VT; case SDTypeConstraint::SDTCisPtrTy: return MVT::iPTR; } @@ -1024,9 +1161,10 @@ static unsigned GetNumNodeResults(Record *Operator, CodeGenDAGPatterns &CDP) { // Get the result tree. DagInit *Tree = Operator->getValueAsDag("Fragment"); - Record *Op = 0; - if (Tree && dynamic_cast(Tree->getOperator())) - Op = dynamic_cast(Tree->getOperator())->getDef(); + Record *Op = nullptr; + if (Tree) + if (DefInit *DI = dyn_cast(Tree->getOperator())) + Op = DI->getDef(); assert(Op && "Invalid Fragment"); return GetNumNodeResults(Op, CDP); } @@ -1034,8 +1172,16 @@ static unsigned GetNumNodeResults(Record *Operator, CodeGenDAGPatterns &CDP) { if (Operator->isSubClassOf("Instruction")) { CodeGenInstruction &InstInfo = CDP.getTargetInfo().getInstruction(Operator); - // FIXME: Should allow access to all the results here. - unsigned NumDefsToAdd = InstInfo.Operands.NumDefs ? 1 : 0; + unsigned NumDefsToAdd = InstInfo.Operands.NumDefs; + + // Subtract any defaulted outputs. + for (unsigned i = 0; i != InstInfo.Operands.NumDefs; ++i) { + Record *OperandNode = InstInfo.Operands[i].Rec; + + if (OperandNode->isSubClassOf("OperandWithDefaultOps") && + !CDP.getDefaultOperand(OperandNode).DefaultOps.empty()) + --NumDefsToAdd; + } // Add on one implicit def if it has a resolvable type. if (InstInfo.HasOneImplicitDefWithKnownVT(CDP.getTargetInfo()) !=MVT::Other) @@ -1046,9 +1192,14 @@ static unsigned GetNumNodeResults(Record *Operator, CodeGenDAGPatterns &CDP) { if (Operator->isSubClassOf("SDNodeXForm")) return 1; // FIXME: Generalize SDNodeXForm + if (Operator->isSubClassOf("ValueType")) + return 1; // A type-cast of one result. + + if (Operator->isSubClassOf("ComplexPattern")) + return 1; + Operator->dump(); - errs() << "Unhandled node in GetNumNodeResults\n"; - exit(1); + PrintFatalError("Unhandled node in GetNumNodeResults"); } void TreePatternNode::print(raw_ostream &OS) const { @@ -1072,8 +1223,8 @@ void TreePatternNode::print(raw_ostream &OS) const { OS << ")"; } - for (unsigned i = 0, e = PredicateFns.size(); i != e; ++i) - OS << "<>"; + for (const TreePredicateFn &Pred : PredicateFns) + OS << "<>"; if (TransformFn) OS << "<getName() << ">>"; if (!getName().empty()) @@ -1100,8 +1251,8 @@ bool TreePatternNode::isIsomorphicTo(const TreePatternNode *N, return false; if (isLeaf()) { - if (DefInit *DI = dynamic_cast(getLeafValue())) { - if (DefInit *NDI = dynamic_cast(N->getLeafValue())) { + if (DefInit *DI = dyn_cast(getLeafValue())) { + if (DefInit *NDI = dyn_cast(N->getLeafValue())) { return ((DI->getDef() == NDI->getDef()) && (DepVars.find(getName()) == DepVars.end() || getName() == N->getName())); @@ -1140,8 +1291,8 @@ TreePatternNode *TreePatternNode::clone() const { /// RemoveAllTypes - Recursively strip all the types of this tree. void TreePatternNode::RemoveAllTypes() { - for (unsigned i = 0, e = Types.size(); i != e; ++i) - Types[i] = EEVT::TypeSet(); // Reset to unknown type. + // Reset to unknown type. + std::fill(Types.begin(), Types.end(), EEVT::TypeSet()); if (isLeaf()) return; for (unsigned i = 0, e = getNumChildren(); i != e; ++i) getChild(i)->RemoveAllTypes(); @@ -1158,8 +1309,10 @@ SubstituteFormalArguments(std::map &ArgMap) { TreePatternNode *Child = getChild(i); if (Child->isLeaf()) { Init *Val = Child->getLeafValue(); - if (dynamic_cast(Val) && - static_cast(Val)->getDef()->getName() == "node") { + // Note that, when substituting into an output pattern, Val might be an + // UnsetInit. + if (isa(Val) || (isa(Val) && + cast(Val)->getDef()->getName() == "node")) { // We found a use of a formal argument, replace it with its value. TreePatternNode *NewChild = ArgMap[Child->getName()]; assert(NewChild && "Couldn't find formal argument!"); @@ -1179,7 +1332,11 @@ SubstituteFormalArguments(std::map &ArgMap) { /// fragments, inline them into place, giving us a pattern without any /// PatFrag references. TreePatternNode *TreePatternNode::InlinePatternFragments(TreePattern &TP) { - if (isLeaf()) return this; // nothing to do. + if (TP.hasError()) + return nullptr; + + if (isLeaf()) + return this; // nothing to do. Record *Op = getOperator(); if (!Op->isSubClassOf("PatFrag")) { @@ -1202,9 +1359,11 @@ TreePatternNode *TreePatternNode::InlinePatternFragments(TreePattern &TP) { TreePattern *Frag = TP.getDAGPatterns().getPatternFragment(Op); // Verify that we are passing the right number of operands. - if (Frag->getNumArgs() != Children.size()) + if (Frag->getNumArgs() != Children.size()) { TP.error("'" + Op->getName() + "' fragment requires " + utostr(Frag->getNumArgs()) + " operands!"); + return nullptr; + } TreePatternNode *FragTree = Frag->getOnlyTree()->clone(); @@ -1227,8 +1386,8 @@ TreePatternNode *TreePatternNode::InlinePatternFragments(TreePattern &TP) { FragTree->UpdateNodeType(i, getExtType(i), TP); // Transfer in the old predicates. - for (unsigned i = 0, e = getPredicateFns().size(); i != e; ++i) - FragTree->addPredicateFn(getPredicateFns()[i]); + for (const TreePredicateFn &Pred : getPredicateFns()) + FragTree->addPredicateFn(Pred); // Get a new copy of this fragment to stitch into here. //delete this; // FIXME: implement refcounting! @@ -1242,8 +1401,18 @@ TreePatternNode *TreePatternNode::InlinePatternFragments(TreePattern &TP) { /// type which should be applied to it. This will infer the type of register /// references from the register file information, for example. /// +/// When Unnamed is set, return the type of a DAG operand with no name, such as +/// the F8RC register class argument in: +/// +/// (COPY_TO_REGCLASS GPR:$src, F8RC) +/// +/// When Unnamed is false, return the type of a named DAG operand such as the +/// GPR:$src operand above. +/// static EEVT::TypeSet getImplicitType(Record *R, unsigned ResNo, - bool NotRegisters, TreePattern &TP) { + bool NotRegisters, + bool Unnamed, + TreePattern &TP) { // Check to see if this is a register operand. if (R->isSubClassOf("RegisterOperand")) { assert(ResNo == 0 && "Regoperand ref only has one result!"); @@ -1257,6 +1426,13 @@ static EEVT::TypeSet getImplicitType(Record *R, unsigned ResNo, // Check to see if this is a register or a register class. if (R->isSubClassOf("RegisterClass")) { assert(ResNo == 0 && "Regclass ref only has one result!"); + // An unnamed register class represents itself as an i32 immediate, for + // example on a COPY_TO_REGCLASS instruction. + if (Unnamed) + return EEVT::TypeSet(MVT::i32, TP); + + // In a named operand, the register class provides the possible set of + // types. if (NotRegisters) return EEVT::TypeSet(); // Unknown. const CodeGenTarget &T = TP.getDAGPatterns().getTargetInfo(); @@ -1279,12 +1455,30 @@ static EEVT::TypeSet getImplicitType(Record *R, unsigned ResNo, if (R->isSubClassOf("SubRegIndex")) { assert(ResNo == 0 && "SubRegisterIndices only produce one result!"); - return EEVT::TypeSet(); + return EEVT::TypeSet(MVT::i32, TP); } - if (R->isSubClassOf("ValueType") || R->isSubClassOf("CondCode")) { + if (R->isSubClassOf("ValueType")) { assert(ResNo == 0 && "This node only has one result!"); - // Using a VTSDNode or CondCodeSDNode. + // An unnamed VTSDNode represents itself as an MVT::Other immediate. + // + // (sext_inreg GPR:$src, i16) + // ~~~ + if (Unnamed) + return EEVT::TypeSet(MVT::Other, TP); + // With a name, the ValueType simply provides the type of the named + // variable. + // + // (sext_inreg i32:$src, i16) + // ~~~~~~~~ + if (NotRegisters) + return EEVT::TypeSet(); // Unknown. + return EEVT::TypeSet(getValueType(R), TP); + } + + if (R->isSubClassOf("CondCode")) { + assert(ResNo == 0 && "This node only has one result!"); + // Using a CondCodeSDNode. return EEVT::TypeSet(MVT::Other, TP); } @@ -1306,6 +1500,9 @@ static EEVT::TypeSet getImplicitType(Record *R, unsigned ResNo, return EEVT::TypeSet(); // Unknown. } + if (R->isSubClassOf("Operand")) + return EEVT::TypeSet(getValueType(R->getValueAsDef("Type"))); + TP.error("Unknown node flavor used in pattern: " + R->getName()); return EEVT::TypeSet(MVT::Other, TP); } @@ -1318,10 +1515,9 @@ getIntrinsicInfo(const CodeGenDAGPatterns &CDP) const { if (getOperator() != CDP.get_intrinsic_void_sdnode() && getOperator() != CDP.get_intrinsic_w_chain_sdnode() && getOperator() != CDP.get_intrinsic_wo_chain_sdnode()) - return 0; + return nullptr; - unsigned IID = - dynamic_cast(getChild(0)->getLeafValue())->getValue(); + unsigned IID = cast(getChild(0)->getLeafValue())->getValue(); return &CDP.getIntrinsicInfo(IID); } @@ -1329,12 +1525,37 @@ getIntrinsicInfo(const CodeGenDAGPatterns &CDP) const { /// return the ComplexPattern information, otherwise return null. const ComplexPattern * TreePatternNode::getComplexPatternInfo(const CodeGenDAGPatterns &CGP) const { - if (!isLeaf()) return 0; + Record *Rec; + if (isLeaf()) { + DefInit *DI = dyn_cast(getLeafValue()); + if (!DI) + return nullptr; + Rec = DI->getDef(); + } else + Rec = getOperator(); - DefInit *DI = dynamic_cast(getLeafValue()); - if (DI && DI->getDef()->isSubClassOf("ComplexPattern")) - return &CGP.getComplexPattern(DI->getDef()); - return 0; + if (!Rec->isSubClassOf("ComplexPattern")) + return nullptr; + return &CGP.getComplexPattern(Rec); +} + +unsigned TreePatternNode::getNumMIResults(const CodeGenDAGPatterns &CGP) const { + // A ComplexPattern specifically declares how many results it fills in. + if (const ComplexPattern *CP = getComplexPatternInfo(CGP)) + return CP->getNumOperands(); + + // If MIOperandInfo is specified, that gives the count. + if (isLeaf()) { + DefInit *DI = dyn_cast(getLeafValue()); + if (DI && DI->getDef()->isSubClassOf("Operand")) { + DagInit *MIOps = DI->getDef()->getValueAsDag("MIOperandInfo"); + if (MIOps->getNumArgs()) + return MIOps->getNumArgs(); + } + } + + // Otherwise there is just one result. + return 1; } /// NodeHasProperty - Return true if this node has the specified property. @@ -1376,24 +1597,52 @@ TreePatternNode::isCommutativeIntrinsic(const CodeGenDAGPatterns &CDP) const { return false; } +static bool isOperandClass(const TreePatternNode *N, StringRef Class) { + if (!N->isLeaf()) + return N->getOperator()->isSubClassOf(Class); + + DefInit *DI = dyn_cast(N->getLeafValue()); + if (DI && DI->getDef()->isSubClassOf(Class)) + return true; + + return false; +} + +static void emitTooManyOperandsError(TreePattern &TP, + StringRef InstName, + unsigned Expected, + unsigned Actual) { + TP.error("Instruction '" + InstName + "' was provided " + Twine(Actual) + + " operands but expected only " + Twine(Expected) + "!"); +} + +static void emitTooFewOperandsError(TreePattern &TP, + StringRef InstName, + unsigned Actual) { + TP.error("Instruction '" + InstName + + "' expects more than the provided " + Twine(Actual) + " operands!"); +} /// 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. +/// change, false otherwise. If a type contradiction is found, flag an error. bool TreePatternNode::ApplyTypeConstraints(TreePattern &TP, bool NotRegisters) { + if (TP.hasError()) + return false; + CodeGenDAGPatterns &CDP = TP.getDAGPatterns(); if (isLeaf()) { - if (DefInit *DI = dynamic_cast(getLeafValue())) { + if (DefInit *DI = dyn_cast(getLeafValue())) { // If it's a regclass or something else known, include the type. bool MadeChange = false; for (unsigned i = 0, e = Types.size(); i != e; ++i) MadeChange |= UpdateNodeType(i, getImplicitType(DI->getDef(), i, - NotRegisters, TP), TP); + NotRegisters, + !hasName(), TP), TP); return MadeChange; } - if (IntInit *II = dynamic_cast(getLeafValue())) { + if (IntInit *II = dyn_cast(getLeafValue())) { assert(Types.size() == 1 && "Invalid IntInit"); // Int inits are always integers. :) @@ -1406,25 +1655,19 @@ bool TreePatternNode::ApplyTypeConstraints(TreePattern &TP, bool NotRegisters) { if (VT == MVT::iPTR || VT == MVT::iPTRAny) return MadeChange; - unsigned Size = EVT(VT).getSizeInBits(); + unsigned Size = MVT(VT).getSizeInBits(); // Make sure that the value is representable for this type. if (Size >= 32) return MadeChange; - int Val = (II->getValue() << (32-Size)) >> (32-Size); - if (Val == II->getValue()) return MadeChange; - - // If sign-extended doesn't fit, does it fit as unsigned? - unsigned ValueMask; - unsigned UnsignedVal; - ValueMask = unsigned(~uint32_t(0UL) >> (32-Size)); - UnsignedVal = unsigned(II->getValue()); - - if ((ValueMask & UnsignedVal) == UnsignedVal) + // Check that the value doesn't use more bits than we have. It must either + // be a sign- or zero-extended equivalent of the original. + int64_t SignBitAndAbove = II->getValue() >> (Size - 1); + if (SignBitAndAbove == -1 || SignBitAndAbove == 0 || SignBitAndAbove == 1) return MadeChange; - TP.error("Integer value '" + itostr(II->getValue())+ + TP.error("Integer value '" + itostr(II->getValue()) + "' is out of range for type '" + getEnumName(getType(0)) + "'!"); - return MadeChange; + return false; } return false; } @@ -1458,25 +1701,6 @@ bool TreePatternNode::ApplyTypeConstraints(TreePattern &TP, bool NotRegisters) { return MadeChange; } - if (getOperator()->getName() == "COPY_TO_REGCLASS") { - bool MadeChange = false; - MadeChange |= getChild(0)->ApplyTypeConstraints(TP, NotRegisters); - MadeChange |= getChild(1)->ApplyTypeConstraints(TP, NotRegisters); - - assert(getChild(0)->getNumTypes() == 1 && - getChild(1)->getNumTypes() == 1 && "Unhandled case"); - - // child #1 of COPY_TO_REGCLASS should be a register class. We don't care - // what type it gets, so if it didn't get a concrete type just give it the - // first viable type from the reg class. - if (!getChild(1)->hasTypeSet(0) && - !getChild(1)->getExtType(0).isCompletelyUnknown()) { - MVT::SimpleValueType RCVT = getChild(1)->getExtType(0).getTypeList()[0]; - MadeChange |= getChild(1)->UpdateNodeType(0, RCVT, TP); - } - return MadeChange; - } - if (const CodeGenIntrinsic *Int = getIntrinsicInfo(CDP)) { bool MadeChange = false; @@ -1487,10 +1711,12 @@ bool TreePatternNode::ApplyTypeConstraints(TreePattern &TP, bool NotRegisters) { for (unsigned i = 0, e = NumRetVTs; i != e; ++i) MadeChange |= UpdateNodeType(i, Int->IS.RetVTs[i], TP); - if (getNumChildren() != NumParamVTs + 1) + if (getNumChildren() != NumParamVTs + 1) { TP.error("Intrinsic '" + Int->Name + "' expects " + utostr(NumParamVTs) + " operands, not " + utostr(getNumChildren() - 1) + " operands!"); + return false; + } // Apply type info to the intrinsic ID. MadeChange |= getChild(0)->UpdateNodeType(0, MVT::iPTR, TP); @@ -1510,9 +1736,11 @@ bool TreePatternNode::ApplyTypeConstraints(TreePattern &TP, bool NotRegisters) { // Check that the number of operands is sane. Negative operands -> varargs. if (NI.getNumOperands() >= 0 && - getNumChildren() != (unsigned)NI.getNumOperands()) + getNumChildren() != (unsigned)NI.getNumOperands()) { TP.error(getOperator()->getName() + " node requires exactly " + itostr(NI.getNumOperands()) + " operands!"); + return false; + } bool MadeChange = NI.ApplyTypeConstraints(this, TP); for (unsigned i = 0, e = getNumChildren(); i != e; ++i) @@ -1529,28 +1757,10 @@ bool TreePatternNode::ApplyTypeConstraints(TreePattern &TP, bool NotRegisters) { // Apply the result types to the node, these come from the things in the // (outs) list of the instruction. - // FIXME: Cap at one result so far. - unsigned NumResultsToAdd = InstInfo.Operands.NumDefs ? 1 : 0; - for (unsigned ResNo = 0; ResNo != NumResultsToAdd; ++ResNo) { - Record *ResultNode = Inst.getResult(ResNo); - - if (ResultNode->isSubClassOf("PointerLikeRegClass")) { - MadeChange |= UpdateNodeType(ResNo, MVT::iPTR, TP); - } else if (ResultNode->isSubClassOf("RegisterOperand")) { - Record *RegClass = ResultNode->getValueAsDef("RegClass"); - const CodeGenRegisterClass &RC = - CDP.getTargetInfo().getRegisterClass(RegClass); - MadeChange |= UpdateNodeType(ResNo, RC.getValueTypes(), TP); - } else if (ResultNode->getName() == "unknown") { - // Nothing to do. - } else { - assert(ResultNode->isSubClassOf("RegisterClass") && - "Operands should be register classes!"); - const CodeGenRegisterClass &RC = - CDP.getTargetInfo().getRegisterClass(ResultNode); - MadeChange |= UpdateNodeType(ResNo, RC.getValueTypes(), TP); - } - } + unsigned NumResultsToAdd = std::min(InstInfo.Operands.NumDefs, + Inst.getNumResults()); + for (unsigned ResNo = 0; ResNo != NumResultsToAdd; ++ResNo) + MadeChange |= UpdateNodeTypeFromInst(ResNo, Inst.getResult(ResNo), TP); // If the instruction has implicit defs, we apply the first one as a result. // FIXME: This sucks, it should apply all implicit defs. @@ -1572,6 +1782,34 @@ bool TreePatternNode::ApplyTypeConstraints(TreePattern &TP, bool NotRegisters) { assert(getChild(0)->getNumTypes() == 1 && "FIXME: Unhandled"); MadeChange |= UpdateNodeType(0, getChild(0)->getExtType(0), TP); MadeChange |= getChild(0)->UpdateNodeType(0, getExtType(0), TP); + } else if (getOperator()->getName() == "REG_SEQUENCE") { + // We need to do extra, custom typechecking for REG_SEQUENCE since it is + // variadic. + + unsigned NChild = getNumChildren(); + if (NChild < 3) { + TP.error("REG_SEQUENCE requires at least 3 operands!"); + return false; + } + + if (NChild % 2 == 0) { + TP.error("REG_SEQUENCE requires an odd number of operands!"); + return false; + } + + if (!isOperandClass(getChild(0), "RegisterClass")) { + TP.error("REG_SEQUENCE requires a RegisterClass for first operand!"); + return false; + } + + for (unsigned I = 1; I < NChild; I += 2) { + TreePatternNode *SubIdxChild = getChild(I + 1); + if (!isOperandClass(SubIdxChild, "SubRegIndex")) { + TP.error("REG_SEQUENCE requires a SubRegIndex for operand " + + itostr(I + 1) + "!"); + return false; + } + } } unsigned ChildNo = 0; @@ -1581,45 +1819,72 @@ bool TreePatternNode::ApplyTypeConstraints(TreePattern &TP, bool NotRegisters) { // If the instruction expects a predicate or optional def operand, we // codegen this by setting the operand to it's default value if it has a // non-empty DefaultOps field. - if ((OperandNode->isSubClassOf("PredicateOperand") || - OperandNode->isSubClassOf("OptionalDefOperand")) && + if (OperandNode->isSubClassOf("OperandWithDefaultOps") && !CDP.getDefaultOperand(OperandNode).DefaultOps.empty()) continue; // Verify that we didn't run out of provided operands. - if (ChildNo >= getNumChildren()) - TP.error("Instruction '" + getOperator()->getName() + - "' expects more operands than were provided."); + if (ChildNo >= getNumChildren()) { + emitTooFewOperandsError(TP, getOperator()->getName(), getNumChildren()); + return false; + } - MVT::SimpleValueType VT; TreePatternNode *Child = getChild(ChildNo++); unsigned ChildResNo = 0; // Instructions always use res #0 of their op. - if (OperandNode->isSubClassOf("RegisterClass")) { - const CodeGenRegisterClass &RC = - CDP.getTargetInfo().getRegisterClass(OperandNode); - MadeChange |= Child->UpdateNodeType(ChildResNo, RC.getValueTypes(), TP); - } else if (OperandNode->isSubClassOf("RegisterOperand")) { - Record *RegClass = OperandNode->getValueAsDef("RegClass"); - const CodeGenRegisterClass &RC = - CDP.getTargetInfo().getRegisterClass(RegClass); - MadeChange |= Child->UpdateNodeType(ChildResNo, RC.getValueTypes(), TP); - } else if (OperandNode->isSubClassOf("Operand")) { - VT = getValueType(OperandNode->getValueAsDef("Type")); - MadeChange |= Child->UpdateNodeType(ChildResNo, VT, TP); - } else if (OperandNode->isSubClassOf("PointerLikeRegClass")) { - MadeChange |= Child->UpdateNodeType(ChildResNo, MVT::iPTR, TP); - } else if (OperandNode->getName() == "unknown") { - // Nothing to do. - } else - llvm_unreachable("Unknown operand type!"); + // If the operand has sub-operands, they may be provided by distinct + // child patterns, so attempt to match each sub-operand separately. + if (OperandNode->isSubClassOf("Operand")) { + DagInit *MIOpInfo = OperandNode->getValueAsDag("MIOperandInfo"); + if (unsigned NumArgs = MIOpInfo->getNumArgs()) { + // But don't do that if the whole operand is being provided by + // a single ComplexPattern-related Operand. + + if (Child->getNumMIResults(CDP) < NumArgs) { + // Match first sub-operand against the child we already have. + Record *SubRec = cast(MIOpInfo->getArg(0))->getDef(); + MadeChange |= + Child->UpdateNodeTypeFromInst(ChildResNo, SubRec, TP); + + // And the remaining sub-operands against subsequent children. + for (unsigned Arg = 1; Arg < NumArgs; ++Arg) { + if (ChildNo >= getNumChildren()) { + emitTooFewOperandsError(TP, getOperator()->getName(), + getNumChildren()); + return false; + } + Child = getChild(ChildNo++); + + SubRec = cast(MIOpInfo->getArg(Arg))->getDef(); + MadeChange |= + Child->UpdateNodeTypeFromInst(ChildResNo, SubRec, TP); + } + continue; + } + } + } - MadeChange |= Child->ApplyTypeConstraints(TP, NotRegisters); + // If we didn't match by pieces above, attempt to match the whole + // operand now. + MadeChange |= Child->UpdateNodeTypeFromInst(ChildResNo, OperandNode, TP); } - if (ChildNo != getNumChildren()) - TP.error("Instruction '" + getOperator()->getName() + - "' was provided too many operands!"); + if (!InstInfo.Operands.isVariadic && ChildNo != getNumChildren()) { + emitTooManyOperandsError(TP, getOperator()->getName(), + ChildNo, getNumChildren()); + return false; + } + + for (unsigned i = 0, e = getNumChildren(); i != e; ++i) + MadeChange |= getChild(i)->ApplyTypeConstraints(TP, NotRegisters); + return MadeChange; + } + + if (getOperator()->isSubClassOf("ComplexPattern")) { + bool MadeChange = false; + + for (unsigned i = 0; i < getNumChildren(); ++i) + MadeChange |= getChild(i)->ApplyTypeConstraints(TP, NotRegisters); return MadeChange; } @@ -1627,9 +1892,11 @@ bool TreePatternNode::ApplyTypeConstraints(TreePattern &TP, bool NotRegisters) { assert(getOperator()->isSubClassOf("SDNodeXForm") && "Unknown node type!"); // Node transforms always take one operand. - if (getNumChildren() != 1) + if (getNumChildren() != 1) { TP.error("Node transform '" + getOperator()->getName() + "' requires one operand!"); + return false; + } bool MadeChange = getChild(0)->ApplyTypeConstraints(TP, NotRegisters); @@ -1652,7 +1919,7 @@ bool TreePatternNode::ApplyTypeConstraints(TreePattern &TP, bool NotRegisters) { static bool OnlyOnRHSOfCommutative(TreePatternNode *N) { if (!N->isLeaf() && N->getOperator()->getName() == "imm") return true; - if (N->isLeaf() && dynamic_cast(N->getLeafValue())) + if (N->isLeaf() && isa(N->getLeafValue())) return true; return false; } @@ -1678,6 +1945,9 @@ bool TreePatternNode::canPatternMatch(std::string &Reason, return true; } + if (getOperator()->isSubClassOf("ComplexPattern")) + return true; + // If this node is a commutative operator, check that the LHS isn't an // immediate. const SDNodeInfo &NodeInfo = CDP.getSDNodeInfo(getOperator()); @@ -1703,32 +1973,35 @@ bool TreePatternNode::canPatternMatch(std::string &Reason, // TreePattern::TreePattern(Record *TheRec, ListInit *RawPat, bool isInput, - CodeGenDAGPatterns &cdp) : TheRecord(TheRec), CDP(cdp){ - isInputPattern = isInput; - for (unsigned i = 0, e = RawPat->getSize(); i != e; ++i) - Trees.push_back(ParseTreePattern(RawPat->getElement(i), "")); + CodeGenDAGPatterns &cdp) : TheRecord(TheRec), CDP(cdp), + isInputPattern(isInput), HasError(false) { + for (Init *I : RawPat->getValues()) + Trees.push_back(ParseTreePattern(I, "")); } TreePattern::TreePattern(Record *TheRec, DagInit *Pat, bool isInput, - CodeGenDAGPatterns &cdp) : TheRecord(TheRec), CDP(cdp){ - isInputPattern = isInput; + CodeGenDAGPatterns &cdp) : TheRecord(TheRec), CDP(cdp), + isInputPattern(isInput), HasError(false) { Trees.push_back(ParseTreePattern(Pat, "")); } TreePattern::TreePattern(Record *TheRec, TreePatternNode *Pat, bool isInput, - CodeGenDAGPatterns &cdp) : TheRecord(TheRec), CDP(cdp){ - isInputPattern = isInput; + CodeGenDAGPatterns &cdp) : TheRecord(TheRec), CDP(cdp), + isInputPattern(isInput), HasError(false) { Trees.push_back(Pat); } -void TreePattern::error(const std::string &Msg) const { +void TreePattern::error(const Twine &Msg) { + if (HasError) + return; dump(); - throw TGError(TheRecord->getLoc(), "In " + TheRecord->getName() + ": " + Msg); + PrintError(TheRecord->getLoc(), "In " + TheRecord->getName() + ": " + Msg); + HasError = true; } void TreePattern::ComputeNamedNodes() { - for (unsigned i = 0, e = Trees.size(); i != e; ++i) - ComputeNamedNodes(Trees[i]); + for (TreePatternNode *Tree : Trees) + ComputeNamedNodes(Tree); } void TreePattern::ComputeNamedNodes(TreePatternNode *N) { @@ -1741,7 +2014,7 @@ void TreePattern::ComputeNamedNodes(TreePatternNode *N) { TreePatternNode *TreePattern::ParseTreePattern(Init *TheInit, StringRef OpName){ - if (DefInit *DI = dynamic_cast(TheInit)) { + if (DefInit *DI = dyn_cast(TheInit)) { Record *R = DI->getDef(); // Direct reference to a leaf DagNode or PatFrag? Turn it into a @@ -1765,26 +2038,36 @@ TreePatternNode *TreePattern::ParseTreePattern(Init *TheInit, StringRef OpName){ return Res; } - if (IntInit *II = dynamic_cast(TheInit)) { + // ?:$name or just $name. + if (isa(TheInit)) { + if (OpName.empty()) + error("'?' argument requires a name to match with operand list"); + TreePatternNode *Res = new TreePatternNode(TheInit, 1); + Args.push_back(OpName); + Res->setName(OpName); + return Res; + } + + if (IntInit *II = dyn_cast(TheInit)) { if (!OpName.empty()) error("Constant int argument should not have a name!"); return new TreePatternNode(II, 1); } - if (BitsInit *BI = dynamic_cast(TheInit)) { + if (BitsInit *BI = dyn_cast(TheInit)) { // Turn this into an IntInit. Init *II = BI->convertInitializerTo(IntRecTy::get()); - if (II == 0 || !dynamic_cast(II)) + if (!II || !isa(II)) error("Bits value must be constants!"); return ParseTreePattern(II, OpName); } - DagInit *Dag = dynamic_cast(TheInit); + DagInit *Dag = dyn_cast(TheInit); if (!Dag) { TheInit->dump(); error("Pattern has unexpected init kind!"); } - DefInit *OpDef = dynamic_cast(Dag->getOperator()); + DefInit *OpDef = dyn_cast(Dag->getOperator()); if (!OpDef) error("Pattern has unexpected operator type!"); Record *Operator = OpDef->getDef(); @@ -1811,6 +2094,7 @@ TreePatternNode *TreePattern::ParseTreePattern(Init *TheInit, StringRef OpName){ !Operator->isSubClassOf("Instruction") && !Operator->isSubClassOf("SDNodeXForm") && !Operator->isSubClassOf("Intrinsic") && + !Operator->isSubClassOf("ComplexPattern") && Operator->getName() != "set" && Operator->getName() != "implicit") error("Unrecognized node '" + Operator->getName() + "'!"); @@ -1835,7 +2119,8 @@ TreePatternNode *TreePattern::ParseTreePattern(Init *TheInit, StringRef OpName){ Operator->getName() != "tblockaddress" && Operator->getName() != "tglobaladdr" && Operator->getName() != "bb" && - Operator->getName() != "vt") + Operator->getName() != "vt" && + Operator->getName() != "mcsym") error("Cannot use '" + Operator->getName() + "' in an output pattern!"); } @@ -1866,6 +2151,27 @@ TreePatternNode *TreePattern::ParseTreePattern(Init *TheInit, StringRef OpName){ Children.insert(Children.begin(), IIDNode); } + if (Operator->isSubClassOf("ComplexPattern")) { + for (unsigned i = 0; i < Children.size(); ++i) { + TreePatternNode *Child = Children[i]; + + if (Child->getName().empty()) + error("All arguments to a ComplexPattern must be named"); + + // Check that the ComplexPattern uses are consistent: "(MY_PAT $a, $b)" + // and "(MY_PAT $b, $a)" should not be allowed in the same pattern; + // neither should "(MY_PAT_1 $a, $b)" and "(MY_PAT_2 $a, $b)". + auto OperandId = std::make_pair(Operator, i); + auto PrevOp = ComplexPatternOperands.find(Child->getName()); + if (PrevOp != ComplexPatternOperands.end()) { + if (PrevOp->getValue() != OperandId) + error("All ComplexPattern operands must appear consistently: " + "in the same order in just one ComplexPattern instance."); + } else + ComplexPatternOperands[Child->getName()] = OperandId; + } + } + unsigned NumResults = GetNumNodeResults(Operator, CDP); TreePatternNode *Result = new TreePatternNode(Operator, Children, NumResults); Result->setName(OpName); @@ -1912,7 +2218,7 @@ static bool SimplifyTree(TreePatternNode *&N) { /// InferAllTypes - Infer/propagate as many types throughout the expression /// patterns as possible. Return true if all types are inferred, false -/// otherwise. Throw an exception if a type contradiction is found. +/// otherwise. Flags an error if a type contradiction is found. bool TreePattern:: InferAllTypes(const StringMap > *InNamedTypes) { if (NamedNodes.empty()) @@ -1921,51 +2227,52 @@ InferAllTypes(const StringMap > *InNamedTypes) { bool MadeChange = true; while (MadeChange) { MadeChange = false; - for (unsigned i = 0, e = Trees.size(); i != e; ++i) { - MadeChange |= Trees[i]->ApplyTypeConstraints(*this, false); - MadeChange |= SimplifyTree(Trees[i]); + for (TreePatternNode *Tree : Trees) { + MadeChange |= Tree->ApplyTypeConstraints(*this, false); + MadeChange |= SimplifyTree(Tree); } // If there are constraints on our named nodes, apply them. - for (StringMap >::iterator - I = NamedNodes.begin(), E = NamedNodes.end(); I != E; ++I) { - SmallVectorImpl &Nodes = I->second; + for (auto &Entry : NamedNodes) { + SmallVectorImpl &Nodes = Entry.second; // If we have input named node types, propagate their types to the named // values here. if (InNamedTypes) { - // FIXME: Should be error? - assert(InNamedTypes->count(I->getKey()) && - "Named node in output pattern but not input pattern?"); + if (!InNamedTypes->count(Entry.getKey())) { + error("Node '" + std::string(Entry.getKey()) + + "' in output pattern but not input pattern"); + return true; + } const SmallVectorImpl &InNodes = - InNamedTypes->find(I->getKey())->second; + InNamedTypes->find(Entry.getKey())->second; // The input types should be fully resolved by now. - for (unsigned i = 0, e = Nodes.size(); i != e; ++i) { + for (TreePatternNode *Node : Nodes) { // If this node is a register class, and it is the root of the pattern // then we're mapping something onto an input register. We allow // changing the type of the input register in this case. This allows // us to match things like: // def : Pat<(v1i64 (bitconvert(v2i32 DPR:$src))), (v1i64 DPR:$src)>; - if (Nodes[i] == Trees[0] && Nodes[i]->isLeaf()) { - DefInit *DI = dynamic_cast(Nodes[i]->getLeafValue()); + if (Node == Trees[0] && Node->isLeaf()) { + DefInit *DI = dyn_cast(Node->getLeafValue()); if (DI && (DI->getDef()->isSubClassOf("RegisterClass") || DI->getDef()->isSubClassOf("RegisterOperand"))) continue; } - assert(Nodes[i]->getNumTypes() == 1 && + assert(Node->getNumTypes() == 1 && InNodes[0]->getNumTypes() == 1 && "FIXME: cannot name multiple result nodes yet"); - MadeChange |= Nodes[i]->UpdateNodeType(0, InNodes[0]->getExtType(0), - *this); + MadeChange |= Node->UpdateNodeType(0, InNodes[0]->getExtType(0), + *this); } } // If there are multiple nodes with the same name, they must all have the // same type. - if (I->second.size() > 1) { + if (Entry.second.size() > 1) { for (unsigned i = 0, e = Nodes.size()-1; i != e; ++i) { TreePatternNode *N1 = Nodes[i], *N2 = Nodes[i+1]; assert(N1->getNumTypes() == 1 && N2->getNumTypes() == 1 && @@ -1979,8 +2286,8 @@ InferAllTypes(const StringMap > *InNamedTypes) { } bool HasUnresolvedTypes = false; - for (unsigned i = 0, e = Trees.size(); i != e; ++i) - HasUnresolvedTypes |= Trees[i]->ContainsUnresolvedType(); + for (const TreePatternNode *Tree : Trees) + HasUnresolvedTypes |= Tree->ContainsUnresolvedType(); return !HasUnresolvedTypes; } @@ -1996,9 +2303,9 @@ void TreePattern::print(raw_ostream &OS) const { if (Trees.size() > 1) OS << "[\n"; - for (unsigned i = 0, e = Trees.size(); i != e; ++i) { + for (const TreePatternNode *Tree : Trees) { OS << "\t"; - Trees[i]->print(OS); + Tree->print(OS); OS << "\n"; } @@ -2023,6 +2330,7 @@ CodeGenDAGPatterns::CodeGenDAGPatterns(RecordKeeper &R) : ParsePatternFragments(); ParseDefaultOperands(); ParseInstructions(); + ParsePatternFragments(/*OutFrags*/true); ParsePatterns(); // Generate variants. For example, commutative patterns can match @@ -2033,21 +2341,16 @@ CodeGenDAGPatterns::CodeGenDAGPatterns(RecordKeeper &R) : // stores, and side effects in many cases by examining an // instruction's pattern. InferInstructionFlags(); -} -CodeGenDAGPatterns::~CodeGenDAGPatterns() { - for (pf_iterator I = PatternFragments.begin(), - E = PatternFragments.end(); I != E; ++I) - delete I->second; + // Verify that instruction flags match the patterns. + VerifyInstructionFlags(); } - Record *CodeGenDAGPatterns::getSDNodeNamed(const std::string &Name) const { Record *N = Records.getDef(Name); - if (!N || !N->isSubClassOf("SDNode")) { - errs() << "Error getting SDNode '" << Name << "'!\n"; - exit(1); - } + if (!N || !N->isSubClassOf("SDNode")) + PrintFatalError("Error getting SDNode '" + Name + "'!"); + return N; } @@ -2093,14 +2396,19 @@ void CodeGenDAGPatterns::ParseComplexPatterns() { /// inline fragments together as necessary, so that there are no references left /// inside a pattern fragment to a pattern fragment. /// -void CodeGenDAGPatterns::ParsePatternFragments() { +void CodeGenDAGPatterns::ParsePatternFragments(bool OutFrags) { std::vector Fragments = Records.getAllDerivedDefinitions("PatFrag"); // First step, parse all of the fragments. - for (unsigned i = 0, e = Fragments.size(); i != e; ++i) { - DagInit *Tree = Fragments[i]->getValueAsDag("Fragment"); - TreePattern *P = new TreePattern(Fragments[i], Tree, true, *this); - PatternFragments[Fragments[i]] = P; + for (Record *Frag : Fragments) { + if (OutFrags != Frag->isSubClassOf("OutPatFrag")) + continue; + + DagInit *Tree = Frag->getValueAsDag("Fragment"); + TreePattern *P = + (PatternFragments[Frag] = llvm::make_unique( + Frag, Tree, !Frag->isSubClassOf("OutPatFrag"), + *this)).get(); // Validate the argument list, converting it to set, to discard duplicates. std::vector &Args = P->getArgList(); @@ -2110,8 +2418,8 @@ void CodeGenDAGPatterns::ParsePatternFragments() { P->error("Cannot have unnamed 'node' values in pattern fragment!"); // Parse the operands list. - DagInit *OpsList = Fragments[i]->getValueAsDag("Operands"); - DefInit *OpsOp = dynamic_cast(OpsList->getOperator()); + DagInit *OpsList = Frag->getValueAsDag("Operands"); + DefInit *OpsOp = dyn_cast(OpsList->getOperator()); // Special cases: ops == outs == ins. Different names are used to // improve readability. if (!OpsOp || @@ -2123,9 +2431,8 @@ void CodeGenDAGPatterns::ParsePatternFragments() { // Copy over the arguments. Args.clear(); for (unsigned j = 0, e = OpsList->getNumArgs(); j != e; ++j) { - if (!dynamic_cast(OpsList->getArg(j)) || - static_cast(OpsList->getArg(j))-> - getDef()->getName() != "node") + if (!isa(OpsList->getArg(j)) || + cast(OpsList->getArg(j))->getDef()->getName() != "node") P->error("Operands list should all be 'node' values."); if (OpsList->getArgName(j).empty()) P->error("Operands list should have names for each operand!"); @@ -2148,81 +2455,72 @@ void CodeGenDAGPatterns::ParsePatternFragments() { // If there is a node transformation corresponding to this, keep track of // it. - Record *Transform = Fragments[i]->getValueAsDef("OperandTransform"); + Record *Transform = Frag->getValueAsDef("OperandTransform"); if (!getSDNodeTransform(Transform).second.empty()) // not noop xform? P->getOnlyTree()->setTransformFn(Transform); } // 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 (unsigned i = 0, e = Fragments.size(); i != e; ++i) { - TreePattern *ThePat = PatternFragments[Fragments[i]]; - ThePat->InlinePatternFragments(); + for (Record *Frag : Fragments) { + if (OutFrags != Frag->isSubClassOf("OutPatFrag")) + continue; + + TreePattern &ThePat = *PatternFragments[Frag]; + ThePat.InlinePatternFragments(); // Infer as many types as possible. Don't worry about it if we don't infer // all of them, some may depend on the inputs of the pattern. - try { - ThePat->InferAllTypes(); - } catch (...) { - // If this pattern fragment is not supported by this target (no types can - // satisfy its constraints), just ignore it. If the bogus pattern is - // actually used by instructions, the type consistency error will be - // reported there. - } + ThePat.InferAllTypes(); + ThePat.resetError(); // If debugging, print out the pattern fragment result. - DEBUG(ThePat->dump()); + DEBUG(ThePat.dump()); } } void CodeGenDAGPatterns::ParseDefaultOperands() { - std::vector DefaultOps[2]; - DefaultOps[0] = Records.getAllDerivedDefinitions("PredicateOperand"); - DefaultOps[1] = Records.getAllDerivedDefinitions("OptionalDefOperand"); + std::vector DefaultOps; + DefaultOps = Records.getAllDerivedDefinitions("OperandWithDefaultOps"); // Find some SDNode. assert(!SDNodes.empty() && "No SDNodes parsed?"); Init *SomeSDNode = DefInit::get(SDNodes.begin()->first); - for (unsigned iter = 0; iter != 2; ++iter) { - for (unsigned i = 0, e = DefaultOps[iter].size(); i != e; ++i) { - DagInit *DefaultInfo = DefaultOps[iter][i]->getValueAsDag("DefaultOps"); - - // Clone the DefaultInfo dag node, changing the operator from 'ops' to - // SomeSDnode so that we can parse this. - std::vector > Ops; - for (unsigned op = 0, e = DefaultInfo->getNumArgs(); op != e; ++op) - Ops.push_back(std::make_pair(DefaultInfo->getArg(op), - DefaultInfo->getArgName(op))); - DagInit *DI = DagInit::get(SomeSDNode, "", Ops); - - // Create a TreePattern to parse this. - TreePattern P(DefaultOps[iter][i], DI, false, *this); - assert(P.getNumTrees() == 1 && "This ctor can only produce one tree!"); - - // Copy the operands over into a DAGDefaultOperand. - DAGDefaultOperand DefaultOpInfo; - - TreePatternNode *T = P.getTree(0); - for (unsigned op = 0, e = T->getNumChildren(); op != e; ++op) { - TreePatternNode *TPN = T->getChild(op); - while (TPN->ApplyTypeConstraints(P, false)) - /* Resolve all types */; - - if (TPN->ContainsUnresolvedType()) { - if (iter == 0) - throw "Value #" + utostr(i) + " of PredicateOperand '" + - DefaultOps[iter][i]->getName() +"' doesn't have a concrete type!"; - else - throw "Value #" + utostr(i) + " of OptionalDefOperand '" + - DefaultOps[iter][i]->getName() +"' doesn't have a concrete type!"; - } - DefaultOpInfo.DefaultOps.push_back(TPN); + for (unsigned i = 0, e = DefaultOps.size(); i != e; ++i) { + DagInit *DefaultInfo = DefaultOps[i]->getValueAsDag("DefaultOps"); + + // Clone the DefaultInfo dag node, changing the operator from 'ops' to + // SomeSDnode so that we can parse this. + std::vector > Ops; + for (unsigned op = 0, e = DefaultInfo->getNumArgs(); op != e; ++op) + Ops.push_back(std::make_pair(DefaultInfo->getArg(op), + DefaultInfo->getArgName(op))); + DagInit *DI = DagInit::get(SomeSDNode, "", Ops); + + // Create a TreePattern to parse this. + TreePattern P(DefaultOps[i], DI, false, *this); + assert(P.getNumTrees() == 1 && "This ctor can only produce one tree!"); + + // Copy the operands over into a DAGDefaultOperand. + DAGDefaultOperand DefaultOpInfo; + + TreePatternNode *T = P.getTree(0); + for (unsigned op = 0, e = T->getNumChildren(); op != e; ++op) { + TreePatternNode *TPN = T->getChild(op); + while (TPN->ApplyTypeConstraints(P, false)) + /* Resolve all types */; + + if (TPN->ContainsUnresolvedType()) { + PrintFatalError("Value #" + Twine(i) + " of OperandWithDefaultOps '" + + DefaultOps[i]->getName() + + "' doesn't have a concrete type!"); } - - // Insert it into the DefaultOperands map so we can find it later. - DefaultOperands[DefaultOps[iter][i]] = DefaultOpInfo; + DefaultOpInfo.DefaultOps.push_back(TPN); } + + // Insert it into the DefaultOperands map so we can find it later. + DefaultOperands[DefaultOps[i]] = DefaultOpInfo; } } @@ -2233,7 +2531,7 @@ static bool HandleUse(TreePattern *I, TreePatternNode *Pat, // No name -> not interesting. if (Pat->getName().empty()) { if (Pat->isLeaf()) { - DefInit *DI = dynamic_cast(Pat->getLeafValue()); + DefInit *DI = dyn_cast(Pat->getLeafValue()); if (DI && (DI->getDef()->isSubClassOf("RegisterClass") || DI->getDef()->isSubClassOf("RegisterOperand"))) I->error("Input " + DI->getDef()->getName() + " must be named!"); @@ -2243,7 +2541,7 @@ static bool HandleUse(TreePattern *I, TreePatternNode *Pat, Record *Rec; if (Pat->isLeaf()) { - DefInit *DI = dynamic_cast(Pat->getLeafValue()); + DefInit *DI = dyn_cast(Pat->getLeafValue()); if (!DI) I->error("Input $" + Pat->getName() + " must be an identifier!"); Rec = DI->getDef(); } else { @@ -2261,7 +2559,7 @@ static bool HandleUse(TreePattern *I, TreePatternNode *Pat, } Record *SlotRec; if (Slot->isLeaf()) { - SlotRec = dynamic_cast(Slot->getLeafValue())->getDef(); + SlotRec = cast(Slot->getLeafValue())->getDef(); } else { assert(Slot->getNumChildren() == 0 && "can't be a use with children!"); SlotRec = Slot->getOperator(); @@ -2296,7 +2594,7 @@ FindPatternInputsAndOutputs(TreePattern *I, TreePatternNode *Pat, if (!Dest->isLeaf()) I->error("implicitly defined value should be a register!"); - DefInit *Val = dynamic_cast(Dest->getLeafValue()); + DefInit *Val = dyn_cast(Dest->getLeafValue()); if (!Val || !Val->getDef()->isSubClassOf("Register")) I->error("implicitly defined value should be a register!"); InstImpResults.push_back(Val->getDef()); @@ -2337,11 +2635,14 @@ FindPatternInputsAndOutputs(TreePattern *I, TreePatternNode *Pat, if (!Dest->isLeaf()) I->error("set destination should be a register!"); - DefInit *Val = dynamic_cast(Dest->getLeafValue()); - if (!Val) + DefInit *Val = dyn_cast(Dest->getLeafValue()); + if (!Val) { I->error("set destination should be a register!"); + continue; + } if (Val->getDef()->isSubClassOf("RegisterClass") || + Val->getDef()->isSubClassOf("ValueType") || Val->getDef()->isSubClassOf("RegisterOperand") || Val->getDef()->isSubClassOf("PointerLikeRegClass")) { if (Dest->getName().empty()) @@ -2367,43 +2668,36 @@ FindPatternInputsAndOutputs(TreePattern *I, TreePatternNode *Pat, class InstAnalyzer { const CodeGenDAGPatterns &CDP; - bool &mayStore; - bool &mayLoad; - bool &IsBitcast; - bool &HasSideEffects; - bool &IsVariadic; public: - InstAnalyzer(const CodeGenDAGPatterns &cdp, - bool &maystore, bool &mayload, bool &isbc, bool &hse, bool &isv) - : CDP(cdp), mayStore(maystore), mayLoad(mayload), IsBitcast(isbc), - HasSideEffects(hse), IsVariadic(isv) { - } + bool hasSideEffects; + bool mayStore; + bool mayLoad; + bool isBitcast; + bool isVariadic; - /// Analyze - Analyze the specified instruction, returning true if the - /// instruction had a pattern. - bool Analyze(Record *InstRecord) { - const TreePattern *Pattern = CDP.getInstruction(InstRecord).getPattern(); - if (Pattern == 0) { - HasSideEffects = 1; - return false; // No pattern. - } + InstAnalyzer(const CodeGenDAGPatterns &cdp) + : CDP(cdp), hasSideEffects(false), mayStore(false), mayLoad(false), + isBitcast(false), isVariadic(false) {} - // FIXME: Assume only the first tree is the pattern. The others are clobber - // nodes. - AnalyzeNode(Pattern->getTree(0)); - return true; + void Analyze(const TreePattern *Pat) { + // Assume only the first tree is the pattern. The others are clobber nodes. + AnalyzeNode(Pat->getTree(0)); + } + + void Analyze(const PatternToMatch *Pat) { + AnalyzeNode(Pat->getSrcPattern()); } private: bool IsNodeBitcast(const TreePatternNode *N) const { - if (HasSideEffects || mayLoad || mayStore || IsVariadic) + if (hasSideEffects || mayLoad || mayStore || isVariadic) return false; if (N->getNumChildren() != 2) return false; const TreePatternNode *N0 = N->getChild(0); - if (!N0->isLeaf() || !dynamic_cast(N0->getLeafValue())) + if (!N0->isLeaf() || !isa(N0->getLeafValue())) return false; const TreePatternNode *N1 = N->getChild(1); @@ -2418,16 +2712,17 @@ private: return OpInfo.getEnumName() == "ISD::BITCAST"; } +public: void AnalyzeNode(const TreePatternNode *N) { if (N->isLeaf()) { - if (DefInit *DI = dynamic_cast(N->getLeafValue())) { + if (DefInit *DI = dyn_cast(N->getLeafValue())) { Record *LeafRec = DI->getDef(); // Handle ComplexPattern leaves. if (LeafRec->isSubClassOf("ComplexPattern")) { const ComplexPattern &CP = CDP.getComplexPattern(LeafRec); if (CP.hasProperty(SDNPMayStore)) mayStore = true; if (CP.hasProperty(SDNPMayLoad)) mayLoad = true; - if (CP.hasProperty(SDNPSideEffect)) HasSideEffects = true; + if (CP.hasProperty(SDNPSideEffect)) hasSideEffects = true; } } return; @@ -2439,18 +2734,15 @@ private: // Ignore set nodes, which are not SDNodes. if (N->getOperator()->getName() == "set") { - IsBitcast = IsNodeBitcast(N); + isBitcast = IsNodeBitcast(N); return; } - // Get information about the SDNode for the operator. - const SDNodeInfo &OpInfo = CDP.getSDNodeInfo(N->getOperator()); - // Notice properties of the node. - if (OpInfo.hasProperty(SDNPMayStore)) mayStore = true; - if (OpInfo.hasProperty(SDNPMayLoad)) mayLoad = true; - if (OpInfo.hasProperty(SDNPSideEffect)) HasSideEffects = true; - if (OpInfo.hasProperty(SDNPVariadic)) IsVariadic = true; + if (N->NodeHasProperty(SDNPMayStore, CDP)) mayStore = true; + if (N->NodeHasProperty(SDNPMayLoad, CDP)) mayLoad = true; + if (N->NodeHasProperty(SDNPSideEffect, CDP)) hasSideEffects = true; + if (N->NodeHasProperty(SDNPVariadic, CDP)) isVariadic = true; if (const CodeGenIntrinsic *IntInfo = N->getIntrinsicInfo(CDP)) { // If this is an intrinsic, analyze it. @@ -2462,270 +2754,339 @@ private: if (IntInfo->ModRef >= CodeGenIntrinsic::ReadWriteMem) // WriteMem intrinsics can have other strange effects. - HasSideEffects = true; + hasSideEffects = true; } } }; -static void InferFromPattern(const CodeGenInstruction &Inst, - bool &MayStore, bool &MayLoad, - bool &IsBitcast, - bool &HasSideEffects, bool &IsVariadic, - const CodeGenDAGPatterns &CDP) { - MayStore = MayLoad = IsBitcast = HasSideEffects = IsVariadic = false; - - bool HadPattern = - InstAnalyzer(CDP, MayStore, MayLoad, IsBitcast, HasSideEffects, IsVariadic) - .Analyze(Inst.TheDef); - - // InstAnalyzer only correctly analyzes mayStore/mayLoad so far. - if (Inst.mayStore) { // If the .td file explicitly sets mayStore, use it. - // If we decided that this is a store from the pattern, then the .td file - // entry is redundant. - if (MayStore) - PrintWarning(Inst.TheDef->getLoc(), - "mayStore flag explicitly set on " - "instruction, but flag already inferred from pattern."); - MayStore = true; +static bool InferFromPattern(CodeGenInstruction &InstInfo, + const InstAnalyzer &PatInfo, + Record *PatDef) { + bool Error = false; + + // Remember where InstInfo got its flags. + if (InstInfo.hasUndefFlags()) + InstInfo.InferredFrom = PatDef; + + // Check explicitly set flags for consistency. + if (InstInfo.hasSideEffects != PatInfo.hasSideEffects && + !InstInfo.hasSideEffects_Unset) { + // Allow explicitly setting hasSideEffects = 1 on instructions, even when + // the pattern has no side effects. That could be useful for div/rem + // instructions that may trap. + if (!InstInfo.hasSideEffects) { + Error = true; + PrintError(PatDef->getLoc(), "Pattern doesn't match hasSideEffects = " + + Twine(InstInfo.hasSideEffects)); + } } - if (Inst.mayLoad) { // If the .td file explicitly sets mayLoad, use it. - // If we decided that this is a load from the pattern, then the .td file - // entry is redundant. - if (MayLoad) - PrintWarning(Inst.TheDef->getLoc(), - "mayLoad flag explicitly set on " - "instruction, but flag already inferred from pattern."); - MayLoad = true; + if (InstInfo.mayStore != PatInfo.mayStore && !InstInfo.mayStore_Unset) { + Error = true; + PrintError(PatDef->getLoc(), "Pattern doesn't match mayStore = " + + Twine(InstInfo.mayStore)); } - if (Inst.neverHasSideEffects) { - if (HadPattern) - PrintWarning(Inst.TheDef->getLoc(), - "neverHasSideEffects flag explicitly set on " - "instruction, but flag already inferred from pattern."); - HasSideEffects = false; + if (InstInfo.mayLoad != PatInfo.mayLoad && !InstInfo.mayLoad_Unset) { + // Allow explicitly setting mayLoad = 1, even when the pattern has no loads. + // Some targets translate immediates to loads. + if (!InstInfo.mayLoad) { + Error = true; + PrintError(PatDef->getLoc(), "Pattern doesn't match mayLoad = " + + Twine(InstInfo.mayLoad)); + } } - if (Inst.hasSideEffects) { - if (HasSideEffects) - PrintWarning(Inst.TheDef->getLoc(), - "hasSideEffects flag explicitly set on " - "instruction, but flag already inferred from pattern."); - HasSideEffects = true; + // Transfer inferred flags. + InstInfo.hasSideEffects |= PatInfo.hasSideEffects; + InstInfo.mayStore |= PatInfo.mayStore; + InstInfo.mayLoad |= PatInfo.mayLoad; + + // These flags are silently added without any verification. + InstInfo.isBitcast |= PatInfo.isBitcast; + + // Don't infer isVariadic. This flag means something different on SDNodes and + // instructions. For example, a CALL SDNode is variadic because it has the + // call arguments as operands, but a CALL instruction is not variadic - it + // has argument registers as implicit, not explicit uses. + + return Error; +} + +/// hasNullFragReference - Return true if the DAG has any reference to the +/// null_frag operator. +static bool hasNullFragReference(DagInit *DI) { + DefInit *OpDef = dyn_cast(DI->getOperator()); + if (!OpDef) return false; + Record *Operator = OpDef->getDef(); + + // If this is the null fragment, return true. + if (Operator->getName() == "null_frag") return true; + // If any of the arguments reference the null fragment, return true. + for (unsigned i = 0, e = DI->getNumArgs(); i != e; ++i) { + DagInit *Arg = dyn_cast(DI->getArg(i)); + if (Arg && hasNullFragReference(Arg)) + return true; } - if (Inst.Operands.isVariadic) - IsVariadic = true; // Can warn if we want. + return false; } -/// ParseInstructions - Parse all of the instructions, inlining and resolving -/// any fragments involved. This populates the Instructions list with fully -/// resolved instructions. -void CodeGenDAGPatterns::ParseInstructions() { - std::vector Instrs = Records.getAllDerivedDefinitions("Instruction"); +/// hasNullFragReference - Return true if any DAG in the list references +/// the null_frag operator. +static bool hasNullFragReference(ListInit *LI) { + for (Init *I : LI->getValues()) { + DagInit *DI = dyn_cast(I); + assert(DI && "non-dag in an instruction Pattern list?!"); + if (hasNullFragReference(DI)) + return true; + } + return false; +} - for (unsigned i = 0, e = Instrs.size(); i != e; ++i) { - ListInit *LI = 0; +/// Get all the instructions in a tree. +static void +getInstructionsInTree(TreePatternNode *Tree, SmallVectorImpl &Instrs) { + if (Tree->isLeaf()) + return; + if (Tree->getOperator()->isSubClassOf("Instruction")) + Instrs.push_back(Tree->getOperator()); + for (unsigned i = 0, e = Tree->getNumChildren(); i != e; ++i) + getInstructionsInTree(Tree->getChild(i), Instrs); +} - if (dynamic_cast(Instrs[i]->getValueInit("Pattern"))) - LI = Instrs[i]->getValueAsListInit("Pattern"); +/// Check the class of a pattern leaf node against the instruction operand it +/// represents. +static bool checkOperandClass(CGIOperandList::OperandInfo &OI, + Record *Leaf) { + if (OI.Rec == Leaf) + return true; - // If there is no pattern, only collect minimal information about the - // instruction for its operand list. We have to assume that there is one - // result, as we have no detailed info. - if (!LI || LI->getSize() == 0) { - std::vector Results; - std::vector Operands; + // Allow direct value types to be used in instruction set patterns. + // The type will be checked later. + if (Leaf->isSubClassOf("ValueType")) + return true; - CodeGenInstruction &InstInfo = Target.getInstruction(Instrs[i]); + // Patterns can also be ComplexPattern instances. + if (Leaf->isSubClassOf("ComplexPattern")) + return true; - if (InstInfo.Operands.size() != 0) { - if (InstInfo.Operands.NumDefs == 0) { - // These produce no results - for (unsigned j = 0, e = InstInfo.Operands.size(); j < e; ++j) - Operands.push_back(InstInfo.Operands[j].Rec); - } else { - // Assume the first operand is the result. - Results.push_back(InstInfo.Operands[0].Rec); - - // The rest are inputs. - for (unsigned j = 1, e = InstInfo.Operands.size(); j < e; ++j) - Operands.push_back(InstInfo.Operands[j].Rec); - } - } + return false; +} - // Create and insert the instruction. - std::vector ImpResults; - Instructions.insert(std::make_pair(Instrs[i], - DAGInstruction(0, Results, Operands, ImpResults))); - continue; // no pattern. - } +const DAGInstruction &CodeGenDAGPatterns::parseInstructionPattern( + CodeGenInstruction &CGI, ListInit *Pat, DAGInstMap &DAGInsts) { - // Parse the instruction. - TreePattern *I = new TreePattern(Instrs[i], LI, true, *this); - // Inline pattern fragments into it. - I->InlinePatternFragments(); + assert(!DAGInsts.count(CGI.TheDef) && "Instruction already parsed!"); - // Infer as many types as possible. If we cannot infer all of them, we can - // never do anything with this instruction pattern: report it to the user. - if (!I->InferAllTypes()) - I->error("Could not infer all types in pattern!"); + // Parse the instruction. + TreePattern *I = new TreePattern(CGI.TheDef, Pat, true, *this); + // Inline pattern fragments into it. + I->InlinePatternFragments(); - // InstInputs - Keep track of all of the inputs of the instruction, along - // with the record they are declared as. - std::map InstInputs; + // Infer as many types as possible. If we cannot infer all of them, we can + // never do anything with this instruction pattern: report it to the user. + if (!I->InferAllTypes()) + I->error("Could not infer all types in pattern!"); - // InstResults - Keep track of all the virtual registers that are 'set' - // in the instruction, including what reg class they are. - std::map InstResults; + // InstInputs - Keep track of all of the inputs of the instruction, along + // with the record they are declared as. + std::map InstInputs; - std::vector InstImpResults; + // InstResults - Keep track of all the virtual registers that are 'set' + // in the instruction, including what reg class they are. + std::map InstResults; - // Verify that the top-level forms in the instruction are of void type, and - // fill in the InstResults map. - for (unsigned j = 0, e = I->getNumTrees(); j != e; ++j) { - TreePatternNode *Pat = I->getTree(j); - if (Pat->getNumTypes() != 0) - I->error("Top-level forms in instruction pattern should have" - " void types"); + std::vector InstImpResults; - // Find inputs and outputs, and verify the structure of the uses/defs. - FindPatternInputsAndOutputs(I, Pat, InstInputs, InstResults, - InstImpResults); - } + // Verify that the top-level forms in the instruction are of void type, and + // fill in the InstResults map. + for (unsigned j = 0, e = I->getNumTrees(); j != e; ++j) { + TreePatternNode *Pat = I->getTree(j); + if (Pat->getNumTypes() != 0) + I->error("Top-level forms in instruction pattern should have" + " void types"); - // Now that we have inputs and outputs of the pattern, inspect the operands - // list for the instruction. This determines the order that operands are - // added to the machine instruction the node corresponds to. - unsigned NumResults = InstResults.size(); + // Find inputs and outputs, and verify the structure of the uses/defs. + FindPatternInputsAndOutputs(I, Pat, InstInputs, InstResults, + InstImpResults); + } - // Parse the operands list from the (ops) list, validating it. - assert(I->getArgList().empty() && "Args list should still be empty here!"); - CodeGenInstruction &CGI = Target.getInstruction(Instrs[i]); + // Now that we have inputs and outputs of the pattern, inspect the operands + // list for the instruction. This determines the order that operands are + // added to the machine instruction the node corresponds to. + unsigned NumResults = InstResults.size(); - // Check that all of the results occur first in the list. - std::vector Results; - TreePatternNode *Res0Node = 0; - for (unsigned i = 0; i != NumResults; ++i) { - if (i == CGI.Operands.size()) - I->error("'" + InstResults.begin()->first + - "' set but does not appear in operand list!"); - const std::string &OpName = CGI.Operands[i].Name; + // Parse the operands list from the (ops) list, validating it. + assert(I->getArgList().empty() && "Args list should still be empty here!"); - // Check that it exists in InstResults. - TreePatternNode *RNode = InstResults[OpName]; - if (RNode == 0) - I->error("Operand $" + OpName + " does not exist in operand list!"); + // Check that all of the results occur first in the list. + std::vector Results; + SmallVector ResNodes; + for (unsigned i = 0; i != NumResults; ++i) { + if (i == CGI.Operands.size()) + I->error("'" + InstResults.begin()->first + + "' set but does not appear in operand list!"); + const std::string &OpName = CGI.Operands[i].Name; - if (i == 0) - Res0Node = RNode; - Record *R = dynamic_cast(RNode->getLeafValue())->getDef(); - if (R == 0) - I->error("Operand $" + OpName + " should be a set destination: all " - "outputs must occur before inputs in operand list!"); + // Check that it exists in InstResults. + TreePatternNode *RNode = InstResults[OpName]; + if (!RNode) + I->error("Operand $" + OpName + " does not exist in operand list!"); - if (CGI.Operands[i].Rec != R) - I->error("Operand $" + OpName + " class mismatch!"); + ResNodes.push_back(RNode); - // Remember the return type. - Results.push_back(CGI.Operands[i].Rec); + Record *R = cast(RNode->getLeafValue())->getDef(); + if (!R) + I->error("Operand $" + OpName + " should be a set destination: all " + "outputs must occur before inputs in operand list!"); - // Okay, this one checks out. - InstResults.erase(OpName); - } + if (!checkOperandClass(CGI.Operands[i], R)) + I->error("Operand $" + OpName + " class mismatch!"); - // Loop over the inputs next. Make a copy of InstInputs so we can destroy - // the copy while we're checking the inputs. - std::map InstInputsCheck(InstInputs); + // Remember the return type. + Results.push_back(CGI.Operands[i].Rec); - std::vector ResultNodeOperands; - std::vector Operands; - for (unsigned i = NumResults, e = CGI.Operands.size(); i != e; ++i) { - CGIOperandList::OperandInfo &Op = CGI.Operands[i]; - const std::string &OpName = Op.Name; - if (OpName.empty()) - I->error("Operand #" + utostr(i) + " in operands list has no name!"); - - if (!InstInputsCheck.count(OpName)) { - // If this is an predicate operand or optional def operand with an - // DefaultOps set filled in, we can ignore this. When we codegen it, - // we will do so as always executed. - if (Op.Rec->isSubClassOf("PredicateOperand") || - Op.Rec->isSubClassOf("OptionalDefOperand")) { - // Does it have a non-empty DefaultOps field? If so, ignore this - // operand. - if (!getDefaultOperand(Op.Rec).DefaultOps.empty()) - continue; - } - I->error("Operand $" + OpName + - " does not appear in the instruction pattern"); - } - TreePatternNode *InVal = InstInputsCheck[OpName]; - InstInputsCheck.erase(OpName); // It occurred, remove from map. - - if (InVal->isLeaf() && - dynamic_cast(InVal->getLeafValue())) { - Record *InRec = static_cast(InVal->getLeafValue())->getDef(); - if (Op.Rec != InRec && !InRec->isSubClassOf("ComplexPattern")) - I->error("Operand $" + OpName + "'s register class disagrees" - " between the operand and pattern"); - } - Operands.push_back(Op.Rec); + // Okay, this one checks out. + InstResults.erase(OpName); + } - // Construct the result for the dest-pattern operand list. - TreePatternNode *OpNode = InVal->clone(); + // Loop over the inputs next. Make a copy of InstInputs so we can destroy + // the copy while we're checking the inputs. + std::map InstInputsCheck(InstInputs); - // No predicate is useful on the result. - OpNode->clearPredicateFns(); + std::vector ResultNodeOperands; + std::vector Operands; + for (unsigned i = NumResults, e = CGI.Operands.size(); i != e; ++i) { + CGIOperandList::OperandInfo &Op = CGI.Operands[i]; + const std::string &OpName = Op.Name; + if (OpName.empty()) + I->error("Operand #" + utostr(i) + " in operands list has no name!"); - // Promote the xform function to be an explicit node if set. - if (Record *Xform = OpNode->getTransformFn()) { - OpNode->setTransformFn(0); - std::vector Children; - Children.push_back(OpNode); - OpNode = new TreePatternNode(Xform, Children, OpNode->getNumTypes()); + if (!InstInputsCheck.count(OpName)) { + // If this is an operand with a DefaultOps set filled in, we can ignore + // this. When we codegen it, we will do so as always executed. + if (Op.Rec->isSubClassOf("OperandWithDefaultOps")) { + // Does it have a non-empty DefaultOps field? If so, ignore this + // operand. + if (!getDefaultOperand(Op.Rec).DefaultOps.empty()) + continue; } + I->error("Operand $" + OpName + + " does not appear in the instruction pattern"); + } + TreePatternNode *InVal = InstInputsCheck[OpName]; + InstInputsCheck.erase(OpName); // It occurred, remove from map. + + if (InVal->isLeaf() && isa(InVal->getLeafValue())) { + Record *InRec = static_cast(InVal->getLeafValue())->getDef(); + if (!checkOperandClass(Op, InRec)) + I->error("Operand $" + OpName + "'s register class disagrees" + " between the operand and pattern"); + } + Operands.push_back(Op.Rec); - ResultNodeOperands.push_back(OpNode); + // Construct the result for the dest-pattern operand list. + TreePatternNode *OpNode = InVal->clone(); + + // No predicate is useful on the result. + OpNode->clearPredicateFns(); + + // Promote the xform function to be an explicit node if set. + if (Record *Xform = OpNode->getTransformFn()) { + OpNode->setTransformFn(nullptr); + std::vector Children; + Children.push_back(OpNode); + OpNode = new TreePatternNode(Xform, Children, OpNode->getNumTypes()); } - if (!InstInputsCheck.empty()) - I->error("Input operand $" + InstInputsCheck.begin()->first + - " occurs in pattern but not in operands list!"); + ResultNodeOperands.push_back(OpNode); + } + + if (!InstInputsCheck.empty()) + I->error("Input operand $" + InstInputsCheck.begin()->first + + " occurs in pattern but not in operands list!"); + + TreePatternNode *ResultPattern = + new TreePatternNode(I->getRecord(), ResultNodeOperands, + GetNumNodeResults(I->getRecord(), *this)); + // Copy fully inferred output node types to instruction result pattern. + for (unsigned i = 0; i != NumResults; ++i) { + assert(ResNodes[i]->getNumTypes() == 1 && "FIXME: Unhandled"); + ResultPattern->setType(i, ResNodes[i]->getExtType(0)); + } + + // Create and insert the instruction. + // FIXME: InstImpResults should not be part of DAGInstruction. + DAGInstruction TheInst(I, Results, Operands, InstImpResults); + DAGInsts.insert(std::make_pair(I->getRecord(), TheInst)); - TreePatternNode *ResultPattern = - new TreePatternNode(I->getRecord(), ResultNodeOperands, - GetNumNodeResults(I->getRecord(), *this)); - // Copy fully inferred output node type to instruction result pattern. - for (unsigned i = 0; i != NumResults; ++i) - ResultPattern->setType(i, Res0Node->getExtType(i)); + // Use a temporary tree pattern to infer all types and make sure that the + // constructed result is correct. This depends on the instruction already + // being inserted into the DAGInsts map. + TreePattern Temp(I->getRecord(), ResultPattern, false, *this); + Temp.InferAllTypes(&I->getNamedNodesMap()); - // Create and insert the instruction. - // FIXME: InstImpResults should not be part of DAGInstruction. - DAGInstruction TheInst(I, Results, Operands, InstImpResults); - Instructions.insert(std::make_pair(I->getRecord(), TheInst)); + DAGInstruction &TheInsertedInst = DAGInsts.find(I->getRecord())->second; + TheInsertedInst.setResultPattern(Temp.getOnlyTree()); - // Use a temporary tree pattern to infer all types and make sure that the - // constructed result is correct. This depends on the instruction already - // being inserted into the Instructions map. - TreePattern Temp(I->getRecord(), ResultPattern, false, *this); - Temp.InferAllTypes(&I->getNamedNodesMap()); + return TheInsertedInst; +} + +/// ParseInstructions - Parse all of the instructions, inlining and resolving +/// any fragments involved. This populates the Instructions list with fully +/// resolved instructions. +void CodeGenDAGPatterns::ParseInstructions() { + std::vector Instrs = Records.getAllDerivedDefinitions("Instruction"); + + for (Record *Instr : Instrs) { + ListInit *LI = nullptr; + + if (isa(Instr->getValueInit("Pattern"))) + LI = Instr->getValueAsListInit("Pattern"); + + // If there is no pattern, only collect minimal information about the + // instruction for its operand list. We have to assume that there is one + // result, as we have no detailed info. A pattern which references the + // null_frag operator is as-if no pattern were specified. Normally this + // is from a multiclass expansion w/ a SDPatternOperator passed in as + // null_frag. + if (!LI || LI->empty() || hasNullFragReference(LI)) { + std::vector Results; + std::vector Operands; - DAGInstruction &TheInsertedInst = Instructions.find(I->getRecord())->second; - TheInsertedInst.setResultPattern(Temp.getOnlyTree()); + CodeGenInstruction &InstInfo = Target.getInstruction(Instr); - DEBUG(I->dump()); + if (InstInfo.Operands.size() != 0) { + for (unsigned j = 0, e = InstInfo.Operands.NumDefs; j < e; ++j) + Results.push_back(InstInfo.Operands[j].Rec); + + // The rest are inputs. + for (unsigned j = InstInfo.Operands.NumDefs, + e = InstInfo.Operands.size(); j < e; ++j) + Operands.push_back(InstInfo.Operands[j].Rec); + } + + // Create and insert the instruction. + std::vector ImpResults; + Instructions.insert(std::make_pair(Instr, + DAGInstruction(nullptr, Results, Operands, ImpResults))); + continue; // no pattern. + } + + CodeGenInstruction &CGI = Target.getInstruction(Instr); + const DAGInstruction &DI = parseInstructionPattern(CGI, LI, Instructions); + + (void)DI; + DEBUG(DI.getPattern()->dump()); } // If we can, convert the instructions to be patterns that are matched! - for (std::map::iterator II = - Instructions.begin(), - E = Instructions.end(); II != E; ++II) { - DAGInstruction &TheInst = II->second; - const TreePattern *I = TheInst.getPattern(); - if (I == 0) continue; // No pattern. + for (auto &Entry : Instructions) { + DAGInstruction &TheInst = Entry.second; + TreePattern *I = TheInst.getPattern(); + if (!I) continue; // No pattern. // FIXME: Assume only the first tree is the pattern. The others are clobber // nodes. @@ -2738,7 +3099,7 @@ void CodeGenDAGPatterns::ParseInstructions() { SrcPattern = Pattern; } - Record *Instr = II->first; + Record *Instr = Entry.first; AddPatternToMatch(I, PatternToMatch(Instr, Instr->getValueAsListInit("Predicates"), @@ -2755,7 +3116,7 @@ typedef std::pair NameRecord; static void FindNames(const TreePatternNode *P, std::map &Names, - const TreePattern *PatternTop) { + TreePattern *PatternTop) { if (!P->getName().empty()) { NameRecord &Rec = Names[P->getName()]; // If this is the first instance of the name, remember the node. @@ -2772,12 +3133,15 @@ static void FindNames(const TreePatternNode *P, } } -void CodeGenDAGPatterns::AddPatternToMatch(const TreePattern *Pattern, +void CodeGenDAGPatterns::AddPatternToMatch(TreePattern *Pattern, const PatternToMatch &PTM) { // Do some sanity checking on the pattern we're about to match. std::string Reason; - if (!PTM.getSrcPattern()->canPatternMatch(Reason, *this)) - Pattern->error("Pattern can never match: " + Reason); + if (!PTM.getSrcPattern()->canPatternMatch(Reason, *this)) { + PrintWarning(Pattern->getRecord()->getLoc(), + Twine("Pattern can never match: ") + Reason); + return; + } // If the source pattern's root is a complex pattern, that complex pattern // must specify the nodes it can potentially match. @@ -2796,19 +3160,18 @@ void CodeGenDAGPatterns::AddPatternToMatch(const TreePattern *Pattern, // Scan all of the named values in the destination pattern, rejecting them if // they don't exist in the input pattern. - for (std::map::iterator - I = DstNames.begin(), E = DstNames.end(); I != E; ++I) { - if (SrcNames[I->first].first == 0) + for (const auto &Entry : DstNames) { + if (SrcNames[Entry.first].first == nullptr) Pattern->error("Pattern has input without matching name in output: $" + - I->first); + Entry.first); } // Scan all of the named values in the source pattern, rejecting them if the // name isn't used in the dest, and isn't used to tie two values together. - for (std::map::iterator - I = SrcNames.begin(), E = SrcNames.end(); I != E; ++I) - if (DstNames[I->first].first == 0 && SrcNames[I->first].second == 1) - Pattern->error("Pattern has dead named input: $" + I->first); + for (const auto &Entry : SrcNames) + if (DstNames[Entry.first].first == nullptr && + SrcNames[Entry.first].second == 1) + Pattern->error("Pattern has dead named input: $" + Entry.first); PatternsToMatch.push_back(PTM); } @@ -2818,25 +3181,147 @@ void CodeGenDAGPatterns::AddPatternToMatch(const TreePattern *Pattern, void CodeGenDAGPatterns::InferInstructionFlags() { const std::vector &Instructions = Target.getInstructionsByEnumValue(); + + // First try to infer flags from the primary instruction pattern, if any. + SmallVector Revisit; + unsigned Errors = 0; for (unsigned i = 0, e = Instructions.size(); i != e; ++i) { CodeGenInstruction &InstInfo = const_cast(*Instructions[i]); - // Determine properties of the instruction from its pattern. - bool MayStore, MayLoad, IsBitcast, HasSideEffects, IsVariadic; - InferFromPattern(InstInfo, MayStore, MayLoad, IsBitcast, - HasSideEffects, IsVariadic, *this); - InstInfo.mayStore = MayStore; - InstInfo.mayLoad = MayLoad; - InstInfo.isBitcast = IsBitcast; - InstInfo.hasSideEffects = HasSideEffects; - InstInfo.Operands.isVariadic = IsVariadic; - // Sanity checks. - if (InstInfo.isReMaterializable && InstInfo.hasSideEffects) - throw TGError(InstInfo.TheDef->getLoc(), "The instruction " + - InstInfo.TheDef->getName() + - " is rematerializable AND has unmodeled side effects?"); + // Get the primary instruction pattern. + const TreePattern *Pattern = getInstruction(InstInfo.TheDef).getPattern(); + if (!Pattern) { + if (InstInfo.hasUndefFlags()) + Revisit.push_back(&InstInfo); + continue; + } + InstAnalyzer PatInfo(*this); + PatInfo.Analyze(Pattern); + Errors += InferFromPattern(InstInfo, PatInfo, InstInfo.TheDef); + } + + // Second, look for single-instruction patterns defined outside the + // instruction. + for (ptm_iterator I = ptm_begin(), E = ptm_end(); I != E; ++I) { + const PatternToMatch &PTM = *I; + + // We can only infer from single-instruction patterns, otherwise we won't + // know which instruction should get the flags. + SmallVector PatInstrs; + getInstructionsInTree(PTM.getDstPattern(), PatInstrs); + if (PatInstrs.size() != 1) + continue; + + // Get the single instruction. + CodeGenInstruction &InstInfo = Target.getInstruction(PatInstrs.front()); + + // Only infer properties from the first pattern. We'll verify the others. + if (InstInfo.InferredFrom) + continue; + + InstAnalyzer PatInfo(*this); + PatInfo.Analyze(&PTM); + Errors += InferFromPattern(InstInfo, PatInfo, PTM.getSrcRecord()); + } + + if (Errors) + PrintFatalError("pattern conflicts"); + + // Revisit instructions with undefined flags and no pattern. + if (Target.guessInstructionProperties()) { + for (CodeGenInstruction *InstInfo : Revisit) { + if (InstInfo->InferredFrom) + continue; + // The mayLoad and mayStore flags default to false. + // Conservatively assume hasSideEffects if it wasn't explicit. + if (InstInfo->hasSideEffects_Unset) + InstInfo->hasSideEffects = true; + } + return; } + + // Complain about any flags that are still undefined. + for (CodeGenInstruction *InstInfo : Revisit) { + if (InstInfo->InferredFrom) + continue; + if (InstInfo->hasSideEffects_Unset) + PrintError(InstInfo->TheDef->getLoc(), + "Can't infer hasSideEffects from patterns"); + if (InstInfo->mayStore_Unset) + PrintError(InstInfo->TheDef->getLoc(), + "Can't infer mayStore from patterns"); + if (InstInfo->mayLoad_Unset) + PrintError(InstInfo->TheDef->getLoc(), + "Can't infer mayLoad from patterns"); + } +} + + +/// Verify instruction flags against pattern node properties. +void CodeGenDAGPatterns::VerifyInstructionFlags() { + unsigned Errors = 0; + for (ptm_iterator I = ptm_begin(), E = ptm_end(); I != E; ++I) { + const PatternToMatch &PTM = *I; + SmallVector Instrs; + getInstructionsInTree(PTM.getDstPattern(), Instrs); + if (Instrs.empty()) + continue; + + // Count the number of instructions with each flag set. + unsigned NumSideEffects = 0; + unsigned NumStores = 0; + unsigned NumLoads = 0; + for (const Record *Instr : Instrs) { + const CodeGenInstruction &InstInfo = Target.getInstruction(Instr); + NumSideEffects += InstInfo.hasSideEffects; + NumStores += InstInfo.mayStore; + NumLoads += InstInfo.mayLoad; + } + + // Analyze the source pattern. + InstAnalyzer PatInfo(*this); + PatInfo.Analyze(&PTM); + + // Collect error messages. + SmallVector Msgs; + + // Check for missing flags in the output. + // Permit extra flags for now at least. + if (PatInfo.hasSideEffects && !NumSideEffects) + Msgs.push_back("pattern has side effects, but hasSideEffects isn't set"); + + // Don't verify store flags on instructions with side effects. At least for + // intrinsics, side effects implies mayStore. + if (!PatInfo.hasSideEffects && PatInfo.mayStore && !NumStores) + Msgs.push_back("pattern may store, but mayStore isn't set"); + + // Similarly, mayStore implies mayLoad on intrinsics. + if (!PatInfo.mayStore && PatInfo.mayLoad && !NumLoads) + Msgs.push_back("pattern may load, but mayLoad isn't set"); + + // Print error messages. + if (Msgs.empty()) + continue; + ++Errors; + + for (const std::string &Msg : Msgs) + PrintError(PTM.getSrcRecord()->getLoc(), Twine(Msg) + " on the " + + (Instrs.size() == 1 ? + "instruction" : "output instructions")); + // Provide the location of the relevant instruction definitions. + for (const Record *Instr : Instrs) { + if (Instr != PTM.getSrcRecord()) + PrintError(Instr->getLoc(), "defined here"); + const CodeGenInstruction &InstInfo = Target.getInstruction(Instr); + if (InstInfo.InferredFrom && + InstInfo.InferredFrom != InstInfo.TheDef && + InstInfo.InferredFrom != PTM.getSrcRecord()) + PrintError(InstInfo.InferredFrom->getLoc(), "inferred from pattern"); + } + } + if (Errors) + PrintFatalError("Errors in DAG patterns"); } /// Given a pattern result with an unresolved type, see if we can find one @@ -2871,26 +3356,30 @@ static bool ForceArbitraryInstResultType(TreePatternNode *N, TreePattern &TP) { void CodeGenDAGPatterns::ParsePatterns() { std::vector Patterns = Records.getAllDerivedDefinitions("Pattern"); - for (unsigned i = 0, e = Patterns.size(); i != e; ++i) { - Record *CurPattern = Patterns[i]; + for (Record *CurPattern : Patterns) { DagInit *Tree = CurPattern->getValueAsDag("PatternToMatch"); + + // If the pattern references the null_frag, there's nothing to do. + if (hasNullFragReference(Tree)) + continue; + TreePattern *Pattern = new TreePattern(CurPattern, Tree, true, *this); // Inline pattern fragments into it. Pattern->InlinePatternFragments(); ListInit *LI = CurPattern->getValueAsListInit("ResultInstrs"); - if (LI->getSize() == 0) continue; // no pattern. + if (LI->empty()) continue; // no pattern. // Parse the instruction. - TreePattern *Result = new TreePattern(CurPattern, LI, false, *this); + TreePattern Result(CurPattern, LI, false, *this); // Inline pattern fragments into it. - Result->InlinePatternFragments(); + Result.InlinePatternFragments(); - if (Result->getNumTrees() != 1) - Result->error("Cannot handle instructions producing instructions " - "with temporaries yet!"); + if (Result.getNumTrees() != 1) + Result.error("Cannot handle instructions producing instructions " + "with temporaries yet!"); bool IterateInference; bool InferredAllPatternTypes, InferredAllResultTypes; @@ -2903,7 +3392,7 @@ void CodeGenDAGPatterns::ParsePatterns() { // 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(&Pattern->getNamedNodesMap()); + Result.InferAllTypes(&Pattern->getNamedNodesMap()); IterateInference = false; @@ -2911,13 +3400,13 @@ void CodeGenDAGPatterns::ParsePatterns() { // resolve cases where the input type is known to be a pointer type (which // is considered resolved), but the result knows it needs to be 32- or // 64-bits. Infer the other way for good measure. - for (unsigned i = 0, e = std::min(Result->getTree(0)->getNumTypes(), + for (unsigned i = 0, e = std::min(Result.getTree(0)->getNumTypes(), Pattern->getTree(0)->getNumTypes()); i != e; ++i) { - IterateInference = Pattern->getTree(0)-> - UpdateNodeType(i, Result->getTree(0)->getExtType(i), *Result); - IterateInference |= Result->getTree(0)-> - UpdateNodeType(i, Pattern->getTree(0)->getExtType(i), *Result); + IterateInference = Pattern->getTree(0)->UpdateNodeType( + i, Result.getTree(0)->getExtType(i), Result); + IterateInference |= Result.getTree(0)->UpdateNodeType( + i, Pattern->getTree(0)->getExtType(i), Result); } // If our iteration has converged and the input pattern's types are fully @@ -2931,8 +3420,8 @@ void CodeGenDAGPatterns::ParsePatterns() { // arbitrary types to the result pattern's nodes. if (!IterateInference && InferredAllPatternTypes && !InferredAllResultTypes) - IterateInference = ForceArbitraryInstResultType(Result->getTree(0), - *Result); + IterateInference = + ForceArbitraryInstResultType(Result.getTree(0), Result); } while (IterateInference); // Verify that we inferred enough types that we can do something with the @@ -2941,7 +3430,7 @@ void CodeGenDAGPatterns::ParsePatterns() { Pattern->error("Could not infer all types in pattern!"); if (!InferredAllResultTypes) { Pattern->dump(); - Result->error("Could not infer all types in pattern result!"); + Result.error("Could not infer all types in pattern result!"); } // Validate that the input pattern is correct. @@ -2954,28 +3443,28 @@ void CodeGenDAGPatterns::ParsePatterns() { InstImpResults); // Promote the xform function to be an explicit node if set. - TreePatternNode *DstPattern = Result->getOnlyTree(); + TreePatternNode *DstPattern = Result.getOnlyTree(); std::vector ResultNodeOperands; for (unsigned ii = 0, ee = DstPattern->getNumChildren(); ii != ee; ++ii) { TreePatternNode *OpNode = DstPattern->getChild(ii); if (Record *Xform = OpNode->getTransformFn()) { - OpNode->setTransformFn(0); + OpNode->setTransformFn(nullptr); std::vector Children; Children.push_back(OpNode); OpNode = new TreePatternNode(Xform, Children, OpNode->getNumTypes()); } ResultNodeOperands.push_back(OpNode); } - DstPattern = Result->getOnlyTree(); + DstPattern = Result.getOnlyTree(); if (!DstPattern->isLeaf()) DstPattern = new TreePatternNode(DstPattern->getOperator(), ResultNodeOperands, DstPattern->getNumTypes()); - for (unsigned i = 0, e = Result->getOnlyTree()->getNumTypes(); i != e; ++i) - DstPattern->setType(i, Result->getOnlyTree()->getExtType(i)); + for (unsigned i = 0, e = Result.getOnlyTree()->getNumTypes(); i != e; ++i) + DstPattern->setType(i, Result.getOnlyTree()->getExtType(i)); - TreePattern Temp(Result->getRecord(), DstPattern, false, *this); + TreePattern Temp(Result.getRecord(), DstPattern, false, *this); Temp.InferAllTypes(); @@ -2997,8 +3486,8 @@ static void CombineChildVariants(TreePatternNode *Orig, CodeGenDAGPatterns &CDP, const MultipleUseVarSet &DepVars) { // Make sure that each operand has at least one variant to choose from. - for (unsigned i = 0, e = ChildVariants.size(); i != e; ++i) - if (ChildVariants[i].empty()) + for (const auto &Variants : ChildVariants) + if (Variants.empty()) return; // The end result is an all-pairs construction of the resultant pattern. @@ -3009,8 +3498,8 @@ static void CombineChildVariants(TreePatternNode *Orig, #ifndef NDEBUG DEBUG(if (!Idxs.empty()) { errs() << Orig->getOperator()->getName() << ": Idxs = [ "; - for (unsigned i = 0; i < Idxs.size(); ++i) { - errs() << Idxs[i] << " "; + for (unsigned Idx : Idxs) { + errs() << Idx << " "; } errs() << "]\n"; }); @@ -3019,8 +3508,8 @@ static void CombineChildVariants(TreePatternNode *Orig, std::vector NewChildren; for (unsigned i = 0, e = ChildVariants.size(); i != e; ++i) NewChildren.push_back(ChildVariants[i][Idxs[i]]); - TreePatternNode *R = new TreePatternNode(Orig->getOperator(), NewChildren, - Orig->getNumTypes()); + auto R = llvm::make_unique( + Orig->getOperator(), NewChildren, Orig->getNumTypes()); // Copy over properties. R->setName(Orig->getName()); @@ -3031,29 +3520,19 @@ static void CombineChildVariants(TreePatternNode *Orig, // If this pattern cannot match, do not include it as a variant. std::string ErrString; - if (!R->canPatternMatch(ErrString, CDP)) { - delete R; - } else { - bool AlreadyExists = false; - - // Scan to see if this pattern has already been emitted. We can get - // duplication due to things like commuting: - // (and GPRC:$a, GPRC:$b) -> (and GPRC:$b, GPRC:$a) - // which are the same pattern. Ignore the dups. - for (unsigned i = 0, e = OutVariants.size(); i != e; ++i) - if (R->isIsomorphicTo(OutVariants[i], DepVars)) { - AlreadyExists = true; - break; - } - - if (AlreadyExists) - delete R; - else - OutVariants.push_back(R); - } + // Scan to see if this pattern has already been emitted. We can get + // duplication due to things like commuting: + // (and GPRC:$a, GPRC:$b) -> (and GPRC:$b, GPRC:$a) + // which are the same pattern. Ignore the dups. + if (R->canPatternMatch(ErrString, CDP) && + std::none_of(OutVariants.begin(), OutVariants.end(), + [&](TreePatternNode *Variant) { + return R->isIsomorphicTo(Variant, DepVars); + })) + OutVariants.push_back(R.release()); // Increment indices to the next permutation by incrementing the - // indicies from last index backward, e.g., generate the sequence + // indices from last index backward, e.g., generate the sequence // [0, 0], [0, 1], [1, 0], [1, 1]. int IdxsIdx; for (IdxsIdx = Idxs.size() - 1; IdxsIdx >= 0; --IdxsIdx) { @@ -3111,8 +3590,8 @@ static void GenerateVariantsOf(TreePatternNode *N, std::vector &OutVariants, CodeGenDAGPatterns &CDP, const MultipleUseVarSet &DepVars) { - // We cannot permute leaves. - if (N->isLeaf()) { + // We cannot permute leaves or ComplexPattern uses. + if (N->isLeaf() || N->getOperator()->isSubClassOf("ComplexPattern")) { OutVariants.push_back(N); return; } @@ -3191,7 +3670,7 @@ static void GenerateVariantsOf(TreePatternNode *N, for (unsigned i = 0, e = N->getNumChildren(); i != e; ++i) { TreePatternNode *Child = N->getChild(i); if (Child->isLeaf()) - if (DefInit *DI = dynamic_cast(Child->getLeafValue())) { + if (DefInit *DI = dyn_cast(Child->getLeafValue())) { Record *RR = DI->getDef(); if (RR->isSubClassOf("Register")) continue; @@ -3204,7 +3683,7 @@ static void GenerateVariantsOf(TreePatternNode *N, // operands are the commutative operands, and there might be more operands // after those. assert(NC >= 3 && - "Commutative intrinsic should have at least 3 childrean!"); + "Commutative intrinsic should have at least 3 children!"); std::vector > Variants; Variants.push_back(ChildVariants[0]); // Intrinsic id. Variants.push_back(ChildVariants[2]); @@ -3279,16 +3758,13 @@ void CodeGenDAGPatterns::GenerateVariants() { if (AlreadyExists) continue; // Otherwise, add it to the list of patterns we have. - PatternsToMatch. - push_back(PatternToMatch(PatternsToMatch[i].getSrcRecord(), - PatternsToMatch[i].getPredicates(), - Variant, PatternsToMatch[i].getDstPattern(), - PatternsToMatch[i].getDstRegs(), - PatternsToMatch[i].getAddedComplexity(), - Record::getNewUID())); + PatternsToMatch.emplace_back( + PatternsToMatch[i].getSrcRecord(), PatternsToMatch[i].getPredicates(), + Variant, PatternsToMatch[i].getDstPattern(), + PatternsToMatch[i].getDstRegs(), + PatternsToMatch[i].getAddedComplexity(), Record::getNewUID()); } DEBUG(errs() << "\n"); } } -