Mercurial > hg > CbC > CbC_llvm
comparison test/CodeGen/X86/fp128-i128.ll @ 100:7d135dc70f03 LLVM 3.9
LLVM 3.9
author | Miyagi Mitsuki <e135756@ie.u-ryukyu.ac.jp> |
---|---|
date | Tue, 26 Jan 2016 22:53:40 +0900 |
parents | |
children | 803732b1fca8 |
comparison
equal
deleted
inserted
replaced
96:6418606d0ead | 100:7d135dc70f03 |
---|---|
1 ; RUN: llc < %s -O2 -mtriple=x86_64-linux-android -mattr=+mmx | FileCheck %s | |
2 ; RUN: llc < %s -O2 -mtriple=x86_64-linux-gnu -mattr=+mmx | FileCheck %s | |
3 | |
4 ; These tests were generated from simplified libm C code. | |
5 ; When compiled for the x86_64-linux-android target, | |
6 ; long double is mapped to f128 type that should be passed | |
7 ; in SSE registers. When the f128 type calling convention | |
8 ; problem was fixed, old llvm code failed to handle f128 values | |
9 ; in several f128/i128 type operations. These unit tests hopefully | |
10 ; will catch regression in any future change in this area. | |
11 ; To modified or enhance these test cases, please consult libm | |
12 ; code pattern and compile with -target x86_64-linux-android | |
13 ; to generate IL. The __float128 keyword if not accepted by | |
14 ; clang, just define it to "long double". | |
15 ; | |
16 | |
17 ; typedef long double __float128; | |
18 ; union IEEEl2bits { | |
19 ; __float128 e; | |
20 ; struct { | |
21 ; unsigned long manl :64; | |
22 ; unsigned long manh :48; | |
23 ; unsigned int exp :15; | |
24 ; unsigned int sign :1; | |
25 ; } bits; | |
26 ; struct { | |
27 ; unsigned long manl :64; | |
28 ; unsigned long manh :48; | |
29 ; unsigned int expsign :16; | |
30 ; } xbits; | |
31 ; }; | |
32 | |
33 ; C code: | |
34 ; void foo(__float128 x); | |
35 ; void TestUnionLD1(__float128 s, unsigned long n) { | |
36 ; union IEEEl2bits u; | |
37 ; __float128 w; | |
38 ; u.e = s; | |
39 ; u.bits.manh = n; | |
40 ; w = u.e; | |
41 ; foo(w); | |
42 ; } | |
43 define void @TestUnionLD1(fp128 %s, i64 %n) #0 { | |
44 entry: | |
45 %0 = bitcast fp128 %s to i128 | |
46 %1 = zext i64 %n to i128 | |
47 %bf.value = shl nuw i128 %1, 64 | |
48 %bf.shl = and i128 %bf.value, 5192296858534809181786422619668480 | |
49 %bf.clear = and i128 %0, -5192296858534809181786422619668481 | |
50 %bf.set = or i128 %bf.shl, %bf.clear | |
51 %2 = bitcast i128 %bf.set to fp128 | |
52 tail call void @foo(fp128 %2) #2 | |
53 ret void | |
54 ; CHECK-LABEL: TestUnionLD1: | |
55 ; CHECK: movaps %xmm0, -24(%rsp) | |
56 ; CHECK-NEXT: movq -24(%rsp), %rax | |
57 ; CHECK-NEXT: movabsq $281474976710655, %rcx | |
58 ; CHECK-NEXT: andq %rdi, %rcx | |
59 ; CHECK-NEXT: movabsq $-281474976710656, %rdx | |
60 ; CHECK-NEXT: andq -16(%rsp), %rdx | |
61 ; CHECK-NEXT: movq %rax, -40(%rsp) | |
62 ; CHECK-NEXT: orq %rcx, %rdx | |
63 ; CHECK-NEXT: movq %rdx, -32(%rsp) | |
64 ; CHECK-NEXT: movaps -40(%rsp), %xmm0 | |
65 ; CHECK-NEXT: jmp foo | |
66 } | |
67 | |
68 ; C code: | |
69 ; __float128 TestUnionLD2(__float128 s) { | |
70 ; union IEEEl2bits u; | |
71 ; __float128 w; | |
72 ; u.e = s; | |
73 ; u.bits.manl = 0; | |
74 ; w = u.e; | |
75 ; return w; | |
76 ; } | |
77 define fp128 @TestUnionLD2(fp128 %s) #0 { | |
78 entry: | |
79 %0 = bitcast fp128 %s to i128 | |
80 %bf.clear = and i128 %0, -18446744073709551616 | |
81 %1 = bitcast i128 %bf.clear to fp128 | |
82 ret fp128 %1 | |
83 ; CHECK-LABEL: TestUnionLD2: | |
84 ; CHECK: movaps %xmm0, -24(%rsp) | |
85 ; CHECK-NEXT: movq -16(%rsp), %rax | |
86 ; CHECK-NEXT: movq %rax, -32(%rsp) | |
87 ; CHECK-NEXT: movq $0, -40(%rsp) | |
88 ; CHECK-NEXT: movaps -40(%rsp), %xmm0 | |
89 ; CHECK-NEXT: retq | |
90 } | |
91 | |
92 ; C code: | |
93 ; __float128 TestI128_1(__float128 x) | |
94 ; { | |
95 ; union IEEEl2bits z; | |
96 ; z.e = x; | |
97 ; z.bits.sign = 0; | |
98 ; return (z.e < 0.1L) ? 1.0L : 2.0L; | |
99 ; } | |
100 define fp128 @TestI128_1(fp128 %x) #0 { | |
101 entry: | |
102 %0 = bitcast fp128 %x to i128 | |
103 %bf.clear = and i128 %0, 170141183460469231731687303715884105727 | |
104 %1 = bitcast i128 %bf.clear to fp128 | |
105 %cmp = fcmp olt fp128 %1, 0xL999999999999999A3FFB999999999999 | |
106 %cond = select i1 %cmp, fp128 0xL00000000000000003FFF000000000000, fp128 0xL00000000000000004000000000000000 | |
107 ret fp128 %cond | |
108 ; CHECK-LABEL: TestI128_1: | |
109 ; CHECK: movaps %xmm0, | |
110 ; CHECK: movabsq $9223372036854775807, | |
111 ; CHECK: callq __lttf2 | |
112 ; CHECK: testl %eax, %eax | |
113 ; CHECK: movaps {{.*}}, %xmm0 | |
114 ; CHECK: retq | |
115 } | |
116 | |
117 ; C code: | |
118 ; __float128 TestI128_2(__float128 x, __float128 y) | |
119 ; { | |
120 ; unsigned short hx; | |
121 ; union IEEEl2bits ge_u; | |
122 ; ge_u.e = x; | |
123 ; hx = ge_u.xbits.expsign; | |
124 ; return (hx & 0x8000) == 0 ? x : y; | |
125 ; } | |
126 define fp128 @TestI128_2(fp128 %x, fp128 %y) #0 { | |
127 entry: | |
128 %0 = bitcast fp128 %x to i128 | |
129 %cmp = icmp sgt i128 %0, -1 | |
130 %cond = select i1 %cmp, fp128 %x, fp128 %y | |
131 ret fp128 %cond | |
132 ; CHECK-LABEL: TestI128_2: | |
133 ; CHECK: movaps %xmm0, -24(%rsp) | |
134 ; CHECK-NEXT: cmpq $0, -16(%rsp) | |
135 ; CHECK-NEXT: jns | |
136 ; CHECK: movaps %xmm1, %xmm0 | |
137 ; CHECK: retq | |
138 } | |
139 | |
140 ; C code: | |
141 ; __float128 TestI128_3(__float128 x, int *ex) | |
142 ; { | |
143 ; union IEEEl2bits u; | |
144 ; u.e = x; | |
145 ; if (u.bits.exp == 0) { | |
146 ; u.e *= 0x1.0p514; | |
147 ; u.bits.exp = 0x3ffe; | |
148 ; } | |
149 ; return (u.e); | |
150 ; } | |
151 define fp128 @TestI128_3(fp128 %x, i32* nocapture readnone %ex) #0 { | |
152 entry: | |
153 %0 = bitcast fp128 %x to i128 | |
154 %bf.cast = and i128 %0, 170135991163610696904058773219554885632 | |
155 %cmp = icmp eq i128 %bf.cast, 0 | |
156 br i1 %cmp, label %if.then, label %if.end | |
157 | |
158 if.then: ; preds = %entry | |
159 %mul = fmul fp128 %x, 0xL00000000000000004201000000000000 | |
160 %1 = bitcast fp128 %mul to i128 | |
161 %bf.clear4 = and i128 %1, -170135991163610696904058773219554885633 | |
162 %bf.set = or i128 %bf.clear4, 85060207136517546210586590865283612672 | |
163 br label %if.end | |
164 | |
165 if.end: ; preds = %if.then, %entry | |
166 %u.sroa.0.0 = phi i128 [ %bf.set, %if.then ], [ %0, %entry ] | |
167 %2 = bitcast i128 %u.sroa.0.0 to fp128 | |
168 ret fp128 %2 | |
169 ; CHECK-LABEL: TestI128_3: | |
170 ; CHECK: movaps %xmm0, | |
171 ; CHECK: movabsq $9223090561878065152, | |
172 ; CHECK: testq | |
173 ; CHECK: callq __multf3 | |
174 ; CHECK-NEXT: movaps %xmm0 | |
175 ; CHECK: movabsq $-9223090561878065153, | |
176 ; CHECK: movabsq $4611123068473966592, | |
177 ; CHECK: retq | |
178 } | |
179 | |
180 ; C code: | |
181 ; __float128 TestI128_4(__float128 x) | |
182 ; { | |
183 ; union IEEEl2bits u; | |
184 ; __float128 df; | |
185 ; u.e = x; | |
186 ; u.xbits.manl = 0; | |
187 ; df = u.e; | |
188 ; return x + df; | |
189 ; } | |
190 define fp128 @TestI128_4(fp128 %x) #0 { | |
191 entry: | |
192 %0 = bitcast fp128 %x to i128 | |
193 %bf.clear = and i128 %0, -18446744073709551616 | |
194 %1 = bitcast i128 %bf.clear to fp128 | |
195 %add = fadd fp128 %1, %x | |
196 ret fp128 %add | |
197 ; CHECK-LABEL: TestI128_4: | |
198 ; CHECK: movaps %xmm0, %xmm1 | |
199 ; CHECK-NEXT: movaps %xmm1, 16(%rsp) | |
200 ; CHECK-NEXT: movq 24(%rsp), %rax | |
201 ; CHECK-NEXT: movq %rax, 8(%rsp) | |
202 ; CHECK-NEXT: movq $0, (%rsp) | |
203 ; CHECK-NEXT: movaps (%rsp), %xmm0 | |
204 ; CHECK-NEXT: callq __addtf3 | |
205 ; CHECK: retq | |
206 } | |
207 | |
208 @v128 = common global i128 0, align 16 | |
209 @v128_2 = common global i128 0, align 16 | |
210 | |
211 ; C code: | |
212 ; unsigned __int128 v128, v128_2; | |
213 ; void TestShift128_2() { | |
214 ; v128 = ((v128 << 96) | v128_2); | |
215 ; } | |
216 define void @TestShift128_2() #2 { | |
217 entry: | |
218 %0 = load i128, i128* @v128, align 16 | |
219 %shl = shl i128 %0, 96 | |
220 %1 = load i128, i128* @v128_2, align 16 | |
221 %or = or i128 %shl, %1 | |
222 store i128 %or, i128* @v128, align 16 | |
223 ret void | |
224 ; CHECK-LABEL: TestShift128_2: | |
225 ; CHECK: movq v128(%rip), %rax | |
226 ; CHECK-NEXT: shlq $32, %rax | |
227 ; CHECK-NEXT: movq v128_2(%rip), %rcx | |
228 ; CHECK-NEXT: orq v128_2+8(%rip), %rax | |
229 ; CHECK-NEXT: movq %rcx, v128(%rip) | |
230 ; CHECK-NEXT: movq %rax, v128+8(%rip) | |
231 ; CHECK-NEXT: retq | |
232 } | |
233 | |
234 define fp128 @acosl(fp128 %x) #0 { | |
235 entry: | |
236 %0 = bitcast fp128 %x to i128 | |
237 %bf.clear = and i128 %0, -18446744073709551616 | |
238 %1 = bitcast i128 %bf.clear to fp128 | |
239 %add = fadd fp128 %1, %x | |
240 ret fp128 %add | |
241 ; CHECK-LABEL: acosl: | |
242 ; CHECK: movaps %xmm0, %xmm1 | |
243 ; CHECK-NEXT: movaps %xmm1, 16(%rsp) | |
244 ; CHECK-NEXT: movq 24(%rsp), %rax | |
245 ; CHECK-NEXT: movq %rax, 8(%rsp) | |
246 ; CHECK-NEXT: movq $0, (%rsp) | |
247 ; CHECK-NEXT: movaps (%rsp), %xmm0 | |
248 ; CHECK-NEXT: callq __addtf3 | |
249 ; CHECK: retq | |
250 } | |
251 | |
252 ; Compare i128 values and check i128 constants. | |
253 define fp128 @TestComp(fp128 %x, fp128 %y) #0 { | |
254 entry: | |
255 %0 = bitcast fp128 %x to i128 | |
256 %cmp = icmp sgt i128 %0, -1 | |
257 %cond = select i1 %cmp, fp128 %x, fp128 %y | |
258 ret fp128 %cond | |
259 ; CHECK-LABEL: TestComp: | |
260 ; CHECK: movaps %xmm0, -24(%rsp) | |
261 ; CHECK-NEXT: cmpq $0, -16(%rsp) | |
262 ; CHECK-NEXT: jns | |
263 ; CHECK: movaps %xmm1, %xmm0 | |
264 ; CHECK: retq | |
265 } | |
266 | |
267 declare void @foo(fp128) #1 | |
268 | |
269 ; Test logical operations on fp128 values. | |
270 define fp128 @TestFABS_LD(fp128 %x) #0 { | |
271 entry: | |
272 %call = tail call fp128 @fabsl(fp128 %x) #2 | |
273 ret fp128 %call | |
274 ; CHECK-LABEL: TestFABS_LD | |
275 ; CHECK: andps {{.*}}, %xmm0 | |
276 ; CHECK-NEXT: retq | |
277 } | |
278 | |
279 declare fp128 @fabsl(fp128) #1 | |
280 | |
281 declare fp128 @copysignl(fp128, fp128) #1 | |
282 | |
283 ; Test more complicated logical operations generated from copysignl. | |
284 define void @TestCopySign({ fp128, fp128 }* noalias nocapture sret %agg.result, { fp128, fp128 }* byval nocapture readonly align 16 %z) #0 { | |
285 entry: | |
286 %z.realp = getelementptr inbounds { fp128, fp128 }, { fp128, fp128 }* %z, i64 0, i32 0 | |
287 %z.real = load fp128, fp128* %z.realp, align 16 | |
288 %z.imagp = getelementptr inbounds { fp128, fp128 }, { fp128, fp128 }* %z, i64 0, i32 1 | |
289 %z.imag4 = load fp128, fp128* %z.imagp, align 16 | |
290 %cmp = fcmp ogt fp128 %z.real, %z.imag4 | |
291 %sub = fsub fp128 %z.imag4, %z.imag4 | |
292 br i1 %cmp, label %if.then, label %cleanup | |
293 | |
294 if.then: ; preds = %entry | |
295 %call = tail call fp128 @fabsl(fp128 %sub) #2 | |
296 br label %cleanup | |
297 | |
298 cleanup: ; preds = %entry, %if.then | |
299 %z.real.sink = phi fp128 [ %z.real, %if.then ], [ %sub, %entry ] | |
300 %call.sink = phi fp128 [ %call, %if.then ], [ %z.real, %entry ] | |
301 %call5 = tail call fp128 @copysignl(fp128 %z.real.sink, fp128 %z.imag4) #2 | |
302 %0 = getelementptr inbounds { fp128, fp128 }, { fp128, fp128 }* %agg.result, i64 0, i32 0 | |
303 %1 = getelementptr inbounds { fp128, fp128 }, { fp128, fp128 }* %agg.result, i64 0, i32 1 | |
304 store fp128 %call.sink, fp128* %0, align 16 | |
305 store fp128 %call5, fp128* %1, align 16 | |
306 ret void | |
307 ; CHECK-LABEL: TestCopySign | |
308 ; CHECK-NOT: call | |
309 ; CHECK: callq __subtf3 | |
310 ; CHECK-NOT: call | |
311 ; CHECK: callq __gttf2 | |
312 ; CHECK-NOT: call | |
313 ; CHECK: andps {{.*}}, %xmm0 | |
314 ; CHECK: retq | |
315 } | |
316 | |
317 | |
318 attributes #0 = { nounwind uwtable "disable-tail-calls"="false" "less-precise-fpmad"="false" "no-frame-pointer-elim"="false" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "stack-protector-buffer-size"="8" "target-cpu"="x86-64" "target-features"="+ssse3,+sse3,+popcnt,+sse,+sse2,+sse4.1,+sse4.2" "unsafe-fp-math"="false" "use-soft-float"="false" } | |
319 attributes #1 = { "disable-tail-calls"="false" "less-precise-fpmad"="false" "no-frame-pointer-elim"="false" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "stack-protector-buffer-size"="8" "target-cpu"="x86-64" "target-features"="+ssse3,+sse3,+popcnt,+sse,+sse2,+sse4.1,+sse4.2" "unsafe-fp-math"="false" "use-soft-float"="false" } | |
320 attributes #2 = { nounwind readnone } |