https://github.com/erichkeane updated https://github.com/llvm/llvm-project/pull/211614
>From 86f67eec9cf622426e7f5efae542797f38defe48 Mon Sep 17 00:00:00 2001 From: erichkeane <[email protected]> Date: Thu, 23 Jul 2026 07:50:31 -0700 Subject: [PATCH 1/2] [CIR]Implement lowering for simple sin/cos/tan/exp10 builtins. Discovered these just looking around, they are pretty simple/trivial translations to LLVM-IR intrins, and the infrastructure to do so is already in place, so this is a bit of simple wiring up! Implements f/h/hl versions of sin/cos/tan. Also implements base-10 exponent, since it is also trivial. --- clang/include/clang/CIR/Dialect/IR/CIROps.td | 40 +++++ clang/lib/CIR/CodeGen/CIRGenBuiltin.cpp | 7 +- .../CodeGenBuiltins/builtins-floating-point.c | 160 ++++++++++++++++++ 3 files changed, 204 insertions(+), 3 deletions(-) diff --git a/clang/include/clang/CIR/Dialect/IR/CIROps.td b/clang/include/clang/CIR/Dialect/IR/CIROps.td index 25b634f0e96f6..627cd626bae1d 100644 --- a/clang/include/clang/CIR/Dialect/IR/CIROps.td +++ b/clang/include/clang/CIR/Dialect/IR/CIROps.td @@ -6987,6 +6987,16 @@ def CIR_CosOp : CIR_UnaryFPToFPBuiltinOp<"cos", "CosOp"> { }]; } +def CIR_CoshOp : CIR_UnaryFPToFPBuiltinOp<"cosh", "CoshOp"> { + let summary = "Computes the floating-point hyperbolic cosine value"; + let description = [{ + `cir.cosh` computes the hyperbolic cosine of a floating-point operand and + returns a result of the same type. + + Floating-point exceptions are ignored, and it does not set `errno`. + }]; +} + def CIR_ExpOp : CIR_UnaryFPToFPBuiltinOp<"exp", "ExpOp"> { let summary = "Computes the floating-point base-e exponential value"; let description = [{ @@ -6997,6 +7007,16 @@ def CIR_ExpOp : CIR_UnaryFPToFPBuiltinOp<"exp", "ExpOp"> { }]; } +def CIR_Exp10Op : CIR_UnaryFPToFPBuiltinOp<"exp10", "Exp10Op"> { + let summary = "Computes the floating-point base-10 exponential value"; + let description = [{ + `cir.exp10` computes the base-10 exponential of a floating-point operand and + returns a result of the same type. + + Floating-point exceptions are ignored, and it does not set `errno`. + }]; +} + def CIR_Exp2Op : CIR_UnaryFPToFPBuiltinOp<"exp2", "Exp2Op"> { let summary = "Computes the floating-point base-2 exponential value"; let description = [{ @@ -7089,6 +7109,16 @@ def CIR_SinOp : CIR_UnaryFPToFPBuiltinOp<"sin", "SinOp"> { }]; } +def CIR_SinhOp : CIR_UnaryFPToFPBuiltinOp<"sinh", "SinhOp"> { + let summary = "Computes the floating-point hyperbolic sine"; + let description = [{ + `cir.sinh` computes the hyperbolic sine of a floating-point operand and + returns a result of the same type. + + Floating-point exceptions are ignored, and it does not set `errno`. + }]; +} + def CIR_TanOp : CIR_UnaryFPToFPBuiltinOp<"tan", "TanOp"> { let summary = "Computes the floating-point tangent"; let description = [{ @@ -7099,6 +7129,16 @@ def CIR_TanOp : CIR_UnaryFPToFPBuiltinOp<"tan", "TanOp"> { }]; } +def CIR_TanhOp : CIR_UnaryFPToFPBuiltinOp<"tanh", "TanhOp"> { + let summary = "Computes the floating-point hyperbolic tangent"; + let description = [{ + `cir.tanh` computes the hyperbolic tangent of a floating-point operand and + returns a result of the same type. + + Floating-point exceptions are ignored, and it does not set `errno`. + }]; +} + def CIR_TruncOp : CIR_UnaryFPToFPBuiltinOp<"trunc", "FTruncOp"> { let summary = "Truncates floating-point value to integer"; let description = [{ diff --git a/clang/lib/CIR/CodeGen/CIRGenBuiltin.cpp b/clang/lib/CIR/CodeGen/CIRGenBuiltin.cpp index d67134583d48a..5828cd4a14755 100644 --- a/clang/lib/CIR/CodeGen/CIRGenBuiltin.cpp +++ b/clang/lib/CIR/CodeGen/CIRGenBuiltin.cpp @@ -609,7 +609,7 @@ static RValue tryEmitFPMathIntrinsic(CIRGenFunction &cgf, const CallExpr *e, case Builtin::BI__builtin_coshl: case Builtin::BI__builtin_coshf128: case Builtin::BI__builtin_elementwise_cosh: - return errorBuiltinNYI(cgf, e, builtinID); + return emitUnaryMaybeConstrainedFPBuiltin<cir::CoshOp>(cgf, *e); case Builtin::BIexp: case Builtin::BIexpf: case Builtin::BIexpl: @@ -636,7 +636,7 @@ static RValue tryEmitFPMathIntrinsic(CIRGenFunction &cgf, const CallExpr *e, case Builtin::BI__builtin_exp10l: case Builtin::BI__builtin_exp10f128: case Builtin::BI__builtin_elementwise_exp10: - return errorBuiltinNYI(cgf, e, builtinID); + return emitUnaryMaybeConstrainedFPBuiltin<cir::Exp10Op>(cgf, *e); case Builtin::BIfabs: case Builtin::BIfabsf: case Builtin::BIfabsl: @@ -814,6 +814,7 @@ static RValue tryEmitFPMathIntrinsic(CIRGenFunction &cgf, const CallExpr *e, case Builtin::BI__builtin_sinhl: case Builtin::BI__builtin_sinhf128: case Builtin::BI__builtin_elementwise_sinh: + return emitUnaryMaybeConstrainedFPBuiltin<cir::SinhOp>(cgf, *e); case Builtin::BI__builtin_sincospi: case Builtin::BI__builtin_sincospif: case Builtin::BI__builtin_sincospil: @@ -855,7 +856,7 @@ static RValue tryEmitFPMathIntrinsic(CIRGenFunction &cgf, const CallExpr *e, case Builtin::BI__builtin_tanhl: case Builtin::BI__builtin_tanhf128: case Builtin::BI__builtin_elementwise_tanh: - return errorBuiltinNYI(cgf, e, builtinID); + return emitUnaryMaybeConstrainedFPBuiltin<cir::TanhOp>(cgf, *e); case Builtin::BItrunc: case Builtin::BItruncf: case Builtin::BItruncl: diff --git a/clang/test/CIR/CodeGenBuiltins/builtins-floating-point.c b/clang/test/CIR/CodeGenBuiltins/builtins-floating-point.c index c3306ccbada01..bd288526736ea 100644 --- a/clang/test/CIR/CodeGenBuiltins/builtins-floating-point.c +++ b/clang/test/CIR/CodeGenBuiltins/builtins-floating-point.c @@ -1511,6 +1511,166 @@ long double my_tanl(long double f) { // OGCG: call x86_fp80 @llvm.tan.f80( } +// cosh + +float my_coshf(float f) { + return __builtin_coshf(f); + // CIR: cir.func no_inline dso_local @my_coshf + // CIR: {{.+}} = cir.cosh {{.+}} : !cir.float + + // LLVM: define dso_local float @my_coshf(float noundef {{.*}}) + // LLVM: call float @llvm.cosh.f32(float %{{.+}}) + // LLVM: } + + // OGCG: define{{.*}}@my_coshf( + // OGCG: call float @llvm.cosh.f32( +} +double my_cosh(double f) { + return __builtin_cosh(f); + // CIR: cir.func no_inline dso_local @my_cosh + // CIR: {{.+}} = cir.cosh {{.+}} : !cir.double + + // LLVM: define dso_local double @my_cosh(double noundef {{.*}}) + // LLVM: call double @llvm.cosh.f64(double %{{.+}}) + // LLVM: } + + // OGCG: define{{.*}}@my_cosh( + // OGCG: call double @llvm.cosh.f64( +} +long double my_coshl(long double f) { + return __builtin_coshl(f); + // CIR: cir.func no_inline dso_local @my_coshl + // CIR: {{.+}} = cir.cosh {{.+}} : !cir.long_double<!cir.f80> + // AARCH64: {{.+}} = cir.cosh {{.+}} : !cir.long_double<!cir.double> + + // LLVM: define dso_local x86_fp80 @my_coshl(x86_fp80 noundef {{.*}}) + // LLVM: call x86_fp80 @llvm.cosh.f80(x86_fp80 %{{.+}}) + // LLVM: } + + // OGCG: define{{.*}}@my_coshl( + // OGCG: call x86_fp80 @llvm.cosh.f80( +} + +// sinh + +float my_sinhf(float f) { + return __builtin_sinhf(f); + // CIR: cir.func no_inline dso_local @my_sinhf + // CIR: {{.+}} = cir.sinh {{.+}} : !cir.float + + // LLVM: define dso_local float @my_sinhf(float noundef {{.*}}) + // LLVM: call float @llvm.sinh.f32(float %{{.+}}) + // LLVM: } + + // OGCG: define{{.*}}@my_sinhf( + // OGCG: call float @llvm.sinh.f32( +} +double my_sinh(double f) { + return __builtin_sinh(f); + // CIR: cir.func no_inline dso_local @my_sinh + // CIR: {{.+}} = cir.sinh {{.+}} : !cir.double + + // LLVM: define dso_local double @my_sinh(double noundef {{.*}}) + // LLVM: call double @llvm.sinh.f64(double %{{.+}}) + // LLVM: } + + // OGCG: define{{.*}}@my_sinh( + // OGCG: call double @llvm.sinh.f64( +} +long double my_sinhl(long double f) { + return __builtin_sinhl(f); + // CIR: cir.func no_inline dso_local @my_sinhl + // CIR: {{.+}} = cir.sinh {{.+}} : !cir.long_double<!cir.f80> + // AARCH64: {{.+}} = cir.sinh {{.+}} : !cir.long_double<!cir.double> + + // LLVM: define dso_local x86_fp80 @my_sinhl(x86_fp80 noundef {{.*}}) + // LLVM: call x86_fp80 @llvm.sinh.f80(x86_fp80 %{{.+}}) + // LLVM: } + + // OGCG: define{{.*}}@my_sinhl( + // OGCG: call x86_fp80 @llvm.sinh.f80( +} + +// tanh + +float my_tanhf(float f) { + return __builtin_tanhf(f); + // CIR: cir.func no_inline dso_local @my_tanhf + // CIR: {{.+}} = cir.tanh {{.+}} : !cir.float + + // LLVM: define dso_local float @my_tanhf(float noundef {{.*}}) + // LLVM: call float @llvm.tanh.f32(float %{{.+}}) + // LLVM: } + + // OGCG: define{{.*}}@my_tanhf( + // OGCG: call float @llvm.tanh.f32( +} +double my_tanh(double f) { + return __builtin_tanh(f); + // CIR: cir.func no_inline dso_local @my_tanh + // CIR: {{.+}} = cir.tanh {{.+}} : !cir.double + + // LLVM: define dso_local double @my_tanh(double noundef {{.*}}) + // LLVM: call double @llvm.tanh.f64(double %{{.+}}) + // LLVM: } + + // OGCG: define{{.*}}@my_tanh( + // OGCG: call double @llvm.tanh.f64( +} +long double my_tanhl(long double f) { + return __builtin_tanhl(f); + // CIR: cir.func no_inline dso_local @my_tanhl + // CIR: {{.+}} = cir.tanh {{.+}} : !cir.long_double<!cir.f80> + // AARCH64: {{.+}} = cir.tanh {{.+}} : !cir.long_double<!cir.double> + + // LLVM: define dso_local x86_fp80 @my_tanhl(x86_fp80 noundef {{.*}}) + // LLVM: call x86_fp80 @llvm.tanh.f80(x86_fp80 %{{.+}}) + // LLVM: } + + // OGCG: define{{.*}}@my_tanhl( + // OGCG: call x86_fp80 @llvm.tanh.f80( +} + +// exp10 + +float my_exp10f(float f) { + return __builtin_exp10f(f); + // CIR: cir.func no_inline dso_local @my_exp10f + // CIR: {{.+}} = cir.exp10 {{.+}} : !cir.float + + // LLVM: define dso_local float @my_exp10f(float noundef {{.*}}) + // LLVM: call float @llvm.exp10.f32(float %{{.+}}) + // LLVM: } + + // OGCG: define{{.*}}@my_exp10f( + // OGCG: call float @llvm.exp10.f32( +} +double my_exp10(double f) { + return __builtin_exp10(f); + // CIR: cir.func no_inline dso_local @my_exp10 + // CIR: {{.+}} = cir.exp10 {{.+}} : !cir.double + + // LLVM: define dso_local double @my_exp10(double noundef {{.*}}) + // LLVM: call double @llvm.exp10.f64(double %{{.+}}) + // LLVM: } + + // OGCG: define{{.*}}@my_exp10( + // OGCG: call double @llvm.exp10.f64( +} +long double my_exp10l(long double f) { + return __builtin_exp10l(f); + // CIR: cir.func no_inline dso_local @my_exp10l + // CIR: {{.+}} = cir.exp10 {{.+}} : !cir.long_double<!cir.f80> + // AARCH64: {{.+}} = cir.exp10 {{.+}} : !cir.long_double<!cir.double> + + // LLVM: define dso_local x86_fp80 @my_exp10l(x86_fp80 noundef {{.*}}) + // LLVM: call x86_fp80 @llvm.exp10.f80(x86_fp80 %{{.+}}) + // LLVM: } + + // OGCG: define{{.*}}@my_exp10l( + // OGCG: call x86_fp80 @llvm.exp10.f80( +} + float tanf(float); double tan(double); long double tanl(long double); >From 9b542d6adc7afa2a96342d23fc4128cf29123df3 Mon Sep 17 00:00:00 2001 From: erichkeane <[email protected]> Date: Thu, 30 Jul 2026 07:32:05 -0700 Subject: [PATCH 2/2] Add additional tests as requested by Andy --- .../CodeGenBuiltins/builtins-elementwise.c | 88 +++++++++++++++++++ .../CodeGenBuiltins/builtins-floating-point.c | 52 +++++++++++ 2 files changed, 140 insertions(+) diff --git a/clang/test/CIR/CodeGenBuiltins/builtins-elementwise.c b/clang/test/CIR/CodeGenBuiltins/builtins-elementwise.c index b5600901be247..f89c9278c082d 100644 --- a/clang/test/CIR/CodeGenBuiltins/builtins-elementwise.c +++ b/clang/test/CIR/CodeGenBuiltins/builtins-elementwise.c @@ -64,6 +64,28 @@ void test_builtin_elementwise_acos(float f, double d, vfloat4 vf4, vd4 = __builtin_elementwise_acos(vd4); } +void test_builtin_elementwise_cosh(float f, double d, vfloat4 vf4, + vdouble4 vd4) { + // CIR-LABEL: test_builtin_elementwise_cosh + // LLVM-LABEL: test_builtin_elementwise_cosh + + // CIR: cir.cosh %{{.*}} : !cir.float + // LLVM: call float @llvm.cosh.f32(float %{{.*}}) + f = __builtin_elementwise_cosh(f); + + // CIR: cir.cosh %{{.*}} : !cir.double + // LLVM: call double @llvm.cosh.f64(double %{{.*}}) + d = __builtin_elementwise_cosh(d); + + // CIR: cir.cosh %{{.*}} : !cir.vector<4 x !cir.float> + // LLVM: call <4 x float> @llvm.cosh.v4f32(<4 x float> %{{.*}}) + vf4 = __builtin_elementwise_cosh(vf4); + + // CIR: cir.cosh %{{.*}} : !cir.vector<4 x !cir.double> + // LLVM: call <4 x double> @llvm.cosh.v4f64(<4 x double> %{{.*}}) + vd4 = __builtin_elementwise_cosh(vd4); +} + void test_builtin_elementwise_asin(float f, double d, vfloat4 vf4, vdouble4 vd4) { // CIR-LABEL: test_builtin_elementwise_asin @@ -86,6 +108,28 @@ void test_builtin_elementwise_asin(float f, double d, vfloat4 vf4, vd4 = __builtin_elementwise_asin(vd4); } +void test_builtin_elementwise_sinh(float f, double d, vfloat4 vf4, + vdouble4 vd4) { + // CIR-LABEL: test_builtin_elementwise_sinh + // LLVM-LABEL: test_builtin_elementwise_sinh + + // CIR: cir.sinh %{{.*}} : !cir.float + // LLVM: call float @llvm.sinh.f32(float %{{.*}}) + f = __builtin_elementwise_sinh(f); + + // CIR: cir.sinh %{{.*}} : !cir.double + // LLVM: call double @llvm.sinh.f64(double %{{.*}}) + d = __builtin_elementwise_sinh(d); + + // CIR: cir.sinh %{{.*}} : !cir.vector<4 x !cir.float> + // LLVM: call <4 x float> @llvm.sinh.v4f32(<4 x float> %{{.*}}) + vf4 = __builtin_elementwise_sinh(vf4); + + // CIR: cir.sinh %{{.*}} : !cir.vector<4 x !cir.double> + // LLVM: call <4 x double> @llvm.sinh.v4f64(<4 x double> %{{.*}}) + vd4 = __builtin_elementwise_sinh(vd4); +} + void test_builtin_elementwise_atan(float f, double d, vfloat4 vf4, vdouble4 vd4) { // CIR-LABEL: test_builtin_elementwise_atan @@ -108,6 +152,28 @@ void test_builtin_elementwise_atan(float f, double d, vfloat4 vf4, vd4 = __builtin_elementwise_atan(vd4); } +void test_builtin_elementwise_tanh(float f, double d, vfloat4 vf4, + vdouble4 vd4) { + // CIR-LABEL: test_builtin_elementwise_tanh + // LLVM-LABEL: test_builtin_elementwise_tanh + + // CIR: cir.tanh %{{.*}} : !cir.float + // LLVM: call float @llvm.tanh.f32(float %{{.*}}) + f = __builtin_elementwise_tanh(f); + + // CIR: cir.tanh %{{.*}} : !cir.double + // LLVM: call double @llvm.tanh.f64(double %{{.*}}) + d = __builtin_elementwise_tanh(d); + + // CIR: cir.tanh %{{.*}} : !cir.vector<4 x !cir.float> + // LLVM: call <4 x float> @llvm.tanh.v4f32(<4 x float> %{{.*}}) + vf4 = __builtin_elementwise_tanh(vf4); + + // CIR: cir.tanh %{{.*}} : !cir.vector<4 x !cir.double> + // LLVM: call <4 x double> @llvm.tanh.v4f64(<4 x double> %{{.*}}) + vd4 = __builtin_elementwise_tanh(vd4); +} + void test_builtin_elementwise_atan2(float f, double d, vfloat4 vf4, vdouble4 vd4) { // CIR-LABEL: test_builtin_elementwise_atan2 @@ -174,6 +240,28 @@ void test_builtin_elementwise_exp2(float f, double d, vfloat4 vf4, vd4 = __builtin_elementwise_exp2(vd4); } +void test_builtin_elementwise_exp10(float f, double d, vfloat4 vf4, + vdouble4 vd4) { + // CIR-LABEL: test_builtin_elementwise_exp10 + // LLVM-LABEL: test_builtin_elementwise_exp10 + + // CIR: cir.exp10 %{{.*}} : !cir.float + // LLVM: call float @llvm.exp10.f32(float %{{.*}}) + f = __builtin_elementwise_exp10(f); + + // CIR: cir.exp10 %{{.*}} : !cir.double + // LLVM: call double @llvm.exp10.f64(double %{{.*}}) + d = __builtin_elementwise_exp10(d); + + // CIR: cir.exp10 %{{.*}} : !cir.vector<4 x !cir.float> + // LLVM: call <4 x float> @llvm.exp10.v4f32(<4 x float> %{{.*}}) + vf4 = __builtin_elementwise_exp10(vf4); + + // CIR: cir.exp10 %{{.*}} : !cir.vector<4 x !cir.double> + // LLVM: call <4 x double> @llvm.exp10.v4f64(<4 x double> %{{.*}}) + vd4 = __builtin_elementwise_exp10(vd4); +} + void test_builtin_elementwise_log(float f, double d, vfloat4 vf4, vdouble4 vd4) { // CIR-LABEL: test_builtin_elementwise_log diff --git a/clang/test/CIR/CodeGenBuiltins/builtins-floating-point.c b/clang/test/CIR/CodeGenBuiltins/builtins-floating-point.c index bd288526736ea..47f01bebfe90c 100644 --- a/clang/test/CIR/CodeGenBuiltins/builtins-floating-point.c +++ b/clang/test/CIR/CodeGenBuiltins/builtins-floating-point.c @@ -1550,6 +1550,19 @@ long double my_coshl(long double f) { // OGCG: define{{.*}}@my_coshl( // OGCG: call x86_fp80 @llvm.cosh.f80( } +long double my_coshf128(long double f) { + return __builtin_coshf128(f); + // CIR: cir.func no_inline dso_local @my_coshf128 + // CIR: {{.*}} = cir.cosh {{.*}} : !cir.f128 + // AARCH64: {{.+}} = cir.cosh {{.+}} : !cir.f128 + + // LLVM: define dso_local x86_fp80 @my_coshf128(x86_fp80 noundef {{.*}}) + // LLVM: call fp128 @llvm.cosh.f128(fp128 %{{.+}}) + // LLVM: } + + // OGCG: define{{.*}}@my_coshf128( + // OGCG: call fp128 @llvm.cosh.f128( +} // sinh @@ -1590,6 +1603,19 @@ long double my_sinhl(long double f) { // OGCG: define{{.*}}@my_sinhl( // OGCG: call x86_fp80 @llvm.sinh.f80( } +long double my_sinhf128(long double f) { + return __builtin_sinhf128(f); + // CIR: cir.func no_inline dso_local @my_sinhf128 + // CIR: {{.+}} = cir.sinh {{.+}} : !cir.f128 + // AARCH64: {{.+}} = cir.sinh {{.+}} : !cir.f128 + + // LLVM: define dso_local x86_fp80 @my_sinhf128(x86_fp80 noundef {{.*}}) + // LLVM: call fp128 @llvm.sinh.f128(fp128 %{{.+}}) + // LLVM: } + + // OGCG: define{{.*}}@my_sinhf128( + // OGCG: call fp128 @llvm.sinh.f128( +} // tanh @@ -1630,6 +1656,19 @@ long double my_tanhl(long double f) { // OGCG: define{{.*}}@my_tanhl( // OGCG: call x86_fp80 @llvm.tanh.f80( } +long double my_tanhf128(long double f) { + return __builtin_tanhf128(f); + // CIR: cir.func no_inline dso_local @my_tanhf128 + // CIR: {{.+}} = cir.tanh {{.+}} : !cir.f128 + // AARCH64: {{.+}} = cir.tanh {{.+}} : !cir.f128 + + // LLVM: define dso_local x86_fp80 @my_tanhf128(x86_fp80 noundef {{.*}}) + // LLVM: call fp128 @llvm.tanh.f128(fp128 %{{.+}}) + // LLVM: } + + // OGCG: define{{.*}}@my_tanhf128( + // OGCG: call fp128 @llvm.tanh.f128( +} // exp10 @@ -1670,6 +1709,19 @@ long double my_exp10l(long double f) { // OGCG: define{{.*}}@my_exp10l( // OGCG: call x86_fp80 @llvm.exp10.f80( } +long double my_exp10f128(long double f) { + return __builtin_exp10f128(f); + // CIR: cir.func no_inline dso_local @my_exp10f128 + // CIR: {{.+}} = cir.exp10 {{.+}} : !cir.f128 + // AARCH64: {{.+}} = cir.exp10 {{.+}} : !cir.f128 + + // LLVM: define dso_local x86_fp80 @my_exp10f128(x86_fp80 noundef {{.*}}) + // LLVM: call fp128 @llvm.exp10.f128(fp128 %{{.+}}) + // LLVM: } + + // OGCG: define{{.*}}@my_exp10f128( + // OGCG: call fp128 @llvm.exp10.f128( +} float tanf(float); double tan(double); _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
