1; RUN: llc < %s -mtriple aarch64-unknown-unknown -aarch64-neon-syntax=apple -asm-verbose=false -disable-post-ra -disable-fp-elim | FileCheck %s 2 3target 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 11define 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 22define 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 33define 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 44define 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 58define 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 66define 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 74define half @test_load(half* %a) #0 { 75 %r = load half, half* %a 76 ret half %r 77} 78 79 80declare 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 88define 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 102define 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 112define 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 124define 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 140define 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 152define 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 167define 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 179define 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 192define 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 203define 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 214define 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 225define 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 236define 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 248define 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 261define 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 272define 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 283define 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 294define 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 305define 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 316define 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 327define 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 342define 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 345then: 346 store i32 0, i32* %p1 347 ret void 348else: 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 363define half @test_phi(half* %p1) #0 { 364entry: 365 %a = load half, half* %p1 366 br label %loop 367loop: 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 372return: 373 ret half %r 374} 375declare 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 381define 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 390define 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 399define 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 408define 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 417define 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 426define 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 435define 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 444define 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 457define 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 471define 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 481define 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 489define 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 497define 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 505define 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 514define 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 522define half @test_bitcast_i16tohalf(i16 %a) #0 { 523 %r = bitcast i16 %a to half 524 ret half %r 525} 526 527 528declare half @llvm.sqrt.f16(half %a) #0 529declare half @llvm.powi.f16(half %a, i32 %b) #0 530declare half @llvm.sin.f16(half %a) #0 531declare half @llvm.cos.f16(half %a) #0 532declare half @llvm.pow.f16(half %a, half %b) #0 533declare half @llvm.exp.f16(half %a) #0 534declare half @llvm.exp2.f16(half %a) #0 535declare half @llvm.log.f16(half %a) #0 536declare half @llvm.log10.f16(half %a) #0 537declare half @llvm.log2.f16(half %a) #0 538declare half @llvm.fma.f16(half %a, half %b, half %c) #0 539declare half @llvm.fabs.f16(half %a) #0 540declare half @llvm.minnum.f16(half %a, half %b) #0 541declare half @llvm.maxnum.f16(half %a, half %b) #0 542declare half @llvm.copysign.f16(half %a, half %b) #0 543declare half @llvm.floor.f16(half %a) #0 544declare half @llvm.ceil.f16(half %a) #0 545declare half @llvm.trunc.f16(half %a) #0 546declare half @llvm.rint.f16(half %a) #0 547declare half @llvm.nearbyint.f16(half %a) #0 548declare half @llvm.round.f16(half %a) #0 549declare 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 556define 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 569define 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 582define 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 595define 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 609define 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 622define 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 635define 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 648define 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 661define 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 674define 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 686define 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 696define 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 707define 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 718define 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 730define 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 741define 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 754define 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 769define 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 780define 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 790define 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 800define 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 810define 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 820define 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 830define 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 845define 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 850attributes #0 = { nounwind } 851