1; RUN: llc -asm-verbose=false < %s -mattr=+vfp3,+fp16 | FileCheck %s -check-prefix=CHECK-FP16 --check-prefix=CHECK-VFP -check-prefix=CHECK-ALL 2; RUN: llc -asm-verbose=false < %s | FileCheck %s -check-prefix=CHECK-LIBCALL --check-prefix=CHECK-VFP -check-prefix=CHECK-ALL --check-prefix=CHECK-LIBCALL-VFP 3; RUN: llc -asm-verbose=false < %s -mattr=-vfp2 | FileCheck %s --check-prefix=CHECK-LIBCALL -check-prefix=CHECK-NOVFP -check-prefix=CHECK-ALL 4 5target datalayout = "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-n32" 6target triple = "armv7---eabihf" 7 8; CHECK-ALL-LABEL: test_fadd: 9; CHECK-FP16: vcvtb.f32.f16 10; CHECK-FP16: vcvtb.f32.f16 11; CHECK-LIBCALL: bl __aeabi_h2f 12; CHECK-LIBCALL: bl __aeabi_h2f 13; CHECK-VFP: vadd.f32 14; CHECK-NOVFP: bl __aeabi_fadd 15; CHECK-FP16: vcvtb.f16.f32 16; CHECK-LIBCALL: bl __aeabi_f2h 17define void @test_fadd(half* %p, half* %q) #0 { 18 %a = load half, half* %p, align 2 19 %b = load half, half* %q, align 2 20 %r = fadd half %a, %b 21 store half %r, half* %p 22 ret void 23} 24 25; CHECK-ALL-LABEL: test_fsub: 26; CHECK-FP16: vcvtb.f32.f16 27; CHECK-FP16: vcvtb.f32.f16 28; CHECK-LIBCALL: bl __aeabi_h2f 29; CHECK-LIBCALL: bl __aeabi_h2f 30; CHECK-VFP: vsub.f32 31; CHECK-NOVFP: bl __aeabi_fsub 32; CHECK-FP16: vcvtb.f16.f32 33; CHECK-LIBCALL: bl __aeabi_f2h 34define void @test_fsub(half* %p, half* %q) #0 { 35 %a = load half, half* %p, align 2 36 %b = load half, half* %q, align 2 37 %r = fsub half %a, %b 38 store half %r, half* %p 39 ret void 40} 41 42; CHECK-ALL-LABEL: test_fmul: 43; CHECK-FP16: vcvtb.f32.f16 44; CHECK-FP16: vcvtb.f32.f16 45; CHECK-LIBCALL: bl __aeabi_h2f 46; CHECK-LIBCALL: bl __aeabi_h2f 47; CHECK-VFP: vmul.f32 48; CHECK-NOVFP: bl __aeabi_fmul 49; CHECK-FP16: vcvtb.f16.f32 50; CHECK-LIBCALL: bl __aeabi_f2h 51define void @test_fmul(half* %p, half* %q) #0 { 52 %a = load half, half* %p, align 2 53 %b = load half, half* %q, align 2 54 %r = fmul half %a, %b 55 store half %r, half* %p 56 ret void 57} 58 59; CHECK-ALL-LABEL: test_fdiv: 60; CHECK-FP16: vcvtb.f32.f16 61; CHECK-FP16: vcvtb.f32.f16 62; CHECK-LIBCALL: bl __aeabi_h2f 63; CHECK-LIBCALL: bl __aeabi_h2f 64; CHECK-VFP: vdiv.f32 65; CHECK-NOVFP: bl __aeabi_fdiv 66; CHECK-FP16: vcvtb.f16.f32 67; CHECK-LIBCALL: bl __aeabi_f2h 68define void @test_fdiv(half* %p, half* %q) #0 { 69 %a = load half, half* %p, align 2 70 %b = load half, half* %q, align 2 71 %r = fdiv half %a, %b 72 store half %r, half* %p 73 ret void 74} 75 76; CHECK-ALL-LABEL: test_frem: 77; CHECK-FP16: vcvtb.f32.f16 78; CHECK-FP16: vcvtb.f32.f16 79; CHECK-LIBCALL: bl __aeabi_h2f 80; CHECK-LIBCALL: bl __aeabi_h2f 81; CHECK-LIBCALL: bl fmodf 82; CHECK-FP16: vcvtb.f16.f32 83; CHECK-LIBCALL: bl __aeabi_f2h 84define void @test_frem(half* %p, half* %q) #0 { 85 %a = load half, half* %p, align 2 86 %b = load half, half* %q, align 2 87 %r = frem half %a, %b 88 store half %r, half* %p 89 ret void 90} 91 92; CHECK-ALL-LABEL: test_load_store: 93; CHECK-ALL-NEXT: .fnstart 94; CHECK-ALL: ldrh {{r[0-9]+}}, [{{r[0-9]+}}] 95; CHECK-ALL: strh {{r[0-9]+}}, [{{r[0-9]+}}] 96define void @test_load_store(half* %p, half* %q) #0 { 97 %a = load half, half* %p, align 2 98 store half %a, half* %q 99 ret void 100} 101 102; Testing only successfull compilation of function calls. In ARM ABI, half 103; args and returns are handled as f32. 104 105declare half @test_callee(half %a, half %b) #0 106 107; CHECK-ALL-LABEL: test_call: 108; CHECK-ALL-NEXT: .fnstart 109; CHECK-ALL-NEXT: .save {r11, lr} 110; CHECK-ALL-NEXT: push {r11, lr} 111; CHECK-ALL-NEXT: bl test_callee 112; CHECK-ALL-NEXT: pop {r11, pc} 113define half @test_call(half %a, half %b) #0 { 114 %r = call half @test_callee(half %a, half %b) 115 ret half %r 116} 117 118; CHECK-ALL-LABEL: test_call_flipped: 119; CHECK-ALL-NEXT: .fnstart 120; CHECK-ALL-NEXT: .save {r11, lr} 121; CHECK-ALL-NEXT: push {r11, lr} 122; CHECK-VFP-NEXT: vmov.f32 s2, s0 123; CHECK-VFP-NEXT: vmov.f32 s0, s1 124; CHECK-VFP-NEXT: vmov.f32 s1, s2 125; CHECK-NOVFP-NEXT: mov r2, r0 126; CHECK-NOVFP-NEXT: mov r0, r1 127; CHECK-NOVFP-NEXT: mov r1, r2 128; CHECK-ALL-NEXT: bl test_callee 129; CHECK-ALL-NEXT: pop {r11, pc} 130define half @test_call_flipped(half %a, half %b) #0 { 131 %r = call half @test_callee(half %b, half %a) 132 ret half %r 133} 134 135; CHECK-ALL-LABEL: test_tailcall_flipped: 136; CHECK-ALL-NEXT: .fnstart 137; CHECK-VFP-NEXT: vmov.f32 s2, s0 138; CHECK-VFP-NEXT: vmov.f32 s0, s1 139; CHECK-VFP-NEXT: vmov.f32 s1, s2 140; CHECK-NOVFP-NEXT: mov r2, r0 141; CHECK-NOVFP-NEXT: mov r0, r1 142; CHECK-NOVFP-NEXT: mov r1, r2 143; CHECK-ALL-NEXT: b test_callee 144define half @test_tailcall_flipped(half %a, half %b) #0 { 145 %r = tail call half @test_callee(half %b, half %a) 146 ret half %r 147} 148 149; Optimizer picks %p or %q based on %c and only loads that value 150; No conversion is needed 151; CHECK-ALL-LABEL: test_select: 152; CHECK-ALL: cmp {{r[0-9]+}}, #0 153; CHECK-ALL: movne {{r[0-9]+}}, {{r[0-9]+}} 154; CHECK-ALL: ldrh {{r[0-9]+}}, [{{r[0-9]+}}] 155; CHECK-ALL: strh {{r[0-9]+}}, [{{r[0-9]+}}] 156define void @test_select(half* %p, half* %q, i1 zeroext %c) #0 { 157 %a = load half, half* %p, align 2 158 %b = load half, half* %q, align 2 159 %r = select i1 %c, half %a, half %b 160 store half %r, half* %p 161 ret void 162} 163 164; Test only two variants of fcmp. These get translated to f32 vcmpe 165; instructions anyway. 166; CHECK-ALL-LABEL: test_fcmp_une: 167; CHECK-FP16: vcvtb.f32.f16 168; CHECK-FP16: vcvtb.f32.f16 169; CHECK-LIBCALL: bl __aeabi_h2f 170; CHECK-LIBCALL: bl __aeabi_h2f 171; CHECK-VFP: vcmpe.f32 172; CHECK-NOVFP: bl __aeabi_fcmpeq 173; CHECK-FP16: vmrs APSR_nzcv, fpscr 174; CHECK-ALL: movw{{ne|eq}} 175define i1 @test_fcmp_une(half* %p, half* %q) #0 { 176 %a = load half, half* %p, align 2 177 %b = load half, half* %q, align 2 178 %r = fcmp une half %a, %b 179 ret i1 %r 180} 181 182; CHECK-ALL-LABEL: test_fcmp_ueq: 183; CHECK-FP16: vcvtb.f32.f16 184; CHECK-FP16: vcvtb.f32.f16 185; CHECK-LIBCALL: bl __aeabi_h2f 186; CHECK-LIBCALL: bl __aeabi_h2f 187; CHECK-VFP: vcmpe.f32 188; CHECK-NOVFP: bl __aeabi_fcmpeq 189; CHECK-FP16: vmrs APSR_nzcv, fpscr 190; CHECK-LIBCALL: movw{{ne|eq}} 191define i1 @test_fcmp_ueq(half* %p, half* %q) #0 { 192 %a = load half, half* %p, align 2 193 %b = load half, half* %q, align 2 194 %r = fcmp ueq half %a, %b 195 ret i1 %r 196} 197 198; CHECK-ALL-LABEL: test_br_cc: 199; CHECK-FP16: vcvtb.f32.f16 200; CHECK-FP16: vcvtb.f32.f16 201; CHECK-LIBCALL: bl __aeabi_h2f 202; CHECK-LIBCALL: bl __aeabi_h2f 203; CHECK-VFP: vcmpe.f32 204; CHECK-NOVFP: bl __aeabi_fcmplt 205; CHECK-FP16: vmrs APSR_nzcv, fpscr 206; CHECK-VFP: strmi 207; CHECK-VFP: strpl 208; CHECK-NOVFP: strne 209; CHECK-NOVFP: streq 210define void @test_br_cc(half* %p, half* %q, i32* %p1, i32* %p2) #0 { 211 %a = load half, half* %p, align 2 212 %b = load half, half* %q, align 2 213 %c = fcmp uge half %a, %b 214 br i1 %c, label %then, label %else 215then: 216 store i32 0, i32* %p1 217 ret void 218else: 219 store i32 0, i32* %p2 220 ret void 221} 222 223declare i1 @test_dummy(half* %p) #0 224; CHECK-ALL-LABEL: test_phi: 225; CHECK-FP16: vcvtb.f32.f16 226; CHECK-FP16: [[LOOP:.LBB[1-9_]+]]: 227; CHECK-FP16: vcvtb.f32.f16 228; CHECK-FP16: bl test_dummy 229; CHECK-FP16: bne [[LOOP]] 230; CHECK-FP16: vcvtb.f16.f32 231; CHECK-LIBCALL-VFP: bl __aeabi_h2f 232; CHECK-LIBCALL: [[LOOP:.LBB[1-9_]+]]: 233; CHECK-LIBCALL-VFP: bl __aeabi_h2f 234; CHECK-LIBCALL: bl test_dummy 235; CHECK-LIBCALL: bne [[LOOP]] 236; CHECK-LIBCALL-VFP: bl __aeabi_f2h 237define void @test_phi(half* %p) #0 { 238entry: 239 %a = load half, half* %p 240 br label %loop 241loop: 242 %r = phi half [%a, %entry], [%b, %loop] 243 %b = load half, half* %p 244 %c = call i1 @test_dummy(half* %p) 245 br i1 %c, label %loop, label %return 246return: 247 store half %r, half* %p 248 ret void 249} 250 251; CHECK-ALL-LABEL: test_fptosi_i32: 252; CHECK-FP16: vcvtb.f32.f16 253; CHECK-LIBCALL: bl __aeabi_h2f 254; CHECK-VFP: vcvt.s32.f32 255; CHECK-NOVFP: bl __aeabi_f2iz 256define i32 @test_fptosi_i32(half* %p) #0 { 257 %a = load half, half* %p, align 2 258 %r = fptosi half %a to i32 259 ret i32 %r 260} 261 262; CHECK-ALL-LABEL: test_fptosi_i64: 263; CHECK-FP16: vcvtb.f32.f16 264; CHECK-LIBCALL: bl __aeabi_h2f 265; CHECK-ALL: bl __aeabi_f2lz 266define i64 @test_fptosi_i64(half* %p) #0 { 267 %a = load half, half* %p, align 2 268 %r = fptosi half %a to i64 269 ret i64 %r 270} 271 272; CHECK-ALL-LABEL: test_fptoui_i32: 273; CHECK-FP16: vcvtb.f32.f16 274; CHECK-LIBCALL: bl __aeabi_h2f 275; CHECK-VFP: vcvt.u32.f32 276; CHECK-NOVFP: bl __aeabi_f2uiz 277define i32 @test_fptoui_i32(half* %p) #0 { 278 %a = load half, half* %p, align 2 279 %r = fptoui half %a to i32 280 ret i32 %r 281} 282 283; CHECK-ALL-LABEL: test_fptoui_i64: 284; CHECK-FP16: vcvtb.f32.f16 285; CHECK-LIBCALL: bl __aeabi_h2f 286; CHECK-ALL: bl __aeabi_f2ulz 287define i64 @test_fptoui_i64(half* %p) #0 { 288 %a = load half, half* %p, align 2 289 %r = fptoui half %a to i64 290 ret i64 %r 291} 292 293; CHECK-ALL-LABEL: test_sitofp_i32: 294; CHECK-VFP: vcvt.f32.s32 295; CHECK-NOVFP: bl __aeabi_i2f 296; CHECK-FP16: vcvtb.f16.f32 297; CHECK-LIBCALL: bl __aeabi_f2h 298define void @test_sitofp_i32(i32 %a, half* %p) #0 { 299 %r = sitofp i32 %a to half 300 store half %r, half* %p 301 ret void 302} 303 304; CHECK-ALL-LABEL: test_uitofp_i32: 305; CHECK-VFP: vcvt.f32.u32 306; CHECK-NOVFP: bl __aeabi_ui2f 307; CHECK-FP16: vcvtb.f16.f32 308; CHECK-LIBCALL: bl __aeabi_f2h 309define void @test_uitofp_i32(i32 %a, half* %p) #0 { 310 %r = uitofp i32 %a to half 311 store half %r, half* %p 312 ret void 313} 314 315; CHECK-ALL-LABEL: test_sitofp_i64: 316; CHECK-ALL: bl __aeabi_l2f 317; CHECK-FP16: vcvtb.f16.f32 318; CHECK-LIBCALL: bl __aeabi_f2h 319define void @test_sitofp_i64(i64 %a, half* %p) #0 { 320 %r = sitofp i64 %a to half 321 store half %r, half* %p 322 ret void 323} 324 325; CHECK-ALL-LABEL: test_uitofp_i64: 326; CHECK-ALL: bl __aeabi_ul2f 327; CHECK-FP16: vcvtb.f16.f32 328; CHECK-LIBCALL: bl __aeabi_f2h 329define void @test_uitofp_i64(i64 %a, half* %p) #0 { 330 %r = uitofp i64 %a to half 331 store half %r, half* %p 332 ret void 333} 334 335; CHECK-FP16-LABEL: test_fptrunc_float: 336; CHECK-FP16: vcvtb.f16.f32 337; CHECK-LIBCALL-LABEL: test_fptrunc_float: 338; CHECK-LIBCALL: bl __aeabi_f2h 339define void @test_fptrunc_float(float %f, half* %p) #0 { 340 %a = fptrunc float %f to half 341 store half %a, half* %p 342 ret void 343} 344 345; CHECK-FP16-LABEL: test_fptrunc_double: 346; CHECK-FP16: bl __aeabi_d2h 347; CHECK-LIBCALL-LABEL: test_fptrunc_double: 348; CHECK-LIBCALL: bl __aeabi_d2h 349define void @test_fptrunc_double(double %d, half* %p) #0 { 350 %a = fptrunc double %d to half 351 store half %a, half* %p 352 ret void 353} 354 355; CHECK-FP16-LABEL: test_fpextend_float: 356; CHECK-FP16: vcvtb.f32.f16 357; CHECK-LIBCALL-LABEL: test_fpextend_float: 358; CHECK-LIBCALL: bl __aeabi_h2f 359define float @test_fpextend_float(half* %p) { 360 %a = load half, half* %p, align 2 361 %r = fpext half %a to float 362 ret float %r 363} 364 365; CHECK-FP16-LABEL: test_fpextend_double: 366; CHECK-FP16: vcvtb.f32.f16 367; CHECK-LIBCALL-LABEL: test_fpextend_double: 368; CHECK-LIBCALL: bl __aeabi_h2f 369; CHECK-VFP: vcvt.f64.f32 370; CHECK-NOVFP: bl __aeabi_f2d 371define double @test_fpextend_double(half* %p) { 372 %a = load half, half* %p, align 2 373 %r = fpext half %a to double 374 ret double %r 375} 376 377; CHECK-ALL-LABEL: test_bitcast_halftoi16: 378; CHECK-ALL-NEXT: .fnstart 379; CHECK-ALL-NEXT: ldrh r0, [r0] 380; CHECK-ALL-NEXT: bx lr 381define i16 @test_bitcast_halftoi16(half* %p) #0 { 382 %a = load half, half* %p, align 2 383 %r = bitcast half %a to i16 384 ret i16 %r 385} 386 387; CHECK-ALL-LABEL: test_bitcast_i16tohalf: 388; CHECK-ALL-NEXT: .fnstart 389; CHECK-ALL-NEXT: strh r0, [r1] 390; CHECK-ALL-NEXT: bx lr 391define void @test_bitcast_i16tohalf(i16 %a, half* %p) #0 { 392 %r = bitcast i16 %a to half 393 store half %r, half* %p 394 ret void 395} 396 397declare half @llvm.sqrt.f16(half %a) #0 398declare half @llvm.powi.f16(half %a, i32 %b) #0 399declare half @llvm.sin.f16(half %a) #0 400declare half @llvm.cos.f16(half %a) #0 401declare half @llvm.pow.f16(half %a, half %b) #0 402declare half @llvm.exp.f16(half %a) #0 403declare half @llvm.exp2.f16(half %a) #0 404declare half @llvm.log.f16(half %a) #0 405declare half @llvm.log10.f16(half %a) #0 406declare half @llvm.log2.f16(half %a) #0 407declare half @llvm.fma.f16(half %a, half %b, half %c) #0 408declare half @llvm.fabs.f16(half %a) #0 409declare half @llvm.minnum.f16(half %a, half %b) #0 410declare half @llvm.maxnum.f16(half %a, half %b) #0 411declare half @llvm.copysign.f16(half %a, half %b) #0 412declare half @llvm.floor.f16(half %a) #0 413declare half @llvm.ceil.f16(half %a) #0 414declare half @llvm.trunc.f16(half %a) #0 415declare half @llvm.rint.f16(half %a) #0 416declare half @llvm.nearbyint.f16(half %a) #0 417declare half @llvm.round.f16(half %a) #0 418declare half @llvm.fmuladd.f16(half %a, half %b, half %c) #0 419 420; CHECK-ALL-LABEL: test_sqrt: 421; CHECK-FP16: vcvtb.f32.f16 422; CHECK-FP16: vsqrt.f32 423; CHECK-FP16: vcvtb.f16.f32 424; CHECK-LIBCALL: bl __aeabi_h2f 425; CHECK-VFP-LIBCALL: vsqrt.f32 426; CHECK-NOVFP: bl sqrtf 427; CHECK-LIBCALL: bl __aeabi_f2h 428define void @test_sqrt(half* %p) #0 { 429 %a = load half, half* %p, align 2 430 %r = call half @llvm.sqrt.f16(half %a) 431 store half %r, half* %p 432 ret void 433} 434 435; CHECK-FP16-LABEL: test_fpowi: 436; CHECK-FP16: vcvtb.f32.f16 437; CHECK-FP16: bl __powisf2 438; CHECK-FP16: vcvtb.f16.f32 439; CHECK-LIBCALL-LABEL: test_fpowi: 440; CHECK-LIBCALL: bl __aeabi_h2f 441; CHECK-LIBCALL: bl __powisf2 442; CHECK-LIBCALL: bl __aeabi_f2h 443define void @test_fpowi(half* %p, i32 %b) #0 { 444 %a = load half, half* %p, align 2 445 %r = call half @llvm.powi.f16(half %a, i32 %b) 446 store half %r, half* %p 447 ret void 448} 449 450; CHECK-FP16-LABEL: test_sin: 451; CHECK-FP16: vcvtb.f32.f16 452; CHECK-FP16: bl sinf 453; CHECK-FP16: vcvtb.f16.f32 454; CHECK-LIBCALL-LABEL: test_sin: 455; CHECK-LIBCALL: bl __aeabi_h2f 456; CHECK-LIBCALL: bl sinf 457; CHECK-LIBCALL: bl __aeabi_f2h 458define void @test_sin(half* %p) #0 { 459 %a = load half, half* %p, align 2 460 %r = call half @llvm.sin.f16(half %a) 461 store half %r, half* %p 462 ret void 463} 464 465; CHECK-FP16-LABEL: test_cos: 466; CHECK-FP16: vcvtb.f32.f16 467; CHECK-FP16: bl cosf 468; CHECK-FP16: vcvtb.f16.f32 469; CHECK-LIBCALL-LABEL: test_cos: 470; CHECK-LIBCALL: bl __aeabi_h2f 471; CHECK-LIBCALL: bl cosf 472; CHECK-LIBCALL: bl __aeabi_f2h 473define void @test_cos(half* %p) #0 { 474 %a = load half, half* %p, align 2 475 %r = call half @llvm.cos.f16(half %a) 476 store half %r, half* %p 477 ret void 478} 479 480; CHECK-FP16-LABEL: test_pow: 481; CHECK-FP16: vcvtb.f32.f16 482; CHECK-FP16: vcvtb.f32.f16 483; CHECK-FP16: bl powf 484; CHECK-FP16: vcvtb.f16.f32 485; CHECK-LIBCALL-LABEL: test_pow: 486; CHECK-LIBCALL: bl __aeabi_h2f 487; CHECK-LIBCALL: bl __aeabi_h2f 488; CHECK-LIBCALL: bl powf 489; CHECK-LIBCALL: bl __aeabi_f2h 490define void @test_pow(half* %p, half* %q) #0 { 491 %a = load half, half* %p, align 2 492 %b = load half, half* %q, align 2 493 %r = call half @llvm.pow.f16(half %a, half %b) 494 store half %r, half* %p 495 ret void 496} 497 498; CHECK-FP16-LABEL: test_exp: 499; CHECK-FP16: vcvtb.f32.f16 500; CHECK-FP16: bl expf 501; CHECK-FP16: vcvtb.f16.f32 502; CHECK-LIBCALL-LABEL: test_exp: 503; CHECK-LIBCALL: bl __aeabi_h2f 504; CHECK-LIBCALL: bl expf 505; CHECK-LIBCALL: bl __aeabi_f2h 506define void @test_exp(half* %p) #0 { 507 %a = load half, half* %p, align 2 508 %r = call half @llvm.exp.f16(half %a) 509 store half %r, half* %p 510 ret void 511} 512 513; CHECK-FP16-LABEL: test_exp2: 514; CHECK-FP16: vcvtb.f32.f16 515; CHECK-FP16: bl exp2f 516; CHECK-FP16: vcvtb.f16.f32 517; CHECK-LIBCALL-LABEL: test_exp2: 518; CHECK-LIBCALL: bl __aeabi_h2f 519; CHECK-LIBCALL: bl exp2f 520; CHECK-LIBCALL: bl __aeabi_f2h 521define void @test_exp2(half* %p) #0 { 522 %a = load half, half* %p, align 2 523 %r = call half @llvm.exp2.f16(half %a) 524 store half %r, half* %p 525 ret void 526} 527 528; CHECK-FP16-LABEL: test_log: 529; CHECK-FP16: vcvtb.f32.f16 530; CHECK-FP16: bl logf 531; CHECK-FP16: vcvtb.f16.f32 532; CHECK-LIBCALL-LABEL: test_log: 533; CHECK-LIBCALL: bl __aeabi_h2f 534; CHECK-LIBCALL: bl logf 535; CHECK-LIBCALL: bl __aeabi_f2h 536define void @test_log(half* %p) #0 { 537 %a = load half, half* %p, align 2 538 %r = call half @llvm.log.f16(half %a) 539 store half %r, half* %p 540 ret void 541} 542 543; CHECK-FP16-LABEL: test_log10: 544; CHECK-FP16: vcvtb.f32.f16 545; CHECK-FP16: bl log10f 546; CHECK-FP16: vcvtb.f16.f32 547; CHECK-LIBCALL-LABEL: test_log10: 548; CHECK-LIBCALL: bl __aeabi_h2f 549; CHECK-LIBCALL: bl log10f 550; CHECK-LIBCALL: bl __aeabi_f2h 551define void @test_log10(half* %p) #0 { 552 %a = load half, half* %p, align 2 553 %r = call half @llvm.log10.f16(half %a) 554 store half %r, half* %p 555 ret void 556} 557 558; CHECK-FP16-LABEL: test_log2: 559; CHECK-FP16: vcvtb.f32.f16 560; CHECK-FP16: bl log2f 561; CHECK-FP16: vcvtb.f16.f32 562; CHECK-LIBCALL-LABEL: test_log2: 563; CHECK-LIBCALL: bl __aeabi_h2f 564; CHECK-LIBCALL: bl log2f 565; CHECK-LIBCALL: bl __aeabi_f2h 566define void @test_log2(half* %p) #0 { 567 %a = load half, half* %p, align 2 568 %r = call half @llvm.log2.f16(half %a) 569 store half %r, half* %p 570 ret void 571} 572 573; CHECK-FP16-LABEL: test_fma: 574; CHECK-FP16: vcvtb.f32.f16 575; CHECK-FP16: vcvtb.f32.f16 576; CHECK-FP16: vcvtb.f32.f16 577; CHECK-FP16: bl fmaf 578; CHECK-FP16: vcvtb.f16.f32 579; CHECK-LIBCALL-LABEL: test_fma: 580; CHECK-LIBCALL: bl __aeabi_h2f 581; CHECK-LIBCALL: bl __aeabi_h2f 582; CHECK-LIBCALL: bl __aeabi_h2f 583; CHECK-LIBCALL: bl fmaf 584; CHECK-LIBCALL: bl __aeabi_f2h 585define void @test_fma(half* %p, half* %q, half* %r) #0 { 586 %a = load half, half* %p, align 2 587 %b = load half, half* %q, align 2 588 %c = load half, half* %r, align 2 589 %v = call half @llvm.fma.f16(half %a, half %b, half %c) 590 store half %v, half* %p 591 ret void 592} 593 594; CHECK-FP16-LABEL: test_fabs: 595; CHECK-FP16: vcvtb.f32.f16 596; CHECK-FP16: vabs.f32 597; CHECK-FP16: vcvtb.f16.f32 598; CHECK-LIBCALL-LABEL: test_fabs: 599; CHECK-LIBCALL: bl __aeabi_h2f 600; CHECK-LIBCALL: bfc 601; CHECK-LIBCALL: bl __aeabi_f2h 602define void @test_fabs(half* %p) { 603 %a = load half, half* %p, align 2 604 %r = call half @llvm.fabs.f16(half %a) 605 store half %r, half* %p 606 ret void 607} 608 609; CHECK-FP16-LABEL: test_minnum: 610; CHECK-FP16: vcvtb.f32.f16 611; CHECK-FP16: vcvtb.f32.f16 612; CHECK-FP16: bl fminf 613; CHECK-FP16: vcvtb.f16.f32 614; CHECK-LIBCALL-LABEL: test_minnum: 615; CHECK-LIBCALL: bl __aeabi_h2f 616; CHECK-LIBCALL: bl __aeabi_h2f 617; CHECK-LIBCALL: bl fminf 618; CHECK-LIBCALL: bl __aeabi_f2h 619define void @test_minnum(half* %p, half* %q) #0 { 620 %a = load half, half* %p, align 2 621 %b = load half, half* %q, align 2 622 %r = call half @llvm.minnum.f16(half %a, half %b) 623 store half %r, half* %p 624 ret void 625} 626 627; CHECK-FP16-LABEL: test_maxnum: 628; CHECK-FP16: vcvtb.f32.f16 629; CHECK-FP16: vcvtb.f32.f16 630; CHECK-FP16: bl fmaxf 631; CHECK-FP16: vcvtb.f16.f32 632; CHECK-LIBCALL-LABEL: test_maxnum: 633; CHECK-LIBCALL: bl __aeabi_h2f 634; CHECK-LIBCALL: bl __aeabi_h2f 635; CHECK-LIBCALL: bl fmaxf 636; CHECK-LIBCALL: bl __aeabi_f2h 637define void @test_maxnum(half* %p, half* %q) #0 { 638 %a = load half, half* %p, align 2 639 %b = load half, half* %q, align 2 640 %r = call half @llvm.maxnum.f16(half %a, half %b) 641 store half %r, half* %p 642 ret void 643} 644 645; CHECK-ALL-LABEL: test_minnan: 646; CHECK-FP16: vcvtb.f32.f16 647; CHECK-FP16: vcvtb.f32.f16 648; CHECK-LIBCALL: bl __aeabi_h2f 649; CHECK-LIBCALL: bl __aeabi_h2f 650; CHECK-VFP: vmin.f32 651; CHECK-NOVFP: bl __aeabi_fcmpge 652; CHECK-FP16: vcvtb.f16.f32 653; CHECK-LIBCALL: bl __aeabi_f2h 654define void @test_minnan(half* %p) #0 { 655 %a = load half, half* %p, align 2 656 %c = fcmp ult half %a, 1.0 657 %r = select i1 %c, half %a, half 1.0 658 store half %r, half* %p 659 ret void 660} 661 662; CHECK-ALL-LABEL: test_maxnan: 663; CHECK-FP16: vcvtb.f32.f16 664; CHECK-FP16: vcvtb.f32.f16 665; CHECK-LIBCALL: bl __aeabi_h2f 666; CHECK-LIBCALL: bl __aeabi_h2f 667; CHECK-VFP: vmax.f32 668; CHECK-NOVFP: bl __aeabi_fcmple 669; CHECK-FP16: vcvtb.f16.f32 670; CHECK-LIBCALL: bl __aeabi_f2h 671define void @test_maxnan(half* %p) #0 { 672 %a = load half, half* %p, align 2 673 %c = fcmp ugt half %a, 1.0 674 %r = select i1 %c, half %a, half 1.0 675 store half %r, half* %p 676 ret void 677} 678 679; CHECK-FP16-LABEL: test_copysign: 680; CHECK-FP16: vcvtb.f32.f16 681; CHECK-FP16: vcvtb.f32.f16 682; CHECK-FP16: vbsl 683; CHECK-FP16: vcvtb.f16.f32 684; CHECK-LIBCALL-LABEL: test_copysign: 685; CHECK-LIBCALL: bl __aeabi_h2f 686; CHECK-LIBCALL: bl __aeabi_h2f 687; CHECK-VFP-LIBCALL: vbsl 688; CHECK-NOVFP: bfc 689; CHECK-NOVFP: and 690; CHECK-NOVFP: orr 691; CHECK-LIBCALL: bl __aeabi_f2h 692define void @test_copysign(half* %p, half* %q) #0 { 693 %a = load half, half* %p, align 2 694 %b = load half, half* %q, align 2 695 %r = call half @llvm.copysign.f16(half %a, half %b) 696 store half %r, half* %p 697 ret void 698} 699 700; CHECK-FP16-LABEL: test_floor: 701; CHECK-FP16: vcvtb.f32.f16 702; CHECK-FP16: bl floorf 703; CHECK-FP16: vcvtb.f16.f32 704; CHECK-LIBCALL-LABEL: test_floor: 705; CHECK-LIBCALL: bl __aeabi_h2f 706; CHECK-LIBCALL: bl floorf 707; CHECK-LIBCALL: bl __aeabi_f2h 708define void @test_floor(half* %p) { 709 %a = load half, half* %p, align 2 710 %r = call half @llvm.floor.f16(half %a) 711 store half %r, half* %p 712 ret void 713} 714 715; CHECK-FP16-LABEL: test_ceil: 716; CHECK-FP16: vcvtb.f32.f16 717; CHECK-FP16: bl ceilf 718; CHECK-FP16: vcvtb.f16.f32 719; CHECK-LIBCALL-LABEL: test_ceil: 720; CHECK-LIBCALL: bl __aeabi_h2f 721; CHECK-LIBCALL: bl ceilf 722; CHECK-LIBCALL: bl __aeabi_f2h 723define void @test_ceil(half* %p) { 724 %a = load half, half* %p, align 2 725 %r = call half @llvm.ceil.f16(half %a) 726 store half %r, half* %p 727 ret void 728} 729 730; CHECK-FP16-LABEL: test_trunc: 731; CHECK-FP16: vcvtb.f32.f16 732; CHECK-FP16: bl truncf 733; CHECK-FP16: vcvtb.f16.f32 734; CHECK-LIBCALL-LABEL: test_trunc: 735; CHECK-LIBCALL: bl __aeabi_h2f 736; CHECK-LIBCALL: bl truncf 737; CHECK-LIBCALL: bl __aeabi_f2h 738define void @test_trunc(half* %p) { 739 %a = load half, half* %p, align 2 740 %r = call half @llvm.trunc.f16(half %a) 741 store half %r, half* %p 742 ret void 743} 744 745; CHECK-FP16-LABEL: test_rint: 746; CHECK-FP16: vcvtb.f32.f16 747; CHECK-FP16: bl rintf 748; CHECK-FP16: vcvtb.f16.f32 749; CHECK-LIBCALL-LABEL: test_rint: 750; CHECK-LIBCALL: bl __aeabi_h2f 751; CHECK-LIBCALL: bl rintf 752; CHECK-LIBCALL: bl __aeabi_f2h 753define void @test_rint(half* %p) { 754 %a = load half, half* %p, align 2 755 %r = call half @llvm.rint.f16(half %a) 756 store half %r, half* %p 757 ret void 758} 759 760; CHECK-FP16-LABEL: test_nearbyint: 761; CHECK-FP16: vcvtb.f32.f16 762; CHECK-FP16: bl nearbyintf 763; CHECK-FP16: vcvtb.f16.f32 764; CHECK-LIBCALL-LABEL: test_nearbyint: 765; CHECK-LIBCALL: bl __aeabi_h2f 766; CHECK-LIBCALL: bl nearbyintf 767; CHECK-LIBCALL: bl __aeabi_f2h 768define void @test_nearbyint(half* %p) { 769 %a = load half, half* %p, align 2 770 %r = call half @llvm.nearbyint.f16(half %a) 771 store half %r, half* %p 772 ret void 773} 774 775; CHECK-FP16-LABEL: test_round: 776; CHECK-FP16: vcvtb.f32.f16 777; CHECK-FP16: bl roundf 778; CHECK-FP16: vcvtb.f16.f32 779; CHECK-LIBCALL-LABEL: test_round: 780; CHECK-LIBCALL: bl __aeabi_h2f 781; CHECK-LIBCALL: bl roundf 782; CHECK-LIBCALL: bl __aeabi_f2h 783define void @test_round(half* %p) { 784 %a = load half, half* %p, align 2 785 %r = call half @llvm.round.f16(half %a) 786 store half %r, half* %p 787 ret void 788} 789 790; CHECK-FP16-LABEL: test_fmuladd: 791; CHECK-FP16: vcvtb.f32.f16 792; CHECK-FP16: vcvtb.f32.f16 793; CHECK-FP16: vcvtb.f32.f16 794; CHECK-FP16: vmla.f32 795; CHECK-FP16: vcvtb.f16.f32 796; CHECK-LIBCALL-LABEL: test_fmuladd: 797; CHECK-LIBCALL: bl __aeabi_h2f 798; CHECK-LIBCALL: bl __aeabi_h2f 799; CHECK-LIBCALL: bl __aeabi_h2f 800; CHECK-VFP-LIBCALL: vmla.f32 801; CHECK-NOVFP: bl __aeabi_fmul 802; CHECK-LIBCALL: bl __aeabi_f2h 803define void @test_fmuladd(half* %p, half* %q, half* %r) #0 { 804 %a = load half, half* %p, align 2 805 %b = load half, half* %q, align 2 806 %c = load half, half* %r, align 2 807 %v = call half @llvm.fmuladd.f16(half %a, half %b, half %c) 808 store half %v, half* %p 809 ret void 810} 811 812; f16 vectors are not legal in the backend. Vector elements are not assigned 813; to the register, but are stored in the stack instead. Hence insertelement 814; and extractelement have these extra loads and stores. 815 816; CHECK-ALL-LABEL: test_insertelement: 817; CHECK-ALL: sub sp, sp, #8 818; CHECK-ALL: ldrh 819; CHECK-ALL: strh 820; CHECK-ALL: ldrh 821; CHECK-ALL: strh 822; CHECK-ALL: ldrh 823; CHECK-ALL: strh 824; CHECK-ALL: ldrh 825; CHECK-ALL: strh 826; CHECK-ALL: mov 827; CHECK-ALL-DAG: ldrh 828; CHECK-ALL-DAG: add 829; CHECK-ALL: strh 830; CHECK-ALL: ldrh 831; CHECK-ALL: strh 832; CHECK-ALL: ldrh 833; CHECK-ALL: strh 834; CHECK-ALL: ldrh 835; CHECK-ALL: strh 836; CHECK-ALL: ldrh 837; CHECK-ALL: strh 838; CHECK-ALL: add sp, sp, #8 839define void @test_insertelement(half* %p, <4 x half>* %q, i32 %i) #0 { 840 %a = load half, half* %p, align 2 841 %b = load <4 x half>, <4 x half>* %q, align 8 842 %c = insertelement <4 x half> %b, half %a, i32 %i 843 store <4 x half> %c, <4 x half>* %q 844 ret void 845} 846 847; CHECK-ALL-LABEL: test_extractelement: 848; CHECK-VFP: sub sp, sp, #8 849; CHECK-VFP: ldrh 850; CHECK-VFP: ldrh 851; CHECK-VFP: orr 852; CHECK-VFP: str 853; CHECK-VFP: ldrh 854; CHECK-VFP: ldrh 855; CHECK-VFP: orr 856; CHECK-VFP: str 857; CHECK-VFP: mov 858; CHECK-VFP: add 859; CHECK-VFP: ldrh 860; CHECK-VFP: strh 861; CHECK-VFP: add sp, sp, #8 862; CHECK-VFP: bx lr 863; CHECK-NOVFP: ldrh 864; CHECK-NOVFP: strh 865; CHECK-NOVFP: ldrh 866; CHECK-NOVFP: strh 867; CHECK-NOVFP: ldrh 868; CHECK-NOVFP: strh 869; CHECK-NOVFP: ldrh 870; CHECK-NOVFP: strh 871; CHECK-NOVFP: ldrh 872define void @test_extractelement(half* %p, <4 x half>* %q, i32 %i) #0 { 873 %a = load <4 x half>, <4 x half>* %q, align 8 874 %b = extractelement <4 x half> %a, i32 %i 875 store half %b, half* %p 876 ret void 877} 878 879; test struct operations 880 881%struct.dummy = type { i32, half } 882 883; CHECK-ALL-LABEL: test_insertvalue: 884; CHECK-ALL-DAG: ldr 885; CHECK-ALL-DAG: ldrh 886; CHECK-ALL-DAG: strh 887; CHECK-ALL-DAG: str 888define void @test_insertvalue(%struct.dummy* %p, half* %q) { 889 %a = load %struct.dummy, %struct.dummy* %p 890 %b = load half, half* %q 891 %c = insertvalue %struct.dummy %a, half %b, 1 892 store %struct.dummy %c, %struct.dummy* %p 893 ret void 894} 895 896; CHECK-ALL-LABEL: test_extractvalue: 897; CHECK-ALL: .fnstart 898; CHECK-ALL: ldrh 899; CHECK-ALL: strh 900define void @test_extractvalue(%struct.dummy* %p, half* %q) { 901 %a = load %struct.dummy, %struct.dummy* %p 902 %b = extractvalue %struct.dummy %a, 1 903 store half %b, half* %q 904 ret void 905} 906 907; CHECK-ALL-LABEL: test_struct_return: 908; CHECK-FP16: vcvtb.f32.f16 909; CHECK-VFP-LIBCALL: bl __aeabi_h2f 910; CHECK-NOVFP-DAG: ldr 911; CHECK-NOVFP-DAG: ldrh 912define %struct.dummy @test_struct_return(%struct.dummy* %p) { 913 %a = load %struct.dummy, %struct.dummy* %p 914 ret %struct.dummy %a 915} 916 917; CHECK-ALL-LABEL: test_struct_arg: 918; CHECK-ALL-NEXT: .fnstart 919; CHECK-NOVFP-NEXT: mov r0, r1 920; CHECK-ALL-NEXT: bx lr 921define half @test_struct_arg(%struct.dummy %p) { 922 %a = extractvalue %struct.dummy %p, 1 923 ret half %a 924} 925 926; CHECK-LABEL: test_uitofp_i32_fadd: 927; CHECK-VFP-DAG: vcvt.f32.u32 928; CHECK-NOVFP-DAG: bl __aeabi_ui2f 929 930; CHECK-FP16-DAG: vcvtb.f16.f32 931; CHECK-FP16-DAG: vcvtb.f32.f16 932; CHECK-LIBCALL-DAG: bl __aeabi_h2f 933; CHECK-LIBCALL-DAG: bl __aeabi_h2f 934 935; CHECK-VFP-DAG: vadd.f32 936; CHECK-NOVFP-DAG: bl __aeabi_fadd 937 938; CHECK-FP16-DAG: vcvtb.f16.f32 939; CHECK-LIBCALL-DAG: bl __aeabi_f2h 940define half @test_uitofp_i32_fadd(i32 %a, half %b) #0 { 941 %c = uitofp i32 %a to half 942 %r = fadd half %b, %c 943 ret half %r 944} 945 946; CHECK-LABEL: test_sitofp_i32_fadd: 947; CHECK-VFP-DAG: vcvt.f32.s32 948; CHECK-NOVFP-DAG: bl __aeabi_i2f 949 950; CHECK-FP16-DAG: vcvtb.f16.f32 951; CHECK-FP16-DAG: vcvtb.f32.f16 952; CHECK-LIBCALL-DAG: bl __aeabi_h2f 953; CHECK-LIBCALL-DAG: bl __aeabi_h2f 954 955; CHECK-VFP-DAG: vadd.f32 956; CHECK-NOVFP-DAG: bl __aeabi_fadd 957 958; CHECK-FP16-DAG: vcvtb.f16.f32 959; CHECK-LIBCALL-DAG: bl __aeabi_f2h 960define half @test_sitofp_i32_fadd(i32 %a, half %b) #0 { 961 %c = sitofp i32 %a to half 962 %r = fadd half %b, %c 963 ret half %r 964} 965 966attributes #0 = { nounwind } 967