1; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --filter-out "(\.v?save|push|pop)" 2 3; No FP16/BF16 4; RUN: llc -mtriple=arm-none-eabi -float-abi=soft -mattr=+armv8.2-a,+fp-armv8,-fullfp16,-bf16,-neon %s -o - | FileCheck %s --check-prefixes=NO-FP16-SOFT 5; RUN: llc -mtriple=thumb-none-eabi -float-abi=soft -mattr=+armv8.2-a,+fp-armv8,-fullfp16,-bf16,-neon %s -o - | FileCheck %s --check-prefixes=NO-FP16-SOFT 6; RUN: llc -mtriple=arm-none-eabi -mattr=+armv8.2-a,+fp-armv8,-fullfp16,-bf16,-neon %s -o - | FileCheck %s --check-prefixes=NO-FP16-SOFT 7; RUN: llc -mtriple=thumb-none-eabi -mattr=+armv8.2-a,+fp-armv8,-fullfp16,-bf16,-neon %s -o - | FileCheck %s --check-prefixes=NO-FP16-SOFT 8; RUN: llc -mtriple=arm-none-eabihf -mattr=+armv8.2-a,+fp-armv8,-fullfp16,-bf16,-neon %s -o - | FileCheck %s --check-prefixes=NO-FP16-HARD 9; RUN: llc -mtriple=thumb-none-eabihf -mattr=+armv8.2-a,+fp-armv8,-fullfp16,-bf16,-neon %s -o - | FileCheck %s --check-prefixes=NO-FP16-HARD 10 11; FP16/BF16 12; RUN: llc -mtriple=arm-none-eabi -float-abi=soft -mattr=+armv8.2-a,+fp-armv8,+fullfp16,+bf16,-neon %s -o - | FileCheck %s --check-prefixes=FP16-SOFT 13; RUN: llc -mtriple=thumb-none-eabi -float-abi=soft -mattr=+armv8.2-a,+fp-armv8,+fullfp16,+bf16,-neon %s -o - | FileCheck %s --check-prefixes=FP16-SOFT 14; RUN: llc -mtriple=arm-none-eabi -mattr=+armv8.2-a,+fp-armv8,+fullfp16,+bf16,-neon %s -o - | FileCheck %s --check-prefixes=FP16-SOFT 15; RUN: llc -mtriple=thumb-none-eabi -mattr=+armv8.2-a,+fp-armv8,+fullfp16,+bf16,-neon %s -o - | FileCheck %s --check-prefixes=FP16-SOFT 16; RUN: llc -mtriple=arm-none-eabihf -mattr=+armv8.2-a,+fp-armv8,+fullfp16,+bf16,-neon %s -o - | FileCheck %s --check-prefixes=FP16-HARD 17; RUN: llc -mtriple=thumb-none-eabihf -mattr=+armv8.2-a,+fp-armv8,+fullfp16,+bf16,-neon %s -o - | FileCheck %s --check-prefixes=FP16-HARD 18 19; PR60510 showed a bug where the return from `*_inner` was getting "lost" by an 20; optimisation, and a garbage value was being left in `s0`. 21 22declare dso_local float @other(float) nounwind 23declare dso_local void @fp16_sink(half) nounwind 24declare dso_local void @bf16_sink(bfloat) nounwind 25 26declare dso_local half @fp16_inner() nounwind 27declare dso_local bfloat @bf_inner() nounwind 28 29define half @fp16_out_call_oneuse(float %arg) nounwind { 30; NO-FP16-SOFT-LABEL: fp16_out_call_oneuse: 31; NO-FP16-SOFT: @ %bb.0: 32; NO-FP16-SOFT: mov r4, r0 33; NO-FP16-SOFT: bl fp16_inner 34; NO-FP16-SOFT: mov r5, r0 35; NO-FP16-SOFT: mov r0, r4 36; NO-FP16-SOFT: bl other 37; NO-FP16-SOFT: mov r0, r5 38; 39; NO-FP16-HARD-LABEL: fp16_out_call_oneuse: 40; NO-FP16-HARD: @ %bb.0: 41; NO-FP16-HARD: vmov.f32 s16, s0 42; NO-FP16-HARD: bl fp16_inner 43; NO-FP16-HARD: vmov.f32 s18, s0 44; NO-FP16-HARD: vmov.f32 s0, s16 45; NO-FP16-HARD: bl other 46; NO-FP16-HARD: vmov.f32 s0, s18 47; 48; FP16-SOFT-LABEL: fp16_out_call_oneuse: 49; FP16-SOFT: @ %bb.0: 50; FP16-SOFT: mov r4, r0 51; FP16-SOFT: bl fp16_inner 52; FP16-SOFT: mov r5, r0 53; FP16-SOFT: mov r0, r4 54; FP16-SOFT: bl other 55; FP16-SOFT: vmov.f16 s0, r5 56; FP16-SOFT: vmov r0, s0 57; 58; FP16-HARD-LABEL: fp16_out_call_oneuse: 59; FP16-HARD: @ %bb.0: 60; FP16-HARD: vmov.f32 s16, s0 61; FP16-HARD: bl fp16_inner 62; FP16-HARD: vmov.f32 s18, s0 63; FP16-HARD: vmov.f32 s0, s16 64; FP16-HARD: bl other 65; FP16-HARD: vmov.f32 s0, s18 66 %call = call half @fp16_inner() 67 %call1 = call float @other(float %arg) 68 ret half %call 69} 70 71define half @fp16_out_call_multiuse(float %arg) nounwind { 72; NO-FP16-SOFT-LABEL: fp16_out_call_multiuse: 73; NO-FP16-SOFT: @ %bb.0: 74; NO-FP16-SOFT: mov r4, r0 75; NO-FP16-SOFT: bl fp16_inner 76; NO-FP16-SOFT: mov r5, r0 77; NO-FP16-SOFT: mov r0, r4 78; NO-FP16-SOFT: bl other 79; NO-FP16-SOFT: mov r0, r5 80; NO-FP16-SOFT: bl fp16_sink 81; NO-FP16-SOFT: mov r0, r5 82; 83; NO-FP16-HARD-LABEL: fp16_out_call_multiuse: 84; NO-FP16-HARD: @ %bb.0: 85; NO-FP16-HARD: vmov.f32 s16, s0 86; NO-FP16-HARD: bl fp16_inner 87; NO-FP16-HARD: vmov.f32 s18, s0 88; NO-FP16-HARD: vmov.f32 s0, s16 89; NO-FP16-HARD: bl other 90; NO-FP16-HARD: vmov.f32 s0, s18 91; NO-FP16-HARD: bl fp16_sink 92; NO-FP16-HARD: vmov.f32 s0, s18 93; 94; FP16-SOFT-LABEL: fp16_out_call_multiuse: 95; FP16-SOFT: @ %bb.0: 96; FP16-SOFT: mov r4, r0 97; FP16-SOFT: bl fp16_inner 98; FP16-SOFT: mov r5, r0 99; FP16-SOFT: mov r0, r4 100; FP16-SOFT: bl other 101; FP16-SOFT: vmov.f16 s16, r5 102; FP16-SOFT: vmov.f16 r0, s16 103; FP16-SOFT: bl fp16_sink 104; FP16-SOFT: vmov r0, s16 105; 106; FP16-HARD-LABEL: fp16_out_call_multiuse: 107; FP16-HARD: @ %bb.0: 108; FP16-HARD: vmov.f32 s16, s0 109; FP16-HARD: bl fp16_inner 110; FP16-HARD: vmov.f32 s18, s0 111; FP16-HARD: vmov.f32 s0, s16 112; FP16-HARD: bl other 113; FP16-HARD: vmov.f16 r0, s18 114; FP16-HARD: vmov s0, r0 115; FP16-HARD: bl fp16_sink 116; FP16-HARD: vmov.f32 s0, s18 117 %call = call half @fp16_inner() 118 %call1 = call float @other(float %arg) 119 call void @fp16_sink(half %call) 120 ret half %call 121} 122 123define bfloat @bf_out_call_oneuse(float %arg) nounwind { 124; NO-FP16-SOFT-LABEL: bf_out_call_oneuse: 125; NO-FP16-SOFT: @ %bb.0: 126; NO-FP16-SOFT: mov r4, r0 127; NO-FP16-SOFT: bl bf_inner 128; NO-FP16-SOFT: mov r5, r0 129; NO-FP16-SOFT: mov r0, r4 130; NO-FP16-SOFT: bl other 131; NO-FP16-SOFT: mov r0, r5 132; 133; NO-FP16-HARD-LABEL: bf_out_call_oneuse: 134; NO-FP16-HARD: @ %bb.0: 135; NO-FP16-HARD: vmov.f32 s16, s0 136; NO-FP16-HARD: bl bf_inner 137; NO-FP16-HARD: vmov.f32 s18, s0 138; NO-FP16-HARD: vmov.f32 s0, s16 139; NO-FP16-HARD: bl other 140; NO-FP16-HARD: vmov.f32 s0, s18 141; 142; FP16-SOFT-LABEL: bf_out_call_oneuse: 143; FP16-SOFT: @ %bb.0: 144; FP16-SOFT: mov r4, r0 145; FP16-SOFT: bl bf_inner 146; FP16-SOFT: mov r5, r0 147; FP16-SOFT: mov r0, r4 148; FP16-SOFT: bl other 149; FP16-SOFT: mov r0, r5 150; 151; FP16-HARD-LABEL: bf_out_call_oneuse: 152; FP16-HARD: @ %bb.0: 153; FP16-HARD: vmov.f32 s16, s0 154; FP16-HARD: bl bf_inner 155; FP16-HARD: vmov.f32 s18, s0 156; FP16-HARD: vmov.f32 s0, s16 157; FP16-HARD: bl other 158; FP16-HARD: vmov.f32 s0, s18 159 %call = call bfloat @bf_inner() 160 %call1 = call float @other(float %arg) 161 ret bfloat %call 162} 163 164define bfloat @bf_out_call_multiuse(float %arg) nounwind { 165; NO-FP16-SOFT-LABEL: bf_out_call_multiuse: 166; NO-FP16-SOFT: @ %bb.0: 167; NO-FP16-SOFT: mov r4, r0 168; NO-FP16-SOFT: bl bf_inner 169; NO-FP16-SOFT: mov r5, r0 170; NO-FP16-SOFT: mov r0, r4 171; NO-FP16-SOFT: bl other 172; NO-FP16-SOFT: mov r0, r5 173; NO-FP16-SOFT: bl bf16_sink 174; NO-FP16-SOFT: mov r0, r5 175; 176; NO-FP16-HARD-LABEL: bf_out_call_multiuse: 177; NO-FP16-HARD: @ %bb.0: 178; NO-FP16-HARD: vmov.f32 s16, s0 179; NO-FP16-HARD: bl bf_inner 180; NO-FP16-HARD: vmov.f32 s18, s0 181; NO-FP16-HARD: vmov.f32 s0, s16 182; NO-FP16-HARD: bl other 183; NO-FP16-HARD: vmov.f32 s0, s18 184; NO-FP16-HARD: bl bf16_sink 185; NO-FP16-HARD: vmov.f32 s0, s18 186; 187; FP16-SOFT-LABEL: bf_out_call_multiuse: 188; FP16-SOFT: @ %bb.0: 189; FP16-SOFT: mov r4, r0 190; FP16-SOFT: bl bf_inner 191; FP16-SOFT: mov r5, r0 192; FP16-SOFT: mov r0, r4 193; FP16-SOFT: bl other 194; FP16-SOFT: mov r0, r5 195; FP16-SOFT: bl bf16_sink 196; FP16-SOFT: mov r0, r5 197; 198; FP16-HARD-LABEL: bf_out_call_multiuse: 199; FP16-HARD: @ %bb.0: 200; FP16-HARD: vmov.f32 s16, s0 201; FP16-HARD: bl bf_inner 202; FP16-HARD: vmov.f32 s18, s0 203; FP16-HARD: vmov.f32 s0, s16 204; FP16-HARD: bl other 205; FP16-HARD: vmov.f32 s0, s18 206; FP16-HARD: bl bf16_sink 207; FP16-HARD: vmov.f32 s0, s18 208 %call = call bfloat @bf_inner() 209 %call1 = call float @other(float %arg) 210 call void @bf16_sink(bfloat %call) 211 ret bfloat %call 212} 213