Skip to content

Conversation

@arsenm
Copy link
Contributor

@arsenm arsenm commented Jan 5, 2026

There is no reason to use these over fpext/fptrunc and bitcast.

Split out from #174484. The test coverage is also shockingly bad,
so adds a new wasm test which shows different contexts the intrinsics
are used.

I've also reverted this to a more conservative version that leaves the
useFP16ConversionIntrinsics configuration in place, and only replaces
the exact intrinsic usage. This should be removed, but it seems to have
turned into a buggy ABI option. Some contexts which probably meant to
check NativeHalfType or NativeHalfArgsAndReturns were relying on this
instead. Additionally, some of the SVE intrinsics appear to be using
__fp16 but really expect _Float16 treatment.

@arsenm arsenm marked this pull request as ready for review January 5, 2026 22:18
@llvmbot llvmbot added clang Clang issues not falling into any other category backend:ARM backend:AArch64 backend:AMDGPU backend:RISC-V backend:SystemZ backend:WebAssembly clang:frontend Language frontend issues, e.g. anything involving "Sema" clang:codegen IR generation bugs: mangling, exceptions, etc. backend:DirectX backend:loongarch ClangIR Anything related to the ClangIR project labels Jan 5, 2026
Copy link
Contributor Author

arsenm commented Jan 5, 2026

This stack of pull requests is managed by Graphite. Learn more about stacking.

@llvmbot
Copy link
Member

llvmbot commented Jan 5, 2026

@llvm/pr-subscribers-backend-systemz
@llvm/pr-subscribers-backend-arm
@llvm/pr-subscribers-clang-codegen
@llvm/pr-subscribers-clangir

@llvm/pr-subscribers-backend-loongarch

Author: Matt Arsenault (arsenm)

Changes

There is no reason to use these over fpext/fptrunc and bitcast.

Split out from #174484.


Patch is 25.12 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/174494.diff

23 Files Affected:

  • (modified) clang/include/clang/Basic/TargetInfo.h (-8)
  • (modified) clang/lib/Basic/Targets/AArch64.h (-4)
  • (modified) clang/lib/Basic/Targets/AMDGPU.h (-2)
  • (modified) clang/lib/Basic/Targets/ARM.h (-4)
  • (modified) clang/lib/Basic/Targets/DirectX.h (-1)
  • (modified) clang/lib/Basic/Targets/LoongArch.h (-2)
  • (modified) clang/lib/Basic/Targets/NVPTX.h (-2)
  • (modified) clang/lib/Basic/Targets/RISCV.h (-4)
  • (modified) clang/lib/Basic/Targets/SPIR.h (-4)
  • (modified) clang/lib/Basic/Targets/SystemZ.h (-2)
  • (modified) clang/lib/Basic/Targets/WebAssembly.h (-1)
  • (modified) clang/lib/Basic/Targets/X86.h (-4)
  • (modified) clang/lib/CIR/CodeGen/CIRGenExprConstant.cpp (+1-9)
  • (modified) clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp (+6-18)
  • (modified) clang/lib/CIR/CodeGen/CIRGenTypes.cpp (+1-7)
  • (modified) clang/lib/CodeGen/CGExprConstant.cpp (+2-10)
  • (modified) clang/lib/CodeGen/CGExprScalar.cpp (+5-43)
  • (modified) clang/lib/CodeGen/CodeGenTypes.cpp (+2-4)
  • (modified) clang/lib/CodeGen/TargetBuiltins/NVPTX.cpp (+2-20)
  • (modified) clang/lib/Sema/SemaChecking.cpp (+5-15)
  • (modified) clang/lib/Sema/SemaExpr.cpp (+1-2)
  • (modified) clang/test/CodeGen/builtin_float.c (+3-4)
  • (modified) clang/test/CodeGen/builtin_float_strictfp.c (+8-13)
diff --git a/clang/include/clang/Basic/TargetInfo.h b/clang/include/clang/Basic/TargetInfo.h
index 4ff77bb64cf1c..f1aeeb13dcb57 100644
--- a/clang/include/clang/Basic/TargetInfo.h
+++ b/clang/include/clang/Basic/TargetInfo.h
@@ -1013,14 +1013,6 @@ class TargetInfo : public TransferrableTargetInfo,
     return ComplexLongDoubleUsesFP2Ret;
   }
 
