diff options
author | Bob Wilson <bob.wilson@apple.com> | 2011-11-08 01:16:11 +0000 |
---|---|---|
committer | Bob Wilson <bob.wilson@apple.com> | 2011-11-08 01:16:11 +0000 |
commit | da95f73b59f9af964e33725c515139d34c90c863 (patch) | |
tree | 366c5e1ac7b2b1bdc51e0dad058c7155eb61dd08 | |
parent | bc05f57cba6655d1f8ff7f17338dac63139b878e (diff) |
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.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@144054 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r-- | include/clang/Basic/TargetBuiltins.h | 40 | ||||
-rw-r--r-- | lib/CodeGen/CGBuiltin.cpp | 75 | ||||
-rw-r--r-- | lib/Sema/SemaChecking.cpp | 44 | ||||
-rw-r--r-- | utils/TableGen/NeonEmitter.cpp | 22 | ||||
-rw-r--r-- | utils/TableGen/NeonEmitter.h | 34 |
5 files changed, 150 insertions, 65 deletions
diff --git a/include/clang/Basic/TargetBuiltins.h b/include/clang/Basic/TargetBuiltins.h index 8bc60ff538..62e970c41b 100644 --- a/include/clang/Basic/TargetBuiltins.h +++ b/include/clang/Basic/TargetBuiltins.h @@ -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. #endif diff --git a/lib/CodeGen/CGBuiltin.cpp b/lib/CodeGen/CGBuiltin.cpp index bdf49a1e79..ec271b311d 100644 --- a/lib/CodeGen/CGBuiltin.cpp +++ b/lib/CodeGen/CGBuiltin.cpp @@ -1186,17 +1186,23 @@ Value *CodeGenFunction::EmitTargetBuiltinExpr(unsigned BuiltinID, } } -static llvm::VectorType *GetNeonType(LLVMContext &C, unsigned type, bool q) { - switch (type) { - default: break; - case 0: - case 5: return llvm::VectorType::get(llvm::Type::getInt8Ty(C), 8 << (int)q); - case 6: - case 7: - case 1: return llvm::VectorType::get(llvm::Type::getInt16Ty(C),4 << (int)q); - case 2: return llvm::VectorType::get(llvm::Type::getInt32Ty(C),2 << (int)q); - case 3: return llvm::VectorType::get(llvm::Type::getInt64Ty(C),1 << (int)q); - case 4: return llvm::VectorType::get(llvm::Type::getFloatTy(C),2 << (int)q); +static llvm::VectorType *GetNeonType(LLVMContext &C, NeonTypeFlags Type) { + int IsQuad = Type.isQuad(); + switch (Type.getEltType()) { + default: break; + case NeonTypeFlags::Int8: + case NeonTypeFlags::Poly8: + return llvm::VectorType::get(llvm::Type::getInt8Ty(C), 8 << IsQuad); + case NeonTypeFlags::Int16: + case NeonTypeFlags::Poly16: + case NeonTypeFlags::Float16: + 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; } @@ -1363,14 +1369,12 @@ Value *CodeGenFunction::EmitARMBuiltinExpr(unsigned BuiltinID, } // Determine the type of this overloaded NEON intrinsic. - unsigned type = Result.getZExtValue(); - bool usgn = type & 0x08; - bool quad = type & 0x10; - bool poly = (type & 0x7) == 5 || (type & 0x7) == 6; - (void)poly; // Only used in assert()s. + NeonTypeFlags Type(Result.getZExtValue()); + bool usgn = Type.isUnsigned(); + bool quad = Type.isQuad(); bool rightShift = false; - llvm::VectorType *VTy = GetNeonType(getLLVMContext(), type & 0x7, quad); + llvm::VectorType *VTy = GetNeonType(getLLVMContext(), Type); llvm::Type *Ty = VTy; if (!Ty) return 0; @@ -1429,34 +1433,43 @@ Value *CodeGenFunction::EmitARMBuiltinExpr(unsigned BuiltinID, return EmitNeonCall(F, Ops, "vcnt"); } 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); return EmitNeonCall(F, Ops, "vcvt"); } 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); return EmitNeonCall(F, Ops, "vcvt"); } 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); - Ty = GetNeonType(getLLVMContext(), 4, quad); + Ty = GetNeonType(getLLVMContext(), + NeonTypeFlags(NeonTypeFlags::Float32, false, quad)); return usgn ? Builder.CreateUIToFP(Ops[0], Ty, "vcvt") : Builder.CreateSIToFP(Ops[0], Ty, "vcvt"); - } case ARM::BI__builtin_neon_vcvt_s32_v: case ARM::BI__builtin_neon_vcvt_u32_v: case ARM::BI__builtin_neon_vcvtq_s32_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") : Builder.CreateFPToSI(Ops[0], Ty, "vcvt"); } case ARM::BI__builtin_neon_vcvt_n_f32_v: case ARM::BI__builtin_neon_vcvtq_n_f32_v: { - llvm::Type *Tys[2] = { GetNeonType(getLLVMContext(), 4, quad), Ty }; - Int = usgn ? Intrinsic::arm_neon_vcvtfxu2fp : Intrinsic::arm_neon_vcvtfxs2fp; + llvm::Type *FloatTy = + 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); 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_vcvtq_n_s32_v: case ARM::BI__builtin_neon_vcvtq_n_u32_v: { - llvm::Type *Tys[2] = { Ty, GetNeonType(getLLVMContext(), 4, quad) }; - Int = usgn ? Intrinsic::arm_neon_vcvtfp2fxu : Intrinsic::arm_neon_vcvtfp2fxs; + llvm::Type *FloatTy = + 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); 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_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), Ops, "vmul"); case ARM::BI__builtin_neon_vmull_v: 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"); case ARM::BI__builtin_neon_vpadal_v: case ARM::BI__builtin_neon_vpadalq_v: { diff --git a/lib/Sema/SemaChecking.cpp b/lib/Sema/SemaChecking.cpp index 50bc5755dd..90b9738039 100644 --- a/lib/Sema/SemaChecking.cpp +++ b/lib/Sema/SemaChecking.cpp @@ -245,27 +245,25 @@ Sema::CheckBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall) { // Get the valid immediate range for the specified NEON type code. static unsigned RFT(unsigned t, bool shift = false) { - bool quad = t & 0x10; - - switch (t & 0x7) { - case 0: // i8 - return shift ? 7 : (8 << (int)quad) - 1; - case 1: // i16 - return shift ? 15 : (4 << (int)quad) - 1; - case 2: // i32 - return shift ? 31 : (2 << (int)quad) - 1; - case 3: // i64 - return shift ? 63 : (1 << (int)quad) - 1; - case 4: // f32 - assert(!shift && "cannot shift float types!"); - return (2 << (int)quad) - 1; - case 5: // poly8 - return shift ? 7 : (8 << (int)quad) - 1; - case 6: // poly16 - return shift ? 15 : (4 << (int)quad) - 1; - case 7: // float16 - assert(!shift && "cannot shift float types!"); - return (4 << (int)quad) - 1; + NeonTypeFlags Type(t); + int IsQuad = Type.isQuad(); + switch (Type.getEltType()) { + case NeonTypeFlags::Int8: + case NeonTypeFlags::Poly8: + return shift ? 7 : (8 << IsQuad) - 1; + case NeonTypeFlags::Int16: + case NeonTypeFlags::Poly16: + return shift ? 15 : (4 << IsQuad) - 1; + case NeonTypeFlags::Int32: + return shift ? 31 : (2 << IsQuad) - 1; + case NeonTypeFlags::Int64: + return shift ? 63 : (1 << IsQuad) - 1; + case NeonTypeFlags::Float16: + assert(!shift && "cannot shift float types!"); + return (4 << IsQuad) - 1; + case NeonTypeFlags::Float32: + assert(!shift && "cannot shift float types!"); + return (2 << IsQuad) - 1; } return 0; } @@ -288,8 +286,8 @@ bool Sema::CheckARMBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall) { if (SemaBuiltinConstantArg(TheCall, ArgNo, Result)) return true; - TV = Result.getLimitedValue(32); - if ((TV > 31) || (mask & (1 << TV)) == 0) + TV = Result.getLimitedValue(64); + if ((TV > 63) || (mask & (1 << TV)) == 0) return Diag(TheCall->getLocStart(), diag::err_invalid_neon_type_code) << TheCall->getArg(ArgNo)->getSourceRange(); } diff --git a/utils/TableGen/NeonEmitter.cpp b/utils/TableGen/NeonEmitter.cpp index 66845ccacb..f393dff614 100644 --- a/utils/TableGen/NeonEmitter.cpp +++ b/utils/TableGen/NeonEmitter.cpp @@ -833,7 +833,6 @@ static std::string GenOpString(OpKind op, const std::string &proto, static unsigned GetNeonEnum(const std::string &proto, StringRef typestr) { unsigned mod = proto[0]; - unsigned ret = 0; if (mod == 'v' || mod == 'f') 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. type = ModType(mod, type, quad, poly, usgn, scal, cnst, pntr); - if (usgn) - ret |= 0x08; - if (quad && proto[1] != 'g') - ret |= 0x10; - + NeonTypeFlags::EltType ET; switch (type) { case 'c': - ret |= poly ? 5 : 0; + ET = poly ? NeonTypeFlags::Poly8 : NeonTypeFlags::Int8; break; case 's': - ret |= poly ? 6 : 1; + ET = poly ? NeonTypeFlags::Poly16 : NeonTypeFlags::Int16; break; case 'i': - ret |= 2; + ET = NeonTypeFlags::Int32; break; case 'l': - ret |= 3; + ET = NeonTypeFlags::Int64; break; case 'h': - ret |= 7; + ET = NeonTypeFlags::Float16; break; case 'f': - ret |= 4; + ET = NeonTypeFlags::Float32; break; default: throw "unhandled type!"; 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) diff --git a/utils/TableGen/NeonEmitter.h b/utils/TableGen/NeonEmitter.h index 708ad3c06a..dec7451111 100644 --- a/utils/TableGen/NeonEmitter.h +++ b/utils/TableGen/NeonEmitter.h @@ -86,6 +86,40 @@ enum ClassKind { 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 { class NeonEmitter : public TableGenBackend { |