[clang] 8a21ea1 - clang: Start emitting intrinsic for __builtin_ldexp*
Matt Arsenault via cfe-commits
cfe-commits at lists.llvm.org
Tue Jun 6 14:07:33 PDT 2023
Author: Matt Arsenault
Date: 2023-06-06T17:07:19-04:00
New Revision: 8a21ea1d0a3883a8d0aa15440388f91e49da4d08
URL: https://github.com/llvm/llvm-project/commit/8a21ea1d0a3883a8d0aa15440388f91e49da4d08
DIFF: https://github.com/llvm/llvm-project/commit/8a21ea1d0a3883a8d0aa15440388f91e49da4d08.diff
LOG: clang: Start emitting intrinsic for __builtin_ldexp*
Also introduce __builtin_ldexpf16.
Added:
Modified:
clang/include/clang/Basic/Builtins.def
clang/lib/CodeGen/CGBuiltin.cpp
clang/test/CodeGen/aix-builtin-mapping.c
clang/test/CodeGen/constrained-math-builtins.c
clang/test/CodeGen/math-builtins.c
clang/test/CodeGenOpenCL/builtins-f16.cl
clang/test/CodeGenOpenCL/builtins-generic-amdgcn.cl
Removed:
################################################################################
diff --git a/clang/include/clang/Basic/Builtins.def b/clang/include/clang/Basic/Builtins.def
index c8f955a1f4b28..4f18c48d0ce40 100644
--- a/clang/include/clang/Basic/Builtins.def
+++ b/clang/include/clang/Basic/Builtins.def
@@ -159,6 +159,7 @@ BUILTIN(__builtin_ldexp , "ddi" , "Fne")
BUILTIN(__builtin_ldexpf, "ffi" , "Fne")
BUILTIN(__builtin_ldexpl, "LdLdi", "Fne")
BUILTIN(__builtin_ldexpf128, "LLdLLdi", "Fne")
+BUILTIN(__builtin_ldexpf16, "hhi", "Fne")
BUILTIN(__builtin_modf , "ddd*" , "Fn")
BUILTIN(__builtin_modff, "fff*" , "Fn")
BUILTIN(__builtin_modfl, "LdLdLd*", "Fn")
diff --git a/clang/lib/CodeGen/CGBuiltin.cpp b/clang/lib/CodeGen/CGBuiltin.cpp
index ddf28dc166636..d958198c5aef3 100644
--- a/clang/lib/CodeGen/CGBuiltin.cpp
+++ b/clang/lib/CodeGen/CGBuiltin.cpp
@@ -540,6 +540,25 @@ static Value *emitBinaryMaybeConstrainedFPBuiltin(CodeGenFunction &CGF,
}
}
+// Has second type mangled argument.
+static Value *emitBinaryExpMaybeConstrainedFPBuiltin(
+ CodeGenFunction &CGF, const CallExpr *E, llvm::Intrinsic::ID IntrinsicID,
+ llvm::Intrinsic::ID ConstrainedIntrinsicID) {
+ llvm::Value *Src0 = CGF.EmitScalarExpr(E->getArg(0));
+ llvm::Value *Src1 = CGF.EmitScalarExpr(E->getArg(1));
+
+ if (CGF.Builder.getIsFPConstrained()) {
+ CodeGenFunction::CGFPOptionsRAII FPOptsRAII(CGF, E);
+ Function *F = CGF.CGM.getIntrinsic(ConstrainedIntrinsicID,
+ {Src0->getType(), Src1->getType()});
+ return CGF.Builder.CreateConstrainedFPCall(F, {Src0, Src1});
+ }
+
+ Function *F =
+ CGF.CGM.getIntrinsic(IntrinsicID, {Src0->getType(), Src1->getType()});
+ return CGF.Builder.CreateCall(F, {Src0, Src1});
+}
+
// Emit an intrinsic that has 3 operands of the same type as its result.
// Depending on mode, this may be a constrained floating-point intrinsic.
static Value *emitTernaryMaybeConstrainedFPBuiltin(CodeGenFunction &CGF,
@@ -2567,7 +2586,15 @@ RValue CodeGenFunction::EmitBuiltinExpr(const GlobalDecl GD, unsigned BuiltinID,
return RValue::get(emitMaybeConstrainedFPToIntRoundBuiltin(
*this, E, Intrinsic::llrint,
Intrinsic::experimental_constrained_llrint));
-
+ case Builtin::BI__builtin_ldexp:
+ case Builtin::BI__builtin_ldexpf:
+ case Builtin::BI__builtin_ldexpl:
+ case Builtin::BI__builtin_ldexpf16:
+ case Builtin::BI__builtin_ldexpf128: {
+ return RValue::get(emitBinaryExpMaybeConstrainedFPBuiltin(
+ *this, E, Intrinsic::ldexp,
+ Intrinsic::experimental_constrained_ldexp));
+ }
default:
break;
}
@@ -3035,6 +3062,8 @@ RValue CodeGenFunction::EmitBuiltinExpr(const GlobalDecl GD, unsigned BuiltinID,
llvm::Value *Src1 = EmitScalarExpr(E->getArg(1));
if (Builder.getIsFPConstrained()) {
+ // FIXME: llvm.powi has 2 mangling types,
+ // llvm.experimental.constrained.powi has one.
CodeGenFunction::CGFPOptionsRAII FPOptsRAII(*this, E);
Function *F = CGM.getIntrinsic(Intrinsic::experimental_constrained_powi,
Src0->getType());
diff --git a/clang/test/CodeGen/aix-builtin-mapping.c b/clang/test/CodeGen/aix-builtin-mapping.c
index 57ea558652e1a..98fcfd4a3a6fc 100644
--- a/clang/test/CodeGen/aix-builtin-mapping.c
+++ b/clang/test/CodeGen/aix-builtin-mapping.c
@@ -19,4 +19,4 @@ int main()
// CHECK: %call = call double @modf(double noundef 1.000000e+00, ptr noundef %DummyLongDouble) #3
// CHECK: %call1 = call double @frexp(double noundef 0.000000e+00, ptr noundef %DummyInt) #3
-// CHECK: %call2 = call double @ldexp(double noundef 1.000000e+00, i32 noundef {{(signext )?}}1) #4
+// CHECK: %{{.+}} = call double @llvm.ldexp.f64.i32(double 1.000000e+00, i32 1)
diff --git a/clang/test/CodeGen/constrained-math-builtins.c b/clang/test/CodeGen/constrained-math-builtins.c
index cccfd8bc7746a..88ae8f58a7e20 100644
--- a/clang/test/CodeGen/constrained-math-builtins.c
+++ b/clang/test/CodeGen/constrained-math-builtins.c
@@ -7,7 +7,7 @@
#pragma float_control(except, on)
-void foo(double *d, float f, float *fp, long double *l, int *i, const char *c) {
+void foo(double *d, float f, float *fp, long double *l, int *i, const char *c, _Float16 h) {
f = __builtin_fmod(f,f); f = __builtin_fmodf(f,f); f = __builtin_fmodl(f,f); f = __builtin_fmodf128(f,f);
// CHECK: call double @llvm.experimental.constrained.frem.f64(double %{{.*}}, double %{{.*}}, metadata !"round.tonearest", metadata !"fpexcept.strict")
@@ -28,6 +28,14 @@ void foo(double *d, float f, float *fp, long double *l, int *i, const char *c) {
// CHECK: call float @llvm.experimental.constrained.powi.f32(float %{{.*}}, metadata !"round.tonearest", metadata !"fpexcept.strict")
// CHECK: call x86_fp80 @llvm.experimental.constrained.powi.f80(x86_fp80 %{{.*}}, metadata !"round.tonearest", metadata !"fpexcept.strict")
+
+ h = __builtin_ldexpf16(h, *i); *d = __builtin_ldexp(*d, *i); f = __builtin_ldexpf(f, *i); __builtin_ldexpl(*l, *i);
+
+// CHECK: call half @llvm.experimental.constrained.ldexp.f16.i32(half %{{.*}}, i32 %{{.*}}, metadata !"round.tonearest", metadata !"fpexcept.strict")
+// CHECK: call double @llvm.experimental.constrained.ldexp.f64.i32(double %{{.*}}, i32 %{{.*}}, metadata !"round.tonearest", metadata !"fpexcept.strict")
+// CHECK: call float @llvm.experimental.constrained.ldexp.f32.i32(float %{{.*}}, i32 %{{.*}}, metadata !"round.tonearest", metadata !"fpexcept.strict")
+// CHECK: call x86_fp80 @llvm.experimental.constrained.ldexp.f80.i32(x86_fp80 %{{.*}}, i32 %{{.*}}, metadata !"round.tonearest", metadata !"fpexcept.strict")
+
__builtin_ceil(f); __builtin_ceilf(f); __builtin_ceill(f); __builtin_ceilf128(f);
// CHECK: call double @llvm.experimental.constrained.ceil.f64(double %{{.*}}, metadata !"fpexcept.strict")
@@ -190,6 +198,11 @@ void foo(double *d, float f, float *fp, long double *l, int *i, const char *c) {
// CHECK: declare float @llvm.experimental.constrained.powi.f32(float, i32, metadata, metadata)
// CHECK: declare x86_fp80 @llvm.experimental.constrained.powi.f80(x86_fp80, i32, metadata, metadata)
+// CHECK: declare half @llvm.experimental.constrained.ldexp.f16.i32(half, i32, metadata, metadata)
+// CHECK: declare double @llvm.experimental.constrained.ldexp.f64.i32(double, i32, metadata, metadata)
+// CHECK: declare float @llvm.experimental.constrained.ldexp.f32.i32(float, i32, metadata, metadata)
+// CHECK: declare x86_fp80 @llvm.experimental.constrained.ldexp.f80.i32(x86_fp80, i32, metadata, metadata)
+
// CHECK: declare double @llvm.experimental.constrained.ceil.f64(double, metadata)
// CHECK: declare float @llvm.experimental.constrained.ceil.f32(float, metadata)
// CHECK: declare x86_fp80 @llvm.experimental.constrained.ceil.f80(x86_fp80, metadata)
diff --git a/clang/test/CodeGen/math-builtins.c b/clang/test/CodeGen/math-builtins.c
index 04738cce01073..6233501937920 100644
--- a/clang/test/CodeGen/math-builtins.c
+++ b/clang/test/CodeGen/math-builtins.c
@@ -77,10 +77,10 @@ void foo(double *d, float f, float *fp, long double *l, int *i, const char *c) {
__builtin_ldexp(f,f); __builtin_ldexpf(f,f); __builtin_ldexpl(f,f); __builtin_ldexpf128(f,f);
-// NO__ERRNO: declare double @ldexp(double noundef, i32 noundef) [[READNONE]]
-// NO__ERRNO: declare float @ldexpf(float noundef, i32 noundef) [[READNONE]]
-// NO__ERRNO: declare x86_fp80 @ldexpl(x86_fp80 noundef, i32 noundef) [[READNONE]]
-// NO__ERRNO: declare fp128 @ldexpf128(fp128 noundef, i32 noundef) [[READNONE]]
+// NO__ERRNO: declare double @llvm.ldexp.f64.i32(double, i32) [[READNONE_INTRINSIC]]
+// NO__ERRNO: declare float @llvm.ldexp.f32.i32(float, i32) [[READNONE_INTRINSIC]]
+// NO__ERRNO: declare x86_fp80 @llvm.ldexp.f80.i32(x86_fp80, i32) [[READNONE_INTRINSIC]]
+// NO__ERRNO: declare fp128 @llvm.ldexp.f128.i32(fp128, i32) [[READNONE_INTRINSIC]]
// HAS_ERRNO: declare double @ldexp(double noundef, i32 noundef) [[NOT_READNONE]]
// HAS_ERRNO: declare float @ldexpf(float noundef, i32 noundef) [[NOT_READNONE]]
// HAS_ERRNO: declare x86_fp80 @ldexpl(x86_fp80 noundef, i32 noundef) [[NOT_READNONE]]
diff --git a/clang/test/CodeGenOpenCL/builtins-f16.cl b/clang/test/CodeGenOpenCL/builtins-f16.cl
index 48412ddfaaead..caf20742ca846 100644
--- a/clang/test/CodeGenOpenCL/builtins-f16.cl
+++ b/clang/test/CodeGenOpenCL/builtins-f16.cl
@@ -3,7 +3,7 @@
#pragma OPENCL EXTENSION cl_khr_fp16 : enable
// CHECK-LABEL: define{{.*}} void @test_half_builtins
-void test_half_builtins(half h0, half h1, half h2) {
+void test_half_builtins(half h0, half h1, half h2, int i0) {
volatile half res;
// CHECK: call half @llvm.copysign.f16(half %h0, half %h1)
@@ -68,4 +68,7 @@ void test_half_builtins(half h0, half h1, half h2) {
// CHECK: call half @llvm.canonicalize.f16(half %h0)
res = __builtin_canonicalizef16(h0);
+
+ // CHECK: call half @llvm.ldexp.f16.i32(half %h0, i32 %i0)
+ res = __builtin_ldexpf16(h0, i0);
}
diff --git a/clang/test/CodeGenOpenCL/builtins-generic-amdgcn.cl b/clang/test/CodeGenOpenCL/builtins-generic-amdgcn.cl
index 46c044a0bef69..aa8f13310b5fd 100644
--- a/clang/test/CodeGenOpenCL/builtins-generic-amdgcn.cl
+++ b/clang/test/CodeGenOpenCL/builtins-generic-amdgcn.cl
@@ -1,6 +1,8 @@
// REQUIRES: amdgpu-registered-target
// RUN: %clang_cc1 -Wno-error=int-conversion -triple amdgcn-unknown-unknown -S -emit-llvm -o - %s | FileCheck %s
+#pragma OPENCL EXTENSION cl_khr_fp16 : enable
+
// CHECK-LABEL: @test_builtin_clz(
// CHECK: tail call i32 @llvm.ctlz.i32(i32 %a, i1 true)
void test_builtin_clz(global int* out, int a)
@@ -19,3 +21,21 @@ void test_builtin_clzl(global long* out, long a)
void test_builtin_frame_address(int *out) {
*out = __builtin_frame_address(0);
}
+
+// CHECK-LABEL: @test_builtin_ldexpf16(
+// CHECK: tail call half @llvm.ldexp.f16.i32(half %v, i32 %e)
+half test_builtin_ldexpf16(half v, int e) {
+ return __builtin_ldexpf16(v, e);
+}
+
+// CHECK-LABEL: @test_builtin_ldexpf(
+// CHECK: tail call float @llvm.ldexp.f32.i32(float %v, i32 %e)
+float test_builtin_ldexpf(float v, int e) {
+ return __builtin_ldexpf(v, e);
+}
+
+// CHECK-LABEL: @test_builtin_ldexp(
+// CHECK: tail call double @llvm.ldexp.f64.i32(double %v, i32 %e)
+double test_builtin_ldexp(double v, int e) {
+ return __builtin_ldexp(v, e);
+}
More information about the cfe-commits
mailing list