From b7de4288bc0b712a7691fe8bf9305d3963363b4f Mon Sep 17 00:00:00 2001 From: Tim Northover Date: Fri, 28 Mar 2014 12:31:39 +0000 Subject: [PATCH] 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 --- include/llvm/IR/Intrinsics.h | 10 ++++---- include/llvm/IR/Intrinsics.td | 12 ++++----- include/llvm/IR/IntrinsicsAArch64.td | 2 +- include/llvm/IR/IntrinsicsARM.td | 15 +++-------- lib/IR/Function.cpp | 33 ++++++++++++++++--------- lib/IR/Verifier.cpp | 37 ++++++++++++++++++++-------- utils/TableGen/CodeGenTarget.cpp | 8 +++--- 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 473e525d9b9..b3e58b7cc40 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 0c9cc3be3d7..91bf99eab2e 100644 --- a/include/llvm/IR/Intrinsics.td +++ b/include/llvm/IR/Intrinsics.td @@ -106,12 +106,12 @@ class LLVMMatchType 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 : LLVMMatchType; -class LLVMTruncatedElementVectorType : LLVMMatchType; +// Match the type of another intrinsic parameter that is expected to be based on +// an integral type (i.e. either iN or ), 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 : LLVMMatchType; +class LLVMTruncatedType : LLVMMatchType; def llvm_void_ty : LLVMType; def llvm_anyint_ty : LLVMType; diff --git a/include/llvm/IR/IntrinsicsAArch64.td b/include/llvm/IR/IntrinsicsAArch64.td index c052963bf98..61c0e5d419f 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 f70dbabd171..482f98ef895 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 865970c4690..f690ee07769 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 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 &Infos, case IITDescriptor::Argument: return Tys[D.getArgumentNumber()]; - case IITDescriptor::ExtendVecArgument: - return VectorType::getExtendedElementVectorType(cast( - Tys[D.getArgumentNumber()])); + case IITDescriptor::ExtendArgument: { + Type *Ty = Tys[D.getArgumentNumber()]; + if (VectorType *VTy = dyn_cast(Ty)) + return VectorType::getExtendedElementVectorType(VTy); - case IITDescriptor::TruncVecArgument: - return VectorType::getTruncatedElementVectorType(cast( - Tys[D.getArgumentNumber()])); + return IntegerType::get(Context, 2 * cast(Ty)->getBitWidth()); + } + case IITDescriptor::TruncArgument: { + Type *Ty = Tys[D.getArgumentNumber()]; + if (VectorType *VTy = dyn_cast(Ty)) + return VectorType::getTruncatedElementVectorType(VTy); + + IntegerType *ITy = cast(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 f5c8ac623b1..aa84f230d01 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(ArgTys[D.getArgumentNumber()]) || - VectorType::getExtendedElementVectorType( - cast(ArgTys[D.getArgumentNumber()])) != Ty; + if (D.getArgumentNumber() >= ArgTys.size()) + return true; - case IITDescriptor::TruncVecArgument: + Type *NewTy = ArgTys[D.getArgumentNumber()]; + if (VectorType *VTy = dyn_cast(NewTy)) + NewTy = VectorType::getExtendedElementVectorType(VTy); + else if (IntegerType *ITy = dyn_cast(NewTy)) + NewTy = IntegerType::get(ITy->getContext(), 2 * ITy->getBitWidth()); + else + return true; + + return Ty != NewTy; + } + case IITDescriptor::TruncArgument: { // This may only be used when referring to a previous vector argument. - return D.getArgumentNumber() >= ArgTys.size() || - !isa(ArgTys[D.getArgumentNumber()]) || - VectorType::getTruncatedElementVectorType( - cast(ArgTys[D.getArgumentNumber()])) != Ty; + if (D.getArgumentNumber() >= ArgTys.size()) + return true; + + Type *NewTy = ArgTys[D.getArgumentNumber()]; + if (VectorType *VTy = dyn_cast(NewTy)) + NewTy = VectorType::getTruncatedElementVectorType(VTy); + else if (IntegerType *ITy = dyn_cast(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 884af4c7cb7..685c4bf0750 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 1b281288a4e..dc32dfa8584 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 &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]);