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