-  /// Check whether llvm intrinsics such as llvm.convert.to.fp16 should be used
-  /// to convert to and from __fp16.
-  /// FIXME: This function should be removed once all targets stop using the
-  /// conversion intrinsics.
-  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 2d3b8d2a8d950..2d2d469a5c7d6 100644
--- a/clang/lib/Basic/Targets/AArch64.h
+++ b/clang/lib/Basic/Targets/AArch64.h
@@ -154,10 +154,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 0076f822c02a1..0ec4c50bde8c4 100644
--- a/clang/lib/Basic/Targets/AMDGPU.h
+++ b/clang/lib/Basic/Targets/AMDGPU.h
@@ -268,8 +268,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 43c4718f4735b..00c2918bd2f23 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 7589b4309ebf5..ca470e126795f 100644
--- a/clang/lib/Basic/Targets/DirectX.h
+++ b/clang/lib/Basic/Targets/DirectX.h
@@ -68,7 +68,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 31afd3eed96f9..45c0bd2896993 100644
--- a/clang/lib/Basic/Targets/LoongArch.h
+++ b/clang/lib/Basic/Targets/LoongArch.h
@@ -105,8 +105,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 6338a4f2f9036..b928fc800ecaa 100644
--- a/clang/lib/Basic/Targets/NVPTX.h
+++ b/clang/lib/Basic/Targets/NVPTX.h
@@ -81,8 +81,6 @@ class LLVM_LIBRARY_VISIBILITY NVPTXTargetInfo : public TargetInfo {
 
   llvm::SmallVector<Builtin::InfosShard> getTargetBuiltins() const override;
 
-  bool useFP16ConversionIntrinsics() const override { return false; }
-
   bool
   initFeatureMap(llvm::StringMap<bool> &Features, DiagnosticsEngine &Diags,
                  StringRef CPU,
diff --git a/clang/lib/Basic/Targets/RISCV.h b/clang/lib/Basic/Targets/RISCV.h
index 685735b54a45b..9441204e02bc8 100644
--- a/clang/lib/Basic/Targets/RISCV.h
+++ b/clang/lib/Basic/Targets/RISCV.h
@@ -113,10 +113,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 d5374602caeaa..d05c0f01603d3 100644
--- a/clang/lib/Basic/Targets/SPIR.h
+++ b/clang/lib/Basic/Targets/SPIR.h
@@ -168,10 +168,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 2bcf75deb0a91..80032da545e53 100644
--- a/clang/lib/Basic/Targets/SystemZ.h
+++ b/clang/lib/Basic/Targets/SystemZ.h
@@ -106,8 +106,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 3634330ec6698..ca8e3990cc54d 100644
--- a/clang/lib/Basic/Targets/WebAssembly.h
+++ b/clang/lib/Basic/Targets/WebAssembly.h
@@ -110,7 +110,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 922e32906cd04..d00f0acdee666 100644
--- a/clang/lib/Basic/Targets/X86.h
+++ b/clang/lib/Basic/Targets/X86.h
@@ -325,10 +325,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 ecb65d901de54..f797973683805 100644
--- a/clang/lib/CIR/CodeGen/CIRGenExprConstant.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenExprConstant.cpp
@@ -1793,18 +1793,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 a06f1f1dc1784..4b2572ce4858d 100644
--- a/clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp
@@ -924,19 +924,12 @@ 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).  FIXME(cir): For now lets pretend we
+        // shouldn't use the conversion intrinsics and insert a cast here
+        // unconditionally.
         src = builder.createCast(cgf.getLoc(loc), cir::CastKind::floating, src,
                                  cgf.floatTy);
         srcType = cgf.getContext().FloatTy;
@@ -994,11 +987,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 cddc849180971..23875d100ac0e 100644
--- a/clang/lib/CIR/CodeGen/CIRGenTypes.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenTypes.cpp
@@ -396,13 +396,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 0eec4dba4824a..26cb3f39bfbd0 100644
--- a/clang/lib/CodeGen/CGExprConstant.cpp
+++ b/clang/lib/CodeGen/CGExprConstant.cpp
@@ -2469,16 +2469,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 84421fef9f524..1b3486c86d493 100644
--- a/clang/lib/CodeGen/CGExprScalar.cpp
+++ b/clang/lib/CodeGen/CGExprScalar.cpp
@@ -1596,23 +1596,11 @@ Value *ScalarExprEmitter::EmitScalarConversion(Value *Src, QualType SrcType,
   // 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())
-        return Builder.CreateCall(
-            CGF.CGM.getIntrinsic(llvm::Intrinsic::convert_from_fp16, DstTy),
-            Src);
-    } else {
+    if (!DstTy->isFloatingPointTy()) {
       // 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()) {
-        Src = Builder.CreateCall(
-            CGF.CGM.getIntrinsic(llvm::Intrinsic::convert_from_fp16,
-                                 CGF.CGM.FloatTy),
-            Src);
-      } else {
-        Src = Builder.CreateFPExt(Src, CGF.CGM.FloatTy, "conv");
-      }
+      Src = Builder.CreateFPExt(Src, CGF.CGM.FloatTy, "conv");
       SrcType = CGF.getContext().FloatTy;
       SrcTy = CGF.FloatTy;
     }
@@ -1723,11 +1711,6 @@ Value *ScalarExprEmitter::EmitScalarConversion(Value *Src, QualType SrcType,
   if (DstType->isHalfType() && !CGF.getContext().getLangOpts().NativeHalfType) {
     // Make sure we cast in a single step if from another FP type.
     if (SrcTy->isFloatingPointTy()) {
-      // Use the intrinsic if the half type itself isn't supported
-      // (as opposed to operations on half, available with NativeHalfType).
-      if (CGF.getContext().getTargetInfo().useFP16ConversionIntrinsics())
-        return Builder.CreateCall(
-            CGF.CGM.getIntrinsic(llvm::Intrinsic::convert_to_fp16, SrcTy), Src);
       // If the half type is supported, just use an fptrunc.
       return Builder.CreateFPTrunc(Src, DstTy);
     }
@@ -1737,14 +1720,7 @@ Value *ScalarExprEmitter::EmitScalarConversion(Value *Src, QualType SrcType,
   Res = EmitScalarCast(Src, SrcType, DstType, SrcTy, DstTy, Opts);
 
   if (DstTy != ResTy) {
-    if (CGF.getContext().getTargetInfo().useFP16ConversionIntrinsics()) {
-      assert(ResTy->isIntegerTy(16) && "Only half FP requires extra conversion");
-      Res = Builder.CreateCall(
-        CGF.CGM.getIntrinsic(llvm::Intrinsic::convert_to_fp16, CGF.CGM.FloatTy),
-        Res);
-    } else {
-      Res = Builder.CreateFPTrunc(Res, ResTy, "conv");
-    }
+    Res = Builder.CreateFPTrunc(Res, ResTy, "conv");
   }
 
   if (Opts.EmitImplicitIntegerTruncationChecks)
@@ -3399,14 +3375,7 @@ ScalarExprEmitter::EmitScalarPrePostIncDec(const UnaryOperator *E, LValue LV,
 
     if (type->isHalfType() && !CGF.getContext().getLangOpts().NativeHalfType) {
       // Another special case: half FP increment should be done via float
-      if (CGF.getContext().getTargetInfo().useFP16ConversionIntrinsics()) {
-        value = Builder.CreateCall(
-            CGF.CGM.getIntrinsic(llvm::Intrinsic::convert_from_fp16,
-                                 CGF.CGM.FloatTy),
-            input, "incdec.conv");
-      } else {
-        value = Builder.CreateFPExt(input, CGF.CGM.FloatTy, "incdec.conv");
-      }
+      value = Builder.CreateFPExt(input, CGF.CGM.FloatTy, "incdec.conv");
     }
 
     if (value->getType()->isFloatTy())
@@ -3439,14 +3408,7 @@ ScalarExprEmitter::EmitScalarPrePostIncDec(const UnaryOperator *E, LValue LV,
     value = Builder.CreateFAdd(value, amt, isInc ? "inc" : "dec");
 
     if (type->isHalfType() && !CGF.getContext().getLangOpts().NativeHalfType) {
-      if (CGF.getContext().getTargetInfo().useFP16ConversionIntrinsics()) {
-        value = Builder.CreateCall(
-            CGF.CGM.getIntrinsic(llvm::Intrinsic::convert_to_fp16,
-                                 CGF.CGM.FloatTy),
-            value, "incdec.conv");
-      } else {
-        value = Builder.CreateFPTrunc(value, input->getType(), "incdec.conv");
-      }
+      value = Builder.CreateFPTrunc(value, input->getType(), "incdec.conv");
     }
 
   // Fixed-point types.
diff --git a/clang/lib/CodeGen/CodeGenTypes.cpp b/clang/lib/CodeGen/CodeGenTypes.cpp
index 4239552d1299e..080082a8dc652 100644
--- a/clang/lib/CodeGen/CodeGenTypes.cpp
+++ b/clang/lib/CodeGen/CodeGenTypes.cpp
@@ -471,10 +471,8 @@ llvm::Type *CodeGenTypes::ConvertType(QualType T) {
 
     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());
+      ResultType = getTypeForFormat(getLLVMContext(),
+                                    Context.getFloatTypeSemantics(T), true);
       break;
     case BuiltinType::LongDouble:
       LongDoubleReferenced = true;
diff --git a/clang/lib/CodeGen/TargetBuiltins/NVPTX.cpp b/clang/lib/CodeGen/TargetBuiltins/NVPTX.cpp
index a4486965a851a..ee911f5258554 100644
--- a/clang/lib/CodeGen/TargetBuiltins/NVPTX.cpp
+++ b/clang/lib/CodeGen/TargetBuiltins/NVPTX.cpp
@@ -375,23 +375,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;
@@ -1069,13 +1054,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 ba4b25961d70d..daddeef808f73 100644
--- a/clang/lib/Sema/SemaChecking.cpp
+++ b/clang/lib/Sema/SemaChecking.cpp
@@ -5763,22 +5763,12 @@ bool Sema::BuiltinFPClassification(CallExpr *TheCall, unsigned NumArgs,
   if (OrigArg->isTypeDependent())
     return false;
 
-  // Usual Unary Conversions will convert half to ...
[truncated]

@llvmbot
Copy link
Member

llvmbot commented Jan 5, 2026

@llvm/pr-subscribers-clang

Author: Matt Arsenault (arsenm)

Changes

There is no reason to use these over fpext/fptrunc and bitcast.

Split out from #174484.


Patch is 25.12 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/174494.diff

23 Files Affected:

  • (modified) clang/include/clang/Basic/TargetInfo.h (-8)
  • (modified) clang/lib/Basic/Targets/AArch64.h (-4)
  • (modified) clang/lib/Basic/Targets/AMDGPU.h (-2)
  • (modified) clang/lib/Basic/Targets/ARM.h (-4)
  • (modified) clang/lib/Basic/Targets/DirectX.h (-1)
  • (modified) clang/lib/Basic/Targets/LoongArch.h (-2)
  • (modified) clang/lib/Basic/Targets/NVPTX.h (-2)
  • (modified) clang/lib/Basic/Targets/RISCV.h (-4)
  • (modified) clang/lib/Basic/Targets/SPIR.h (-4)
  • (modified) clang/lib/Basic/Targets/SystemZ.h (-2)
  • (modified) clang/lib/Basic/Targets/WebAssembly.h (-1)
  • (modified) clang/lib/Basic/Targets/X86.h (-4)
  • (modified) clang/lib/CIR/CodeGen/CIRGenExprConstant.cpp (+1-9)
  • (modified) clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp (+6-18)
  • (modified) clang/lib/CIR/CodeGen/CIRGenTypes.cpp (+1-7)
  • (modified) clang/lib/CodeGen/CGExprConstant.cpp (+2-10)
  • (modified) clang/lib/CodeGen/CGExprScalar.cpp (+5-43)
  • (modified) clang/lib/CodeGen/CodeGenTypes.cpp (+2-4)
  • (modified) clang/lib/CodeGen/TargetBuiltins/NVPTX.cpp (+2-20)
  • (modified) clang/lib/Sema/SemaChecking.cpp (+5-15)
  • (modified) clang/lib/Sema/SemaExpr.cpp (+1-2)
  • (modified) clang/test/CodeGen/builtin_float.c (+3-4)
  • (modified) clang/test/CodeGen/builtin_float_strictfp.c (+8-13)
diff --git a/clang/include/clang/Basic/TargetInfo.h b/clang/include/clang/Basic/TargetInfo.h
index 4ff77bb64cf1c..f1aeeb13dcb57 100644
--- a/clang/include/clang/Basic/TargetInfo.h
+++ b/clang/include/clang/Basic/TargetInfo.h
@@ -1013,14 +1013,6 @@ class TargetInfo : public TransferrableTargetInfo,
     return ComplexLongDoubleUsesFP2Ret;
   }
 
-  /// Check whether llvm intrinsics such as llvm.convert.to.fp16 should be used
-  /// to convert to and from __fp16.
-  /// FIXME: This function should be removed once all targets stop using the
-  /// conversion intrinsics.
-  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 2d3b8d2a8d950..2d2d469a5c7d6 100644
--- a/clang/lib/Basic/Targets/AArch64.h
+++ b/clang/lib/Basic/Targets/AArch64.h
@@ -154,10 +154,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 0076f822c02a1..0ec4c50bde8c4 100644
--- a/clang/lib/Basic/Targets/AMDGPU.h
+++ b/clang/lib/Basic/Targets/AMDGPU.h
@@ -268,8 +268,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 43c4718f4735b..00c2918bd2f23 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 7589b4309ebf5..ca470e126795f 100644
--- a/clang/lib/Basic/Targets/DirectX.h
+++ b/clang/lib/Basic/Targets/DirectX.h
@@ -68,7 +68,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 31afd3eed96f9..45c0bd2896993 100644
--- a/clang/lib/Basic/Targets/LoongArch.h
+++ b/clang/lib/Basic/Targets/LoongArch.h
@@ -105,8 +105,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 6338a4f2f9036..b928fc800ecaa 100644
--- a/clang/lib/Basic/Targets/NVPTX.h
+++ b/clang/lib/Basic/Targets/NVPTX.h
@@ -81,8 +81,6 @@ class LLVM_LIBRARY_VISIBILITY NVPTXTargetInfo : public TargetInfo {
 
   llvm::SmallVector<Builtin::InfosShard> getTargetBuiltins() const override;
 
-  bool useFP16ConversionIntrinsics() const override { return false; }
-
   bool
   initFeatureMap(llvm::StringMap<bool> &Features, DiagnosticsEngine &Diags,
                  StringRef CPU,
diff --git a/clang/lib/Basic/Targets/RISCV.h b/clang/lib/Basic/Targets/RISCV.h
index 685735b54a45b..9441204e02bc8 100644
--- a/clang/lib/Basic/Targets/RISCV.h
+++ b/clang/lib/Basic/Targets/RISCV.h
@@ -113,10 +113,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 d5374602caeaa..d05c0f01603d3 100644
--- a/clang/lib/Basic/Targets/SPIR.h
+++ b/clang/lib/Basic/Targets/SPIR.h
@@ -168,10 +168,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 2bcf75deb0a91..80032da545e53 100644
--- a/clang/lib/Basic/Targets/SystemZ.h
+++ b/clang/lib/Basic/Targets/SystemZ.h
@@ -106,8 +106,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 3634330ec6698..ca8e3990cc54d 100644
--- a/clang/lib/Basic/Targets/WebAssembly.h
+++ b/clang/lib/Basic/Targets/WebAssembly.h
@@ -110,7 +110,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 922e32906cd04..d00f0acdee666 100644
--- a/clang/lib/Basic/Targets/X86.h
+++ b/clang/lib/Basic/Targets/X86.h
@@ -325,10 +325,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 ecb65d901de54..f797973683805 100644
--- a/clang/lib/CIR/CodeGen/CIRGenExprConstant.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenExprConstant.cpp
@@ -1793,18 +1793,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 a06f1f1dc1784..4b2572ce4858d 100644
--- a/clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp
@@ -924,19 +924,12 @@ 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).  FIXME(cir): For now lets pretend we
+        // shouldn't use the conversion intrinsics and insert a cast here
+        // unconditionally.
         src = builder.createCast(cgf.getLoc(loc), cir::CastKind::floating, src,
                                  cgf.floatTy);
         srcType = cgf.getContext().FloatTy;
@@ -994,11 +987,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 cddc849180971..23875d100ac0e 100644
--- a/clang/lib/CIR/CodeGen/CIRGenTypes.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenTypes.cpp
@@ -396,13 +396,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 0eec4dba4824a..26cb3f39bfbd0 100644
--- a/clang/lib/CodeGen/CGExprConstant.cpp
+++ b/clang/lib/CodeGen/CGExprConstant.cpp
@@ -2469,16 +2469,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 84421fef9f524..1b3486c86d493 100644
--- a/clang/lib/CodeGen/CGExprScalar.cpp
+++ b/clang/lib/CodeGen/CGExprScalar.cpp
@@ -1596,23 +1596,11 @@ Value *ScalarExprEmitter::EmitScalarConversion(Value *Src, QualType SrcType,
   // 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())
-        return Builder.CreateCall(
-            CGF.CGM.getIntrinsic(llvm::Intrinsic::convert_from_fp16, DstTy),
-            Src);
-    } else {
+    if (!DstTy->isFloatingPointTy()) {
       // 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()) {
-        Src = Builder.CreateCall(
-            CGF.CGM.getIntrinsic(llvm::Intrinsic::convert_from_fp16,
-                                 CGF.CGM.FloatTy),
-            Src);
-      } else {
-        Src = Builder.CreateFPExt(Src, CGF.CGM.FloatTy, "conv");
-      }
+      Src = Builder.CreateFPExt(Src, CGF.CGM.FloatTy, "conv");
       SrcType = CGF.getContext().FloatTy;
       SrcTy = CGF.FloatTy;
     }
@@ -1723,11 +1711,6 @@ Value *ScalarExprEmitter::EmitScalarConversion(Value *Src, QualType SrcType,
   if (DstType->isHalfType() && !CGF.getContext().getLangOpts().NativeHalfType) {
     // Make sure we cast in a single step if from another FP type.
     if (SrcTy->isFloatingPointTy()) {
-      // Use the intrinsic if the half type itself isn't supported
-      // (as opposed to operations on half, available with NativeHalfType).
-      if (CGF.getContext().getTargetInfo().useFP16ConversionIntrinsics())
-        return Builder.CreateCall(
-            CGF.CGM.getIntrinsic(llvm::Intrinsic::convert_to_fp16, SrcTy), Src);
       // If the half type is supported, just use an fptrunc.
       return Builder.CreateFPTrunc(Src, DstTy);
     }
@@ -1737,14 +1720,7 @@ Value *ScalarExprEmitter::EmitScalarConversion(Value *Src, QualType SrcType,
   Res = EmitScalarCast(Src, SrcType, DstType, SrcTy, DstTy, Opts);
 
   if (DstTy != ResTy) {
-    if (CGF.getContext().getTargetInfo().useFP16ConversionIntrinsics()) {
-      assert(ResTy->isIntegerTy(16) && "Only half FP requires extra conversion");
-      Res = Builder.CreateCall(
-        CGF.CGM.getIntrinsic(llvm::Intrinsic::convert_to_fp16, CGF.CGM.FloatTy),
-        Res);
-    } else {
-      Res = Builder.CreateFPTrunc(Res, ResTy, "conv");
-    }
+    Res = Builder.CreateFPTrunc(Res, ResTy, "conv");
   }
 
   if (Opts.EmitImplicitIntegerTruncationChecks)
@@ -3399,14 +3375,7 @@ ScalarExprEmitter::EmitScalarPrePostIncDec(const UnaryOperator *E, LValue LV,
 
     if (type->isHalfType() && !CGF.getContext().getLangOpts().NativeHalfType) {
       // Another special case: half FP increment should be done via float
-      if (CGF.getContext().getTargetInfo().useFP16ConversionIntrinsics()) {
-        value = Builder.CreateCall(
-            CGF.CGM.getIntrinsic(llvm::Intrinsic::convert_from_fp16,
-                                 CGF.CGM.FloatTy),
-            input, "incdec.conv");
-      } else {
-        value = Builder.CreateFPExt(input, CGF.CGM.FloatTy, "incdec.conv");
-      }
+      value = Builder.CreateFPExt(input, CGF.CGM.FloatTy, "incdec.conv");
     }
 
     if (value->getType()->isFloatTy())
@@ -3439,14 +3408,7 @@ ScalarExprEmitter::EmitScalarPrePostIncDec(const UnaryOperator *E, LValue LV,
     value = Builder.CreateFAdd(value, amt, isInc ? "inc" : "dec");
 
     if (type->isHalfType() && !CGF.getContext().getLangOpts().NativeHalfType) {
-      if (CGF.getContext().getTargetInfo().useFP16ConversionIntrinsics()) {
-        value = Builder.CreateCall(
-            CGF.CGM.getIntrinsic(llvm::Intrinsic::convert_to_fp16,
-                                 CGF.CGM.FloatTy),
-            value, "incdec.conv");
-      } else {
-        value = Builder.CreateFPTrunc(value, input->getType(), "incdec.conv");
-      }
+      value = Builder.CreateFPTrunc(value, input->getType(), "incdec.conv");
     }
 
   // Fixed-point types.
diff --git a/clang/lib/CodeGen/CodeGenTypes.cpp b/clang/lib/CodeGen/CodeGenTypes.cpp
index 4239552d1299e..080082a8dc652 100644
--- a/clang/lib/CodeGen/CodeGenTypes.cpp
+++ b/clang/lib/CodeGen/CodeGenTypes.cpp
@@ -471,10 +471,8 @@ llvm::Type *CodeGenTypes::ConvertType(QualType T) {
 
     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());
+      ResultType = getTypeForFormat(getLLVMContext(),
+                                    Context.getFloatTypeSemantics(T), true);
       break;
     case BuiltinType::LongDouble:
       LongDoubleReferenced = true;
diff --git a/clang/lib/CodeGen/TargetBuiltins/NVPTX.cpp b/clang/lib/CodeGen/TargetBuiltins/NVPTX.cpp
index a4486965a851a..ee911f5258554 100644
--- a/clang/lib/CodeGen/TargetBuiltins/NVPTX.cpp
+++ b/clang/lib/CodeGen/TargetBuiltins/NVPTX.cpp
@@ -375,23 +375,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;
@@ -1069,13 +1054,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 ba4b25961d70d..daddeef808f73 100644
--- a/clang/lib/Sema/SemaChecking.cpp
+++ b/clang/lib/Sema/SemaChecking.cpp
@@ -5763,22 +5763,12 @@ bool Sema::BuiltinFPClassification(CallExpr *TheCall, unsigned NumArgs,
   if (OrigArg->isTypeDependent())
     return false;
 
-  // Usual Unary Conversions will convert half to ...
[truncated]

Copy link
Contributor

@andykaylor andykaylor left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This all looks reasonable to me, pending resolution of the ABI concern that @nikic brought up on the other PR. Thanks for including the CIR changes!

@arsenm arsenm force-pushed the users/arsenm/clang/stop-using-convert-to-from-fp16-intrinsics branch from 4374203 to 091ebf1 Compare January 6, 2026 19:04
@arsenm
Copy link
Contributor Author

arsenm commented Jan 6, 2026

I've switched this to leaving most of the useFP16ConversionIntrinsics usage in place. It should be removed, but it's been misused as an ABI option and I'm not sure how to untangle it. In particular I think some of the AArch64 builtins should be defined using _Float16 instead of __fp16

There is no reason to use these over fpext/fptrunc and bitcast.

Split out from #174484. The test coverage is also shockingly bad,
so adds a new wasm test which shows different contexts the intrinsics
are used.

I've also reverted this to a more conservative version that leaves the
useFP16ConversionIntrinsics configuration in place, and only replaces
the exact intrinsic usage. This should be removed, but it seems to have
turned into a buggy ABI option. Some contexts which probably meant to
check NativeHalfType or NativeHalfArgsAndReturns were relying on this
instead. Additionally, some of the SVE intrinsics appear to be using
__fp16 but really expect _Float16 treatment.
@arsenm arsenm force-pushed the users/arsenm/clang/stop-using-convert-to-from-fp16-intrinsics branch from 091ebf1 to 1e07f1d Compare January 6, 2026 19:06
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

backend:AArch64 backend:AMDGPU backend:ARM backend:DirectX backend:loongarch backend:RISC-V backend:SystemZ backend:WebAssembly clang:codegen IR generation bugs: mangling, exceptions, etc. clang:frontend Language frontend issues, e.g. anything involving "Sema" clang Clang issues not falling into any other category ClangIR Anything related to the ClangIR project

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants