1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2; RUN: opt < %s -passes='float2int' -S | FileCheck %s
3
4;
5; Positive tests
6;
7
8define i16 @simple1(i8 %a) {
9; CHECK-LABEL: @simple1(
10; CHECK-NEXT:    [[TMP1:%.*]] = zext i8 [[A:%.*]] to i32
11; CHECK-NEXT:    [[T21:%.*]] = add i32 [[TMP1]], 1
12; CHECK-NEXT:    [[TMP2:%.*]] = trunc i32 [[T21]] to i16
13; CHECK-NEXT:    ret i16 [[TMP2]]
14;
15  %t1 = uitofp i8 %a to float
16  %t2 = fadd float %t1, 1.0
17  %t3 = fptoui float %t2 to i16
18  ret i16 %t3
19}
20
21define i8 @simple2(i8 %a) {
22; CHECK-LABEL: @simple2(
23; CHECK-NEXT:    [[TMP1:%.*]] = zext i8 [[A:%.*]] to i32
24; CHECK-NEXT:    [[T21:%.*]] = sub i32 [[TMP1]], 1
25; CHECK-NEXT:    [[TMP2:%.*]] = trunc i32 [[T21]] to i8
26; CHECK-NEXT:    ret i8 [[TMP2]]
27;
28  %t1 = uitofp i8 %a to float
29  %t2 = fsub float %t1, 1.0
30  %t3 = fptoui float %t2 to i8
31  ret i8 %t3
32}
33
34define i32 @simple3(i8 %a) {
35; CHECK-LABEL: @simple3(
36; CHECK-NEXT:    [[TMP1:%.*]] = zext i8 [[A:%.*]] to i32
37; CHECK-NEXT:    [[T21:%.*]] = sub i32 [[TMP1]], 1
38; CHECK-NEXT:    ret i32 [[T21]]
39;
40  %t1 = uitofp i8 %a to float
41  %t2 = fsub float %t1, 1.0
42  %t3 = fptoui float %t2 to i32
43  ret i32 %t3
44}
45
46define i1 @cmp(i8 %a, i8 %b) {
47; CHECK-LABEL: @cmp(
48; CHECK-NEXT:    [[TMP1:%.*]] = zext i8 [[A:%.*]] to i32
49; CHECK-NEXT:    [[TMP2:%.*]] = zext i8 [[B:%.*]] to i32
50; CHECK-NEXT:    [[T31:%.*]] = icmp slt i32 [[TMP1]], [[TMP2]]
51; CHECK-NEXT:    ret i1 [[T31]]
52;
53  %t1 = uitofp i8 %a to float
54  %t2 = uitofp i8 %b to float
55  %t3 = fcmp ult float %t1, %t2
56  ret i1 %t3
57}
58
59define i32 @simple4(i32 %a) {
60; CHECK-LABEL: @simple4(
61; CHECK-NEXT:    [[TMP1:%.*]] = zext i32 [[A:%.*]] to i64
62; CHECK-NEXT:    [[T21:%.*]] = add i64 [[TMP1]], 1
63; CHECK-NEXT:    [[TMP2:%.*]] = trunc i64 [[T21]] to i32
64; CHECK-NEXT:    ret i32 [[TMP2]]
65;
66  %t1 = uitofp i32 %a to double
67  %t2 = fadd double %t1, 1.0
68  %t3 = fptoui double %t2 to i32
69  ret i32 %t3
70}
71
72define i32 @simple5(i8 %a, i8 %b) {
73; CHECK-LABEL: @simple5(
74; CHECK-NEXT:    [[TMP1:%.*]] = zext i8 [[A:%.*]] to i32
75; CHECK-NEXT:    [[TMP2:%.*]] = zext i8 [[B:%.*]] to i32
76; CHECK-NEXT:    [[T31:%.*]] = add i32 [[TMP1]], 1
77; CHECK-NEXT:    [[T42:%.*]] = mul i32 [[T31]], [[TMP2]]
78; CHECK-NEXT:    ret i32 [[T42]]
79;
80  %t1 = uitofp i8 %a to float
81  %t2 = uitofp i8 %b to float
82  %t3 = fadd float %t1, 1.0
83  %t4 = fmul float %t3, %t2
84  %t5 = fptoui float %t4 to i32
85  ret i32 %t5
86}
87
88define i32 @simple6(i8 %a, i8 %b) {
89; CHECK-LABEL: @simple6(
90; CHECK-NEXT:    [[TMP1:%.*]] = zext i8 [[A:%.*]] to i32
91; CHECK-NEXT:    [[TMP2:%.*]] = zext i8 [[B:%.*]] to i32
92; CHECK-NEXT:    [[T31:%.*]] = sub i32 0, [[TMP1]]
93; CHECK-NEXT:    [[T42:%.*]] = mul i32 [[T31]], [[TMP2]]
94; CHECK-NEXT:    ret i32 [[T42]]
95;
96  %t1 = uitofp i8 %a to float
97  %t2 = uitofp i8 %b to float
98  %t3 = fneg float %t1
99  %t4 = fmul float %t3, %t2
100  %t5 = fptoui float %t4 to i32
101  ret i32 %t5
102}
103
104; The two chains don't interact - failure of one shouldn't
105; cause failure of the other.
106
107define i32 @multi1(i8 %a, i8 %b, i8 %c, float %d) {
108; CHECK-LABEL: @multi1(
109; CHECK-NEXT:    [[TMP1:%.*]] = zext i8 [[A:%.*]] to i32
110; CHECK-NEXT:    [[TMP2:%.*]] = zext i8 [[B:%.*]] to i32
111; CHECK-NEXT:    [[FC:%.*]] = uitofp i8 [[C:%.*]] to float
112; CHECK-NEXT:    [[X1:%.*]] = add i32 [[TMP1]], [[TMP2]]
113; CHECK-NEXT:    [[Z:%.*]] = fadd float [[FC]], [[D:%.*]]
114; CHECK-NEXT:    [[W:%.*]] = fptoui float [[Z]] to i32
115; CHECK-NEXT:    [[R:%.*]] = add i32 [[X1]], [[W]]
116; CHECK-NEXT:    ret i32 [[R]]
117;
118  %fa = uitofp i8 %a to float
119  %fb = uitofp i8 %b to float
120  %fc = uitofp i8 %c to float
121  %x = fadd float %fa, %fb
122  %y = fptoui float %x to i32
123  %z = fadd float %fc, %d
124  %w = fptoui float %z to i32
125  %r = add i32 %y, %w
126  ret i32 %r
127}
128
129define i16 @simple_negzero(i8 %a) {
130; CHECK-LABEL: @simple_negzero(
131; CHECK-NEXT:    [[TMP1:%.*]] = zext i8 [[A:%.*]] to i32
132; CHECK-NEXT:    [[T21:%.*]] = add i32 [[TMP1]], 0
133; CHECK-NEXT:    [[TMP2:%.*]] = trunc i32 [[T21]] to i16
134; CHECK-NEXT:    ret i16 [[TMP2]]
135;
136  %t1 = uitofp i8 %a to float
137  %t2 = fadd fast float %t1, -0.0
138  %t3 = fptoui float %t2 to i16
139  ret i16 %t3
140}
141
142define i32 @simple_negative(i8 %call) {
143; CHECK-LABEL: @simple_negative(
144; CHECK-NEXT:    [[TMP1:%.*]] = sext i8 [[CALL:%.*]] to i32
145; CHECK-NEXT:    [[MUL1:%.*]] = mul i32 [[TMP1]], -3
146; CHECK-NEXT:    [[TMP2:%.*]] = trunc i32 [[MUL1]] to i8
147; CHECK-NEXT:    [[CONV3:%.*]] = sext i8 [[TMP2]] to i32
148; CHECK-NEXT:    ret i32 [[CONV3]]
149;
150  %conv1 = sitofp i8 %call to float
151  %mul = fmul float %conv1, -3.000000e+00
152  %conv2 = fptosi float %mul to i8
153  %conv3 = sext i8 %conv2 to i32
154  ret i32 %conv3
155}
156
157define i16 @simple_fneg(i8 %a) {
158; CHECK-LABEL: @simple_fneg(
159; CHECK-NEXT:    [[TMP1:%.*]] = zext i8 [[A:%.*]] to i32
160; CHECK-NEXT:    [[T21:%.*]] = sub i32 0, [[TMP1]]
161; CHECK-NEXT:    [[TMP2:%.*]] = trunc i32 [[T21]] to i16
162; CHECK-NEXT:    ret i16 [[TMP2]]
163;
164  %t1 = uitofp i8 %a to float
165  %t2 = fneg fast float %t1
166  %t3 = fptoui float %t2 to i16
167  ret i16 %t3
168}
169
170;
171; Negative tests
172;
173
174; The two chains intersect, which means because one fails, no
175; transform can occur.
176
177define i32 @neg_multi1(i8 %a, i8 %b, i8 %c, float %d) {
178; CHECK-LABEL: @neg_multi1(
179; CHECK-NEXT:    [[FA:%.*]] = uitofp i8 [[A:%.*]] to float
180; CHECK-NEXT:    [[FC:%.*]] = uitofp i8 [[C:%.*]] to float
181; CHECK-NEXT:    [[X:%.*]] = fadd float [[FA]], [[FC]]
182; CHECK-NEXT:    [[Y:%.*]] = fptoui float [[X]] to i32
183; CHECK-NEXT:    [[Z:%.*]] = fadd float [[FC]], [[D:%.*]]
184; CHECK-NEXT:    [[W:%.*]] = fptoui float [[Z]] to i32
185; CHECK-NEXT:    [[R:%.*]] = add i32 [[Y]], [[W]]
186; CHECK-NEXT:    ret i32 [[R]]
187;
188  %fa = uitofp i8 %a to float
189  %fc = uitofp i8 %c to float
190  %x = fadd float %fa, %fc
191  %y = fptoui float %x to i32
192  %z = fadd float %fc, %d
193  %w = fptoui float %z to i32
194  %r = add i32 %y, %w
195  ret i32 %r
196}
197
198; The i32 * i32 = i64, which has 64 bits, which is greater than the 52 bits
199; that can be exactly represented in a double.
200
201define i64 @neg_muld(i32 %a, i32 %b) {
202; CHECK-LABEL: @neg_muld(
203; CHECK-NEXT:    [[FA:%.*]] = uitofp i32 [[A:%.*]] to double
204; CHECK-NEXT:    [[FB:%.*]] = uitofp i32 [[B:%.*]] to double
205; CHECK-NEXT:    [[MUL:%.*]] = fmul double [[FA]], [[FB]]
206; CHECK-NEXT:    [[R:%.*]] = fptoui double [[MUL]] to i64
207; CHECK-NEXT:    ret i64 [[R]]
208;
209  %fa = uitofp i32 %a to double
210  %fb = uitofp i32 %b to double
211  %mul = fmul double %fa, %fb
212  %r = fptoui double %mul to i64
213  ret i64 %r
214}
215
216; The i16 * i16 = i32, which can't be represented in a float, but can in a
217; double. This should fail, as the written code uses floats, not doubles so
218; the original result may be inaccurate.
219
220define i32 @neg_mulf(i16 %a, i16 %b) {
221; CHECK-LABEL: @neg_mulf(
222; CHECK-NEXT:    [[FA:%.*]] = uitofp i16 [[A:%.*]] to float
223; CHECK-NEXT:    [[FB:%.*]] = uitofp i16 [[B:%.*]] to float
224; CHECK-NEXT:    [[MUL:%.*]] = fmul float [[FA]], [[FB]]
225; CHECK-NEXT:    [[R:%.*]] = fptoui float [[MUL]] to i32
226; CHECK-NEXT:    ret i32 [[R]]
227;
228  %fa = uitofp i16 %a to float
229  %fb = uitofp i16 %b to float
230  %mul = fmul float %fa, %fb
231  %r = fptoui float %mul to i32
232  ret i32 %r
233}
234
235; "false" doesn't have an icmp equivalent.
236
237define i1 @neg_cmp(i8 %a, i8 %b) {
238; CHECK-LABEL: @neg_cmp(
239; CHECK-NEXT:    [[T1:%.*]] = uitofp i8 [[A:%.*]] to float
240; CHECK-NEXT:    [[T2:%.*]] = uitofp i8 [[B:%.*]] to float
241; CHECK-NEXT:    [[T3:%.*]] = fcmp false float [[T1]], [[T2]]
242; CHECK-NEXT:    ret i1 [[T3]]
243;
244  %t1 = uitofp i8 %a to float
245  %t2 = uitofp i8 %b to float
246  %t3 = fcmp false float %t1, %t2
247  ret i1 %t3
248}
249
250; Division isn't a supported operator.
251
252define i16 @neg_div(i8 %a) {
253; CHECK-LABEL: @neg_div(
254; CHECK-NEXT:    [[T1:%.*]] = uitofp i8 [[A:%.*]] to float
255; CHECK-NEXT:    [[T2:%.*]] = fdiv float [[T1]], 1.000000e+00
256; CHECK-NEXT:    [[T3:%.*]] = fptoui float [[T2]] to i16
257; CHECK-NEXT:    ret i16 [[T3]]
258;
259  %t1 = uitofp i8 %a to float
260  %t2 = fdiv float %t1, 1.0
261  %t3 = fptoui float %t2 to i16
262  ret i16 %t3
263}
264
265; 1.2 is not an integer.
266
267define i16 @neg_remainder(i8 %a) {
268; CHECK-LABEL: @neg_remainder(
269; CHECK-NEXT:    [[T1:%.*]] = uitofp i8 [[A:%.*]] to float
270; CHECK-NEXT:    [[T2:%.*]] = fadd float [[T1]], 1.250000e+00
271; CHECK-NEXT:    [[T3:%.*]] = fptoui float [[T2]] to i16
272; CHECK-NEXT:    ret i16 [[T3]]
273;
274  %t1 = uitofp i8 %a to float
275  %t2 = fadd float %t1, 1.25
276  %t3 = fptoui float %t2 to i16
277  ret i16 %t3
278}
279
280; i80 > i64, which is the largest bitwidth handleable by default.
281
282define i80 @neg_toolarge(i80 %a) {
283; CHECK-LABEL: @neg_toolarge(
284; CHECK-NEXT:    [[T1:%.*]] = uitofp i80 [[A:%.*]] to fp128
285; CHECK-NEXT:    [[T2:%.*]] = fadd fp128 [[T1]], [[T1]]
286; CHECK-NEXT:    [[T3:%.*]] = fptoui fp128 [[T2]] to i80
287; CHECK-NEXT:    ret i80 [[T3]]
288;
289  %t1 = uitofp i80 %a to fp128
290  %t2 = fadd fp128 %t1, %t1
291  %t3 = fptoui fp128 %t2 to i80
292  ret i80 %t3
293}
294
295; The sequence %t1..%t3 cannot be converted because %t4 uses %t2.
296
297define i32 @neg_calluser(i32 %value) {
298; CHECK-LABEL: @neg_calluser(
299; CHECK-NEXT:    [[T1:%.*]] = sitofp i32 [[VALUE:%.*]] to double
300; CHECK-NEXT:    [[T2:%.*]] = fadd double [[T1]], 1.000000e+00
301; CHECK-NEXT:    [[T3:%.*]] = fcmp olt double [[T2]], 0.000000e+00
302; CHECK-NEXT:    [[T4:%.*]] = tail call double @g(double [[T2]])
303; CHECK-NEXT:    [[T5:%.*]] = fptosi double [[T4]] to i32
304; CHECK-NEXT:    [[T6:%.*]] = zext i1 [[T3]] to i32
305; CHECK-NEXT:    [[T7:%.*]] = add i32 [[T6]], [[T5]]
306; CHECK-NEXT:    ret i32 [[T7]]
307;
308  %t1 = sitofp i32 %value to double
309  %t2 = fadd double %t1, 1.0
310  %t3 = fcmp olt double %t2, 0.000000e+00
311  %t4 = tail call double @g(double %t2)
312  %t5 = fptosi double %t4 to i32
313  %t6 = zext i1 %t3 to i32
314  %t7 = add i32 %t6, %t5
315  ret i32 %t7
316}
317
318declare double @g(double)
319
320define <4 x i16> @neg_vector(<4 x i8> %a) {
321; CHECK-LABEL: @neg_vector(
322; CHECK-NEXT:    [[T1:%.*]] = uitofp <4 x i8> [[A:%.*]] to <4 x float>
323; CHECK-NEXT:    [[T2:%.*]] = fptoui <4 x float> [[T1]] to <4 x i16>
324; CHECK-NEXT:    ret <4 x i16> [[T2]]
325;
326  %t1 = uitofp <4 x i8> %a to <4 x float>
327  %t2 = fptoui <4 x float> %t1 to <4 x i16>
328  ret <4 x i16> %t2
329}
330
331; Don't crash while processing unreachable (non-standard) IR.
332
333define void @PR38502() {
334; CHECK-LABEL: @PR38502(
335; CHECK-NEXT:  entry:
336; CHECK-NEXT:    ret void
337; CHECK:       bogusBB:
338; CHECK-NEXT:    [[INC1:%.*]] = fadd double [[INC:%.*]], 1.000000e+00
339; CHECK-NEXT:    [[INC]] = fadd double [[INC1]], 1.000000e+00
340; CHECK-NEXT:    [[TOBOOL:%.*]] = fcmp une double [[INC]], 0.000000e+00
341; CHECK-NEXT:    br label [[BOGUSBB:%.*]]
342;
343entry:
344  ret void
345
346bogusBB:                                          ; preds = %bogusBB
347  %inc1 = fadd double %inc, 1.000000e+00
348  %inc = fadd double %inc1, 1.000000e+00
349  %tobool = fcmp une double %inc, 0.000000e+00
350  br label %bogusBB
351}
352