https://github.com/kito-cheng updated 
https://github.com/llvm/llvm-project/pull/184760

>From 2b6c8bb9bd72ae0c530d37d051a6d285a7d0680d Mon Sep 17 00:00:00 2001
From: Kito Cheng <[email protected]>
Date: Fri, 27 Feb 2026 09:49:01 +0800
Subject: [PATCH 1/8] [SimplifyLibCalls] Combine sin/cos libcall pairs into
 llvm.sincos

When both sin(x) and cos(x) are called with the same argument in a
function, replace them with a single llvm.sincos intrinsic call.
This is analogous to the existing sinpi/cospi -> sincospi_stret
optimization. The two optimizations now share a unified code path
via optimizeSinCos() with an IsPi flag.

Also remove the completed sincos TODO from Target/README.txt.
---
 .../llvm/Transforms/Utils/SimplifyLibCalls.h  |   5 +-
 llvm/lib/Target/README.txt                    |  15 --
 .../lib/Transforms/Utils/SimplifyLibCalls.cpp |  93 +++++++++---
 llvm/test/Transforms/InstCombine/sincos.ll    | 136 ++++++++++++++++++
 4 files changed, 210 insertions(+), 39 deletions(-)
 create mode 100644 llvm/test/Transforms/InstCombine/sincos.ll

