Home | History | Annotate | Download | only in X86
      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 ; }
     44 define 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
     58 entry:
     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 ; }
     79 define 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
     88 entry:
     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 ; }
    103 define 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
    123 entry:
    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 ; }
    141 define 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
    151 entry:
    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 ; }
    169 define 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
    196 entry:
    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 
    202 if.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 
    209 if.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 ; }
    225 define 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
    238 entry:
    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 ; }
    254 define 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
    264 entry:
    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 
    273 define 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
    286 entry:
    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.
    295 define 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
    305 entry:
    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 
    312 declare void @foo(fp128) #1
    313 
    314 ; Test logical operations on fp128 values.
    315 define 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
    320 entry:
    321   %call = tail call fp128 @fabsl(fp128 %x) #2
    322   ret fp128 %call
    323 }
    324 
    325 declare fp128 @fabsl(fp128) #1
    326 
    327 declare fp128 @copysignl(fp128, fp128) #1
    328 
    329 ; Test more complicated logical operations generated from copysignl.
    330 define 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
    368 entry:
    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 
    377 if.then:                                          ; preds = %entry
    378   %call = tail call fp128 @fabsl(fp128 %sub) #2
    379   br label %cleanup
    380 
    381 cleanup:                                          ; 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 
    393 attributes #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" }
    394 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" }
    395 attributes #2 = { nounwind readnone }
    396