Clean up type flags for overloaded Neon builtins. No functional change.
This patch just adds a simple NeonTypeFlags class to replace the various hardcoded constants that had been used until now. Unfortunately I couldn't figure out a good way to avoid duplicating that class between clang and TableGen, but since it's small and rarely changes, that's not so bad. llvm-svn: 144054
This commit is contained in:
parent
1654bb22ca
commit
98bc98caa8
|
@ -56,6 +56,46 @@ namespace clang {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// NeonTypeFlags - Flags to identify the types for overloaded Neon
|
||||||
|
/// builtins. These must be kept in sync with the flags in
|
||||||
|
/// utils/TableGen/NeonEmitter.h.
|
||||||
|
class NeonTypeFlags {
|
||||||
|
enum {
|
||||||
|
EltTypeMask = 0xf,
|
||||||
|
UnsignedFlag = 0x10,
|
||||||
|
QuadFlag = 0x20
|
||||||
|
};
|
||||||
|
uint32_t Flags;
|
||||||
|
|
||||||
|
public:
|
||||||
|
enum EltType {
|
||||||
|
Int8,
|
||||||
|
Int16,
|
||||||
|
Int32,
|
||||||
|
Int64,
|
||||||
|
Poly8,
|
||||||
|
Poly16,
|
||||||
|
Float16,
|
||||||
|
Float32
|
||||||
|
};
|
||||||
|
|
||||||
|
NeonTypeFlags(unsigned F) : Flags(F) {}
|
||||||
|
NeonTypeFlags(EltType ET, bool IsUnsigned, bool IsQuad) : Flags(ET) {
|
||||||
|
if (IsUnsigned)
|
||||||
|
Flags |= UnsignedFlag;
|
||||||
|
if (IsQuad)
|
||||||
|
Flags |= QuadFlag;
|
||||||
|
}
|
||||||
|
|
||||||
|
EltType getEltType() const { return (EltType)(Flags & EltTypeMask); }
|
||||||
|
bool isPoly() const {
|
||||||
|
EltType ET = getEltType();
|
||||||
|
return ET == Poly8 || ET == Poly16;
|
||||||
|
}
|
||||||
|
bool isUnsigned() const { return (Flags & UnsignedFlag) != 0; }
|
||||||
|
bool isQuad() const { return (Flags & QuadFlag) != 0; }
|
||||||
|
};
|
||||||
|
|
||||||
} // end namespace clang.
|
} // end namespace clang.
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -1186,17 +1186,23 @@ Value *CodeGenFunction::EmitTargetBuiltinExpr(unsigned BuiltinID,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static llvm::VectorType *GetNeonType(LLVMContext &C, unsigned type, bool q) {
|
static llvm::VectorType *GetNeonType(LLVMContext &C, NeonTypeFlags Type) {
|
||||||
switch (type) {
|
int IsQuad = Type.isQuad();
|
||||||
default: break;
|
switch (Type.getEltType()) {
|
||||||
case 0:
|
default: break;
|
||||||
case 5: return llvm::VectorType::get(llvm::Type::getInt8Ty(C), 8 << (int)q);
|
case NeonTypeFlags::Int8:
|
||||||
case 6:
|
case NeonTypeFlags::Poly8:
|
||||||
case 7:
|
return llvm::VectorType::get(llvm::Type::getInt8Ty(C), 8 << IsQuad);
|
||||||
case 1: return llvm::VectorType::get(llvm::Type::getInt16Ty(C),4 << (int)q);
|
case NeonTypeFlags::Int16:
|
||||||
case 2: return llvm::VectorType::get(llvm::Type::getInt32Ty(C),2 << (int)q);
|
case NeonTypeFlags::Poly16:
|
||||||
case 3: return llvm::VectorType::get(llvm::Type::getInt64Ty(C),1 << (int)q);
|
case NeonTypeFlags::Float16:
|
||||||
case 4: return llvm::VectorType::get(llvm::Type::getFloatTy(C),2 << (int)q);
|
return llvm::VectorType::get(llvm::Type::getInt16Ty(C), 4 << IsQuad);
|
||||||
|
case NeonTypeFlags::Int32:
|
||||||
|
return llvm::VectorType::get(llvm::Type::getInt32Ty(C), 2 << IsQuad);
|
||||||
|
case NeonTypeFlags::Int64:
|
||||||
|
return llvm::VectorType::get(llvm::Type::getInt64Ty(C), 1 << IsQuad);
|
||||||
|
case NeonTypeFlags::Float32:
|
||||||
|
return llvm::VectorType::get(llvm::Type::getFloatTy(C), 2 << IsQuad);
|
||||||
};
|
};
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -1363,14 +1369,12 @@ Value *CodeGenFunction::EmitARMBuiltinExpr(unsigned BuiltinID,
|
||||||
}
|
}
|
||||||
|
|
||||||
// Determine the type of this overloaded NEON intrinsic.
|
// Determine the type of this overloaded NEON intrinsic.
|
||||||
unsigned type = Result.getZExtValue();
|
NeonTypeFlags Type(Result.getZExtValue());
|
||||||
bool usgn = type & 0x08;
|
bool usgn = Type.isUnsigned();
|
||||||
bool quad = type & 0x10;
|
bool quad = Type.isQuad();
|
||||||
bool poly = (type & 0x7) == 5 || (type & 0x7) == 6;
|
|
||||||
(void)poly; // Only used in assert()s.
|
|
||||||
bool rightShift = false;
|
bool rightShift = false;
|
||||||
|
|
||||||
llvm::VectorType *VTy = GetNeonType(getLLVMContext(), type & 0x7, quad);
|
llvm::VectorType *VTy = GetNeonType(getLLVMContext(), Type);
|
||||||
llvm::Type *Ty = VTy;
|
llvm::Type *Ty = VTy;
|
||||||
if (!Ty)
|
if (!Ty)
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -1429,34 +1433,43 @@ Value *CodeGenFunction::EmitARMBuiltinExpr(unsigned BuiltinID,
|
||||||
return EmitNeonCall(F, Ops, "vcnt");
|
return EmitNeonCall(F, Ops, "vcnt");
|
||||||
}
|
}
|
||||||
case ARM::BI__builtin_neon_vcvt_f16_v: {
|
case ARM::BI__builtin_neon_vcvt_f16_v: {
|
||||||
assert((type & 0x7) == 7 && !quad && "unexpected vcvt_f16_v builtin");
|
assert(Type.getEltType() == NeonTypeFlags::Float16 && !quad &&
|
||||||
|
"unexpected vcvt_f16_v builtin");
|
||||||
Function *F = CGM.getIntrinsic(Intrinsic::arm_neon_vcvtfp2hf);
|
Function *F = CGM.getIntrinsic(Intrinsic::arm_neon_vcvtfp2hf);
|
||||||
return EmitNeonCall(F, Ops, "vcvt");
|
return EmitNeonCall(F, Ops, "vcvt");
|
||||||
}
|
}
|
||||||
case ARM::BI__builtin_neon_vcvt_f32_f16: {
|
case ARM::BI__builtin_neon_vcvt_f32_f16: {
|
||||||
assert((type & 0x7) == 7 && !quad && "unexpected vcvt_f32_f16 builtin");
|
assert(Type.getEltType() == NeonTypeFlags::Float16 && !quad &&
|
||||||
|
"unexpected vcvt_f32_f16 builtin");
|
||||||
Function *F = CGM.getIntrinsic(Intrinsic::arm_neon_vcvthf2fp);
|
Function *F = CGM.getIntrinsic(Intrinsic::arm_neon_vcvthf2fp);
|
||||||
return EmitNeonCall(F, Ops, "vcvt");
|
return EmitNeonCall(F, Ops, "vcvt");
|
||||||
}
|
}
|
||||||
case ARM::BI__builtin_neon_vcvt_f32_v:
|
case ARM::BI__builtin_neon_vcvt_f32_v:
|
||||||
case ARM::BI__builtin_neon_vcvtq_f32_v: {
|
case ARM::BI__builtin_neon_vcvtq_f32_v:
|
||||||
Ops[0] = Builder.CreateBitCast(Ops[0], Ty);
|
Ops[0] = Builder.CreateBitCast(Ops[0], Ty);
|
||||||
Ty = GetNeonType(getLLVMContext(), 4, quad);
|
Ty = GetNeonType(getLLVMContext(),
|
||||||
|
NeonTypeFlags(NeonTypeFlags::Float32, false, quad));
|
||||||
return usgn ? Builder.CreateUIToFP(Ops[0], Ty, "vcvt")
|
return usgn ? Builder.CreateUIToFP(Ops[0], Ty, "vcvt")
|
||||||
: Builder.CreateSIToFP(Ops[0], Ty, "vcvt");
|
: Builder.CreateSIToFP(Ops[0], Ty, "vcvt");
|
||||||
}
|
|
||||||
case ARM::BI__builtin_neon_vcvt_s32_v:
|
case ARM::BI__builtin_neon_vcvt_s32_v:
|
||||||
case ARM::BI__builtin_neon_vcvt_u32_v:
|
case ARM::BI__builtin_neon_vcvt_u32_v:
|
||||||
case ARM::BI__builtin_neon_vcvtq_s32_v:
|
case ARM::BI__builtin_neon_vcvtq_s32_v:
|
||||||
case ARM::BI__builtin_neon_vcvtq_u32_v: {
|
case ARM::BI__builtin_neon_vcvtq_u32_v: {
|
||||||
Ops[0] = Builder.CreateBitCast(Ops[0], GetNeonType(getLLVMContext(), 4, quad));
|
llvm::Type *FloatTy =
|
||||||
|
GetNeonType(getLLVMContext(),
|
||||||
|
NeonTypeFlags(NeonTypeFlags::Float32, false, quad));
|
||||||
|
Ops[0] = Builder.CreateBitCast(Ops[0], FloatTy);
|
||||||
return usgn ? Builder.CreateFPToUI(Ops[0], Ty, "vcvt")
|
return usgn ? Builder.CreateFPToUI(Ops[0], Ty, "vcvt")
|
||||||
: Builder.CreateFPToSI(Ops[0], Ty, "vcvt");
|
: Builder.CreateFPToSI(Ops[0], Ty, "vcvt");
|
||||||
}
|
}
|
||||||
case ARM::BI__builtin_neon_vcvt_n_f32_v:
|
case ARM::BI__builtin_neon_vcvt_n_f32_v:
|
||||||
case ARM::BI__builtin_neon_vcvtq_n_f32_v: {
|
case ARM::BI__builtin_neon_vcvtq_n_f32_v: {
|
||||||
llvm::Type *Tys[2] = { GetNeonType(getLLVMContext(), 4, quad), Ty };
|
llvm::Type *FloatTy =
|
||||||
Int = usgn ? Intrinsic::arm_neon_vcvtfxu2fp : Intrinsic::arm_neon_vcvtfxs2fp;
|
GetNeonType(getLLVMContext(),
|
||||||
|
NeonTypeFlags(NeonTypeFlags::Float32, false, quad));
|
||||||
|
llvm::Type *Tys[2] = { FloatTy, Ty };
|
||||||
|
Int = usgn ? Intrinsic::arm_neon_vcvtfxu2fp
|
||||||
|
: Intrinsic::arm_neon_vcvtfxs2fp;
|
||||||
Function *F = CGM.getIntrinsic(Int, Tys);
|
Function *F = CGM.getIntrinsic(Int, Tys);
|
||||||
return EmitNeonCall(F, Ops, "vcvt_n");
|
return EmitNeonCall(F, Ops, "vcvt_n");
|
||||||
}
|
}
|
||||||
|
@ -1464,8 +1477,12 @@ Value *CodeGenFunction::EmitARMBuiltinExpr(unsigned BuiltinID,
|
||||||
case ARM::BI__builtin_neon_vcvt_n_u32_v:
|
case ARM::BI__builtin_neon_vcvt_n_u32_v:
|
||||||
case ARM::BI__builtin_neon_vcvtq_n_s32_v:
|
case ARM::BI__builtin_neon_vcvtq_n_s32_v:
|
||||||
case ARM::BI__builtin_neon_vcvtq_n_u32_v: {
|
case ARM::BI__builtin_neon_vcvtq_n_u32_v: {
|
||||||
llvm::Type *Tys[2] = { Ty, GetNeonType(getLLVMContext(), 4, quad) };
|
llvm::Type *FloatTy =
|
||||||
Int = usgn ? Intrinsic::arm_neon_vcvtfp2fxu : Intrinsic::arm_neon_vcvtfp2fxs;
|
GetNeonType(getLLVMContext(),
|
||||||
|
NeonTypeFlags(NeonTypeFlags::Float32, false, quad));
|
||||||
|
llvm::Type *Tys[2] = { Ty, FloatTy };
|
||||||
|
Int = usgn ? Intrinsic::arm_neon_vcvtfp2fxu
|
||||||
|
: Intrinsic::arm_neon_vcvtfp2fxs;
|
||||||
Function *F = CGM.getIntrinsic(Int, Tys);
|
Function *F = CGM.getIntrinsic(Int, Tys);
|
||||||
return EmitNeonCall(F, Ops, "vcvt_n");
|
return EmitNeonCall(F, Ops, "vcvt_n");
|
||||||
}
|
}
|
||||||
|
@ -1656,12 +1673,12 @@ Value *CodeGenFunction::EmitARMBuiltinExpr(unsigned BuiltinID,
|
||||||
}
|
}
|
||||||
case ARM::BI__builtin_neon_vmul_v:
|
case ARM::BI__builtin_neon_vmul_v:
|
||||||
case ARM::BI__builtin_neon_vmulq_v:
|
case ARM::BI__builtin_neon_vmulq_v:
|
||||||
assert(poly && "vmul builtin only supported for polynomial types");
|
assert(Type.isPoly() && "vmul builtin only supported for polynomial types");
|
||||||
return EmitNeonCall(CGM.getIntrinsic(Intrinsic::arm_neon_vmulp, Ty),
|
return EmitNeonCall(CGM.getIntrinsic(Intrinsic::arm_neon_vmulp, Ty),
|
||||||
Ops, "vmul");
|
Ops, "vmul");
|
||||||
case ARM::BI__builtin_neon_vmull_v:
|
case ARM::BI__builtin_neon_vmull_v:
|
||||||
Int = usgn ? Intrinsic::arm_neon_vmullu : Intrinsic::arm_neon_vmulls;
|
Int = usgn ? Intrinsic::arm_neon_vmullu : Intrinsic::arm_neon_vmulls;
|
||||||
Int = poly ? (unsigned)Intrinsic::arm_neon_vmullp : Int;
|
Int = Type.isPoly() ? (unsigned)Intrinsic::arm_neon_vmullp : Int;
|
||||||
return EmitNeonCall(CGM.getIntrinsic(Int, Ty), Ops, "vmull");
|
return EmitNeonCall(CGM.getIntrinsic(Int, Ty), Ops, "vmull");
|
||||||
case ARM::BI__builtin_neon_vpadal_v:
|
case ARM::BI__builtin_neon_vpadal_v:
|
||||||
case ARM::BI__builtin_neon_vpadalq_v: {
|
case ARM::BI__builtin_neon_vpadalq_v: {
|
||||||
|
|
|
@ -245,27 +245,25 @@ Sema::CheckBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall) {
|
||||||
|
|
||||||
// Get the valid immediate range for the specified NEON type code.
|
// Get the valid immediate range for the specified NEON type code.
|
||||||
static unsigned RFT(unsigned t, bool shift = false) {
|
static unsigned RFT(unsigned t, bool shift = false) {
|
||||||
bool quad = t & 0x10;
|
NeonTypeFlags Type(t);
|
||||||
|
int IsQuad = Type.isQuad();
|
||||||
switch (t & 0x7) {
|
switch (Type.getEltType()) {
|
||||||
case 0: // i8
|
case NeonTypeFlags::Int8:
|
||||||
return shift ? 7 : (8 << (int)quad) - 1;
|
case NeonTypeFlags::Poly8:
|
||||||
case 1: // i16
|
return shift ? 7 : (8 << IsQuad) - 1;
|
||||||
return shift ? 15 : (4 << (int)quad) - 1;
|
case NeonTypeFlags::Int16:
|
||||||
case 2: // i32
|
case NeonTypeFlags::Poly16:
|
||||||
return shift ? 31 : (2 << (int)quad) - 1;
|
return shift ? 15 : (4 << IsQuad) - 1;
|
||||||
case 3: // i64
|
case NeonTypeFlags::Int32:
|
||||||
return shift ? 63 : (1 << (int)quad) - 1;
|
return shift ? 31 : (2 << IsQuad) - 1;
|
||||||
case 4: // f32
|
case NeonTypeFlags::Int64:
|
||||||
assert(!shift && "cannot shift float types!");
|
return shift ? 63 : (1 << IsQuad) - 1;
|
||||||
return (2 << (int)quad) - 1;
|
case NeonTypeFlags::Float16:
|
||||||
case 5: // poly8
|
assert(!shift && "cannot shift float types!");
|
||||||
return shift ? 7 : (8 << (int)quad) - 1;
|
return (4 << IsQuad) - 1;
|
||||||
case 6: // poly16
|
case NeonTypeFlags::Float32:
|
||||||
return shift ? 15 : (4 << (int)quad) - 1;
|
assert(!shift && "cannot shift float types!");
|
||||||
case 7: // float16
|
return (2 << IsQuad) - 1;
|
||||||
assert(!shift && "cannot shift float types!");
|
|
||||||
return (4 << (int)quad) - 1;
|
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -288,8 +286,8 @@ bool Sema::CheckARMBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall) {
|
||||||
if (SemaBuiltinConstantArg(TheCall, ArgNo, Result))
|
if (SemaBuiltinConstantArg(TheCall, ArgNo, Result))
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
TV = Result.getLimitedValue(32);
|
TV = Result.getLimitedValue(64);
|
||||||
if ((TV > 31) || (mask & (1 << TV)) == 0)
|
if ((TV > 63) || (mask & (1 << TV)) == 0)
|
||||||
return Diag(TheCall->getLocStart(), diag::err_invalid_neon_type_code)
|
return Diag(TheCall->getLocStart(), diag::err_invalid_neon_type_code)
|
||||||
<< TheCall->getArg(ArgNo)->getSourceRange();
|
<< TheCall->getArg(ArgNo)->getSourceRange();
|
||||||
}
|
}
|
||||||
|
|
|
@ -833,7 +833,6 @@ static std::string GenOpString(OpKind op, const std::string &proto,
|
||||||
|
|
||||||
static unsigned GetNeonEnum(const std::string &proto, StringRef typestr) {
|
static unsigned GetNeonEnum(const std::string &proto, StringRef typestr) {
|
||||||
unsigned mod = proto[0];
|
unsigned mod = proto[0];
|
||||||
unsigned ret = 0;
|
|
||||||
|
|
||||||
if (mod == 'v' || mod == 'f')
|
if (mod == 'v' || mod == 'f')
|
||||||
mod = proto[1];
|
mod = proto[1];
|
||||||
|
@ -851,35 +850,32 @@ static unsigned GetNeonEnum(const std::string &proto, StringRef typestr) {
|
||||||
// Based on the modifying character, change the type and width if necessary.
|
// Based on the modifying character, change the type and width if necessary.
|
||||||
type = ModType(mod, type, quad, poly, usgn, scal, cnst, pntr);
|
type = ModType(mod, type, quad, poly, usgn, scal, cnst, pntr);
|
||||||
|
|
||||||
if (usgn)
|
NeonTypeFlags::EltType ET;
|
||||||
ret |= 0x08;
|
|
||||||
if (quad && proto[1] != 'g')
|
|
||||||
ret |= 0x10;
|
|
||||||
|
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case 'c':
|
case 'c':
|
||||||
ret |= poly ? 5 : 0;
|
ET = poly ? NeonTypeFlags::Poly8 : NeonTypeFlags::Int8;
|
||||||
break;
|
break;
|
||||||
case 's':
|
case 's':
|
||||||
ret |= poly ? 6 : 1;
|
ET = poly ? NeonTypeFlags::Poly16 : NeonTypeFlags::Int16;
|
||||||
break;
|
break;
|
||||||
case 'i':
|
case 'i':
|
||||||
ret |= 2;
|
ET = NeonTypeFlags::Int32;
|
||||||
break;
|
break;
|
||||||
case 'l':
|
case 'l':
|
||||||
ret |= 3;
|
ET = NeonTypeFlags::Int64;
|
||||||
break;
|
break;
|
||||||
case 'h':
|
case 'h':
|
||||||
ret |= 7;
|
ET = NeonTypeFlags::Float16;
|
||||||
break;
|
break;
|
||||||
case 'f':
|
case 'f':
|
||||||
ret |= 4;
|
ET = NeonTypeFlags::Float32;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
throw "unhandled type!";
|
throw "unhandled type!";
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
return ret;
|
NeonTypeFlags Flags(ET, usgn, quad && proto[1] != 'g');
|
||||||
|
return Flags.getFlags();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Generate the definition for this intrinsic, e.g. __builtin_neon_cls(a)
|
// Generate the definition for this intrinsic, e.g. __builtin_neon_cls(a)
|
||||||
|
|
|
@ -86,6 +86,40 @@ enum ClassKind {
|
||||||
ClassB // bitcast arguments with enum argument to specify type
|
ClassB // bitcast arguments with enum argument to specify type
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/// NeonTypeFlags - Flags to identify the types for overloaded Neon
|
||||||
|
/// builtins. These must be kept in sync with the flags in
|
||||||
|
/// include/clang/Basic/TargetBuiltins.h.
|
||||||
|
class NeonTypeFlags {
|
||||||
|
enum {
|
||||||
|
EltTypeMask = 0xf,
|
||||||
|
UnsignedFlag = 0x10,
|
||||||
|
QuadFlag = 0x20
|
||||||
|
};
|
||||||
|
uint32_t Flags;
|
||||||
|
|
||||||
|
public:
|
||||||
|
enum EltType {
|
||||||
|
Int8,
|
||||||
|
Int16,
|
||||||
|
Int32,
|
||||||
|
Int64,
|
||||||
|
Poly8,
|
||||||
|
Poly16,
|
||||||
|
Float16,
|
||||||
|
Float32
|
||||||
|
};
|
||||||
|
|
||||||
|
NeonTypeFlags(unsigned F) : Flags(F) {}
|
||||||
|
NeonTypeFlags(EltType ET, bool IsUnsigned, bool IsQuad) : Flags(ET) {
|
||||||
|
if (IsUnsigned)
|
||||||
|
Flags |= UnsignedFlag;
|
||||||
|
if (IsQuad)
|
||||||
|
Flags |= QuadFlag;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t getFlags() const { return Flags; }
|
||||||
|
};
|
||||||
|
|
||||||
namespace llvm {
|
namespace llvm {
|
||||||
|
|
||||||
class NeonEmitter : public TableGenBackend {
|
class NeonEmitter : public TableGenBackend {
|
||||||
|
|
Loading…
Reference in New Issue