diff --git a/llvm/include/llvm/Transforms/Utils/SimplifyLibCalls.h 
b/llvm/include/llvm/Transforms/Utils/SimplifyLibCalls.h
index df98131a54ca9..14da88a66fd61 100644
--- a/llvm/include/llvm/Transforms/Utils/SimplifyLibCalls.h
+++ b/llvm/include/llvm/Transforms/Utils/SimplifyLibCalls.h
@@ -210,6 +210,8 @@ class LibCallSimplifier {
   Value *optimizeFMod(CallInst *CI, IRBuilderBase &B);
   Value *mergeSqrtToExp(CallInst *CI, IRBuilderBase &B);
   Value *optimizeSinCosPi(CallInst *CI, bool IsSin, IRBuilderBase &B);
+  Value *optimizeSinCos(CallInst *CI, bool IsSin, IRBuilderBase &B,
+                        bool IsPi = false);
   Value *optimizeTrigInversionPairs(CallInst *CI, IRBuilderBase &B);
   Value *optimizeSymmetric(CallInst *CI, LibFunc Func, IRBuilderBase &B);
   Value *optimizeRemquo(CallInst *CI, IRBuilderBase &B);
@@ -247,7 +249,8 @@ class LibCallSimplifier {
   void classifyArgUse(Value *Val, Function *F, bool IsFloat,
                       SmallVectorImpl<CallInst *> &SinCalls,
                       SmallVectorImpl<CallInst *> &CosCalls,
-                      SmallVectorImpl<CallInst *> &SinCosCalls);
+                      SmallVectorImpl<CallInst *> &SinCosCalls,
+                      bool IsPi);
   Value *optimizePrintFString(CallInst *CI, IRBuilderBase &B);
   Value *optimizeSPrintFString(CallInst *CI, IRBuilderBase &B);
   Value *optimizeSnPrintFString(CallInst *CI, IRBuilderBase &B);
diff --git a/llvm/lib/Target/README.txt b/llvm/lib/Target/README.txt
index adf75c3368677..4d98a5fac3984 100644
--- a/llvm/lib/Target/README.txt
+++ b/llvm/lib/Target/README.txt
@@ -132,21 +132,6 @@ emit:
 
 //===---------------------------------------------------------------------===//
 
-Combine: a = sin(x), b = cos(x) into a,b = sincos(x).
-
-Expand these to calls of sin/cos and stores:
-      double sincos(double x, double *sin, double *cos);
-      float sincosf(float x, float *sin, float *cos);
-      long double sincosl(long double x, long double *sin, long double *cos);
-
-Doing so could allow SROA of the destination pointers.  See also:
-http://gcc.gnu.org/bugzilla/show_bug.cgi?id=17687
-
-This is now easily doable with MRVs.  We could even make an intrinsic for this
-if anyone cared enough about sincos.
-
-//===---------------------------------------------------------------------===//
-
 quantum_sigma_x in 462.libquantum contains the following loop:
 
       for(i=0; i<reg->size; i++)
diff --git a/llvm/lib/Transforms/Utils/SimplifyLibCalls.cpp 
b/llvm/lib/Transforms/Utils/SimplifyLibCalls.cpp
index 3b68afe8700dd..4ce540c4376e2 100644
--- a/llvm/lib/Transforms/Utils/SimplifyLibCalls.cpp
+++ b/llvm/lib/Transforms/Utils/SimplifyLibCalls.cpp
@@ -2941,9 +2941,10 @@ static bool isTrigLibCall(CallInst *CI) {
   return CI->doesNotThrow() && CI->doesNotAccessMemory();
 }
 
-static bool insertSinCosCall(IRBuilderBase &B, Function *OrigCallee, Value 
*Arg,
-                             bool UseFloat, Value *&Sin, Value *&Cos,
-                             Value *&SinCos, const TargetLibraryInfo *TLI) {
+static bool insertSinCosPiCall(IRBuilderBase &B, Function *OrigCallee,
+                               Value *Arg, bool UseFloat, Value *&Sin,
+                               Value *&Cos, Value *&SinCos,
+                               const TargetLibraryInfo *TLI) {
   Module *M = OrigCallee->getParent();
   Type *ArgTy = Arg->getType();
   Type *ResTy;
@@ -3051,7 +3052,13 @@ Value *LibCallSimplifier::optimizeSymmetric(CallInst 
*CI, LibFunc Func,
   }
 }
 
-Value *LibCallSimplifier::optimizeSinCosPi(CallInst *CI, bool IsSin, 
IRBuilderBase &B) {
+Value *LibCallSimplifier::optimizeSinCosPi(CallInst *CI, bool IsSin,
+                                            IRBuilderBase &B) {
+  return optimizeSinCos(CI, IsSin, B, /*IsPi=*/true);
+}
+
+Value *LibCallSimplifier::optimizeSinCos(CallInst *CI, bool IsSin,
+                                         IRBuilderBase &B, bool IsPi) {
   // Make sure the prototype is as expected, otherwise the rest of the
   // function is probably invalid and likely to abort.
   if (!isTrigLibCall(CI))
@@ -3067,21 +3074,41 @@ Value *LibCallSimplifier::optimizeSinCosPi(CallInst 
*CI, bool IsSin, IRBuilderBa
 
   bool IsFloat = Arg->getType()->isFloatTy();
 
-  // Look for all compatible sinpi, cospi and sincospi calls with the same
+  // Look for all compatible sin/cos (or sinpi/cospi) calls with the same
   // argument. If there are enough (in some sense) we can make the
   // substitution.
   Function *F = CI->getFunction();
   for (User *U : Arg->users())
-    classifyArgUse(U, F, IsFloat, SinCalls, CosCalls, SinCosCalls);
+    classifyArgUse(U, F, IsFloat, SinCalls, CosCalls, SinCosCalls, IsPi);
 
-  // It's only worthwhile if both sinpi and cospi are actually used.
+  // It's only worthwhile if both sin and cos are actually used.
   if (SinCalls.empty() || CosCalls.empty())
     return nullptr;
 
   Value *Sin, *Cos, *SinCos;
-  if (!insertSinCosCall(B, CI->getCalledFunction(), Arg, IsFloat, Sin, Cos,
-                        SinCos, TLI))
-    return nullptr;
+  if (IsPi) {
+    // For sinpi/cospi, use platform-specific __sincospi_stret libcall.
+    if (!insertSinCosPiCall(B, CI->getCalledFunction(), Arg, IsFloat, Sin, Cos,
+                            SinCos, TLI))
+      return nullptr;
+  } else {
+    // For sin/cos, use the llvm.sincos intrinsic.
+    IRBuilderBase::InsertPointGuard Guard(B);
+    if (Instruction *ArgInst = dyn_cast<Instruction>(Arg)) {
+      B.SetInsertPoint(ArgInst->getParent(), ++ArgInst->getIterator());
+    } else {
+      BasicBlock &EntryBB = B.GetInsertBlock()->getParent()->getEntryBlock();
+      B.SetInsertPoint(&EntryBB, EntryBB.begin());
+    }
+
+    Module *M = CI->getModule();
+    Type *ArgTy = Arg->getType();
+    Function *SinCosFunc =
+        Intrinsic::getOrInsertDeclaration(M, Intrinsic::sincos, ArgTy);
+    SinCos = B.CreateCall(SinCosFunc, Arg, "sincos");
+    Sin = B.CreateExtractValue(SinCos, 0, "sin");
+    Cos = B.CreateExtractValue(SinCos, 1, "cos");
+  }
 
   auto replaceTrigInsts = [this](SmallVectorImpl<CallInst *> &Calls,
                                  Value *Res) {
@@ -3100,7 +3127,7 @@ void LibCallSimplifier::classifyArgUse(
     Value *Val, Function *F, bool IsFloat,
     SmallVectorImpl<CallInst *> &SinCalls,
     SmallVectorImpl<CallInst *> &CosCalls,
-    SmallVectorImpl<CallInst *> &SinCosCalls) {
+    SmallVectorImpl<CallInst *> &SinCosCalls, bool IsPi) {
   auto *CI = dyn_cast<CallInst>(Val);
   if (!CI || CI->use_empty())
     return;
@@ -3117,20 +3144,29 @@ void LibCallSimplifier::classifyArgUse(
       !isTrigLibCall(CI))
     return;
 
-  if (IsFloat) {
-    if (Func == LibFunc_sinpif)
-      SinCalls.push_back(CI);
-    else if (Func == LibFunc_cospif)
-      CosCalls.push_back(CI);
-    else if (Func == LibFunc_sincospif_stret)
-      SinCosCalls.push_back(CI);
+  if (IsPi) {
+    if (IsFloat) {
+      if (Func == LibFunc_sinpif)
+        SinCalls.push_back(CI);
+      else if (Func == LibFunc_cospif)
+        CosCalls.push_back(CI);
+      else if (Func == LibFunc_sincospif_stret)
+        SinCosCalls.push_back(CI);
+    } else {
+      if (Func == LibFunc_sinpi)
+        SinCalls.push_back(CI);
+      else if (Func == LibFunc_cospi)
+        CosCalls.push_back(CI);
+      else if (Func == LibFunc_sincospi_stret)
+        SinCosCalls.push_back(CI);
+    }
   } else {
-    if (Func == LibFunc_sinpi)
+    if (Func == LibFunc_sin || Func == LibFunc_sinf ||
+        Func == LibFunc_sinl)
       SinCalls.push_back(CI);
-    else if (Func == LibFunc_cospi)
+    else if (Func == LibFunc_cos || Func == LibFunc_cosf ||
+             Func == LibFunc_cosl)
       CosCalls.push_back(CI);
-    else if (Func == LibFunc_sincospi_stret)
-      SinCosCalls.push_back(CI);
   }
 }
 
@@ -4029,6 +4065,12 @@ Value 
*LibCallSimplifier::optimizeFloatingPointLibCall(CallInst *CI,
   case LibFunc_cospif:
   case LibFunc_cospi:
     return optimizeSinCosPi(CI, /*IsSin*/false, Builder);
+  case LibFunc_sinf:
+  case LibFunc_sinl:
+    return optimizeSinCos(CI, /*IsSin*/true, Builder);
+  case LibFunc_cosf:
+  case LibFunc_cosl:
+    return optimizeSinCos(CI, /*IsSin*/false, Builder);
   case LibFunc_powf:
   case LibFunc_pow:
   case LibFunc_powl:
@@ -4103,8 +4145,13 @@ Value 
*LibCallSimplifier::optimizeFloatingPointLibCall(CallInst *CI,
   case LibFunc_exp:
   case LibFunc_exp10:
   case LibFunc_expm1:
-  case LibFunc_cos:
   case LibFunc_sin:
+  case LibFunc_cos:
+    if (Value *V = optimizeSinCos(CI, Func == LibFunc_sin, Builder))
+      return V;
+    if (UnsafeFPShrink && hasFloatVersion(M, 
CI->getCalledFunction()->getName()))
+      return optimizeUnaryDoubleFP(CI, Builder, TLI, true);
+    return nullptr;
   case LibFunc_tanh:
     if (UnsafeFPShrink && hasFloatVersion(M, 
CI->getCalledFunction()->getName()))
       return optimizeUnaryDoubleFP(CI, Builder, TLI, true);
diff --git a/llvm/test/Transforms/InstCombine/sincos.ll 
b/llvm/test/Transforms/InstCombine/sincos.ll
new file mode 100644
index 0000000000000..00fc060b3287d
--- /dev/null
+++ b/llvm/test/Transforms/InstCombine/sincos.ll
@@ -0,0 +1,136 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
+; RUN: opt -passes=instcombine -S < %s -mtriple=x86_64-apple-macosx10.9 | 
FileCheck %s --check-prefixes=CHECK,CHECK-DOUBLE-ALIGN8
+; RUN: opt -passes=instcombine -S < %s -mtriple=arm-apple-ios7.0 | FileCheck 
%s --check-prefixes=CHECK,CHECK-DOUBLE-ALIGN4
+; RUN: opt -passes=instcombine -S < %s -mtriple=x86_64-none-linux-gnu | 
FileCheck %s --check-prefixes=CHECK,CHECK-DOUBLE-ALIGN8-LINUX
+; REQUIRES: arm-registered-target, x86-registered-target
+
+attributes #0 = { readnone nounwind }
+
+declare float @sinf(float) #0
+declare float @cosf(float) #0
+declare double @sin(double) #0
+declare double @cos(double) #0
+
+@var32 = global float 0.0
+@var64 = global double 0.0
+
+; Basic sin+cos combination for float
+define float @sincos_f32() {
+; CHECK-LABEL: @sincos_f32(
+; CHECK-NEXT:    [[VAL:%.*]] = load float, ptr @var32, align 4
+; CHECK-NEXT:    [[SINCOS:%.*]] = call { float, float } @llvm.sincos.f32(float 
[[VAL]])
+; CHECK-NEXT:    [[SIN:%.*]] = extractvalue { float, float } [[SINCOS]], 0
+; CHECK-NEXT:    [[COS:%.*]] = extractvalue { float, float } [[SINCOS]], 1
+; CHECK-NEXT:    [[C:%.*]] = call float @cosf(float [[VAL]]) #[[ATTR0:[0-9]+]]
+; CHECK-NEXT:    [[RES:%.*]] = fadd float [[SIN]], [[COS]]
+; CHECK-NEXT:    ret float [[RES]]
+;
+  %val = load float, ptr @var32
+  %s = call float @sinf(float %val) #0
+  %c = call float @cosf(float %val) #0
+  %res = fadd float %s, %c
+  ret float %res
+}
+
+; Basic sin+cos combination for double
+define double @sincos_f64() {
+; CHECK-DOUBLE-ALIGN8-LABEL: @sincos_f64(
+; CHECK-DOUBLE-ALIGN8-NEXT:    [[VAL:%.*]] = load double, ptr @var64, align 8
+; CHECK-DOUBLE-ALIGN8-NEXT:    [[SINCOS:%.*]] = call { double, double } 
@llvm.sincos.f64(double [[VAL]])
+; CHECK-DOUBLE-ALIGN8-NEXT:    [[SIN:%.*]] = extractvalue { double, double } 
[[SINCOS]], 0
+; CHECK-DOUBLE-ALIGN8-NEXT:    [[COS:%.*]] = extractvalue { double, double } 
[[SINCOS]], 1
+; CHECK-DOUBLE-ALIGN8-NEXT:    [[C:%.*]] = call double @cos(double [[VAL]]) 
#[[ATTR0]]
+; CHECK-DOUBLE-ALIGN8-NEXT:    [[RES:%.*]] = fadd double [[SIN]], [[COS]]
+; CHECK-DOUBLE-ALIGN8-NEXT:    ret double [[RES]]
+;
+; CHECK-DOUBLE-ALIGN4-LABEL: @sincos_f64(
+; CHECK-DOUBLE-ALIGN4-NEXT:    [[VAL:%.*]] = load double, ptr @var64, align 4
+; CHECK-DOUBLE-ALIGN4-NEXT:    [[SINCOS:%.*]] = call { double, double } 
@llvm.sincos.f64(double [[VAL]])
+; CHECK-DOUBLE-ALIGN4-NEXT:    [[SIN:%.*]] = extractvalue { double, double } 
[[SINCOS]], 0
+; CHECK-DOUBLE-ALIGN4-NEXT:    [[COS:%.*]] = extractvalue { double, double } 
[[SINCOS]], 1
+; CHECK-DOUBLE-ALIGN4-NEXT:    [[C:%.*]] = call double @cos(double [[VAL]]) 
#[[ATTR0]]
+; CHECK-DOUBLE-ALIGN4-NEXT:    [[RES:%.*]] = fadd double [[SIN]], [[COS]]
+; CHECK-DOUBLE-ALIGN4-NEXT:    ret double [[RES]]
+;
+; CHECK-DOUBLE-ALIGN8-LINUX-LABEL: @sincos_f64(
+; CHECK-DOUBLE-ALIGN8-LINUX-NEXT:    [[VAL:%.*]] = load double, ptr @var64, 
align 8
+; CHECK-DOUBLE-ALIGN8-LINUX-NEXT:    [[SINCOS:%.*]] = call { double, double } 
@llvm.sincos.f64(double [[VAL]])
+; CHECK-DOUBLE-ALIGN8-LINUX-NEXT:    [[SIN:%.*]] = extractvalue { double, 
double } [[SINCOS]], 0
+; CHECK-DOUBLE-ALIGN8-LINUX-NEXT:    [[COS:%.*]] = extractvalue { double, 
double } [[SINCOS]], 1
+; CHECK-DOUBLE-ALIGN8-LINUX-NEXT:    [[C:%.*]] = call double @cos(double 
[[VAL]]) #[[ATTR0]]
+; CHECK-DOUBLE-ALIGN8-LINUX-NEXT:    [[RES:%.*]] = fadd double [[SIN]], [[COS]]
+; CHECK-DOUBLE-ALIGN8-LINUX-NEXT:    ret double [[RES]]
+;
+  %val = load double, ptr @var64
+  %s = call double @sin(double %val) #0
+  %c = call double @cos(double %val) #0
+  %res = fadd double %s, %c
+  ret double %res
+}
+
+; Only sin, no cos - should NOT combine
+define float @sin_only_f32(float %x) {
+; CHECK-LABEL: @sin_only_f32(
+; CHECK-NEXT:    [[S:%.*]] = call float @sinf(float [[X:%.*]]) #[[ATTR0]]
+; CHECK-NEXT:    ret float [[S]]
+;
+  %s = call float @sinf(float %x) #0
+  ret float %s
+}
+
+; Only cos, no sin - should NOT combine
+define float @cos_only_f32(float %x) {
+; CHECK-LABEL: @cos_only_f32(
+; CHECK-NEXT:    [[C:%.*]] = call float @cosf(float [[X:%.*]]) #[[ATTR0]]
+; CHECK-NEXT:    ret float [[C]]
+;
+  %c = call float @cosf(float %x) #0
+  ret float %c
+}
+
+; Different arguments - should NOT combine
+define float @sincos_different_args(float %x, float %y) {
+; CHECK-LABEL: @sincos_different_args(
+; CHECK-NEXT:    [[S:%.*]] = call float @sinf(float [[X:%.*]]) #[[ATTR0]]
+; CHECK-NEXT:    [[C:%.*]] = call float @cosf(float [[Y:%.*]]) #[[ATTR0]]
+; CHECK-NEXT:    [[RES:%.*]] = fadd float [[S]], [[C]]
+; CHECK-NEXT:    ret float [[RES]]
+;
+  %s = call float @sinf(float %x) #0
+  %c = call float @cosf(float %y) #0
+  %res = fadd float %s, %c
+  ret float %res
+}
+
+; Constant argument - should NOT combine
+define float @sincos_const_arg() {
+; CHECK-LABEL: @sincos_const_arg(
+; CHECK-NEXT:    [[S:%.*]] = call float @sinf(float 1.000000e+00) #[[ATTR0]]
+; CHECK-NEXT:    [[C:%.*]] = call float @cosf(float 1.000000e+00) #[[ATTR0]]
+; CHECK-NEXT:    ret float 0x3FF61BBE40000000
+;
+  %s = call float @sinf(float 1.0) #0
+  %c = call float @cosf(float 1.0) #0
+  %res = fadd float %s, %c
+  ret float %res
+}
+
+; Multiple uses of sin and cos results
+define float @sincos_multi_use(float %x) {
+; CHECK-LABEL: @sincos_multi_use(
+; CHECK-NEXT:    [[SINCOS:%.*]] = call { float, float } @llvm.sincos.f32(float 
[[X:%.*]])
+; CHECK-NEXT:    [[SIN:%.*]] = extractvalue { float, float } [[SINCOS]], 0
+; CHECK-NEXT:    [[COS:%.*]] = extractvalue { float, float } [[SINCOS]], 1
+; CHECK-NEXT:    [[C:%.*]] = call float @cosf(float [[X]]) #[[ATTR0]]
+; CHECK-NEXT:    [[ADD:%.*]] = fadd float [[SIN]], [[COS]]
+; CHECK-NEXT:    [[MUL:%.*]] = fmul float [[SIN]], [[COS]]
+; CHECK-NEXT:    [[RES:%.*]] = fadd float [[ADD]], [[MUL]]
+; CHECK-NEXT:    ret float [[RES]]
+;
+  %s = call float @sinf(float %x) #0
+  %c = call float @cosf(float %x) #0
+  %add = fadd float %s, %c
+  %mul = fmul float %s, %c
+  %res = fadd float %add, %mul
+  ret float %res
+}

>From 6cbacc50a29f2fe4d2f66bd75ca455dda04dfdcd Mon Sep 17 00:00:00 2001
From: Kito Cheng <[email protected]>
Date: Thu, 5 Mar 2026 17:49:50 +0800
Subject: [PATCH 2/8] !fixup: Fix clang-format issues in SimplifyLibCalls

---
 .../llvm/Transforms/Utils/SimplifyLibCalls.h  |  3 +--
 .../lib/Transforms/Utils/SimplifyLibCalls.cpp | 22 +++++++++----------
 2 files changed, 12 insertions(+), 13 deletions(-)

diff --git a/llvm/include/llvm/Transforms/Utils/SimplifyLibCalls.h 
b/llvm/include/llvm/Transforms/Utils/SimplifyLibCalls.h
index 14da88a66fd61..e174a1c484eec 100644
--- a/llvm/include/llvm/Transforms/Utils/SimplifyLibCalls.h
+++ b/llvm/include/llvm/Transforms/Utils/SimplifyLibCalls.h
@@ -249,8 +249,7 @@ class LibCallSimplifier {
   void classifyArgUse(Value *Val, Function *F, bool IsFloat,
                       SmallVectorImpl<CallInst *> &SinCalls,
                       SmallVectorImpl<CallInst *> &CosCalls,
-                      SmallVectorImpl<CallInst *> &SinCosCalls,
-                      bool IsPi);
+                      SmallVectorImpl<CallInst *> &SinCosCalls, bool IsPi);
   Value *optimizePrintFString(CallInst *CI, IRBuilderBase &B);
   Value *optimizeSPrintFString(CallInst *CI, IRBuilderBase &B);
   Value *optimizeSnPrintFString(CallInst *CI, IRBuilderBase &B);
diff --git a/llvm/lib/Transforms/Utils/SimplifyLibCalls.cpp 
b/llvm/lib/Transforms/Utils/SimplifyLibCalls.cpp
index 4ce540c4376e2..155a037c9495a 100644
--- a/llvm/lib/Transforms/Utils/SimplifyLibCalls.cpp
+++ b/llvm/lib/Transforms/Utils/SimplifyLibCalls.cpp
@@ -3053,7 +3053,7 @@ Value *LibCallSimplifier::optimizeSymmetric(CallInst *CI, 
LibFunc Func,
 }
 
 Value *LibCallSimplifier::optimizeSinCosPi(CallInst *CI, bool IsSin,
-                                            IRBuilderBase &B) {
+                                           IRBuilderBase &B) {
   return optimizeSinCos(CI, IsSin, B, /*IsPi=*/true);
 }
 
@@ -3123,11 +3123,11 @@ Value *LibCallSimplifier::optimizeSinCos(CallInst *CI, 
bool IsSin,
   return IsSin ? Sin : Cos;
 }
 
-void LibCallSimplifier::classifyArgUse(
-    Value *Val, Function *F, bool IsFloat,
-    SmallVectorImpl<CallInst *> &SinCalls,
-    SmallVectorImpl<CallInst *> &CosCalls,
-    SmallVectorImpl<CallInst *> &SinCosCalls, bool IsPi) {
+void LibCallSimplifier::classifyArgUse(Value *Val, Function *F, bool IsFloat,
+                                       SmallVectorImpl<CallInst *> &SinCalls,
+                                       SmallVectorImpl<CallInst *> &CosCalls,
+                                       SmallVectorImpl<CallInst *> 
&SinCosCalls,
+                                       bool IsPi) {
   auto *CI = dyn_cast<CallInst>(Val);
   if (!CI || CI->use_empty())
     return;
@@ -3161,8 +3161,7 @@ void LibCallSimplifier::classifyArgUse(
         SinCosCalls.push_back(CI);
     }
   } else {
-    if (Func == LibFunc_sin || Func == LibFunc_sinf ||
-        Func == LibFunc_sinl)
+    if (Func == LibFunc_sin || Func == LibFunc_sinf || Func == LibFunc_sinl)
       SinCalls.push_back(CI);
     else if (Func == LibFunc_cos || Func == LibFunc_cosf ||
              Func == LibFunc_cosl)
@@ -4067,10 +4066,10 @@ Value 
*LibCallSimplifier::optimizeFloatingPointLibCall(CallInst *CI,
     return optimizeSinCosPi(CI, /*IsSin*/false, Builder);
   case LibFunc_sinf:
   case LibFunc_sinl:
-    return optimizeSinCos(CI, /*IsSin*/true, Builder);
+    return optimizeSinCos(CI, /*IsSin*/ true, Builder);
   case LibFunc_cosf:
   case LibFunc_cosl:
-    return optimizeSinCos(CI, /*IsSin*/false, Builder);
+    return optimizeSinCos(CI, /*IsSin*/ false, Builder);
   case LibFunc_powf:
   case LibFunc_pow:
   case LibFunc_powl:
@@ -4149,7 +4148,8 @@ Value 
*LibCallSimplifier::optimizeFloatingPointLibCall(CallInst *CI,
   case LibFunc_cos:
     if (Value *V = optimizeSinCos(CI, Func == LibFunc_sin, Builder))
       return V;
-    if (UnsafeFPShrink && hasFloatVersion(M, 
CI->getCalledFunction()->getName()))
+    if (UnsafeFPShrink &&
+        hasFloatVersion(M, CI->getCalledFunction()->getName()))
       return optimizeUnaryDoubleFP(CI, Builder, TLI, true);
     return nullptr;
   case LibFunc_tanh:

>From c998b245164c17e9845947656f448c0e1f1a7786 Mon Sep 17 00:00:00 2001
From: Kito Cheng <[email protected]>
Date: Fri, 6 Mar 2026 18:38:24 +0800
Subject: [PATCH 3/8] !fixup: Address review feedback on sincos.ll test

- Move attributes block to end of file, use memory(none)
- Add intrinsic-only and mixed libcall/intrinsic test cases
---
 llvm/test/Transforms/InstCombine/sincos.ll | 46 +++++++++++++++++++++-
 1 file changed, 44 insertions(+), 2 deletions(-)

diff --git a/llvm/test/Transforms/InstCombine/sincos.ll 
b/llvm/test/Transforms/InstCombine/sincos.ll
index 00fc060b3287d..8485f66b348f3 100644
--- a/llvm/test/Transforms/InstCombine/sincos.ll
+++ b/llvm/test/Transforms/InstCombine/sincos.ll
@@ -4,8 +4,6 @@
 ; RUN: opt -passes=instcombine -S < %s -mtriple=x86_64-none-linux-gnu | 
FileCheck %s --check-prefixes=CHECK,CHECK-DOUBLE-ALIGN8-LINUX
 ; REQUIRES: arm-registered-target, x86-registered-target
 
-attributes #0 = { readnone nounwind }
-
 declare float @sinf(float) #0
 declare float @cosf(float) #0
 declare double @sin(double) #0
@@ -134,3 +132,47 @@ define float @sincos_multi_use(float %x) {
   %res = fadd float %add, %mul
   ret float %res
 }
+
+; Intrinsic sin + intrinsic cos - should combine
+define float @sincos_intrinsic_f32(float %x) {
+; CHECK-LABEL: @sincos_intrinsic_f32(
+; CHECK-NEXT:    [[S:%.*]] = call float @llvm.sin.f32(float [[X:%.*]])
+; CHECK-NEXT:    [[C:%.*]] = call float @llvm.cos.f32(float [[X]])
+; CHECK-NEXT:    [[RES:%.*]] = fadd float [[S]], [[C]]
+; CHECK-NEXT:    ret float [[RES]]
+;
+  %s = call float @llvm.sin.f32(float %x)
+  %c = call float @llvm.cos.f32(float %x)
+  %res = fadd float %s, %c
+  ret float %res
+}
+
+; Mixed: libcall sin + intrinsic cos
+define float @sincos_mixed_libcall_sin_intrinsic_cos(float %x) {
+; CHECK-LABEL: @sincos_mixed_libcall_sin_intrinsic_cos(
+; CHECK-NEXT:    [[S:%.*]] = call float @sinf(float [[X:%.*]]) #[[ATTR0]]
+; CHECK-NEXT:    [[C:%.*]] = call float @llvm.cos.f32(float [[X]])
+; CHECK-NEXT:    [[RES:%.*]] = fadd float [[S]], [[C]]
+; CHECK-NEXT:    ret float [[RES]]
+;
+  %s = call float @sinf(float %x) #0
+  %c = call float @llvm.cos.f32(float %x)
+  %res = fadd float %s, %c
+  ret float %res
+}
+
+; Mixed: intrinsic sin + libcall cos
+define float @sincos_mixed_intrinsic_sin_libcall_cos(float %x) {
+; CHECK-LABEL: @sincos_mixed_intrinsic_sin_libcall_cos(
+; CHECK-NEXT:    [[S:%.*]] = call float @llvm.sin.f32(float [[X:%.*]])
+; CHECK-NEXT:    [[C:%.*]] = call float @cosf(float [[X]]) #[[ATTR0]]
+; CHECK-NEXT:    [[RES:%.*]] = fadd float [[S]], [[C]]
+; CHECK-NEXT:    ret float [[RES]]
+;
+  %s = call float @llvm.sin.f32(float %x)
+  %c = call float @cosf(float %x) #0
+  %res = fadd float %s, %c
+  ret float %res
+}
+
+attributes #0 = { nounwind memory(none) }

>From 8d76d9c774ff8e8c2f4fa6461d8661e6dee0ed34 Mon Sep 17 00:00:00 2001
From: Kito Cheng <[email protected]>
Date: Fri, 6 Mar 2026 21:47:06 +0800
Subject: [PATCH 4/8] Refactor sincos optimization: convert sin/cos libcalls to
 intrinsics first

Instead of combining sin/cos libcall pairs directly into llvm.sincos in
SimplifyLibCalls, split the optimization into two phases:

1. SimplifyLibCalls: Convert sin/cos libcalls to llvm.sin/llvm.cos
   intrinsics (similar to fabs -> llvm.fabs). UnsafeFPShrink narrowing
   (double -> float) is attempted first for LibFunc_sin/LibFunc_cos.

2. InstCombineCalls: Combine llvm.sin(x) + llvm.cos(x) intrinsic pairs
   into a single llvm.sincos(x) call via foldSinCosToSinCos().

This approach unifies sincos merging at the intrinsic level, enabling
combination of libcall pairs, intrinsic pairs, and mixed cases. The
sinpi/cospi path in SimplifyLibCalls remains unchanged.
---
 .../llvm/Transforms/Utils/SimplifyLibCalls.h  |   4 +-
 .../InstCombine/InstCombineCalls.cpp          |  72 ++++++++
 .../lib/Transforms/Utils/SimplifyLibCalls.cpp | 104 ++++-------
 llvm/test/Transforms/InstCombine/sincos.ll    | 167 +++++++++++++++---
 4 files changed, 247 insertions(+), 100 deletions(-)

diff --git a/llvm/include/llvm/Transforms/Utils/SimplifyLibCalls.h 
b/llvm/include/llvm/Transforms/Utils/SimplifyLibCalls.h
index e174a1c484eec..df98131a54ca9 100644
--- a/llvm/include/llvm/Transforms/Utils/SimplifyLibCalls.h
+++ b/llvm/include/llvm/Transforms/Utils/SimplifyLibCalls.h
@@ -210,8 +210,6 @@ class LibCallSimplifier {
   Value *optimizeFMod(CallInst *CI, IRBuilderBase &B);
   Value *mergeSqrtToExp(CallInst *CI, IRBuilderBase &B);
   Value *optimizeSinCosPi(CallInst *CI, bool IsSin, IRBuilderBase &B);
-  Value *optimizeSinCos(CallInst *CI, bool IsSin, IRBuilderBase &B,
-                        bool IsPi = false);
   Value *optimizeTrigInversionPairs(CallInst *CI, IRBuilderBase &B);
   Value *optimizeSymmetric(CallInst *CI, LibFunc Func, IRBuilderBase &B);
   Value *optimizeRemquo(CallInst *CI, IRBuilderBase &B);
@@ -249,7 +247,7 @@ class LibCallSimplifier {
   void classifyArgUse(Value *Val, Function *F, bool IsFloat,
                       SmallVectorImpl<CallInst *> &SinCalls,
                       SmallVectorImpl<CallInst *> &CosCalls,
-                      SmallVectorImpl<CallInst *> &SinCosCalls, bool IsPi);
+                      SmallVectorImpl<CallInst *> &SinCosCalls);
   Value *optimizePrintFString(CallInst *CI, IRBuilderBase &B);
   Value *optimizeSPrintFString(CallInst *CI, IRBuilderBase &B);
   Value *optimizeSnPrintFString(CallInst *CI, IRBuilderBase &B);
diff --git a/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp 
b/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp
index 3585c787bb880..31efc85723719 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp
@@ -1879,6 +1879,62 @@ static Instruction *foldNeonShift(IntrinsicInst *II, 
InstCombinerImpl &IC) {
   return IC.replaceInstUsesWith(*II, Result);
 }
 
+// If II is llvm.sin(x) or llvm.cos(x), and there is a matching
+// llvm.cos(x) or llvm.sin(x) using the same argument, combine them
+// into a single llvm.sincos(x) call. Returns the sin or cos result
+// extracted from sincos via ResultForII, and the matched instruction
+// via MatchedInst, or returns false if no match is found.
+static bool foldSinCosToSinCos(IntrinsicInst *II, IRBuilderBase &B,
+                               Value *&ResultForII,
+                               IntrinsicInst *&MatchedInst) {
+  Intrinsic::ID IID = II->getIntrinsicID();
+  bool IsSin = (IID == Intrinsic::sin);
+  Intrinsic::ID MatchID = IsSin ? Intrinsic::cos : Intrinsic::sin;
+
+  Value *Arg = II->getArgOperand(0);
+
+  // Don't bother looking through uses of constants.
+  if (isa<Constant>(Arg))
+    return false;
+
+  // Look for a matching cos/sin intrinsic with the same argument.
+  IntrinsicInst *Match = nullptr;
+  for (User *U : Arg->users()) {
+    if (auto *Cand = dyn_cast<IntrinsicInst>(U)) {
+      if (Cand != II && !Cand->use_empty() &&
+          Cand->getIntrinsicID() == MatchID &&
+          Cand->getFunction() == II->getFunction()) {
+        Match = Cand;
+        break;
+      }
+    }
+  }
+
+  if (!Match)
+    return false;
+
+  // Insert sincos right after the argument definition.
+  IRBuilderBase::InsertPointGuard Guard(B);
+  if (auto *ArgInst = dyn_cast<Instruction>(Arg))
+    B.SetInsertPoint(ArgInst->getParent(), std::next(ArgInst->getIterator()));
+  else {
+    BasicBlock &EntryBB = II->getFunction()->getEntryBlock();
+    B.SetInsertPoint(&EntryBB, EntryBB.begin());
+  }
+
+  Function *SinCosFunc = Intrinsic::getOrInsertDeclaration(
+      II->getModule(), Intrinsic::sincos, Arg->getType());
+  Value *SinCos = B.CreateCall(SinCosFunc, Arg, "sincos");
+  Value *Sin = B.CreateExtractValue(SinCos, 0, "sin");
+  Value *Cos = B.CreateExtractValue(SinCos, 1, "cos");
+
+  // Replace the matching call and return both results.
+  Match->replaceAllUsesWith(IsSin ? Cos : Sin);
+  MatchedInst = Match;
+  ResultForII = IsSin ? Sin : Cos;
+  return true;
+}
+
 /// CallInst simplification. This mostly only handles folding of intrinsic
 /// instructions. For normal calls, it allows visitCallBase to do the heavy
 /// lifting.
@@ -3179,6 +3235,14 @@ Instruction *InstCombinerImpl::visitCallInst(CallInst 
&CI) {
       // for f in {cos, cosh}
       return replaceOperand(*II, 0, X);
     }
+    if (IID == Intrinsic::cos) {
+      Value *Result;
+      IntrinsicInst *Match;
+      if (foldSinCosToSinCos(II, Builder, Result, Match)) {
+        eraseInstFromFunction(*Match);
+        return replaceInstUsesWith(*II, Result);
+      }
+    }
     break;
   }
   case Intrinsic::sin:
@@ -3193,6 +3257,14 @@ Instruction *InstCombinerImpl::visitCallInst(CallInst 
&CI) {
       Value *NewFunc = Builder.CreateUnaryIntrinsic(IID, X, II);
       return UnaryOperator::CreateFNegFMF(NewFunc, II);
     }
+    if (IID == Intrinsic::sin) {
+      Value *Result;
+      IntrinsicInst *Match;
+      if (foldSinCosToSinCos(II, Builder, Result, Match)) {
+        eraseInstFromFunction(*Match);
+        return replaceInstUsesWith(*II, Result);
+      }
+    }
     break;
   }
   case Intrinsic::ldexp: {
diff --git a/llvm/lib/Transforms/Utils/SimplifyLibCalls.cpp 
b/llvm/lib/Transforms/Utils/SimplifyLibCalls.cpp
index 155a037c9495a..48f4eda1d7638 100644
--- a/llvm/lib/Transforms/Utils/SimplifyLibCalls.cpp
+++ b/llvm/lib/Transforms/Utils/SimplifyLibCalls.cpp
@@ -2941,10 +2941,9 @@ static bool isTrigLibCall(CallInst *CI) {
   return CI->doesNotThrow() && CI->doesNotAccessMemory();
 }
 
-static bool insertSinCosPiCall(IRBuilderBase &B, Function *OrigCallee,
-                               Value *Arg, bool UseFloat, Value *&Sin,
-                               Value *&Cos, Value *&SinCos,
-                               const TargetLibraryInfo *TLI) {
+static bool insertSinCosCall(IRBuilderBase &B, Function *OrigCallee, Value 
*Arg,
+                             bool UseFloat, Value *&Sin, Value *&Cos,
+                             Value *&SinCos, const TargetLibraryInfo *TLI) {
   Module *M = OrigCallee->getParent();
   Type *ArgTy = Arg->getType();
   Type *ResTy;
@@ -3054,11 +3053,6 @@ Value *LibCallSimplifier::optimizeSymmetric(CallInst 
*CI, LibFunc Func,
 
 Value *LibCallSimplifier::optimizeSinCosPi(CallInst *CI, bool IsSin,
                                            IRBuilderBase &B) {
-  return optimizeSinCos(CI, IsSin, B, /*IsPi=*/true);
-}
-
-Value *LibCallSimplifier::optimizeSinCos(CallInst *CI, bool IsSin,
-                                         IRBuilderBase &B, bool IsPi) {
   // Make sure the prototype is as expected, otherwise the rest of the
   // function is probably invalid and likely to abort.
   if (!isTrigLibCall(CI))
@@ -3074,41 +3068,21 @@ Value *LibCallSimplifier::optimizeSinCos(CallInst *CI, 
bool IsSin,
 
   bool IsFloat = Arg->getType()->isFloatTy();
 
-  // Look for all compatible sin/cos (or sinpi/cospi) calls with the same
+  // Look for all compatible sinpi, cospi and sincospi calls with the same
   // argument. If there are enough (in some sense) we can make the
   // substitution.
   Function *F = CI->getFunction();
   for (User *U : Arg->users())
-    classifyArgUse(U, F, IsFloat, SinCalls, CosCalls, SinCosCalls, IsPi);
+    classifyArgUse(U, F, IsFloat, SinCalls, CosCalls, SinCosCalls);
 
-  // It's only worthwhile if both sin and cos are actually used.
+  // It's only worthwhile if both sinpi and cospi are actually used.
   if (SinCalls.empty() || CosCalls.empty())
     return nullptr;
 
   Value *Sin, *Cos, *SinCos;
-  if (IsPi) {
-    // For sinpi/cospi, use platform-specific __sincospi_stret libcall.
-    if (!insertSinCosPiCall(B, CI->getCalledFunction(), Arg, IsFloat, Sin, Cos,
-                            SinCos, TLI))
-      return nullptr;
-  } else {
-    // For sin/cos, use the llvm.sincos intrinsic.
-    IRBuilderBase::InsertPointGuard Guard(B);
-    if (Instruction *ArgInst = dyn_cast<Instruction>(Arg)) {
-      B.SetInsertPoint(ArgInst->getParent(), ++ArgInst->getIterator());
-    } else {
-      BasicBlock &EntryBB = B.GetInsertBlock()->getParent()->getEntryBlock();
-      B.SetInsertPoint(&EntryBB, EntryBB.begin());
-    }
-
-    Module *M = CI->getModule();
-    Type *ArgTy = Arg->getType();
-    Function *SinCosFunc =
-        Intrinsic::getOrInsertDeclaration(M, Intrinsic::sincos, ArgTy);
-    SinCos = B.CreateCall(SinCosFunc, Arg, "sincos");
-    Sin = B.CreateExtractValue(SinCos, 0, "sin");
-    Cos = B.CreateExtractValue(SinCos, 1, "cos");
-  }
+  if (!insertSinCosCall(B, CI->getCalledFunction(), Arg, IsFloat, Sin, Cos,
+                        SinCos, TLI))
+    return nullptr;
 
   auto replaceTrigInsts = [this](SmallVectorImpl<CallInst *> &Calls,
                                  Value *Res) {
@@ -3123,11 +3097,11 @@ Value *LibCallSimplifier::optimizeSinCos(CallInst *CI, 
bool IsSin,
   return IsSin ? Sin : Cos;
 }
 
-void LibCallSimplifier::classifyArgUse(Value *Val, Function *F, bool IsFloat,
-                                       SmallVectorImpl<CallInst *> &SinCalls,
-                                       SmallVectorImpl<CallInst *> &CosCalls,
-                                       SmallVectorImpl<CallInst *> 
&SinCosCalls,
-                                       bool IsPi) {
+void LibCallSimplifier::classifyArgUse(
+    Value *Val, Function *F, bool IsFloat,
+    SmallVectorImpl<CallInst *> &SinCalls,
+    SmallVectorImpl<CallInst *> &CosCalls,
+    SmallVectorImpl<CallInst *> &SinCosCalls) {
   auto *CI = dyn_cast<CallInst>(Val);
   if (!CI || CI->use_empty())
     return;
@@ -3144,28 +3118,20 @@ void LibCallSimplifier::classifyArgUse(Value *Val, 
Function *F, bool IsFloat,
       !isTrigLibCall(CI))
     return;
 
-  if (IsPi) {
-    if (IsFloat) {
-      if (Func == LibFunc_sinpif)
-        SinCalls.push_back(CI);
-      else if (Func == LibFunc_cospif)
-        CosCalls.push_back(CI);
-      else if (Func == LibFunc_sincospif_stret)
-        SinCosCalls.push_back(CI);
-    } else {
-      if (Func == LibFunc_sinpi)
-        SinCalls.push_back(CI);
-      else if (Func == LibFunc_cospi)
-        CosCalls.push_back(CI);
-      else if (Func == LibFunc_sincospi_stret)
-        SinCosCalls.push_back(CI);
-    }
+  if (IsFloat) {
+    if (Func == LibFunc_sinpif)
+      SinCalls.push_back(CI);
+    else if (Func == LibFunc_cospif)
+      CosCalls.push_back(CI);
+    else if (Func == LibFunc_sincospif_stret)
+      SinCosCalls.push_back(CI);
   } else {
-    if (Func == LibFunc_sin || Func == LibFunc_sinf || Func == LibFunc_sinl)
+    if (Func == LibFunc_sinpi)
       SinCalls.push_back(CI);
-    else if (Func == LibFunc_cos || Func == LibFunc_cosf ||
-             Func == LibFunc_cosl)
+    else if (Func == LibFunc_cospi)
       CosCalls.push_back(CI);
+    else if (Func == LibFunc_sincospi_stret)
+      SinCosCalls.push_back(CI);
   }
 }
 
@@ -4066,10 +4032,10 @@ Value 
*LibCallSimplifier::optimizeFloatingPointLibCall(CallInst *CI,
     return optimizeSinCosPi(CI, /*IsSin*/false, Builder);
   case LibFunc_sinf:
   case LibFunc_sinl:
-    return optimizeSinCos(CI, /*IsSin*/ true, Builder);
+    return replaceUnaryCall(CI, Builder, Intrinsic::sin);
   case LibFunc_cosf:
   case LibFunc_cosl:
-    return optimizeSinCos(CI, /*IsSin*/ false, Builder);
+    return replaceUnaryCall(CI, Builder, Intrinsic::cos);
   case LibFunc_powf:
   case LibFunc_pow:
   case LibFunc_powl:
@@ -4136,6 +4102,14 @@ Value 
*LibCallSimplifier::optimizeFloatingPointLibCall(CallInst *CI,
     return replaceUnaryCall(CI, Builder, Intrinsic::rint);
   case LibFunc_trunc:
     return replaceUnaryCall(CI, Builder, Intrinsic::trunc);
+  case LibFunc_sin:
+  case LibFunc_cos:
+    if (UnsafeFPShrink &&
+        hasFloatVersion(M, CI->getCalledFunction()->getName()))
+      if (Value *V = optimizeUnaryDoubleFP(CI, Builder, TLI, true))
+        return V;
+    return replaceUnaryCall(
+        CI, Builder, Func == LibFunc_sin ? Intrinsic::sin : Intrinsic::cos);
   case LibFunc_acos:
   case LibFunc_acosh:
   case LibFunc_asin:
@@ -4144,14 +4118,6 @@ Value 
*LibCallSimplifier::optimizeFloatingPointLibCall(CallInst *CI,
   case LibFunc_exp:
   case LibFunc_exp10:
   case LibFunc_expm1:
-  case LibFunc_sin:
-  case LibFunc_cos:
-    if (Value *V = optimizeSinCos(CI, Func == LibFunc_sin, Builder))
-      return V;
-    if (UnsafeFPShrink &&
-        hasFloatVersion(M, CI->getCalledFunction()->getName()))
-      return optimizeUnaryDoubleFP(CI, Builder, TLI, true);
-    return nullptr;
   case LibFunc_tanh:
     if (UnsafeFPShrink && hasFloatVersion(M, 
CI->getCalledFunction()->getName()))
       return optimizeUnaryDoubleFP(CI, Builder, TLI, true);
diff --git a/llvm/test/Transforms/InstCombine/sincos.ll 
b/llvm/test/Transforms/InstCombine/sincos.ll
index 8485f66b348f3..ced643c349fde 100644
--- a/llvm/test/Transforms/InstCombine/sincos.ll
+++ b/llvm/test/Transforms/InstCombine/sincos.ll
@@ -2,6 +2,7 @@
 ; RUN: opt -passes=instcombine -S < %s -mtriple=x86_64-apple-macosx10.9 | 
FileCheck %s --check-prefixes=CHECK,CHECK-DOUBLE-ALIGN8
 ; RUN: opt -passes=instcombine -S < %s -mtriple=arm-apple-ios7.0 | FileCheck 
%s --check-prefixes=CHECK,CHECK-DOUBLE-ALIGN4
 ; RUN: opt -passes=instcombine -S < %s -mtriple=x86_64-none-linux-gnu | 
FileCheck %s --check-prefixes=CHECK,CHECK-DOUBLE-ALIGN8-LINUX
+; RUN: opt -passes=instcombine -S < %s -mtriple=x86_64-apple-macosx10.9 
-enable-double-float-shrink | FileCheck %s --check-prefixes=CHECK-SHRINK
 ; REQUIRES: arm-registered-target, x86-registered-target
 
 declare float @sinf(float) #0
@@ -19,9 +20,16 @@ define float @sincos_f32() {
 ; CHECK-NEXT:    [[SINCOS:%.*]] = call { float, float } @llvm.sincos.f32(float 
[[VAL]])
 ; CHECK-NEXT:    [[SIN:%.*]] = extractvalue { float, float } [[SINCOS]], 0
 ; CHECK-NEXT:    [[COS:%.*]] = extractvalue { float, float } [[SINCOS]], 1
-; CHECK-NEXT:    [[C:%.*]] = call float @cosf(float [[VAL]]) #[[ATTR0:[0-9]+]]
 ; CHECK-NEXT:    [[RES:%.*]] = fadd float [[SIN]], [[COS]]
 ; CHECK-NEXT:    ret float [[RES]]
+;
+; CHECK-SHRINK-LABEL: @sincos_f32(
+; CHECK-SHRINK-NEXT:    [[VAL:%.*]] = load float, ptr @var32, align 4
+; CHECK-SHRINK-NEXT:    [[SINCOS:%.*]] = call { float, float } 
@llvm.sincos.f32(float [[VAL]])
+; CHECK-SHRINK-NEXT:    [[SIN:%.*]] = extractvalue { float, float } 
[[SINCOS]], 0
+; CHECK-SHRINK-NEXT:    [[COS:%.*]] = extractvalue { float, float } 
[[SINCOS]], 1
+; CHECK-SHRINK-NEXT:    [[RES:%.*]] = fadd float [[SIN]], [[COS]]
+; CHECK-SHRINK-NEXT:    ret float [[RES]]
 ;
   %val = load float, ptr @var32
   %s = call float @sinf(float %val) #0
@@ -37,7 +45,6 @@ define double @sincos_f64() {
 ; CHECK-DOUBLE-ALIGN8-NEXT:    [[SINCOS:%.*]] = call { double, double } 
@llvm.sincos.f64(double [[VAL]])
 ; CHECK-DOUBLE-ALIGN8-NEXT:    [[SIN:%.*]] = extractvalue { double, double } 
[[SINCOS]], 0
 ; CHECK-DOUBLE-ALIGN8-NEXT:    [[COS:%.*]] = extractvalue { double, double } 
[[SINCOS]], 1
-; CHECK-DOUBLE-ALIGN8-NEXT:    [[C:%.*]] = call double @cos(double [[VAL]]) 
#[[ATTR0]]
 ; CHECK-DOUBLE-ALIGN8-NEXT:    [[RES:%.*]] = fadd double [[SIN]], [[COS]]
 ; CHECK-DOUBLE-ALIGN8-NEXT:    ret double [[RES]]
 ;
@@ -46,7 +53,6 @@ define double @sincos_f64() {
 ; CHECK-DOUBLE-ALIGN4-NEXT:    [[SINCOS:%.*]] = call { double, double } 
@llvm.sincos.f64(double [[VAL]])
 ; CHECK-DOUBLE-ALIGN4-NEXT:    [[SIN:%.*]] = extractvalue { double, double } 
[[SINCOS]], 0
 ; CHECK-DOUBLE-ALIGN4-NEXT:    [[COS:%.*]] = extractvalue { double, double } 
[[SINCOS]], 1
-; CHECK-DOUBLE-ALIGN4-NEXT:    [[C:%.*]] = call double @cos(double [[VAL]]) 
#[[ATTR0]]
 ; CHECK-DOUBLE-ALIGN4-NEXT:    [[RES:%.*]] = fadd double [[SIN]], [[COS]]
 ; CHECK-DOUBLE-ALIGN4-NEXT:    ret double [[RES]]
 ;
@@ -55,9 +61,16 @@ define double @sincos_f64() {
 ; CHECK-DOUBLE-ALIGN8-LINUX-NEXT:    [[SINCOS:%.*]] = call { double, double } 
@llvm.sincos.f64(double [[VAL]])
 ; CHECK-DOUBLE-ALIGN8-LINUX-NEXT:    [[SIN:%.*]] = extractvalue { double, 
double } [[SINCOS]], 0
 ; CHECK-DOUBLE-ALIGN8-LINUX-NEXT:    [[COS:%.*]] = extractvalue { double, 
double } [[SINCOS]], 1
-; CHECK-DOUBLE-ALIGN8-LINUX-NEXT:    [[C:%.*]] = call double @cos(double 
[[VAL]]) #[[ATTR0]]
 ; CHECK-DOUBLE-ALIGN8-LINUX-NEXT:    [[RES:%.*]] = fadd double [[SIN]], [[COS]]
 ; CHECK-DOUBLE-ALIGN8-LINUX-NEXT:    ret double [[RES]]
+;
+; CHECK-SHRINK-LABEL: @sincos_f64(
+; CHECK-SHRINK-NEXT:    [[VAL:%.*]] = load double, ptr @var64, align 8
+; CHECK-SHRINK-NEXT:    [[SINCOS:%.*]] = call { double, double } 
@llvm.sincos.f64(double [[VAL]])
+; CHECK-SHRINK-NEXT:    [[SIN:%.*]] = extractvalue { double, double } 
[[SINCOS]], 0
+; CHECK-SHRINK-NEXT:    [[COS:%.*]] = extractvalue { double, double } 
[[SINCOS]], 1
+; CHECK-SHRINK-NEXT:    [[RES:%.*]] = fadd double [[SIN]], [[COS]]
+; CHECK-SHRINK-NEXT:    ret double [[RES]]
 ;
   %val = load double, ptr @var64
   %s = call double @sin(double %val) #0
@@ -69,8 +82,12 @@ define double @sincos_f64() {
 ; Only sin, no cos - should NOT combine
 define float @sin_only_f32(float %x) {
 ; CHECK-LABEL: @sin_only_f32(
-; CHECK-NEXT:    [[S:%.*]] = call float @sinf(float [[X:%.*]]) #[[ATTR0]]
+; CHECK-NEXT:    [[S:%.*]] = call float @llvm.sin.f32(float [[X:%.*]])
 ; CHECK-NEXT:    ret float [[S]]
+;
+; CHECK-SHRINK-LABEL: @sin_only_f32(
+; CHECK-SHRINK-NEXT:    [[S:%.*]] = call float @llvm.sin.f32(float [[X:%.*]])
+; CHECK-SHRINK-NEXT:    ret float [[S]]
 ;
   %s = call float @sinf(float %x) #0
   ret float %s
@@ -79,8 +96,12 @@ define float @sin_only_f32(float %x) {
 ; Only cos, no sin - should NOT combine
 define float @cos_only_f32(float %x) {
 ; CHECK-LABEL: @cos_only_f32(
-; CHECK-NEXT:    [[C:%.*]] = call float @cosf(float [[X:%.*]]) #[[ATTR0]]
+; CHECK-NEXT:    [[C:%.*]] = call float @llvm.cos.f32(float [[X:%.*]])
 ; CHECK-NEXT:    ret float [[C]]
+;
+; CHECK-SHRINK-LABEL: @cos_only_f32(
+; CHECK-SHRINK-NEXT:    [[C:%.*]] = call float @llvm.cos.f32(float [[X:%.*]])
+; CHECK-SHRINK-NEXT:    ret float [[C]]
 ;
   %c = call float @cosf(float %x) #0
   ret float %c
@@ -89,10 +110,16 @@ define float @cos_only_f32(float %x) {
 ; Different arguments - should NOT combine
 define float @sincos_different_args(float %x, float %y) {
 ; CHECK-LABEL: @sincos_different_args(
-; CHECK-NEXT:    [[S:%.*]] = call float @sinf(float [[X:%.*]]) #[[ATTR0]]
-; CHECK-NEXT:    [[C:%.*]] = call float @cosf(float [[Y:%.*]]) #[[ATTR0]]
+; CHECK-NEXT:    [[S:%.*]] = call float @llvm.sin.f32(float [[X:%.*]])
+; CHECK-NEXT:    [[C:%.*]] = call float @llvm.cos.f32(float [[Y:%.*]])
 ; CHECK-NEXT:    [[RES:%.*]] = fadd float [[S]], [[C]]
 ; CHECK-NEXT:    ret float [[RES]]
+;
+; CHECK-SHRINK-LABEL: @sincos_different_args(
+; CHECK-SHRINK-NEXT:    [[S:%.*]] = call float @llvm.sin.f32(float [[X:%.*]])
+; CHECK-SHRINK-NEXT:    [[C:%.*]] = call float @llvm.cos.f32(float [[Y:%.*]])
+; CHECK-SHRINK-NEXT:    [[RES:%.*]] = fadd float [[S]], [[C]]
+; CHECK-SHRINK-NEXT:    ret float [[RES]]
 ;
   %s = call float @sinf(float %x) #0
   %c = call float @cosf(float %y) #0
@@ -100,30 +127,25 @@ define float @sincos_different_args(float %x, float %y) {
   ret float %res
 }
 
-; Constant argument - should NOT combine
-define float @sincos_const_arg() {
-; CHECK-LABEL: @sincos_const_arg(
-; CHECK-NEXT:    [[S:%.*]] = call float @sinf(float 1.000000e+00) #[[ATTR0]]
-; CHECK-NEXT:    [[C:%.*]] = call float @cosf(float 1.000000e+00) #[[ATTR0]]
-; CHECK-NEXT:    ret float 0x3FF61BBE40000000
-;
-  %s = call float @sinf(float 1.0) #0
-  %c = call float @cosf(float 1.0) #0
-  %res = fadd float %s, %c
-  ret float %res
-}
-
 ; Multiple uses of sin and cos results
 define float @sincos_multi_use(float %x) {
 ; CHECK-LABEL: @sincos_multi_use(
 ; CHECK-NEXT:    [[SINCOS:%.*]] = call { float, float } @llvm.sincos.f32(float 
[[X:%.*]])
 ; CHECK-NEXT:    [[SIN:%.*]] = extractvalue { float, float } [[SINCOS]], 0
 ; CHECK-NEXT:    [[COS:%.*]] = extractvalue { float, float } [[SINCOS]], 1
-; CHECK-NEXT:    [[C:%.*]] = call float @cosf(float [[X]]) #[[ATTR0]]
 ; CHECK-NEXT:    [[ADD:%.*]] = fadd float [[SIN]], [[COS]]
 ; CHECK-NEXT:    [[MUL:%.*]] = fmul float [[SIN]], [[COS]]
 ; CHECK-NEXT:    [[RES:%.*]] = fadd float [[ADD]], [[MUL]]
 ; CHECK-NEXT:    ret float [[RES]]
+;
+; CHECK-SHRINK-LABEL: @sincos_multi_use(
+; CHECK-SHRINK-NEXT:    [[SINCOS:%.*]] = call { float, float } 
@llvm.sincos.f32(float [[X:%.*]])
+; CHECK-SHRINK-NEXT:    [[SIN:%.*]] = extractvalue { float, float } 
[[SINCOS]], 0
+; CHECK-SHRINK-NEXT:    [[COS:%.*]] = extractvalue { float, float } 
[[SINCOS]], 1
+; CHECK-SHRINK-NEXT:    [[ADD:%.*]] = fadd float [[SIN]], [[COS]]
+; CHECK-SHRINK-NEXT:    [[MUL:%.*]] = fmul float [[SIN]], [[COS]]
+; CHECK-SHRINK-NEXT:    [[RES:%.*]] = fadd float [[ADD]], [[MUL]]
+; CHECK-SHRINK-NEXT:    ret float [[RES]]
 ;
   %s = call float @sinf(float %x) #0
   %c = call float @cosf(float %x) #0
@@ -136,10 +158,18 @@ define float @sincos_multi_use(float %x) {
 ; Intrinsic sin + intrinsic cos - should combine
 define float @sincos_intrinsic_f32(float %x) {
 ; CHECK-LABEL: @sincos_intrinsic_f32(
-; CHECK-NEXT:    [[S:%.*]] = call float @llvm.sin.f32(float [[X:%.*]])
-; CHECK-NEXT:    [[C:%.*]] = call float @llvm.cos.f32(float [[X]])
+; CHECK-NEXT:    [[SINCOS:%.*]] = call { float, float } @llvm.sincos.f32(float 
[[X:%.*]])
+; CHECK-NEXT:    [[S:%.*]] = extractvalue { float, float } [[SINCOS]], 0
+; CHECK-NEXT:    [[C:%.*]] = extractvalue { float, float } [[SINCOS]], 1
 ; CHECK-NEXT:    [[RES:%.*]] = fadd float [[S]], [[C]]
 ; CHECK-NEXT:    ret float [[RES]]
+;
+; CHECK-SHRINK-LABEL: @sincos_intrinsic_f32(
+; CHECK-SHRINK-NEXT:    [[SINCOS:%.*]] = call { float, float } 
@llvm.sincos.f32(float [[X:%.*]])
+; CHECK-SHRINK-NEXT:    [[SIN:%.*]] = extractvalue { float, float } 
[[SINCOS]], 0
+; CHECK-SHRINK-NEXT:    [[COS:%.*]] = extractvalue { float, float } 
[[SINCOS]], 1
+; CHECK-SHRINK-NEXT:    [[RES:%.*]] = fadd float [[SIN]], [[COS]]
+; CHECK-SHRINK-NEXT:    ret float [[RES]]
 ;
   %s = call float @llvm.sin.f32(float %x)
   %c = call float @llvm.cos.f32(float %x)
@@ -150,10 +180,18 @@ define float @sincos_intrinsic_f32(float %x) {
 ; Mixed: libcall sin + intrinsic cos
 define float @sincos_mixed_libcall_sin_intrinsic_cos(float %x) {
 ; CHECK-LABEL: @sincos_mixed_libcall_sin_intrinsic_cos(
-; CHECK-NEXT:    [[S:%.*]] = call float @sinf(float [[X:%.*]]) #[[ATTR0]]
-; CHECK-NEXT:    [[C:%.*]] = call float @llvm.cos.f32(float [[X]])
+; CHECK-NEXT:    [[SINCOS:%.*]] = call { float, float } @llvm.sincos.f32(float 
[[X:%.*]])
+; CHECK-NEXT:    [[S:%.*]] = extractvalue { float, float } [[SINCOS]], 0
+; CHECK-NEXT:    [[C:%.*]] = extractvalue { float, float } [[SINCOS]], 1
 ; CHECK-NEXT:    [[RES:%.*]] = fadd float [[S]], [[C]]
 ; CHECK-NEXT:    ret float [[RES]]
+;
+; CHECK-SHRINK-LABEL: @sincos_mixed_libcall_sin_intrinsic_cos(
+; CHECK-SHRINK-NEXT:    [[SINCOS:%.*]] = call { float, float } 
@llvm.sincos.f32(float [[X:%.*]])
+; CHECK-SHRINK-NEXT:    [[SIN:%.*]] = extractvalue { float, float } 
[[SINCOS]], 0
+; CHECK-SHRINK-NEXT:    [[COS:%.*]] = extractvalue { float, float } 
[[SINCOS]], 1
+; CHECK-SHRINK-NEXT:    [[RES:%.*]] = fadd float [[SIN]], [[COS]]
+; CHECK-SHRINK-NEXT:    ret float [[RES]]
 ;
   %s = call float @sinf(float %x) #0
   %c = call float @llvm.cos.f32(float %x)
@@ -164,10 +202,18 @@ define float 
@sincos_mixed_libcall_sin_intrinsic_cos(float %x) {
 ; Mixed: intrinsic sin + libcall cos
 define float @sincos_mixed_intrinsic_sin_libcall_cos(float %x) {
 ; CHECK-LABEL: @sincos_mixed_intrinsic_sin_libcall_cos(
-; CHECK-NEXT:    [[S:%.*]] = call float @llvm.sin.f32(float [[X:%.*]])
-; CHECK-NEXT:    [[C:%.*]] = call float @cosf(float [[X]]) #[[ATTR0]]
+; CHECK-NEXT:    [[SINCOS:%.*]] = call { float, float } @llvm.sincos.f32(float 
[[X:%.*]])
+; CHECK-NEXT:    [[S:%.*]] = extractvalue { float, float } [[SINCOS]], 0
+; CHECK-NEXT:    [[C:%.*]] = extractvalue { float, float } [[SINCOS]], 1
 ; CHECK-NEXT:    [[RES:%.*]] = fadd float [[S]], [[C]]
 ; CHECK-NEXT:    ret float [[RES]]
+;
+; CHECK-SHRINK-LABEL: @sincos_mixed_intrinsic_sin_libcall_cos(
+; CHECK-SHRINK-NEXT:    [[SINCOS:%.*]] = call { float, float } 
@llvm.sincos.f32(float [[X:%.*]])
+; CHECK-SHRINK-NEXT:    [[SIN:%.*]] = extractvalue { float, float } 
[[SINCOS]], 0
+; CHECK-SHRINK-NEXT:    [[COS:%.*]] = extractvalue { float, float } 
[[SINCOS]], 1
+; CHECK-SHRINK-NEXT:    [[RES:%.*]] = fadd float [[SIN]], [[COS]]
+; CHECK-SHRINK-NEXT:    ret float [[RES]]
 ;
   %s = call float @llvm.sin.f32(float %x)
   %c = call float @cosf(float %x) #0
@@ -175,4 +221,69 @@ define float @sincos_mixed_intrinsic_sin_libcall_cos(float 
%x) {
   ret float %res
 }
 
+; UnsafeFPShrink: sin(fpext float) -> fpext(sinf(float))
+; This should trigger optimizeUnaryDoubleFP before converting to intrinsic.
+define float @sin_double_to_float_shrink(float %x) {
+; CHECK-LABEL: @sin_double_to_float_shrink(
+; CHECK-NEXT:    [[EXT:%.*]] = fpext float [[X:%.*]] to double
+; CHECK-NEXT:    [[S:%.*]] = call double @llvm.sin.f64(double [[EXT]])
+; CHECK-NEXT:    [[TRUNC:%.*]] = fptrunc double [[S]] to float
+; CHECK-NEXT:    ret float [[TRUNC]]
+;
+; CHECK-SHRINK-LABEL: @sin_double_to_float_shrink(
+; CHECK-SHRINK-NEXT:    [[SINF:%.*]] = call float @llvm.sin.f32(float 
[[X:%.*]])
+; CHECK-SHRINK-NEXT:    ret float [[SINF]]
+;
+  %ext = fpext float %x to double
+  %s = call double @sin(double %ext) #0
+  %trunc = fptrunc double %s to float
+  ret float %trunc
+}
+
+; UnsafeFPShrink: cos(fpext float) -> fpext(cosf(float))
+define float @cos_double_to_float_shrink(float %x) {
+; CHECK-LABEL: @cos_double_to_float_shrink(
+; CHECK-NEXT:    [[EXT:%.*]] = fpext float [[X:%.*]] to double
+; CHECK-NEXT:    [[C:%.*]] = call double @llvm.cos.f64(double [[EXT]])
+; CHECK-NEXT:    [[TRUNC:%.*]] = fptrunc double [[C]] to float
+; CHECK-NEXT:    ret float [[TRUNC]]
+;
+; CHECK-SHRINK-LABEL: @cos_double_to_float_shrink(
+; CHECK-SHRINK-NEXT:    [[COSF:%.*]] = call float @llvm.cos.f32(float 
[[X:%.*]])
+; CHECK-SHRINK-NEXT:    ret float [[COSF]]
+;
+  %ext = fpext float %x to double
+  %c = call double @cos(double %ext) #0
+  %trunc = fptrunc double %c to float
+  ret float %trunc
+}
+
+; UnsafeFPShrink + sincos: sin(fpext float) + cos(fpext float) should
+; first shrink to sinf/cosf, then combine into llvm.sincos.f32.
+define { float, float } @sincos_double_to_float_shrink(float %x) {
+; CHECK-LABEL: @sincos_double_to_float_shrink(
+; CHECK-NEXT:    [[EXT:%.*]] = fpext float [[X:%.*]] to double
+; CHECK-NEXT:    [[SINCOS:%.*]] = call { double, double } 
@llvm.sincos.f64(double [[EXT]])
+; CHECK-NEXT:    [[SIN:%.*]] = extractvalue { double, double } [[SINCOS]], 0
+; CHECK-NEXT:    [[COS:%.*]] = extractvalue { double, double } [[SINCOS]], 1
+; CHECK-NEXT:    [[ST:%.*]] = fptrunc double [[SIN]] to float
+; CHECK-NEXT:    [[CT:%.*]] = fptrunc double [[COS]] to float
+; CHECK-NEXT:    [[R0:%.*]] = insertvalue { float, float } undef, float 
[[ST]], 0
+; CHECK-NEXT:    [[R1:%.*]] = insertvalue { float, float } [[R0]], float 
[[CT]], 1
+; CHECK-NEXT:    ret { float, float } [[R1]]
+;
+; CHECK-SHRINK-LABEL: @sincos_double_to_float_shrink(
+; CHECK-SHRINK-NEXT:    [[SINCOS:%.*]] = call { float, float } 
@llvm.sincos.f32(float [[X:%.*]])
+; CHECK-SHRINK-NEXT:    ret { float, float } [[SINCOS]]
+;
+  %ext = fpext float %x to double
+  %s = call double @sin(double %ext) #0
+  %c = call double @cos(double %ext) #0
+  %st = fptrunc double %s to float
+  %ct = fptrunc double %c to float
+  %r0 = insertvalue { float, float } undef, float %st, 0
+  %r1 = insertvalue { float, float } %r0, float %ct, 1
+  ret { float, float } %r1
+}
+
 attributes #0 = { nounwind memory(none) }

>From 41944e9bc9d7d5649d23b4f38fbb5e80827de895 Mon Sep 17 00:00:00 2001
From: Kito Cheng <[email protected]>
Date: Fri, 6 Mar 2026 22:05:56 +0800
Subject: [PATCH 5/8] !fixup: Guard sin/cos to intrinsic conversion on
 doesNotAccessMemory

Only convert sin/cos libcalls to llvm.sin/llvm.cos intrinsics when the
call has memory(none) attribute, preserving errno-setting semantics for
calls that may write to errno. Update affected test CHECK lines.
---
 .../lib/Transforms/Utils/SimplifyLibCalls.cpp | 14 ++++--
 .../test/Transforms/InstCombine/AMDGPU/tan.ll |  3 +-
 .../Transforms/InstCombine/fdiv-cos-sin.ll    | 50 ++++++++++++-------
 .../Transforms/InstCombine/fdiv-sin-cos.ll    | 40 +++++++++++----
 .../Transforms/InstCombine/may-alias-errno.ll |  4 +-
 5 files changed, 74 insertions(+), 37 deletions(-)

diff --git a/llvm/lib/Transforms/Utils/SimplifyLibCalls.cpp 
b/llvm/lib/Transforms/Utils/SimplifyLibCalls.cpp
index 48f4eda1d7638..920aac644b9c5 100644
--- a/llvm/lib/Transforms/Utils/SimplifyLibCalls.cpp
+++ b/llvm/lib/Transforms/Utils/SimplifyLibCalls.cpp
@@ -4032,10 +4032,14 @@ Value 
*LibCallSimplifier::optimizeFloatingPointLibCall(CallInst *CI,
     return optimizeSinCosPi(CI, /*IsSin*/false, Builder);
   case LibFunc_sinf:
   case LibFunc_sinl:
-    return replaceUnaryCall(CI, Builder, Intrinsic::sin);
+    if (CI->doesNotAccessMemory())
+      return replaceUnaryCall(CI, Builder, Intrinsic::sin);
+    return nullptr;
   case LibFunc_cosf:
   case LibFunc_cosl:
-    return replaceUnaryCall(CI, Builder, Intrinsic::cos);
+    if (CI->doesNotAccessMemory())
+      return replaceUnaryCall(CI, Builder, Intrinsic::cos);
+    return nullptr;
   case LibFunc_powf:
   case LibFunc_pow:
   case LibFunc_powl:
@@ -4108,8 +4112,10 @@ Value 
*LibCallSimplifier::optimizeFloatingPointLibCall(CallInst *CI,
         hasFloatVersion(M, CI->getCalledFunction()->getName()))
       if (Value *V = optimizeUnaryDoubleFP(CI, Builder, TLI, true))
         return V;
-    return replaceUnaryCall(
-        CI, Builder, Func == LibFunc_sin ? Intrinsic::sin : Intrinsic::cos);
+    if (CI->doesNotAccessMemory())
+      return replaceUnaryCall(
+          CI, Builder, Func == LibFunc_sin ? Intrinsic::sin : Intrinsic::cos);
+    return nullptr;
   case LibFunc_acos:
   case LibFunc_acosh:
   case LibFunc_asin:
diff --git a/llvm/test/Transforms/InstCombine/AMDGPU/tan.ll 
b/llvm/test/Transforms/InstCombine/AMDGPU/tan.ll
index 62160a6d3063a..f8103f0cc229b 100644
--- a/llvm/test/Transforms/InstCombine/AMDGPU/tan.ll
+++ b/llvm/test/Transforms/InstCombine/AMDGPU/tan.ll
@@ -3,8 +3,7 @@
 ; Check that sin/cos is not folded to tan on amdgcn.
 
 ; GCN-LABEL: define amdgpu_ps float @llpc.shader.FS.main
-; GCN: call float @llvm.sin.f32
-; GCN: call float @llvm.cos.f32
+; GCN: call { float, float } @llvm.sincos.f32
 
 declare float @llvm.sin.f32(float) #0
 declare float @llvm.cos.f32(float) #0
diff --git a/llvm/test/Transforms/InstCombine/fdiv-cos-sin.ll 
b/llvm/test/Transforms/InstCombine/fdiv-cos-sin.ll
index 6d945ede3b387..007125501b30b 100644
--- a/llvm/test/Transforms/InstCombine/fdiv-cos-sin.ll
+++ b/llvm/test/Transforms/InstCombine/fdiv-cos-sin.ll
@@ -3,8 +3,9 @@
 
 define double @fdiv_cos_sin(double %a) {
 ; CHECK-LABEL: @fdiv_cos_sin(
-; CHECK-NEXT:    [[TMP1:%.*]] = call double @llvm.cos.f64(double [[A:%.*]])
-; CHECK-NEXT:    [[TMP2:%.*]] = call double @llvm.sin.f64(double [[A]])
+; CHECK-NEXT:    [[SINCOS:%.*]] = call { double, double } 
@llvm.sincos.f64(double [[A:%.*]])
+; CHECK-NEXT:    [[TMP2:%.*]] = extractvalue { double, double } [[SINCOS]], 0
+; CHECK-NEXT:    [[TMP1:%.*]] = extractvalue { double, double } [[SINCOS]], 1
 ; CHECK-NEXT:    [[DIV:%.*]] = fdiv double [[TMP1]], [[TMP2]]
 ; CHECK-NEXT:    ret double [[DIV]]
 ;
@@ -16,8 +17,9 @@ define double @fdiv_cos_sin(double %a) {
 
 define double @fdiv_strict_cos_strict_sin_reassoc(double %a) {
 ; CHECK-LABEL: @fdiv_strict_cos_strict_sin_reassoc(
-; CHECK-NEXT:    [[TMP1:%.*]] = call double @llvm.cos.f64(double [[A:%.*]])
-; CHECK-NEXT:    [[TMP2:%.*]] = call reassoc double @llvm.sin.f64(double [[A]])
+; CHECK-NEXT:    [[SINCOS:%.*]] = call { double, double } 
@llvm.sincos.f64(double [[A:%.*]])
+; CHECK-NEXT:    [[TMP2:%.*]] = extractvalue { double, double } [[SINCOS]], 0
+; CHECK-NEXT:    [[TMP1:%.*]] = extractvalue { double, double } [[SINCOS]], 1
 ; CHECK-NEXT:    [[DIV:%.*]] = fdiv double [[TMP1]], [[TMP2]]
 ; CHECK-NEXT:    ret double [[DIV]]
 ;
@@ -29,8 +31,10 @@ define double @fdiv_strict_cos_strict_sin_reassoc(double %a) 
{
 
 define double @fdiv_reassoc_cos_strict_sin_strict(double %a, ptr 
dereferenceable(2) %dummy) {
 ; CHECK-LABEL: @fdiv_reassoc_cos_strict_sin_strict(
-; CHECK-NEXT:    [[TAN:%.*]] = call reassoc double @tan(double [[A:%.*]]) 
#[[ATTR1:[0-9]+]]
-; CHECK-NEXT:    [[DIV:%.*]] = fdiv reassoc double 1.000000e+00, [[TAN]]
+; CHECK-NEXT:    [[SINCOS:%.*]] = call { double, double } 
@llvm.sincos.f64(double [[A:%.*]])
+; CHECK-NEXT:    [[SIN:%.*]] = extractvalue { double, double } [[SINCOS]], 0
+; CHECK-NEXT:    [[COS:%.*]] = extractvalue { double, double } [[SINCOS]], 1
+; CHECK-NEXT:    [[DIV:%.*]] = fdiv reassoc double [[COS]], [[SIN]]
 ; CHECK-NEXT:    ret double [[DIV]]
 ;
   %1 = call double @llvm.cos.f64(double %a)
@@ -41,8 +45,10 @@ define double @fdiv_reassoc_cos_strict_sin_strict(double %a, 
ptr dereferenceable
 
 define double @fdiv_reassoc_cos_reassoc_sin_strict(double %a) {
 ; CHECK-LABEL: @fdiv_reassoc_cos_reassoc_sin_strict(
-; CHECK-NEXT:    [[TAN:%.*]] = call reassoc double @tan(double [[A:%.*]]) 
#[[ATTR1]]
-; CHECK-NEXT:    [[DIV:%.*]] = fdiv reassoc double 1.000000e+00, [[TAN]]
+; CHECK-NEXT:    [[SINCOS:%.*]] = call { double, double } 
@llvm.sincos.f64(double [[A:%.*]])
+; CHECK-NEXT:    [[SIN:%.*]] = extractvalue { double, double } [[SINCOS]], 0
+; CHECK-NEXT:    [[COS:%.*]] = extractvalue { double, double } [[SINCOS]], 1
+; CHECK-NEXT:    [[DIV:%.*]] = fdiv reassoc double [[COS]], [[SIN]]
 ; CHECK-NEXT:    ret double [[DIV]]
 ;
   %1 = call reassoc double @llvm.cos.f64(double %a)
@@ -53,8 +59,9 @@ define double @fdiv_reassoc_cos_reassoc_sin_strict(double %a) 
{
 
 define double @fdiv_cos_sin_reassoc_multiple_uses(double %a) {
 ; CHECK-LABEL: @fdiv_cos_sin_reassoc_multiple_uses(
-; CHECK-NEXT:    [[TMP1:%.*]] = call reassoc double @llvm.cos.f64(double 
[[A:%.*]])
-; CHECK-NEXT:    [[TMP2:%.*]] = call reassoc double @llvm.sin.f64(double [[A]])
+; CHECK-NEXT:    [[SINCOS:%.*]] = call { double, double } 
@llvm.sincos.f64(double [[A:%.*]])
+; CHECK-NEXT:    [[TMP2:%.*]] = extractvalue { double, double } [[SINCOS]], 0
+; CHECK-NEXT:    [[TMP1:%.*]] = extractvalue { double, double } [[SINCOS]], 1
 ; CHECK-NEXT:    [[DIV:%.*]] = fdiv reassoc double [[TMP1]], [[TMP2]]
 ; CHECK-NEXT:    call void @use(double [[TMP2]])
 ; CHECK-NEXT:    ret double [[DIV]]
@@ -68,8 +75,10 @@ define double @fdiv_cos_sin_reassoc_multiple_uses(double %a) 
{
 
 define double @fdiv_cos_sin_reassoc(double %a) {
 ; CHECK-LABEL: @fdiv_cos_sin_reassoc(
-; CHECK-NEXT:    [[TAN:%.*]] = call reassoc double @tan(double [[A:%.*]]) 
#[[ATTR1]]
-; CHECK-NEXT:    [[DIV:%.*]] = fdiv reassoc double 1.000000e+00, [[TAN]]
+; CHECK-NEXT:    [[SINCOS:%.*]] = call { double, double } 
@llvm.sincos.f64(double [[A:%.*]])
+; CHECK-NEXT:    [[SIN:%.*]] = extractvalue { double, double } [[SINCOS]], 0
+; CHECK-NEXT:    [[COS:%.*]] = extractvalue { double, double } [[SINCOS]], 1
+; CHECK-NEXT:    [[DIV:%.*]] = fdiv reassoc double [[COS]], [[SIN]]
 ; CHECK-NEXT:    ret double [[DIV]]
 ;
   %1 = call reassoc double @llvm.cos.f64(double %a)
@@ -80,8 +89,9 @@ define double @fdiv_cos_sin_reassoc(double %a) {
 
 define half @fdiv_cosf16_sinf16_reassoc(half %a) {
 ; CHECK-LABEL: @fdiv_cosf16_sinf16_reassoc(
-; CHECK-NEXT:    [[TMP1:%.*]] = call reassoc half @llvm.cos.f16(half [[A:%.*]])
-; CHECK-NEXT:    [[TMP2:%.*]] = call reassoc half @llvm.sin.f16(half [[A]])
+; CHECK-NEXT:    [[SINCOS:%.*]] = call { half, half } @llvm.sincos.f16(half 
[[A:%.*]])
+; CHECK-NEXT:    [[TMP2:%.*]] = extractvalue { half, half } [[SINCOS]], 0
+; CHECK-NEXT:    [[TMP1:%.*]] = extractvalue { half, half } [[SINCOS]], 1
 ; CHECK-NEXT:    [[DIV:%.*]] = fdiv reassoc half [[TMP1]], [[TMP2]]
 ; CHECK-NEXT:    ret half [[DIV]]
 ;
@@ -93,8 +103,10 @@ define half @fdiv_cosf16_sinf16_reassoc(half %a) {
 
 define float @fdiv_cosf_sinf_reassoc(float %a) {
 ; CHECK-LABEL: @fdiv_cosf_sinf_reassoc(
-; CHECK-NEXT:    [[TANF:%.*]] = call reassoc float @tanf(float [[A:%.*]]) 
#[[ATTR1]]
-; CHECK-NEXT:    [[DIV:%.*]] = fdiv reassoc float 1.000000e+00, [[TANF]]
+; CHECK-NEXT:    [[SINCOS:%.*]] = call { float, float } @llvm.sincos.f32(float 
[[A:%.*]])
+; CHECK-NEXT:    [[SIN:%.*]] = extractvalue { float, float } [[SINCOS]], 0
+; CHECK-NEXT:    [[COS:%.*]] = extractvalue { float, float } [[SINCOS]], 1
+; CHECK-NEXT:    [[DIV:%.*]] = fdiv reassoc float [[COS]], [[SIN]]
 ; CHECK-NEXT:    ret float [[DIV]]
 ;
   %1 = call reassoc float @llvm.cos.f32(float %a)
@@ -105,8 +117,10 @@ define float @fdiv_cosf_sinf_reassoc(float %a) {
 
 define fp128 @fdiv_cosfp128_sinfp128_reassoc(fp128 %a) {
 ; CHECK-LABEL: @fdiv_cosfp128_sinfp128_reassoc(
-; CHECK-NEXT:    [[TANL:%.*]] = call reassoc fp128 @tanl(fp128 [[A:%.*]]) 
#[[ATTR1]]
-; CHECK-NEXT:    [[DIV:%.*]] = fdiv reassoc fp128 
0xL00000000000000003FFF000000000000, [[TANL]]
+; CHECK-NEXT:    [[SINCOS:%.*]] = call { fp128, fp128 } 
@llvm.sincos.f128(fp128 [[A:%.*]])
+; CHECK-NEXT:    [[SIN:%.*]] = extractvalue { fp128, fp128 } [[SINCOS]], 0
+; CHECK-NEXT:    [[COS:%.*]] = extractvalue { fp128, fp128 } [[SINCOS]], 1
+; CHECK-NEXT:    [[DIV:%.*]] = fdiv reassoc fp128 [[COS]], [[SIN]]
 ; CHECK-NEXT:    ret fp128 [[DIV]]
 ;
   %1 = call reassoc fp128 @llvm.cos.fp128(fp128 %a)
diff --git a/llvm/test/Transforms/InstCombine/fdiv-sin-cos.ll 
b/llvm/test/Transforms/InstCombine/fdiv-sin-cos.ll
index a9b8af345f96d..5e79f8a9296c3 100644
--- a/llvm/test/Transforms/InstCombine/fdiv-sin-cos.ll
+++ b/llvm/test/Transforms/InstCombine/fdiv-sin-cos.ll
@@ -3,8 +3,9 @@
 
 define double @fdiv_sin_cos(double %a) {
 ; CHECK-LABEL: @fdiv_sin_cos(
-; CHECK-NEXT:    [[TMP1:%.*]] = call double @llvm.sin.f64(double [[A:%.*]])
-; CHECK-NEXT:    [[TMP2:%.*]] = call double @llvm.cos.f64(double [[A]])
+; CHECK-NEXT:    [[SINCOS:%.*]] = call { double, double } 
@llvm.sincos.f64(double [[A:%.*]])
+; CHECK-NEXT:    [[TMP1:%.*]] = extractvalue { double, double } [[SINCOS]], 0
+; CHECK-NEXT:    [[TMP2:%.*]] = extractvalue { double, double } [[SINCOS]], 1
 ; CHECK-NEXT:    [[DIV:%.*]] = fdiv double [[TMP1]], [[TMP2]]
 ; CHECK-NEXT:    ret double [[DIV]]
 ;
@@ -16,8 +17,9 @@ define double @fdiv_sin_cos(double %a) {
 
 define double @fdiv_strict_sin_strict_cos_reassoc(double %a) {
 ; CHECK-LABEL: @fdiv_strict_sin_strict_cos_reassoc(
-; CHECK-NEXT:    [[TMP1:%.*]] = call double @llvm.sin.f64(double [[A:%.*]])
-; CHECK-NEXT:    [[TMP2:%.*]] = call reassoc double @llvm.cos.f64(double [[A]])
+; CHECK-NEXT:    [[SINCOS:%.*]] = call { double, double } 
@llvm.sincos.f64(double [[A:%.*]])
+; CHECK-NEXT:    [[TMP1:%.*]] = extractvalue { double, double } [[SINCOS]], 0
+; CHECK-NEXT:    [[TMP2:%.*]] = extractvalue { double, double } [[SINCOS]], 1
 ; CHECK-NEXT:    [[DIV:%.*]] = fdiv double [[TMP1]], [[TMP2]]
 ; CHECK-NEXT:    ret double [[DIV]]
 ;
@@ -29,7 +31,10 @@ define double @fdiv_strict_sin_strict_cos_reassoc(double %a) 
{
 
 define double @fdiv_reassoc_sin_strict_cos_strict(double %a, ptr 
dereferenceable(2) %dummy) {
 ; CHECK-LABEL: @fdiv_reassoc_sin_strict_cos_strict(
-; CHECK-NEXT:    [[TAN:%.*]] = call reassoc double @tan(double [[A:%.*]]) 
#[[ATTR1:[0-9]+]]
+; CHECK-NEXT:    [[SINCOS:%.*]] = call { double, double } 
@llvm.sincos.f64(double [[A:%.*]])
+; CHECK-NEXT:    [[SIN:%.*]] = extractvalue { double, double } [[SINCOS]], 0
+; CHECK-NEXT:    [[COS:%.*]] = extractvalue { double, double } [[SINCOS]], 1
+; CHECK-NEXT:    [[TAN:%.*]] = fdiv reassoc double [[SIN]], [[COS]]
 ; CHECK-NEXT:    ret double [[TAN]]
 ;
   %1 = call double @llvm.sin.f64(double %a)
@@ -40,7 +45,10 @@ define double @fdiv_reassoc_sin_strict_cos_strict(double %a, 
ptr dereferenceable
 
 define double @fdiv_reassoc_sin_reassoc_cos_strict(double %a) {
 ; CHECK-LABEL: @fdiv_reassoc_sin_reassoc_cos_strict(
-; CHECK-NEXT:    [[TAN:%.*]] = call reassoc double @tan(double [[A:%.*]]) 
#[[ATTR1]]
+; CHECK-NEXT:    [[SINCOS:%.*]] = call { double, double } 
@llvm.sincos.f64(double [[A:%.*]])
+; CHECK-NEXT:    [[SIN:%.*]] = extractvalue { double, double } [[SINCOS]], 0
+; CHECK-NEXT:    [[COS:%.*]] = extractvalue { double, double } [[SINCOS]], 1
+; CHECK-NEXT:    [[TAN:%.*]] = fdiv reassoc double [[SIN]], [[COS]]
 ; CHECK-NEXT:    ret double [[TAN]]
 ;
   %1 = call reassoc double @llvm.sin.f64(double %a)
@@ -51,8 +59,9 @@ define double @fdiv_reassoc_sin_reassoc_cos_strict(double %a) 
{
 
 define double @fdiv_sin_cos_reassoc_multiple_uses(double %a) {
 ; CHECK-LABEL: @fdiv_sin_cos_reassoc_multiple_uses(
-; CHECK-NEXT:    [[TMP1:%.*]] = call reassoc double @llvm.sin.f64(double 
[[A:%.*]])
-; CHECK-NEXT:    [[TMP2:%.*]] = call reassoc double @llvm.cos.f64(double [[A]])
+; CHECK-NEXT:    [[SINCOS:%.*]] = call { double, double } 
@llvm.sincos.f64(double [[A:%.*]])
+; CHECK-NEXT:    [[TMP1:%.*]] = extractvalue { double, double } [[SINCOS]], 0
+; CHECK-NEXT:    [[TMP2:%.*]] = extractvalue { double, double } [[SINCOS]], 1
 ; CHECK-NEXT:    [[DIV:%.*]] = fdiv reassoc double [[TMP1]], [[TMP2]]
 ; CHECK-NEXT:    call void @use(double [[TMP2]])
 ; CHECK-NEXT:    ret double [[DIV]]
@@ -66,7 +75,10 @@ define double @fdiv_sin_cos_reassoc_multiple_uses(double %a) 
{
 
 define double @fdiv_sin_cos_reassoc(double %a) {
 ; CHECK-LABEL: @fdiv_sin_cos_reassoc(
-; CHECK-NEXT:    [[TAN:%.*]] = call reassoc double @tan(double [[A:%.*]]) 
#[[ATTR1]]
+; CHECK-NEXT:    [[SINCOS:%.*]] = call { double, double } 
@llvm.sincos.f64(double [[A:%.*]])
+; CHECK-NEXT:    [[SIN:%.*]] = extractvalue { double, double } [[SINCOS]], 0
+; CHECK-NEXT:    [[COS:%.*]] = extractvalue { double, double } [[SINCOS]], 1
+; CHECK-NEXT:    [[TAN:%.*]] = fdiv reassoc double [[SIN]], [[COS]]
 ; CHECK-NEXT:    ret double [[TAN]]
 ;
   %1 = call reassoc double @llvm.sin.f64(double %a)
@@ -77,7 +89,10 @@ define double @fdiv_sin_cos_reassoc(double %a) {
 
 define float @fdiv_sinf_cosf_reassoc(float %a) {
 ; CHECK-LABEL: @fdiv_sinf_cosf_reassoc(
-; CHECK-NEXT:    [[TANF:%.*]] = call reassoc float @tanf(float [[A:%.*]]) 
#[[ATTR1]]
+; CHECK-NEXT:    [[SINCOS:%.*]] = call { float, float } @llvm.sincos.f32(float 
[[A:%.*]])
+; CHECK-NEXT:    [[SIN:%.*]] = extractvalue { float, float } [[SINCOS]], 0
+; CHECK-NEXT:    [[COS:%.*]] = extractvalue { float, float } [[SINCOS]], 1
+; CHECK-NEXT:    [[TANF:%.*]] = fdiv reassoc float [[SIN]], [[COS]]
 ; CHECK-NEXT:    ret float [[TANF]]
 ;
   %1 = call reassoc float @llvm.sin.f32(float %a)
@@ -88,7 +103,10 @@ define float @fdiv_sinf_cosf_reassoc(float %a) {
 
 define fp128 @fdiv_sinfp128_cosfp128_reassoc(fp128 %a) {
 ; CHECK-LABEL: @fdiv_sinfp128_cosfp128_reassoc(
-; CHECK-NEXT:    [[TANL:%.*]] = call reassoc fp128 @tanl(fp128 [[A:%.*]]) 
#[[ATTR1]]
+; CHECK-NEXT:    [[SINCOS:%.*]] = call { fp128, fp128 } 
@llvm.sincos.f128(fp128 [[A:%.*]])
+; CHECK-NEXT:    [[SIN:%.*]] = extractvalue { fp128, fp128 } [[SINCOS]], 0
+; CHECK-NEXT:    [[COS:%.*]] = extractvalue { fp128, fp128 } [[SINCOS]], 1
+; CHECK-NEXT:    [[TANL:%.*]] = fdiv reassoc fp128 [[SIN]], [[COS]]
 ; CHECK-NEXT:    ret fp128 [[TANL]]
 ;
   %1 = call reassoc fp128 @llvm.sin.fp128(fp128 %a)
diff --git a/llvm/test/Transforms/InstCombine/may-alias-errno.ll 
b/llvm/test/Transforms/InstCombine/may-alias-errno.ll
index 40fab8024b362..89f5e49cdf581 100644
--- a/llvm/test/Transforms/InstCombine/may-alias-errno.ll
+++ b/llvm/test/Transforms/InstCombine/may-alias-errno.ll
@@ -27,7 +27,7 @@ define float @does_not_alias_errno_2(float %f) {
 ; CHECK-NEXT:    [[P:%.*]] = alloca float, align 4
 ; CHECK-NEXT:    call void @escape(ptr nonnull [[P]])
 ; CHECK-NEXT:    store float 0.000000e+00, ptr [[P]], align 4
-; CHECK-NEXT:    [[TMP1:%.*]] = call float @sinf(float [[F]])
+; CHECK-NEXT:    [[TMP0:%.*]] = call float @sinf(float [[F]])
 ; CHECK-NEXT:    ret float 0.000000e+00
 ;
 entry:
@@ -47,7 +47,7 @@ define double @does_not_alias_errno_3(ptr %p, float %f) {
 ; CHECK-NEXT:  [[ENTRY:.*:]]
 ; CHECK-NEXT:    call void @escape(ptr [[P]])
 ; CHECK-NEXT:    store double 0.000000e+00, ptr [[P]], align 8
-; CHECK-NEXT:    [[TMP1:%.*]] = call float @sinf(float [[F]])
+; CHECK-NEXT:    [[TMP0:%.*]] = call float @sinf(float [[F]])
 ; CHECK-NEXT:    ret double 0.000000e+00
 ;
 entry:

>From ec401836c09861725e5cd543097dddcf21c21c00 Mon Sep 17 00:00:00 2001
From: Kito Cheng <[email protected]>
Date: Mon, 9 Mar 2026 08:33:00 +0800
Subject: [PATCH 6/8] !fixup: Guard sin/cos to intrinsic on
 doesNotAccessMemory, update tests

Only convert sin/cos libcalls to llvm.sin/llvm.cos intrinsics when the
call has memory(none) attribute, preserving errno-setting semantics.
Update affected test CHECK lines across InstCombine and CodeGenOpenCL.
---
 clang/test/CodeGenOpenCL/builtins-f16.cl | 8 ++++++--
 1 file changed, 6 insertions(+), 2 deletions(-)

diff --git a/clang/test/CodeGenOpenCL/builtins-f16.cl 
b/clang/test/CodeGenOpenCL/builtins-f16.cl
index f30ed0a1944ff..a0d9be6c8940b 100644
--- a/clang/test/CodeGenOpenCL/builtins-f16.cl
+++ b/clang/test/CodeGenOpenCL/builtins-f16.cl
@@ -3,6 +3,8 @@
 #pragma OPENCL EXTENSION cl_khr_fp16 : enable
 
 // CHECK-LABEL: define{{.*}} void @test_half_builtins
+// sin and cos with the same argument are combined into sincos
+// CHECK: call { half, half } @llvm.sincos.f16(half %h0)
 void test_half_builtins(half h0, half h1, half h2, int i0) {
   volatile half res;
 
@@ -27,7 +29,8 @@ void test_half_builtins(half h0, half h1, half h2, int i0) {
   // CHECK: call half @llvm.ceil.f16(half %h0)
   res = __builtin_ceilf16(h0);
 
-  // CHECK: call half @llvm.cos.f16(half %h0)
+  // cos result extracted from sincos above
+  // CHECK: store volatile half %cos
   res = __builtin_cosf16(h0);
 
   // CHECK: call half @llvm.cosh.f16(half %h0)
@@ -75,7 +78,8 @@ void test_half_builtins(half h0, half h1, half h2, int i0) {
   // CHECK: call half @llvm.round.f16(half %h0)
   res = __builtin_roundf16(h0);
 
-  // CHECK: call half @llvm.sin.f16(half %h0)
+  // sin result extracted from sincos above
+  // CHECK: store volatile half %sin
   res = __builtin_sinf16(h0);
 
   // CHECK: call half @llvm.sinh.f16(half %h0)

>From e838a85a8da049fb0e54bb3f2ffa8430795146ee Mon Sep 17 00:00:00 2001
From: Kito Cheng <[email protected]>
Date: Mon, 9 Mar 2026 20:45:33 +0800
Subject: [PATCH 7/8] !fixup don't touch unrelated code

---
 llvm/lib/Transforms/Utils/SimplifyLibCalls.cpp | 3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)

diff --git a/llvm/lib/Transforms/Utils/SimplifyLibCalls.cpp 
b/llvm/lib/Transforms/Utils/SimplifyLibCalls.cpp
index 920aac644b9c5..aafdb8cb1a0c4 100644
--- a/llvm/lib/Transforms/Utils/SimplifyLibCalls.cpp
+++ b/llvm/lib/Transforms/Utils/SimplifyLibCalls.cpp
@@ -3051,8 +3051,7 @@ Value *LibCallSimplifier::optimizeSymmetric(CallInst *CI, 
LibFunc Func,
   }
 }
 
-Value *LibCallSimplifier::optimizeSinCosPi(CallInst *CI, bool IsSin,
-                                           IRBuilderBase &B) {
+Value *LibCallSimplifier::optimizeSinCosPi(CallInst *CI, bool IsSin, 
IRBuilderBase &B) {
   // Make sure the prototype is as expected, otherwise the rest of the
   // function is probably invalid and likely to abort.
   if (!isTrigLibCall(CI))

>From c31335bd823c20e552247312dbfb34391ce6fb81 Mon Sep 17 00:00:00 2001
From: Kito Cheng <[email protected]>
Date: Tue, 10 Mar 2026 23:07:32 +0800
Subject: [PATCH 8/8] !fixup use poison rather than undef in testcase

---
 llvm/test/Transforms/InstCombine/sincos.ll | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/llvm/test/Transforms/InstCombine/sincos.ll 
b/llvm/test/Transforms/InstCombine/sincos.ll
index ced643c349fde..021f6fbdbfe8b 100644
--- a/llvm/test/Transforms/InstCombine/sincos.ll
+++ b/llvm/test/Transforms/InstCombine/sincos.ll
@@ -268,7 +268,7 @@ define { float, float } 
@sincos_double_to_float_shrink(float %x) {
 ; CHECK-NEXT:    [[COS:%.*]] = extractvalue { double, double } [[SINCOS]], 1
 ; CHECK-NEXT:    [[ST:%.*]] = fptrunc double [[SIN]] to float
 ; CHECK-NEXT:    [[CT:%.*]] = fptrunc double [[COS]] to float
-; CHECK-NEXT:    [[R0:%.*]] = insertvalue { float, float } undef, float 
[[ST]], 0
+; CHECK-NEXT:    [[R0:%.*]] = insertvalue { float, float } poison, float 
[[ST]], 0
 ; CHECK-NEXT:    [[R1:%.*]] = insertvalue { float, float } [[R0]], float 
[[CT]], 1
 ; CHECK-NEXT:    ret { float, float } [[R1]]
 ;
@@ -281,7 +281,7 @@ define { float, float } 
@sincos_double_to_float_shrink(float %x) {
   %c = call double @cos(double %ext) #0
   %st = fptrunc double %s to float
   %ct = fptrunc double %c to float
-  %r0 = insertvalue { float, float } undef, float %st, 0
+  %r0 = insertvalue { float, float } poison, float %st, 0
   %r1 = insertvalue { float, float } %r0, float %ct, 1
   ret { float, float } %r1
 }

_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to