[clang] [clang] Lower modf builtin using `llvm.modf` intrinsic (PR #126750)
Benjamin Maxwell via cfe-commits
cfe-commits at lists.llvm.org
Tue Feb 11 07:50:40 PST 2025
https://github.com/MacDue created https://github.com/llvm/llvm-project/pull/126750
This updates the existing `modf[f|l]` builtin to be lowered via the `llvm.modf.*` intrinsic when `-fno-math-errno` is set (rather than directly to a library call).
>From eee5bc815c4b6b7e5a18503959b2a2354d73058b Mon Sep 17 00:00:00 2001
From: Benjamin Maxwell <benjamin.maxwell at arm.com>
Date: Tue, 11 Feb 2025 15:32:23 +0000
Subject: [PATCH] [clang] Lower modf builtin using `llvm.modf` intrinsic
This updates the existing `modf[f|l]` builtin to be lowered via the
`llvm.modf.*` intrinsic when `-fno-math-errno` is set (rather than
directly to a library call).
---
clang/lib/CodeGen/CGBuiltin.cpp | 26 ++++++++++++++++++++++++
clang/test/CodeGen/X86/math-builtins.c | 26 ++++++++++++++++++++----
clang/test/CodeGen/aix-builtin-mapping.c | 2 +-
clang/test/CodeGen/builtin-attributes.c | 2 +-
clang/test/CodeGen/math-libcalls.c | 12 +++++------
5 files changed, 56 insertions(+), 12 deletions(-)
diff --git a/clang/lib/CodeGen/CGBuiltin.cpp b/clang/lib/CodeGen/CGBuiltin.cpp
index 361e4c4bf2e2ed..07522a62ccae6b 100644
--- a/clang/lib/CodeGen/CGBuiltin.cpp
+++ b/clang/lib/CodeGen/CGBuiltin.cpp
@@ -859,6 +859,24 @@ static void emitSincosBuiltin(CodeGenFunction &CGF, const CallExpr *E,
StoreCos->setMetadata(LLVMContext::MD_noalias, AliasScopeList);
}
+static llvm::Value *emitModfBuiltin(CodeGenFunction &CGF, const CallExpr *E,
+ llvm::Intrinsic::ID IntrinsicID) {
+ llvm::Value *Val = CGF.EmitScalarExpr(E->getArg(0));
+ llvm::Value *IntPartDest = CGF.EmitScalarExpr(E->getArg(1));
+
+ llvm::Function *F = CGF.CGM.getIntrinsic(IntrinsicID, {Val->getType()});
+ llvm::Value *Call = CGF.Builder.CreateCall(F, Val);
+
+ llvm::Value *FractionalResult = CGF.Builder.CreateExtractValue(Call, 0);
+ llvm::Value *IntegralResult = CGF.Builder.CreateExtractValue(Call, 1);
+
+ QualType DestPtrType = E->getArg(1)->getType()->getPointeeType();
+ LValue IntegralLV = CGF.MakeNaturalAlignAddrLValue(IntPartDest, DestPtrType);
+ CGF.Builder.CreateStore(IntegralResult, IntegralLV.getAddress());
+
+ return FractionalResult;
+}
+
/// EmitFAbs - Emit a call to @llvm.fabs().
static Value *EmitFAbs(CodeGenFunction &CGF, Value *V) {
Function *F = CGF.CGM.getIntrinsic(Intrinsic::fabs, V->getType());
@@ -3259,6 +3277,14 @@ RValue CodeGenFunction::EmitBuiltinExpr(const GlobalDecl GD, unsigned BuiltinID,
return RValue::get(Builder.CreateFRem(Arg1, Arg2, "fmod"));
}
+ case Builtin::BImodf:
+ case Builtin::BImodff:
+ case Builtin::BImodfl:
+ case Builtin::BI__builtin_modf:
+ case Builtin::BI__builtin_modff:
+ case Builtin::BI__builtin_modfl:
+ return RValue::get(emitModfBuiltin(*this, E, Intrinsic::modf));
+
case Builtin::BIlog:
case Builtin::BIlogf:
case Builtin::BIlogl:
diff --git a/clang/test/CodeGen/X86/math-builtins.c b/clang/test/CodeGen/X86/math-builtins.c
index d7bf7d57fba26d..08c7765dd4002d 100644
--- a/clang/test/CodeGen/X86/math-builtins.c
+++ b/clang/test/CodeGen/X86/math-builtins.c
@@ -38,6 +38,24 @@ void foo(double *d, float f, float *fp, long double *l, int *i, const char *c) {
// NO__ERRNO-NEXT: [[FREXP_F128_0:%.+]] = extractvalue { fp128, i32 } [[FREXP_F128]], 0
+// NO__ERRNO: [[MODF_F64:%.+]] = call { double, double } @llvm.modf.f64(double %{{.+}})
+// NO__ERRNO-NEXT: [[MODF_F64_FP:%.+]] = extractvalue { double, double } [[MODF_F64]], 0
+// NO__ERRNO-NEXT: [[MODF_F64_IP:%.+]] = extractvalue { double, double } [[MODF_F64]], 1
+// NO__ERRNO-NEXT: store double [[MODF_F64_IP]], ptr %{{.+}}, align 8
+
+// NO__ERRNO: [[MODF_F32:%.+]] = call { float, float } @llvm.modf.f32(float %{{.+}})
+// NO__ERRNO-NEXT: [[MODF_F32_FP:%.+]] = extractvalue { float, float } [[MODF_F32]], 0
+// NO__ERRNO-NEXT: [[MODF_F32_IP:%.+]] = extractvalue { float, float } [[MODF_F32]], 1
+// NO__ERRNO-NEXT: store float [[MODF_F32_IP]], ptr %{{.+}}, align 4
+
+// NO__ERRNO: [[MODF_F80:%.+]] = call { x86_fp80, x86_fp80 } @llvm.modf.f80(x86_fp80 %{{.+}})
+// NO__ERRNO-NEXT: [[MODF_F80_FP:%.+]] = extractvalue { x86_fp80, x86_fp80 } [[MODF_F80]], 0
+// NO__ERRNO-NEXT: [[MODF_F80_IP:%.+]] = extractvalue { x86_fp80, x86_fp80 } [[MODF_F80]], 1
+// NO__ERRNO-NEXT: store x86_fp80 [[MODF_F80_IP]], ptr %{{.+}}, align 16
+
+// NO__ERRNO: call fp128 @modff128(fp128 noundef %{{.+}}, ptr noundef %{{.+}})
+
+
// NO__ERRNO: [[SINCOS_F64:%.+]] = call { double, double } @llvm.sincos.f64(double %{{.+}})
// NO__ERRNO-NEXT: [[SINCOS_F64_0:%.+]] = extractvalue { double, double } [[SINCOS_F64]], 0
// NO__ERRNO-NEXT: [[SINCOS_F64_1:%.+]] = extractvalue { double, double } [[SINCOS_F64]], 1
@@ -139,10 +157,10 @@ void foo(double *d, float f, float *fp, long double *l, int *i, const char *c) {
__builtin_modf(f,d); __builtin_modff(f,fp); __builtin_modfl(f,l); __builtin_modff128(f,l);
-// NO__ERRNO: declare double @modf(double noundef, ptr noundef) [[NOT_READNONE:#[0-9]+]]
-// NO__ERRNO: declare float @modff(float noundef, ptr noundef) [[NOT_READNONE]]
-// NO__ERRNO: declare x86_fp80 @modfl(x86_fp80 noundef, ptr noundef) [[NOT_READNONE]]
-// NO__ERRNO: declare fp128 @modff128(fp128 noundef, ptr noundef) [[NOT_READNONE]]
+// NO__ERRNO: declare { double, double } @llvm.modf.f64(double) [[READNONE_INTRINSIC]]
+// NO__ERRNO: declare { float, float } @llvm.modf.f32(float) [[READNONE_INTRINSIC]]
+// NO__ERRNO: declare { x86_fp80, x86_fp80 } @llvm.modf.f80(x86_fp80) [[READNONE_INTRINSIC]]
+// NO__ERRNO: declare fp128 @modff128(fp128 noundef, ptr noundef) [[NOT_READNONE:#[0-9]+]]
// HAS_ERRNO: declare double @modf(double noundef, ptr noundef) [[NOT_READNONE]]
// HAS_ERRNO: declare float @modff(float noundef, ptr noundef) [[NOT_READNONE]]
// HAS_ERRNO: declare x86_fp80 @modfl(x86_fp80 noundef, ptr noundef) [[NOT_READNONE]]
diff --git a/clang/test/CodeGen/aix-builtin-mapping.c b/clang/test/CodeGen/aix-builtin-mapping.c
index a79218c6f1d8b9..cc1cc1a44f32ce 100644
--- a/clang/test/CodeGen/aix-builtin-mapping.c
+++ b/clang/test/CodeGen/aix-builtin-mapping.c
@@ -17,6 +17,6 @@ int main()
returnValue = __builtin_ldexpl(1.0L, 1);
}
-// CHECK: %call = call double @modf(double noundef 1.000000e+00, ptr noundef %DummyLongDouble) #3
+// CHECK: %{{.+}} = call { double, double } @llvm.modf.f64(double 1.000000e+00)
// CHECK: %{{.+}} = call { double, i32 } @llvm.frexp.f64.i32(double 0.000000e+00)
// CHECK: %{{.+}} = call double @llvm.ldexp.f64.i32(double 1.000000e+00, i32 1)
diff --git a/clang/test/CodeGen/builtin-attributes.c b/clang/test/CodeGen/builtin-attributes.c
index e5b0faccfd23f2..8461467b104698 100644
--- a/clang/test/CodeGen/builtin-attributes.c
+++ b/clang/test/CodeGen/builtin-attributes.c
@@ -1,5 +1,5 @@
// REQUIRES: arm-registered-target
-// RUN: %clang_cc1 -triple arm-unknown-linux-gnueabi -emit-llvm -o - %s | FileCheck %s
+// RUN: %clang_cc1 -triple arm-unknown-linux-gnueabi -fmath-errno -emit-llvm -o - %s | FileCheck %s
int printf(const char *, ...);
void exit(int);
diff --git a/clang/test/CodeGen/math-libcalls.c b/clang/test/CodeGen/math-libcalls.c
index bcc61c8f046b43..507d3a9bd03692 100644
--- a/clang/test/CodeGen/math-libcalls.c
+++ b/clang/test/CodeGen/math-libcalls.c
@@ -83,15 +83,15 @@ void foo(double *d, float f, float *fp, long double *l, int *i, const char *c) {
modf(f,d); modff(f,fp); modfl(f,l);
- // NO__ERRNO: declare double @modf(double noundef, ptr noundef) [[NOT_READNONE]]
- // NO__ERRNO: declare float @modff(float noundef, ptr noundef) [[NOT_READNONE]]
- // NO__ERRNO: declare x86_fp80 @modfl(x86_fp80 noundef, ptr noundef) [[NOT_READNONE]]
+ // NO__ERRNO: declare { double, double } @llvm.modf.f64(double) [[READNONE_INTRINSIC]]
+ // NO__ERRNO: declare { float, float } @llvm.modf.f32(float) [[READNONE_INTRINSIC]]
+ // NO__ERRNO: declare { x86_fp80, x86_fp80 } @llvm.modf.f80(x86_fp80) [[READNONE_INTRINSIC]]
// HAS_ERRNO: declare double @modf(double noundef, ptr noundef) [[NOT_READNONE]]
// HAS_ERRNO: declare float @modff(float noundef, ptr noundef) [[NOT_READNONE]]
// HAS_ERRNO: declare x86_fp80 @modfl(x86_fp80 noundef, ptr noundef) [[NOT_READNONE]]
- // HAS_MAYTRAP: declare double @modf(double noundef, ptr noundef) [[NOT_READNONE]]
- // HAS_MAYTRAP: declare float @modff(float noundef, ptr noundef) [[NOT_READNONE]]
- // HAS_MAYTRAP: declare x86_fp80 @modfl(x86_fp80 noundef, ptr noundef) [[NOT_READNONE]]
+ // HAS_MAYTRAP: declare { double, double } @llvm.modf.f64(double) [[READNONE_INTRINSIC]]
+ // HAS_MAYTRAP: declare { float, float } @llvm.modf.f32(float) [[READNONE_INTRINSIC]]
+ // HAS_MAYTRAP: declare { x86_fp80, x86_fp80 } @llvm.modf.f80(x86_fp80) [[READNONE_INTRINSIC]]
nan(c); nanf(c); nanl(c);
More information about the cfe-commits
mailing list