Home | History | Annotate | Download | only in AArch64
      1 ; RUN: llc < %s -mtriple aarch64-unknown-unknown -aarch64-neon-syntax=apple -asm-verbose=false -disable-post-ra -disable-fp-elim | FileCheck %s
      2 
      3 target datalayout = "e-m:o-i64:64-i128:128-n32:64-S128"
      4 
      5 ; CHECK-LABEL: test_fadd:
      6 ; CHECK-NEXT: fcvt s1, h1
      7 ; CHECK-NEXT: fcvt s0, h0
      8 ; CHECK-NEXT: fadd s0, s0, s1
      9 ; CHECK-NEXT: fcvt h0, s0
     10 ; CHECK-NEXT: ret
     11 define half @test_fadd(half %a, half %b) #0 {
     12   %r = fadd half %a, %b
     13   ret half %r
     14 }
     15 
     16 ; CHECK-LABEL: test_fsub:
     17 ; CHECK-NEXT: fcvt s1, h1
     18 ; CHECK-NEXT: fcvt s0, h0
     19 ; CHECK-NEXT: fsub s0, s0, s1
     20 ; CHECK-NEXT: fcvt h0, s0
     21 ; CHECK-NEXT: ret
     22 define half @test_fsub(half %a, half %b) #0 {
     23   %r = fsub half %a, %b
     24   ret half %r
     25 }
     26 
     27 ; CHECK-LABEL: test_fmul:
     28 ; CHECK-NEXT: fcvt s1, h1
     29 ; CHECK-NEXT: fcvt s0, h0
     30 ; CHECK-NEXT: fmul s0, s0, s1
     31 ; CHECK-NEXT: fcvt h0, s0
     32 ; CHECK-NEXT: ret
     33 define half @test_fmul(half %a, half %b) #0 {
     34   %r = fmul half %a, %b
     35   ret half %r
     36 }
     37 
     38 ; CHECK-LABEL: test_fdiv:
     39 ; CHECK-NEXT: fcvt s1, h1
     40 ; CHECK-NEXT: fcvt s0, h0
     41 ; CHECK-NEXT: fdiv s0, s0, s1
     42 ; CHECK-NEXT: fcvt h0, s0
     43 ; CHECK-NEXT: ret
     44 define half @test_fdiv(half %a, half %b) #0 {
     45   %r = fdiv half %a, %b
     46   ret half %r
     47 }
     48 
     49 ; CHECK-LABEL: test_frem:
     50 ; CHECK-NEXT: stp x29, x30, [sp, #-16]!
     51 ; CHECK-NEXT: mov  x29, sp
     52 ; CHECK-NEXT: fcvt s0, h0
     53 ; CHECK-NEXT: fcvt s1, h1
     54 ; CHECK-NEXT: bl {{_?}}fmodf
     55 ; CHECK-NEXT: fcvt h0, s0
     56 ; CHECK-NEXT: ldp x29, x30, [sp], #16
     57 ; CHECK-NEXT: ret
     58 define half @test_frem(half %a, half %b) #0 {
     59   %r = frem half %a, %b
     60   ret half %r
     61 }
     62 
     63 ; CHECK-LABEL: test_store:
     64 ; CHECK-NEXT: str  h0, [x0]
     65 ; CHECK-NEXT: ret
     66 define void @test_store(half %a, half* %b) #0 {
     67   store half %a, half* %b
     68   ret void
     69 }
     70 
     71 ; CHECK-LABEL: test_load:
     72 ; CHECK-NEXT: ldr  h0, [x0]
     73 ; CHECK-NEXT: ret
     74 define half @test_load(half* %a) #0 {
     75   %r = load half, half* %a
     76   ret half %r
     77 }
     78 
     79 
     80 declare half @test_callee(half %a, half %b) #0
     81 
     82 ; CHECK-LABEL: test_call:
     83 ; CHECK-NEXT: stp x29, x30, [sp, #-16]!
     84 ; CHECK-NEXT: mov  x29, sp
     85 ; CHECK-NEXT: bl {{_?}}test_callee
     86 ; CHECK-NEXT: ldp x29, x30, [sp], #16
     87 ; CHECK-NEXT: ret
     88 define half @test_call(half %a, half %b) #0 {
     89   %r = call half @test_callee(half %a, half %b)
     90   ret half %r
     91 }
     92 
     93 ; CHECK-LABEL: test_call_flipped:
     94 ; CHECK-NEXT: stp x29, x30, [sp, #-16]!
     95 ; CHECK-NEXT: mov  x29, sp
     96 ; CHECK-NEXT: mov.16b  v2, v0
     97 ; CHECK-NEXT: mov.16b  v0, v1
     98 ; CHECK-NEXT: mov.16b  v1, v2
     99 ; CHECK-NEXT: bl {{_?}}test_callee
    100 ; CHECK-NEXT: ldp x29, x30, [sp], #16
    101 ; CHECK-NEXT: ret
    102 define half @test_call_flipped(half %a, half %b) #0 {
    103   %r = call half @test_callee(half %b, half %a)
    104   ret half %r
    105 }
    106 
    107 ; CHECK-LABEL: test_tailcall_flipped:
    108 ; CHECK-NEXT: mov.16b  v2, v0
    109 ; CHECK-NEXT: mov.16b  v0, v1
    110 ; CHECK-NEXT: mov.16b  v1, v2
    111 ; CHECK-NEXT: b {{_?}}test_callee
    112 define half @test_tailcall_flipped(half %a, half %b) #0 {
    113   %r = tail call half @test_callee(half %b, half %a)
    114   ret half %r
    115 }
    116 
    117 ; CHECK-LABEL: test_select:
    118 ; CHECK-NEXT: fcvt s1, h1
    119 ; CHECK-NEXT: fcvt s0, h0
    120 ; CHECK-NEXT: cmp  w0, #0
    121 ; CHECK-NEXT: fcsel s0, s0, s1, ne
    122 ; CHECK-NEXT: fcvt h0, s0
    123 ; CHECK-NEXT: ret
    124 define half @test_select(half %a, half %b, i1 zeroext %c) #0 {
    125   %r = select i1 %c, half %a, half %b
    126   ret half %r
    127 }
    128 
    129 ; CHECK-LABEL: test_select_cc:
    130 ; CHECK-DAG: fcvt s3, h3
    131 ; CHECK-DAG: fcvt s2, h2
    132 ; CHECK-DAG: fcvt s1, h1
    133 ; CHECK-DAG: fcvt s0, h0
    134 ; CHECK-DAG: fcmp s2, s3
    135 ; CHECK-DAG: cset [[CC:w[0-9]+]], ne
    136 ; CHECK-DAG: cmp [[CC]], #0
    137 ; CHECK-NEXT: fcsel s0, s0, s1, ne
    138 ; CHECK-NEXT: fcvt h0, s0
    139 ; CHECK-NEXT: ret
    140 define half @test_select_cc(half %a, half %b, half %c, half %d) #0 {
    141   %cc = fcmp une half %c, %d
    142   %r = select i1 %cc, half %a, half %b
    143   ret half %r
    144 }
    145 
    146 ; CHECK-LABEL: test_select_cc_f32_f16:
    147 ; CHECK-DAG:   fcvt s2, h2
    148 ; CHECK-DAG:   fcvt s3, h3
    149 ; CHECK-NEXT:  fcmp s2, s3
    150 ; CHECK-NEXT:  fcsel s0, s0, s1, ne
    151 ; CHECK-NEXT:  ret
    152 define float @test_select_cc_f32_f16(float %a, float %b, half %c, half %d) #0 {
    153   %cc = fcmp une half %c, %d
    154   %r = select i1 %cc, float %a, float %b
    155   ret float %r
    156 }
    157 
    158 ; CHECK-LABEL: test_select_cc_f16_f32:
    159 ; CHECK-DAG:  fcvt s0, h0
    160 ; CHECK-DAG:  fcvt s1, h1
    161 ; CHECK-DAG:  fcmp s2, s3
    162 ; CHECK-DAG:  cset w8, ne
    163 ; CHECK-NEXT: cmp w8, #0
    164 ; CHECK-NEXT: fcsel s0, s0, s1, ne
    165 ; CHECK-NEXT: fcvt h0, s0
    166 ; CHECK-NEXT: ret
    167 define half @test_select_cc_f16_f32(half %a, half %b, float %c, float %d) #0 {
    168   %cc = fcmp une float %c, %d
    169   %r = select i1 %cc, half %a, half %b
    170   ret half %r
    171 }
    172 
    173 ; CHECK-LABEL: test_fcmp_une:
    174 ; CHECK-NEXT: fcvt s1, h1
    175 ; CHECK-NEXT: fcvt s0, h0
    176 ; CHECK-NEXT: fcmp s0, s1
    177 ; CHECK-NEXT: cset  w0, ne
    178 ; CHECK-NEXT: ret
    179 define i1 @test_fcmp_une(half %a, half %b) #0 {
    180   %r = fcmp une half %a, %b
    181   ret i1 %r
    182 }
    183 
    184 ; CHECK-LABEL: test_fcmp_ueq:
    185 ; CHECK-NEXT: fcvt s1, h1
    186 ; CHECK-NEXT: fcvt s0, h0
    187 ; CHECK-NEXT: fcmp s0, s1
    188 ; CHECK-NEXT: orr [[TRUE:w[0-9]+]], wzr, #0x1
    189 ; CHECK-NEXT: csel [[CC:w[0-9]+]], [[TRUE]], wzr, eq
    190 ; CHECK-NEXT: csel w0, [[TRUE]], [[CC]], vs
    191 ; CHECK-NEXT: ret
    192 define i1 @test_fcmp_ueq(half %a, half %b) #0 {
    193   %r = fcmp ueq half %a, %b
    194   ret i1 %r
    195 }
    196 
    197 ; CHECK-LABEL: test_fcmp_ugt:
    198 ; CHECK-NEXT: fcvt s1, h1
    199 ; CHECK-NEXT: fcvt s0, h0
    200 ; CHECK-NEXT: fcmp s0, s1
    201 ; CHECK-NEXT: cset  w0, hi
    202 ; CHECK-NEXT: ret
    203 define i1 @test_fcmp_ugt(half %a, half %b) #0 {
    204   %r = fcmp ugt half %a, %b
    205   ret i1 %r
    206 }
    207 
    208 ; CHECK-LABEL: test_fcmp_uge:
    209 ; CHECK-NEXT: fcvt s1, h1
    210 ; CHECK-NEXT: fcvt s0, h0
    211 ; CHECK-NEXT: fcmp s0, s1
    212 ; CHECK-NEXT: cset  w0, pl
    213 ; CHECK-NEXT: ret
    214 define i1 @test_fcmp_uge(half %a, half %b) #0 {
    215   %r = fcmp uge half %a, %b
    216   ret i1 %r
    217 }
    218 
    219 ; CHECK-LABEL: test_fcmp_ult:
    220 ; CHECK-NEXT: fcvt s1, h1
    221 ; CHECK-NEXT: fcvt s0, h0
    222 ; CHECK-NEXT: fcmp s0, s1
    223 ; CHECK-NEXT: cset  w0, lt
    224 ; CHECK-NEXT: ret
    225 define i1 @test_fcmp_ult(half %a, half %b) #0 {
    226   %r = fcmp ult half %a, %b
    227   ret i1 %r
    228 }
    229 
    230 ; CHECK-LABEL: test_fcmp_ule:
    231 ; CHECK-NEXT: fcvt s1, h1
    232 ; CHECK-NEXT: fcvt s0, h0
    233 ; CHECK-NEXT: fcmp s0, s1
    234 ; CHECK-NEXT: cset  w0, le
    235 ; CHECK-NEXT: ret
    236 define i1 @test_fcmp_ule(half %a, half %b) #0 {
    237   %r = fcmp ule half %a, %b
    238   ret i1 %r
    239 }
    240 
    241 
    242 ; CHECK-LABEL: test_fcmp_uno:
    243 ; CHECK-NEXT: fcvt s1, h1
    244 ; CHECK-NEXT: fcvt s0, h0
    245 ; CHECK-NEXT: fcmp s0, s1
    246 ; CHECK-NEXT: cset  w0, vs
    247 ; CHECK-NEXT: ret
    248 define i1 @test_fcmp_uno(half %a, half %b) #0 {
    249   %r = fcmp uno half %a, %b
    250   ret i1 %r
    251 }
    252 
    253 ; CHECK-LABEL: test_fcmp_one:
    254 ; CHECK-NEXT: fcvt s1, h1
    255 ; CHECK-NEXT: fcvt s0, h0
    256 ; CHECK-NEXT: fcmp s0, s1
    257 ; CHECK-NEXT: orr [[TRUE:w[0-9]+]], wzr, #0x1
    258 ; CHECK-NEXT: csel [[CC:w[0-9]+]], [[TRUE]], wzr, mi
    259 ; CHECK-NEXT: csel w0, [[TRUE]], [[CC]], gt
    260 ; CHECK-NEXT: ret
    261 define i1 @test_fcmp_one(half %a, half %b) #0 {
    262   %r = fcmp one half %a, %b
    263   ret i1 %r
    264 }
    265 
    266 ; CHECK-LABEL: test_fcmp_oeq:
    267 ; CHECK-NEXT: fcvt s1, h1
    268 ; CHECK-NEXT: fcvt s0, h0
    269 ; CHECK-NEXT: fcmp s0, s1
    270 ; CHECK-NEXT: cset  w0, eq
    271 ; CHECK-NEXT: ret
    272 define i1 @test_fcmp_oeq(half %a, half %b) #0 {
    273   %r = fcmp oeq half %a, %b
    274   ret i1 %r
    275 }
    276 
    277 ; CHECK-LABEL: test_fcmp_ogt:
    278 ; CHECK-NEXT: fcvt s1, h1
    279 ; CHECK-NEXT: fcvt s0, h0
    280 ; CHECK-NEXT: fcmp s0, s1
    281 ; CHECK-NEXT: cset  w0, gt
    282 ; CHECK-NEXT: ret
    283 define i1 @test_fcmp_ogt(half %a, half %b) #0 {
    284   %r = fcmp ogt half %a, %b
    285   ret i1 %r
    286 }
    287 
    288 ; CHECK-LABEL: test_fcmp_oge:
    289 ; CHECK-NEXT: fcvt s1, h1
    290 ; CHECK-NEXT: fcvt s0, h0
    291 ; CHECK-NEXT: fcmp s0, s1
    292 ; CHECK-NEXT: cset  w0, ge
    293 ; CHECK-NEXT: ret
    294 define i1 @test_fcmp_oge(half %a, half %b) #0 {
    295   %r = fcmp oge half %a, %b
    296   ret i1 %r
    297 }
    298 
    299 ; CHECK-LABEL: test_fcmp_olt:
    300 ; CHECK-NEXT: fcvt s1, h1
    301 ; CHECK-NEXT: fcvt s0, h0
    302 ; CHECK-NEXT: fcmp s0, s1
    303 ; CHECK-NEXT: cset  w0, mi
    304 ; CHECK-NEXT: ret
    305 define i1 @test_fcmp_olt(half %a, half %b) #0 {
    306   %r = fcmp olt half %a, %b
    307   ret i1 %r
    308 }
    309 
    310 ; CHECK-LABEL: test_fcmp_ole:
    311 ; CHECK-NEXT: fcvt s1, h1
    312 ; CHECK-NEXT: fcvt s0, h0
    313 ; CHECK-NEXT: fcmp s0, s1
    314 ; CHECK-NEXT: cset  w0, ls
    315 ; CHECK-NEXT: ret
    316 define i1 @test_fcmp_ole(half %a, half %b) #0 {
    317   %r = fcmp ole half %a, %b
    318   ret i1 %r
    319 }
    320 
    321 ; CHECK-LABEL: test_fcmp_ord:
    322 ; CHECK-NEXT: fcvt s1, h1
    323 ; CHECK-NEXT: fcvt s0, h0
    324 ; CHECK-NEXT: fcmp s0, s1
    325 ; CHECK-NEXT: cset  w0, vc
    326 ; CHECK-NEXT: ret
    327 define i1 @test_fcmp_ord(half %a, half %b) #0 {
    328   %r = fcmp ord half %a, %b
    329   ret i1 %r
    330 }
    331 
    332 ; CHECK-LABEL: test_br_cc:
    333 ; CHECK-NEXT: fcvt s1, h1
    334 ; CHECK-NEXT: fcvt s0, h0
    335 ; CHECK-NEXT: fcmp s0, s1
    336 ; CHECK-NEXT: b.mi [[BRCC_ELSE:.?LBB[0-9_]+]]
    337 ; CHECK-NEXT: str  wzr, [x0]
    338 ; CHECK-NEXT: ret
    339 ; CHECK-NEXT: [[BRCC_ELSE]]:
    340 ; CHECK-NEXT: str  wzr, [x1]
    341 ; CHECK-NEXT: ret
    342 define void @test_br_cc(half %a, half %b, i32* %p1, i32* %p2) #0 {
    343   %c = fcmp uge half %a, %b
    344   br i1 %c, label %then, label %else
    345 then:
    346   store i32 0, i32* %p1
    347   ret void
    348 else:
    349   store i32 0, i32* %p2
    350   ret void
    351 }
    352 
    353 ; CHECK-LABEL: test_phi:
    354 ; CHECK: mov  x[[PTR:[0-9]+]], x0
    355 ; CHECK: ldr  h[[AB:[0-9]+]], [x[[PTR]]]
    356 ; CHECK: [[LOOP:LBB[0-9_]+]]:
    357 ; CHECK: mov.16b  v[[R:[0-9]+]], v[[AB]]
    358 ; CHECK: ldr  h[[AB]], [x[[PTR]]]
    359 ; CHECK: mov  x0, x[[PTR]]
    360 ; CHECK: bl {{_?}}test_dummy
    361 ; CHECK: mov.16b  v0, v[[R]]
    362 ; CHECK: ret
    363 define half @test_phi(half* %p1) #0 {
    364 entry:
    365   %a = load half, half* %p1
    366   br label %loop
    367 loop:
    368   %r = phi half [%a, %entry], [%b, %loop]
    369   %b = load half, half* %p1
    370   %c = call i1 @test_dummy(half* %p1)
    371   br i1 %c, label %loop, label %return
    372 return:
    373   ret half %r
    374 }
    375 declare i1 @test_dummy(half* %p1) #0
    376 
    377 ; CHECK-LABEL: test_fptosi_i32:
    378 ; CHECK-NEXT: fcvt s0, h0
    379 ; CHECK-NEXT: fcvtzs w0, s0
    380 ; CHECK-NEXT: ret
    381 define i32 @test_fptosi_i32(half %a) #0 {
    382   %r = fptosi half %a to i32
    383   ret i32 %r
    384 }
    385 
    386 ; CHECK-LABEL: test_fptosi_i64:
    387 ; CHECK-NEXT: fcvt s0, h0
    388 ; CHECK-NEXT: fcvtzs x0, s0
    389 ; CHECK-NEXT: ret
    390 define i64 @test_fptosi_i64(half %a) #0 {
    391   %r = fptosi half %a to i64
    392   ret i64 %r
    393 }
    394 
    395 ; CHECK-LABEL: test_fptoui_i32:
    396 ; CHECK-NEXT: fcvt s0, h0
    397 ; CHECK-NEXT: fcvtzu w0, s0
    398 ; CHECK-NEXT: ret
    399 define i32 @test_fptoui_i32(half %a) #0 {
    400   %r = fptoui half %a to i32
    401   ret i32 %r
    402 }
    403 
    404 ; CHECK-LABEL: test_fptoui_i64:
    405 ; CHECK-NEXT: fcvt s0, h0
    406 ; CHECK-NEXT: fcvtzu x0, s0
    407 ; CHECK-NEXT: ret
    408 define i64 @test_fptoui_i64(half %a) #0 {
    409   %r = fptoui half %a to i64
    410   ret i64 %r
    411 }
    412 
    413 ; CHECK-LABEL: test_uitofp_i32:
    414 ; CHECK-NEXT: ucvtf s0, w0
    415 ; CHECK-NEXT: fcvt h0, s0
    416 ; CHECK-NEXT: ret
    417 define half @test_uitofp_i32(i32 %a) #0 {
    418   %r = uitofp i32 %a to half
    419   ret half %r
    420 }
    421 
    422 ; CHECK-LABEL: test_uitofp_i64:
    423 ; CHECK-NEXT: ucvtf s0, x0
    424 ; CHECK-NEXT: fcvt h0, s0
    425 ; CHECK-NEXT: ret
    426 define half @test_uitofp_i64(i64 %a) #0 {
    427   %r = uitofp i64 %a to half
    428   ret half %r
    429 }
    430 
    431 ; CHECK-LABEL: test_sitofp_i32:
    432 ; CHECK-NEXT: scvtf s0, w0
    433 ; CHECK-NEXT: fcvt h0, s0
    434 ; CHECK-NEXT: ret
    435 define half @test_sitofp_i32(i32 %a) #0 {
    436   %r = sitofp i32 %a to half
    437   ret half %r
    438 }
    439 
    440 ; CHECK-LABEL: test_sitofp_i64:
    441 ; CHECK-NEXT: scvtf s0, x0
    442 ; CHECK-NEXT: fcvt h0, s0
    443 ; CHECK-NEXT: ret
    444 define half @test_sitofp_i64(i64 %a) #0 {
    445   %r = sitofp i64 %a to half
    446   ret half %r
    447 }
    448 
    449 ; CHECK-LABEL: test_uitofp_i32_fadd:
    450 ; CHECK-NEXT: ucvtf s1, w0
    451 ; CHECK-NEXT: fcvt h1, s1
    452 ; CHECK-NEXT: fcvt s0, h0
    453 ; CHECK-NEXT: fcvt s1, h1
    454 ; CHECK-NEXT: fadd s0, s0, s1
    455 ; CHECK-NEXT: fcvt h0, s0
    456 ; CHECK-NEXT: ret
    457 define half @test_uitofp_i32_fadd(i32 %a, half %b) #0 {
    458   %c = uitofp i32 %a to half
    459   %r = fadd half %b, %c
    460   ret half %r
    461 }
    462 
    463 ; CHECK-LABEL: test_sitofp_i32_fadd:
    464 ; CHECK-NEXT: scvtf s1, w0
    465 ; CHECK-NEXT: fcvt h1, s1
    466 ; CHECK-NEXT: fcvt s0, h0
    467 ; CHECK-NEXT: fcvt s1, h1
    468 ; CHECK-NEXT: fadd s0, s0, s1
    469 ; CHECK-NEXT: fcvt h0, s0
    470 ; CHECK-NEXT: ret
    471 define half @test_sitofp_i32_fadd(i32 %a, half %b) #0 {
    472   %c = sitofp i32 %a to half
    473   %r = fadd half %b, %c
    474   ret half %r
    475 }
    476 
    477 ; CHECK-LABEL: test_fptrunc_float:
    478 ; CHECK-NEXT: fcvt h0, s0
    479 ; CHECK-NEXT: ret
    480 
    481 define half @test_fptrunc_float(float %a) #0 {
    482   %r = fptrunc float %a to half
    483   ret half %r
    484 }
    485 
    486 ; CHECK-LABEL: test_fptrunc_double:
    487 ; CHECK-NEXT: fcvt h0, d0
    488 ; CHECK-NEXT: ret
    489 define half @test_fptrunc_double(double %a) #0 {
    490   %r = fptrunc double %a to half
    491   ret half %r
    492 }
    493 
    494 ; CHECK-LABEL: test_fpext_float:
    495 ; CHECK-NEXT: fcvt s0, h0
    496 ; CHECK-NEXT: ret
    497 define float @test_fpext_float(half %a) #0 {
    498   %r = fpext half %a to float
    499   ret float %r
    500 }
    501 
    502 ; CHECK-LABEL: test_fpext_double:
    503 ; CHECK-NEXT: fcvt d0, h0
    504 ; CHECK-NEXT: ret
    505 define double @test_fpext_double(half %a) #0 {
    506   %r = fpext half %a to double
    507   ret double %r
    508 }
    509 
    510 
    511 ; CHECK-LABEL: test_bitcast_halftoi16:
    512 ; CHECK-NEXT: fmov w0, s0
    513 ; CHECK-NEXT: ret
    514 define i16 @test_bitcast_halftoi16(half %a) #0 {
    515   %r = bitcast half %a to i16
    516   ret i16 %r
    517 }
    518 
    519 ; CHECK-LABEL: test_bitcast_i16tohalf:
    520 ; CHECK-NEXT: fmov s0, w0
    521 ; CHECK-NEXT: ret
    522 define half @test_bitcast_i16tohalf(i16 %a) #0 {
    523   %r = bitcast i16 %a to half
    524   ret half %r
    525 }
    526 
    527 
    528 declare half @llvm.sqrt.f16(half %a) #0
    529 declare half @llvm.powi.f16(half %a, i32 %b) #0
    530 declare half @llvm.sin.f16(half %a) #0
    531 declare half @llvm.cos.f16(half %a) #0
    532 declare half @llvm.pow.f16(half %a, half %b) #0
    533 declare half @llvm.exp.f16(half %a) #0
    534 declare half @llvm.exp2.f16(half %a) #0
    535 declare half @llvm.log.f16(half %a) #0
    536 declare half @llvm.log10.f16(half %a) #0
    537 declare half @llvm.log2.f16(half %a) #0
    538 declare half @llvm.fma.f16(half %a, half %b, half %c) #0
    539 declare half @llvm.fabs.f16(half %a) #0
    540 declare half @llvm.minnum.f16(half %a, half %b) #0
    541 declare half @llvm.maxnum.f16(half %a, half %b) #0
    542 declare half @llvm.copysign.f16(half %a, half %b) #0
    543 declare half @llvm.floor.f16(half %a) #0
    544 declare half @llvm.ceil.f16(half %a) #0
    545 declare half @llvm.trunc.f16(half %a) #0
    546 declare half @llvm.rint.f16(half %a) #0
    547 declare half @llvm.nearbyint.f16(half %a) #0
    548 declare half @llvm.round.f16(half %a) #0
    549 declare half @llvm.fmuladd.f16(half %a, half %b, half %c) #0
    550 
    551 ; CHECK-LABEL: test_sqrt:
    552 ; CHECK-NEXT: fcvt s0, h0
    553 ; CHECK-NEXT: fsqrt s0, s0
    554 ; CHECK-NEXT: fcvt h0, s0
    555 ; CHECK-NEXT: ret
    556 define half @test_sqrt(half %a) #0 {
    557   %r = call half @llvm.sqrt.f16(half %a)
    558   ret half %r
    559 }
    560 
    561 ; CHECK-LABEL: test_powi:
    562 ; CHECK-NEXT: stp x29, x30, [sp, #-16]!
    563 ; CHECK-NEXT: mov  x29, sp
    564 ; CHECK-NEXT: fcvt s0, h0
    565 ; CHECK-NEXT: bl {{_?}}__powisf2
    566 ; CHECK-NEXT: fcvt h0, s0
    567 ; CHECK-NEXT: ldp x29, x30, [sp], #16
    568 ; CHECK-NEXT: ret
    569 define half @test_powi(half %a, i32 %b) #0 {
    570   %r = call half @llvm.powi.f16(half %a, i32 %b)
    571   ret half %r
    572 }
    573 
    574 ; CHECK-LABEL: test_sin:
    575 ; CHECK-NEXT: stp x29, x30, [sp, #-16]!
    576 ; CHECK-NEXT: mov  x29, sp
    577 ; CHECK-NEXT: fcvt s0, h0
    578 ; CHECK-NEXT: bl {{_?}}sinf
    579 ; CHECK-NEXT: fcvt h0, s0
    580 ; CHECK-NEXT: ldp x29, x30, [sp], #16
    581 ; CHECK-NEXT: ret
    582 define half @test_sin(half %a) #0 {
    583   %r = call half @llvm.sin.f16(half %a)
    584   ret half %r
    585 }
    586 
    587 ; CHECK-LABEL: test_cos:
    588 ; CHECK-NEXT: stp x29, x30, [sp, #-16]!
    589 ; CHECK-NEXT: mov  x29, sp
    590 ; CHECK-NEXT: fcvt s0, h0
    591 ; CHECK-NEXT: bl {{_?}}cosf
    592 ; CHECK-NEXT: fcvt h0, s0
    593 ; CHECK-NEXT: ldp x29, x30, [sp], #16
    594 ; CHECK-NEXT: ret
    595 define half @test_cos(half %a) #0 {
    596   %r = call half @llvm.cos.f16(half %a)
    597   ret half %r
    598 }
    599 
    600 ; CHECK-LABEL: test_pow:
    601 ; CHECK-NEXT: stp x29, x30, [sp, #-16]!
    602 ; CHECK-NEXT: mov  x29, sp
    603 ; CHECK-NEXT: fcvt s0, h0
    604 ; CHECK-NEXT: fcvt s1, h1
    605 ; CHECK-NEXT: bl {{_?}}powf
    606 ; CHECK-NEXT: fcvt h0, s0
    607 ; CHECK-NEXT: ldp x29, x30, [sp], #16
    608 ; CHECK-NEXT: ret
    609 define half @test_pow(half %a, half %b) #0 {
    610   %r = call half @llvm.pow.f16(half %a, half %b)
    611   ret half %r
    612 }
    613 
    614 ; CHECK-LABEL: test_exp:
    615 ; CHECK-NEXT: stp x29, x30, [sp, #-16]!
    616 ; CHECK-NEXT: mov  x29, sp
    617 ; CHECK-NEXT: fcvt s0, h0
    618 ; CHECK-NEXT: bl {{_?}}expf
    619 ; CHECK-NEXT: fcvt h0, s0
    620 ; CHECK-NEXT: ldp x29, x30, [sp], #16
    621 ; CHECK-NEXT: ret
    622 define half @test_exp(half %a) #0 {
    623   %r = call half @llvm.exp.f16(half %a)
    624   ret half %r
    625 }
    626 
    627 ; CHECK-LABEL: test_exp2:
    628 ; CHECK-NEXT: stp x29, x30, [sp, #-16]!
    629 ; CHECK-NEXT: mov  x29, sp
    630 ; CHECK-NEXT: fcvt s0, h0
    631 ; CHECK-NEXT: bl {{_?}}exp2f
    632 ; CHECK-NEXT: fcvt h0, s0
    633 ; CHECK-NEXT: ldp x29, x30, [sp], #16
    634 ; CHECK-NEXT: ret
    635 define half @test_exp2(half %a) #0 {
    636   %r = call half @llvm.exp2.f16(half %a)
    637   ret half %r
    638 }
    639 
    640 ; CHECK-LABEL: test_log:
    641 ; CHECK-NEXT: stp x29, x30, [sp, #-16]!
    642 ; CHECK-NEXT: mov  x29, sp
    643 ; CHECK-NEXT: fcvt s0, h0
    644 ; CHECK-NEXT: bl {{_?}}logf
    645 ; CHECK-NEXT: fcvt h0, s0
    646 ; CHECK-NEXT: ldp x29, x30, [sp], #16
    647 ; CHECK-NEXT: ret
    648 define half @test_log(half %a) #0 {
    649   %r = call half @llvm.log.f16(half %a)
    650   ret half %r
    651 }
    652 
    653 ; CHECK-LABEL: test_log10:
    654 ; CHECK-NEXT: stp x29, x30, [sp, #-16]!
    655 ; CHECK-NEXT: mov  x29, sp
    656 ; CHECK-NEXT: fcvt s0, h0
    657 ; CHECK-NEXT: bl {{_?}}log10f
    658 ; CHECK-NEXT: fcvt h0, s0
    659 ; CHECK-NEXT: ldp x29, x30, [sp], #16
    660 ; CHECK-NEXT: ret
    661 define half @test_log10(half %a) #0 {
    662   %r = call half @llvm.log10.f16(half %a)
    663   ret half %r
    664 }
    665 
    666 ; CHECK-LABEL: test_log2:
    667 ; CHECK-NEXT: stp x29, x30, [sp, #-16]!
    668 ; CHECK-NEXT: mov  x29, sp
    669 ; CHECK-NEXT: fcvt s0, h0
    670 ; CHECK-NEXT: bl {{_?}}log2f
    671 ; CHECK-NEXT: fcvt h0, s0
    672 ; CHECK-NEXT: ldp x29, x30, [sp], #16
    673 ; CHECK-NEXT: ret
    674 define half @test_log2(half %a) #0 {
    675   %r = call half @llvm.log2.f16(half %a)
    676   ret half %r
    677 }
    678 
    679 ; CHECK-LABEL: test_fma:
    680 ; CHECK-NEXT: fcvt s2, h2
    681 ; CHECK-NEXT: fcvt s1, h1
    682 ; CHECK-NEXT: fcvt s0, h0
    683 ; CHECK-NEXT: fmadd s0, s0, s1, s2
    684 ; CHECK-NEXT: fcvt h0, s0
    685 ; CHECK-NEXT: ret
    686 define half @test_fma(half %a, half %b, half %c) #0 {
    687   %r = call half @llvm.fma.f16(half %a, half %b, half %c)
    688   ret half %r
    689 }
    690 
    691 ; CHECK-LABEL: test_fabs:
    692 ; CHECK-NEXT: fcvt s0, h0
    693 ; CHECK-NEXT: fabs s0, s0
    694 ; CHECK-NEXT: fcvt h0, s0
    695 ; CHECK-NEXT: ret
    696 define half @test_fabs(half %a) #0 {
    697   %r = call half @llvm.fabs.f16(half %a)
    698   ret half %r
    699 }
    700 
    701 ; CHECK-LABEL: test_minnum:
    702 ; CHECK-NEXT: fcvt s1, h1
    703 ; CHECK-NEXT: fcvt s0, h0
    704 ; CHECK-NEXT: fminnm s0, s0, s1
    705 ; CHECK-NEXT: fcvt h0, s0
    706 ; CHECK-NEXT: ret
    707 define half @test_minnum(half %a, half %b) #0 {
    708   %r = call half @llvm.minnum.f16(half %a, half %b)
    709   ret half %r
    710 }
    711 
    712 ; CHECK-LABEL: test_maxnum:
    713 ; CHECK-NEXT: fcvt s1, h1
    714 ; CHECK-NEXT: fcvt s0, h0
    715 ; CHECK-NEXT: fmaxnm s0, s0, s1
    716 ; CHECK-NEXT: fcvt h0, s0
    717 ; CHECK-NEXT: ret
    718 define half @test_maxnum(half %a, half %b) #0 {
    719   %r = call half @llvm.maxnum.f16(half %a, half %b)
    720   ret half %r
    721 }
    722 
    723 ; CHECK-LABEL: test_copysign:
    724 ; CHECK-NEXT: fcvt s1, h1
    725 ; CHECK-NEXT: fcvt s0, h0
    726 ; CHECK-NEXT: movi.4s v2, #128, lsl #24
    727 ; CHECK-NEXT: bit.16b v0, v1, v2
    728 ; CHECK-NEXT: fcvt h0, s0
    729 ; CHECK-NEXT: ret
    730 define half @test_copysign(half %a, half %b) #0 {
    731   %r = call half @llvm.copysign.f16(half %a, half %b)
    732   ret half %r
    733 }
    734 
    735 ; CHECK-LABEL: test_copysign_f32:
    736 ; CHECK-NEXT: fcvt s0, h0
    737 ; CHECK-NEXT: movi.4s v2, #128, lsl #24
    738 ; CHECK-NEXT: bit.16b v0, v1, v2
    739 ; CHECK-NEXT: fcvt h0, s0
    740 ; CHECK-NEXT: ret
    741 define half @test_copysign_f32(half %a, float %b) #0 {
    742   %tb = fptrunc float %b to half
    743   %r = call half @llvm.copysign.f16(half %a, half %tb)
    744   ret half %r
    745 }
    746 
    747 ; CHECK-LABEL: test_copysign_f64:
    748 ; CHECK-NEXT: fcvt s1, d1
    749 ; CHECK-NEXT: fcvt s0, h0
    750 ; CHECK-NEXT: movi.4s v2, #128, lsl #24
    751 ; CHECK-NEXT: bit.16b v0, v1, v2
    752 ; CHECK-NEXT: fcvt h0, s0
    753 ; CHECK-NEXT: ret
    754 define half @test_copysign_f64(half %a, double %b) #0 {
    755   %tb = fptrunc double %b to half
    756   %r = call half @llvm.copysign.f16(half %a, half %tb)
    757   ret half %r
    758 }
    759 
    760 ; Check that the FP promotion will use a truncating FP_ROUND, so we can fold
    761 ; away the (fpext (fp_round <result>)) here.
    762 
    763 ; CHECK-LABEL: test_copysign_extended:
    764 ; CHECK-NEXT: fcvt s1, h1
    765 ; CHECK-NEXT: fcvt s0, h0
    766 ; CHECK-NEXT: movi.4s v2, #128, lsl #24
    767 ; CHECK-NEXT: bit.16b v0, v1, v2
    768 ; CHECK-NEXT: ret
    769 define float @test_copysign_extended(half %a, half %b) #0 {
    770   %r = call half @llvm.copysign.f16(half %a, half %b)
    771   %xr = fpext half %r to float
    772   ret float %xr
    773 }
    774 
    775 ; CHECK-LABEL: test_floor:
    776 ; CHECK-NEXT: fcvt [[FLOAT32:s[0-9]+]], h0
    777 ; CHECK-NEXT: frintm [[INT32:s[0-9]+]], [[FLOAT32]]
    778 ; CHECK-NEXT: fcvt h0, [[INT32]]
    779 ; CHECK-NEXT: ret
    780 define half @test_floor(half %a) #0 {
    781   %r = call half @llvm.floor.f16(half %a)
    782   ret half %r
    783 }
    784 
    785 ; CHECK-LABEL: test_ceil:
    786 ; CHECK-NEXT: fcvt [[FLOAT32:s[0-9]+]], h0
    787 ; CHECK-NEXT: frintp [[INT32:s[0-9]+]], [[FLOAT32]]
    788 ; CHECK-NEXT: fcvt h0, [[INT32]]
    789 ; CHECK-NEXT: ret
    790 define half @test_ceil(half %a) #0 {
    791   %r = call half @llvm.ceil.f16(half %a)
    792   ret half %r
    793 }
    794 
    795 ; CHECK-LABEL: test_trunc:
    796 ; CHECK-NEXT: fcvt [[FLOAT32:s[0-9]+]], h0
    797 ; CHECK-NEXT: frintz [[INT32:s[0-9]+]], [[FLOAT32]]
    798 ; CHECK-NEXT: fcvt h0, [[INT32]]
    799 ; CHECK-NEXT: ret
    800 define half @test_trunc(half %a) #0 {
    801   %r = call half @llvm.trunc.f16(half %a)
    802   ret half %r
    803 }
    804 
    805 ; CHECK-LABEL: test_rint:
    806 ; CHECK-NEXT: fcvt s0, h0
    807 ; CHECK-NEXT: frintx s0, s0
    808 ; CHECK-NEXT: fcvt h0, s0
    809 ; CHECK-NEXT: ret
    810 define half @test_rint(half %a) #0 {
    811   %r = call half @llvm.rint.f16(half %a)
    812   ret half %r
    813 }
    814 
    815 ; CHECK-LABEL: test_nearbyint:
    816 ; CHECK-NEXT: fcvt s0, h0
    817 ; CHECK-NEXT: frinti s0, s0
    818 ; CHECK-NEXT: fcvt h0, s0
    819 ; CHECK-NEXT: ret
    820 define half @test_nearbyint(half %a) #0 {
    821   %r = call half @llvm.nearbyint.f16(half %a)
    822   ret half %r
    823 }
    824 
    825 ; CHECK-LABEL: test_round:
    826 ; CHECK-NEXT: fcvt [[FLOAT32:s[0-9]+]], h0
    827 ; CHECK-NEXT: frinta [[INT32:s[0-9]+]], [[FLOAT32]]
    828 ; CHECK-NEXT: fcvt h0, [[INT32]]
    829 ; CHECK-NEXT: ret
    830 define half @test_round(half %a) #0 {
    831   %r = call half @llvm.round.f16(half %a)
    832   ret half %r
    833 }
    834 
    835 ; CHECK-LABEL: test_fmuladd:
    836 ; CHECK-NEXT: fcvt s1, h1
    837 ; CHECK-NEXT: fcvt s0, h0
    838 ; CHECK-NEXT: fmul s0, s0, s1
    839 ; CHECK-NEXT: fcvt h0, s0
    840 ; CHECK-NEXT: fcvt s0, h0
    841 ; CHECK-NEXT: fcvt s1, h2
    842 ; CHECK-NEXT: fadd s0, s0, s1
    843 ; CHECK-NEXT: fcvt h0, s0
    844 ; CHECK-NEXT: ret
    845 define half @test_fmuladd(half %a, half %b, half %c) #0 {
    846   %r = call half @llvm.fmuladd.f16(half %a, half %b, half %c)
    847   ret half %r
    848 }
    849 
    850 attributes #0 = { nounwind }
    851