Index: llvm/trunk/include/llvm/Target/TargetSelectionDAG.td =================================================================== --- llvm/trunk/include/llvm/Target/TargetSelectionDAG.td +++ llvm/trunk/include/llvm/Target/TargetSelectionDAG.td @@ -649,6 +649,39 @@ code PredicateCode = pred; code ImmediateCode = [{}]; SDNodeXForm OperandTransform = xform; + + // Define a few pre-packaged predicates. This helps GlobalISel import + // existing rules from SelectionDAG for many common cases. + // They will be tested prior to the code in pred and must not be used in + // ImmLeaf and its subclasses. + + // Is the desired pre-packaged predicate for a load? + bit IsLoad = ?; + // Is the desired pre-packaged predicate for a store? + bit IsStore = ?; + + // cast(N)->getAddressingMode() == ISD::UNINDEXED; + // cast(N)->getAddressingMode() == ISD::UNINDEXED; + bit IsUnindexed = ?; + + // cast(N)->getExtensionType() != ISD::NON_EXTLOAD + bit IsNonExtLoad = ?; + // cast(N)->getExtensionType() == ISD::EXTLOAD; + bit IsAnyExtLoad = ?; + // cast(N)->getExtensionType() == ISD::SEXTLOAD; + bit IsSignExtLoad = ?; + // cast(N)->getExtensionType() == ISD::ZEXTLOAD; + bit IsZeroExtLoad = ?; + // !cast(N)->isTruncatingStore(); + // cast(N)->isTruncatingStore(); + bit IsTruncStore = ?; + + // cast(N)->getMemoryVT() == MVT::; + // cast(N)->getMemoryVT() == MVT::; + ValueType MemoryVT = ?; + // cast(N)->getMemoryVT().getScalarType() == MVT::; + // cast(N)->getMemoryVT().getScalarType() == MVT::; + ValueType ScalarMemoryVT = ?; } // OutPatFrag is a pattern fragment that is used as part of an output pattern @@ -739,170 +772,215 @@ def null_frag : SDPatternOperator; // load fragments. -def unindexedload : PatFrag<(ops node:$ptr), (ld node:$ptr), [{ - return cast(N)->getAddressingMode() == ISD::UNINDEXED; -}]>; -def load : PatFrag<(ops node:$ptr), (unindexedload node:$ptr), [{ - return cast(N)->getExtensionType() == ISD::NON_EXTLOAD; -}]>; +def unindexedload : PatFrag<(ops node:$ptr), (ld node:$ptr)> { + let IsLoad = 1; + let IsUnindexed = 1; +} +def load : PatFrag<(ops node:$ptr), (unindexedload node:$ptr)> { + let IsLoad = 1; + let IsNonExtLoad = 1; +} // extending load fragments. -def extload : PatFrag<(ops node:$ptr), (unindexedload node:$ptr), [{ - return cast(N)->getExtensionType() == ISD::EXTLOAD; -}]>; -def sextload : PatFrag<(ops node:$ptr), (unindexedload node:$ptr), [{ - return cast(N)->getExtensionType() == ISD::SEXTLOAD; -}]>; -def zextload : PatFrag<(ops node:$ptr), (unindexedload node:$ptr), [{ - return cast(N)->getExtensionType() == ISD::ZEXTLOAD; -}]>; +def extload : PatFrag<(ops node:$ptr), (unindexedload node:$ptr)> { + let IsLoad = 1; + let IsAnyExtLoad = 1; +} +def sextload : PatFrag<(ops node:$ptr), (unindexedload node:$ptr)> { + let IsLoad = 1; + let IsSignExtLoad = 1; +} +def zextload : PatFrag<(ops node:$ptr), (unindexedload node:$ptr)> { + let IsLoad = 1; + let IsZeroExtLoad = 1; +} -def extloadi1 : PatFrag<(ops node:$ptr), (extload node:$ptr), [{ - return cast(N)->getMemoryVT() == MVT::i1; -}]>; -def extloadi8 : PatFrag<(ops node:$ptr), (extload node:$ptr), [{ - return cast(N)->getMemoryVT() == MVT::i8; -}]>; -def extloadi16 : PatFrag<(ops node:$ptr), (extload node:$ptr), [{ - return cast(N)->getMemoryVT() == MVT::i16; -}]>; -def extloadi32 : PatFrag<(ops node:$ptr), (extload node:$ptr), [{ - return cast(N)->getMemoryVT() == MVT::i32; -}]>; -def extloadf32 : PatFrag<(ops node:$ptr), (extload node:$ptr), [{ - return cast(N)->getMemoryVT() == MVT::f32; -}]>; -def extloadf64 : PatFrag<(ops node:$ptr), (extload node:$ptr), [{ - return cast(N)->getMemoryVT() == MVT::f64; -}]>; +def extloadi1 : PatFrag<(ops node:$ptr), (extload node:$ptr)> { + let IsLoad = 1; + let MemoryVT = i1; +} +def extloadi8 : PatFrag<(ops node:$ptr), (extload node:$ptr)> { + let IsLoad = 1; + let MemoryVT = i8; +} +def extloadi16 : PatFrag<(ops node:$ptr), (extload node:$ptr)> { + let IsLoad = 1; + let MemoryVT = i16; +} +def extloadi32 : PatFrag<(ops node:$ptr), (extload node:$ptr)> { + let IsLoad = 1; + let MemoryVT = i32; +} +def extloadf32 : PatFrag<(ops node:$ptr), (extload node:$ptr)> { + let IsLoad = 1; + let MemoryVT = f32; +} +def extloadf64 : PatFrag<(ops node:$ptr), (extload node:$ptr)> { + let IsLoad = 1; + let MemoryVT = f64; +} -def sextloadi1 : PatFrag<(ops node:$ptr), (sextload node:$ptr), [{ - return cast(N)->getMemoryVT() == MVT::i1; -}]>; -def sextloadi8 : PatFrag<(ops node:$ptr), (sextload node:$ptr), [{ - return cast(N)->getMemoryVT() == MVT::i8; -}]>; -def sextloadi16 : PatFrag<(ops node:$ptr), (sextload node:$ptr), [{ - return cast(N)->getMemoryVT() == MVT::i16; -}]>; -def sextloadi32 : PatFrag<(ops node:$ptr), (sextload node:$ptr), [{ - return cast(N)->getMemoryVT() == MVT::i32; -}]>; +def sextloadi1 : PatFrag<(ops node:$ptr), (sextload node:$ptr)> { + let IsLoad = 1; + let MemoryVT = i1; +} +def sextloadi8 : PatFrag<(ops node:$ptr), (sextload node:$ptr)> { + let IsLoad = 1; + let MemoryVT = i8; +} +def sextloadi16 : PatFrag<(ops node:$ptr), (sextload node:$ptr)> { + let IsLoad = 1; + let MemoryVT = i16; +} +def sextloadi32 : PatFrag<(ops node:$ptr), (sextload node:$ptr)> { + let IsLoad = 1; + let MemoryVT = i32; +} -def zextloadi1 : PatFrag<(ops node:$ptr), (zextload node:$ptr), [{ - return cast(N)->getMemoryVT() == MVT::i1; -}]>; -def zextloadi8 : PatFrag<(ops node:$ptr), (zextload node:$ptr), [{ - return cast(N)->getMemoryVT() == MVT::i8; -}]>; -def zextloadi16 : PatFrag<(ops node:$ptr), (zextload node:$ptr), [{ - return cast(N)->getMemoryVT() == MVT::i16; -}]>; -def zextloadi32 : PatFrag<(ops node:$ptr), (zextload node:$ptr), [{ - return cast(N)->getMemoryVT() == MVT::i32; -}]>; +def zextloadi1 : PatFrag<(ops node:$ptr), (zextload node:$ptr)> { + let IsLoad = 1; + let MemoryVT = i1; +} +def zextloadi8 : PatFrag<(ops node:$ptr), (zextload node:$ptr)> { + let IsLoad = 1; + let MemoryVT = i8; +} +def zextloadi16 : PatFrag<(ops node:$ptr), (zextload node:$ptr)> { + let IsLoad = 1; + let MemoryVT = i16; +} +def zextloadi32 : PatFrag<(ops node:$ptr), (zextload node:$ptr)> { + let IsLoad = 1; + let MemoryVT = i32; +} -def extloadvi1 : PatFrag<(ops node:$ptr), (extload node:$ptr), [{ - return cast(N)->getMemoryVT().getScalarType() == MVT::i1; -}]>; -def extloadvi8 : PatFrag<(ops node:$ptr), (extload node:$ptr), [{ - return cast(N)->getMemoryVT().getScalarType() == MVT::i8; -}]>; -def extloadvi16 : PatFrag<(ops node:$ptr), (extload node:$ptr), [{ - return cast(N)->getMemoryVT().getScalarType() == MVT::i16; -}]>; -def extloadvi32 : PatFrag<(ops node:$ptr), (extload node:$ptr), [{ - return cast(N)->getMemoryVT().getScalarType() == MVT::i32; -}]>; -def extloadvf32 : PatFrag<(ops node:$ptr), (extload node:$ptr), [{ - return cast(N)->getMemoryVT().getScalarType() == MVT::f32; -}]>; -def extloadvf64 : PatFrag<(ops node:$ptr), (extload node:$ptr), [{ - return cast(N)->getMemoryVT().getScalarType() == MVT::f64; -}]>; +def extloadvi1 : PatFrag<(ops node:$ptr), (extload node:$ptr)> { + let IsLoad = 1; + let ScalarMemoryVT = i1; +} +def extloadvi8 : PatFrag<(ops node:$ptr), (extload node:$ptr)> { + let IsLoad = 1; + let ScalarMemoryVT = i8; +} +def extloadvi16 : PatFrag<(ops node:$ptr), (extload node:$ptr)> { + let IsLoad = 1; + let ScalarMemoryVT = i16; +} +def extloadvi32 : PatFrag<(ops node:$ptr), (extload node:$ptr)> { + let IsLoad = 1; + let ScalarMemoryVT = i32; +} +def extloadvf32 : PatFrag<(ops node:$ptr), (extload node:$ptr)> { + let IsLoad = 1; + let ScalarMemoryVT = f32; +} +def extloadvf64 : PatFrag<(ops node:$ptr), (extload node:$ptr)> { + let IsLoad = 1; + let ScalarMemoryVT = f64; +} -def sextloadvi1 : PatFrag<(ops node:$ptr), (sextload node:$ptr), [{ - return cast(N)->getMemoryVT().getScalarType() == MVT::i1; -}]>; -def sextloadvi8 : PatFrag<(ops node:$ptr), (sextload node:$ptr), [{ - return cast(N)->getMemoryVT().getScalarType() == MVT::i8; -}]>; -def sextloadvi16 : PatFrag<(ops node:$ptr), (sextload node:$ptr), [{ - return cast(N)->getMemoryVT().getScalarType() == MVT::i16; -}]>; -def sextloadvi32 : PatFrag<(ops node:$ptr), (sextload node:$ptr), [{ - return cast(N)->getMemoryVT().getScalarType() == MVT::i32; -}]>; +def sextloadvi1 : PatFrag<(ops node:$ptr), (sextload node:$ptr)> { + let IsLoad = 1; + let ScalarMemoryVT = i1; +} +def sextloadvi8 : PatFrag<(ops node:$ptr), (sextload node:$ptr)> { + let IsLoad = 1; + let ScalarMemoryVT = i8; +} +def sextloadvi16 : PatFrag<(ops node:$ptr), (sextload node:$ptr)> { + let IsLoad = 1; + let ScalarMemoryVT = i16; +} +def sextloadvi32 : PatFrag<(ops node:$ptr), (sextload node:$ptr)> { + let IsLoad = 1; + let ScalarMemoryVT = i32; +} -def zextloadvi1 : PatFrag<(ops node:$ptr), (zextload node:$ptr), [{ - return cast(N)->getMemoryVT().getScalarType() == MVT::i1; -}]>; -def zextloadvi8 : PatFrag<(ops node:$ptr), (zextload node:$ptr), [{ - return cast(N)->getMemoryVT().getScalarType() == MVT::i8; -}]>; -def zextloadvi16 : PatFrag<(ops node:$ptr), (zextload node:$ptr), [{ - return cast(N)->getMemoryVT().getScalarType() == MVT::i16; -}]>; -def zextloadvi32 : PatFrag<(ops node:$ptr), (zextload node:$ptr), [{ - return cast(N)->getMemoryVT().getScalarType() == MVT::i32; -}]>; +def zextloadvi1 : PatFrag<(ops node:$ptr), (zextload node:$ptr)> { + let IsLoad = 1; + let ScalarMemoryVT = i1; +} +def zextloadvi8 : PatFrag<(ops node:$ptr), (zextload node:$ptr)> { + let IsLoad = 1; + let ScalarMemoryVT = i8; +} +def zextloadvi16 : PatFrag<(ops node:$ptr), (zextload node:$ptr)> { + let IsLoad = 1; + let ScalarMemoryVT = i16; +} +def zextloadvi32 : PatFrag<(ops node:$ptr), (zextload node:$ptr)> { + let IsLoad = 1; + let ScalarMemoryVT = i32; +} // store fragments. def unindexedstore : PatFrag<(ops node:$val, node:$ptr), - (st node:$val, node:$ptr), [{ - return cast(N)->getAddressingMode() == ISD::UNINDEXED; -}]>; + (st node:$val, node:$ptr)> { + let IsStore = 1; + let IsUnindexed = 1; +} def store : PatFrag<(ops node:$val, node:$ptr), - (unindexedstore node:$val, node:$ptr), [{ - return !cast(N)->isTruncatingStore(); -}]>; + (unindexedstore node:$val, node:$ptr)> { + let IsStore = 1; + let IsTruncStore = 0; +} // truncstore fragments. def truncstore : PatFrag<(ops node:$val, node:$ptr), - (unindexedstore node:$val, node:$ptr), [{ - return cast(N)->isTruncatingStore(); -}]>; + (unindexedstore node:$val, node:$ptr)> { + let IsStore = 1; + let IsTruncStore = 1; +} def truncstorei8 : PatFrag<(ops node:$val, node:$ptr), - (truncstore node:$val, node:$ptr), [{ - return cast(N)->getMemoryVT() == MVT::i8; -}]>; + (truncstore node:$val, node:$ptr)> { + let IsStore = 1; + let MemoryVT = i8; +} def truncstorei16 : PatFrag<(ops node:$val, node:$ptr), - (truncstore node:$val, node:$ptr), [{ - return cast(N)->getMemoryVT() == MVT::i16; -}]>; + (truncstore node:$val, node:$ptr)> { + let IsStore = 1; + let MemoryVT = i16; +} def truncstorei32 : PatFrag<(ops node:$val, node:$ptr), - (truncstore node:$val, node:$ptr), [{ - return cast(N)->getMemoryVT() == MVT::i32; -}]>; + (truncstore node:$val, node:$ptr)> { + let IsStore = 1; + let MemoryVT = i32; +} def truncstoref32 : PatFrag<(ops node:$val, node:$ptr), - (truncstore node:$val, node:$ptr), [{ - return cast(N)->getMemoryVT() == MVT::f32; -}]>; + (truncstore node:$val, node:$ptr)> { + let IsStore = 1; + let MemoryVT = f32; +} def truncstoref64 : PatFrag<(ops node:$val, node:$ptr), - (truncstore node:$val, node:$ptr), [{ - return cast(N)->getMemoryVT() == MVT::f64; -}]>; + (truncstore node:$val, node:$ptr)> { + let IsStore = 1; + let MemoryVT = f64; +} def truncstorevi8 : PatFrag<(ops node:$val, node:$ptr), - (truncstore node:$val, node:$ptr), [{ - return cast(N)->getMemoryVT().getScalarType() == MVT::i8; -}]>; + (truncstore node:$val, node:$ptr)> { + let IsStore = 1; + let ScalarMemoryVT = i8; +} def truncstorevi16 : PatFrag<(ops node:$val, node:$ptr), - (truncstore node:$val, node:$ptr), [{ - return cast(N)->getMemoryVT().getScalarType() == MVT::i16; -}]>; + (truncstore node:$val, node:$ptr)> { + let IsStore = 1; + let ScalarMemoryVT = i16; +} def truncstorevi32 : PatFrag<(ops node:$val, node:$ptr), - (truncstore node:$val, node:$ptr), [{ - return cast(N)->getMemoryVT().getScalarType() == MVT::i32; -}]>; + (truncstore node:$val, node:$ptr)> { + let IsStore = 1; + let ScalarMemoryVT = i32; +} // indexed store fragments. def istore : PatFrag<(ops node:$val, node:$base, node:$offset), - (ist node:$val, node:$base, node:$offset), [{ - return !cast(N)->isTruncatingStore(); -}]>; + (ist node:$val, node:$base, node:$offset)> { + let IsStore = 1; + let IsTruncStore = 0; +} def pre_store : PatFrag<(ops node:$val, node:$base, node:$offset), (istore node:$val, node:$base, node:$offset), [{ @@ -911,34 +989,40 @@ }]>; def itruncstore : PatFrag<(ops node:$val, node:$base, node:$offset), - (ist node:$val, node:$base, node:$offset), [{ - return cast(N)->isTruncatingStore(); -}]>; + (ist node:$val, node:$base, node:$offset)> { + let IsStore = 1; + let IsTruncStore = 1; +} def pre_truncst : PatFrag<(ops node:$val, node:$base, node:$offset), (itruncstore node:$val, node:$base, node:$offset), [{ ISD::MemIndexedMode AM = cast(N)->getAddressingMode(); return AM == ISD::PRE_INC || AM == ISD::PRE_DEC; }]>; def pre_truncsti1 : PatFrag<(ops node:$val, node:$base, node:$offset), - (pre_truncst node:$val, node:$base, node:$offset), [{ - return cast(N)->getMemoryVT() == MVT::i1; -}]>; + (pre_truncst node:$val, node:$base, node:$offset)> { + let IsStore = 1; + let MemoryVT = i1; +} def pre_truncsti8 : PatFrag<(ops node:$val, node:$base, node:$offset), - (pre_truncst node:$val, node:$base, node:$offset), [{ - return cast(N)->getMemoryVT() == MVT::i8; -}]>; + (pre_truncst node:$val, node:$base, node:$offset)> { + let IsStore = 1; + let MemoryVT = i8; +} def pre_truncsti16 : PatFrag<(ops node:$val, node:$base, node:$offset), - (pre_truncst node:$val, node:$base, node:$offset), [{ - return cast(N)->getMemoryVT() == MVT::i16; -}]>; + (pre_truncst node:$val, node:$base, node:$offset)> { + let IsStore = 1; + let MemoryVT = i16; +} def pre_truncsti32 : PatFrag<(ops node:$val, node:$base, node:$offset), - (pre_truncst node:$val, node:$base, node:$offset), [{ - return cast(N)->getMemoryVT() == MVT::i32; -}]>; + (pre_truncst node:$val, node:$base, node:$offset)> { + let IsStore = 1; + let MemoryVT = i32; +} def pre_truncstf32 : PatFrag<(ops node:$val, node:$base, node:$offset), - (pre_truncst node:$val, node:$base, node:$offset), [{ - return cast(N)->getMemoryVT() == MVT::f32; -}]>; + (pre_truncst node:$val, node:$base, node:$offset)> { + let IsStore = 1; + let MemoryVT = f32; +} def post_store : PatFrag<(ops node:$val, node:$ptr, node:$offset), (istore node:$val, node:$ptr, node:$offset), [{ @@ -952,25 +1036,30 @@ return AM == ISD::POST_INC || AM == ISD::POST_DEC; }]>; def post_truncsti1 : PatFrag<(ops node:$val, node:$base, node:$offset), - (post_truncst node:$val, node:$base, node:$offset), [{ - return cast(N)->getMemoryVT() == MVT::i1; -}]>; + (post_truncst node:$val, node:$base, node:$offset)> { + let IsStore = 1; + let MemoryVT = i1; +} def post_truncsti8 : PatFrag<(ops node:$val, node:$base, node:$offset), - (post_truncst node:$val, node:$base, node:$offset), [{ - return cast(N)->getMemoryVT() == MVT::i8; -}]>; + (post_truncst node:$val, node:$base, node:$offset)> { + let IsStore = 1; + let MemoryVT = i8; +} def post_truncsti16 : PatFrag<(ops node:$val, node:$base, node:$offset), - (post_truncst node:$val, node:$base, node:$offset), [{ - return cast(N)->getMemoryVT() == MVT::i16; -}]>; + (post_truncst node:$val, node:$base, node:$offset)> { + let IsStore = 1; + let MemoryVT = i16; +} def post_truncsti32 : PatFrag<(ops node:$val, node:$base, node:$offset), - (post_truncst node:$val, node:$base, node:$offset), [{ - return cast(N)->getMemoryVT() == MVT::i32; -}]>; + (post_truncst node:$val, node:$base, node:$offset)> { + let IsStore = 1; + let MemoryVT = i32; +} def post_truncstf32 : PatFrag<(ops node:$val, node:$base, node:$offset), - (post_truncst node:$val, node:$base, node:$offset), [{ - return cast(N)->getMemoryVT() == MVT::f32; -}]>; + (post_truncst node:$val, node:$base, node:$offset)> { + let IsStore = 1; + let MemoryVT = f32; +} // nontemporal store fragments. def nontemporalstore : PatFrag<(ops node:$val, node:$ptr), Index: llvm/trunk/utils/TableGen/CodeGenDAGPatterns.h =================================================================== --- llvm/trunk/utils/TableGen/CodeGenDAGPatterns.h +++ llvm/trunk/utils/TableGen/CodeGenDAGPatterns.h @@ -452,8 +452,8 @@ /// getImmediatePredicateCode - Return the code that evaluates this pattern if /// this is an immediate predicate. It is an error to call this on a /// non-immediate pattern. - StringRef getImmediatePredicateCode() const { - StringRef Result = getImmCode(); + std::string getImmediatePredicateCode() const { + std::string Result = getImmCode(); assert(!Result.empty() && "Isn't an immediate pattern!"); return Result; } @@ -481,11 +481,42 @@ /// usable as part of an identifier. StringRef getImmTypeIdentifier() const; + // Is the desired predefined predicate for a load? + bool isLoad() const; + // Is the desired predefined predicate for a store? + bool isStore() const; + + /// Is this predicate the predefined unindexed load predicate? + /// Is this predicate the predefined unindexed store predicate? + bool isUnindexed() const; + /// Is this predicate the predefined non-extending load predicate? + bool isNonExtLoad() const; + /// Is this predicate the predefined any-extend load predicate? + bool isAnyExtLoad() const; + /// Is this predicate the predefined sign-extend load predicate? + bool isSignExtLoad() const; + /// Is this predicate the predefined zero-extend load predicate? + bool isZeroExtLoad() const; + /// Is this predicate the predefined non-truncating store predicate? + bool isNonTruncStore() const; + /// Is this predicate the predefined truncating store predicate? + bool isTruncStore() const; + + /// If non-null, indicates that this predicate is a predefined memory VT + /// predicate for a load/store and returns the ValueType record for the memory VT. + Record *getMemoryVT() const; + /// If non-null, indicates that this predicate is a predefined memory VT + /// predicate (checking only the scalar type) for load/store and returns the + /// ValueType record for the memory VT. + Record *getScalarMemoryVT() const; + private: - StringRef getPredCode() const; - StringRef getImmCode() const; + std::string getPredCode() const; + std::string getImmCode() const; bool immCodeUsesAPInt() const; bool immCodeUsesAPFloat() const; + + bool isPredefinedPredicateEqualTo(StringRef Field, bool Value) const; }; Index: llvm/trunk/utils/TableGen/CodeGenDAGPatterns.cpp =================================================================== --- llvm/trunk/utils/TableGen/CodeGenDAGPatterns.cpp +++ llvm/trunk/utils/TableGen/CodeGenDAGPatterns.cpp @@ -854,11 +854,129 @@ ".td file corrupt: can't have a node predicate *and* an imm predicate"); } -StringRef TreePredicateFn::getPredCode() const { - return PatFragRec->getRecord()->getValueAsString("PredicateCode"); +std::string TreePredicateFn::getPredCode() const { + std::string Code = ""; + + if (!isLoad() && !isStore()) { + if (isUnindexed()) + PrintFatalError(getOrigPatFragRecord()->getRecord()->getLoc(), + "IsUnindexed requires IsLoad or IsStore"); + + Record *MemoryVT = getMemoryVT(); + Record *ScalarMemoryVT = getScalarMemoryVT(); + + if (MemoryVT) + PrintFatalError(getOrigPatFragRecord()->getRecord()->getLoc(), + "MemoryVT requires IsLoad or IsStore"); + if (ScalarMemoryVT) + PrintFatalError(getOrigPatFragRecord()->getRecord()->getLoc(), + "ScalarMemoryVT requires IsLoad or IsStore"); + } + + if (isLoad() && isStore()) + PrintFatalError(getOrigPatFragRecord()->getRecord()->getLoc(), + "IsLoad and IsStore are mutually exclusive"); + + if (isLoad()) { + if (!isUnindexed() && !isNonExtLoad() && !isAnyExtLoad() && + !isSignExtLoad() && !isZeroExtLoad() && getMemoryVT() == nullptr && + getScalarMemoryVT() == nullptr) + PrintFatalError(getOrigPatFragRecord()->getRecord()->getLoc(), + "IsLoad cannot be used by itself"); + } else { + if (isNonExtLoad()) + PrintFatalError(getOrigPatFragRecord()->getRecord()->getLoc(), + "IsNonExtLoad requires IsLoad"); + if (isAnyExtLoad()) + PrintFatalError(getOrigPatFragRecord()->getRecord()->getLoc(), + "IsAnyExtLoad requires IsLoad"); + if (isSignExtLoad()) + PrintFatalError(getOrigPatFragRecord()->getRecord()->getLoc(), + "IsSignExtLoad requires IsLoad"); + if (isZeroExtLoad()) + PrintFatalError(getOrigPatFragRecord()->getRecord()->getLoc(), + "IsZeroExtLoad requires IsLoad"); + } + + if (isStore()) { + if (!isUnindexed() && !isTruncStore() && !isNonTruncStore() && + getMemoryVT() == nullptr && getScalarMemoryVT() == nullptr) + PrintFatalError(getOrigPatFragRecord()->getRecord()->getLoc(), + "IsStore cannot be used by itself"); + } else { + if (isNonTruncStore()) + PrintFatalError(getOrigPatFragRecord()->getRecord()->getLoc(), + "IsNonTruncStore requires IsStore"); + if (isTruncStore()) + PrintFatalError(getOrigPatFragRecord()->getRecord()->getLoc(), + "IsTruncStore requires IsStore"); + } + + if (isLoad() || isStore()) { + StringRef SDNodeName = isLoad() ? "LoadSDNode" : "StoreSDNode"; + + if (isUnindexed()) + Code += ("if (cast<" + SDNodeName + + ">(N)->getAddressingMode() != ISD::UNINDEXED) " + "return false;\n") + .str(); + + if (isLoad()) { + if ((isNonExtLoad() + isAnyExtLoad() + isSignExtLoad() + + isZeroExtLoad()) > 1) + PrintFatalError(getOrigPatFragRecord()->getRecord()->getLoc(), + "IsNonExtLoad, IsAnyExtLoad, IsSignExtLoad, and " + "IsZeroExtLoad are mutually exclusive"); + if (isNonExtLoad()) + Code += "if (cast(N)->getExtensionType() != " + "ISD::NON_EXTLOAD) return false;\n"; + if (isAnyExtLoad()) + Code += "if (cast(N)->getExtensionType() != ISD::EXTLOAD) " + "return false;\n"; + if (isSignExtLoad()) + Code += "if (cast(N)->getExtensionType() != ISD::SEXTLOAD) " + "return false;\n"; + if (isZeroExtLoad()) + Code += "if (cast(N)->getExtensionType() != ISD::ZEXTLOAD) " + "return false;\n"; + } else { + if ((isNonTruncStore() + isTruncStore()) > 1) + PrintFatalError( + getOrigPatFragRecord()->getRecord()->getLoc(), + "IsNonTruncStore, and IsTruncStore are mutually exclusive"); + if (isNonTruncStore()) + Code += + " if (cast(N)->isTruncatingStore()) return false;\n"; + if (isTruncStore()) + Code += + " if (!cast(N)->isTruncatingStore()) return false;\n"; + } + + Record *MemoryVT = getMemoryVT(); + Record *ScalarMemoryVT = getScalarMemoryVT(); + + if (MemoryVT) + Code += ("if (cast<" + SDNodeName + ">(N)->getMemoryVT() != MVT::" + + MemoryVT->getName() + ") return false;\n") + .str(); + if (ScalarMemoryVT) + Code += ("if (cast<" + SDNodeName + + ">(N)->getMemoryVT().getScalarType() != MVT::" + + ScalarMemoryVT->getName() + ") return false;\n") + .str(); + } + + std::string PredicateCode = PatFragRec->getRecord()->getValueAsString("PredicateCode"); + + Code += PredicateCode; + + if (PredicateCode.empty() && !Code.empty()) + Code += "return true;\n"; + + return Code; } -StringRef TreePredicateFn::getImmCode() const { +std::string TreePredicateFn::getImmCode() const { return PatFragRec->getRecord()->getValueAsString("ImmediateCode"); } @@ -873,6 +991,55 @@ Unset); } +bool TreePredicateFn::isPredefinedPredicateEqualTo(StringRef Field, + bool Value) const { + bool Unset; + bool Result = + getOrigPatFragRecord()->getRecord()->getValueAsBitOrUnset(Field, Unset); + if (Unset) + return false; + return Result == Value; +} +bool TreePredicateFn::isLoad() const { + return isPredefinedPredicateEqualTo("IsLoad", true); +} +bool TreePredicateFn::isStore() const { + return isPredefinedPredicateEqualTo("IsStore", true); +} +bool TreePredicateFn::isUnindexed() const { + return isPredefinedPredicateEqualTo("IsUnindexed", true); +} +bool TreePredicateFn::isNonExtLoad() const { + return isPredefinedPredicateEqualTo("IsNonExtLoad", true); +} +bool TreePredicateFn::isAnyExtLoad() const { + return isPredefinedPredicateEqualTo("IsAnyExtLoad", true); +} +bool TreePredicateFn::isSignExtLoad() const { + return isPredefinedPredicateEqualTo("IsSignExtLoad", true); +} +bool TreePredicateFn::isZeroExtLoad() const { + return isPredefinedPredicateEqualTo("IsZeroExtLoad", true); +} +bool TreePredicateFn::isNonTruncStore() const { + return isPredefinedPredicateEqualTo("IsTruncStore", false); +} +bool TreePredicateFn::isTruncStore() const { + return isPredefinedPredicateEqualTo("IsTruncStore", true); +} +Record *TreePredicateFn::getMemoryVT() const { + Record *R = getOrigPatFragRecord()->getRecord(); + if (R->isValueUnset("MemoryVT")) + return nullptr; + return R->getValueAsDef("MemoryVT"); +} +Record *TreePredicateFn::getScalarMemoryVT() const { + Record *R = getOrigPatFragRecord()->getRecord(); + if (R->isValueUnset("ScalarMemoryVT")) + return nullptr; + return R->getValueAsDef("ScalarMemoryVT"); +} + StringRef TreePredicateFn::getImmType() const { if (immCodeUsesAPInt()) return "const APInt &"; @@ -906,16 +1073,58 @@ /// appropriate. std::string TreePredicateFn::getCodeToRunOnSDNode() const { // Handle immediate predicates first. - StringRef ImmCode = getImmCode(); + std::string ImmCode = getImmCode(); if (!ImmCode.empty()) { - std::string Result = " " + getImmType().str() + " Imm = "; + if (isLoad()) + PrintFatalError(getOrigPatFragRecord()->getRecord()->getLoc(), + "IsLoad cannot be used with ImmLeaf or its subclasses"); + if (isStore()) + PrintFatalError(getOrigPatFragRecord()->getRecord()->getLoc(), + "IsStore cannot be used with ImmLeaf or its subclasses"); + if (isUnindexed()) + PrintFatalError( + getOrigPatFragRecord()->getRecord()->getLoc(), + "IsUnindexed cannot be used with ImmLeaf or its subclasses"); + if (isNonExtLoad()) + PrintFatalError( + getOrigPatFragRecord()->getRecord()->getLoc(), + "IsNonExtLoad cannot be used with ImmLeaf or its subclasses"); + if (isAnyExtLoad()) + PrintFatalError( + getOrigPatFragRecord()->getRecord()->getLoc(), + "IsAnyExtLoad cannot be used with ImmLeaf or its subclasses"); + if (isSignExtLoad()) + PrintFatalError( + getOrigPatFragRecord()->getRecord()->getLoc(), + "IsSignExtLoad cannot be used with ImmLeaf or its subclasses"); + if (isZeroExtLoad()) + PrintFatalError( + getOrigPatFragRecord()->getRecord()->getLoc(), + "IsZeroExtLoad cannot be used with ImmLeaf or its subclasses"); + if (isNonTruncStore()) + PrintFatalError( + getOrigPatFragRecord()->getRecord()->getLoc(), + "IsNonTruncStore cannot be used with ImmLeaf or its subclasses"); + if (isTruncStore()) + PrintFatalError( + getOrigPatFragRecord()->getRecord()->getLoc(), + "IsTruncStore cannot be used with ImmLeaf or its subclasses"); + if (getMemoryVT()) + PrintFatalError(getOrigPatFragRecord()->getRecord()->getLoc(), + "MemoryVT cannot be used with ImmLeaf or its subclasses"); + if (getScalarMemoryVT()) + PrintFatalError( + getOrigPatFragRecord()->getRecord()->getLoc(), + "ScalarMemoryVT cannot be used with ImmLeaf or its subclasses"); + + std::string Result = (" " + getImmType() + " Imm = ").str(); if (immCodeUsesAPFloat()) Result += "cast(Node)->getValueAPF();\n"; else if (immCodeUsesAPInt()) Result += "cast(Node)->getAPIntValue();\n"; else Result += "cast(Node)->getSExtValue();\n"; - return Result + ImmCode.str(); + return Result + ImmCode; } // Handle arbitrary node predicates. @@ -933,7 +1142,7 @@ else Result = " auto *N = cast<" + ClassName.str() + ">(Node);\n"; - return Result + getPredCode().str(); + return Result + getPredCode(); } //===----------------------------------------------------------------------===// Index: llvm/trunk/utils/TableGen/GlobalISelEmitter.cpp =================================================================== --- llvm/trunk/utils/TableGen/GlobalISelEmitter.cpp +++ llvm/trunk/utils/TableGen/GlobalISelEmitter.cpp @@ -170,6 +170,28 @@ Explanation += " always-true"; if (P.isImmediatePattern()) Explanation += " immediate"; + + if (P.isUnindexed()) + Explanation += " unindexed"; + + if (P.isNonExtLoad()) + Explanation += " non-extload"; + if (P.isAnyExtLoad()) + Explanation += " extload"; + if (P.isSignExtLoad()) + Explanation += " sextload"; + if (P.isZeroExtLoad()) + Explanation += " zextload"; + + if (P.isNonTruncStore()) + Explanation += " non-truncstore"; + if (P.isTruncStore()) + Explanation += " truncstore"; + + if (Record *VT = P.getMemoryVT()) + Explanation += (" MemVT=" + VT->getName()).str(); + if (Record *VT = P.getScalarMemoryVT()) + Explanation += (" ScalarVT(MemVT)=" + VT->getName()).str(); } return Explanation; } @@ -204,6 +226,9 @@ HasUnsupportedPredicate = true; Explanation = Separator + "Has a predicate (" + explainPredicates(N) + ")"; Separator = ", "; + Explanation += (Separator + "first-failing:" + + Predicate.getOrigPatFragRecord()->getRecord()->getName()) + .str(); break; }