Index: cfe/trunk/include/clang/Basic/TargetInfo.h =================================================================== --- cfe/trunk/include/clang/Basic/TargetInfo.h +++ cfe/trunk/include/clang/Basic/TargetInfo.h @@ -61,6 +61,8 @@ bool TLSSupported; bool VLASupported; bool NoAsmVariants; // True if {|} are normal characters. + bool HasLegalHalfType; // True if the backend supports operations on the half + // LLVM IR type. bool HasFloat128; unsigned char PointerWidth, PointerAlign; unsigned char BoolWidth, BoolAlign; @@ -361,6 +363,9 @@ return (getPointerWidth(0) >= 64) || getTargetOpts().ForceEnableInt128; } // FIXME + /// \brief Determine whether _Float16 is supported on this target. + virtual bool hasLegalHalfType() const { return HasLegalHalfType; } + /// \brief Determine whether the __float128 type is supported on this target. virtual bool hasFloat128Type() const { return HasFloat128; } Index: cfe/trunk/lib/Basic/TargetInfo.cpp =================================================================== --- cfe/trunk/lib/Basic/TargetInfo.cpp +++ cfe/trunk/lib/Basic/TargetInfo.cpp @@ -32,6 +32,7 @@ TLSSupported = true; VLASupported = true; NoAsmVariants = false; + HasLegalHalfType = false; HasFloat128 = false; PointerWidth = PointerAlign = 32; BoolWidth = BoolAlign = 8; Index: cfe/trunk/lib/Basic/Targets/AArch64.cpp =================================================================== --- cfe/trunk/lib/Basic/Targets/AArch64.cpp +++ cfe/trunk/lib/Basic/Targets/AArch64.cpp @@ -49,6 +49,8 @@ IntMaxType = SignedLong; } + // All AArch64 implementations support ARMv8 FP, which makes half a legal type. + HasLegalHalfType = true; LongWidth = LongAlign = PointerWidth = PointerAlign = 64; MaxVectorAlign = 128; Index: cfe/trunk/lib/Basic/Targets/ARM.h =================================================================== --- cfe/trunk/lib/Basic/Targets/ARM.h +++ cfe/trunk/lib/Basic/Targets/ARM.h @@ -69,7 +69,6 @@ unsigned Crypto : 1; unsigned DSP : 1; unsigned Unaligned : 1; - unsigned HasFullFP16 : 1; enum { LDREX_B = (1 << 0), /// byte (8-bit) Index: cfe/trunk/lib/Basic/Targets/ARM.cpp =================================================================== --- cfe/trunk/lib/Basic/Targets/ARM.cpp +++ cfe/trunk/lib/Basic/Targets/ARM.cpp @@ -379,7 +379,6 @@ Unaligned = 1; SoftFloat = SoftFloatABI = false; HWDiv = 0; - HasFullFP16 = 0; // This does not diagnose illegal cases like having both // "+vfpv2" and "+vfpv3" or having "+neon" and "+fp-only-sp". @@ -421,7 +420,7 @@ } else if (Feature == "+fp16") { HW_FP |= HW_FP_HP; } else if (Feature == "+fullfp16") { - HasFullFP16 = 1; + HasLegalHalfType = true; } } HW_FP &= ~HW_FP_remove; @@ -714,11 +713,11 @@ Builder.defineMacro("__ARM_FP_FAST", "1"); // Armv8.2-A FP16 vector intrinsic - if ((FPU & NeonFPU) && HasFullFP16) + if ((FPU & NeonFPU) && HasLegalHalfType) Builder.defineMacro("__ARM_FEATURE_FP16_VECTOR_ARITHMETIC", "1"); // Armv8.2-A FP16 scalar intrinsics - if (HasFullFP16) + if (HasLegalHalfType) Builder.defineMacro("__ARM_FEATURE_FP16_SCALAR_ARITHMETIC", "1"); Index: cfe/trunk/lib/CodeGen/CGBuiltin.cpp =================================================================== --- cfe/trunk/lib/CodeGen/CGBuiltin.cpp +++ cfe/trunk/lib/CodeGen/CGBuiltin.cpp @@ -3441,7 +3441,7 @@ static llvm::VectorType *GetNeonType(CodeGenFunction *CGF, NeonTypeFlags TypeFlags, - llvm::Triple::ArchType Arch, + bool HasLegalHalfType=true, bool V1Ty=false) { int IsQuad = TypeFlags.isQuad(); switch (TypeFlags.getEltType()) { @@ -3452,9 +3452,7 @@ case NeonTypeFlags::Poly16: return llvm::VectorType::get(CGF->Int16Ty, V1Ty ? 1 : (4 << IsQuad)); case NeonTypeFlags::Float16: - // FIXME: Only AArch64 backend can so far properly handle half types. - // Remove else part once ARM backend support for half is complete. - if (Arch == llvm::Triple::aarch64) + if (HasLegalHalfType) return llvm::VectorType::get(CGF->HalfTy, V1Ty ? 1 : (4 << IsQuad)); else return llvm::VectorType::get(CGF->Int16Ty, V1Ty ? 1 : (4 << IsQuad)); @@ -4338,8 +4336,9 @@ NeonTypeFlags Type(NeonTypeConst.getZExtValue()); bool Usgn = Type.isUnsigned(); bool Quad = Type.isQuad(); + const bool HasLegalHalfType = getTarget().hasLegalHalfType(); - llvm::VectorType *VTy = GetNeonType(this, Type, Arch); + llvm::VectorType *VTy = GetNeonType(this, Type, HasLegalHalfType); llvm::Type *Ty = VTy; if (!Ty) return nullptr; @@ -4413,13 +4412,15 @@ case NEON::BI__builtin_neon_vcvt_f32_v: case NEON::BI__builtin_neon_vcvtq_f32_v: Ops[0] = Builder.CreateBitCast(Ops[0], Ty); - Ty = GetNeonType(this, NeonTypeFlags(NeonTypeFlags::Float32, false, Quad), Arch); + Ty = GetNeonType(this, NeonTypeFlags(NeonTypeFlags::Float32, false, Quad), + HasLegalHalfType); return Usgn ? Builder.CreateUIToFP(Ops[0], Ty, "vcvt") : Builder.CreateSIToFP(Ops[0], Ty, "vcvt"); case NEON::BI__builtin_neon_vcvt_f16_v: case NEON::BI__builtin_neon_vcvtq_f16_v: Ops[0] = Builder.CreateBitCast(Ops[0], Ty); - Ty = GetNeonType(this, NeonTypeFlags(NeonTypeFlags::Float16, false, Quad), Arch); + Ty = GetNeonType(this, NeonTypeFlags(NeonTypeFlags::Float16, false, Quad), + HasLegalHalfType); return Usgn ? Builder.CreateUIToFP(Ops[0], Ty, "vcvt") : Builder.CreateSIToFP(Ops[0], Ty, "vcvt"); case NEON::BI__builtin_neon_vcvt_n_f16_v: @@ -5528,7 +5529,8 @@ bool usgn = Type.isUnsigned(); bool rightShift = false; - llvm::VectorType *VTy = GetNeonType(this, Type, Arch); + llvm::VectorType *VTy = GetNeonType(this, Type, + getTarget().hasLegalHalfType()); llvm::Type *Ty = VTy; if (!Ty) return nullptr; @@ -5774,7 +5776,7 @@ // Determine the type of this overloaded NEON intrinsic. NeonTypeFlags Type(Result.getZExtValue()); - llvm::VectorType *Ty = GetNeonType(&CGF, Type, Arch); + llvm::VectorType *Ty = GetNeonType(&CGF, Type); if (!Ty) return nullptr; @@ -6828,7 +6830,7 @@ } } - llvm::VectorType *VTy = GetNeonType(this, Type, Arch); + llvm::VectorType *VTy = GetNeonType(this, Type); llvm::Type *Ty = VTy; if (!Ty) return nullptr; @@ -6893,7 +6895,7 @@ Ops[0] = Builder.CreateBitCast(Ops[0], DoubleTy); Ops[1] = Builder.CreateBitCast(Ops[1], DoubleTy); llvm::Type *VTy = GetNeonType(this, - NeonTypeFlags(NeonTypeFlags::Float64, false, true), Arch); + NeonTypeFlags(NeonTypeFlags::Float64, false, true)); Ops[2] = Builder.CreateBitCast(Ops[2], VTy); Ops[2] = Builder.CreateExtractElement(Ops[2], Ops[3], "extract"); Value *F = CGM.getIntrinsic(Intrinsic::fma, DoubleTy); @@ -7132,14 +7134,14 @@ case NEON::BI__builtin_neon_vcvt_f64_v: case NEON::BI__builtin_neon_vcvtq_f64_v: Ops[0] = Builder.CreateBitCast(Ops[0], Ty); - Ty = GetNeonType(this, NeonTypeFlags(NeonTypeFlags::Float64, false, quad), Arch); + Ty = GetNeonType(this, NeonTypeFlags(NeonTypeFlags::Float64, false, quad)); return usgn ? Builder.CreateUIToFP(Ops[0], Ty, "vcvt") : Builder.CreateSIToFP(Ops[0], Ty, "vcvt"); case NEON::BI__builtin_neon_vcvt_f64_f32: { assert(Type.getEltType() == NeonTypeFlags::Float64 && quad && "unexpected vcvt_f64_f32 builtin"); NeonTypeFlags SrcFlag = NeonTypeFlags(NeonTypeFlags::Float32, false, false); - Ops[0] = Builder.CreateBitCast(Ops[0], GetNeonType(this, SrcFlag, Arch)); + Ops[0] = Builder.CreateBitCast(Ops[0], GetNeonType(this, SrcFlag)); return Builder.CreateFPExt(Ops[0], Ty, "vcvt"); } @@ -7147,7 +7149,7 @@ assert(Type.getEltType() == NeonTypeFlags::Float32 && "unexpected vcvt_f32_f64 builtin"); NeonTypeFlags SrcFlag = NeonTypeFlags(NeonTypeFlags::Float64, false, true); - Ops[0] = Builder.CreateBitCast(Ops[0], GetNeonType(this, SrcFlag, Arch)); + Ops[0] = Builder.CreateBitCast(Ops[0], GetNeonType(this, SrcFlag)); return Builder.CreateFPTrunc(Ops[0], Ty, "vcvt"); } @@ -7244,7 +7246,7 @@ Quad = true; Ops[0] = Builder.CreateBitCast(Ops[0], DoubleTy); llvm::Type *VTy = GetNeonType(this, - NeonTypeFlags(NeonTypeFlags::Float64, false, Quad), Arch); + NeonTypeFlags(NeonTypeFlags::Float64, false, Quad)); Ops[1] = Builder.CreateBitCast(Ops[1], VTy); Ops[1] = Builder.CreateExtractElement(Ops[1], Ops[2], "extract"); Value *Result = Builder.CreateFMul(Ops[0], Ops[1]);