[clang] [clang] Add sincos builtin using `llvm.sincos` intrinsic (PR #114086)
Benjamin Maxwell via cfe-commits
cfe-commits at lists.llvm.org
Mon Dec 16 08:04:56 PST 2024
https://github.com/MacDue updated https://github.com/llvm/llvm-project/pull/114086
>From 5e6e49cf8bceed6d137ea67abe81a8a425d5aed8 Mon Sep 17 00:00:00 2001
From: Benjamin Maxwell <benjamin.maxwell at arm.com>
Date: Mon, 9 Sep 2024 10:15:20 +0000
Subject: [PATCH 1/4] [clang] Add sincos builtin using `llvm.sincos` intrinsic
This registers `sincos[f|l]` as a clang builtin and updates GCBuiltin
to emit the `llvm.sincos.*` intrinsic when `-fno-math-errno` is set.
---
clang/include/clang/Basic/Builtins.td | 13 +++++++
clang/lib/CodeGen/CGBuiltin.cpp | 43 ++++++++++++++++++++++++
clang/test/CodeGen/AArch64/sincos.c | 33 ++++++++++++++++++
clang/test/CodeGen/X86/math-builtins.c | 35 +++++++++++++++++++
clang/test/OpenMP/declare_simd_aarch64.c | 4 +--
5 files changed, 126 insertions(+), 2 deletions(-)
create mode 100644 clang/test/CodeGen/AArch64/sincos.c
diff --git a/clang/include/clang/Basic/Builtins.td b/clang/include/clang/Basic/Builtins.td
index 32a09e2ceb3857..d0e09e735c39d3 100644
--- a/clang/include/clang/Basic/Builtins.td
+++ b/clang/include/clang/Basic/Builtins.td
@@ -3568,6 +3568,19 @@ def Frexp : FPMathTemplate, LibBuiltin<"math.h"> {
let AddBuiltinPrefixedAlias = 1;
}
+def Sincos : FPMathTemplate, GNULibBuiltin<"math.h"> {
+ let Spellings = ["sincos"];
+ let Attributes = [NoThrow];
+ let Prototype = "void(T, T*, T*)";
+ let AddBuiltinPrefixedAlias = 1;
+}
+
+def SincosF16F128 : F16F128MathTemplate, Builtin {
+ let Spellings = ["__builtin_sincos"];
+ let Attributes = [FunctionWithBuiltinPrefix, NoThrow];
+ let Prototype = "void(T, T*, T*)";
+}
+
def Ldexp : FPMathTemplate, LibBuiltin<"math.h"> {
let Spellings = ["ldexp"];
let Attributes = [NoThrow, ConstIgnoringErrnoAndExceptions];
diff --git a/clang/lib/CodeGen/CGBuiltin.cpp b/clang/lib/CodeGen/CGBuiltin.cpp
index 84048a4beac2c5..bdf797440d36a2 100644
--- a/clang/lib/CodeGen/CGBuiltin.cpp
+++ b/clang/lib/CodeGen/CGBuiltin.cpp
@@ -835,6 +835,38 @@ static Value *emitFrexpBuiltin(CodeGenFunction &CGF, const CallExpr *E,
return CGF.Builder.CreateExtractValue(Call, 0);
}
+static void emitSincosBuiltin(CodeGenFunction &CGF, const CallExpr *E,
+ llvm::Intrinsic::ID IntrinsicID) {
+ llvm::Value *Val = CGF.EmitScalarExpr(E->getArg(0));
+ llvm::Value *Dest0 = CGF.EmitScalarExpr(E->getArg(1));
+ llvm::Value *Dest1 = CGF.EmitScalarExpr(E->getArg(2));
+
+ llvm::Function *F = CGF.CGM.getIntrinsic(IntrinsicID, {Val->getType()});
+ llvm::Value *Call = CGF.Builder.CreateCall(F, Val);
+
+ llvm::Value *SinResult = CGF.Builder.CreateExtractValue(Call, 0);
+ llvm::Value *CosResult = CGF.Builder.CreateExtractValue(Call, 1);
+
+ QualType DestPtrType = E->getArg(1)->getType()->getPointeeType();
+ LValue SinLV = CGF.MakeNaturalAlignAddrLValue(Dest0, DestPtrType);
+ LValue CosLV = CGF.MakeNaturalAlignAddrLValue(Dest1, DestPtrType);
+
+ llvm::StoreInst *StoreSin =
+ CGF.Builder.CreateStore(SinResult, SinLV.getAddress());
+ llvm::StoreInst *StoreCos =
+ CGF.Builder.CreateStore(CosResult, CosLV.getAddress());
+
+ // Mark the two stores as non-aliasing with eachother. The order of stores
+ // emitted by this builtin is arbitrary, enforcing a particular order will
+ // prevent optimizations later on.
+ llvm::MDBuilder MDHelper(CGF.getLLVMContext());
+ MDNode *Domain = MDHelper.createAnonymousAliasScopeDomain();
+ MDNode *AliasScope = MDHelper.createAnonymousAliasScope(Domain);
+ MDNode *AliasScopeList = MDNode::get(Call->getContext(), AliasScope);
+ StoreSin->setMetadata(LLVMContext::MD_alias_scope, AliasScopeList);
+ StoreCos->setMetadata(LLVMContext::MD_noalias, AliasScopeList);
+}
+
/// EmitFAbs - Emit a call to @llvm.fabs().
static Value *EmitFAbs(CodeGenFunction &CGF, Value *V) {
Function *F = CGF.CGM.getIntrinsic(Intrinsic::fabs, V->getType());
@@ -3232,6 +3264,17 @@ RValue CodeGenFunction::EmitBuiltinExpr(const GlobalDecl GD, unsigned BuiltinID,
return RValue::get(emitUnaryMaybeConstrainedFPBuiltin(
*this, E, Intrinsic::sinh, Intrinsic::experimental_constrained_sinh));
+ case Builtin::BIsincos:
+ case Builtin::BIsincosf:
+ case Builtin::BIsincosl:
+ case Builtin::BI__builtin_sincos:
+ case Builtin::BI__builtin_sincosf:
+ case Builtin::BI__builtin_sincosl:
+ case Builtin::BI__builtin_sincosf128:
+ case Builtin::BI__builtin_sincosf16:
+ emitSincosBuiltin(*this, E, Intrinsic::sincos);
+ return RValue::get(nullptr);
+
case Builtin::BIsqrt:
case Builtin::BIsqrtf:
case Builtin::BIsqrtl:
diff --git a/clang/test/CodeGen/AArch64/sincos.c b/clang/test/CodeGen/AArch64/sincos.c
new file mode 100644
index 00000000000000..240d921b2b7034
--- /dev/null
+++ b/clang/test/CodeGen/AArch64/sincos.c
@@ -0,0 +1,33 @@
+// RUN: %clang_cc1 -triple=aarch64-gnu-linux -emit-llvm %s -o - | FileCheck --check-prefix=NO-MATH-ERRNO %s
+// RUN: %clang_cc1 -triple=aarch64-gnu-linux -emit-llvm -fmath-errno %s -o - | FileCheck --check-prefix=MATH-ERRNO %s
+
+void sincos(double, double*, double*);
+void sincosf(float, float*, float*);
+
+// NO-MATH-ERRNO-LABEL: @foo
+// NO-MATH-ERRNO: [[SINCOS:%.*]] = call { double, double } @llvm.sincos.f64(double {{.*}})
+// NO-MATH-ERRNO-NEXT: [[SIN:%.*]] = extractvalue { double, double } [[SINCOS]], 0
+// NO-MATH-ERRNO-NEXT: [[COS:%.*]] = extractvalue { double, double } [[SINCOS]], 1
+// NO-MATH-ERRNO-NEXT: store double [[SIN]], ptr {{.*}}, align 8, !alias.scope [[SINCOS_ALIAS_SCOPE:![0-9]+]]
+// NO-MATH-ERRNO-NEXT: store double [[COS]], ptr {{.*}}, align 8, !noalias [[SINCOS_ALIAS_SCOPE]]
+//
+// MATH-ERRNO-LABEL: @foo
+// MATH-ERRNO: call void @sincos(
+//
+void foo(double x, double* dp0, double* dp1) {
+ sincos(x, dp0, dp1);
+}
+
+// NO-MATH-ERRNO-LABEL: @bar
+// NO-MATH-ERRNO: [[SINCOS:%.*]] = call { float, float } @llvm.sincos.f32(float {{.*}})
+// NO-MATH-ERRNO-NEXT: [[SIN:%.*]] = extractvalue { float, float } [[SINCOS]], 0
+// NO-MATH-ERRNO-NEXT: [[COS:%.*]] = extractvalue { float, float } [[SINCOS]], 1
+// NO-MATH-ERRNO-NEXT: store float [[SIN]], ptr {{.*}}, align 4, !alias.scope [[SINCOS_ALIAS_SCOPE:![0-9]+]]
+// NO-MATH-ERRNO-NEXT: store float [[COS]], ptr {{.*}}, align 4, !noalias [[SINCOS_ALIAS_SCOPE]]
+//
+// MATH-ERRNO-LABEL: @bar
+// MATH-ERRNO: call void @sincosf(
+//
+void bar(float x, float* fp0, float* fp1) {
+ sincosf(x, fp0, fp1);
+}
diff --git a/clang/test/CodeGen/X86/math-builtins.c b/clang/test/CodeGen/X86/math-builtins.c
index bf107437fc63a3..292e87c33c240b 100644
--- a/clang/test/CodeGen/X86/math-builtins.c
+++ b/clang/test/CodeGen/X86/math-builtins.c
@@ -38,6 +38,31 @@ 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: [[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
+// NO__ERRNO-NEXT: store double [[SINCOS_F64_0]], ptr %{{.+}}, align 8
+// NO__ERRNO-NEXT: store double [[SINCOS_F64_1]], ptr %{{.+}}, align 8
+
+// NO__ERRNO: [[SINCOS_F32:%.+]] = call { float, float } @llvm.sincos.f32(float %{{.+}})
+// NO__ERRNO-NEXT: [[SINCOS_F32_0:%.+]] = extractvalue { float, float } [[SINCOS_F32]], 0
+// NO__ERRNO-NEXT: [[SINCOS_F32_1:%.+]] = extractvalue { float, float } [[SINCOS_F32]], 1
+// NO__ERRNO-NEXT: store float [[SINCOS_F32_0]], ptr %{{.+}}, align 4
+// NO__ERRNO-NEXT: store float [[SINCOS_F32_1]], ptr %{{.+}}, align 4
+
+// NO__ERRNO: [[SINCOS_F80:%.+]] = call { x86_fp80, x86_fp80 } @llvm.sincos.f80(x86_fp80 %{{.+}})
+// NO__ERRNO-NEXT: [[SINCOS_F80_0:%.+]] = extractvalue { x86_fp80, x86_fp80 } [[SINCOS_F80]], 0
+// NO__ERRNO-NEXT: [[SINCOS_F80_1:%.+]] = extractvalue { x86_fp80, x86_fp80 } [[SINCOS_F80]], 1
+// NO__ERRNO-NEXT: store x86_fp80 [[SINCOS_F80_0]], ptr %{{.+}}, align 16
+// NO__ERRNO-NEXT: store x86_fp80 [[SINCOS_F80_1]], ptr %{{.+}}, align 16
+
+// NO__ERRNO: [[SINCOS_F128:%.+]] = call { fp128, fp128 } @llvm.sincos.f128(fp128 %{{.+}})
+// NO__ERRNO-NEXT: [[SINCOS_F128_0:%.+]] = extractvalue { fp128, fp128 } [[SINCOS_F128]], 0
+// NO__ERRNO-NEXT: [[SINCOS_F128_1:%.+]] = extractvalue { fp128, fp128 } [[SINCOS_F128]], 1
+// NO__ERRNO-NEXT: store fp128 [[SINCOS_F128_0]], ptr %{{.+}}, align 16
+// NO__ERRNO-NEXT: store fp128 [[SINCOS_F128_1]], ptr %{{.+}}, align 16
+
+
// HAS_ERRNO: declare double @fmod(double noundef, double noundef) [[NOT_READNONE:#[0-9]+]]
// HAS_ERRNO: declare float @fmodf(float noundef, float noundef) [[NOT_READNONE]]
// HAS_ERRNO: declare x86_fp80 @fmodl(x86_fp80 noundef, x86_fp80 noundef) [[NOT_READNONE]]
@@ -665,6 +690,16 @@ __builtin_sinh(f); __builtin_sinhf(f); __builtin_sinhl(f); __builtin_
// HAS_ERRNO: declare x86_fp80 @sinhl(x86_fp80 noundef) [[NOT_READNONE]]
// HAS_ERRNO: declare fp128 @sinhf128(fp128 noundef) [[NOT_READNONE]]
+__builtin_sincos(f,d,d); __builtin_sincosf(f,fp,fp); __builtin_sincosl(f,l,l); __builtin_sincosf128(f,l,l);
+// NO__ERRNO: declare { double, double } @llvm.sincos.f64(double) [[READNONE_INTRINSIC]]
+// NO__ERRNO: declare { float, float } @llvm.sincos.f32(float) [[READNONE_INTRINSIC]]
+// NO__ERRNO: declare { x86_fp80, x86_fp80 } @llvm.sincos.f80(x86_fp80) [[READNONE_INTRINSIC]]
+// NO__ERRNO: declare { fp128, fp128 } @llvm.sincos.f128(fp128) [[READNONE_INTRINSIC]]
+// HAS_ERRNO: declare void @sincos(double noundef, ptr noundef, ptr noundef) [[NOT_READNONE]]
+// HAS_ERRNO: declare void @sincosf(float noundef, ptr noundef, ptr noundef) [[NOT_READNONE]]
+// HAS_ERRNO: declare void @sincosl(x86_fp80 noundef, ptr noundef, ptr noundef) [[NOT_READNONE]]
+// HAS_ERRNO: declare void @sincosf128(fp128 noundef, ptr noundef, ptr noundef) [[NOT_READNONE]]
+
__builtin_sqrt(f); __builtin_sqrtf(f); __builtin_sqrtl(f); __builtin_sqrtf128(f);
// NO__ERRNO: declare double @llvm.sqrt.f64(double) [[READNONE_INTRINSIC]]
diff --git a/clang/test/OpenMP/declare_simd_aarch64.c b/clang/test/OpenMP/declare_simd_aarch64.c
index 21c83c225963f9..e9538e7446eec9 100644
--- a/clang/test/OpenMP/declare_simd_aarch64.c
+++ b/clang/test/OpenMP/declare_simd_aarch64.c
@@ -1,8 +1,8 @@
// REQUIRES: aarch64-registered-target
// -fopemp and -fopenmp-simd behavior are expected to be the same.
-// RUN: %clang_cc1 -triple aarch64-linux-gnu -target-feature +neon -fopenmp -x c -emit-llvm %s -o - -femit-all-decls | FileCheck %s --check-prefix=AARCH64
-// RUN: %clang_cc1 -triple aarch64-linux-gnu -target-feature +neon -fopenmp-simd -x c -emit-llvm %s -o - -femit-all-decls | FileCheck %s --check-prefix=AARCH64
+// RUN: %clang_cc1 -triple aarch64-linux-gnu -target-feature +neon -fmath-errno -fopenmp -x c -emit-llvm %s -o - -femit-all-decls | FileCheck %s --check-prefix=AARCH64
+// RUN: %clang_cc1 -triple aarch64-linux-gnu -target-feature +neon -fmath-errno -fopenmp-simd -x c -emit-llvm %s -o - -femit-all-decls | FileCheck %s --check-prefix=AARCH64
#pragma omp declare simd
#pragma omp declare simd simdlen(2)
>From 7210b512f6eca502df0382eac61e7434a0884d0c Mon Sep 17 00:00:00 2001
From: Benjamin Maxwell <benjamin.maxwell at arm.com>
Date: Wed, 30 Oct 2024 15:13:22 +0000
Subject: [PATCH 2/4] Fix typo
---
clang/lib/CodeGen/CGBuiltin.cpp | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/clang/lib/CodeGen/CGBuiltin.cpp b/clang/lib/CodeGen/CGBuiltin.cpp
index bdf797440d36a2..71804503c8e336 100644
--- a/clang/lib/CodeGen/CGBuiltin.cpp
+++ b/clang/lib/CodeGen/CGBuiltin.cpp
@@ -856,7 +856,7 @@ static void emitSincosBuiltin(CodeGenFunction &CGF, const CallExpr *E,
llvm::StoreInst *StoreCos =
CGF.Builder.CreateStore(CosResult, CosLV.getAddress());
- // Mark the two stores as non-aliasing with eachother. The order of stores
+ // Mark the two stores as non-aliasing with each other. The order of stores
// emitted by this builtin is arbitrary, enforcing a particular order will
// prevent optimizations later on.
llvm::MDBuilder MDHelper(CGF.getLLVMContext());
>From 3ab305e195c83f09b52916833dc78e6b04345f2d Mon Sep 17 00:00:00 2001
From: Benjamin Maxwell <benjamin.maxwell at arm.com>
Date: Mon, 16 Dec 2024 13:54:53 +0000
Subject: [PATCH 3/4] Fixups
---
clang/lib/CodeGen/CGBuiltin.cpp | 4 +--
clang/test/CodeGen/AArch64/sincos.c | 41 ++++++++++++++++++--------
clang/test/CodeGen/X86/math-builtins.c | 33 +++------------------
3 files changed, 34 insertions(+), 44 deletions(-)
diff --git a/clang/lib/CodeGen/CGBuiltin.cpp b/clang/lib/CodeGen/CGBuiltin.cpp
index 71804503c8e336..1294e02b5edc94 100644
--- a/clang/lib/CodeGen/CGBuiltin.cpp
+++ b/clang/lib/CodeGen/CGBuiltin.cpp
@@ -3270,8 +3270,8 @@ RValue CodeGenFunction::EmitBuiltinExpr(const GlobalDecl GD, unsigned BuiltinID,
case Builtin::BI__builtin_sincos:
case Builtin::BI__builtin_sincosf:
case Builtin::BI__builtin_sincosl:
- case Builtin::BI__builtin_sincosf128:
- case Builtin::BI__builtin_sincosf16:
+ if (!getTarget().getTriple().isAArch64())
+ break;
emitSincosBuiltin(*this, E, Intrinsic::sincos);
return RValue::get(nullptr);
diff --git a/clang/test/CodeGen/AArch64/sincos.c b/clang/test/CodeGen/AArch64/sincos.c
index 240d921b2b7034..0bfdb8e804632a 100644
--- a/clang/test/CodeGen/AArch64/sincos.c
+++ b/clang/test/CodeGen/AArch64/sincos.c
@@ -3,31 +3,46 @@
void sincos(double, double*, double*);
void sincosf(float, float*, float*);
+void sincosl(long double, long double*, long double*);
-// NO-MATH-ERRNO-LABEL: @foo
+// NO-MATH-ERRNO-LABEL: @sincos_f32
+// NO-MATH-ERRNO: [[SINCOS:%.*]] = call { float, float } @llvm.sincos.f32(float {{.*}})
+// NO-MATH-ERRNO-NEXT: [[SIN:%.*]] = extractvalue { float, float } [[SINCOS]], 0
+// NO-MATH-ERRNO-NEXT: [[COS:%.*]] = extractvalue { float, float } [[SINCOS]], 1
+// NO-MATH-ERRNO-NEXT: store float [[SIN]], ptr {{.*}}, align 4, !alias.scope [[SINCOS_ALIAS_SCOPE:![0-9]+]]
+// NO-MATH-ERRNO-NEXT: store float [[COS]], ptr {{.*}}, align 4, !noalias [[SINCOS_ALIAS_SCOPE]]
+//
+// MATH-ERRNO-LABEL: @sincos_f32
+// MATH-ERRNO: call void @sincosf(
+//
+void sincos_f32(float x, float* fp0, float* fp1) {
+ sincosf(x, fp0, fp1);
+}
+
+// NO-MATH-ERRNO-LABEL: @sincos_f64
// NO-MATH-ERRNO: [[SINCOS:%.*]] = call { double, double } @llvm.sincos.f64(double {{.*}})
// NO-MATH-ERRNO-NEXT: [[SIN:%.*]] = extractvalue { double, double } [[SINCOS]], 0
// NO-MATH-ERRNO-NEXT: [[COS:%.*]] = extractvalue { double, double } [[SINCOS]], 1
// NO-MATH-ERRNO-NEXT: store double [[SIN]], ptr {{.*}}, align 8, !alias.scope [[SINCOS_ALIAS_SCOPE:![0-9]+]]
// NO-MATH-ERRNO-NEXT: store double [[COS]], ptr {{.*}}, align 8, !noalias [[SINCOS_ALIAS_SCOPE]]
//
-// MATH-ERRNO-LABEL: @foo
+// MATH-ERRNO-LABEL: @sincos_f64
// MATH-ERRNO: call void @sincos(
//
-void foo(double x, double* dp0, double* dp1) {
+void sincos_f64(double x, double* dp0, double* dp1) {
sincos(x, dp0, dp1);
}
-// NO-MATH-ERRNO-LABEL: @bar
-// NO-MATH-ERRNO: [[SINCOS:%.*]] = call { float, float } @llvm.sincos.f32(float {{.*}})
-// NO-MATH-ERRNO-NEXT: [[SIN:%.*]] = extractvalue { float, float } [[SINCOS]], 0
-// NO-MATH-ERRNO-NEXT: [[COS:%.*]] = extractvalue { float, float } [[SINCOS]], 1
-// NO-MATH-ERRNO-NEXT: store float [[SIN]], ptr {{.*}}, align 4, !alias.scope [[SINCOS_ALIAS_SCOPE:![0-9]+]]
-// NO-MATH-ERRNO-NEXT: store float [[COS]], ptr {{.*}}, align 4, !noalias [[SINCOS_ALIAS_SCOPE]]
+// NO-MATH-ERRNO-LABEL: @sincos_f128
+// NO-MATH-ERRNO: [[SINCOS:%.*]] = call { fp128, fp128 } @llvm.sincos.f128(fp128 {{.*}})
+// NO-MATH-ERRNO-NEXT: [[SIN:%.*]] = extractvalue { fp128, fp128 } [[SINCOS]], 0
+// NO-MATH-ERRNO-NEXT: [[COS:%.*]] = extractvalue { fp128, fp128 } [[SINCOS]], 1
+// NO-MATH-ERRNO-NEXT: store fp128 [[SIN]], ptr {{.*}}, align 16, !alias.scope [[SINCOS_ALIAS_SCOPE:![0-9]+]]
+// NO-MATH-ERRNO-NEXT: store fp128 [[COS]], ptr {{.*}}, align 16, !noalias [[SINCOS_ALIAS_SCOPE]]
//
-// MATH-ERRNO-LABEL: @bar
-// MATH-ERRNO: call void @sincosf(
+// MATH-ERRNO-LABEL: @sincos_f128
+// MATH-ERRNO: call void @sincosl(
//
-void bar(float x, float* fp0, float* fp1) {
- sincosf(x, fp0, fp1);
+void sincos_f128(long double x, long double* ldp0, long double* ldp1) {
+ sincosl(x, ldp0, ldp1);
}
diff --git a/clang/test/CodeGen/X86/math-builtins.c b/clang/test/CodeGen/X86/math-builtins.c
index 292e87c33c240b..db0297d710085f 100644
--- a/clang/test/CodeGen/X86/math-builtins.c
+++ b/clang/test/CodeGen/X86/math-builtins.c
@@ -38,31 +38,6 @@ 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: [[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
-// NO__ERRNO-NEXT: store double [[SINCOS_F64_0]], ptr %{{.+}}, align 8
-// NO__ERRNO-NEXT: store double [[SINCOS_F64_1]], ptr %{{.+}}, align 8
-
-// NO__ERRNO: [[SINCOS_F32:%.+]] = call { float, float } @llvm.sincos.f32(float %{{.+}})
-// NO__ERRNO-NEXT: [[SINCOS_F32_0:%.+]] = extractvalue { float, float } [[SINCOS_F32]], 0
-// NO__ERRNO-NEXT: [[SINCOS_F32_1:%.+]] = extractvalue { float, float } [[SINCOS_F32]], 1
-// NO__ERRNO-NEXT: store float [[SINCOS_F32_0]], ptr %{{.+}}, align 4
-// NO__ERRNO-NEXT: store float [[SINCOS_F32_1]], ptr %{{.+}}, align 4
-
-// NO__ERRNO: [[SINCOS_F80:%.+]] = call { x86_fp80, x86_fp80 } @llvm.sincos.f80(x86_fp80 %{{.+}})
-// NO__ERRNO-NEXT: [[SINCOS_F80_0:%.+]] = extractvalue { x86_fp80, x86_fp80 } [[SINCOS_F80]], 0
-// NO__ERRNO-NEXT: [[SINCOS_F80_1:%.+]] = extractvalue { x86_fp80, x86_fp80 } [[SINCOS_F80]], 1
-// NO__ERRNO-NEXT: store x86_fp80 [[SINCOS_F80_0]], ptr %{{.+}}, align 16
-// NO__ERRNO-NEXT: store x86_fp80 [[SINCOS_F80_1]], ptr %{{.+}}, align 16
-
-// NO__ERRNO: [[SINCOS_F128:%.+]] = call { fp128, fp128 } @llvm.sincos.f128(fp128 %{{.+}})
-// NO__ERRNO-NEXT: [[SINCOS_F128_0:%.+]] = extractvalue { fp128, fp128 } [[SINCOS_F128]], 0
-// NO__ERRNO-NEXT: [[SINCOS_F128_1:%.+]] = extractvalue { fp128, fp128 } [[SINCOS_F128]], 1
-// NO__ERRNO-NEXT: store fp128 [[SINCOS_F128_0]], ptr %{{.+}}, align 16
-// NO__ERRNO-NEXT: store fp128 [[SINCOS_F128_1]], ptr %{{.+}}, align 16
-
-
// HAS_ERRNO: declare double @fmod(double noundef, double noundef) [[NOT_READNONE:#[0-9]+]]
// HAS_ERRNO: declare float @fmodf(float noundef, float noundef) [[NOT_READNONE]]
// HAS_ERRNO: declare x86_fp80 @fmodl(x86_fp80 noundef, x86_fp80 noundef) [[NOT_READNONE]]
@@ -691,10 +666,10 @@ __builtin_sinh(f); __builtin_sinhf(f); __builtin_sinhl(f); __builtin_
// HAS_ERRNO: declare fp128 @sinhf128(fp128 noundef) [[NOT_READNONE]]
__builtin_sincos(f,d,d); __builtin_sincosf(f,fp,fp); __builtin_sincosl(f,l,l); __builtin_sincosf128(f,l,l);
-// NO__ERRNO: declare { double, double } @llvm.sincos.f64(double) [[READNONE_INTRINSIC]]
-// NO__ERRNO: declare { float, float } @llvm.sincos.f32(float) [[READNONE_INTRINSIC]]
-// NO__ERRNO: declare { x86_fp80, x86_fp80 } @llvm.sincos.f80(x86_fp80) [[READNONE_INTRINSIC]]
-// NO__ERRNO: declare { fp128, fp128 } @llvm.sincos.f128(fp128) [[READNONE_INTRINSIC]]
+// NO__ERRNO: declare void @sincos(double noundef, ptr noundef, ptr noundef) [[NOT_READNONE]]
+// NO__ERRNO: declare void @sincosf(float noundef, ptr noundef, ptr noundef) [[NOT_READNONE]]
+// NO__ERRNO: declare void @sincosl(x86_fp80 noundef, ptr noundef, ptr noundef) [[NOT_READNONE]]
+// NO__ERRNO: declare void @sincosf128(fp128 noundef, ptr noundef, ptr noundef) [[NOT_READNONE]]
// HAS_ERRNO: declare void @sincos(double noundef, ptr noundef, ptr noundef) [[NOT_READNONE]]
// HAS_ERRNO: declare void @sincosf(float noundef, ptr noundef, ptr noundef) [[NOT_READNONE]]
// HAS_ERRNO: declare void @sincosl(x86_fp80 noundef, ptr noundef, ptr noundef) [[NOT_READNONE]]
>From c317a26089039b2f6f86b66e1cd845017a892c76 Mon Sep 17 00:00:00 2001
From: Benjamin Maxwell <benjamin.maxwell at arm.com>
Date: Mon, 16 Dec 2024 16:03:31 +0000
Subject: [PATCH 4/4] Fixups
---
clang/lib/CodeGen/CGBuiltin.cpp | 7 ++++++-
clang/test/CodeGen/AArch64/sincos.c | 8 ++++----
2 files changed, 10 insertions(+), 5 deletions(-)
diff --git a/clang/lib/CodeGen/CGBuiltin.cpp b/clang/lib/CodeGen/CGBuiltin.cpp
index 1294e02b5edc94..b58bfbf34082e1 100644
--- a/clang/lib/CodeGen/CGBuiltin.cpp
+++ b/clang/lib/CodeGen/CGBuiltin.cpp
@@ -3270,7 +3270,12 @@ RValue CodeGenFunction::EmitBuiltinExpr(const GlobalDecl GD, unsigned BuiltinID,
case Builtin::BI__builtin_sincos:
case Builtin::BI__builtin_sincosf:
case Builtin::BI__builtin_sincosl:
- if (!getTarget().getTriple().isAArch64())
+ // Only use the llvm.sincos.* builtin on AArch64 with optimizations.
+ // Currently, getting codegen that is no worse than the direct call
+ // requires using AA during codegen. This is not done at optlevel=none,
+ // and not all targets support this (AArch64 is one of the few known to).
+ if (!getTarget().getTriple().isAArch64() ||
+ CGM.getCodeGenOpts().OptimizationLevel == 0)
break;
emitSincosBuiltin(*this, E, Intrinsic::sincos);
return RValue::get(nullptr);
diff --git a/clang/test/CodeGen/AArch64/sincos.c b/clang/test/CodeGen/AArch64/sincos.c
index 0bfdb8e804632a..9000d641528fbb 100644
--- a/clang/test/CodeGen/AArch64/sincos.c
+++ b/clang/test/CodeGen/AArch64/sincos.c
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 -triple=aarch64-gnu-linux -emit-llvm %s -o - | FileCheck --check-prefix=NO-MATH-ERRNO %s
+// RUN: %clang_cc1 -triple=aarch64-gnu-linux -emit-llvm -O1 %s -o - | FileCheck --check-prefix=NO-MATH-ERRNO %s
// RUN: %clang_cc1 -triple=aarch64-gnu-linux -emit-llvm -fmath-errno %s -o - | FileCheck --check-prefix=MATH-ERRNO %s
void sincos(double, double*, double*);
@@ -6,7 +6,7 @@ void sincosf(float, float*, float*);
void sincosl(long double, long double*, long double*);
// NO-MATH-ERRNO-LABEL: @sincos_f32
-// NO-MATH-ERRNO: [[SINCOS:%.*]] = call { float, float } @llvm.sincos.f32(float {{.*}})
+// NO-MATH-ERRNO: [[SINCOS:%.*]] = tail call { float, float } @llvm.sincos.f32(float {{.*}})
// NO-MATH-ERRNO-NEXT: [[SIN:%.*]] = extractvalue { float, float } [[SINCOS]], 0
// NO-MATH-ERRNO-NEXT: [[COS:%.*]] = extractvalue { float, float } [[SINCOS]], 1
// NO-MATH-ERRNO-NEXT: store float [[SIN]], ptr {{.*}}, align 4, !alias.scope [[SINCOS_ALIAS_SCOPE:![0-9]+]]
@@ -20,7 +20,7 @@ void sincos_f32(float x, float* fp0, float* fp1) {
}
// NO-MATH-ERRNO-LABEL: @sincos_f64
-// NO-MATH-ERRNO: [[SINCOS:%.*]] = call { double, double } @llvm.sincos.f64(double {{.*}})
+// NO-MATH-ERRNO: [[SINCOS:%.*]] = tail call { double, double } @llvm.sincos.f64(double {{.*}})
// NO-MATH-ERRNO-NEXT: [[SIN:%.*]] = extractvalue { double, double } [[SINCOS]], 0
// NO-MATH-ERRNO-NEXT: [[COS:%.*]] = extractvalue { double, double } [[SINCOS]], 1
// NO-MATH-ERRNO-NEXT: store double [[SIN]], ptr {{.*}}, align 8, !alias.scope [[SINCOS_ALIAS_SCOPE:![0-9]+]]
@@ -34,7 +34,7 @@ void sincos_f64(double x, double* dp0, double* dp1) {
}
// NO-MATH-ERRNO-LABEL: @sincos_f128
-// NO-MATH-ERRNO: [[SINCOS:%.*]] = call { fp128, fp128 } @llvm.sincos.f128(fp128 {{.*}})
+// NO-MATH-ERRNO: [[SINCOS:%.*]] = tail call { fp128, fp128 } @llvm.sincos.f128(fp128 {{.*}})
// NO-MATH-ERRNO-NEXT: [[SIN:%.*]] = extractvalue { fp128, fp128 } [[SINCOS]], 0
// NO-MATH-ERRNO-NEXT: [[COS:%.*]] = extractvalue { fp128, fp128 } [[SINCOS]], 1
// NO-MATH-ERRNO-NEXT: store fp128 [[SIN]], ptr {{.*}}, align 16, !alias.scope [[SINCOS_ALIAS_SCOPE:![0-9]+]]
More information about the cfe-commits
mailing list