• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1; RUN: llc < %s -O2 -mtriple=x86_64-linux-android -mattr=+mmx | FileCheck %s --check-prefix=X64
2; RUN: llc < %s -O2 -mtriple=x86_64-linux-gnu -mattr=+mmx | FileCheck %s --check-prefix=X64
3; RUN: llc < %s -O2 -mtriple=i686-linux-gnu -mattr=+mmx | FileCheck %s --check-prefix=X32
4
5; Check soft floating point conversion function calls.
6
7@vi32 = common global i32 0, align 4
8@vi64 = common global i64 0, align 8
9@vu32 = common global i32 0, align 4
10@vu64 = common global i64 0, align 8
11@vf32 = common global float 0.000000e+00, align 4
12@vf64 = common global double 0.000000e+00, align 8
13@vf128 = common global fp128 0xL00000000000000000000000000000000, align 16
14
15define void @TestFPExtF32_F128() {
16entry:
17  %0 = load float, float* @vf32, align 4
18  %conv = fpext float %0 to fp128
19  store fp128 %conv, fp128* @vf128, align 16
20  ret void
21; X32-LABEL: TestFPExtF32_F128:
22; X32:       flds       vf32
23; X32:       fstps
24; X32:       calll      __extendsftf2
25; X32:       retl
26;
27; X64-LABEL: TestFPExtF32_F128:
28; X64:       movss      vf32(%rip), %xmm0
29; X64-NEXT:  callq      __extendsftf2
30; X64-NEXT:  movaps     %xmm0, vf128(%rip)
31; X64:       retq
32}
33
34define void @TestFPExtF64_F128() {
35entry:
36  %0 = load double, double* @vf64, align 8
37  %conv = fpext double %0 to fp128
38  store fp128 %conv, fp128* @vf128, align 16
39  ret void
40; X32-LABEL: TestFPExtF64_F128:
41; X32:       fldl       vf64
42; X32:       fstpl
43; X32:       calll      __extenddftf2
44; X32:       retl
45;
46; X64-LABEL: TestFPExtF64_F128:
47; X64:       movsd      vf64(%rip), %xmm0
48; X64-NEXT:  callq      __extenddftf2
49; X64-NEXT:  movapd     %xmm0, vf128(%rip)
50; X64:       ret
51}
52
53define void @TestFPToSIF128_I32() {
54entry:
55  %0 = load fp128, fp128* @vf128, align 16
56  %conv = fptosi fp128 %0 to i32
57  store i32 %conv, i32* @vi32, align 4
58  ret void
59; X32-LABEL: TestFPToSIF128_I32:
60; X32:       calll      __fixtfsi
61; X32:       retl
62;
63; X64-LABEL: TestFPToSIF128_I32:
64; X64:        movaps     vf128(%rip), %xmm0
65; X64-NEXT:   callq      __fixtfsi
66; X64-NEXT:   movl       %eax, vi32(%rip)
67; X64:        retq
68}
69
70define void @TestFPToUIF128_U32() {
71entry:
72  %0 = load fp128, fp128* @vf128, align 16
73  %conv = fptoui fp128 %0 to i32
74  store i32 %conv, i32* @vu32, align 4
75  ret void
76; X32-LABEL: TestFPToUIF128_U32:
77; X32:       calll      __fixunstfsi
78; X32:       retl
79;
80; X64-LABEL: TestFPToUIF128_U32:
81; X64:        movaps     vf128(%rip), %xmm0
82; X64-NEXT:   callq      __fixunstfsi
83; X64-NEXT:   movl       %eax, vu32(%rip)
84; X64:        retq
85}
86
87define void @TestFPToSIF128_I64() {
88entry:
89  %0 = load fp128, fp128* @vf128, align 16
90  %conv = fptosi fp128 %0 to i32
91  %conv1 = sext i32 %conv to i64
92  store i64 %conv1, i64* @vi64, align 8
93  ret void
94; X32-LABEL: TestFPToSIF128_I64:
95; X32:       calll      __fixtfsi
96; X32:       retl
97;
98; X64-LABEL: TestFPToSIF128_I64:
99; X64:       movaps      vf128(%rip), %xmm0
100; X64-NEXT:  callq       __fixtfsi
101; X64-NEXT:  cltq
102; X64-NEXT:  movq        %rax, vi64(%rip)
103; X64:       retq
104}
105
106define void @TestFPToUIF128_U64() {
107entry:
108  %0 = load fp128, fp128* @vf128, align 16
109  %conv = fptoui fp128 %0 to i32
110  %conv1 = zext i32 %conv to i64
111  store i64 %conv1, i64* @vu64, align 8
112  ret void
113; X32-LABEL: TestFPToUIF128_U64:
114; X32:       calll      __fixunstfsi
115; X32:       retl
116;
117; X64-LABEL: TestFPToUIF128_U64:
118; X64:       movaps      vf128(%rip), %xmm0
119; X64-NEXT:  callq       __fixunstfsi
120; X64-NEXT:  movl        %eax, %eax
121; X64-NEXT:  movq        %rax, vu64(%rip)
122; X64:       retq
123}
124
125define void @TestFPTruncF128_F32() {
126entry:
127  %0 = load fp128, fp128* @vf128, align 16
128  %conv = fptrunc fp128 %0 to float
129  store float %conv, float* @vf32, align 4
130  ret void
131; X32-LABEL: TestFPTruncF128_F32:
132; X32:       calll      __trunctfsf2
133; X32:       fstps      vf32
134; X32:       retl
135;
136; X64-LABEL: TestFPTruncF128_F32:
137; X64:       movaps      vf128(%rip), %xmm0
138; X64-NEXT:  callq       __trunctfsf2
139; X64-NEXT:  movss       %xmm0, vf32(%rip)
140; X64:       retq
141}
142
143define void @TestFPTruncF128_F64() {
144entry:
145  %0 = load fp128, fp128* @vf128, align 16
146  %conv = fptrunc fp128 %0 to double
147  store double %conv, double* @vf64, align 8
148  ret void
149; X32-LABEL: TestFPTruncF128_F64:
150; X32:       calll      __trunctfdf2
151; X32:       fstpl      vf64
152; X32:       retl
153;
154; X64-LABEL: TestFPTruncF128_F64:
155; X64:       movapd      vf128(%rip), %xmm0
156; X64-NEXT:  callq       __trunctfdf2
157; X64-NEXT:  movsd       %xmm0, vf64(%rip)
158; X64:       retq
159}
160
161define void @TestSIToFPI32_F128() {
162entry:
163  %0 = load i32, i32* @vi32, align 4
164  %conv = sitofp i32 %0 to fp128
165  store fp128 %conv, fp128* @vf128, align 16
166  ret void
167; X32-LABEL: TestSIToFPI32_F128:
168; X32:       calll      __floatsitf
169; X32:       retl
170;
171; X64-LABEL: TestSIToFPI32_F128:
172; X64:       movl       vi32(%rip), %edi
173; X64-NEXT:  callq      __floatsitf
174; X64-NEXT:  movaps     %xmm0, vf128(%rip)
175; X64:       retq
176}
177
178define void @TestUIToFPU32_F128() #2 {
179entry:
180  %0 = load i32, i32* @vu32, align 4
181  %conv = uitofp i32 %0 to fp128
182  store fp128 %conv, fp128* @vf128, align 16
183  ret void
184; X32-LABEL: TestUIToFPU32_F128:
185; X32:       calll      __floatunsitf
186; X32:       retl
187;
188; X64-LABEL: TestUIToFPU32_F128:
189; X64:       movl       vu32(%rip), %edi
190; X64-NEXT:  callq      __floatunsitf
191; X64-NEXT:  movaps     %xmm0, vf128(%rip)
192; X64:       retq
193}
194
195define void @TestSIToFPI64_F128(){
196entry:
197  %0 = load i64, i64* @vi64, align 8
198  %conv = sitofp i64 %0 to fp128
199  store fp128 %conv, fp128* @vf128, align 16
200  ret void
201; X32-LABEL: TestSIToFPI64_F128:
202; X32:       calll      __floatditf
203; X32:       retl
204;
205; X64-LABEL: TestSIToFPI64_F128:
206; X64:       movq       vi64(%rip), %rdi
207; X64-NEXT:  callq      __floatditf
208; X64-NEXT:  movaps     %xmm0, vf128(%rip)
209; X64:       retq
210}
211
212define void @TestUIToFPU64_F128() #2 {
213entry:
214  %0 = load i64, i64* @vu64, align 8
215  %conv = uitofp i64 %0 to fp128
216  store fp128 %conv, fp128* @vf128, align 16
217  ret void
218; X32-LABEL: TestUIToFPU64_F128:
219; X32:       calll      __floatunditf
220; X32:       retl
221;
222; X64-LABEL: TestUIToFPU64_F128:
223; X64:       movq       vu64(%rip), %rdi
224; X64-NEXT:  callq      __floatunditf
225; X64-NEXT:  movaps     %xmm0, vf128(%rip)
226; X64:       retq
227}
228
229define i32 @TestConst128(fp128 %v) {
230entry:
231  %cmp = fcmp ogt fp128 %v, 0xL00000000000000003FFF000000000000
232  %conv = zext i1 %cmp to i32
233  ret i32 %conv
234; X32-LABEL: TestConst128:
235; X32:       calll      __gttf2
236; X32:       retl
237;
238; X64-LABEL: TestConst128:
239; X64:       movaps {{.*}}, %xmm1
240; X64-NEXT:  callq __gttf2
241; X64-NEXT:  xorl
242; X64-NEXT:  test
243; X64:       retq
244}
245
246; C code:
247;  struct TestBits_ieee_ext {
248;    unsigned v1;
249;    unsigned v2;
250; };
251; union TestBits_LDU {
252;   FP128 ld;
253;   struct TestBits_ieee_ext bits;
254; };
255; int TestBits128(FP128 ld) {
256;   union TestBits_LDU u;
257;   u.ld = ld * ld;
258;   return ((u.bits.v1 | u.bits.v2)  == 0);
259; }
260define i32 @TestBits128(fp128 %ld) {
261entry:
262  %mul = fmul fp128 %ld, %ld
263  %0 = bitcast fp128 %mul to i128
264  %shift = lshr i128 %0, 32
265  %or5 = or i128 %shift, %0
266  %or = trunc i128 %or5 to i32
267  %cmp = icmp eq i32 %or, 0
268  %conv = zext i1 %cmp to i32
269  ret i32 %conv
270; X32-LABEL: TestBits128:
271; X32:       calll      __multf3
272; X32:       retl
273;
274; X64-LABEL: TestBits128:
275; X64:       movaps %xmm0, %xmm1
276; X64-NEXT:  callq __multf3
277; X64-NEXT:  movaps %xmm0, (%rsp)
278; X64-NEXT:  movq (%rsp),
279; X64-NEXT:  movq %
280; X64-NEXT:  shrq $32,
281; X64:       xorl %eax, %eax
282; X64-NEXT:  orl
283; X64-NEXT:  sete %al
284; X64:       retq
285;
286; If TestBits128 fails due to any llvm or clang change,
287; please make sure the original simplified C code will
288; be compiled into correct IL and assembly code, not
289; just this TestBits128 test case. Better yet, try to
290; test the whole libm and its test cases.
291}
292
293; C code: (compiled with -target x86_64-linux-android)
294; typedef long double __float128;
295; __float128 TestPair128(unsigned long a, unsigned long b) {
296;   unsigned __int128 n;
297;   unsigned __int128 v1 = ((unsigned __int128)a << 64);
298;   unsigned __int128 v2 = (unsigned __int128)b;
299;   n = (v1 | v2) + 3;
300;   return *(__float128*)&n;
301; }
302define fp128 @TestPair128(i64 %a, i64 %b) {
303entry:
304  %conv = zext i64 %a to i128
305  %shl = shl nuw i128 %conv, 64
306  %conv1 = zext i64 %b to i128
307  %or = or i128 %shl, %conv1
308  %add = add i128 %or, 3
309  %0 = bitcast i128 %add to fp128
310  ret fp128 %0
311; X32-LABEL: TestPair128:
312; X32:       addl
313; X32-NEXT:  adcl
314; X32-NEXT:  adcl
315; X32-NEXT:  adcl
316; X32:       retl
317;
318; X64-LABEL: TestPair128:
319; X64:       addq $3, %rsi
320; X64:       movq %rsi, -24(%rsp)
321; X64:       movq %rdi, -16(%rsp)
322; X64:       movaps -24(%rsp), %xmm0
323; X64-NEXT:  retq
324}
325
326define fp128 @TestTruncCopysign(fp128 %x, i32 %n) {
327entry:
328  %cmp = icmp sgt i32 %n, 50000
329  br i1 %cmp, label %if.then, label %cleanup
330
331if.then:                                          ; preds = %entry
332  %conv = fptrunc fp128 %x to double
333  %call = tail call double @copysign(double 0x7FF0000000000000, double %conv) #2
334  %conv1 = fpext double %call to fp128
335  br label %cleanup
336
337cleanup:                                          ; preds = %entry, %if.then
338  %retval.0 = phi fp128 [ %conv1, %if.then ], [ %x, %entry ]
339  ret fp128 %retval.0
340; X32-LABEL: TestTruncCopysign:
341; X32:       calll __trunctfdf2
342; X32:       fstpl
343; X32:       flds
344; X32:       flds
345; X32:       fstp
346; X32:       fldz
347; X32:       fstp
348; X32:       fstpl
349; X32:       calll __extenddftf2
350; X32:       retl
351;
352; X64-LABEL: TestTruncCopysign:
353; X64:       callq __trunctfdf2
354; X64-NEXT:  andpd {{.*}}, %xmm0
355; X64-NEXT:  orpd {{.*}}, %xmm0
356; X64-NEXT:  callq __extenddftf2
357; X64:       retq
358}
359
360declare double @copysign(double, double) #1
361
362attributes #2 = { nounwind readnone }
363