1560 lines · plain
1; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py2; RUN: llc -mtriple armv8a-none-none-eabihf -mattr=fullfp16 -asm-verbose=false < %s | FileCheck %s3 4define void @test_fadd(ptr %p, ptr %q) {5; CHECK-LABEL: test_fadd:6; CHECK: vldr.16 s0, [r1]7; CHECK-NEXT: vldr.16 s2, [r0]8; CHECK-NEXT: vadd.f16 s0, s2, s09; CHECK-NEXT: vstr.16 s0, [r0]10; CHECK-NEXT: bx lr11 %a = load half, ptr %p, align 212 %b = load half, ptr %q, align 213 %r = fadd half %a, %b14 store half %r, ptr %p15 ret void16}17 18define void @test_fsub(ptr %p, ptr %q) {19; CHECK-LABEL: test_fsub:20; CHECK: vldr.16 s0, [r1]21; CHECK-NEXT: vldr.16 s2, [r0]22; CHECK-NEXT: vsub.f16 s0, s2, s023; CHECK-NEXT: vstr.16 s0, [r0]24; CHECK-NEXT: bx lr25 %a = load half, ptr %p, align 226 %b = load half, ptr %q, align 227 %r = fsub half %a, %b28 store half %r, ptr %p29 ret void30}31 32define void @test_fmul(ptr %p, ptr %q) {33; CHECK-LABEL: test_fmul:34; CHECK: vldr.16 s0, [r1]35; CHECK-NEXT: vldr.16 s2, [r0]36; CHECK-NEXT: vmul.f16 s0, s2, s037; CHECK-NEXT: vstr.16 s0, [r0]38; CHECK-NEXT: bx lr39 %a = load half, ptr %p, align 240 %b = load half, ptr %q, align 241 %r = fmul half %a, %b42 store half %r, ptr %p43 ret void44}45 46define void @test_fdiv(ptr %p, ptr %q) {47; CHECK-LABEL: test_fdiv:48; CHECK: vldr.16 s0, [r1]49; CHECK-NEXT: vldr.16 s2, [r0]50; CHECK-NEXT: vdiv.f16 s0, s2, s051; CHECK-NEXT: vstr.16 s0, [r0]52; CHECK-NEXT: bx lr53 %a = load half, ptr %p, align 254 %b = load half, ptr %q, align 255 %r = fdiv half %a, %b56 store half %r, ptr %p57 ret void58}59 60define arm_aapcs_vfpcc void @test_frem(ptr %p, ptr %q) {61; CHECK-LABEL: test_frem:62; CHECK: .save {r4, lr}63; CHECK-NEXT: push {r4, lr}64; CHECK-NEXT: vldr.16 s0, [r0]65; CHECK-NEXT: vldr.16 s2, [r1]66; CHECK-NEXT: mov r4, r067; CHECK-NEXT: vcvtb.f32.f16 s0, s068; CHECK-NEXT: vcvtb.f32.f16 s1, s269; CHECK-NEXT: bl fmodf70; CHECK-NEXT: vcvtb.f16.f32 s0, s071; CHECK-NEXT: vstr.16 s0, [r4]72; CHECK-NEXT: pop {r4, pc}73 %a = load half, ptr %p, align 274 %b = load half, ptr %q, align 275 %r = frem half %a, %b76 store half %r, ptr %p77 ret void78}79 80define void @test_load_store(ptr %p, ptr %q) {81; CHECK-LABEL: test_load_store:82; CHECK: vldr.16 s0, [r0]83; CHECK-NEXT: vstr.16 s0, [r1]84; CHECK-NEXT: bx lr85 %a = load half, ptr %p, align 286 store half %a, ptr %q87 ret void88}89 90define i32 @test_fptosi_i32(ptr %p) {91; CHECK-LABEL: test_fptosi_i32:92; CHECK: vldr.16 s0, [r0]93; CHECK-NEXT: vcvt.s32.f16 s0, s094; CHECK-NEXT: vmov r0, s095; CHECK-NEXT: bx lr96 %a = load half, ptr %p, align 297 %r = fptosi half %a to i3298 ret i32 %r99}100 101define i64 @test_fptosi_i64(ptr %p) {102; CHECK-LABEL: test_fptosi_i64:103; CHECK: .save {r11, lr}104; CHECK-NEXT: push {r11, lr}105; CHECK-NEXT: ldrh r0, [r0]106; CHECK-NEXT: vmov s0, r0107; CHECK-NEXT: bl __fixhfdi108; CHECK-NEXT: pop {r11, pc}109 %a = load half, ptr %p, align 2110 %r = fptosi half %a to i64111 ret i64 %r112}113 114define i32 @test_fptoui_i32(ptr %p) {115; CHECK-LABEL: test_fptoui_i32:116; CHECK: vldr.16 s0, [r0]117; CHECK-NEXT: vcvt.u32.f16 s0, s0118; CHECK-NEXT: vmov r0, s0119; CHECK-NEXT: bx lr120 %a = load half, ptr %p, align 2121 %r = fptoui half %a to i32122 ret i32 %r123}124 125define i64 @test_fptoui_i64(ptr %p) {126; CHECK-LABEL: test_fptoui_i64:127; CHECK: .save {r11, lr}128; CHECK-NEXT: push {r11, lr}129; CHECK-NEXT: ldrh r0, [r0]130; CHECK-NEXT: vmov s0, r0131; CHECK-NEXT: bl __fixunshfdi132; CHECK-NEXT: pop {r11, pc}133 %a = load half, ptr %p, align 2134 %r = fptoui half %a to i64135 ret i64 %r136}137 138define void @test_sitofp_i32(i32 %a, ptr %p) {139; CHECK-LABEL: test_sitofp_i32:140; CHECK: vmov s0, r0141; CHECK-NEXT: vcvt.f16.s32 s0, s0142; CHECK-NEXT: vstr.16 s0, [r1]143; CHECK-NEXT: bx lr144 %r = sitofp i32 %a to half145 store half %r, ptr %p146 ret void147}148 149define void @test_uitofp_i32(i32 %a, ptr %p) {150; CHECK-LABEL: test_uitofp_i32:151; CHECK: vmov s0, r0152; CHECK-NEXT: vcvt.f16.u32 s0, s0153; CHECK-NEXT: vstr.16 s0, [r1]154; CHECK-NEXT: bx lr155 %r = uitofp i32 %a to half156 store half %r, ptr %p157 ret void158}159 160define void @test_sitofp_i64(i64 %a, ptr %p) {161; CHECK-LABEL: test_sitofp_i64:162; CHECK: .save {r4, lr}163; CHECK-NEXT: push {r4, lr}164; CHECK-NEXT: mov r4, r2165; CHECK-NEXT: bl __floatdihf166; CHECK-NEXT: vstr.16 s0, [r4]167; CHECK-NEXT: pop {r4, pc}168 %r = sitofp i64 %a to half169 store half %r, ptr %p170 ret void171}172 173define void @test_uitofp_i64(i64 %a, ptr %p) {174; CHECK-LABEL: test_uitofp_i64:175; CHECK: .save {r4, lr}176; CHECK-NEXT: push {r4, lr}177; CHECK-NEXT: mov r4, r2178; CHECK-NEXT: bl __floatundihf179; CHECK-NEXT: vstr.16 s0, [r4]180; CHECK-NEXT: pop {r4, pc}181 %r = uitofp i64 %a to half182 store half %r, ptr %p183 ret void184}185 186define void @test_fptrunc_float(float %f, ptr %p) {187; CHECK-LABEL: test_fptrunc_float:188; CHECK: vcvtb.f16.f32 s0, s0189; CHECK-NEXT: vstr.16 s0, [r0]190; CHECK-NEXT: bx lr191 %a = fptrunc float %f to half192 store half %a, ptr %p193 ret void194}195 196define void @test_fptrunc_double(double %d, ptr %p) {197; CHECK-LABEL: test_fptrunc_double:198; CHECK: vcvtb.f16.f64 s0, d0199; CHECK-NEXT: vstr.16 s0, [r0]200; CHECK-NEXT: bx lr201 %a = fptrunc double %d to half202 store half %a, ptr %p203 ret void204}205 206define float @test_fpextend_float(ptr %p) {207; CHECK-LABEL: test_fpextend_float:208; CHECK: vldr.16 s0, [r0]209; CHECK-NEXT: vcvtb.f32.f16 s0, s0210; CHECK-NEXT: bx lr211 %a = load half, ptr %p, align 2212 %r = fpext half %a to float213 ret float %r214}215 216define double @test_fpextend_double(ptr %p) {217; CHECK-LABEL: test_fpextend_double:218; CHECK: vldr.16 s0, [r0]219; CHECK-NEXT: vcvtb.f64.f16 d0, s0220; CHECK-NEXT: bx lr221 %a = load half, ptr %p, align 2222 %r = fpext half %a to double223 ret double %r224}225 226define i16 @test_bitcast_halftoi16(ptr %p) {227; CHECK-LABEL: test_bitcast_halftoi16:228; CHECK: ldrh r0, [r0]229; CHECK-NEXT: bx lr230 %a = load half, ptr %p, align 2231 %r = bitcast half %a to i16232 ret i16 %r233}234 235define void @test_bitcast_i16tohalf(i16 %a, ptr %p) {236; CHECK-LABEL: test_bitcast_i16tohalf:237; CHECK: strh r0, [r1]238; CHECK-NEXT: bx lr239 %r = bitcast i16 %a to half240 store half %r, ptr %p241 ret void242}243 244define void @test_sqrt(ptr %p) {245; CHECK-LABEL: test_sqrt:246; CHECK: vldr.16 s0, [r0]247; CHECK-NEXT: vsqrt.f16 s0, s0248; CHECK-NEXT: vstr.16 s0, [r0]249; CHECK-NEXT: bx lr250 %a = load half, ptr %p, align 2251 %r = call half @llvm.sqrt.f16(half %a)252 store half %r, ptr %p253 ret void254}255 256define void @test_fpowi(ptr %p, i32 %b) {257; CHECK-LABEL: test_fpowi:258; CHECK: .save {r4, lr}259; CHECK-NEXT: push {r4, lr}260; CHECK-NEXT: vldr.16 s0, [r0]261; CHECK-NEXT: mov r4, r0262; CHECK-NEXT: mov r0, r1263; CHECK-NEXT: vcvtb.f32.f16 s0, s0264; CHECK-NEXT: bl __powisf2265; CHECK-NEXT: vcvtb.f16.f32 s0, s0266; CHECK-NEXT: vstr.16 s0, [r4]267; CHECK-NEXT: pop {r4, pc}268 %a = load half, ptr %p, align 2269 %r = call half @llvm.powi.f16.i32(half %a, i32 %b)270 store half %r, ptr %p271 ret void272}273 274define void @test_sin(ptr %p) {275; CHECK-LABEL: test_sin:276; CHECK: .save {r4, lr}277; CHECK-NEXT: push {r4, lr}278; CHECK-NEXT: vldr.16 s0, [r0]279; CHECK-NEXT: mov r4, r0280; CHECK-NEXT: vcvtb.f32.f16 s0, s0281; CHECK-NEXT: bl sinf282; CHECK-NEXT: vcvtb.f16.f32 s0, s0283; CHECK-NEXT: vstr.16 s0, [r4]284; CHECK-NEXT: pop {r4, pc}285 %a = load half, ptr %p, align 2286 %r = call half @llvm.sin.f16(half %a)287 store half %r, ptr %p288 ret void289}290 291define void @test_cos(ptr %p) {292; CHECK-LABEL: test_cos:293; CHECK: .save {r4, lr}294; CHECK-NEXT: push {r4, lr}295; CHECK-NEXT: vldr.16 s0, [r0]296; CHECK-NEXT: mov r4, r0297; CHECK-NEXT: vcvtb.f32.f16 s0, s0298; CHECK-NEXT: bl cosf299; CHECK-NEXT: vcvtb.f16.f32 s0, s0300; CHECK-NEXT: vstr.16 s0, [r4]301; CHECK-NEXT: pop {r4, pc}302 %a = load half, ptr %p, align 2303 %r = call half @llvm.cos.f16(half %a)304 store half %r, ptr %p305 ret void306}307 308define void @test_tan(ptr %p) {309; CHECK-LABEL: test_tan:310; CHECK: .save {r4, lr}311; CHECK-NEXT: push {r4, lr}312; CHECK-NEXT: vldr.16 s0, [r0]313; CHECK-NEXT: mov r4, r0314; CHECK-NEXT: vcvtb.f32.f16 s0, s0315; CHECK-NEXT: bl tanf316; CHECK-NEXT: vcvtb.f16.f32 s0, s0317; CHECK-NEXT: vstr.16 s0, [r4]318; CHECK-NEXT: pop {r4, pc}319 %a = load half, ptr %p, align 2320 %r = call half @llvm.tan.f16(half %a)321 store half %r, ptr %p322 ret void323}324 325define void @test_pow(ptr %p, ptr %q) {326; CHECK-LABEL: test_pow:327; CHECK: .save {r4, lr}328; CHECK-NEXT: push {r4, lr}329; CHECK-NEXT: vldr.16 s0, [r0]330; CHECK-NEXT: vldr.16 s2, [r1]331; CHECK-NEXT: mov r4, r0332; CHECK-NEXT: vcvtb.f32.f16 s0, s0333; CHECK-NEXT: vcvtb.f32.f16 s1, s2334; CHECK-NEXT: bl powf335; CHECK-NEXT: vcvtb.f16.f32 s0, s0336; CHECK-NEXT: vstr.16 s0, [r4]337; CHECK-NEXT: pop {r4, pc}338 %a = load half, ptr %p, align 2339 %b = load half, ptr %q, align 2340 %r = call half @llvm.pow.f16(half %a, half %b)341 store half %r, ptr %p342 ret void343}344 345define void @test_exp(ptr %p) {346; CHECK-LABEL: test_exp:347; CHECK: .save {r4, lr}348; CHECK-NEXT: push {r4, lr}349; CHECK-NEXT: vldr.16 s0, [r0]350; CHECK-NEXT: mov r4, r0351; CHECK-NEXT: vcvtb.f32.f16 s0, s0352; CHECK-NEXT: bl expf353; CHECK-NEXT: vcvtb.f16.f32 s0, s0354; CHECK-NEXT: vstr.16 s0, [r4]355; CHECK-NEXT: pop {r4, pc}356 %a = load half, ptr %p, align 2357 %r = call half @llvm.exp.f16(half %a)358 store half %r, ptr %p359 ret void360}361 362define void @test_exp2(ptr %p) {363; CHECK-LABEL: test_exp2:364; CHECK: .save {r4, lr}365; CHECK-NEXT: push {r4, lr}366; CHECK-NEXT: vldr.16 s0, [r0]367; CHECK-NEXT: mov r4, r0368; CHECK-NEXT: vcvtb.f32.f16 s0, s0369; CHECK-NEXT: bl exp2f370; CHECK-NEXT: vcvtb.f16.f32 s0, s0371; CHECK-NEXT: vstr.16 s0, [r4]372; CHECK-NEXT: pop {r4, pc}373 %a = load half, ptr %p, align 2374 %r = call half @llvm.exp2.f16(half %a)375 store half %r, ptr %p376 ret void377}378 379define void @test_log(ptr %p) {380; CHECK-LABEL: test_log:381; CHECK: .save {r4, lr}382; CHECK-NEXT: push {r4, lr}383; CHECK-NEXT: vldr.16 s0, [r0]384; CHECK-NEXT: mov r4, r0385; CHECK-NEXT: vcvtb.f32.f16 s0, s0386; CHECK-NEXT: bl logf387; CHECK-NEXT: vcvtb.f16.f32 s0, s0388; CHECK-NEXT: vstr.16 s0, [r4]389; CHECK-NEXT: pop {r4, pc}390 %a = load half, ptr %p, align 2391 %r = call half @llvm.log.f16(half %a)392 store half %r, ptr %p393 ret void394}395 396define void @test_log10(ptr %p) {397; CHECK-LABEL: test_log10:398; CHECK: .save {r4, lr}399; CHECK-NEXT: push {r4, lr}400; CHECK-NEXT: vldr.16 s0, [r0]401; CHECK-NEXT: mov r4, r0402; CHECK-NEXT: vcvtb.f32.f16 s0, s0403; CHECK-NEXT: bl log10f404; CHECK-NEXT: vcvtb.f16.f32 s0, s0405; CHECK-NEXT: vstr.16 s0, [r4]406; CHECK-NEXT: pop {r4, pc}407 %a = load half, ptr %p, align 2408 %r = call half @llvm.log10.f16(half %a)409 store half %r, ptr %p410 ret void411}412 413define void @test_log2(ptr %p) {414; CHECK-LABEL: test_log2:415; CHECK: .save {r4, lr}416; CHECK-NEXT: push {r4, lr}417; CHECK-NEXT: vldr.16 s0, [r0]418; CHECK-NEXT: mov r4, r0419; CHECK-NEXT: vcvtb.f32.f16 s0, s0420; CHECK-NEXT: bl log2f421; CHECK-NEXT: vcvtb.f16.f32 s0, s0422; CHECK-NEXT: vstr.16 s0, [r4]423; CHECK-NEXT: pop {r4, pc}424 %a = load half, ptr %p, align 2425 %r = call half @llvm.log2.f16(half %a)426 store half %r, ptr %p427 ret void428}429 430define void @test_fma(ptr %p, ptr %q, ptr %r) {431; CHECK-LABEL: test_fma:432; CHECK: vldr.16 s0, [r1]433; CHECK-NEXT: vldr.16 s2, [r0]434; CHECK-NEXT: vldr.16 s4, [r2]435; CHECK-NEXT: vfma.f16 s4, s2, s0436; CHECK-NEXT: vstr.16 s4, [r0]437; CHECK-NEXT: bx lr438 %a = load half, ptr %p, align 2439 %b = load half, ptr %q, align 2440 %c = load half, ptr %r, align 2441 %v = call half @llvm.fma.f16(half %a, half %b, half %c)442 store half %v, ptr %p443 ret void444}445 446define void @test_fabs(ptr %p) {447; CHECK-LABEL: test_fabs:448; CHECK: vldr.16 s0, [r0]449; CHECK-NEXT: vabs.f16 s0, s0450; CHECK-NEXT: vstr.16 s0, [r0]451; CHECK-NEXT: bx lr452 %a = load half, ptr %p, align 2453 %r = call half @llvm.fabs.f16(half %a)454 store half %r, ptr %p455 ret void456}457 458define void @test_minnum(ptr %p, ptr %q) {459; CHECK-LABEL: test_minnum:460; CHECK: vldr.16 s0, [r1]461; CHECK-NEXT: vldr.16 s2, [r0]462; CHECK-NEXT: vminnm.f16 s0, s2, s0463; CHECK-NEXT: vstr.16 s0, [r0]464; CHECK-NEXT: bx lr465 %a = load half, ptr %p, align 2466 %b = load half, ptr %q, align 2467 %r = call half @llvm.minnum.f16(half %a, half %b)468 store half %r, ptr %p469 ret void470}471 472define void @test_maxnum(ptr %p, ptr %q) {473; CHECK-LABEL: test_maxnum:474; CHECK: vldr.16 s0, [r1]475; CHECK-NEXT: vldr.16 s2, [r0]476; CHECK-NEXT: vmaxnm.f16 s0, s2, s0477; CHECK-NEXT: vstr.16 s0, [r0]478; CHECK-NEXT: bx lr479 %a = load half, ptr %p, align 2480 %b = load half, ptr %q, align 2481 %r = call half @llvm.maxnum.f16(half %a, half %b)482 store half %r, ptr %p483 ret void484}485 486define void @test_minimum(ptr %p) {487; CHECK-LABEL: test_minimum:488; CHECK: vldr.16 s2, [r0]489; CHECK-NEXT: vmov.f16 s0, #1.000000e+00490; CHECK-NEXT: vcmp.f16 s2, s0491; CHECK-NEXT: vmrs APSR_nzcv, fpscr492; CHECK-NEXT: vselge.f16 s0, s0, s2493; CHECK-NEXT: vstr.16 s0, [r0]494; CHECK-NEXT: bx lr495 %a = load half, ptr %p, align 2496 %c = fcmp ult half %a, 1.0497 %r = select i1 %c, half %a, half 1.0498 store half %r, ptr %p499 ret void500}501 502define void @test_maximum(ptr %p) {503; CHECK-LABEL: test_maximum:504; CHECK: vldr.16 s2, [r0]505; CHECK-NEXT: vmov.f16 s0, #1.000000e+00506; CHECK-NEXT: vcmp.f16 s0, s2507; CHECK-NEXT: vmrs APSR_nzcv, fpscr508; CHECK-NEXT: vselge.f16 s0, s0, s2509; CHECK-NEXT: vstr.16 s0, [r0]510; CHECK-NEXT: bx lr511 %a = load half, ptr %p, align 2512 %c = fcmp ugt half %a, 1.0513 %r = select i1 %c, half %a, half 1.0514 store half %r, ptr %p515 ret void516}517 518define void @test_copysign(ptr %p, ptr %q) {519; CHECK-LABEL: test_copysign:520; CHECK: .pad #4521; CHECK-NEXT: sub sp, sp, #4522; CHECK-NEXT: vldr.16 s0, [r1]523; CHECK-NEXT: vstr.16 s0, [sp]524; CHECK-NEXT: vldr.16 s0, [r0]525; CHECK-NEXT: ldrb r1, [sp, #1]526; CHECK-NEXT: vabs.f16 s0, s0527; CHECK-NEXT: tst r1, #128528; CHECK-NEXT: vneg.f16 s2, s0529; CHECK-NEXT: vseleq.f16 s0, s0, s2530; CHECK-NEXT: vstr.16 s0, [r0]531; CHECK-NEXT: add sp, sp, #4532; CHECK-NEXT: bx lr533 %a = load half, ptr %p, align 2534 %b = load half, ptr %q, align 2535 %r = call half @llvm.copysign.f16(half %a, half %b)536 store half %r, ptr %p537 ret void538}539 540define void @test_floor(ptr %p) {541; CHECK-LABEL: test_floor:542; CHECK: vldr.16 s0, [r0]543; CHECK-NEXT: vrintm.f16 s0, s0544; CHECK-NEXT: vstr.16 s0, [r0]545; CHECK-NEXT: bx lr546 %a = load half, ptr %p, align 2547 %r = call half @llvm.floor.f16(half %a)548 store half %r, ptr %p549 ret void550}551 552define void @test_ceil(ptr %p) {553; CHECK-LABEL: test_ceil:554; CHECK: vldr.16 s0, [r0]555; CHECK-NEXT: vrintp.f16 s0, s0556; CHECK-NEXT: vstr.16 s0, [r0]557; CHECK-NEXT: bx lr558 %a = load half, ptr %p, align 2559 %r = call half @llvm.ceil.f16(half %a)560 store half %r, ptr %p561 ret void562}563 564define void @test_trunc(ptr %p) {565; CHECK-LABEL: test_trunc:566; CHECK: vldr.16 s0, [r0]567; CHECK-NEXT: vrintz.f16 s0, s0568; CHECK-NEXT: vstr.16 s0, [r0]569; CHECK-NEXT: bx lr570 %a = load half, ptr %p, align 2571 %r = call half @llvm.trunc.f16(half %a)572 store half %r, ptr %p573 ret void574}575 576define void @test_rint(ptr %p) {577; CHECK-LABEL: test_rint:578; CHECK: vldr.16 s0, [r0]579; CHECK-NEXT: vrintx.f16 s0, s0580; CHECK-NEXT: vstr.16 s0, [r0]581; CHECK-NEXT: bx lr582 %a = load half, ptr %p, align 2583 %r = call half @llvm.rint.f16(half %a)584 store half %r, ptr %p585 ret void586}587 588define void @test_nearbyint(ptr %p) {589; CHECK-LABEL: test_nearbyint:590; CHECK: vldr.16 s0, [r0]591; CHECK-NEXT: vrintr.f16 s0, s0592; CHECK-NEXT: vstr.16 s0, [r0]593; CHECK-NEXT: bx lr594 %a = load half, ptr %p, align 2595 %r = call half @llvm.nearbyint.f16(half %a)596 store half %r, ptr %p597 ret void598}599 600define void @test_round(ptr %p) {601; CHECK-LABEL: test_round:602; CHECK: vldr.16 s0, [r0]603; CHECK-NEXT: vrinta.f16 s0, s0604; CHECK-NEXT: vstr.16 s0, [r0]605; CHECK-NEXT: bx lr606 %a = load half, ptr %p, align 2607 %r = call half @llvm.round.f16(half %a)608 store half %r, ptr %p609 ret void610}611 612define void @test_roundeven(ptr %p) {613; CHECK-LABEL: test_roundeven:614; CHECK: vldr.16 s0, [r0]615; CHECK-NEXT: vrintn.f16 s0, s0616; CHECK-NEXT: vstr.16 s0, [r0]617; CHECK-NEXT: bx lr618 %a = load half, ptr %p, align 2619 %r = call half @llvm.roundeven.f16(half %a)620 store half %r, ptr %p621 ret void622}623 624define void @test_fmuladd(ptr %p, ptr %q, ptr %r) {625; CHECK-LABEL: test_fmuladd:626; CHECK: vldr.16 s0, [r1]627; CHECK-NEXT: vldr.16 s2, [r0]628; CHECK-NEXT: vldr.16 s4, [r2]629; CHECK-NEXT: vfma.f16 s4, s2, s0630; CHECK-NEXT: vstr.16 s4, [r0]631; CHECK-NEXT: bx lr632 %a = load half, ptr %p, align 2633 %b = load half, ptr %q, align 2634 %c = load half, ptr %r, align 2635 %v = call half @llvm.fmuladd.f16(half %a, half %b, half %c)636 store half %v, ptr %p637 ret void638}639 640; Half-precision intrinsics641 642define half @add_f16(half %x, half %y) #0 {643; CHECK-LABEL: add_f16:644; CHECK: vadd.f16 s0, s0, s1645; CHECK-NEXT: bx lr646 %val = call half @llvm.experimental.constrained.fadd.f16(half %x, half %y, metadata !"round.tonearest", metadata !"fpexcept.strict") #0647 ret half %val648}649 650define half @sub_f16(half %x, half %y) #0 {651; CHECK-LABEL: sub_f16:652; CHECK: vsub.f16 s0, s0, s1653; CHECK-NEXT: bx lr654 %val = call half @llvm.experimental.constrained.fsub.f16(half %x, half %y, metadata !"round.tonearest", metadata !"fpexcept.strict") #0655 ret half %val656}657 658define half @mul_f16(half %x, half %y) #0 {659; CHECK-LABEL: mul_f16:660; CHECK: vmul.f16 s0, s0, s1661; CHECK-NEXT: bx lr662 %val = call half @llvm.experimental.constrained.fmul.f16(half %x, half %y, metadata !"round.tonearest", metadata !"fpexcept.strict") #0663 ret half %val664}665 666define half @div_f16(half %x, half %y) #0 {667; CHECK-LABEL: div_f16:668; CHECK: vdiv.f16 s0, s0, s1669; CHECK-NEXT: bx lr670 %val = call half @llvm.experimental.constrained.fdiv.f16(half %x, half %y, metadata !"round.tonearest", metadata !"fpexcept.strict") #0671 ret half %val672}673 674define half @frem_f16(half %x, half %y) #0 {675; CHECK-LABEL: frem_f16:676; CHECK: .save {r11, lr}677; CHECK-NEXT: push {r11, lr}678; CHECK-NEXT: vcvtb.f32.f16 s1, s1679; CHECK-NEXT: vcvtb.f32.f16 s0, s0680; CHECK-NEXT: bl fmodf681; CHECK-NEXT: vcvtb.f16.f32 s0, s0682; CHECK-NEXT: pop {r11, pc}683 %val = call half @llvm.experimental.constrained.frem.f16(half %x, half %y, metadata !"round.tonearest", metadata !"fpexcept.strict") #0684 ret half %val685}686 687define half @fma_f16(half %x, half %y, half %z) #0 {688; CHECK-LABEL: fma_f16:689; CHECK: vfma.f16 s2, s0, s1690; CHECK-NEXT: vmov.f32 s0, s2691; CHECK-NEXT: bx lr692 %val = call half @llvm.experimental.constrained.fma.f16(half %x, half %y, half %z, metadata !"round.tonearest", metadata !"fpexcept.strict") #0693 ret half %val694}695 696define half @fmuladd_f16(half %x, half %y, half %z) #0 {697; CHECK-LABEL: fmuladd_f16:698; CHECK: vfma.f16 s2, s0, s1699; CHECK-NEXT: vmov.f32 s0, s2700; CHECK-NEXT: bx lr701 %val = call half @llvm.experimental.constrained.fmuladd.f16(half %x, half %y, half %z, metadata !"round.tonearest", metadata !"fpexcept.strict") #0702 ret half %val703}704 705define i32 @fptosi_i32_f16(half %x) #0 {706; CHECK-LABEL: fptosi_i32_f16:707; CHECK: vcvt.s32.f16 s0, s0708; CHECK-NEXT: vmov r0, s0709; CHECK-NEXT: bx lr710 %val = call i32 @llvm.experimental.constrained.fptosi.i32.f16(half %x, metadata !"fpexcept.strict") #0711 ret i32 %val712}713 714define i32 @fptoui_i32_f16(half %x) #0 {715; CHECK-LABEL: fptoui_i32_f16:716; CHECK: vcvt.u32.f16 s0, s0717; CHECK-NEXT: vmov r0, s0718; CHECK-NEXT: bx lr719 %val = call i32 @llvm.experimental.constrained.fptoui.i32.f16(half %x, metadata !"fpexcept.strict") #0720 ret i32 %val721}722 723define i64 @fptosi_i64_f16(half %x) #0 {724; CHECK-LABEL: fptosi_i64_f16:725; CHECK: .save {r11, lr}726; CHECK-NEXT: push {r11, lr}727; CHECK-NEXT: vmov.f16 r0, s0728; CHECK-NEXT: vmov s0, r0729; CHECK-NEXT: bl __fixhfdi730; CHECK-NEXT: pop {r11, pc}731 %val = call i64 @llvm.experimental.constrained.fptosi.i64.f16(half %x, metadata !"fpexcept.strict") #0732 ret i64 %val733}734 735define i64 @fptoui_i64_f16(half %x) #0 {736; CHECK-LABEL: fptoui_i64_f16:737; CHECK: .save {r11, lr}738; CHECK-NEXT: push {r11, lr}739; CHECK-NEXT: vmov.f16 r0, s0740; CHECK-NEXT: vmov s0, r0741; CHECK-NEXT: bl __fixunshfdi742; CHECK-NEXT: pop {r11, pc}743 %val = call i64 @llvm.experimental.constrained.fptoui.i64.f16(half %x, metadata !"fpexcept.strict") #0744 ret i64 %val745}746 747define half @sitofp_f16_i32(i32 %x) #0 {748; CHECK-LABEL: sitofp_f16_i32:749; CHECK: .pad #8750; CHECK-NEXT: sub sp, sp, #8751; CHECK-NEXT: movw r1, #0752; CHECK-NEXT: eor r0, r0, #-2147483648753; CHECK-NEXT: movt r1, #17200754; CHECK-NEXT: str r0, [sp]755; CHECK-NEXT: str r1, [sp, #4]756; CHECK-NEXT: vldr d16, .LCPI57_0757; CHECK-NEXT: vldr d17, [sp]758; CHECK-NEXT: vsub.f64 d16, d17, d16759; CHECK-NEXT: vcvtb.f16.f64 s0, d16760; CHECK-NEXT: add sp, sp, #8761; CHECK-NEXT: bx lr762; CHECK-NEXT: .p2align 3763; CHECK-NEXT: .LCPI57_0:764; CHECK-NEXT: .long 2147483648765; CHECK-NEXT: .long 1127219200766 %val = call half @llvm.experimental.constrained.sitofp.f16.i32(i32 %x, metadata !"round.tonearest", metadata !"fpexcept.strict") #0767 ret half %val768}769 770define half @uitofp_f16_i32(i32 %x) #0 {771; CHECK-LABEL: uitofp_f16_i32:772; CHECK: .pad #8773; CHECK-NEXT: sub sp, sp, #8774; CHECK-NEXT: movw r1, #0775; CHECK-NEXT: str r0, [sp]776; CHECK-NEXT: movt r1, #17200777; CHECK-NEXT: vldr d16, .LCPI58_0778; CHECK-NEXT: str r1, [sp, #4]779; CHECK-NEXT: vldr d17, [sp]780; CHECK-NEXT: vsub.f64 d16, d17, d16781; CHECK-NEXT: vcvtb.f16.f64 s0, d16782; CHECK-NEXT: add sp, sp, #8783; CHECK-NEXT: bx lr784; CHECK-NEXT: .p2align 3785; CHECK-NEXT: .LCPI58_0:786; CHECK-NEXT: .long 0787; CHECK-NEXT: .long 1127219200788 %val = call half @llvm.experimental.constrained.uitofp.f16.i32(i32 %x, metadata !"round.tonearest", metadata !"fpexcept.strict") #0789 ret half %val790}791 792define half @sitofp_f16_i64(i64 %x) #0 {793; CHECK-LABEL: sitofp_f16_i64:794; CHECK: .save {r11, lr}795; CHECK-NEXT: push {r11, lr}796; CHECK-NEXT: bl __floatdihf797; CHECK-NEXT: pop {r11, pc}798 %val = call half @llvm.experimental.constrained.sitofp.f16.i64(i64 %x, metadata !"round.tonearest", metadata !"fpexcept.strict") #0799 ret half %val800}801 802define half @uitofp_f16_i64(i64 %x) #0 {803; CHECK-LABEL: uitofp_f16_i64:804; CHECK: .save {r11, lr}805; CHECK-NEXT: push {r11, lr}806; CHECK-NEXT: bl __floatundihf807; CHECK-NEXT: pop {r11, pc}808 %val = call half @llvm.experimental.constrained.uitofp.f16.i64(i64 %x, metadata !"round.tonearest", metadata !"fpexcept.strict") #0809 ret half %val810}811 812define half @sitofp_f16_i128(i128 %x) #0 {813; CHECK-LABEL: sitofp_f16_i128:814; CHECK: .save {r11, lr}815; CHECK-NEXT: push {r11, lr}816; CHECK-NEXT: bl __floattihf817; CHECK-NEXT: pop {r11, pc}818 %val = call half @llvm.experimental.constrained.sitofp.f16.i128(i128 %x, metadata !"round.tonearest", metadata !"fpexcept.strict") #0819 ret half %val820}821 822define half @uitofp_f16_i128(i128 %x) #0 {823; CHECK-LABEL: uitofp_f16_i128:824; CHECK: .save {r11, lr}825; CHECK-NEXT: push {r11, lr}826; CHECK-NEXT: bl __floatuntihf827; CHECK-NEXT: pop {r11, pc}828 %val = call half @llvm.experimental.constrained.uitofp.f16.i128(i128 %x, metadata !"round.tonearest", metadata !"fpexcept.strict") #0829 ret half %val830}831 832define half @sqrt_f16(half %x) #0 {833; CHECK-LABEL: sqrt_f16:834; CHECK: vsqrt.f16 s0, s0835; CHECK-NEXT: bx lr836 %val = call half @llvm.experimental.constrained.sqrt.f16(half %x, metadata !"round.tonearest", metadata !"fpexcept.strict") #0837 ret half %val838}839 840define half @powi_f16(half %x, i32 %y) #0 {841; CHECK-LABEL: powi_f16:842; CHECK: .save {r11, lr}843; CHECK-NEXT: push {r11, lr}844; CHECK-NEXT: vcvtb.f32.f16 s0, s0845; CHECK-NEXT: bl __powisf2846; CHECK-NEXT: vcvtb.f16.f32 s0, s0847; CHECK-NEXT: pop {r11, pc}848 %val = call half @llvm.experimental.constrained.powi.f16(half %x, i32 %y, metadata !"round.tonearest", metadata !"fpexcept.strict") #0849 ret half %val850}851 852define half @sin_f16(half %x) #0 {853; CHECK-LABEL: sin_f16:854; CHECK: .save {r11, lr}855; CHECK-NEXT: push {r11, lr}856; CHECK-NEXT: vcvtb.f32.f16 s0, s0857; CHECK-NEXT: bl sinf858; CHECK-NEXT: vcvtb.f16.f32 s0, s0859; CHECK-NEXT: pop {r11, pc}860 %val = call half @llvm.experimental.constrained.sin.f16(half %x, metadata !"round.tonearest", metadata !"fpexcept.strict") #0861 ret half %val862}863 864define half @cos_f16(half %x) #0 {865; CHECK-LABEL: cos_f16:866; CHECK: .save {r11, lr}867; CHECK-NEXT: push {r11, lr}868; CHECK-NEXT: vcvtb.f32.f16 s0, s0869; CHECK-NEXT: bl cosf870; CHECK-NEXT: vcvtb.f16.f32 s0, s0871; CHECK-NEXT: pop {r11, pc}872 %val = call half @llvm.experimental.constrained.cos.f16(half %x, metadata !"round.tonearest", metadata !"fpexcept.strict") #0873 ret half %val874}875 876define half @tan_f16(half %x) #0 {877; CHECK-LABEL: tan_f16:878; CHECK: .save {r11, lr}879; CHECK-NEXT: push {r11, lr}880; CHECK-NEXT: vcvtb.f32.f16 s0, s0881; CHECK-NEXT: bl tanf882; CHECK-NEXT: vcvtb.f16.f32 s0, s0883; CHECK-NEXT: pop {r11, pc}884 %val = call half @llvm.experimental.constrained.tan.f16(half %x, metadata !"round.tonearest", metadata !"fpexcept.strict") #0885 ret half %val886}887 888define half @asin_f16(half %x) #0 {889; CHECK-LABEL: asin_f16:890; CHECK: .save {r11, lr}891; CHECK-NEXT: push {r11, lr}892; CHECK-NEXT: vcvtb.f32.f16 s0, s0893; CHECK-NEXT: bl asinf894; CHECK-NEXT: vcvtb.f16.f32 s0, s0895; CHECK-NEXT: pop {r11, pc}896 %val = call half @llvm.experimental.constrained.asin.f16(half %x, metadata !"round.tonearest", metadata !"fpexcept.strict") #0897 ret half %val898}899 900define half @acos_f16(half %x) #0 {901; CHECK-LABEL: acos_f16:902; CHECK: .save {r11, lr}903; CHECK-NEXT: push {r11, lr}904; CHECK-NEXT: vcvtb.f32.f16 s0, s0905; CHECK-NEXT: bl acosf906; CHECK-NEXT: vcvtb.f16.f32 s0, s0907; CHECK-NEXT: pop {r11, pc}908 %val = call half @llvm.experimental.constrained.acos.f16(half %x, metadata !"round.tonearest", metadata !"fpexcept.strict") #0909 ret half %val910}911 912define half @atan_f16(half %x) #0 {913; CHECK-LABEL: atan_f16:914; CHECK: .save {r11, lr}915; CHECK-NEXT: push {r11, lr}916; CHECK-NEXT: vcvtb.f32.f16 s0, s0917; CHECK-NEXT: bl atanf918; CHECK-NEXT: vcvtb.f16.f32 s0, s0919; CHECK-NEXT: pop {r11, pc}920 %val = call half @llvm.experimental.constrained.atan.f16(half %x, metadata !"round.tonearest", metadata !"fpexcept.strict") #0921 ret half %val922}923 924define half @atan2_f16(half %x, half %y) #0 {925; CHECK-LABEL: atan2_f16:926; CHECK: .save {r11, lr}927; CHECK-NEXT: push {r11, lr}928; CHECK-NEXT: vcvtb.f32.f16 s1, s1929; CHECK-NEXT: vcvtb.f32.f16 s0, s0930; CHECK-NEXT: bl atan2f931; CHECK-NEXT: vcvtb.f16.f32 s0, s0932; CHECK-NEXT: pop {r11, pc}933 %val = call half @llvm.experimental.constrained.atan2.f16(half %x, half %y, metadata !"round.tonearest", metadata !"fpexcept.strict") #0934 ret half %val935}936 937define half @sinh_f16(half %x) #0 {938; CHECK-LABEL: sinh_f16:939; CHECK: .save {r11, lr}940; CHECK-NEXT: push {r11, lr}941; CHECK-NEXT: vcvtb.f32.f16 s0, s0942; CHECK-NEXT: bl sinhf943; CHECK-NEXT: vcvtb.f16.f32 s0, s0944; CHECK-NEXT: pop {r11, pc}945 %val = call half @llvm.experimental.constrained.sinh.f16(half %x, metadata !"round.tonearest", metadata !"fpexcept.strict") #0946 ret half %val947}948 949define half @cosh_f16(half %x) #0 {950; CHECK-LABEL: cosh_f16:951; CHECK: .save {r11, lr}952; CHECK-NEXT: push {r11, lr}953; CHECK-NEXT: vcvtb.f32.f16 s0, s0954; CHECK-NEXT: bl coshf955; CHECK-NEXT: vcvtb.f16.f32 s0, s0956; CHECK-NEXT: pop {r11, pc}957 %val = call half @llvm.experimental.constrained.cosh.f16(half %x, metadata !"round.tonearest", metadata !"fpexcept.strict") #0958 ret half %val959}960 961define half @tanh_f16(half %x) #0 {962; CHECK-LABEL: tanh_f16:963; CHECK: .save {r11, lr}964; CHECK-NEXT: push {r11, lr}965; CHECK-NEXT: vcvtb.f32.f16 s0, s0966; CHECK-NEXT: bl tanhf967; CHECK-NEXT: vcvtb.f16.f32 s0, s0968; CHECK-NEXT: pop {r11, pc}969 %val = call half @llvm.experimental.constrained.tanh.f16(half %x, metadata !"round.tonearest", metadata !"fpexcept.strict") #0970 ret half %val971}972 973define half @pow_f16(half %x, half %y) #0 {974; CHECK-LABEL: pow_f16:975; CHECK: .save {r11, lr}976; CHECK-NEXT: push {r11, lr}977; CHECK-NEXT: vcvtb.f32.f16 s1, s1978; CHECK-NEXT: vcvtb.f32.f16 s0, s0979; CHECK-NEXT: bl powf980; CHECK-NEXT: vcvtb.f16.f32 s0, s0981; CHECK-NEXT: pop {r11, pc}982 %val = call half @llvm.experimental.constrained.pow.f16(half %x, half %y, metadata !"round.tonearest", metadata !"fpexcept.strict") #0983 ret half %val984}985 986define half @log_f16(half %x) #0 {987; CHECK-LABEL: log_f16:988; CHECK: .save {r11, lr}989; CHECK-NEXT: push {r11, lr}990; CHECK-NEXT: vcvtb.f32.f16 s0, s0991; CHECK-NEXT: bl logf992; CHECK-NEXT: vcvtb.f16.f32 s0, s0993; CHECK-NEXT: pop {r11, pc}994 %val = call half @llvm.experimental.constrained.log.f16(half %x, metadata !"round.tonearest", metadata !"fpexcept.strict") #0995 ret half %val996}997 998define half @log10_f16(half %x) #0 {999; CHECK-LABEL: log10_f16:1000; CHECK: .save {r11, lr}1001; CHECK-NEXT: push {r11, lr}1002; CHECK-NEXT: vcvtb.f32.f16 s0, s01003; CHECK-NEXT: bl log10f1004; CHECK-NEXT: vcvtb.f16.f32 s0, s01005; CHECK-NEXT: pop {r11, pc}1006 %val = call half @llvm.experimental.constrained.log10.f16(half %x, metadata !"round.tonearest", metadata !"fpexcept.strict") #01007 ret half %val1008}1009 1010define half @log2_f16(half %x) #0 {1011; CHECK-LABEL: log2_f16:1012; CHECK: .save {r11, lr}1013; CHECK-NEXT: push {r11, lr}1014; CHECK-NEXT: vcvtb.f32.f16 s0, s01015; CHECK-NEXT: bl log2f1016; CHECK-NEXT: vcvtb.f16.f32 s0, s01017; CHECK-NEXT: pop {r11, pc}1018 %val = call half @llvm.experimental.constrained.log2.f16(half %x, metadata !"round.tonearest", metadata !"fpexcept.strict") #01019 ret half %val1020}1021 1022define half @exp_f16(half %x) #0 {1023; CHECK-LABEL: exp_f16:1024; CHECK: .save {r11, lr}1025; CHECK-NEXT: push {r11, lr}1026; CHECK-NEXT: vcvtb.f32.f16 s0, s01027; CHECK-NEXT: bl expf1028; CHECK-NEXT: vcvtb.f16.f32 s0, s01029; CHECK-NEXT: pop {r11, pc}1030 %val = call half @llvm.experimental.constrained.exp.f16(half %x, metadata !"round.tonearest", metadata !"fpexcept.strict") #01031 ret half %val1032}1033 1034define half @exp2_f16(half %x) #0 {1035; CHECK-LABEL: exp2_f16:1036; CHECK: .save {r11, lr}1037; CHECK-NEXT: push {r11, lr}1038; CHECK-NEXT: vcvtb.f32.f16 s0, s01039; CHECK-NEXT: bl exp2f1040; CHECK-NEXT: vcvtb.f16.f32 s0, s01041; CHECK-NEXT: pop {r11, pc}1042 %val = call half @llvm.experimental.constrained.exp2.f16(half %x, metadata !"round.tonearest", metadata !"fpexcept.strict") #01043 ret half %val1044}1045 1046define half @rint_f16(half %x) #0 {1047; CHECK-LABEL: rint_f16:1048; CHECK: vrintx.f16 s0, s01049; CHECK-NEXT: bx lr1050 %val = call half @llvm.experimental.constrained.rint.f16(half %x, metadata !"round.tonearest", metadata !"fpexcept.strict") #01051 ret half %val1052}1053 1054define half @nearbyint_f16(half %x) #0 {1055; CHECK-LABEL: nearbyint_f16:1056; CHECK: vrintr.f16 s0, s01057; CHECK-NEXT: bx lr1058 %val = call half @llvm.experimental.constrained.nearbyint.f16(half %x, metadata !"round.tonearest", metadata !"fpexcept.strict") #01059 ret half %val1060}1061 1062define i32 @lrint_f16(half %x) #0 {1063; CHECK-LABEL: lrint_f16:1064; CHECK: .save {r11, lr}1065; CHECK-NEXT: push {r11, lr}1066; CHECK-NEXT: vcvtb.f32.f16 s0, s01067; CHECK-NEXT: bl lrintf1068; CHECK-NEXT: pop {r11, pc}1069 %val = call i32 @llvm.experimental.constrained.lrint.i32.f16(half %x, metadata !"round.tonearest", metadata !"fpexcept.strict") #01070 ret i32 %val1071}1072 1073define i64 @llrint_f16(half %x) #0 {1074; CHECK-LABEL: llrint_f16:1075; CHECK: .save {r11, lr}1076; CHECK-NEXT: push {r11, lr}1077; CHECK-NEXT: vcvtb.f32.f16 s0, s01078; CHECK-NEXT: bl llrintf1079; CHECK-NEXT: pop {r11, pc}1080 %val = call i64 @llvm.experimental.constrained.llrint.i64.f16(half %x, metadata !"round.tonearest", metadata !"fpexcept.strict") #01081 ret i64 %val1082}1083 1084define half @maxnum_f16(half %x, half %y) #0 {1085; CHECK-LABEL: maxnum_f16:1086; CHECK: vmaxnm.f16 s0, s0, s11087; CHECK-NEXT: bx lr1088 %val = call half @llvm.experimental.constrained.maxnum.f16(half %x, half %y, metadata !"fpexcept.strict") #01089 ret half %val1090}1091 1092define half @minnum_f16(half %x, half %y) #0 {1093; CHECK-LABEL: minnum_f16:1094; CHECK: vminnm.f16 s0, s0, s11095; CHECK-NEXT: bx lr1096 %val = call half @llvm.experimental.constrained.minnum.f16(half %x, half %y, metadata !"fpexcept.strict") #01097 ret half %val1098}1099 1100define half @ceil_f16(half %x) #0 {1101; CHECK-LABEL: ceil_f16:1102; CHECK: vrintp.f16 s0, s01103; CHECK-NEXT: bx lr1104 %val = call half @llvm.experimental.constrained.ceil.f16(half %x, metadata !"fpexcept.strict") #01105 ret half %val1106}1107 1108define half @floor_f16(half %x) #0 {1109; CHECK-LABEL: floor_f16:1110; CHECK: vrintm.f16 s0, s01111; CHECK-NEXT: bx lr1112 %val = call half @llvm.experimental.constrained.floor.f16(half %x, metadata !"fpexcept.strict") #01113 ret half %val1114}1115 1116define i32 @lround_f16(half %x) #0 {1117; CHECK-LABEL: lround_f16:1118; CHECK: .save {r11, lr}1119; CHECK-NEXT: push {r11, lr}1120; CHECK-NEXT: vcvtb.f32.f16 s0, s01121; CHECK-NEXT: bl lroundf1122; CHECK-NEXT: pop {r11, pc}1123 %val = call i32 @llvm.experimental.constrained.lround.i32.f16(half %x, metadata !"fpexcept.strict") #01124 ret i32 %val1125}1126 1127define i64 @llround_f16(half %x) #0 {1128; CHECK-LABEL: llround_f16:1129; CHECK: .save {r11, lr}1130; CHECK-NEXT: push {r11, lr}1131; CHECK-NEXT: vcvtb.f32.f16 s0, s01132; CHECK-NEXT: bl llroundf1133; CHECK-NEXT: pop {r11, pc}1134 %val = call i64 @llvm.experimental.constrained.llround.i64.f16(half %x, metadata !"fpexcept.strict") #01135 ret i64 %val1136}1137 1138define half @round_f16(half %x) #0 {1139; CHECK-LABEL: round_f16:1140; CHECK: vrinta.f16 s0, s01141; CHECK-NEXT: bx lr1142 %val = call half @llvm.experimental.constrained.round.f16(half %x, metadata !"fpexcept.strict") #01143 ret half %val1144}1145 1146define half @roundeven_f16(half %x) #0 {1147; CHECK-LABEL: roundeven_f16:1148; CHECK: vrintn.f16 s0, s01149; CHECK-NEXT: bx lr1150 %val = call half @llvm.experimental.constrained.roundeven.f16(half %x, metadata !"fpexcept.strict") #01151 ret half %val1152}1153 1154define half @trunc_f16(half %x) #0 {1155; CHECK-LABEL: trunc_f16:1156; CHECK: vrintz.f16 s0, s01157; CHECK-NEXT: bx lr1158 %val = call half @llvm.experimental.constrained.trunc.f16(half %x, metadata !"fpexcept.strict") #01159 ret half %val1160}1161 1162define half @ldexp_f16(half %x, i32 %y) #0 {1163; CHECK-LABEL: ldexp_f16:1164; CHECK: .save {r11, lr}1165; CHECK-NEXT: push {r11, lr}1166; CHECK-NEXT: vcvtb.f32.f16 s0, s01167; CHECK-NEXT: bl ldexpf1168; CHECK-NEXT: vcvtb.f16.f32 s0, s01169; CHECK-NEXT: pop {r11, pc}1170 %val = call half @llvm.experimental.constrained.ldexp.f16.i32(half %x, i32 %y, metadata !"round.tonearest", metadata !"fpexcept.strict") #01171 ret half %val1172}1173 1174define i32 @fcmp_olt_f16(half %a, half %b) #0 {1175; CHECK-LABEL: fcmp_olt_f16:1176; CHECK: vcmp.f16 s0, s11177; CHECK-NEXT: mov r0, #01178; CHECK-NEXT: vmrs APSR_nzcv, fpscr1179; CHECK-NEXT: movwmi r0, #11180; CHECK-NEXT: bx lr1181 %cmp = call i1 @llvm.experimental.constrained.fcmp.f16(half %a, half %b, metadata !"olt", metadata !"fpexcept.strict") #01182 %conv = zext i1 %cmp to i321183 ret i32 %conv1184}1185 1186define i32 @fcmp_ole_f16(half %a, half %b) #0 {1187; CHECK-LABEL: fcmp_ole_f16:1188; CHECK: vcmp.f16 s0, s11189; CHECK-NEXT: mov r0, #01190; CHECK-NEXT: vmrs APSR_nzcv, fpscr1191; CHECK-NEXT: movwls r0, #11192; CHECK-NEXT: bx lr1193 %cmp = call i1 @llvm.experimental.constrained.fcmp.f16(half %a, half %b, metadata !"ole", metadata !"fpexcept.strict") #01194 %conv = zext i1 %cmp to i321195 ret i32 %conv1196}1197 1198define i32 @fcmp_ogt_f16(half %a, half %b) #0 {1199; CHECK-LABEL: fcmp_ogt_f16:1200; CHECK: vcmp.f16 s0, s11201; CHECK-NEXT: mov r0, #01202; CHECK-NEXT: vmrs APSR_nzcv, fpscr1203; CHECK-NEXT: movwgt r0, #11204; CHECK-NEXT: bx lr1205 %cmp = call i1 @llvm.experimental.constrained.fcmp.f16(half %a, half %b, metadata !"ogt", metadata !"fpexcept.strict") #01206 %conv = zext i1 %cmp to i321207 ret i32 %conv1208}1209 1210define i32 @fcmp_oge_f16(half %a, half %b) #0 {1211; CHECK-LABEL: fcmp_oge_f16:1212; CHECK: vcmp.f16 s0, s11213; CHECK-NEXT: mov r0, #01214; CHECK-NEXT: vmrs APSR_nzcv, fpscr1215; CHECK-NEXT: movwge r0, #11216; CHECK-NEXT: bx lr1217 %cmp = call i1 @llvm.experimental.constrained.fcmp.f16(half %a, half %b, metadata !"oge", metadata !"fpexcept.strict") #01218 %conv = zext i1 %cmp to i321219 ret i32 %conv1220}1221 1222define i32 @fcmp_oeq_f16(half %a, half %b) #0 {1223; CHECK-LABEL: fcmp_oeq_f16:1224; CHECK: vcmp.f16 s0, s11225; CHECK-NEXT: mov r0, #01226; CHECK-NEXT: vmrs APSR_nzcv, fpscr1227; CHECK-NEXT: movweq r0, #11228; CHECK-NEXT: bx lr1229 %cmp = call i1 @llvm.experimental.constrained.fcmp.f16(half %a, half %b, metadata !"oeq", metadata !"fpexcept.strict") #01230 %conv = zext i1 %cmp to i321231 ret i32 %conv1232}1233 1234define i32 @fcmp_one_f16(half %a, half %b) #0 {1235; CHECK-LABEL: fcmp_one_f16:1236; CHECK: vcmp.f16 s0, s11237; CHECK-NEXT: mov r0, #01238; CHECK-NEXT: vmrs APSR_nzcv, fpscr1239; CHECK-NEXT: movwmi r0, #11240; CHECK-NEXT: movwgt r0, #11241; CHECK-NEXT: bx lr1242 %cmp = call i1 @llvm.experimental.constrained.fcmp.f16(half %a, half %b, metadata !"one", metadata !"fpexcept.strict") #01243 %conv = zext i1 %cmp to i321244 ret i32 %conv1245}1246 1247define i32 @fcmp_ult_f16(half %a, half %b) #0 {1248; CHECK-LABEL: fcmp_ult_f16:1249; CHECK: vcmp.f16 s0, s11250; CHECK-NEXT: mov r0, #01251; CHECK-NEXT: vmrs APSR_nzcv, fpscr1252; CHECK-NEXT: movwlt r0, #11253; CHECK-NEXT: bx lr1254 %cmp = call i1 @llvm.experimental.constrained.fcmp.f16(half %a, half %b, metadata !"ult", metadata !"fpexcept.strict") #01255 %conv = zext i1 %cmp to i321256 ret i32 %conv1257}1258 1259define i32 @fcmp_ule_f16(half %a, half %b) #0 {1260; CHECK-LABEL: fcmp_ule_f16:1261; CHECK: vcmp.f16 s0, s11262; CHECK-NEXT: mov r0, #01263; CHECK-NEXT: vmrs APSR_nzcv, fpscr1264; CHECK-NEXT: movwle r0, #11265; CHECK-NEXT: bx lr1266 %cmp = call i1 @llvm.experimental.constrained.fcmp.f16(half %a, half %b, metadata !"ule", metadata !"fpexcept.strict") #01267 %conv = zext i1 %cmp to i321268 ret i32 %conv1269}1270 1271define i32 @fcmp_ugt_f16(half %a, half %b) #0 {1272; CHECK-LABEL: fcmp_ugt_f16:1273; CHECK: vcmp.f16 s0, s11274; CHECK-NEXT: mov r0, #01275; CHECK-NEXT: vmrs APSR_nzcv, fpscr1276; CHECK-NEXT: movwhi r0, #11277; CHECK-NEXT: bx lr1278 %cmp = call i1 @llvm.experimental.constrained.fcmp.f16(half %a, half %b, metadata !"ugt", metadata !"fpexcept.strict") #01279 %conv = zext i1 %cmp to i321280 ret i32 %conv1281}1282 1283define i32 @fcmp_uge_f16(half %a, half %b) #0 {1284; CHECK-LABEL: fcmp_uge_f16:1285; CHECK: vcmp.f16 s0, s11286; CHECK-NEXT: mov r0, #01287; CHECK-NEXT: vmrs APSR_nzcv, fpscr1288; CHECK-NEXT: movwpl r0, #11289; CHECK-NEXT: bx lr1290 %cmp = call i1 @llvm.experimental.constrained.fcmp.f16(half %a, half %b, metadata !"uge", metadata !"fpexcept.strict") #01291 %conv = zext i1 %cmp to i321292 ret i32 %conv1293}1294 1295define i32 @fcmp_ueq_f16(half %a, half %b) #0 {1296; CHECK-LABEL: fcmp_ueq_f16:1297; CHECK: vcmp.f16 s0, s11298; CHECK-NEXT: mov r0, #01299; CHECK-NEXT: vmrs APSR_nzcv, fpscr1300; CHECK-NEXT: movweq r0, #11301; CHECK-NEXT: movwvs r0, #11302; CHECK-NEXT: bx lr1303 %cmp = call i1 @llvm.experimental.constrained.fcmp.f16(half %a, half %b, metadata !"ueq", metadata !"fpexcept.strict") #01304 %conv = zext i1 %cmp to i321305 ret i32 %conv1306}1307 1308define i32 @fcmp_une_f16(half %a, half %b) #0 {1309; CHECK-LABEL: fcmp_une_f16:1310; CHECK: vcmp.f16 s0, s11311; CHECK-NEXT: mov r0, #01312; CHECK-NEXT: vmrs APSR_nzcv, fpscr1313; CHECK-NEXT: movwne r0, #11314; CHECK-NEXT: bx lr1315 %cmp = call i1 @llvm.experimental.constrained.fcmp.f16(half %a, half %b, metadata !"une", metadata !"fpexcept.strict") #01316 %conv = zext i1 %cmp to i321317 ret i32 %conv1318}1319 1320define i32 @fcmps_olt_f16(half %a, half %b) #0 {1321; CHECK-LABEL: fcmps_olt_f16:1322; CHECK: vcmpe.f16 s0, s11323; CHECK-NEXT: mov r0, #01324; CHECK-NEXT: vmrs APSR_nzcv, fpscr1325; CHECK-NEXT: movwmi r0, #11326; CHECK-NEXT: bx lr1327 %cmp = call i1 @llvm.experimental.constrained.fcmps.f16(half %a, half %b, metadata !"olt", metadata !"fpexcept.strict") #01328 %conv = zext i1 %cmp to i321329 ret i32 %conv1330}1331 1332define i32 @fcmps_ole_f16(half %a, half %b) #0 {1333; CHECK-LABEL: fcmps_ole_f16:1334; CHECK: vcmpe.f16 s0, s11335; CHECK-NEXT: mov r0, #01336; CHECK-NEXT: vmrs APSR_nzcv, fpscr1337; CHECK-NEXT: movwls r0, #11338; CHECK-NEXT: bx lr1339 %cmp = call i1 @llvm.experimental.constrained.fcmps.f16(half %a, half %b, metadata !"ole", metadata !"fpexcept.strict") #01340 %conv = zext i1 %cmp to i321341 ret i32 %conv1342}1343 1344define i32 @fcmps_ogt_f16(half %a, half %b) #0 {1345; CHECK-LABEL: fcmps_ogt_f16:1346; CHECK: vcmpe.f16 s0, s11347; CHECK-NEXT: mov r0, #01348; CHECK-NEXT: vmrs APSR_nzcv, fpscr1349; CHECK-NEXT: movwgt r0, #11350; CHECK-NEXT: bx lr1351 %cmp = call i1 @llvm.experimental.constrained.fcmps.f16(half %a, half %b, metadata !"ogt", metadata !"fpexcept.strict") #01352 %conv = zext i1 %cmp to i321353 ret i32 %conv1354}1355 1356define i32 @fcmps_oge_f16(half %a, half %b) #0 {1357; CHECK-LABEL: fcmps_oge_f16:1358; CHECK: vcmpe.f16 s0, s11359; CHECK-NEXT: mov r0, #01360; CHECK-NEXT: vmrs APSR_nzcv, fpscr1361; CHECK-NEXT: movwge r0, #11362; CHECK-NEXT: bx lr1363 %cmp = call i1 @llvm.experimental.constrained.fcmps.f16(half %a, half %b, metadata !"oge", metadata !"fpexcept.strict") #01364 %conv = zext i1 %cmp to i321365 ret i32 %conv1366}1367 1368define i32 @fcmps_oeq_f16(half %a, half %b) #0 {1369; CHECK-LABEL: fcmps_oeq_f16:1370; CHECK: vcmpe.f16 s0, s11371; CHECK-NEXT: mov r0, #01372; CHECK-NEXT: vmrs APSR_nzcv, fpscr1373; CHECK-NEXT: movweq r0, #11374; CHECK-NEXT: bx lr1375 %cmp = call i1 @llvm.experimental.constrained.fcmps.f16(half %a, half %b, metadata !"oeq", metadata !"fpexcept.strict") #01376 %conv = zext i1 %cmp to i321377 ret i32 %conv1378}1379 1380define i32 @fcmps_one_f16(half %a, half %b) #0 {1381; CHECK-LABEL: fcmps_one_f16:1382; CHECK: vcmpe.f16 s0, s11383; CHECK-NEXT: mov r0, #01384; CHECK-NEXT: vmrs APSR_nzcv, fpscr1385; CHECK-NEXT: movwmi r0, #11386; CHECK-NEXT: movwgt r0, #11387; CHECK-NEXT: bx lr1388 %cmp = call i1 @llvm.experimental.constrained.fcmps.f16(half %a, half %b, metadata !"one", metadata !"fpexcept.strict") #01389 %conv = zext i1 %cmp to i321390 ret i32 %conv1391}1392 1393define i32 @fcmps_ult_f16(half %a, half %b) #0 {1394; CHECK-LABEL: fcmps_ult_f16:1395; CHECK: vcmpe.f16 s0, s11396; CHECK-NEXT: mov r0, #01397; CHECK-NEXT: vmrs APSR_nzcv, fpscr1398; CHECK-NEXT: movwlt r0, #11399; CHECK-NEXT: bx lr1400 %cmp = call i1 @llvm.experimental.constrained.fcmps.f16(half %a, half %b, metadata !"ult", metadata !"fpexcept.strict") #01401 %conv = zext i1 %cmp to i321402 ret i32 %conv1403}1404 1405define i32 @fcmps_ule_f16(half %a, half %b) #0 {1406; CHECK-LABEL: fcmps_ule_f16:1407; CHECK: vcmpe.f16 s0, s11408; CHECK-NEXT: mov r0, #01409; CHECK-NEXT: vmrs APSR_nzcv, fpscr1410; CHECK-NEXT: movwle r0, #11411; CHECK-NEXT: bx lr1412 %cmp = call i1 @llvm.experimental.constrained.fcmps.f16(half %a, half %b, metadata !"ule", metadata !"fpexcept.strict") #01413 %conv = zext i1 %cmp to i321414 ret i32 %conv1415}1416 1417define i32 @fcmps_ugt_f16(half %a, half %b) #0 {1418; CHECK-LABEL: fcmps_ugt_f16:1419; CHECK: vcmpe.f16 s0, s11420; CHECK-NEXT: mov r0, #01421; CHECK-NEXT: vmrs APSR_nzcv, fpscr1422; CHECK-NEXT: movwhi r0, #11423; CHECK-NEXT: bx lr1424 %cmp = call i1 @llvm.experimental.constrained.fcmps.f16(half %a, half %b, metadata !"ugt", metadata !"fpexcept.strict") #01425 %conv = zext i1 %cmp to i321426 ret i32 %conv1427}1428 1429define i32 @fcmps_uge_f16(half %a, half %b) #0 {1430; CHECK-LABEL: fcmps_uge_f16:1431; CHECK: vcmpe.f16 s0, s11432; CHECK-NEXT: mov r0, #01433; CHECK-NEXT: vmrs APSR_nzcv, fpscr1434; CHECK-NEXT: movwpl r0, #11435; CHECK-NEXT: bx lr1436 %cmp = call i1 @llvm.experimental.constrained.fcmps.f16(half %a, half %b, metadata !"uge", metadata !"fpexcept.strict") #01437 %conv = zext i1 %cmp to i321438 ret i32 %conv1439}1440 1441define i32 @fcmps_ueq_f16(half %a, half %b) #0 {1442; CHECK-LABEL: fcmps_ueq_f16:1443; CHECK: vcmpe.f16 s0, s11444; CHECK-NEXT: mov r0, #01445; CHECK-NEXT: vmrs APSR_nzcv, fpscr1446; CHECK-NEXT: movweq r0, #11447; CHECK-NEXT: movwvs r0, #11448; CHECK-NEXT: bx lr1449 %cmp = call i1 @llvm.experimental.constrained.fcmps.f16(half %a, half %b, metadata !"ueq", metadata !"fpexcept.strict") #01450 %conv = zext i1 %cmp to i321451 ret i32 %conv1452}1453 1454define i32 @fcmps_une_f16(half %a, half %b) #0 {1455; CHECK-LABEL: fcmps_une_f16:1456; CHECK: vcmpe.f16 s0, s11457; CHECK-NEXT: mov r0, #01458; CHECK-NEXT: vmrs APSR_nzcv, fpscr1459; CHECK-NEXT: movwne r0, #11460; CHECK-NEXT: bx lr1461 %cmp = call i1 @llvm.experimental.constrained.fcmps.f16(half %a, half %b, metadata !"une", metadata !"fpexcept.strict") #01462 %conv = zext i1 %cmp to i321463 ret i32 %conv1464}1465 1466 1467; Intrinsics to convert between floating-point types1468 1469define half @fptrunc_f16_f32(float %x) #0 {1470; CHECK-LABEL: fptrunc_f16_f32:1471; CHECK: vcvtb.f16.f32 s0, s01472; CHECK-NEXT: bx lr1473 %val = call half @llvm.experimental.constrained.fptrunc.f16.f32(float %x, metadata !"round.tonearest", metadata !"fpexcept.strict") #01474 ret half %val1475}1476 1477define float @fpext_f32_f16(half %x) #0 {1478; CHECK-LABEL: fpext_f32_f16:1479; CHECK: vcvtb.f32.f16 s0, s01480; CHECK-NEXT: bx lr1481 %val = call float @llvm.experimental.constrained.fpext.f32.f16(half %x, metadata !"fpexcept.strict") #01482 ret float %val1483}1484 1485 1486attributes #0 = { strictfp }1487 1488declare half @llvm.experimental.constrained.fadd.f16(half, half, metadata, metadata)1489declare half @llvm.experimental.constrained.fsub.f16(half, half, metadata, metadata)1490declare half @llvm.experimental.constrained.fmul.f16(half, half, metadata, metadata)1491declare half @llvm.experimental.constrained.fdiv.f16(half, half, metadata, metadata)1492declare half @llvm.experimental.constrained.frem.f16(half, half, metadata, metadata)1493declare half @llvm.experimental.constrained.fma.f16(half, half, half, metadata, metadata)1494declare half @llvm.experimental.constrained.fmuladd.f16(half, half, half, metadata, metadata)1495declare i32 @llvm.experimental.constrained.fptosi.i32.f16(half, metadata)1496declare i32 @llvm.experimental.constrained.fptoui.i32.f16(half, metadata)1497declare i64 @llvm.experimental.constrained.fptosi.i64.f16(half, metadata)1498declare i64 @llvm.experimental.constrained.fptoui.i64.f16(half, metadata)1499declare half @llvm.experimental.constrained.sitofp.f16.i32(i32, metadata, metadata)1500declare half @llvm.experimental.constrained.uitofp.f16.i32(i32, metadata, metadata)1501declare half @llvm.experimental.constrained.sitofp.f16.i64(i64, metadata, metadata)1502declare half @llvm.experimental.constrained.uitofp.f16.i64(i64, metadata, metadata)1503declare half @llvm.experimental.constrained.sitofp.f16.i128(i128, metadata, metadata)1504declare half @llvm.experimental.constrained.uitofp.f16.i128(i128, metadata, metadata)1505declare half @llvm.experimental.constrained.sqrt.f16(half, metadata, metadata)1506declare half @llvm.experimental.constrained.powi.f16(half, i32, metadata, metadata)1507declare half @llvm.experimental.constrained.sin.f16(half, metadata, metadata)1508declare half @llvm.experimental.constrained.cos.f16(half, metadata, metadata)1509declare half @llvm.experimental.constrained.tan.f16(half, metadata, metadata)1510declare half @llvm.experimental.constrained.pow.f16(half, half, metadata, metadata)1511declare half @llvm.experimental.constrained.log.f16(half, metadata, metadata)1512declare half @llvm.experimental.constrained.log10.f16(half, metadata, metadata)1513declare half @llvm.experimental.constrained.log2.f16(half, metadata, metadata)1514declare half @llvm.experimental.constrained.exp.f16(half, metadata, metadata)1515declare half @llvm.experimental.constrained.exp2.f16(half, metadata, metadata)1516declare half @llvm.experimental.constrained.rint.f16(half, metadata, metadata)1517declare half @llvm.experimental.constrained.nearbyint.f16(half, metadata, metadata)1518declare i32 @llvm.experimental.constrained.lrint.i32.f16(half, metadata, metadata)1519declare i64 @llvm.experimental.constrained.llrint.i64.f16(half, metadata, metadata)1520declare half @llvm.experimental.constrained.maxnum.f16(half, half, metadata)1521declare half @llvm.experimental.constrained.minnum.f16(half, half, metadata)1522declare half @llvm.experimental.constrained.ceil.f16(half, metadata)1523declare half @llvm.experimental.constrained.floor.f16(half, metadata)1524declare i32 @llvm.experimental.constrained.lround.i32.f16(half, metadata)1525declare i64 @llvm.experimental.constrained.llround.i64.f16(half, metadata)1526declare half @llvm.experimental.constrained.round.f16(half, metadata)1527declare half @llvm.experimental.constrained.roundeven.f16(half, metadata)1528declare half @llvm.experimental.constrained.trunc.f16(half, metadata)1529declare i1 @llvm.experimental.constrained.fcmps.f16(half, half, metadata, metadata)1530declare i1 @llvm.experimental.constrained.fcmp.f16(half, half, metadata, metadata)1531 1532declare half @llvm.experimental.constrained.fptrunc.f16.f32(float, metadata, metadata)1533declare float @llvm.experimental.constrained.fpext.f32.f16(half, metadata)1534 1535 1536declare half @llvm.sqrt.f16(half %a)1537declare half @llvm.powi.f16.i32(half %a, i32 %b)1538declare half @llvm.sin.f16(half %a)1539declare half @llvm.cos.f16(half %a)1540declare half @llvm.tan.f16(half %a)1541declare half @llvm.pow.f16(half %a, half %b)1542declare half @llvm.exp.f16(half %a)1543declare half @llvm.exp2.f16(half %a)1544declare half @llvm.log.f16(half %a)1545declare half @llvm.log10.f16(half %a)1546declare half @llvm.log2.f16(half %a)1547declare half @llvm.fma.f16(half %a, half %b, half %c)1548declare half @llvm.fabs.f16(half %a)1549declare half @llvm.minnum.f16(half %a, half %b)1550declare half @llvm.maxnum.f16(half %a, half %b)1551declare half @llvm.copysign.f16(half %a, half %b)1552declare half @llvm.floor.f16(half %a)1553declare half @llvm.ceil.f16(half %a)1554declare half @llvm.trunc.f16(half %a)1555declare half @llvm.rint.f16(half %a)1556declare half @llvm.nearbyint.f16(half %a)1557declare half @llvm.round.f16(half %a)1558declare half @llvm.roundeven.f16(half %a)1559declare half @llvm.fmuladd.f16(half %a, half %b, half %c)1560