Skip to content

Commit 24561f4

Browse files
authored
Reland "[InstSimplify] Add basic constant folding for llvm.sincos" (#119192)
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 at the moment. Note: The constant folding does not consider the `afn` fast-math flag and will produce the same result regardless of if the flag is set. This is a reland of #114527 that updates the syntax of one of the tests from: `<float 1.000000e+00, float 1.000000e+00>` to `splat (float 1.000000e+00)`.
1 parent 99f6ca9 commit 24561f4

File tree

2 files changed

+183
-0
lines changed

2 files changed

+183
-0
lines changed

llvm/lib/Analysis/ConstantFolding.cpp

Lines changed: 35 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,40 @@ 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+
Constant *CosResult =
3547+
ConstantFoldScalarCall(Name, Intrinsic::cos, TyScalar, Op, TLI, Call);
3548+
return std::make_pair(SinResult, CosResult);
3549+
};
3550+
3551+
if (auto *FVTy = dyn_cast<FixedVectorType>(Ty)) {
3552+
SmallVector<Constant *> SinResults(FVTy->getNumElements());
3553+
SmallVector<Constant *> CosResults(FVTy->getNumElements());
3554+
3555+
for (unsigned I = 0, E = FVTy->getNumElements(); I != E; ++I) {
3556+
Constant *Lane = Operands[0]->getAggregateElement(I);
3557+
std::tie(SinResults[I], CosResults[I]) =
3558+
ConstantFoldScalarSincosCall(Lane);
3559+
if (!SinResults[I] || !CosResults[I])
3560+
return nullptr;
3561+
}
3562+
3563+
return ConstantStruct::get(StTy, ConstantVector::get(SinResults),
3564+
ConstantVector::get(CosResults));
3565+
}
3566+
3567+
auto [SinResult, CosResult] = ConstantFoldScalarSincosCall(Operands[0]);
3568+
if (!SinResult || !CosResult)
3569+
return nullptr;
3570+
return ConstantStruct::get(StTy, SinResult, CosResult);
3571+
}
35373572
default:
35383573
// TODO: Constant folding of vector intrinsics that fall through here does
35393574
// not work (e.g. overflow intrinsics)
Lines changed: 148 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,148 @@
1+
; RUN: opt -S -passes=instsimplify %s | FileCheck %s
2+
3+
define { float, float } @sincos_zero() {
4+
; CHECK-LABEL: define { float, float } @sincos_zero() {
5+
; CHECK-NEXT: ret { float, float } { float 0.000000e+00, float 1.000000e+00 }
6+
;
7+
%ret = call { float, float } @llvm.sincos.f32(float zeroinitializer)
8+
ret { float, float } %ret
9+
}
10+
11+
define { float, float } @sincos_neg_zero() {
12+
; CHECK-LABEL: define { float, float } @sincos_neg_zero() {
13+
; CHECK-NEXT: ret { float, float } { float -0.000000e+00, float 1.000000e+00 }
14+
;
15+
%ret = call { float, float } @llvm.sincos.f32(float -0.0)
16+
ret { float, float } %ret
17+
}
18+
19+
define { float, float } @sincos_one() {
20+
; CHECK-LABEL: define { float, float } @sincos_one() {
21+
; CHECK-NEXT: ret { float, float } { float [[$SIN_ONE:.+]], float [[$COS_ONE:.+]] }
22+
;
23+
%ret = call { float, float } @llvm.sincos.f32(float 1.0)
24+
ret { float, float } %ret
25+
}
26+
27+
define { float, float } @sincos_two() {
28+
; CHECK-LABEL: define { float, float } @sincos_two() {
29+
; CHECK-NEXT: ret { float, float } { float [[$SIN_TWO:.+]], float [[$COS_TWO:.+]] }
30+
;
31+
%ret = call { float, float } @llvm.sincos.f32(float 2.0)
32+
ret { float, float } %ret
33+
}
34+
35+
define { <2 x float>, <2 x float> } @sincos_vector() {
36+
; CHECK-LABEL: define { <2 x float>, <2 x float> } @sincos_vector() {
37+
; CHECK-NEXT: ret { <2 x float>, <2 x float> } { <2 x float> <float [[$SIN_ONE]], float [[$SIN_TWO]]>, <2 x float> <float [[$COS_ONE]], float [[$COS_TWO]]> }
38+
;
39+
%ret = call { <2 x float>, <2 x float> } @llvm.sincos.v2f32(<2 x float> <float 1.0, float 2.0>)
40+
ret { <2 x float>, <2 x float> } %ret
41+
}
42+
43+
define { <2 x float>, <2 x float> } @sincos_zero_vector() {
44+
; CHECK-LABEL: define { <2 x float>, <2 x float> } @sincos_zero_vector() {
45+
; CHECK-NEXT: ret { <2 x float>, <2 x float> } { <2 x float> zeroinitializer, <2 x float> splat (float 1.000000e+00) }
46+
;
47+
%ret = call { <2 x float>, <2 x float> } @llvm.sincos.v2f32(<2 x float> zeroinitializer)
48+
ret { <2 x float>, <2 x float> } %ret
49+
}
50+
51+
define { float, float } @sincos_poison() {
52+
; CHECK-LABEL: define { float, float } @sincos_poison() {
53+
; CHECK-NEXT: [[RET:%.*]] = call { float, float } @llvm.sincos.f32(float poison)
54+
; CHECK-NEXT: ret { float, float } [[RET]]
55+
;
56+
%ret = call { float, float } @llvm.sincos.f32(float poison)
57+
ret { float, float } %ret
58+
}
59+
60+
define { <2 x float>, <2 x float> } @sincos_poison_vector() {
61+
; CHECK-LABEL: define { <2 x float>, <2 x float> } @sincos_poison_vector() {
62+
; CHECK-NEXT: [[RET:%.*]] = call { <2 x float>, <2 x float> } @llvm.sincos.v2f32(<2 x float> poison)
63+
; CHECK-NEXT: ret { <2 x float>, <2 x float> } [[RET]]
64+
;
65+
%ret = call { <2 x float>, <2 x float> } @llvm.sincos.v2f32(<2 x float> poison)
66+
ret { <2 x float>, <2 x float> } %ret
67+
}
68+
69+
define { <vscale x 2 x float>, <vscale x 2 x float> } @sincos_poison_scalable_vector() {
70+
; CHECK-LABEL: define { <vscale x 2 x float>, <vscale x 2 x float> } @sincos_poison_scalable_vector() {
71+
; CHECK-NEXT: [[RET:%.*]] = call { <vscale x 2 x float>, <vscale x 2 x float> } @llvm.sincos.nxv2f32(<vscale x 2 x float> poison)
72+
; CHECK-NEXT: ret { <vscale x 2 x float>, <vscale x 2 x float> } [[RET]]
73+
;
74+
%ret = call { <vscale x 2 x float>, <vscale x 2 x float> } @llvm.sincos.nxv2f32(<vscale x 2 x float> poison)
75+
ret { <vscale x 2 x float>, <vscale x 2 x float> } %ret
76+
}
77+
78+
define { float, float } @sincos_undef() {
79+
; CHECK-LABEL: define { float, float } @sincos_undef() {
80+
; CHECK-NEXT: [[RET:%.*]] = call { float, float } @llvm.sincos.f32(float undef)
81+
; CHECK-NEXT: ret { float, float } [[RET]]
82+
;
83+
%ret = call { float, float } @llvm.sincos.f32(float undef)
84+
ret { float, float } %ret
85+
}
86+
87+
define { <2 x float>, <2 x float> } @sincos_undef_vector() {
88+
; CHECK-LABEL: define { <2 x float>, <2 x float> } @sincos_undef_vector() {
89+
; CHECK-NEXT: [[RET:%.*]] = call { <2 x float>, <2 x float> } @llvm.sincos.v2f32(<2 x float> undef)
90+
; CHECK-NEXT: ret { <2 x float>, <2 x float> } [[RET]]
91+
;
92+
%ret = call { <2 x float>, <2 x float> } @llvm.sincos.v2f32(<2 x float> undef)
93+
ret { <2 x float>, <2 x float> } %ret
94+
}
95+
96+
define { <vscale x 2 x float>, <vscale x 2 x float> } @sincos_undef_scalable_vector() {
97+
; CHECK-LABEL: define { <vscale x 2 x float>, <vscale x 2 x float> } @sincos_undef_scalable_vector() {
98+
; CHECK-NEXT: [[RET:%.*]] = call { <vscale x 2 x float>, <vscale x 2 x float> } @llvm.sincos.nxv2f32(<vscale x 2 x float> undef)
99+
; CHECK-NEXT: ret { <vscale x 2 x float>, <vscale x 2 x float> } [[RET]]
100+
;
101+
%ret = call { <vscale x 2 x float>, <vscale x 2 x float> } @llvm.sincos.nxv2f32(<vscale x 2 x float> undef)
102+
ret { <vscale x 2 x float>, <vscale x 2 x float> } %ret
103+
}
104+
105+
define { <vscale x 2 x float>, <vscale x 2 x float> } @sincos_zero_scalable_vector() {
106+
; CHECK-LABEL: define { <vscale x 2 x float>, <vscale x 2 x float> } @sincos_zero_scalable_vector() {
107+
; CHECK-NEXT: [[RET:%.*]] = call { <vscale x 2 x float>, <vscale x 2 x float> } @llvm.sincos.nxv2f32(<vscale x 2 x float> zeroinitializer)
108+
; CHECK-NEXT: ret { <vscale x 2 x float>, <vscale x 2 x float> } [[RET]]
109+
;
110+
%ret = call { <vscale x 2 x float>, <vscale x 2 x float> } @llvm.sincos.nxv2f32(<vscale x 2 x float> zeroinitializer)
111+
ret { <vscale x 2 x float>, <vscale x 2 x float> } %ret
112+
}
113+
114+
define { float, float } @sincos_inf() {
115+
; CHECK-LABEL: define { float, float } @sincos_inf() {
116+
; CHECK-NEXT: [[RET:%.*]] = call { float, float } @llvm.sincos.f32(float 0x7FF0000000000000)
117+
; CHECK-NEXT: ret { float, float } [[RET]]
118+
;
119+
%ret = call { float, float } @llvm.sincos.f32(float 0x7FF0000000000000)
120+
ret { float, float } %ret
121+
}
122+
123+
define { float, float } @sincos_neginf() {
124+
; CHECK-LABEL: define { float, float } @sincos_neginf() {
125+
; CHECK-NEXT: [[RET:%.*]] = call { float, float } @llvm.sincos.f32(float 0xFFF0000000000000)
126+
; CHECK-NEXT: ret { float, float } [[RET]]
127+
;
128+
%ret = call { float, float } @llvm.sincos.f32(float 0xFFF0000000000000)
129+
ret { float, float } %ret
130+
}
131+
132+
define { float, float } @sincos_qnan() {
133+
; CHECK-LABEL: define { float, float } @sincos_qnan() {
134+
; CHECK-NEXT: [[RET:%.*]] = call { float, float } @llvm.sincos.f32(float 0x7FF8000000000000)
135+
; CHECK-NEXT: ret { float, float } [[RET]]
136+
;
137+
%ret = call { float, float } @llvm.sincos.f32(float 0x7FF8000000000000)
138+
ret { float, float } %ret
139+
}
140+
141+
define { float, float } @sincos_snan() {
142+
; CHECK-LABEL: define { float, float } @sincos_snan() {
143+
; CHECK-NEXT: [[RET:%.*]] = call { float, float } @llvm.sincos.f32(float 0x7FF0000020000000)
144+
; CHECK-NEXT: ret { float, float } [[RET]]
145+
;
146+
%ret = call { float, float } @llvm.sincos.f32(float bitcast (i32 2139095041 to float))
147+
ret { float, float } %ret
148+
}

0 commit comments

Comments
 (0)