Index: include/clang/Basic/TargetInfo.h =================================================================== --- include/clang/Basic/TargetInfo.h +++ include/clang/Basic/TargetInfo.h @@ -61,6 +61,7 @@ bool TLSSupported; bool VLASupported; bool NoAsmVariants; // True if {|} are normal characters. + bool HasFloat16; // True if the target has native half-precision support. bool HasFloat128; unsigned char PointerWidth, PointerAlign; unsigned char BoolWidth, BoolAlign; @@ -361,6 +362,9 @@ return (getPointerWidth(0) >= 64) || getTargetOpts().ForceEnableInt128; } // FIXME + /// \brief Determine whether _Float16 is supported on this target. + virtual bool hasFloat16Type() const { return HasFloat16; } + /// \brief Determine whether the __float128 type is supported on this target. virtual bool hasFloat128Type() const { return HasFloat128; } Index: lib/Basic/TargetInfo.cpp =================================================================== --- lib/Basic/TargetInfo.cpp +++ lib/Basic/TargetInfo.cpp @@ -32,6 +32,7 @@ TLSSupported = true; VLASupported = true; NoAsmVariants = false; + HasFloat16 = false; HasFloat128 = false; PointerWidth = PointerAlign = 32; BoolWidth = BoolAlign = 8; Index: lib/Basic/Targets/AArch64.cpp =================================================================== --- lib/Basic/Targets/AArch64.cpp +++ lib/Basic/Targets/AArch64.cpp @@ -49,6 +49,9 @@ IntMaxType = SignedLong; } + // AArch64 has H-registers and at least some level instruction half-precision + // support (as opposed to ARM, where it can be completely unsupported). + HasFloat16 = true; LongWidth = LongAlign = PointerWidth = PointerAlign = 64; MaxVectorAlign = 128; Index: lib/Basic/Targets/ARM.h =================================================================== --- lib/Basic/Targets/ARM.h +++ 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: lib/Basic/Targets/ARM.cpp =================================================================== --- lib/Basic/Targets/ARM.cpp +++ 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; + HasFloat16 = 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) && HasFloat16) Builder.defineMacro("__ARM_FEATURE_FP16_VECTOR_ARITHMETIC", "1"); // Armv8.2-A FP16 scalar intrinsics - if (HasFullFP16) + if (HasFloat16) Builder.defineMacro("__ARM_FEATURE_FP16_SCALAR_ARITHMETIC", "1"); Index: lib/CodeGen/CGBuiltin.cpp =================================================================== --- lib/CodeGen/CGBuiltin.cpp +++ lib/CodeGen/CGBuiltin.cpp @@ -3442,6 +3442,7 @@ static llvm::VectorType *GetNeonType(CodeGenFunction *CGF, NeonTypeFlags TypeFlags, llvm::Triple::ArchType Arch, + bool HasFloat16=true, bool V1Ty=false) { int IsQuad = TypeFlags.isQuad(); switch (TypeFlags.getEltType()) { @@ -3452,9 +3453,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 (HasFloat16) return llvm::VectorType::get(CGF->HalfTy, V1Ty ? 1 : (4 << IsQuad)); else return llvm::VectorType::get(CGF->Int16Ty, V1Ty ? 1 : (4 << IsQuad)); @@ -4338,8 +4337,9 @@ NeonTypeFlags Type(NeonTypeConst.getZExtValue()); bool Usgn = Type.isUnsigned(); bool Quad = Type.isQuad(); + const bool HasFloat16 = getTarget().hasFloat16Type(); - llvm::VectorType *VTy = GetNeonType(this, Type, Arch); + llvm::VectorType *VTy = GetNeonType(this, Type, Arch, HasFloat16); llvm::Type *Ty = VTy; if (!Ty) return nullptr; @@ -4413,13 +4413,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), + Arch, HasFloat16); 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), Arch, + HasFloat16); 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 +5530,8 @@ bool usgn = Type.isUnsigned(); bool rightShift = false; - llvm::VectorType *VTy = GetNeonType(this, Type, Arch); + llvm::VectorType *VTy = GetNeonType(this, Type, Arch, + getTarget().hasFloat16Type()); llvm::Type *Ty = VTy; if (!Ty) return nullptr;