• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2; RUN: opt < %s -instcombine -S | FileCheck %s
3
4; PR4374
5
6define float @test1(float %x, float %y) {
7; CHECK-LABEL: @test1(
8; CHECK-NEXT:    [[T1:%.*]] = fsub float [[X:%.*]], [[Y:%.*]]
9; CHECK-NEXT:    [[T2:%.*]] = fsub float -0.000000e+00, [[T1]]
10; CHECK-NEXT:    ret float [[T2]]
11;
12  %t1 = fsub float %x, %y
13  %t2 = fsub float -0.0, %t1
14  ret float %t2
15}
16
17; Can't do anything with the test above because -0.0 - 0.0 = -0.0, but if we have nsz:
18; -(X - Y) --> Y - X
19
20define float @neg_sub_nsz(float %x, float %y) {
21; CHECK-LABEL: @neg_sub_nsz(
22; CHECK-NEXT:    [[TMP1:%.*]] = fsub nsz float [[Y:%.*]], [[X:%.*]]
23; CHECK-NEXT:    ret float [[TMP1]]
24;
25  %t1 = fsub float %x, %y
26  %t2 = fsub nsz float -0.0, %t1
27  ret float %t2
28}
29
30; If the subtract has another use, we don't do the transform (even though it
31; doesn't increase the IR instruction count) because we assume that fneg is
32; easier to analyze and generally cheaper than generic fsub.
33
34declare void @use(float)
35declare void @use2(float, double)
36
37define float @neg_sub_nsz_extra_use(float %x, float %y) {
38; CHECK-LABEL: @neg_sub_nsz_extra_use(
39; CHECK-NEXT:    [[T1:%.*]] = fsub float [[X:%.*]], [[Y:%.*]]
40; CHECK-NEXT:    [[T2:%.*]] = fsub nsz float -0.000000e+00, [[T1]]
41; CHECK-NEXT:    call void @use(float [[T1]])
42; CHECK-NEXT:    ret float [[T2]]
43;
44  %t1 = fsub float %x, %y
45  %t2 = fsub nsz float -0.0, %t1
46  call void @use(float %t1)
47  ret float %t2
48}
49
50; With nsz: Z - (X - Y) --> Z + (Y - X)
51
52define float @sub_sub_nsz(float %x, float %y, float %z) {
53; CHECK-LABEL: @sub_sub_nsz(
54; CHECK-NEXT:    [[TMP1:%.*]] = fsub nsz float [[Y:%.*]], [[X:%.*]]
55; CHECK-NEXT:    [[T2:%.*]] = fadd nsz float [[TMP1]], [[Z:%.*]]
56; CHECK-NEXT:    ret float [[T2]]
57;
58  %t1 = fsub float %x, %y
59  %t2 = fsub nsz float %z, %t1
60  ret float %t2
61}
62
63; Same as above: if 'Z' is not -0.0, swap fsub operands and convert to fadd.
64
65define float @sub_sub_known_not_negzero(float %x, float %y) {
66; CHECK-LABEL: @sub_sub_known_not_negzero(
67; CHECK-NEXT:    [[TMP1:%.*]] = fsub float [[Y:%.*]], [[X:%.*]]
68; CHECK-NEXT:    [[T2:%.*]] = fadd float [[TMP1]], 4.200000e+01
69; CHECK-NEXT:    ret float [[T2]]
70;
71  %t1 = fsub float %x, %y
72  %t2 = fsub float 42.0, %t1
73  ret float %t2
74}
75
76; <rdar://problem/7530098>
77
78define double @test2(double %x, double %y) {
79; CHECK-LABEL: @test2(
80; CHECK-NEXT:    [[T1:%.*]] = fadd double [[X:%.*]], [[Y:%.*]]
81; CHECK-NEXT:    [[T2:%.*]] = fsub double [[X]], [[T1]]
82; CHECK-NEXT:    ret double [[T2]]
83;
84  %t1 = fadd double %x, %y
85  %t2 = fsub double %x, %t1
86  ret double %t2
87}
88
89; X - C --> X + (-C)
90
91define float @constant_op1(float %x, float %y) {
92; CHECK-LABEL: @constant_op1(
93; CHECK-NEXT:    [[R:%.*]] = fadd float [[X:%.*]], -4.200000e+01
94; CHECK-NEXT:    ret float [[R]]
95;
96  %r = fsub float %x, 42.0
97  ret float %r
98}
99
100define <2 x float> @constant_op1_vec(<2 x float> %x, <2 x float> %y) {
101; CHECK-LABEL: @constant_op1_vec(
102; CHECK-NEXT:    [[R:%.*]] = fadd <2 x float> [[X:%.*]], <float -4.200000e+01, float 4.200000e+01>
103; CHECK-NEXT:    ret <2 x float> [[R]]
104;
105  %r = fsub <2 x float> %x, <float 42.0, float -42.0>
106  ret <2 x float> %r
107}
108
109define <2 x float> @constant_op1_vec_undef(<2 x float> %x, <2 x float> %y) {
110; CHECK-LABEL: @constant_op1_vec_undef(
111; CHECK-NEXT:    [[R:%.*]] = fadd <2 x float> [[X:%.*]], <float 0x7FF8000000000000, float 4.200000e+01>
112; CHECK-NEXT:    ret <2 x float> [[R]]
113;
114  %r = fsub <2 x float> %x, <float undef, float -42.0>
115  ret <2 x float> %r
116}
117
118; X - (-Y) --> X + Y
119
120define float @neg_op1(float %x, float %y) {
121; CHECK-LABEL: @neg_op1(
122; CHECK-NEXT:    [[R:%.*]] = fadd float [[X:%.*]], [[Y:%.*]]
123; CHECK-NEXT:    ret float [[R]]
124;
125  %negy = fsub float -0.0, %y
126  %r = fsub float %x, %negy
127  ret float %r
128}
129
130define <2 x float> @neg_op1_vec(<2 x float> %x, <2 x float> %y) {
131; CHECK-LABEL: @neg_op1_vec(
132; CHECK-NEXT:    [[R:%.*]] = fadd <2 x float> [[X:%.*]], [[Y:%.*]]
133; CHECK-NEXT:    ret <2 x float> [[R]]
134;
135  %negy = fsub <2 x float> <float -0.0, float -0.0>, %y
136  %r = fsub <2 x float> %x, %negy
137  ret <2 x float> %r
138}
139
140define <2 x float> @neg_op1_vec_undef(<2 x float> %x, <2 x float> %y) {
141; CHECK-LABEL: @neg_op1_vec_undef(
142; CHECK-NEXT:    [[R:%.*]] = fadd <2 x float> [[X:%.*]], [[Y:%.*]]
143; CHECK-NEXT:    ret <2 x float> [[R]]
144;
145  %negy = fsub <2 x float> <float -0.0, float undef>, %y
146  %r = fsub <2 x float> %x, %negy
147  ret <2 x float> %r
148}
149
150; Similar to above - but look through fpext/fptrunc casts to find the fneg.
151
152define double @neg_ext_op1(float %a, double %b) {
153; CHECK-LABEL: @neg_ext_op1(
154; CHECK-NEXT:    [[TMP1:%.*]] = fpext float [[A:%.*]] to double
155; CHECK-NEXT:    [[T3:%.*]] = fadd double [[TMP1]], [[B:%.*]]
156; CHECK-NEXT:    ret double [[T3]]
157;
158  %t1 = fsub float -0.0, %a
159  %t2 = fpext float %t1 to double
160  %t3 = fsub double %b, %t2
161  ret double %t3
162}
163
164; Verify that vectors work too.
165
166define <2 x float> @neg_trunc_op1(<2 x double> %a, <2 x float> %b) {
167; CHECK-LABEL: @neg_trunc_op1(
168; CHECK-NEXT:    [[TMP1:%.*]] = fptrunc <2 x double> [[A:%.*]] to <2 x float>
169; CHECK-NEXT:    [[T3:%.*]] = fadd <2 x float> [[TMP1]], [[B:%.*]]
170; CHECK-NEXT:    ret <2 x float> [[T3]]
171;
172  %t1 = fsub <2 x double> <double -0.0, double -0.0>, %a
173  %t2 = fptrunc <2 x double> %t1 to <2 x float>
174  %t3 = fsub <2 x float> %b, %t2
175  ret <2 x float> %t3
176}
177
178; No FMF needed, but they should propagate to the fadd.
179
180define double @neg_ext_op1_fast(float %a, double %b) {
181; CHECK-LABEL: @neg_ext_op1_fast(
182; CHECK-NEXT:    [[TMP1:%.*]] = fpext float [[A:%.*]] to double
183; CHECK-NEXT:    [[T3:%.*]] = fadd fast double [[TMP1]], [[B:%.*]]
184; CHECK-NEXT:    ret double [[T3]]
185;
186  %t1 = fsub float -0.0, %a
187  %t2 = fpext float %t1 to double
188  %t3 = fsub fast double %b, %t2
189  ret double %t3
190}
191
192; Extra use should prevent the transform.
193
194define float @neg_ext_op1_extra_use(half %a, float %b) {
195; CHECK-LABEL: @neg_ext_op1_extra_use(
196; CHECK-NEXT:    [[T1:%.*]] = fsub half 0xH8000, [[A:%.*]]
197; CHECK-NEXT:    [[T2:%.*]] = fpext half [[T1]] to float
198; CHECK-NEXT:    [[T3:%.*]] = fsub float [[B:%.*]], [[T2]]
199; CHECK-NEXT:    call void @use(float [[T2]])
200; CHECK-NEXT:    ret float [[T3]]
201;
202  %t1 = fsub half -0.0, %a
203  %t2 = fpext half %t1 to float
204  %t3 = fsub float %b, %t2
205  call void @use(float %t2)
206  ret float %t3
207}
208
209; One-use fptrunc is always hoisted above fneg, so the corresponding
210; multi-use bug for fptrunc isn't visible with a fold starting from
211; the last fsub.
212
213define float @neg_trunc_op1_extra_use(double %a, float %b) {
214; CHECK-LABEL: @neg_trunc_op1_extra_use(
215; CHECK-NEXT:    [[TMP1:%.*]] = fptrunc double [[A:%.*]] to float
216; CHECK-NEXT:    [[T2:%.*]] = fsub float -0.000000e+00, [[TMP1]]
217; CHECK-NEXT:    [[T3:%.*]] = fadd float [[TMP1]], [[B:%.*]]
218; CHECK-NEXT:    call void @use(float [[T2]])
219; CHECK-NEXT:    ret float [[T3]]
220;
221  %t1 = fsub double -0.0, %a
222  %t2 = fptrunc double %t1 to float
223  %t3 = fsub float %b, %t2
224  call void @use(float %t2)
225  ret float %t3
226}
227
228; Extra uses should prevent the transform.
229
230define float @neg_trunc_op1_extra_uses(double %a, float %b) {
231; CHECK-LABEL: @neg_trunc_op1_extra_uses(
232; CHECK-NEXT:    [[T1:%.*]] = fsub double -0.000000e+00, [[A:%.*]]
233; CHECK-NEXT:    [[T2:%.*]] = fptrunc double [[T1]] to float
234; CHECK-NEXT:    [[T3:%.*]] = fsub float [[B:%.*]], [[T2]]
235; CHECK-NEXT:    call void @use2(float [[T2]], double [[T1]])
236; CHECK-NEXT:    ret float [[T3]]
237;
238  %t1 = fsub double -0.0, %a
239  %t2 = fptrunc double %t1 to float
240  %t3 = fsub float %b, %t2
241  call void @use2(float %t2, double %t1)
242  ret float %t3
243}
244
245; Don't negate a constant expression to form fadd and induce infinite looping:
246; https://bugs.llvm.org/show_bug.cgi?id=37605
247
248@b = external global i16, align 1
249
250define float @PR37605(float %conv) {
251; CHECK-LABEL: @PR37605(
252; CHECK-NEXT:    [[SUB:%.*]] = fsub float [[CONV:%.*]], bitcast (i32 ptrtoint (i16* @b to i32) to float)
253; CHECK-NEXT:    ret float [[SUB]]
254;
255  %sub = fsub float %conv, bitcast (i32 ptrtoint (i16* @b to i32) to float)
256  ret float %sub
257}
258
259