Home | History | Annotate | Download | only in X86
      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 }
    321