diff options
-rw-r--r-- | include/llvm/DerivedTypes.h | 20 | ||||
-rw-r--r-- | include/llvm/Intrinsics.td | 7 | ||||
-rw-r--r-- | lib/VMCore/Verifier.cpp | 28 | ||||
-rw-r--r-- | utils/TableGen/CodeGenTarget.cpp | 28 | ||||
-rw-r--r-- | utils/TableGen/IntrinsicEmitter.cpp | 23 |
5 files changed, 100 insertions, 6 deletions
diff --git a/include/llvm/DerivedTypes.h b/include/llvm/DerivedTypes.h index 04a73fe..3bc00e9 100644 --- a/include/llvm/DerivedTypes.h +++ b/include/llvm/DerivedTypes.h @@ -369,6 +369,26 @@ public: return VectorType::get(EltTy, VTy->getNumElements()); } + /// VectorType::getExtendedElementVectorType - This static method is like + /// getInteger except that the element types are twice as wide as the + /// elements in the input type. + /// + static VectorType *getExtendedElementVectorType(const VectorType *VTy) { + unsigned EltBits = VTy->getElementType()->getPrimitiveSizeInBits(); + const Type *EltTy = IntegerType::get(EltBits * 2); + return VectorType::get(EltTy, VTy->getNumElements()); + } + + /// VectorType::getTruncatedElementVectorType - This static method is like + /// getInteger except that the element types are half as wide as the + /// elements in the input type. + /// + static VectorType *getTruncatedElementVectorType(const VectorType *VTy) { + unsigned EltBits = VTy->getElementType()->getPrimitiveSizeInBits(); + const Type *EltTy = IntegerType::get(EltBits / 2); + return VectorType::get(EltTy, VTy->getNumElements()); + } + /// @brief Return the number of elements in the Vector type. inline unsigned getNumElements() const { return NumElements; } diff --git a/include/llvm/Intrinsics.td b/include/llvm/Intrinsics.td index 154106e..a641caa 100644 --- a/include/llvm/Intrinsics.td +++ b/include/llvm/Intrinsics.td @@ -74,6 +74,13 @@ class LLVMMatchType<int num> int Number = num; } +// Match the type of another intrinsic parameter that is expected to be +// an integral vector type, but change the element size to be twice as wide +// or half as wide as the other type. This is only useful when the intrinsic +// is overloaded, so the matched type should be declared as iAny. +class LLVMExtendedElementVectorType<int num> : LLVMMatchType<num>; +class LLVMTruncatedElementVectorType<int num> : LLVMMatchType<num>; + def llvm_void_ty : LLVMType<isVoid>; def llvm_anyint_ty : LLVMType<iAny>; def llvm_anyfloat_ty : LLVMType<fAny>; diff --git a/lib/VMCore/Verifier.cpp b/lib/VMCore/Verifier.cpp index 5920773..4a79154 100644 --- a/lib/VMCore/Verifier.cpp +++ b/lib/VMCore/Verifier.cpp @@ -1313,6 +1313,11 @@ void Verifier::visitInstruction(Instruction &I) { InstsInThisBlock.insert(&I); } +// Flags used by TableGen to mark intrinsic parameters with the +// LLVMExtendedElementVectorType and LLVMTruncatedElementVectorType classes. +static const unsigned ExtendedElementVectorType = 0x40000000; +static const unsigned TruncatedElementVectorType = 0x20000000; + /// visitIntrinsicFunction - Allow intrinsics to be verified in different ways. /// void Verifier::visitIntrinsicFunctionCall(Intrinsic::ID ID, CallInst &CI) { @@ -1376,13 +1381,34 @@ bool Verifier::PerformTypeCheck(Intrinsic::ID ID, Function *F, const Type *Ty, unsigned NumElts = 0; const Type *EltTy = Ty; - if (const VectorType *VTy = dyn_cast<VectorType>(Ty)) { + const VectorType *VTy = dyn_cast<VectorType>(Ty); + if (VTy) { EltTy = VTy->getElementType(); NumElts = VTy->getNumElements(); } if (VT < 0) { int Match = ~VT; + + // Check flags that indicate a type that is an integral vector type with + // elements that are larger or smaller than the elements of the matched + // type. + if ((Match & (ExtendedElementVectorType | + TruncatedElementVectorType)) != 0) { + if (!VTy) { + CheckFailed("Intrinsic parameter #" + utostr(ArgNo - 1) + " is not " + "a vector type.", F); + return false; + } + // Adjust the current Ty (in the opposite direction) rather than + // the type being matched against. + if ((Match & ExtendedElementVectorType) != 0) + Ty = VectorType::getTruncatedElementVectorType(VTy); + else + Ty = VectorType::getExtendedElementVectorType(VTy); + Match &= ~(ExtendedElementVectorType | TruncatedElementVectorType); + } + const Type *RetTy = FTy->getReturnType(); const StructType *ST = dyn_cast<StructType>(RetTy); unsigned NumRets = 1; diff --git a/utils/TableGen/CodeGenTarget.cpp b/utils/TableGen/CodeGenTarget.cpp index c6e94a5..0039a89 100644 --- a/utils/TableGen/CodeGenTarget.cpp +++ b/utils/TableGen/CodeGenTarget.cpp @@ -483,7 +483,17 @@ CodeGenIntrinsic::CodeGenIntrinsic(Record *R) { for (unsigned i = 0, e = TypeList->getSize(); i != e; ++i) { Record *TyEl = TypeList->getElementAsRecord(i); assert(TyEl->isSubClassOf("LLVMType") && "Expected a type!"); - MVT::SimpleValueType VT = getValueType(TyEl->getValueAsDef("VT")); + MVT::SimpleValueType VT; + if (TyEl->isSubClassOf("LLVMMatchType")) { + VT = IS.RetVTs[TyEl->getValueAsInt("Number")]; + // It only makes sense to use the extended and truncated vector element + // variants with iAny types; otherwise, if the intrinsic is not + // overloaded, all the types can be specified directly. + assert(((!TyEl->isSubClassOf("LLVMExtendedElementVectorType") && + !TyEl->isSubClassOf("LLVMTruncatedElementVectorType")) || + VT == MVT::iAny) && "Expected iAny type"); + } else + VT = getValueType(TyEl->getValueAsDef("VT")); isOverloaded |= VT == MVT::iAny || VT == MVT::fAny || VT == MVT::iPTRAny; IS.RetVTs.push_back(VT); IS.RetTypeDefs.push_back(TyEl); @@ -497,7 +507,21 @@ CodeGenIntrinsic::CodeGenIntrinsic(Record *R) { for (unsigned i = 0, e = TypeList->getSize(); i != e; ++i) { Record *TyEl = TypeList->getElementAsRecord(i); assert(TyEl->isSubClassOf("LLVMType") && "Expected a type!"); - MVT::SimpleValueType VT = getValueType(TyEl->getValueAsDef("VT")); + MVT::SimpleValueType VT; + if (TyEl->isSubClassOf("LLVMMatchType")) { + unsigned MatchTy = TyEl->getValueAsInt("Number"); + if (MatchTy < IS.RetVTs.size()) + VT = IS.RetVTs[MatchTy]; + else + VT = IS.ParamVTs[MatchTy - IS.RetVTs.size()]; + // It only makes sense to use the extended and truncated vector element + // variants with iAny types; otherwise, if the intrinsic is not + // overloaded, all the types can be specified directly. + assert(((!TyEl->isSubClassOf("LLVMExtendedElementVectorType") && + !TyEl->isSubClassOf("LLVMTruncatedElementVectorType")) || + VT == MVT::iAny) && "Expected iAny type"); + } else + VT = getValueType(TyEl->getValueAsDef("VT")); isOverloaded |= VT == MVT::iAny || VT == MVT::fAny || VT == MVT::iPTRAny; IS.ParamVTs.push_back(VT); IS.ParamTypeDefs.push_back(TyEl); diff --git a/utils/TableGen/IntrinsicEmitter.cpp b/utils/TableGen/IntrinsicEmitter.cpp index 7883e7c..86e83e5 100644 --- a/utils/TableGen/IntrinsicEmitter.cpp +++ b/utils/TableGen/IntrinsicEmitter.cpp @@ -167,7 +167,14 @@ static void EmitTypeGenerate(std::ostream &OS, const Record *ArgType, if (ArgType->isSubClassOf("LLVMMatchType")) { unsigned Number = ArgType->getValueAsInt("Number"); assert(Number < ArgNo && "Invalid matching number!"); - OS << "Tys[" << Number << "]"; + if (ArgType->isSubClassOf("LLVMExtendedElementVectorType")) + OS << "VectorType::getExtendedElementVectorType" + << "(dyn_cast<VectorType>(Tys[" << Number << "]))"; + else if (ArgType->isSubClassOf("LLVMTruncatedElementVectorType")) + OS << "VectorType::getTruncatedElementVectorType" + << "(dyn_cast<VectorType>(Tys[" << Number << "]))"; + else + OS << "Tys[" << Number << "]"; } else if (VT == MVT::iAny || VT == MVT::fAny) { // NOTE: The ArgNo variable here is not the absolute argument number, it is // the index of the "arbitrary" type in the Tys array passed to the @@ -281,7 +288,12 @@ void IntrinsicEmitter::EmitVerifier(const std::vector<CodeGenIntrinsic> &Ints, if (ArgType->isSubClassOf("LLVMMatchType")) { unsigned Number = ArgType->getValueAsInt("Number"); assert(Number < j && "Invalid matching number!"); - OS << "~" << Number; + if (ArgType->isSubClassOf("LLVMExtendedElementVectorType")) + OS << "~(ExtendedElementVectorType | " << Number << ")"; + else if (ArgType->isSubClassOf("LLVMTruncatedElementVectorType")) + OS << "~(TruncatedElementVectorType | " << Number << ")"; + else + OS << "~" << Number; } else { MVT::SimpleValueType VT = getValueType(ArgType->getValueAsDef("VT")); OS << getEnumName(VT); @@ -299,7 +311,12 @@ void IntrinsicEmitter::EmitVerifier(const std::vector<CodeGenIntrinsic> &Ints, if (ArgType->isSubClassOf("LLVMMatchType")) { unsigned Number = ArgType->getValueAsInt("Number"); assert(Number < j + RetTys.size() && "Invalid matching number!"); - OS << "~" << Number; + if (ArgType->isSubClassOf("LLVMExtendedElementVectorType")) + OS << "~(ExtendedElementVectorType | " << Number << ")"; + else if (ArgType->isSubClassOf("LLVMTruncatedElementVectorType")) + OS << "~(TruncatedElementVectorType | " << Number << ")"; + else + OS << "~" << Number; } else { MVT::SimpleValueType VT = getValueType(ArgType->getValueAsDef("VT")); OS << getEnumName(VT); |