[clang] [llvm] Reland "[InstCombine] Combine llvm.sin/llvm.cos libcall pairs into llvm.sincos" (PR #194616)
via llvm-commits
llvm-commits at lists.llvm.org
Tue Apr 28 06:29:20 PDT 2026
llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-llvm-transforms
Author: Kito Cheng (kito-cheng)
<details>
<summary>Changes</summary>
This reland #<!-- -->184760
Fixed https://lab.llvm.org/buildbot/#/builders/123/builds/39337
The root cause is new created llvm.sincos is inserted into the right
after of the sin/cos's argument, however we didn't check if it's PHI, it
may cause it inserted into the middle of PHIs, and then fail the
verification.
Teach InstCombine to recognize pairs of `llvm.sin(x)` and `llvm.cos(x)`
intrinsic calls that share the same argument and replace them with a
single `llvm.sincos(x)` call, extracting the individual results.
The optimization works in two phases:
1. **SimplifyLibCalls**: Convert `sin`/`cos` C library calls (e.g.
`sinf`, `cosf`, `sin`, `cos`, `sinl`, `cosl`) into `llvm.sin` /
`llvm.cos` intrinsics when the call does not access memory (i.e. does
not set `errno`). This normalization step brings library calls into
the same form as compiler-generated intrinsics.
2. **InstCombineCalls**: When visiting an `llvm.sin` or `llvm.cos`
intrinsic, scan the users of the shared argument for a matching
counterpart. If found, emit a single `llvm.sincos` call placed right
after the argument definition, replace both original calls, and erase
the matched instruction.
Also remove the completed sincos TODO from Target/README.txt.
---
Patch is 48.65 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/194616.diff
10 Files Affected:
- (modified) clang/test/CodeGenOpenCL/builtins-f16.cl (+13-6)
- (modified) llvm/lib/Target/README.txt (-15)
- (modified) llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp (+73)
- (modified) llvm/lib/Transforms/Utils/SimplifyLibCalls.cpp (+20-2)
- (modified) llvm/test/Transforms/InstCombine/AMDGPU/tan.ll (+1-2)
- (modified) llvm/test/Transforms/InstCombine/fdiv-cos-sin.ll (+32-18)
- (modified) llvm/test/Transforms/InstCombine/fdiv-sin-cos.ll (+29-11)
- (modified) llvm/test/Transforms/InstCombine/may-alias-errno.ll (+2-2)
- (added) llvm/test/Transforms/InstCombine/sincos-fpmath.ll (+77)
- (added) llvm/test/Transforms/InstCombine/sincos.ll (+472)
``````````diff
diff --git a/clang/test/CodeGenOpenCL/builtins-f16.cl b/clang/test/CodeGenOpenCL/builtins-f16.cl
index f30ed0a1944ff..a534cf5e9050f 100644
--- a/clang/test/CodeGenOpenCL/builtins-f16.cl
+++ b/clang/test/CodeGenOpenCL/builtins-f16.cl
@@ -27,9 +27,6 @@ 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)
- res = __builtin_cosf16(h0);
-
// CHECK: call half @llvm.cosh.f16(half %h0)
res = __builtin_coshf16(h0);
@@ -75,9 +72,6 @@ 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)
- res = __builtin_sinf16(h0);
-
// CHECK: call half @llvm.sinh.f16(half %h0)
res = __builtin_sinhf16(h0);
@@ -99,3 +93,16 @@ void test_half_builtins(half h0, half h1, half h2, int i0) {
// CHECK: call half @llvm.ldexp.f16.i32(half %h0, i32 %i0)
res = __builtin_ldexpf16(h0, i0);
}
+
+// sin and cos are split into separate functions to avoid sincos combining.
+// CHECK-LABEL: define{{.*}} half @test_half_sin
+// CHECK: call half @llvm.sin.f16(half %h0)
+half test_half_sin(half h0) {
+ return __builtin_sinf16(h0);
+}
+
+// CHECK-LABEL: define{{.*}} half @test_half_cos
+// CHECK: call half @llvm.cos.f16(half %h0)
+half test_half_cos(half h0) {
+ return __builtin_cosf16(h0);
+}
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/InstCombine/InstCombineCalls.cpp b/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp
index 131982ad7c1d2..8a213794862b8 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp
@@ -1881,6 +1881,71 @@ 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 result for II
+// extracted from sincos, or nullptr if no match is found.
+static Value *foldSinAndCosToSinCos(IntrinsicInst *II, IRBuilderBase &B,
+ InstCombinerImpl &IC) {
+ 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 nullptr;
+
+ // 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) {
+ Match = Cand;
+ break;
+ }
+ }
+ }
+
+ if (!Match)
+ return nullptr;
+
+ // Insert sincos right after the argument definition.
+ IRBuilderBase::InsertPointGuard Guard(B);
+ if (auto *ArgInst = dyn_cast<Instruction>(Arg)) {
+ BasicBlock *ArgBB = ArgInst->getParent();
+ // Need skip whole PHIs if Arg is PHI to prevent insert in the middle
+ // of PHIs.
+ if (isa<PHINode>(ArgInst))
+ B.SetInsertPoint(ArgBB, ArgBB->getFirstInsertionPt());
+ else
+ B.SetInsertPoint(ArgBB, 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());
+ CallInst *SinCos = B.CreateCall(SinCosFunc, Arg, "sincos");
+ // Intersect fast-math flags from the two calls.
+ SinCos->setFastMathFlags(II->getFastMathFlags() & Match->getFastMathFlags());
+ // Propagate the most-generic fpmath metadata from the two original calls.
+ if (MDNode *MD = MDNode::getMostGenericFPMath(
+ II->getMetadata(LLVMContext::MD_fpmath),
+ Match->getMetadata(LLVMContext::MD_fpmath)))
+ SinCos->setMetadata(LLVMContext::MD_fpmath, MD);
+ Value *Sin = B.CreateExtractValue(SinCos, 0, "sin");
+ Value *Cos = B.CreateExtractValue(SinCos, 1, "cos");
+
+ // Replace the matching call and erase it.
+ IC.replaceInstUsesWith(*Match, IsSin ? Cos : Sin);
+ IC.eraseInstFromFunction(*Match);
+ return IsSin ? Sin : Cos;
+}
+
/// CallInst simplification. This mostly only handles folding of intrinsic
/// instructions. For normal calls, it allows visitCallBase to do the heavy
/// lifting.
@@ -3181,6 +3246,10 @@ Instruction *InstCombinerImpl::visitCallInst(CallInst &CI) {
// for f in {cos, cosh}
return replaceOperand(*II, 0, X);
}
+ if (IID == Intrinsic::cos) {
+ if (Value *Result = foldSinAndCosToSinCos(II, Builder, *this))
+ return replaceInstUsesWith(*II, Result);
+ }
break;
}
case Intrinsic::sin:
@@ -3195,6 +3264,10 @@ Instruction *InstCombinerImpl::visitCallInst(CallInst &CI) {
Value *NewFunc = Builder.CreateUnaryIntrinsic(IID, X, II);
return UnaryOperator::CreateFNegFMF(NewFunc, II);
}
+ if (IID == Intrinsic::sin) {
+ if (Value *Result = foldSinAndCosToSinCos(II, Builder, *this))
+ 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 b60f0c7021d51..fdb142f5af350 100644
--- a/llvm/lib/Transforms/Utils/SimplifyLibCalls.cpp
+++ b/llvm/lib/Transforms/Utils/SimplifyLibCalls.cpp
@@ -4043,6 +4043,16 @@ Value *LibCallSimplifier::optimizeFloatingPointLibCall(CallInst *CI,
case LibFunc_cospif:
case LibFunc_cospi:
return optimizeSinCosPi(CI, /*IsSin*/false, Builder);
+ case LibFunc_sinf:
+ case LibFunc_sinl:
+ if (CI->doesNotAccessMemory())
+ return replaceUnaryCall(CI, Builder, Intrinsic::sin);
+ return nullptr;
+ case LibFunc_cosf:
+ case LibFunc_cosl:
+ if (CI->doesNotAccessMemory())
+ return replaceUnaryCall(CI, Builder, Intrinsic::cos);
+ return nullptr;
case LibFunc_powf:
case LibFunc_pow:
case LibFunc_powl:
@@ -4109,6 +4119,16 @@ 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;
+ 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:
@@ -4117,8 +4137,6 @@ Value *LibCallSimplifier::optimizeFloatingPointLibCall(CallInst *CI,
case LibFunc_exp:
case LibFunc_exp10:
case LibFunc_expm1:
- case LibFunc_cos:
- case LibFunc_sin:
case LibFunc_tanh:
if (UnsafeFPShrink && hasFloatVersion(M, CI->getCalledFunction()->getName()))
return optimizeUnaryDoubleFP(CI, Builder, TLI, true);
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..2450f4b54dcab 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 reassoc { 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 reassoc { 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 reassoc { 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 reassoc { 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 reassoc { 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..edfc1036014c7 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 reassoc { 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 reassoc { 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:%.*]]) #...
[truncated]
``````````
</details>
https://github.com/llvm/llvm-project/pull/194616
More information about the llvm-commits
mailing list