• 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 -enable-legalize-types-checking | FileCheck %s
3; RUN: llc < %s -O2 -mtriple=x86_64-linux-gnu     -mattr=+mmx -enable-legalize-types-checking | FileCheck %s
4
5; These tests were generated from simplified libm C code.
6; When compiled for the x86_64-linux-android target,
7; long double is mapped to f128 type that should be passed
8; in SSE registers. When the f128 type calling convention
9; problem was fixed, old llvm code failed to handle f128 values
10; in several f128/i128 type operations. These unit tests hopefully
11; will catch regression in any future change in this area.
12; To modified or enhance these test cases, please consult libm
13; code pattern and compile with -target x86_64-linux-android
14; to generate IL. The __float128 keyword if not accepted by
15; clang, just define it to "long double".
16;
17
18; typedef long double __float128;
19; union IEEEl2bits {
20;   __float128 e;
21;   struct {
22;     unsigned long manl :64;
23;     unsigned long manh :48;
24;     unsigned int exp :15;
25;     unsigned int sign :1;
26;   } bits;
27;   struct {
28;     unsigned long manl :64;
29;     unsigned long manh :48;
30;     unsigned int expsign :16;
31;   } xbits;
32; };
33
34; C code:
35; void foo(__float128 x);
36; void TestUnionLD1(__float128 s, unsigned long n) {
37;      union IEEEl2bits u;
38;      __float128 w;
39;      u.e = s;
40;      u.bits.manh = n;
41;      w = u.e;
42;      foo(w);
43; }
44define void @TestUnionLD1(fp128 %s, i64 %n) #0 {
45; CHECK-LABEL: TestUnionLD1:
46; CHECK:       # %bb.0: # %entry
47; CHECK-NEXT:    movaps %xmm0, -{{[0-9]+}}(%rsp)
48; CHECK-NEXT:    movq -{{[0-9]+}}(%rsp), %rax
49; CHECK-NEXT:    movabsq $281474976710655, %rcx # imm = 0xFFFFFFFFFFFF
50; CHECK-NEXT:    andq %rdi, %rcx
51; CHECK-NEXT:    movabsq $-281474976710656, %rdx # imm = 0xFFFF000000000000
52; CHECK-NEXT:    andq -{{[0-9]+}}(%rsp), %rdx
53; CHECK-NEXT:    orq %rcx, %rdx
54; CHECK-NEXT:    movq %rax, -{{[0-9]+}}(%rsp)
55; CHECK-NEXT:    movq %rdx, -{{[0-9]+}}(%rsp)
56; CHECK-NEXT:    movaps -{{[0-9]+}}(%rsp), %xmm0
57; CHECK-NEXT:    jmp foo # TAILCALL
58entry:
59  %0 = bitcast fp128 %s to i128
60  %1 = zext i64 %n to i128
61  %bf.value = shl nuw i128 %1, 64
62  %bf.shl = and i128 %bf.value, 5192296858534809181786422619668480
63  %bf.clear = and i128 %0, -5192296858534809181786422619668481
64  %bf.set = or i128 %bf.shl, %bf.clear
65  %2 = bitcast i128 %bf.set to fp128
66  tail call void @foo(fp128 %2) #2
67  ret void
68}
69
70; C code:
71; __float128 TestUnionLD2(__float128 s) {
72;      union IEEEl2bits u;
73;      __float128 w;
74;      u.e = s;
75;      u.bits.manl = 0;
76;      w = u.e;
77;      return w;
78; }
79define fp128 @TestUnionLD2(fp128 %s) #0 {
80; CHECK-LABEL: TestUnionLD2:
81; CHECK:       # %bb.0: # %entry
82; CHECK-NEXT:    movaps %xmm0, -{{[0-9]+}}(%rsp)
83; CHECK-NEXT:    movq -{{[0-9]+}}(%rsp), %rax
84; CHECK-NEXT:    movq %rax, -{{[0-9]+}}(%rsp)
85; CHECK-NEXT:    movq $0, -{{[0-9]+}}(%rsp)
86; CHECK-NEXT:    movaps -{{[0-9]+}}(%rsp), %xmm0
87; CHECK-NEXT:    retq
88entry:
89  %0 = bitcast fp128 %s to i128
90  %bf.clear = and i128 %0, -18446744073709551616
91  %1 = bitcast i128 %bf.clear to fp128
92  ret fp128 %1
93}
94
95; C code:
96; __float128 TestI128_1(__float128 x)
97; {
98;  union IEEEl2bits z;
99;  z.e = x;
100;  z.bits.sign = 0;
101;  return (z.e < 0.1L) ? 1.0L : 2.0L;
102; }
103define fp128 @TestI128_1(fp128 %x) #0 {
104; CHECK-LABEL: TestI128_1:
105; CHECK:       # %bb.0: # %entry
106; CHECK-NEXT:    subq $40, %rsp
107; CHECK-NEXT:    movaps %xmm0, {{[0-9]+}}(%rsp)
108; CHECK-NEXT:    movabsq $9223372036854775807, %rax # imm = 0x7FFFFFFFFFFFFFFF
109; CHECK-NEXT:    andq {{[0-9]+}}(%rsp), %rax
110; CHECK-NEXT:    movq {{[0-9]+}}(%rsp), %rcx
111; CHECK-NEXT:    movq %rax, {{[0-9]+}}(%rsp)
112; CHECK-NEXT:    movq %rcx, (%rsp)
113; CHECK-NEXT:    movaps (%rsp), %xmm0
114; CHECK-NEXT:    movaps {{.*}}(%rip), %xmm1
115; CHECK-NEXT:    callq __lttf2
116; CHECK-NEXT:    xorl %ecx, %ecx
117; CHECK-NEXT:    testl %eax, %eax
118; CHECK-NEXT:    sets %cl
119; CHECK-NEXT:    shlq $4, %rcx
120; CHECK-NEXT:    movaps {{\.LCPI.*}}(%rcx), %xmm0
121; CHECK-NEXT:    addq $40, %rsp
122; CHECK-NEXT:    retq
123entry:
124  %0 = bitcast fp128 %x to i128
125  %bf.clear = and i128 %0, 170141183460469231731687303715884105727
126  %1 = bitcast i128 %bf.clear to fp128
127  %cmp = fcmp olt fp128 %1, 0xL999999999999999A3FFB999999999999
128  %cond = select i1 %cmp, fp128 0xL00000000000000003FFF000000000000, fp128 0xL00000000000000004000000000000000
129  ret fp128 %cond
130}
131
132; C code:
133; __float128 TestI128_2(__float128 x, __float128 y)
134; {
135;  unsigned short hx;
136;  union IEEEl2bits ge_u;
137;  ge_u.e = x;
138;  hx = ge_u.xbits.expsign;
139;  return (hx & 0x8000) == 0 ? x : y;
140; }
141define fp128 @TestI128_2(fp128 %x, fp128 %y) #0 {
142; CHECK-LABEL: TestI128_2:
143; CHECK:       # %bb.0: # %entry
144; CHECK-NEXT:    movaps %xmm0, -{{[0-9]+}}(%rsp)
145; CHECK-NEXT:    cmpq $0, -{{[0-9]+}}(%rsp)
146; CHECK-NEXT:    jns .LBB3_2
147; CHECK-NEXT:  # %bb.1: # %entry
148; CHECK-NEXT:    movaps %xmm1, %xmm0
149; CHECK-NEXT:  .LBB3_2: # %entry
150; CHECK-NEXT:    retq
151entry:
152  %0 = bitcast fp128 %x to i128
153  %cmp = icmp sgt i128 %0, -1
154  %cond = select i1 %cmp, fp128 %x, fp128 %y
155  ret fp128 %cond
156}
157
158; C code:
159; __float128 TestI128_3(__float128 x, int *ex)
160; {
161;  union IEEEl2bits u;
162;  u.e = x;
163;  if (u.bits.exp == 0) {
164;    u.e *= 0x1.0p514;
165;    u.bits.exp = 0x3ffe;
166;  }
167;  return (u.e);
168; }
169define fp128 @TestI128_3(fp128 %x, i32* nocapture readnone %ex) #0 {
170; CHECK-LABEL: TestI128_3:
171; CHECK:       # %bb.0: # %entry
172; CHECK-NEXT:    subq $56, %rsp
173; CHECK-NEXT:    movaps %xmm0, {{[0-9]+}}(%rsp)
174; CHECK-NEXT:    movq {{[0-9]+}}(%rsp), %rax
175; CHECK-NEXT:    movabsq $9223090561878065152, %rcx # imm = 0x7FFF000000000000
176; CHECK-NEXT:    testq %rcx, %rax
177; CHECK-NEXT:    je .LBB4_2
178; CHECK-NEXT:  # %bb.1:
179; CHECK-NEXT:    movq {{[0-9]+}}(%rsp), %rcx
180; CHECK-NEXT:    jmp .LBB4_3
181; CHECK-NEXT:  .LBB4_2: # %if.then
182; CHECK-NEXT:    movaps {{.*}}(%rip), %xmm1
183; CHECK-NEXT:    callq __multf3
184; CHECK-NEXT:    movaps %xmm0, {{[0-9]+}}(%rsp)
185; CHECK-NEXT:    movq {{[0-9]+}}(%rsp), %rcx
186; CHECK-NEXT:    movabsq $-9223090561878065153, %rdx # imm = 0x8000FFFFFFFFFFFF
187; CHECK-NEXT:    andq {{[0-9]+}}(%rsp), %rdx
188; CHECK-NEXT:    movabsq $4611123068473966592, %rax # imm = 0x3FFE000000000000
189; CHECK-NEXT:    orq %rdx, %rax
190; CHECK-NEXT:  .LBB4_3: # %if.end
191; CHECK-NEXT:    movq %rcx, (%rsp)
192; CHECK-NEXT:    movq %rax, {{[0-9]+}}(%rsp)
193; CHECK-NEXT:    movaps (%rsp), %xmm0
194; CHECK-NEXT:    addq $56, %rsp
195; CHECK-NEXT:    retq
196entry:
197  %0 = bitcast fp128 %x to i128
198  %bf.cast = and i128 %0, 170135991163610696904058773219554885632
199  %cmp = icmp eq i128 %bf.cast, 0
200  br i1 %cmp, label %if.then, label %if.end
201
202if.then:                                          ; preds = %entry
203  %mul = fmul fp128 %x, 0xL00000000000000004201000000000000
204  %1 = bitcast fp128 %mul to i128
205  %bf.clear4 = and i128 %1, -170135991163610696904058773219554885633
206  %bf.set = or i128 %bf.clear4, 85060207136517546210586590865283612672
207  br label %if.end
208
209if.end:                                           ; preds = %if.then, %entry
210  %u.sroa.0.0 = phi i128 [ %bf.set, %if.then ], [ %0, %entry ]
211  %2 = bitcast i128 %u.sroa.0.0 to fp128
212  ret fp128 %2
213}
214
215; C code:
216; __float128 TestI128_4(__float128 x)
217; {
218;  union IEEEl2bits u;
219;  __float128 df;
220;  u.e = x;
221;  u.xbits.manl = 0;
222;  df = u.e;
223;  return x + df;
224; }
225define fp128 @TestI128_4(fp128 %x) #0 {
226; CHECK-LABEL: TestI128_4:
227; CHECK:       # %bb.0: # %entry
228; CHECK-NEXT:    subq $40, %rsp
229; CHECK-NEXT:    movaps %xmm0, %xmm1
230; CHECK-NEXT:    movaps %xmm0, {{[0-9]+}}(%rsp)
231; CHECK-NEXT:    movq {{[0-9]+}}(%rsp), %rax
232; CHECK-NEXT:    movq %rax, {{[0-9]+}}(%rsp)
233; CHECK-NEXT:    movq $0, (%rsp)
234; CHECK-NEXT:    movaps (%rsp), %xmm0
235; CHECK-NEXT:    callq __addtf3
236; CHECK-NEXT:    addq $40, %rsp
237; CHECK-NEXT:    retq
238entry:
239  %0 = bitcast fp128 %x to i128
240  %bf.clear = and i128 %0, -18446744073709551616
241  %1 = bitcast i128 %bf.clear to fp128
242  %add = fadd fp128 %1, %x
243  ret fp128 %add
244}
245
246@v128 = common global i128 0, align 16
247@v128_2 = common global i128 0, align 16
248
249; C code:
250; unsigned __int128 v128, v128_2;
251; void TestShift128_2() {
252;   v128 = ((v128 << 96) | v128_2);
253; }
254define void @TestShift128_2() #2 {
255; CHECK-LABEL: TestShift128_2:
256; CHECK:       # %bb.0: # %entry
257; CHECK-NEXT:    movq {{.*}}(%rip), %rax
258; CHECK-NEXT:    shlq $32, %rax
259; CHECK-NEXT:    movq {{.*}}(%rip), %rcx
260; CHECK-NEXT:    orq v128_2+{{.*}}(%rip), %rax
261; CHECK-NEXT:    movq %rcx, {{.*}}(%rip)
262; CHECK-NEXT:    movq %rax, v128+{{.*}}(%rip)
263; CHECK-NEXT:    retq
264entry:
265  %0 = load i128, i128* @v128, align 16
266  %shl = shl i128 %0, 96
267  %1 = load i128, i128* @v128_2, align 16
268  %or = or i128 %shl, %1
269  store i128 %or, i128* @v128, align 16
270  ret void
271}
272
273define fp128 @acosl(fp128 %x) #0 {
274; CHECK-LABEL: acosl:
275; CHECK:       # %bb.0: # %entry
276; CHECK-NEXT:    subq $40, %rsp
277; CHECK-NEXT:    movaps %xmm0, %xmm1
278; CHECK-NEXT:    movaps %xmm0, {{[0-9]+}}(%rsp)
279; CHECK-NEXT:    movq {{[0-9]+}}(%rsp), %rax
280; CHECK-NEXT:    movq %rax, {{[0-9]+}}(%rsp)
281; CHECK-NEXT:    movq $0, (%rsp)
282; CHECK-NEXT:    movaps (%rsp), %xmm0
283; CHECK-NEXT:    callq __addtf3
284; CHECK-NEXT:    addq $40, %rsp
285; CHECK-NEXT:    retq
286entry:
287  %0 = bitcast fp128 %x to i128
288  %bf.clear = and i128 %0, -18446744073709551616
289  %1 = bitcast i128 %bf.clear to fp128
290  %add = fadd fp128 %1, %x
291  ret fp128 %add
292}
293
294; Compare i128 values and check i128 constants.
295define fp128 @TestComp(fp128 %x, fp128 %y) #0 {
296; CHECK-LABEL: TestComp:
297; CHECK:       # %bb.0: # %entry
298; CHECK-NEXT:    movaps %xmm0, -{{[0-9]+}}(%rsp)
299; CHECK-NEXT:    cmpq $0, -{{[0-9]+}}(%rsp)
300; CHECK-NEXT:    jns .LBB8_2
301; CHECK-NEXT:  # %bb.1: # %entry
302; CHECK-NEXT:    movaps %xmm1, %xmm0
303; CHECK-NEXT:  .LBB8_2: # %entry
304; CHECK-NEXT:    retq
305entry:
306  %0 = bitcast fp128 %x to i128
307  %cmp = icmp sgt i128 %0, -1
308  %cond = select i1 %cmp, fp128 %x, fp128 %y
309  ret fp128 %cond
310}
311
312declare void @foo(fp128) #1
313
314; Test logical operations on fp128 values.
315define fp128 @TestFABS_LD(fp128 %x) #0 {
316; CHECK-LABEL: TestFABS_LD:
317; CHECK:       # %bb.0: # %entry
318; CHECK-NEXT:    andps {{.*}}(%rip), %xmm0
319; CHECK-NEXT:    retq
320entry:
321  %call = tail call fp128 @fabsl(fp128 %x) #2
322  ret fp128 %call
323}
324
325declare fp128 @fabsl(fp128) #1
326
327declare fp128 @copysignl(fp128, fp128) #1
328
329; Test more complicated logical operations generated from copysignl.
330define void @TestCopySign({ fp128, fp128 }* noalias nocapture sret %agg.result, { fp128, fp128 }* byval nocapture readonly align 16 %z) #0 {
331; CHECK-LABEL: TestCopySign:
332; CHECK:       # %bb.0: # %entry
333; CHECK-NEXT:    pushq %rbp
334; CHECK-NEXT:    pushq %rbx
335; CHECK-NEXT:    subq $40, %rsp
336; CHECK-NEXT:    movq %rdi, %rbx
337; CHECK-NEXT:    movaps {{[0-9]+}}(%rsp), %xmm0
338; CHECK-NEXT:    movaps {{[0-9]+}}(%rsp), %xmm1
339; CHECK-NEXT:    movaps %xmm1, {{[-0-9]+}}(%r{{[sb]}}p) # 16-byte Spill
340; CHECK-NEXT:    movaps %xmm0, (%rsp) # 16-byte Spill
341; CHECK-NEXT:    callq __gttf2
342; CHECK-NEXT:    movl %eax, %ebp
343; CHECK-NEXT:    movaps {{[-0-9]+}}(%r{{[sb]}}p), %xmm0 # 16-byte Reload
344; CHECK-NEXT:    movaps %xmm0, %xmm1
345; CHECK-NEXT:    callq __subtf3
346; CHECK-NEXT:    testl %ebp, %ebp
347; CHECK-NEXT:    jle .LBB10_1
348; CHECK-NEXT:  # %bb.2: # %if.then
349; CHECK-NEXT:    andps {{.*}}(%rip), %xmm0
350; CHECK-NEXT:    movaps %xmm0, %xmm1
351; CHECK-NEXT:    movaps (%rsp), %xmm0 # 16-byte Reload
352; CHECK-NEXT:    movaps %xmm1, %xmm2
353; CHECK-NEXT:    jmp .LBB10_3
354; CHECK-NEXT:  .LBB10_1:
355; CHECK-NEXT:    movaps (%rsp), %xmm2 # 16-byte Reload
356; CHECK-NEXT:  .LBB10_3: # %cleanup
357; CHECK-NEXT:    movaps {{.*}}(%rip), %xmm1
358; CHECK-NEXT:    andps {{.*}}(%rip), %xmm0
359; CHECK-NEXT:    andps {{[-0-9]+}}(%r{{[sb]}}p), %xmm1 # 16-byte Folded Reload
360; CHECK-NEXT:    orps %xmm1, %xmm0
361; CHECK-NEXT:    movaps %xmm2, (%rbx)
362; CHECK-NEXT:    movaps %xmm0, 16(%rbx)
363; CHECK-NEXT:    movq %rbx, %rax
364; CHECK-NEXT:    addq $40, %rsp
365; CHECK-NEXT:    popq %rbx
366; CHECK-NEXT:    popq %rbp
367; CHECK-NEXT:    retq
368entry:
369  %z.realp = getelementptr inbounds { fp128, fp128 }, { fp128, fp128 }* %z, i64 0, i32 0
370  %z.real = load fp128, fp128* %z.realp, align 16
371  %z.imagp = getelementptr inbounds { fp128, fp128 }, { fp128, fp128 }* %z, i64 0, i32 1
372  %z.imag4 = load fp128, fp128* %z.imagp, align 16
373  %cmp = fcmp ogt fp128 %z.real, %z.imag4
374  %sub = fsub fp128 %z.imag4, %z.imag4
375  br i1 %cmp, label %if.then, label %cleanup
376
377if.then:                                          ; preds = %entry
378  %call = tail call fp128 @fabsl(fp128 %sub) #2
379  br label %cleanup
380
381cleanup:                                          ; preds = %entry, %if.then
382  %z.real.sink = phi fp128 [ %z.real, %if.then ], [ %sub, %entry ]
383  %call.sink = phi fp128 [ %call, %if.then ], [ %z.real, %entry ]
384  %call5 = tail call fp128 @copysignl(fp128 %z.real.sink, fp128 %z.imag4) #2
385  %0 = getelementptr inbounds { fp128, fp128 }, { fp128, fp128 }* %agg.result, i64 0, i32 0
386  %1 = getelementptr inbounds { fp128, fp128 }, { fp128, fp128 }* %agg.result, i64 0, i32 1
387  store fp128 %call.sink, fp128* %0, align 16
388  store fp128 %call5, fp128* %1, align 16
389  ret void
390}
391
392
393attributes #0 = { nounwind "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" }
394attributes #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" }
395attributes #2 = { nounwind readnone }
396