diff options
author | Tim Northover <tnorthover@apple.com> | 2014-03-28 12:31:39 +0000 |
---|---|---|
committer | Tim Northover <tnorthover@apple.com> | 2014-03-28 12:31:39 +0000 |
commit | b7de4288bc0b712a7691fe8bf9305d3963363b4f (patch) | |
tree | 6bcf42ec33266e20e65e14b3e92ac208ad11b438 | |
parent | efb8deb6407ef731f17f622d317b122f7c4bd0a1 (diff) | |
download | llvm-b7de4288bc0b712a7691fe8bf9305d3963363b4f.tar.gz llvm-b7de4288bc0b712a7691fe8bf9305d3963363b4f.tar.bz2 llvm-b7de4288bc0b712a7691fe8bf9305d3963363b4f.tar.xz |
Intrinsics: expand semantics of LLVMExtendedVectorType (& trunc)
These are used in the ARM backends to aid type-checking on patterns involving
intrinsics. By making sure one argument is an extended/truncated version of
another.
However, there's no reason to limit them to just vectors types. For example
AArch64 has the instruction "uqshrn sD, dN, #imm" which would naturally use an
intrinsic taking an i64 and returning an i32.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@205003 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r-- | include/llvm/IR/Intrinsics.h | 10 | ||||
-rw-r--r-- | include/llvm/IR/Intrinsics.td | 12 | ||||
-rw-r--r-- | include/llvm/IR/IntrinsicsAArch64.td | 2 | ||||
-rw-r--r-- | include/llvm/IR/IntrinsicsARM.td | 15 | ||||
-rw-r--r-- | lib/IR/Function.cpp | 33 | ||||
-rw-r--r-- | lib/IR/Verifier.cpp | 37 | ||||
-rw-r--r-- | utils/TableGen/CodeGenTarget.cpp | 8 | ||||
-rw-r--r-- | utils/TableGen/IntrinsicEmitter.cpp | 12 |
8 files changed, 74 insertions, 55 deletions
diff --git a/include/llvm/IR/Intrinsics.h b/include/llvm/IR/Intrinsics.h index 473e525d9b..b3e58b7cc4 100644 --- a/include/llvm/IR/Intrinsics.h +++ b/include/llvm/IR/Intrinsics.h @@ -79,7 +79,7 @@ namespace Intrinsic { enum IITDescriptorKind { Void, VarArg, MMX, Metadata, Half, Float, Double, Integer, Vector, Pointer, Struct, - Argument, ExtendVecArgument, TruncVecArgument + Argument, ExtendArgument, TruncArgument, } Kind; union { @@ -98,13 +98,13 @@ namespace Intrinsic { AK_AnyPointer }; unsigned getArgumentNumber() const { - assert(Kind == Argument || Kind == ExtendVecArgument || - Kind == TruncVecArgument); + assert(Kind == Argument || Kind == ExtendArgument || + Kind == TruncArgument); return Argument_Info >> 2; } ArgKind getArgumentKind() const { - assert(Kind == Argument || Kind == ExtendVecArgument || - Kind == TruncVecArgument); + assert(Kind == Argument || Kind == ExtendArgument || + Kind == TruncArgument); return (ArgKind)(Argument_Info&3); } diff --git a/include/llvm/IR/Intrinsics.td b/include/llvm/IR/Intrinsics.td index 0c9cc3be3d..91bf99eab2 100644 --- a/include/llvm/IR/Intrinsics.td +++ b/include/llvm/IR/Intrinsics.td @@ -106,12 +106,12 @@ 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>; +// Match the type of another intrinsic parameter that is expected to be based on +// an integral type (i.e. either iN or <N x iM>), but change the scalar 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 LLVMExtendedType<int num> : LLVMMatchType<num>; +class LLVMTruncatedType<int num> : LLVMMatchType<num>; def llvm_void_ty : LLVMType<isVoid>; def llvm_anyint_ty : LLVMType<iAny>; diff --git a/include/llvm/IR/IntrinsicsAArch64.td b/include/llvm/IR/IntrinsicsAArch64.td index c052963bf9..61c0e5d419 100644 --- a/include/llvm/IR/IntrinsicsAArch64.td +++ b/include/llvm/IR/IntrinsicsAArch64.td @@ -68,7 +68,7 @@ class Neon_N3V_Intrinsic [IntrNoMem]>; class Neon_N2V_Narrow_Intrinsic : Intrinsic<[llvm_anyvector_ty], - [LLVMExtendedElementVectorType<0>, llvm_i32_ty], + [LLVMExtendedType<0>, llvm_i32_ty], [IntrNoMem]>; // Vector rounding shift right by immediate (Signed) diff --git a/include/llvm/IR/IntrinsicsARM.td b/include/llvm/IR/IntrinsicsARM.td index f70dbabd17..482f98ef89 100644 --- a/include/llvm/IR/IntrinsicsARM.td +++ b/include/llvm/IR/IntrinsicsARM.td @@ -131,20 +131,15 @@ def int_arm_sevl : Intrinsic<[], []>; class Neon_1Arg_Intrinsic : Intrinsic<[llvm_anyvector_ty], [LLVMMatchType<0>], [IntrNoMem]>; class Neon_1Arg_Narrow_Intrinsic - : Intrinsic<[llvm_anyvector_ty], - [LLVMExtendedElementVectorType<0>], [IntrNoMem]>; + : Intrinsic<[llvm_anyvector_ty], [LLVMExtendedType<0>], [IntrNoMem]>; class Neon_2Arg_Intrinsic : Intrinsic<[llvm_anyvector_ty], [LLVMMatchType<0>, LLVMMatchType<0>], [IntrNoMem]>; class Neon_2Arg_Narrow_Intrinsic - : Intrinsic<[llvm_anyvector_ty], - [LLVMExtendedElementVectorType<0>, - LLVMExtendedElementVectorType<0>], + : Intrinsic<[llvm_anyvector_ty], [LLVMExtendedType<0>, LLVMExtendedType<0>], [IntrNoMem]>; class Neon_2Arg_Long_Intrinsic - : Intrinsic<[llvm_anyvector_ty], - [LLVMTruncatedElementVectorType<0>, - LLVMTruncatedElementVectorType<0>], + : Intrinsic<[llvm_anyvector_ty], [LLVMTruncatedType<0>, LLVMTruncatedType<0>], [IntrNoMem]>; class Neon_3Arg_Intrinsic : Intrinsic<[llvm_anyvector_ty], @@ -152,9 +147,7 @@ class Neon_3Arg_Intrinsic [IntrNoMem]>; class Neon_3Arg_Long_Intrinsic : Intrinsic<[llvm_anyvector_ty], - [LLVMMatchType<0>, - LLVMTruncatedElementVectorType<0>, - LLVMTruncatedElementVectorType<0>], + [LLVMMatchType<0>, LLVMTruncatedType<0>, LLVMTruncatedType<0>], [IntrNoMem]>; class Neon_CvtFxToFP_Intrinsic : Intrinsic<[llvm_anyfloat_ty], [llvm_anyint_ty, llvm_i32_ty], [IntrNoMem]>; diff --git a/lib/IR/Function.cpp b/lib/IR/Function.cpp index 865970c469..f690ee0776 100644 --- a/lib/IR/Function.cpp +++ b/lib/IR/Function.cpp @@ -466,8 +466,8 @@ enum IIT_Info { IIT_STRUCT3 = 20, IIT_STRUCT4 = 21, IIT_STRUCT5 = 22, - IIT_EXTEND_VEC_ARG = 23, - IIT_TRUNC_VEC_ARG = 24, + IIT_EXTEND_ARG = 23, + IIT_TRUNC_ARG = 24, IIT_ANYPTR = 25, IIT_V1 = 26, IIT_VARARG = 27 @@ -556,15 +556,15 @@ static void DecodeIITType(unsigned &NextElt, ArrayRef<unsigned char> Infos, OutputTable.push_back(IITDescriptor::get(IITDescriptor::Argument, ArgInfo)); return; } - case IIT_EXTEND_VEC_ARG: { + case IIT_EXTEND_ARG: { unsigned ArgInfo = (NextElt == Infos.size() ? 0 : Infos[NextElt++]); - OutputTable.push_back(IITDescriptor::get(IITDescriptor::ExtendVecArgument, + OutputTable.push_back(IITDescriptor::get(IITDescriptor::ExtendArgument, ArgInfo)); return; } - case IIT_TRUNC_VEC_ARG: { + case IIT_TRUNC_ARG: { unsigned ArgInfo = (NextElt == Infos.size() ? 0 : Infos[NextElt++]); - OutputTable.push_back(IITDescriptor::get(IITDescriptor::TruncVecArgument, + OutputTable.push_back(IITDescriptor::get(IITDescriptor::TruncArgument, ArgInfo)); return; } @@ -656,13 +656,22 @@ static Type *DecodeFixedType(ArrayRef<Intrinsic::IITDescriptor> &Infos, case IITDescriptor::Argument: return Tys[D.getArgumentNumber()]; - case IITDescriptor::ExtendVecArgument: - return VectorType::getExtendedElementVectorType(cast<VectorType>( - Tys[D.getArgumentNumber()])); + case IITDescriptor::ExtendArgument: { + Type *Ty = Tys[D.getArgumentNumber()]; + if (VectorType *VTy = dyn_cast<VectorType>(Ty)) + return VectorType::getExtendedElementVectorType(VTy); - case IITDescriptor::TruncVecArgument: - return VectorType::getTruncatedElementVectorType(cast<VectorType>( - Tys[D.getArgumentNumber()])); + return IntegerType::get(Context, 2 * cast<IntegerType>(Ty)->getBitWidth()); + } + case IITDescriptor::TruncArgument: { + Type *Ty = Tys[D.getArgumentNumber()]; + if (VectorType *VTy = dyn_cast<VectorType>(Ty)) + return VectorType::getTruncatedElementVectorType(VTy); + + IntegerType *ITy = cast<IntegerType>(Ty); + assert(ITy->getBitWidth() % 2 == 0); + return IntegerType::get(Context, ITy->getBitWidth() / 2); + } } llvm_unreachable("unhandled"); } diff --git a/lib/IR/Verifier.cpp b/lib/IR/Verifier.cpp index f5c8ac623b..aa84f230d0 100644 --- a/lib/IR/Verifier.cpp +++ b/lib/IR/Verifier.cpp @@ -2176,19 +2176,36 @@ bool Verifier::VerifyIntrinsicType(Type *Ty, } llvm_unreachable("all argument kinds not covered"); - case IITDescriptor::ExtendVecArgument: + case IITDescriptor::ExtendArgument: { // This may only be used when referring to a previous vector argument. - return D.getArgumentNumber() >= ArgTys.size() || - !isa<VectorType>(ArgTys[D.getArgumentNumber()]) || - VectorType::getExtendedElementVectorType( - cast<VectorType>(ArgTys[D.getArgumentNumber()])) != Ty; + if (D.getArgumentNumber() >= ArgTys.size()) + return true; + + Type *NewTy = ArgTys[D.getArgumentNumber()]; + if (VectorType *VTy = dyn_cast<VectorType>(NewTy)) + NewTy = VectorType::getExtendedElementVectorType(VTy); + else if (IntegerType *ITy = dyn_cast<IntegerType>(NewTy)) + NewTy = IntegerType::get(ITy->getContext(), 2 * ITy->getBitWidth()); + else + return true; - case IITDescriptor::TruncVecArgument: + return Ty != NewTy; + } + case IITDescriptor::TruncArgument: { // This may only be used when referring to a previous vector argument. - return D.getArgumentNumber() >= ArgTys.size() || - !isa<VectorType>(ArgTys[D.getArgumentNumber()]) || - VectorType::getTruncatedElementVectorType( - cast<VectorType>(ArgTys[D.getArgumentNumber()])) != Ty; + if (D.getArgumentNumber() >= ArgTys.size()) + return true; + + Type *NewTy = ArgTys[D.getArgumentNumber()]; + if (VectorType *VTy = dyn_cast<VectorType>(NewTy)) + NewTy = VectorType::getTruncatedElementVectorType(VTy); + else if (IntegerType *ITy = dyn_cast<IntegerType>(NewTy)) + NewTy = IntegerType::get(ITy->getContext(), ITy->getBitWidth() / 2); + else + return true; + + return Ty != NewTy; + } } llvm_unreachable("unhandled"); } diff --git a/utils/TableGen/CodeGenTarget.cpp b/utils/TableGen/CodeGenTarget.cpp index 884af4c7cb..685c4bf075 100644 --- a/utils/TableGen/CodeGenTarget.cpp +++ b/utils/TableGen/CodeGenTarget.cpp @@ -498,8 +498,8 @@ CodeGenIntrinsic::CodeGenIntrinsic(Record *R) { // 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")) || + assert(((!TyEl->isSubClassOf("LLVMExtendedType") && + !TyEl->isSubClassOf("LLVMTruncatedType")) || VT == MVT::iAny || VT == MVT::vAny) && "Expected iAny or vAny type"); } else { @@ -532,8 +532,8 @@ CodeGenIntrinsic::CodeGenIntrinsic(Record *R) { // 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")) || + assert(((!TyEl->isSubClassOf("LLVMExtendedType") && + !TyEl->isSubClassOf("LLVMTruncatedType")) || VT == MVT::iAny || VT == MVT::vAny) && "Expected iAny or vAny type"); } else diff --git a/utils/TableGen/IntrinsicEmitter.cpp b/utils/TableGen/IntrinsicEmitter.cpp index 1b281288a4..dc32dfa858 100644 --- a/utils/TableGen/IntrinsicEmitter.cpp +++ b/utils/TableGen/IntrinsicEmitter.cpp @@ -246,8 +246,8 @@ enum IIT_Info { IIT_STRUCT3 = 20, IIT_STRUCT4 = 21, IIT_STRUCT5 = 22, - IIT_EXTEND_VEC_ARG = 23, - IIT_TRUNC_VEC_ARG = 24, + IIT_EXTEND_ARG = 23, + IIT_TRUNC_ARG = 24, IIT_ANYPTR = 25, IIT_V1 = 26, IIT_VARARG = 27 @@ -292,10 +292,10 @@ static void EncodeFixedType(Record *R, std::vector<unsigned char> &ArgCodes, if (R->isSubClassOf("LLVMMatchType")) { unsigned Number = R->getValueAsInt("Number"); assert(Number < ArgCodes.size() && "Invalid matching number!"); - if (R->isSubClassOf("LLVMExtendedElementVectorType")) - Sig.push_back(IIT_EXTEND_VEC_ARG); - else if (R->isSubClassOf("LLVMTruncatedElementVectorType")) - Sig.push_back(IIT_TRUNC_VEC_ARG); + if (R->isSubClassOf("LLVMExtendedType")) + Sig.push_back(IIT_EXTEND_ARG); + else if (R->isSubClassOf("LLVMTruncatedType")) + Sig.push_back(IIT_TRUNC_ARG); else Sig.push_back(IIT_ARG); return Sig.push_back((Number << 2) | ArgCodes[Number]); |