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