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 5 target 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" 6 target 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 17 define 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 34 define 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 51 define 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 68 define 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 84 define 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]+}}] 96 define 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 105 declare 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} 113 define 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} 130 define 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 144 define 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]+}}] 156 define 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}} 175 define 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}} 191 define 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 210 define 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 215 then: 216 store i32 0, i32* %p1 217 ret void 218 else: 219 store i32 0, i32* %p2 220 ret void 221 } 222 223 declare 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 237 define void @test_phi(half* %p) #0 { 238 entry: 239 %a = load half, half* %p 240 br label %loop 241 loop: 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 246 return: 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 256 define 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 266 define 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 277 define 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 287 define 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 298 define 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 309 define 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 319 define 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 329 define 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 339 define 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 349 define 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 359 define 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 371 define 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 381 define 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 391 define 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 397 declare half @llvm.sqrt.f16(half %a) #0 398 declare half @llvm.powi.f16(half %a, i32 %b) #0 399 declare half @llvm.sin.f16(half %a) #0 400 declare half @llvm.cos.f16(half %a) #0 401 declare half @llvm.pow.f16(half %a, half %b) #0 402 declare half @llvm.exp.f16(half %a) #0 403 declare half @llvm.exp2.f16(half %a) #0 404 declare half @llvm.log.f16(half %a) #0 405 declare half @llvm.log10.f16(half %a) #0 406 declare half @llvm.log2.f16(half %a) #0 407 declare half @llvm.fma.f16(half %a, half %b, half %c) #0 408 declare half @llvm.fabs.f16(half %a) #0 409 declare half @llvm.minnum.f16(half %a, half %b) #0 410 declare half @llvm.maxnum.f16(half %a, half %b) #0 411 declare half @llvm.copysign.f16(half %a, half %b) #0 412 declare half @llvm.floor.f16(half %a) #0 413 declare half @llvm.ceil.f16(half %a) #0 414 declare half @llvm.trunc.f16(half %a) #0 415 declare half @llvm.rint.f16(half %a) #0 416 declare half @llvm.nearbyint.f16(half %a) #0 417 declare half @llvm.round.f16(half %a) #0 418 declare 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 428 define 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 443 define 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 458 define 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 473 define 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 490 define 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 506 define 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 521 define 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 536 define 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 551 define 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 566 define 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 585 define 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 602 define 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 619 define 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 637 define 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 654 define 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 671 define 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 692 define 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 708 define 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 723 define 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 738 define 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 753 define 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 768 define 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 783 define 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 803 define 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 839 define 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 872 define 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 888 define 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 900 define 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 912 define %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 921 define 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 940 define 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 960 define 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 966 attributes #0 = { nounwind } 967