mirror of
https://github.com/RPCSX/llvm.git
synced 2024-11-28 22:20:37 +00:00
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
This commit is contained in:
parent
efb8deb640
commit
b7de4288bc
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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>;
|
||||
|
@ -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)
|
||||
|
@ -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]>;
|
||||
|
@ -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");
|
||||
}
|
||||
|
@ -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;
|
||||
|
||||
case IITDescriptor::TruncVecArgument:
|
||||
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;
|
||||
|
||||
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");
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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]);
|
||||
|
Loading…
Reference in New Issue
Block a user