https://github.com/arsenm created https://github.com/llvm/llvm-project/pull/207212
Follow up to #174494. Remove the remnants of the control to use llvm.convert.to.fp16/llvm.convert.from.fp16. Prefer directly using the IR half type, unless the value is used in an ABI context where it needs to remain as i16. I did the first 80% of this a long time ago, and AI finished the last bit and handled the recent rebases and test updates. Co-authored-by: Claude (Opus 4.8) <[email protected]> >From bb9a3c209804806753d04f35036bda728d406be5 Mon Sep 17 00:00:00 2001 From: Matt Arsenault <[email protected]> Date: Mon, 5 Jan 2026 23:15:43 +0100 Subject: [PATCH] clang: Remove useFP16ConversionIntrinsics target option Follow up to #174494. Remove the remnants of the control to use llvm.convert.to.fp16/llvm.convert.from.fp16. Prefer directly using the IR half type, unless the value is used in an ABI context where it needs to remain as i16. I did the first 80% of this a long time ago, and AI finished the last bit and handled the recent rebases and test updates. Co-authored-by: Claude (Opus 4.8) <[email protected]> --- clang/include/clang/Basic/TargetInfo.h | 10 --- clang/lib/Basic/Targets/AArch64.h | 4 - clang/lib/Basic/Targets/AMDGPU.h | 2 - clang/lib/Basic/Targets/ARM.h | 4 - clang/lib/Basic/Targets/DirectX.h | 1 - clang/lib/Basic/Targets/LoongArch.h | 2 - clang/lib/Basic/Targets/NVPTX.h | 2 - clang/lib/Basic/Targets/RISCV.h | 4 - clang/lib/Basic/Targets/SPIR.h | 4 - clang/lib/Basic/Targets/SystemZ.h | 2 - clang/lib/Basic/Targets/WebAssembly.h | 1 - clang/lib/Basic/Targets/X86.h | 4 - clang/lib/CIR/CodeGen/CIRGenExprConstant.cpp | 10 +-- clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp | 22 +----- clang/lib/CIR/CodeGen/CIRGenTypes.cpp | 8 +- clang/lib/CodeGen/CGExprConstant.cpp | 12 +-- clang/lib/CodeGen/CGExprScalar.cpp | 54 ++++---------- clang/lib/CodeGen/CodeGenTypes.cpp | 28 +++---- clang/lib/CodeGen/TargetBuiltins/NVPTX.cpp | 22 +----- clang/lib/Sema/SemaChecking.cpp | 20 ++--- clang/lib/Sema/SemaExpr.cpp | 3 +- clang/test/CodeGen/builtin_float.c | 7 +- clang/test/CodeGen/builtin_float_strictfp.c | 8 +- clang/test/CodeGen/wasm-fp16.c | 77 ++++++++------------ 24 files changed, 79 insertions(+), 232 deletions(-) diff --git a/clang/include/clang/Basic/TargetInfo.h b/clang/include/clang/Basic/TargetInfo.h index d1914d626c753..b3af03cbc2f66 100644 --- a/clang/include/clang/Basic/TargetInfo.h +++ b/clang/include/clang/Basic/TargetInfo.h @@ -1017,16 +1017,6 @@ class TargetInfo : public TransferrableTargetInfo, return ComplexLongDoubleUsesFP2Ret; } - /// Check whether conversions to and from __fp16 should go through an integer - /// bitcast with i16. - /// - /// FIXME: This function should be removed. The intrinsics / no longer exist, - /// and are emulated with bitcast + fp cast. This only exists because of - /// misuse in ABI determining contexts. - virtual bool useFP16ConversionIntrinsics() const { - return true; - } - /// Specify if mangling based on address space map should be used or /// not for language specific address spaces bool useAddressSpaceMapMangling() const { diff --git a/clang/lib/Basic/Targets/AArch64.h b/clang/lib/Basic/Targets/AArch64.h index b4b66db34b9b7..04d0fa84684ef 100644 --- a/clang/lib/Basic/Targets/AArch64.h +++ b/clang/lib/Basic/Targets/AArch64.h @@ -171,10 +171,6 @@ class LLVM_LIBRARY_VISIBILITY AArch64TargetInfo : public TargetInfo { llvm::APInt getFMVPriority(ArrayRef<StringRef> Features) const override; - bool useFP16ConversionIntrinsics() const override { - return false; - } - void getTargetDefinesARMV81A(const LangOptions &Opts, MacroBuilder &Builder) const; void getTargetDefinesARMV82A(const LangOptions &Opts, diff --git a/clang/lib/Basic/Targets/AMDGPU.h b/clang/lib/Basic/Targets/AMDGPU.h index b13e9008b67a4..7bd34526105d3 100644 --- a/clang/lib/Basic/Targets/AMDGPU.h +++ b/clang/lib/Basic/Targets/AMDGPU.h @@ -263,8 +263,6 @@ class LLVM_LIBRARY_VISIBILITY AMDGPUTargetInfo final : public TargetInfo { llvm::SmallVector<Builtin::InfosShard> getTargetBuiltins() const override; - bool useFP16ConversionIntrinsics() const override { return false; } - void getTargetDefines(const LangOptions &Opts, MacroBuilder &Builder) const override; diff --git a/clang/lib/Basic/Targets/ARM.h b/clang/lib/Basic/Targets/ARM.h index 8bd56c8855fe3..976e1e06ae9b2 100644 --- a/clang/lib/Basic/Targets/ARM.h +++ b/clang/lib/Basic/Targets/ARM.h @@ -177,10 +177,6 @@ class LLVM_LIBRARY_VISIBILITY ARMTargetInfo : public TargetInfo { bool setFPMath(StringRef Name) override; - bool useFP16ConversionIntrinsics() const override { - return false; - } - void getTargetDefinesARMV81A(const LangOptions &Opts, MacroBuilder &Builder) const; void getTargetDefinesARMV82A(const LangOptions &Opts, diff --git a/clang/lib/Basic/Targets/DirectX.h b/clang/lib/Basic/Targets/DirectX.h index 8b21b86bac264..64e5533bbffeb 100644 --- a/clang/lib/Basic/Targets/DirectX.h +++ b/clang/lib/Basic/Targets/DirectX.h @@ -70,7 +70,6 @@ class LLVM_LIBRARY_VISIBILITY DirectXTargetInfo : public TargetInfo { resetDataLayout(); TheCXXABI.set(TargetCXXABI::GenericItanium); } - bool useFP16ConversionIntrinsics() const override { return false; } void getTargetDefines(const LangOptions &Opts, MacroBuilder &Builder) const override; diff --git a/clang/lib/Basic/Targets/LoongArch.h b/clang/lib/Basic/Targets/LoongArch.h index 16124a87d4955..4c98f9d0e40ae 100644 --- a/clang/lib/Basic/Targets/LoongArch.h +++ b/clang/lib/Basic/Targets/LoongArch.h @@ -107,8 +107,6 @@ class LLVM_LIBRARY_VISIBILITY LoongArchTargetInfo : public TargetInfo { bool hasBFloat16Type() const override { return true; } - bool useFP16ConversionIntrinsics() const override { return false; } - bool handleTargetFeatures(std::vector<std::string> &Features, DiagnosticsEngine &Diags) override; diff --git a/clang/lib/Basic/Targets/NVPTX.h b/clang/lib/Basic/Targets/NVPTX.h index 8af9cb91c47ab..00be0fe54c1bd 100644 --- a/clang/lib/Basic/Targets/NVPTX.h +++ b/clang/lib/Basic/Targets/NVPTX.h @@ -82,8 +82,6 @@ class LLVM_LIBRARY_VISIBILITY NVPTXTargetInfo : public TargetInfo { llvm::SmallVector<Builtin::InfosShard> getTargetBuiltins() const override; - bool useFP16ConversionIntrinsics() const override { return false; } - bool isCLZForZeroUndef() const override { return false; } bool diff --git a/clang/lib/Basic/Targets/RISCV.h b/clang/lib/Basic/Targets/RISCV.h index 193f77fe68a0b..73287c5d2d58d 100644 --- a/clang/lib/Basic/Targets/RISCV.h +++ b/clang/lib/Basic/Targets/RISCV.h @@ -117,10 +117,6 @@ class RISCVTargetInfo : public TargetInfo { CallingConvCheckResult checkCallingConvention(CallingConv CC) const override; - bool useFP16ConversionIntrinsics() const override { - return false; - } - bool isValidCPUName(StringRef Name) const override; void fillValidCPUList(SmallVectorImpl<StringRef> &Values) const override; bool isValidTuneCPUName(StringRef Name) const override; diff --git a/clang/lib/Basic/Targets/SPIR.h b/clang/lib/Basic/Targets/SPIR.h index 389cc075a3a0b..42256920f353e 100644 --- a/clang/lib/Basic/Targets/SPIR.h +++ b/clang/lib/Basic/Targets/SPIR.h @@ -173,10 +173,6 @@ class LLVM_LIBRARY_VISIBILITY BaseSPIRTargetInfo : public TargetInfo { } public: - // SPIR supports the half type and the only llvm intrinsic allowed in SPIR is - // memcpy as per section 3 of the SPIR spec. - bool useFP16ConversionIntrinsics() const override { return false; } - llvm::SmallVector<Builtin::InfosShard> getTargetBuiltins() const override { return {}; } diff --git a/clang/lib/Basic/Targets/SystemZ.h b/clang/lib/Basic/Targets/SystemZ.h index 70b529e8ca854..d56306c7c4a88 100644 --- a/clang/lib/Basic/Targets/SystemZ.h +++ b/clang/lib/Basic/Targets/SystemZ.h @@ -107,8 +107,6 @@ class LLVM_LIBRARY_VISIBILITY SystemZTargetInfo : public TargetInfo { unsigned getMinGlobalAlign(uint64_t Size, bool HasNonWeakDef) const override; - bool useFP16ConversionIntrinsics() const override { return false; } - void getTargetDefines(const LangOptions &Opts, MacroBuilder &Builder) const override; diff --git a/clang/lib/Basic/Targets/WebAssembly.h b/clang/lib/Basic/Targets/WebAssembly.h index 88192a756cc4f..0b0266a48469a 100644 --- a/clang/lib/Basic/Targets/WebAssembly.h +++ b/clang/lib/Basic/Targets/WebAssembly.h @@ -120,7 +120,6 @@ class LLVM_LIBRARY_VISIBILITY WebAssemblyTargetInfo : public TargetInfo { StringRef getABI() const override; bool setABI(const std::string &Name) override; - bool useFP16ConversionIntrinsics() const override { return !HasFP16; } protected: void getTargetDefines(const LangOptions &Opts, diff --git a/clang/lib/Basic/Targets/X86.h b/clang/lib/Basic/Targets/X86.h index b0daffbea4576..641bb78906610 100644 --- a/clang/lib/Basic/Targets/X86.h +++ b/clang/lib/Basic/Targets/X86.h @@ -338,10 +338,6 @@ class LLVM_LIBRARY_VISIBILITY X86TargetInfo : public TargetInfo { return ""; } - bool useFP16ConversionIntrinsics() const override { - return false; - } - void getTargetDefines(const LangOptions &Opts, MacroBuilder &Builder) const override; diff --git a/clang/lib/CIR/CodeGen/CIRGenExprConstant.cpp b/clang/lib/CIR/CodeGen/CIRGenExprConstant.cpp index 384b975b3f422..ffb0f9148c876 100644 --- a/clang/lib/CIR/CodeGen/CIRGenExprConstant.cpp +++ b/clang/lib/CIR/CodeGen/CIRGenExprConstant.cpp @@ -1304,18 +1304,10 @@ mlir::Attribute ConstantEmitter::tryEmitPrivate(const APValue &value, return cir::IntAttr::get(ty, value.getInt()); } case APValue::Float: { - const llvm::APFloat &init = value.getFloat(); - if (&init.getSemantics() == &llvm::APFloat::IEEEhalf() && - !cgm.getASTContext().getLangOpts().NativeHalfType && - cgm.getASTContext().getTargetInfo().useFP16ConversionIntrinsics()) { - cgm.errorNYI("ConstExprEmitter::tryEmitPrivate half"); - return {}; - } - mlir::Type ty = cgm.convertType(destType); assert(mlir::isa<cir::FPTypeInterface>(ty) && "expected floating-point type"); - return cir::FPAttr::get(ty, init); + return cir::FPAttr::get(ty, value.getFloat()); } case APValue::Array: { const ArrayType *arrayTy = cgm.getASTContext().getAsArrayType(destType); diff --git a/clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp b/clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp index 3c2d2726ac9fa..645cca9fe16eb 100644 --- a/clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp +++ b/clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp @@ -969,19 +969,10 @@ class ScalarExprEmitter : public StmtVisitor<ScalarExprEmitter, mlir::Value> { if (srcType->isHalfType() && !cgf.getContext().getLangOpts().NativeHalfType) { // Cast to FP using the intrinsic if the half type itself isn't supported. - if (mlir::isa<cir::FPTypeInterface>(mlirDstType)) { - if (cgf.getContext().getTargetInfo().useFP16ConversionIntrinsics()) - cgf.getCIRGenModule().errorNYI(loc, - "cast via llvm.convert.from.fp16"); - } else { - // Cast to other types through float, using either the intrinsic or - // FPExt, depending on whether the half type itself is supported (as - // opposed to operations on half, available with NativeHalfType). - if (cgf.getContext().getTargetInfo().useFP16ConversionIntrinsics()) - cgf.getCIRGenModule().errorNYI(loc, - "cast via llvm.convert.from.fp16"); - // FIXME(cir): For now lets pretend we shouldn't use the conversion - // intrinsics and insert a cast here unconditionally. + if (!mlir::isa<cir::FPTypeInterface>(mlirDstType)) { + // Cast to other types through float, using FPExt, depending on whether + // the half type itself is supported (as opposed to operations on half, + // available with NativeHalfType). src = builder.createCast(cgf.getLoc(loc), cir::CastKind::floating, src, cgf.floatTy); srcType = cgf.getContext().FloatTy; @@ -1039,11 +1030,6 @@ class ScalarExprEmitter : public StmtVisitor<ScalarExprEmitter, mlir::Value> { res = emitScalarCast(src, srcType, dstType, mlirSrcType, mlirDstType, opts); if (mlirDstType != resTy) { - if (cgf.getContext().getTargetInfo().useFP16ConversionIntrinsics()) { - cgf.getCIRGenModule().errorNYI(loc, "cast via llvm.convert.to.fp16"); - } - // FIXME(cir): For now we never use FP16 conversion intrinsics even if - // required by the target. Change that once this is implemented res = builder.createCast(cgf.getLoc(loc), cir::CastKind::floating, res, resTy); } diff --git a/clang/lib/CIR/CodeGen/CIRGenTypes.cpp b/clang/lib/CIR/CodeGen/CIRGenTypes.cpp index 3170666304a06..298c44d849782 100644 --- a/clang/lib/CIR/CodeGen/CIRGenTypes.cpp +++ b/clang/lib/CIR/CodeGen/CIRGenTypes.cpp @@ -449,13 +449,7 @@ mlir::Type CIRGenTypes::convertType(QualType type) { resultType = cgm.fP16Ty; break; case BuiltinType::Half: - if (astContext.getLangOpts().NativeHalfType || - !astContext.getTargetInfo().useFP16ConversionIntrinsics()) { - resultType = cgm.fP16Ty; - } else { - cgm.errorNYI(SourceLocation(), "processing of built-in type", type); - resultType = cgm.sInt32Ty; - } + resultType = cgm.fP16Ty; break; case BuiltinType::BFloat16: resultType = cgm.bFloat16Ty; diff --git a/clang/lib/CodeGen/CGExprConstant.cpp b/clang/lib/CodeGen/CGExprConstant.cpp index 7a2b00647f189..27b7423a42f98 100644 --- a/clang/lib/CodeGen/CGExprConstant.cpp +++ b/clang/lib/CodeGen/CGExprConstant.cpp @@ -2598,16 +2598,8 @@ ConstantEmitter::tryEmitPrivate(const APValue &Value, QualType DestType, llvm::StructType::get(Complex[0]->getType(), Complex[1]->getType()); return llvm::ConstantStruct::get(STy, Complex); } - case APValue::Float: { - const llvm::APFloat &Init = Value.getFloat(); - if (&Init.getSemantics() == &llvm::APFloat::IEEEhalf() && - !CGM.getContext().getLangOpts().NativeHalfType && - CGM.getContext().getTargetInfo().useFP16ConversionIntrinsics()) - return llvm::ConstantInt::get(CGM.getLLVMContext(), - Init.bitcastToAPInt()); - else - return llvm::ConstantFP::get(CGM.getLLVMContext(), Init); - } + case APValue::Float: + return llvm::ConstantFP::get(CGM.getLLVMContext(), Value.getFloat()); case APValue::ComplexFloat: { llvm::Constant *Complex[2]; diff --git a/clang/lib/CodeGen/CGExprScalar.cpp b/clang/lib/CodeGen/CGExprScalar.cpp index 18ed6570730f4..6f7b7e7d6840e 100644 --- a/clang/lib/CodeGen/CGExprScalar.cpp +++ b/clang/lib/CodeGen/CGExprScalar.cpp @@ -1690,28 +1690,17 @@ Value *ScalarExprEmitter::EmitScalarConversion(Value *Src, QualType SrcType, bool OBWrapInvolved = (DstOBT && DstOBT->isWrapKind()) || (SrcOBT && SrcOBT->isWrapKind()); - // Cast from half through float if half isn't a native type. - if (SrcType->isHalfType() && !CGF.getContext().getLangOpts().NativeHalfType) { - // Cast to FP using the intrinsic if the half type itself isn't supported. - if (DstTy->isFloatingPointTy()) { - if (CGF.getContext().getTargetInfo().useFP16ConversionIntrinsics()) { - Value *BitCast = Builder.CreateBitCast(Src, CGF.CGM.HalfTy); - return Builder.CreateFPExt(BitCast, DstTy, "conv"); - } - } else { - // Cast to other types through float, using either the intrinsic or FPExt, - // depending on whether the half type itself is supported - // (as opposed to operations on half, available with NativeHalfType). + // If half isn't a native type, cast to float for evaluation. + if (SrcType->isHalfType() && !CGF.getContext().getLangOpts().NativeHalfType && + SrcTy == CGF.CGM.HalfTy && DstTy != CGF.CGM.HalfTy) { + if (DstTy->isFloatingPointTy()) + return Builder.CreateFPExt(Src, DstTy, "conv"); - if (Src->getType() != CGF.CGM.HalfTy) { - assert(CGF.getContext().getTargetInfo().useFP16ConversionIntrinsics()); - Src = Builder.CreateBitCast(Src, CGF.CGM.HalfTy); - } - - Src = Builder.CreateFPExt(Src, CGF.CGM.FloatTy, "conv"); - SrcType = CGF.getContext().FloatTy; - SrcTy = CGF.FloatTy; - } + // Cast to other types through float (as opposed to operations on half, + // available with NativeHalfType). + Src = Builder.CreateFPExt(Src, CGF.CGM.FloatTy, "conv"); + SrcType = CGF.getContext().FloatTy; + SrcTy = CGF.FloatTy; } // Ignore conversions like int -> uint. @@ -1816,23 +1805,13 @@ Value *ScalarExprEmitter::EmitScalarConversion(Value *Src, QualType SrcType, EmitFloatConversionCheck(OrigSrc, OrigSrcType, Src, SrcType, DstType, DstTy, Loc); - // Cast to half through float if half isn't a native type. - if (DstType->isHalfType() && !CGF.getContext().getLangOpts().NativeHalfType) { + // Cast to half from float if half isn't a native type. When __fp16 isn't + // native, arithmetic is evaluated as float. + if (DstType->isHalfType() && !CGF.getContext().getLangOpts().NativeHalfType && + DstTy == CGF.CGM.HalfTy) { // Make sure we cast in a single step if from another FP type. - if (SrcTy->isFloatingPointTy()) { - // Handle the case where the half type is represented as an integer (as - // opposed to operations on half, available with NativeHalfType). - - // If the half type is supported, just use an fptrunc. - Value *Res = Builder.CreateFPTrunc(Src, CGF.CGM.HalfTy, "conv"); - if (DstTy == CGF.CGM.HalfTy) - return Res; - - assert(DstTy->isIntegerTy(16) && - CGF.getContext().getTargetInfo().useFP16ConversionIntrinsics() && - "Only half FP requires extra conversion"); - return Builder.CreateBitCast(Res, DstTy); - } + if (SrcTy->isFloatingPointTy()) + return Builder.CreateFPTrunc(Src, CGF.CGM.HalfTy, "conv"); DstTy = CGF.FloatTy; } @@ -1844,7 +1823,6 @@ Value *ScalarExprEmitter::EmitScalarConversion(Value *Src, QualType SrcType, if (ResTy != CGF.CGM.HalfTy) { assert(ResTy->isIntegerTy(16) && - CGF.getContext().getTargetInfo().useFP16ConversionIntrinsics() && "Only half FP requires extra conversion"); Res = Builder.CreateBitCast(Res, ResTy); } diff --git a/clang/lib/CodeGen/CodeGenTypes.cpp b/clang/lib/CodeGen/CodeGenTypes.cpp index 3de3bad6affb5..c68a24ca045bc 100644 --- a/clang/lib/CodeGen/CodeGenTypes.cpp +++ b/clang/lib/CodeGen/CodeGenTypes.cpp @@ -300,14 +300,9 @@ void CodeGenTypes::RefreshTypeCacheForClass(const CXXRecordDecl *RD) { } static llvm::Type *getTypeForFormat(llvm::LLVMContext &VMContext, - const llvm::fltSemantics &format, - bool UseNativeHalf = false) { - if (&format == &llvm::APFloat::IEEEhalf()) { - if (UseNativeHalf) - return llvm::Type::getHalfTy(VMContext); - else - return llvm::Type::getInt16Ty(VMContext); - } + const llvm::fltSemantics &format) { + if (&format == &llvm::APFloat::IEEEhalf()) + return llvm::Type::getHalfTy(VMContext); if (&format == &llvm::APFloat::BFloat()) return llvm::Type::getBFloatTy(VMContext); if (&format == &llvm::APFloat::IEEEsingle()) @@ -485,16 +480,14 @@ llvm::Type *CodeGenTypes::ConvertType(QualType T) { case BuiltinType::Float16: ResultType = - getTypeForFormat(getLLVMContext(), Context.getFloatTypeSemantics(T), - /* UseNativeHalf = */ true); + getTypeForFormat(getLLVMContext(), Context.getFloatTypeSemantics(T)); break; case BuiltinType::Half: - // Half FP can either be storage-only (lowered to i16) or native. - ResultType = getTypeForFormat( - getLLVMContext(), Context.getFloatTypeSemantics(T), - Context.getLangOpts().NativeHalfType || - !Context.getTargetInfo().useFP16ConversionIntrinsics()); + // Half FP can either be storage-only (lowered to i16 for ABI purposes) or + // native. + ResultType = + getTypeForFormat(getLLVMContext(), Context.getFloatTypeSemantics(T)); break; case BuiltinType::LongDouble: LongDoubleReferenced = true; @@ -504,9 +497,8 @@ llvm::Type *CodeGenTypes::ConvertType(QualType T) { case BuiltinType::Double: case BuiltinType::Float128: case BuiltinType::Ibm128: - ResultType = getTypeForFormat(getLLVMContext(), - Context.getFloatTypeSemantics(T), - /* UseNativeHalf = */ false); + ResultType = + getTypeForFormat(getLLVMContext(), Context.getFloatTypeSemantics(T)); break; case BuiltinType::NullPtr: diff --git a/clang/lib/CodeGen/TargetBuiltins/NVPTX.cpp b/clang/lib/CodeGen/TargetBuiltins/NVPTX.cpp index 0be166ce7bb38..48b6866147281 100644 --- a/clang/lib/CodeGen/TargetBuiltins/NVPTX.cpp +++ b/clang/lib/CodeGen/TargetBuiltins/NVPTX.cpp @@ -393,23 +393,8 @@ static Value *MakeCpAsync(unsigned IntrinsicID, unsigned IntrinsicIDS, CGF.EmitScalarExpr(E->getArg(1))}); } -static bool EnsureNativeHalfSupport(unsigned BuiltinID, const CallExpr *E, - CodeGenFunction &CGF) { - auto &C = CGF.CGM.getContext(); - if (!C.getLangOpts().NativeHalfType && - C.getTargetInfo().useFP16ConversionIntrinsics()) { - CGF.CGM.Error(E->getExprLoc(), C.BuiltinInfo.getQuotedName(BuiltinID) + - " requires native half type support."); - return false; - } - return true; -} - static Value *MakeHalfType(Function *Intrinsic, unsigned BuiltinID, const CallExpr *E, CodeGenFunction &CGF) { - if (!EnsureNativeHalfSupport(BuiltinID, E, CGF)) - return nullptr; - SmallVector<Value *, 16> Args; auto *FTy = Intrinsic->getFunctionType(); unsigned ICEArguments = 0; @@ -1128,13 +1113,10 @@ Value *CodeGenFunction::EmitNVPTXBuiltinExpr(unsigned BuiltinID, EmitScalarExpr(E->getArg(0))); case NVPTX::BI__nvvm_ldg_h: case NVPTX::BI__nvvm_ldg_h2: - return EnsureNativeHalfSupport(BuiltinID, E, *this) ? MakeLdg(*this, E) - : nullptr; + return MakeLdg(*this, E); case NVPTX::BI__nvvm_ldu_h: case NVPTX::BI__nvvm_ldu_h2: - return EnsureNativeHalfSupport(BuiltinID, E, *this) - ? MakeLdu(Intrinsic::nvvm_ldu_global_f, *this, E) - : nullptr; + return MakeLdu(Intrinsic::nvvm_ldu_global_f, *this, E); case NVPTX::BI__nvvm_cp_async_ca_shared_global_4: return MakeCpAsync(Intrinsic::nvvm_cp_async_ca_shared_global_4, Intrinsic::nvvm_cp_async_ca_shared_global_4_s, *this, E, diff --git a/clang/lib/Sema/SemaChecking.cpp b/clang/lib/Sema/SemaChecking.cpp index 01b1f4c26f017..24fa9055e4f9d 100644 --- a/clang/lib/Sema/SemaChecking.cpp +++ b/clang/lib/Sema/SemaChecking.cpp @@ -6416,22 +6416,12 @@ bool Sema::BuiltinFPClassification(CallExpr *TheCall, unsigned NumArgs, if (OrigArg->isTypeDependent()) return false; - // Usual Unary Conversions will convert half to float, which we want for - // machines that use fp16 conversion intrinsics. Else, we wnat to leave the - // type how it is, but do normal L->Rvalue conversions. - if (Context.getTargetInfo().useFP16ConversionIntrinsics()) { - ExprResult Res = UsualUnaryConversions(OrigArg); - - if (!Res.isUsable()) - return true; - OrigArg = Res.get(); - } else { - ExprResult Res = DefaultFunctionArrayLvalueConversion(OrigArg); + // We want to leave the type how it is, but do normal L->Rvalue conversions. + ExprResult Res = DefaultFunctionArrayLvalueConversion(OrigArg); + if (!Res.isUsable()) + return true; + OrigArg = Res.get(); - if (!Res.isUsable()) - return true; - OrigArg = Res.get(); - } TheCall->setArg(FPArgNo, OrigArg); QualType VectorResultTy; diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp index 2e3f242aaff22..256bb598cceb6 100644 --- a/clang/lib/Sema/SemaExpr.cpp +++ b/clang/lib/Sema/SemaExpr.cpp @@ -15528,8 +15528,7 @@ static ExprResult convertHalfVecBinOp(Sema &S, ExprResult LHS, ExprResult RHS, /// is needed. static bool needsConversionOfHalfVec(bool OpRequiresConversion, ASTContext &Ctx, Expr *E0, Expr *E1 = nullptr) { - if (!OpRequiresConversion || Ctx.getLangOpts().NativeHalfType || - Ctx.getTargetInfo().useFP16ConversionIntrinsics()) + if (!OpRequiresConversion || Ctx.getLangOpts().NativeHalfType) return false; auto HasVectorOfHalfType = [&Ctx](Expr *E) { diff --git a/clang/test/CodeGen/builtin_float.c b/clang/test/CodeGen/builtin_float.c index f79b6bd4ff5e0..1c1ce6195b4be 100644 --- a/clang/test/CodeGen/builtin_float.c +++ b/clang/test/CodeGen/builtin_float.c @@ -1,5 +1,5 @@ -// RUN: %clang_cc1 -emit-llvm -triple x86_64-windows-pc -o - %s | FileCheck %s --check-prefixes=CHECK,FP16 -// RUN: %clang_cc1 -emit-llvm -triple ppc64-be -o - %s -DNO_FP16 | FileCheck %s --check-prefixes=CHECK,NOFP16 +// RUN: %clang_cc1 -emit-llvm -triple x86_64-windows-pc -o - %s | FileCheck %s +// RUN: %clang_cc1 -emit-llvm -triple ppc64-be -o - %s -DNO_FP16 | FileCheck %s // test to ensure that these builtins don't do the variadic promotion of float->double. void test_floats(float f1, float f2) { @@ -49,8 +49,7 @@ void test_half(__fp16 *H, __fp16 *H2) { // CHECK: fcmp ogt float // CHECK-NEXT: zext i1 (void)__builtin_isinf(*H); - // FP16: call i1 @llvm.is.fpclass.f16(half %{{.*}}, i32 516) - // NOFP16: call i1 @llvm.is.fpclass.f32(float %{{.*}}, i32 516) + // CHECK: call i1 @llvm.is.fpclass.f16(half %{{.*}}, i32 516) } void test_mixed(double d1, float f2) { diff --git a/clang/test/CodeGen/builtin_float_strictfp.c b/clang/test/CodeGen/builtin_float_strictfp.c index 81bf89228f59c..7966110ddfcd1 100644 --- a/clang/test/CodeGen/builtin_float_strictfp.c +++ b/clang/test/CodeGen/builtin_float_strictfp.c @@ -1,5 +1,5 @@ -// RUN: %clang_cc1 -emit-llvm -triple x86_64-windows-pc -ffp-exception-behavior=maytrap -o - %s | FileCheck %s --check-prefixes=CHECK,FP16 -// RUN: %clang_cc1 -emit-llvm -triple ppc64-be -ffp-exception-behavior=maytrap -o - %s | FileCheck %s --check-prefixes=CHECK,NOFP16 +// RUN: %clang_cc1 -emit-llvm -triple x86_64-windows-pc -ffp-exception-behavior=maytrap -o - %s | FileCheck %s +// RUN: %clang_cc1 -emit-llvm -triple ppc64-be -ffp-exception-behavior=maytrap -o - %s | FileCheck %s // test to ensure that these builtins don't do the variadic promotion of float->double. @@ -11,8 +11,8 @@ // CHECK-LABEL: @test_half void test_half(__fp16 *H, __fp16 *H2) { (void)__builtin_isgreater(*H, *H2); - // FP16: call float @llvm.experimental.constrained.fpext.f32.f16(half %{{.*}}, metadata !"fpexcept.strict") - // FP16: call float @llvm.experimental.constrained.fpext.f32.f16(half %{{.*}}, metadata !"fpexcept.strict") + // CHECK: call float @llvm.experimental.constrained.fpext.f32.f16(half %{{.*}}, metadata !"fpexcept.strict") + // CHECK: call float @llvm.experimental.constrained.fpext.f32.f16(half %{{.*}}, metadata !"fpexcept.strict") // CHECK: call i1 @llvm.experimental.constrained.fcmp.f32(float %{{.*}}, float %{{.*}}, metadata !"ogt", metadata !"fpexcept.strict") // CHECK-NEXT: zext i1 (void)__builtin_isinf(*H); diff --git a/clang/test/CodeGen/wasm-fp16.c b/clang/test/CodeGen/wasm-fp16.c index 8fa35b975ab97..1649a6396baa7 100644 --- a/clang/test/CodeGen/wasm-fp16.c +++ b/clang/test/CodeGen/wasm-fp16.c @@ -4,7 +4,7 @@ __fp16 g = 2.0f; //. -// CHECK: @g = global i16 16384, align 2 +// CHECK: @g = global half 2.000000e+00, align 2 //. // CHECK-LABEL: define float @test_memory_fp16_to_float( // CHECK-SAME: ptr noundef [[PTR:%.*]]) #[[ATTR0:[0-9]+]] { @@ -12,9 +12,8 @@ __fp16 g = 2.0f; // CHECK-NEXT: [[PTR_ADDR:%.*]] = alloca ptr, align 8 // CHECK-NEXT: store ptr [[PTR]], ptr [[PTR_ADDR]], align 8, !tbaa [[__FP16PTR_TBAA6:![0-9]+]] // CHECK-NEXT: [[TMP0:%.*]] = load ptr, ptr [[PTR_ADDR]], align 8, !tbaa [[__FP16PTR_TBAA6]] -// CHECK-NEXT: [[TMP1:%.*]] = load i16, ptr [[TMP0]], align 2, !tbaa [[__FP16_TBAA9:![0-9]+]] -// CHECK-NEXT: [[TMP2:%.*]] = bitcast i16 [[TMP1]] to half -// CHECK-NEXT: [[CONV:%.*]] = fpext half [[TMP2]] to float +// CHECK-NEXT: [[TMP1:%.*]] = load half, ptr [[TMP0]], align 2, !tbaa [[__FP16_TBAA9:![0-9]+]] +// CHECK-NEXT: [[CONV:%.*]] = fpext half [[TMP1]] to float // CHECK-NEXT: ret float [[CONV]] // float test_memory_fp16_to_float(__fp16 *ptr) { @@ -30,9 +29,8 @@ float test_memory_fp16_to_float(__fp16 *ptr) { // CHECK-NEXT: store float [[VAL]], ptr [[VAL_ADDR]], align 4, !tbaa [[FLOAT_TBAA11:![0-9]+]] // CHECK-NEXT: [[TMP0:%.*]] = load float, ptr [[VAL_ADDR]], align 4, !tbaa [[FLOAT_TBAA11]] // CHECK-NEXT: [[CONV:%.*]] = fptrunc float [[TMP0]] to half -// CHECK-NEXT: [[TMP1:%.*]] = bitcast half [[CONV]] to i16 -// CHECK-NEXT: [[TMP2:%.*]] = load ptr, ptr [[PTR_ADDR]], align 8, !tbaa [[__FP16PTR_TBAA6]] -// CHECK-NEXT: store i16 [[TMP1]], ptr [[TMP2]], align 2, !tbaa [[__FP16_TBAA9]] +// CHECK-NEXT: [[TMP1:%.*]] = load ptr, ptr [[PTR_ADDR]], align 8, !tbaa [[__FP16PTR_TBAA6]] +// CHECK-NEXT: store half [[CONV]], ptr [[TMP1]], align 2, !tbaa [[__FP16_TBAA9]] // CHECK-NEXT: ret void // void test_memory_float_from_fp16(__fp16* ptr, float val) { @@ -45,15 +43,12 @@ void test_memory_float_from_fp16(__fp16* ptr, float val) { // CHECK-NEXT: [[PTR_ADDR:%.*]] = alloca ptr, align 8 // CHECK-NEXT: store ptr [[PTR]], ptr [[PTR_ADDR]], align 8, !tbaa [[__FP16PTR_TBAA6]] // CHECK-NEXT: [[TMP0:%.*]] = load ptr, ptr [[PTR_ADDR]], align 8, !tbaa [[__FP16PTR_TBAA6]] -// CHECK-NEXT: [[TMP1:%.*]] = load i16, ptr [[TMP0]], align 2, !tbaa [[__FP16_TBAA9]] -// CHECK-NEXT: [[TMP2:%.*]] = bitcast i16 [[TMP1]] to half -// CHECK-NEXT: [[INCDEC_CONV:%.*]] = fpext half [[TMP2]] to float +// CHECK-NEXT: [[TMP1:%.*]] = load half, ptr [[TMP0]], align 2, !tbaa [[__FP16_TBAA9]] +// CHECK-NEXT: [[INCDEC_CONV:%.*]] = fpext half [[TMP1]] to float // CHECK-NEXT: [[INC:%.*]] = fadd float [[INCDEC_CONV]], 1.000000e+00 // CHECK-NEXT: [[INCDEC_CONV1:%.*]] = fptrunc float [[INC]] to half -// CHECK-NEXT: [[TMP3:%.*]] = bitcast half [[INCDEC_CONV1]] to i16 -// CHECK-NEXT: store i16 [[TMP3]], ptr [[TMP0]], align 2, !tbaa [[__FP16_TBAA9]] -// CHECK-NEXT: [[TMP4:%.*]] = bitcast i16 [[TMP3]] to half -// CHECK-NEXT: [[CONV:%.*]] = fpext half [[TMP4]] to float +// CHECK-NEXT: store half [[INCDEC_CONV1]], ptr [[TMP0]], align 2, !tbaa [[__FP16_TBAA9]] +// CHECK-NEXT: [[CONV:%.*]] = fpext half [[INCDEC_CONV1]] to float // CHECK-NEXT: ret float [[CONV]] // float test_memory_fp16_preinc(__fp16 *ptr) { @@ -66,15 +61,12 @@ float test_memory_fp16_preinc(__fp16 *ptr) { // CHECK-NEXT: [[PTR_ADDR:%.*]] = alloca ptr, align 8 // CHECK-NEXT: store ptr [[PTR]], ptr [[PTR_ADDR]], align 8, !tbaa [[__FP16PTR_TBAA6]] // CHECK-NEXT: [[TMP0:%.*]] = load ptr, ptr [[PTR_ADDR]], align 8, !tbaa [[__FP16PTR_TBAA6]] -// CHECK-NEXT: [[TMP1:%.*]] = load i16, ptr [[TMP0]], align 2, !tbaa [[__FP16_TBAA9]] -// CHECK-NEXT: [[TMP2:%.*]] = bitcast i16 [[TMP1]] to half -// CHECK-NEXT: [[INCDEC_CONV:%.*]] = fpext half [[TMP2]] to float +// CHECK-NEXT: [[TMP1:%.*]] = load half, ptr [[TMP0]], align 2, !tbaa [[__FP16_TBAA9]] +// CHECK-NEXT: [[INCDEC_CONV:%.*]] = fpext half [[TMP1]] to float // CHECK-NEXT: [[INC:%.*]] = fadd float [[INCDEC_CONV]], 1.000000e+00 // CHECK-NEXT: [[INCDEC_CONV1:%.*]] = fptrunc float [[INC]] to half -// CHECK-NEXT: [[TMP3:%.*]] = bitcast half [[INCDEC_CONV1]] to i16 -// CHECK-NEXT: store i16 [[TMP3]], ptr [[TMP0]], align 2, !tbaa [[__FP16_TBAA9]] -// CHECK-NEXT: [[TMP4:%.*]] = bitcast i16 [[TMP1]] to half -// CHECK-NEXT: [[CONV:%.*]] = fpext half [[TMP4]] to float +// CHECK-NEXT: store half [[INCDEC_CONV1]], ptr [[TMP0]], align 2, !tbaa [[__FP16_TBAA9]] +// CHECK-NEXT: [[CONV:%.*]] = fpext half [[TMP1]] to float // CHECK-NEXT: ret float [[CONV]] // float test_memory_fp16_postinc(__fp16 *ptr) { @@ -87,15 +79,12 @@ float test_memory_fp16_postinc(__fp16 *ptr) { // CHECK-NEXT: [[PTR_ADDR:%.*]] = alloca ptr, align 8 // CHECK-NEXT: store ptr [[PTR]], ptr [[PTR_ADDR]], align 8, !tbaa [[__FP16PTR_TBAA6]] // CHECK-NEXT: [[TMP0:%.*]] = load ptr, ptr [[PTR_ADDR]], align 8, !tbaa [[__FP16PTR_TBAA6]] -// CHECK-NEXT: [[TMP1:%.*]] = load i16, ptr [[TMP0]], align 2, !tbaa [[__FP16_TBAA9]] -// CHECK-NEXT: [[TMP2:%.*]] = bitcast i16 [[TMP1]] to half -// CHECK-NEXT: [[INCDEC_CONV:%.*]] = fpext half [[TMP2]] to float +// CHECK-NEXT: [[TMP1:%.*]] = load half, ptr [[TMP0]], align 2, !tbaa [[__FP16_TBAA9]] +// CHECK-NEXT: [[INCDEC_CONV:%.*]] = fpext half [[TMP1]] to float // CHECK-NEXT: [[DEC:%.*]] = fadd float [[INCDEC_CONV]], -1.000000e+00 // CHECK-NEXT: [[INCDEC_CONV1:%.*]] = fptrunc float [[DEC]] to half -// CHECK-NEXT: [[TMP3:%.*]] = bitcast half [[INCDEC_CONV1]] to i16 -// CHECK-NEXT: store i16 [[TMP3]], ptr [[TMP0]], align 2, !tbaa [[__FP16_TBAA9]] -// CHECK-NEXT: [[TMP4:%.*]] = bitcast i16 [[TMP3]] to half -// CHECK-NEXT: [[CONV:%.*]] = fpext half [[TMP4]] to float +// CHECK-NEXT: store half [[INCDEC_CONV1]], ptr [[TMP0]], align 2, !tbaa [[__FP16_TBAA9]] +// CHECK-NEXT: [[CONV:%.*]] = fpext half [[INCDEC_CONV1]] to float // CHECK-NEXT: ret float [[CONV]] // float test_memory_fp16_predec(__fp16 *ptr) { @@ -108,36 +97,30 @@ float test_memory_fp16_predec(__fp16 *ptr) { // CHECK-NEXT: [[PTR_ADDR:%.*]] = alloca ptr, align 8 // CHECK-NEXT: store ptr [[PTR]], ptr [[PTR_ADDR]], align 8, !tbaa [[__FP16PTR_TBAA6]] // CHECK-NEXT: [[TMP0:%.*]] = load ptr, ptr [[PTR_ADDR]], align 8, !tbaa [[__FP16PTR_TBAA6]] -// CHECK-NEXT: [[TMP1:%.*]] = load i16, ptr [[TMP0]], align 2, !tbaa [[__FP16_TBAA9]] -// CHECK-NEXT: [[TMP2:%.*]] = bitcast i16 [[TMP1]] to half -// CHECK-NEXT: [[INCDEC_CONV:%.*]] = fpext half [[TMP2]] to float +// CHECK-NEXT: [[TMP1:%.*]] = load half, ptr [[TMP0]], align 2, !tbaa [[__FP16_TBAA9]] +// CHECK-NEXT: [[INCDEC_CONV:%.*]] = fpext half [[TMP1]] to float // CHECK-NEXT: [[DEC:%.*]] = fadd float [[INCDEC_CONV]], -1.000000e+00 // CHECK-NEXT: [[INCDEC_CONV1:%.*]] = fptrunc float [[DEC]] to half -// CHECK-NEXT: [[TMP3:%.*]] = bitcast half [[INCDEC_CONV1]] to i16 -// CHECK-NEXT: store i16 [[TMP3]], ptr [[TMP0]], align 2, !tbaa [[__FP16_TBAA9]] -// CHECK-NEXT: [[TMP4:%.*]] = bitcast i16 [[TMP1]] to half -// CHECK-NEXT: [[CONV:%.*]] = fpext half [[TMP4]] to float +// CHECK-NEXT: store half [[INCDEC_CONV1]], ptr [[TMP0]], align 2, !tbaa [[__FP16_TBAA9]] +// CHECK-NEXT: [[CONV:%.*]] = fpext half [[TMP1]] to float // CHECK-NEXT: ret float [[CONV]] // float test_memory_fp16_postdec(__fp16 *ptr) { return (*ptr)--; } -// CHECK-LABEL: define i16 @test_arg_return( -// CHECK-SAME: i16 noundef [[X:%.*]]) #[[ATTR0]] { +// CHECK-LABEL: define half @test_arg_return( +// CHECK-SAME: half noundef [[X:%.*]]) #[[ATTR0]] { // CHECK-NEXT: [[ENTRY:.*:]] -// CHECK-NEXT: [[X_ADDR:%.*]] = alloca i16, align 2 -// CHECK-NEXT: store i16 [[X]], ptr [[X_ADDR]], align 2, !tbaa [[__FP16_TBAA9]] -// CHECK-NEXT: [[TMP0:%.*]] = load i16, ptr [[X_ADDR]], align 2, !tbaa [[__FP16_TBAA9]] -// CHECK-NEXT: [[TMP1:%.*]] = bitcast i16 [[TMP0]] to half -// CHECK-NEXT: [[CONV:%.*]] = fpext half [[TMP1]] to float -// CHECK-NEXT: [[TMP2:%.*]] = load i16, ptr [[X_ADDR]], align 2, !tbaa [[__FP16_TBAA9]] -// CHECK-NEXT: [[TMP3:%.*]] = bitcast i16 [[TMP2]] to half -// CHECK-NEXT: [[CONV1:%.*]] = fpext half [[TMP3]] to float +// CHECK-NEXT: [[X_ADDR:%.*]] = alloca half, align 2 +// CHECK-NEXT: store half [[X]], ptr [[X_ADDR]], align 2, !tbaa [[__FP16_TBAA9]] +// CHECK-NEXT: [[TMP0:%.*]] = load half, ptr [[X_ADDR]], align 2, !tbaa [[__FP16_TBAA9]] +// CHECK-NEXT: [[CONV:%.*]] = fpext half [[TMP0]] to float +// CHECK-NEXT: [[TMP1:%.*]] = load half, ptr [[X_ADDR]], align 2, !tbaa [[__FP16_TBAA9]] +// CHECK-NEXT: [[CONV1:%.*]] = fpext half [[TMP1]] to float // CHECK-NEXT: [[ADD:%.*]] = fadd float [[CONV]], [[CONV1]] // CHECK-NEXT: [[CONV2:%.*]] = fptrunc float [[ADD]] to half -// CHECK-NEXT: [[TMP4:%.*]] = bitcast half [[CONV2]] to i16 -// CHECK-NEXT: ret i16 [[TMP4]] +// CHECK-NEXT: ret half [[CONV2]] // __fp16 test_arg_return(__fp16 x) { return x + x; _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
