1 ; RUN: opt < %s -float2int -S | FileCheck %s
2 ; RUN: opt < %s -passes='float2int' -S | FileCheck %s
8 ; CHECK-LABEL: @simple1
9 ; CHECK: %1 = zext i8 %a to i32
10 ; CHECK: %2 = add i32 %1, 1
11 ; CHECK: %3 = trunc i32 %2 to i16
13 define i16 @simple1(i8 %a) {
14 %1 = uitofp i8 %a to float
15 %2 = fadd float %1, 1.0
16 %3 = fptoui float %2 to i16
20 ; CHECK-LABEL: @simple2
21 ; CHECK: %1 = zext i8 %a to i32
22 ; CHECK: %2 = sub i32 %1, 1
23 ; CHECK: %3 = trunc i32 %2 to i8
25 define i8 @simple2(i8 %a) {
26 %1 = uitofp i8 %a to float
27 %2 = fsub float %1, 1.0
28 %3 = fptoui float %2 to i8
32 ; CHECK-LABEL: @simple3
33 ; CHECK: %1 = zext i8 %a to i32
34 ; CHECK: %2 = sub i32 %1, 1
36 define i32 @simple3(i8 %a) {
37 %1 = uitofp i8 %a to float
38 %2 = fsub float %1, 1.0
39 %3 = fptoui float %2 to i32
44 ; CHECK: %1 = zext i8 %a to i32
45 ; CHECK: %2 = zext i8 %b to i32
46 ; CHECK: %3 = icmp slt i32 %1, %2
48 define i1 @cmp(i8 %a, i8 %b) {
49 %1 = uitofp i8 %a to float
50 %2 = uitofp i8 %b to float
51 %3 = fcmp ult float %1, %2
55 ; CHECK-LABEL: @simple4
56 ; CHECK: %1 = zext i32 %a to i64
57 ; CHECK: %2 = add i64 %1, 1
58 ; CHECK: %3 = trunc i64 %2 to i32
60 define i32 @simple4(i32 %a) {
61 %1 = uitofp i32 %a to double
62 %2 = fadd double %1, 1.0
63 %3 = fptoui double %2 to i32
67 ; CHECK-LABEL: @simple5
68 ; CHECK: %1 = zext i8 %a to i32
69 ; CHECK: %2 = zext i8 %b to i32
70 ; CHECK: %3 = add i32 %1, 1
71 ; CHECK: %4 = mul i32 %3, %2
73 define i32 @simple5(i8 %a, i8 %b) {
74 %1 = uitofp i8 %a to float
75 %2 = uitofp i8 %b to float
76 %3 = fadd float %1, 1.0
77 %4 = fmul float %3, %2
78 %5 = fptoui float %4 to i32
82 ; CHECK-LABEL: @simple6
83 ; CHECK: %1 = zext i8 %a to i32
84 ; CHECK: %2 = zext i8 %b to i32
85 ; CHECK: %3 = sub i32 0, %1
86 ; CHECK: %4 = mul i32 %3, %2
88 define i32 @simple6(i8 %a, i8 %b) {
89 %1 = uitofp i8 %a to float
90 %2 = uitofp i8 %b to float
92 %4 = fmul float %3, %2
93 %5 = fptoui float %4 to i32
97 ; The two chains don't interact - failure of one shouldn't
98 ; cause failure of the other.
100 ; CHECK-LABEL: @multi1
101 ; CHECK: %1 = zext i8 %a to i32
102 ; CHECK: %2 = zext i8 %b to i32
103 ; CHECK: %fc = uitofp i8 %c to float
104 ; CHECK: %x1 = add i32 %1, %2
105 ; CHECK: %z = fadd float %fc, %d
106 ; CHECK: %w = fptoui float %z to i32
107 ; CHECK: %r = add i32 %x1, %w
109 define i32 @multi1(i8 %a, i8 %b, i8 %c, float %d) {
110 %fa = uitofp i8 %a to float
111 %fb = uitofp i8 %b to float
112 %fc = uitofp i8 %c to float
113 %x = fadd float %fa, %fb
114 %y = fptoui float %x to i32
115 %z = fadd float %fc, %d
116 %w = fptoui float %z to i32
121 ; CHECK-LABEL: @simple_negzero
122 ; CHECK: %1 = zext i8 %a to i32
123 ; CHECK: %2 = add i32 %1, 0
124 ; CHECK: %3 = trunc i32 %2 to i16
126 define i16 @simple_negzero(i8 %a) {
127 %1 = uitofp i8 %a to float
128 %2 = fadd fast float %1, -0.0
129 %3 = fptoui float %2 to i16
133 ; CHECK-LABEL: @simple_negative
134 ; CHECK: %1 = sext i8 %call to i32
135 ; CHECK: %mul1 = mul i32 %1, -3
136 ; CHECK: %2 = trunc i32 %mul1 to i8
137 ; CHECK: %conv3 = sext i8 %2 to i32
138 ; CHECK: ret i32 %conv3
139 define i32 @simple_negative(i8 %call) {
140 %conv1 = sitofp i8 %call to float
141 %mul = fmul float %conv1, -3.000000e+00
142 %conv2 = fptosi float %mul to i8
143 %conv3 = sext i8 %conv2 to i32
147 ; CHECK-LABEL: @simple_fneg
148 ; CHECK: %1 = zext i8 %a to i32
149 ; CHECK: %2 = sub i32 0, %1
150 ; CHECK: %3 = trunc i32 %2 to i16
152 define i16 @simple_fneg(i8 %a) {
153 %1 = uitofp i8 %a to float
154 %2 = fneg fast float %1
155 %3 = fptoui float %2 to i16
163 ; CHECK-LABEL: @neg_multi1
164 ; CHECK: %fa = uitofp i8 %a to float
165 ; CHECK: %fc = uitofp i8 %c to float
166 ; CHECK: %x = fadd float %fa, %fc
167 ; CHECK: %y = fptoui float %x to i32
168 ; CHECK: %z = fadd float %fc, %d
169 ; CHECK: %w = fptoui float %z to i32
170 ; CHECK: %r = add i32 %y, %w
172 ; The two chains intersect, which means because one fails, no
173 ; transform can occur.
174 define i32 @neg_multi1(i8 %a, i8 %b, i8 %c, float %d) {
175 %fa = uitofp i8 %a to float
176 %fc = uitofp i8 %c to float
177 %x = fadd float %fa, %fc
178 %y = fptoui float %x to i32
179 %z = fadd float %fc, %d
180 %w = fptoui float %z to i32
185 ; CHECK-LABEL: @neg_muld
186 ; CHECK: %fa = uitofp i32 %a to double
187 ; CHECK: %fb = uitofp i32 %b to double
188 ; CHECK: %mul = fmul double %fa, %fb
189 ; CHECK: %r = fptoui double %mul to i64
191 ; The i32 * i32 = i64, which has 64 bits, which is greater than the 52 bits
192 ; that can be exactly represented in a double.
193 define i64 @neg_muld(i32 %a, i32 %b) {
194 %fa = uitofp i32 %a to double
195 %fb = uitofp i32 %b to double
196 %mul = fmul double %fa, %fb
197 %r = fptoui double %mul to i64
201 ; CHECK-LABEL: @neg_mulf
202 ; CHECK: %fa = uitofp i16 %a to float
203 ; CHECK: %fb = uitofp i16 %b to float
204 ; CHECK: %mul = fmul float %fa, %fb
205 ; CHECK: %r = fptoui float %mul to i32
207 ; The i16 * i16 = i32, which can't be represented in a float, but can in a
208 ; double. This should fail, as the written code uses floats, not doubles so
209 ; the original result may be inaccurate.
210 define i32 @neg_mulf(i16 %a, i16 %b) {
211 %fa = uitofp i16 %a to float
212 %fb = uitofp i16 %b to float
213 %mul = fmul float %fa, %fb
214 %r = fptoui float %mul to i32
218 ; CHECK-LABEL: @neg_cmp
219 ; CHECK: %1 = uitofp i8 %a to float
220 ; CHECK: %2 = uitofp i8 %b to float
221 ; CHECK: %3 = fcmp false float %1, %2
223 ; "false" doesn't have an icmp equivalent.
224 define i1 @neg_cmp(i8 %a, i8 %b) {
225 %1 = uitofp i8 %a to float
226 %2 = uitofp i8 %b to float
227 %3 = fcmp false float %1, %2
231 ; CHECK-LABEL: @neg_div
232 ; CHECK: %1 = uitofp i8 %a to float
233 ; CHECK: %2 = fdiv float %1, 1.0
234 ; CHECK: %3 = fptoui float %2 to i16
236 ; Division isn't a supported operator.
237 define i16 @neg_div(i8 %a) {
238 %1 = uitofp i8 %a to float
239 %2 = fdiv float %1, 1.0
240 %3 = fptoui float %2 to i16
244 ; CHECK-LABEL: @neg_remainder
245 ; CHECK: %1 = uitofp i8 %a to float
246 ; CHECK: %2 = fadd float %1, 1.2
247 ; CHECK: %3 = fptoui float %2 to i16
249 ; 1.2 is not an integer.
250 define i16 @neg_remainder(i8 %a) {
251 %1 = uitofp i8 %a to float
252 %2 = fadd float %1, 1.25
253 %3 = fptoui float %2 to i16
257 ; CHECK-LABEL: @neg_toolarge
258 ; CHECK: %1 = uitofp i80 %a to fp128
259 ; CHECK: %2 = fadd fp128 %1, %1
260 ; CHECK: %3 = fptoui fp128 %2 to i80
262 ; i80 > i64, which is the largest bitwidth handleable by default.
263 define i80 @neg_toolarge(i80 %a) {
264 %1 = uitofp i80 %a to fp128
265 %2 = fadd fp128 %1, %1
266 %3 = fptoui fp128 %2 to i80
270 ; CHECK-LABEL: @neg_calluser
273 ; The sequence %1..%3 cannot be converted because %4 uses %2.
274 define i32 @neg_calluser(i32 %value) {
275 %1 = sitofp i32 %value to double
276 %2 = fadd double %1, 1.0
277 %3 = fcmp olt double %2, 0.000000e+00
278 %4 = tail call double @g(double %2)
279 %5 = fptosi double %4 to i32
280 %6 = zext i1 %3 to i32
284 declare double @g(double)
286 ; CHECK-LABEL: @neg_vector
287 ; CHECK: %1 = uitofp <4 x i8> %a to <4 x float>
288 ; CHECK: %2 = fptoui <4 x float> %1 to <4 x i16>
289 ; CHECK: ret <4 x i16> %2
290 define <4 x i16> @neg_vector(<4 x i8> %a) {
291 %1 = uitofp <4 x i8> %a to <4 x float>
292 %2 = fptoui <4 x float> %1 to <4 x i16>