1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2; RUN: opt < %s -instcombine -S                             | FileCheck %s --check-prefixes=ANY,NO-FLOAT-SHRINK
3; RUN: opt < %s -instcombine -enable-double-float-shrink -S | FileCheck %s --check-prefixes=ANY,DO-FLOAT-SHRINK
4
5target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64-S128"
6
7declare double @cos(double)
8declare double @llvm.cos.f64(double)
9declare float @cosf(float)
10declare float @llvm.cos.f32(float)
11
12declare double @sin(double)
13declare double @llvm.sin.f64(double)
14declare float @sinf(float)
15declare float @llvm.sin.f32(float)
16
17declare double @tan(double)
18declare fp128 @tanl(fp128)
19
20; cos(-x) -> cos(x);
21
22define double @cos_negated_arg(double %x) {
23; ANY-LABEL: @cos_negated_arg(
24; ANY-NEXT:    [[COS:%.*]] = call double @cos(double [[X:%.*]])
25; ANY-NEXT:    ret double [[COS]]
26;
27  %neg = fsub double -0.0, %x
28  %r = call double @cos(double %neg)
29  ret double %r
30}
31
32define double @cos_unary_negated_arg(double %x) {
33; ANY-LABEL: @cos_unary_negated_arg(
34; ANY-NEXT:    [[COS:%.*]] = call double @cos(double [[X:%.*]])
35; ANY-NEXT:    ret double [[COS]]
36;
37  %neg = fneg double %x
38  %r = call double @cos(double %neg)
39  ret double %r
40}
41
42define float @cosf_negated_arg(float %x) {
43; ANY-LABEL: @cosf_negated_arg(
44; ANY-NEXT:    [[COS:%.*]] = call float @cosf(float [[X:%.*]])
45; ANY-NEXT:    ret float [[COS]]
46;
47  %neg = fsub float -0.0, %x
48  %r = call float @cosf(float %neg)
49  ret float %r
50}
51
52define float @cosf_unary_negated_arg(float %x) {
53; ANY-LABEL: @cosf_unary_negated_arg(
54; ANY-NEXT:    [[COS:%.*]] = call float @cosf(float [[X:%.*]])
55; ANY-NEXT:    ret float [[COS]]
56;
57  %neg = fneg float %x
58  %r = call float @cosf(float %neg)
59  ret float %r
60}
61
62define float @cosf_negated_arg_FMF(float %x) {
63; ANY-LABEL: @cosf_negated_arg_FMF(
64; ANY-NEXT:    [[COS:%.*]] = call reassoc nnan float @cosf(float [[X:%.*]])
65; ANY-NEXT:    ret float [[COS]]
66;
67  %neg = fsub float -0.0, %x
68  %r = call nnan reassoc float @cosf(float %neg)
69  ret float %r
70}
71
72define float @cosf_unary_negated_arg_FMF(float %x) {
73; ANY-LABEL: @cosf_unary_negated_arg_FMF(
74; ANY-NEXT:    [[COS:%.*]] = call reassoc nnan float @cosf(float [[X:%.*]])
75; ANY-NEXT:    ret float [[COS]]
76;
77  %neg = fneg float %x
78  %r = call nnan reassoc float @cosf(float %neg)
79  ret float %r
80}
81
82; sin(-x) -> -sin(x);
83
84define double @sin_negated_arg(double %x) {
85; ANY-LABEL: @sin_negated_arg(
86; ANY-NEXT:    [[TMP1:%.*]] = call double @sin(double [[X:%.*]])
87; ANY-NEXT:    [[TMP2:%.*]] = fneg double [[TMP1]]
88; ANY-NEXT:    ret double [[TMP2]]
89;
90  %neg = fsub double -0.0, %x
91  %r = call double @sin(double %neg)
92  ret double %r
93}
94
95define double @sin_unary_negated_arg(double %x) {
96; ANY-LABEL: @sin_unary_negated_arg(
97; ANY-NEXT:    [[TMP1:%.*]] = call double @sin(double [[X:%.*]])
98; ANY-NEXT:    [[TMP2:%.*]] = fneg double [[TMP1]]
99; ANY-NEXT:    ret double [[TMP2]]
100;
101  %neg = fneg double %x
102  %r = call double @sin(double %neg)
103  ret double %r
104}
105
106define float @sinf_negated_arg(float %x) {
107; ANY-LABEL: @sinf_negated_arg(
108; ANY-NEXT:    [[TMP1:%.*]] = call float @sinf(float [[X:%.*]])
109; ANY-NEXT:    [[TMP2:%.*]] = fneg float [[TMP1]]
110; ANY-NEXT:    ret float [[TMP2]]
111;
112  %neg = fsub float -0.0, %x
113  %r = call float @sinf(float %neg)
114  ret float %r
115}
116
117define float @sinf_unary_negated_arg(float %x) {
118; ANY-LABEL: @sinf_unary_negated_arg(
119; ANY-NEXT:    [[TMP1:%.*]] = call float @sinf(float [[X:%.*]])
120; ANY-NEXT:    [[TMP2:%.*]] = fneg float [[TMP1]]
121; ANY-NEXT:    ret float [[TMP2]]
122;
123  %neg = fneg float %x
124  %r = call float @sinf(float %neg)
125  ret float %r
126}
127
128define float @sinf_negated_arg_FMF(float %x) {
129; ANY-LABEL: @sinf_negated_arg_FMF(
130; ANY-NEXT:    [[TMP1:%.*]] = call nnan afn float @sinf(float [[X:%.*]])
131; ANY-NEXT:    [[TMP2:%.*]] = fneg nnan afn float [[TMP1]]
132; ANY-NEXT:    ret float [[TMP2]]
133;
134  %neg = fsub ninf float -0.0, %x
135  %r = call afn nnan float @sinf(float %neg)
136  ret float %r
137}
138
139define float @sinf_unary_negated_arg_FMF(float %x) {
140; ANY-LABEL: @sinf_unary_negated_arg_FMF(
141; ANY-NEXT:    [[TMP1:%.*]] = call nnan afn float @sinf(float [[X:%.*]])
142; ANY-NEXT:    [[TMP2:%.*]] = fneg nnan afn float [[TMP1]]
143; ANY-NEXT:    ret float [[TMP2]]
144;
145  %neg = fneg ninf float %x
146  %r = call afn nnan float @sinf(float %neg)
147  ret float %r
148}
149
150declare void @use(double)
151
152define double @sin_negated_arg_extra_use(double %x) {
153; ANY-LABEL: @sin_negated_arg_extra_use(
154; ANY-NEXT:    [[NEG:%.*]] = fneg double [[X:%.*]]
155; ANY-NEXT:    [[R:%.*]] = call double @sin(double [[NEG]])
156; ANY-NEXT:    call void @use(double [[NEG]])
157; ANY-NEXT:    ret double [[R]]
158;
159  %neg = fsub double -0.0, %x
160  %r = call double @sin(double %neg)
161  call void @use(double %neg)
162  ret double %r
163}
164
165define double @sin_unary_negated_arg_extra_use(double %x) {
166; ANY-LABEL: @sin_unary_negated_arg_extra_use(
167; ANY-NEXT:    [[NEG:%.*]] = fneg double [[X:%.*]]
168; ANY-NEXT:    [[R:%.*]] = call double @sin(double [[NEG]])
169; ANY-NEXT:    call void @use(double [[NEG]])
170; ANY-NEXT:    ret double [[R]]
171;
172  %neg = fneg double %x
173  %r = call double @sin(double %neg)
174  call void @use(double %neg)
175  ret double %r
176}
177
178; -sin(-x) --> sin(x)
179; PR38458: https://bugs.llvm.org/show_bug.cgi?id=38458
180
181define double @neg_sin_negated_arg(double %x) {
182; ANY-LABEL: @neg_sin_negated_arg(
183; ANY-NEXT:    [[TMP1:%.*]] = call double @sin(double [[X:%.*]])
184; ANY-NEXT:    ret double [[TMP1]]
185;
186  %neg = fsub double -0.0, %x
187  %r = call double @sin(double %neg)
188  %rn = fsub double -0.0, %r
189  ret double %rn
190}
191
192define double @unary_neg_sin_unary_negated_arg(double %x) {
193; ANY-LABEL: @unary_neg_sin_unary_negated_arg(
194; ANY-NEXT:    [[TMP1:%.*]] = call double @sin(double [[X:%.*]])
195; ANY-NEXT:    ret double [[TMP1]]
196;
197  %neg = fneg double %x
198  %r = call double @sin(double %neg)
199  %rn = fneg double %r
200  ret double %rn
201}
202
203define double @neg_sin_unary_negated_arg(double %x) {
204; ANY-LABEL: @neg_sin_unary_negated_arg(
205; ANY-NEXT:    [[TMP1:%.*]] = call double @sin(double [[X:%.*]])
206; ANY-NEXT:    ret double [[TMP1]]
207;
208  %neg = fsub double -0.0, %x
209  %r = call double @sin(double %neg)
210  %rn = fneg double %r
211  ret double %rn
212}
213
214define double @unary_neg_sin_negated_arg(double %x) {
215; ANY-LABEL: @unary_neg_sin_negated_arg(
216; ANY-NEXT:    [[TMP1:%.*]] = call double @sin(double [[X:%.*]])
217; ANY-NEXT:    ret double [[TMP1]]
218;
219  %neg = fneg double %x
220  %r = call double @sin(double %neg)
221  %rn = fsub double -0.0, %r
222  ret double %rn
223}
224
225; tan(-x) -> -tan(x);
226
227define double @tan_negated_arg(double %x) {
228; ANY-LABEL: @tan_negated_arg(
229; ANY-NEXT:    [[TMP1:%.*]] = call double @tan(double [[X:%.*]])
230; ANY-NEXT:    [[TMP2:%.*]] = fneg double [[TMP1]]
231; ANY-NEXT:    ret double [[TMP2]]
232;
233  %neg = fsub double -0.0, %x
234  %r = call double @tan(double %neg)
235  ret double %r
236}
237
238define double @tan_unary_negated_arg(double %x) {
239; ANY-LABEL: @tan_unary_negated_arg(
240; ANY-NEXT:    [[TMP1:%.*]] = call double @tan(double [[X:%.*]])
241; ANY-NEXT:    [[TMP2:%.*]] = fneg double [[TMP1]]
242; ANY-NEXT:    ret double [[TMP2]]
243;
244  %neg = fneg double %x
245  %r = call double @tan(double %neg)
246  ret double %r
247}
248
249; tanl(-x) -> -tanl(x);
250
251define fp128 @tanl_negated_arg(fp128 %x) {
252; ANY-LABEL: @tanl_negated_arg(
253; ANY-NEXT:    [[TMP1:%.*]] = call fp128 @tanl(fp128 [[X:%.*]])
254; ANY-NEXT:    [[TMP2:%.*]] = fneg fp128 [[TMP1]]
255; ANY-NEXT:    ret fp128 [[TMP2]]
256;
257  %neg = fsub fp128 0xL00000000000000008000000000000000, %x
258  %r = call fp128 @tanl(fp128 %neg)
259  ret fp128 %r
260}
261
262define fp128 @tanl_unary_negated_arg(fp128 %x) {
263; ANY-LABEL: @tanl_unary_negated_arg(
264; ANY-NEXT:    [[TMP1:%.*]] = call fp128 @tanl(fp128 [[X:%.*]])
265; ANY-NEXT:    [[TMP2:%.*]] = fneg fp128 [[TMP1]]
266; ANY-NEXT:    ret fp128 [[TMP2]]
267;
268  %neg = fneg fp128 %x
269  %r = call fp128 @tanl(fp128 %neg)
270  ret fp128 %r
271}
272
273define float @negated_and_shrinkable_libcall(float %f) {
274; NO-FLOAT-SHRINK-LABEL: @negated_and_shrinkable_libcall(
275; NO-FLOAT-SHRINK-NEXT:    [[CONV1:%.*]] = fpext float [[F:%.*]] to double
276; NO-FLOAT-SHRINK-NEXT:    [[COS1:%.*]] = call double @cos(double [[CONV1]])
277; NO-FLOAT-SHRINK-NEXT:    [[CONV2:%.*]] = fptrunc double [[COS1]] to float
278; NO-FLOAT-SHRINK-NEXT:    ret float [[CONV2]]
279;
280; DO-FLOAT-SHRINK-LABEL: @negated_and_shrinkable_libcall(
281; DO-FLOAT-SHRINK-NEXT:    [[COSF:%.*]] = call float @cosf(float [[F:%.*]])
282; DO-FLOAT-SHRINK-NEXT:    ret float [[COSF]]
283;
284  %conv1 = fpext float %f to double
285  %neg = fsub double -0.0, %conv1
286  %cos = call double @cos(double %neg)
287  %conv2 = fptrunc double %cos to float
288  ret float %conv2
289}
290
291define float @unary_negated_and_shrinkable_libcall(float %f) {
292; NO-FLOAT-SHRINK-LABEL: @unary_negated_and_shrinkable_libcall(
293; NO-FLOAT-SHRINK-NEXT:    [[CONV1:%.*]] = fpext float [[F:%.*]] to double
294; NO-FLOAT-SHRINK-NEXT:    [[COS1:%.*]] = call double @cos(double [[CONV1]])
295; NO-FLOAT-SHRINK-NEXT:    [[CONV2:%.*]] = fptrunc double [[COS1]] to float
296; NO-FLOAT-SHRINK-NEXT:    ret float [[CONV2]]
297;
298; DO-FLOAT-SHRINK-LABEL: @unary_negated_and_shrinkable_libcall(
299; DO-FLOAT-SHRINK-NEXT:    [[COSF:%.*]] = call float @cosf(float [[F:%.*]])
300; DO-FLOAT-SHRINK-NEXT:    ret float [[COSF]]
301;
302  %conv1 = fpext float %f to double
303  %neg = fneg double %conv1
304  %cos = call double @cos(double %neg)
305  %conv2 = fptrunc double %cos to float
306  ret float %conv2
307}
308
309; TODO: It was ok to shrink the libcall, so the intrinsic should shrink too?
310
311define float @negated_and_shrinkable_intrinsic(float %f) {
312; ANY-LABEL: @negated_and_shrinkable_intrinsic(
313; ANY-NEXT:    [[CONV1:%.*]] = fpext float [[F:%.*]] to double
314; ANY-NEXT:    [[COS:%.*]] = call double @llvm.cos.f64(double [[CONV1]])
315; ANY-NEXT:    [[CONV2:%.*]] = fptrunc double [[COS]] to float
316; ANY-NEXT:    ret float [[CONV2]]
317;
318  %conv1 = fpext float %f to double
319  %neg = fsub double -0.0, %conv1
320  %cos = call double @llvm.cos.f64(double %neg)
321  %conv2 = fptrunc double %cos to float
322  ret float %conv2
323}
324
325define float @unary_negated_and_shrinkable_intrinsic(float %f) {
326; ANY-LABEL: @unary_negated_and_shrinkable_intrinsic(
327; ANY-NEXT:    [[CONV1:%.*]] = fpext float [[F:%.*]] to double
328; ANY-NEXT:    [[COS:%.*]] = call double @llvm.cos.f64(double [[CONV1]])
329; ANY-NEXT:    [[CONV2:%.*]] = fptrunc double [[COS]] to float
330; ANY-NEXT:    ret float [[CONV2]]
331;
332  %conv1 = fpext float %f to double
333  %neg = fneg double %conv1
334  %cos = call double @llvm.cos.f64(double %neg)
335  %conv2 = fptrunc double %cos to float
336  ret float %conv2
337}
338