Skip to content

Commit e5699a9

Browse files
committed
[InstSimplify] Add basic constant folding for llvm.sincos
This calls into the existing constant folding for `llvm.sin` and `llvm.cos`, which currently does not fold for any non-finite values, so most tests are negative tests.
1 parent f9d6d46 commit e5699a9

File tree

2 files changed

+164
-0
lines changed

2 files changed

+164
-0
lines changed

llvm/lib/Analysis/ConstantFolding.cpp

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1632,6 +1632,7 @@ bool llvm::canConstantFoldCallTo(const CallBase *Call, const Function *F) {
16321632
case Intrinsic::sqrt:
16331633
case Intrinsic::sin:
16341634
case Intrinsic::cos:
1635+
case Intrinsic::sincos:
16351636
case Intrinsic::pow:
16361637
case Intrinsic::powi:
16371638
case Intrinsic::ldexp:
@@ -3534,6 +3535,44 @@ ConstantFoldStructCall(StringRef Name, Intrinsic::ID IntrinsicID,
35343535
return nullptr;
35353536
return ConstantStruct::get(StTy, Result0, Result1);
35363537
}
3538+
case Intrinsic::sincos: {
3539+
Type *Ty = StTy->getContainedType(0);
3540+
Type *TyScalar = Ty->getScalarType();
3541+
3542+
auto ConstantFoldScalarSincosCall =
3543+
[&](Constant *Op) -> std::pair<Constant *, Constant *> {
3544+
Constant *SinResult =
3545+
ConstantFoldScalarCall(Name, Intrinsic::sin, TyScalar, Op, TLI, Call);
3546+
if (!SinResult)
3547+
return {};
3548+
Constant *CosResult =
3549+
ConstantFoldScalarCall(Name, Intrinsic::cos, TyScalar, Op, TLI, Call);
3550+
if (!CosResult)
3551+
return {};
3552+
return std::make_pair(SinResult, CosResult);
3553+
};
3554+
3555+
if (auto *FVTy = dyn_cast<FixedVectorType>(Ty)) {
3556+
SmallVector<Constant *, 4> SinResults(FVTy->getNumElements());
3557+
SmallVector<Constant *, 4> CosResults(FVTy->getNumElements());
3558+
3559+
for (unsigned I = 0, E = FVTy->getNumElements(); I != E; ++I) {
3560+
Constant *Lane = Operands[0]->getAggregateElement(I);
3561+
std::tie(SinResults[I], CosResults[I]) =
3562+
ConstantFoldScalarSincosCall(Lane);
3563+
if (!SinResults[I])
3564+
return nullptr;
3565+
}
3566+
3567+
return ConstantStruct::get(StTy, ConstantVector::get(SinResults),
3568+
ConstantVector::get(CosResults));
3569+
}
3570+
3571+
auto [SinResult, CosResult] = ConstantFoldScalarSincosCall(Operands[0]);
3572+
if (!SinResult)
3573+
return nullptr;
3574+
return ConstantStruct::get(StTy, SinResult, CosResult);
3575+
}
35373576
default:
35383577
// TODO: Constant folding of vector intrinsics that fall through here does
35393578
// not work (e.g. overflow intrinsics)
Lines changed: 125 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,125 @@
1+
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 3
2+
; RUN: opt -S -passes=instsimplify %s | FileCheck %s
3+
4+
define { float, float } @sincos_zero() {
5+
; CHECK-LABEL: define { float, float } @sincos_zero() {
6+
; CHECK-NEXT: ret { float, float } { float 0.000000e+00, float 1.000000e+00 }
7+
;
8+
%ret = call { float, float } @llvm.sincos.f32(float zeroinitializer)
9+
ret { float, float } %ret
10+
}
11+
12+
define { float, float } @sincos_neg_zero() {
13+
; CHECK-LABEL: define { float, float } @sincos_neg_zero() {
14+
; CHECK-NEXT: ret { float, float } { float -0.000000e+00, float 1.000000e+00 }
15+
;
16+
%ret = call { float, float } @llvm.sincos.f32(float -0.0)
17+
ret { float, float } %ret
18+
}
19+
20+
define { <2 x float>, <2 x float> } @sincos_zero_vector() {
21+
; CHECK-LABEL: define { <2 x float>, <2 x float> } @sincos_zero_vector() {
22+
; CHECK-NEXT: ret { <2 x float>, <2 x float> } { <2 x float> zeroinitializer, <2 x float> <float 1.000000e+00, float 1.000000e+00> }
23+
;
24+
%ret = call { <2 x float>, <2 x float> } @llvm.sincos.v2f32(<2 x float> zeroinitializer)
25+
ret { <2 x float>, <2 x float> } %ret
26+
}
27+
28+
define { float, float } @sincos_poison() {
29+
; CHECK-LABEL: define { float, float } @sincos_poison() {
30+
; CHECK-NEXT: [[RET:%.*]] = call { float, float } @llvm.sincos.f32(float poison)
31+
; CHECK-NEXT: ret { float, float } [[RET]]
32+
;
33+
%ret = call { float, float } @llvm.sincos.f32(float poison)
34+
ret { float, float } %ret
35+
}
36+
37+
define { <2 x float>, <2 x float> } @sincos_poison_vector() {
38+
; CHECK-LABEL: define { <2 x float>, <2 x float> } @sincos_poison_vector() {
39+
; CHECK-NEXT: [[RET:%.*]] = call { <2 x float>, <2 x float> } @llvm.sincos.v2f32(<2 x float> poison)
40+
; CHECK-NEXT: ret { <2 x float>, <2 x float> } [[RET]]
41+
;
42+
%ret = call { <2 x float>, <2 x float> } @llvm.sincos.v2f32(<2 x float> poison)
43+
ret { <2 x float>, <2 x float> } %ret
44+
}
45+
46+
define { <vscale x 2 x float>, <vscale x 2 x float> } @sincos_poison_scalable_vector() {
47+
; CHECK-LABEL: define { <vscale x 2 x float>, <vscale x 2 x float> } @sincos_poison_scalable_vector() {
48+
; CHECK-NEXT: [[RET:%.*]] = call { <vscale x 2 x float>, <vscale x 2 x float> } @llvm.sincos.nxv2f32(<vscale x 2 x float> poison)
49+
; CHECK-NEXT: ret { <vscale x 2 x float>, <vscale x 2 x float> } [[RET]]
50+
;
51+
%ret = call { <vscale x 2 x float>, <vscale x 2 x float> } @llvm.sincos.nxv2f32(<vscale x 2 x float> poison)
52+
ret { <vscale x 2 x float>, <vscale x 2 x float> } %ret
53+
}
54+
55+
define { float, float } @sincos_undef() {
56+
; CHECK-LABEL: define { float, float } @sincos_undef() {
57+
; CHECK-NEXT: [[RET:%.*]] = call { float, float } @llvm.sincos.f32(float undef)
58+
; CHECK-NEXT: ret { float, float } [[RET]]
59+
;
60+
%ret = call { float, float } @llvm.sincos.f32(float undef)
61+
ret { float, float } %ret
62+
}
63+
64+
define { <2 x float>, <2 x float> } @sincos_undef_vector() {
65+
; CHECK-LABEL: define { <2 x float>, <2 x float> } @sincos_undef_vector() {
66+
; CHECK-NEXT: [[RET:%.*]] = call { <2 x float>, <2 x float> } @llvm.sincos.v2f32(<2 x float> undef)
67+
; CHECK-NEXT: ret { <2 x float>, <2 x float> } [[RET]]
68+
;
69+
%ret = call { <2 x float>, <2 x float> } @llvm.sincos.v2f32(<2 x float> undef)
70+
ret { <2 x float>, <2 x float> } %ret
71+
}
72+
73+
define { <vscale x 2 x float>, <vscale x 2 x float> } @sincos_undef_scalable_vector() {
74+
; CHECK-LABEL: define { <vscale x 2 x float>, <vscale x 2 x float> } @sincos_undef_scalable_vector() {
75+
; CHECK-NEXT: [[RET:%.*]] = call { <vscale x 2 x float>, <vscale x 2 x float> } @llvm.sincos.nxv2f32(<vscale x 2 x float> undef)
76+
; CHECK-NEXT: ret { <vscale x 2 x float>, <vscale x 2 x float> } [[RET]]
77+
;
78+
%ret = call { <vscale x 2 x float>, <vscale x 2 x float> } @llvm.sincos.nxv2f32(<vscale x 2 x float> undef)
79+
ret { <vscale x 2 x float>, <vscale x 2 x float> } %ret
80+
}
81+
82+
define { <vscale x 2 x float>, <vscale x 2 x float> } @sincos_zero_scalable_vector() {
83+
; CHECK-LABEL: define { <vscale x 2 x float>, <vscale x 2 x float> } @sincos_zero_scalable_vector() {
84+
; CHECK-NEXT: [[RET:%.*]] = call { <vscale x 2 x float>, <vscale x 2 x float> } @llvm.sincos.nxv2f32(<vscale x 2 x float> zeroinitializer)
85+
; CHECK-NEXT: ret { <vscale x 2 x float>, <vscale x 2 x float> } [[RET]]
86+
;
87+
%ret = call { <vscale x 2 x float>, <vscale x 2 x float> } @llvm.sincos.nxv2f32(<vscale x 2 x float> zeroinitializer)
88+
ret { <vscale x 2 x float>, <vscale x 2 x float> } %ret
89+
}
90+
91+
define { float, float } @sincos_inf() {
92+
; CHECK-LABEL: define { float, float } @sincos_inf() {
93+
; CHECK-NEXT: [[RET:%.*]] = call { float, float } @llvm.sincos.f32(float 0x7FF0000000000000)
94+
; CHECK-NEXT: ret { float, float } [[RET]]
95+
;
96+
%ret = call { float, float } @llvm.sincos.f32(float 0x7FF0000000000000)
97+
ret { float, float } %ret
98+
}
99+
100+
define { float, float } @sincos_neginf() {
101+
; CHECK-LABEL: define { float, float } @sincos_neginf() {
102+
; CHECK-NEXT: [[RET:%.*]] = call { float, float } @llvm.sincos.f32(float 0xFFF0000000000000)
103+
; CHECK-NEXT: ret { float, float } [[RET]]
104+
;
105+
%ret = call { float, float } @llvm.sincos.f32(float 0xFFF0000000000000)
106+
ret { float, float } %ret
107+
}
108+
109+
define { float, float } @sincos_qnam() {
110+
; CHECK-LABEL: define { float, float } @sincos_qnam() {
111+
; CHECK-NEXT: [[RET:%.*]] = call { float, float } @llvm.sincos.f32(float 0x7FF8000000000000)
112+
; CHECK-NEXT: ret { float, float } [[RET]]
113+
;
114+
%ret = call { float, float } @llvm.sincos.f32(float 0x7FF8000000000000)
115+
ret { float, float } %ret
116+
}
117+
118+
define { float, float } @sincos_snam() {
119+
; CHECK-LABEL: define { float, float } @sincos_snam() {
120+
; CHECK-NEXT: [[RET:%.*]] = call { float, float } @llvm.sincos.f32(float 0x7FF0000020000000)
121+
; CHECK-NEXT: ret { float, float } [[RET]]
122+
;
123+
%ret = call { float, float } @llvm.sincos.f32(float bitcast (i32 2139095041 to float))
124+
ret { float, float } %ret
125+
}

0 commit comments

Comments
 (0)