215 lines · plain
1; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 52; RUN: llc -mattr=+sve < %s | FileCheck %s --check-prefixes=CHECK,NOBF163; RUN: llc -mattr=+sve --enable-no-nans-fp-math < %s | FileCheck %s --check-prefixes=CHECK,NOBF16NNAN4; RUN: llc -mattr=+sve,+bf16 < %s | FileCheck %s --check-prefixes=CHECK,BF165; RUN: llc -mattr=+sme -force-streaming < %s | FileCheck %s --check-prefixes=CHECK,BF166 7target triple = "aarch64-unknown-linux-gnu"8 9; NOTE: "fptrunc <# x double> to <# x bfloat>" is not supported because SVE10; lacks a down convert that rounds to odd. Such IR will trigger the usual11; failure (crash) when attempting to unroll a scalable vector.12 13define <vscale x 2 x float> @fpext_nxv2bf16_to_nxv2f32(<vscale x 2 x bfloat> %a) {14; CHECK-LABEL: fpext_nxv2bf16_to_nxv2f32:15; CHECK: // %bb.0:16; CHECK-NEXT: lsl z0.s, z0.s, #1617; CHECK-NEXT: ret18 %res = fpext <vscale x 2 x bfloat> %a to <vscale x 2 x float>19 ret <vscale x 2 x float> %res20}21 22define <vscale x 4 x float> @fpext_nxv4bf16_to_nxv4f32(<vscale x 4 x bfloat> %a) {23; CHECK-LABEL: fpext_nxv4bf16_to_nxv4f32:24; CHECK: // %bb.0:25; CHECK-NEXT: lsl z0.s, z0.s, #1626; CHECK-NEXT: ret27 %res = fpext <vscale x 4 x bfloat> %a to <vscale x 4 x float>28 ret <vscale x 4 x float> %res29}30 31define <vscale x 8 x float> @fpext_nxv8bf16_to_nxv8f32(<vscale x 8 x bfloat> %a) {32; CHECK-LABEL: fpext_nxv8bf16_to_nxv8f32:33; CHECK: // %bb.0:34; CHECK-NEXT: uunpklo z1.s, z0.h35; CHECK-NEXT: uunpkhi z2.s, z0.h36; CHECK-NEXT: lsl z0.s, z1.s, #1637; CHECK-NEXT: lsl z1.s, z2.s, #1638; CHECK-NEXT: ret39 %res = fpext <vscale x 8 x bfloat> %a to <vscale x 8 x float>40 ret <vscale x 8 x float> %res41}42 43define <vscale x 2 x double> @fpext_nxv2bf16_to_nxv2f64(<vscale x 2 x bfloat> %a) {44; CHECK-LABEL: fpext_nxv2bf16_to_nxv2f64:45; CHECK: // %bb.0:46; CHECK-NEXT: lsl z0.s, z0.s, #1647; CHECK-NEXT: ptrue p0.d48; CHECK-NEXT: fcvt z0.d, p0/m, z0.s49; CHECK-NEXT: ret50 %res = fpext <vscale x 2 x bfloat> %a to <vscale x 2 x double>51 ret <vscale x 2 x double> %res52}53 54define <vscale x 4 x double> @fpext_nxv4bf16_to_nxv4f64(<vscale x 4 x bfloat> %a) {55; CHECK-LABEL: fpext_nxv4bf16_to_nxv4f64:56; CHECK: // %bb.0:57; CHECK-NEXT: uunpklo z1.d, z0.s58; CHECK-NEXT: uunpkhi z0.d, z0.s59; CHECK-NEXT: ptrue p0.d60; CHECK-NEXT: lsl z1.s, z1.s, #1661; CHECK-NEXT: lsl z2.s, z0.s, #1662; CHECK-NEXT: movprfx z0, z163; CHECK-NEXT: fcvt z0.d, p0/m, z1.s64; CHECK-NEXT: movprfx z1, z265; CHECK-NEXT: fcvt z1.d, p0/m, z2.s66; CHECK-NEXT: ret67 %res = fpext <vscale x 4 x bfloat> %a to <vscale x 4 x double>68 ret <vscale x 4 x double> %res69}70 71define <vscale x 8 x double> @fpext_nxv8bf16_to_nxv8f64(<vscale x 8 x bfloat> %a) {72; CHECK-LABEL: fpext_nxv8bf16_to_nxv8f64:73; CHECK: // %bb.0:74; CHECK-NEXT: uunpklo z1.s, z0.h75; CHECK-NEXT: uunpkhi z0.s, z0.h76; CHECK-NEXT: ptrue p0.d77; CHECK-NEXT: uunpklo z2.d, z1.s78; CHECK-NEXT: uunpkhi z1.d, z1.s79; CHECK-NEXT: uunpklo z3.d, z0.s80; CHECK-NEXT: uunpkhi z0.d, z0.s81; CHECK-NEXT: lsl z1.s, z1.s, #1682; CHECK-NEXT: lsl z2.s, z2.s, #1683; CHECK-NEXT: lsl z3.s, z3.s, #1684; CHECK-NEXT: lsl z4.s, z0.s, #1685; CHECK-NEXT: fcvt z1.d, p0/m, z1.s86; CHECK-NEXT: movprfx z0, z287; CHECK-NEXT: fcvt z0.d, p0/m, z2.s88; CHECK-NEXT: movprfx z2, z389; CHECK-NEXT: fcvt z2.d, p0/m, z3.s90; CHECK-NEXT: movprfx z3, z491; CHECK-NEXT: fcvt z3.d, p0/m, z4.s92; CHECK-NEXT: ret93 %res = fpext <vscale x 8 x bfloat> %a to <vscale x 8 x double>94 ret <vscale x 8 x double> %res95}96 97define <vscale x 2 x bfloat> @fptrunc_nxv2f32_to_nxv2bf16(<vscale x 2 x float> %a) {98; NOBF16-LABEL: fptrunc_nxv2f32_to_nxv2bf16:99; NOBF16: // %bb.0:100; NOBF16-NEXT: mov z1.s, #32767 // =0x7fff101; NOBF16-NEXT: lsr z2.s, z0.s, #16102; NOBF16-NEXT: ptrue p0.d103; NOBF16-NEXT: fcmuo p0.s, p0/z, z0.s, z0.s104; NOBF16-NEXT: and z2.s, z2.s, #0x1105; NOBF16-NEXT: add z1.s, z0.s, z1.s106; NOBF16-NEXT: orr z0.s, z0.s, #0x400000107; NOBF16-NEXT: add z1.s, z2.s, z1.s108; NOBF16-NEXT: sel z0.s, p0, z0.s, z1.s109; NOBF16-NEXT: lsr z0.s, z0.s, #16110; NOBF16-NEXT: ret111;112; NOBF16NNAN-LABEL: fptrunc_nxv2f32_to_nxv2bf16:113; NOBF16NNAN: // %bb.0:114; NOBF16NNAN-NEXT: mov z1.s, #32767 // =0x7fff115; NOBF16NNAN-NEXT: lsr z2.s, z0.s, #16116; NOBF16NNAN-NEXT: and z2.s, z2.s, #0x1117; NOBF16NNAN-NEXT: add z0.s, z0.s, z1.s118; NOBF16NNAN-NEXT: add z0.s, z2.s, z0.s119; NOBF16NNAN-NEXT: lsr z0.s, z0.s, #16120; NOBF16NNAN-NEXT: ret121;122; BF16-LABEL: fptrunc_nxv2f32_to_nxv2bf16:123; BF16: // %bb.0:124; BF16-NEXT: ptrue p0.d125; BF16-NEXT: bfcvt z0.h, p0/m, z0.s126; BF16-NEXT: ret127 %res = fptrunc <vscale x 2 x float> %a to <vscale x 2 x bfloat>128 ret <vscale x 2 x bfloat> %res129}130 131define <vscale x 4 x bfloat> @fptrunc_nxv4f32_to_nxv4bf16(<vscale x 4 x float> %a) {132; NOBF16-LABEL: fptrunc_nxv4f32_to_nxv4bf16:133; NOBF16: // %bb.0:134; NOBF16-NEXT: mov z1.s, #32767 // =0x7fff135; NOBF16-NEXT: lsr z2.s, z0.s, #16136; NOBF16-NEXT: ptrue p0.s137; NOBF16-NEXT: fcmuo p0.s, p0/z, z0.s, z0.s138; NOBF16-NEXT: and z2.s, z2.s, #0x1139; NOBF16-NEXT: add z1.s, z0.s, z1.s140; NOBF16-NEXT: orr z0.s, z0.s, #0x400000141; NOBF16-NEXT: add z1.s, z2.s, z1.s142; NOBF16-NEXT: sel z0.s, p0, z0.s, z1.s143; NOBF16-NEXT: lsr z0.s, z0.s, #16144; NOBF16-NEXT: ret145;146; NOBF16NNAN-LABEL: fptrunc_nxv4f32_to_nxv4bf16:147; NOBF16NNAN: // %bb.0:148; NOBF16NNAN-NEXT: mov z1.s, #32767 // =0x7fff149; NOBF16NNAN-NEXT: lsr z2.s, z0.s, #16150; NOBF16NNAN-NEXT: and z2.s, z2.s, #0x1151; NOBF16NNAN-NEXT: add z0.s, z0.s, z1.s152; NOBF16NNAN-NEXT: add z0.s, z2.s, z0.s153; NOBF16NNAN-NEXT: lsr z0.s, z0.s, #16154; NOBF16NNAN-NEXT: ret155;156; BF16-LABEL: fptrunc_nxv4f32_to_nxv4bf16:157; BF16: // %bb.0:158; BF16-NEXT: ptrue p0.s159; BF16-NEXT: bfcvt z0.h, p0/m, z0.s160; BF16-NEXT: ret161 %res = fptrunc <vscale x 4 x float> %a to <vscale x 4 x bfloat>162 ret <vscale x 4 x bfloat> %res163}164 165define <vscale x 8 x bfloat> @fptrunc_nxv8f32_to_nxv8bf16(<vscale x 8 x float> %a) {166; NOBF16-LABEL: fptrunc_nxv8f32_to_nxv8bf16:167; NOBF16: // %bb.0:168; NOBF16-NEXT: mov z2.s, #32767 // =0x7fff169; NOBF16-NEXT: lsr z3.s, z1.s, #16170; NOBF16-NEXT: lsr z4.s, z0.s, #16171; NOBF16-NEXT: ptrue p0.s172; NOBF16-NEXT: and z3.s, z3.s, #0x1173; NOBF16-NEXT: and z4.s, z4.s, #0x1174; NOBF16-NEXT: add z5.s, z1.s, z2.s175; NOBF16-NEXT: add z2.s, z0.s, z2.s176; NOBF16-NEXT: fcmuo p1.s, p0/z, z1.s, z1.s177; NOBF16-NEXT: orr z1.s, z1.s, #0x400000178; NOBF16-NEXT: fcmuo p0.s, p0/z, z0.s, z0.s179; NOBF16-NEXT: orr z0.s, z0.s, #0x400000180; NOBF16-NEXT: add z3.s, z3.s, z5.s181; NOBF16-NEXT: add z2.s, z4.s, z2.s182; NOBF16-NEXT: sel z1.s, p1, z1.s, z3.s183; NOBF16-NEXT: sel z0.s, p0, z0.s, z2.s184; NOBF16-NEXT: lsr z1.s, z1.s, #16185; NOBF16-NEXT: lsr z0.s, z0.s, #16186; NOBF16-NEXT: uzp1 z0.h, z0.h, z1.h187; NOBF16-NEXT: ret188;189; NOBF16NNAN-LABEL: fptrunc_nxv8f32_to_nxv8bf16:190; NOBF16NNAN: // %bb.0:191; NOBF16NNAN-NEXT: mov z2.s, #32767 // =0x7fff192; NOBF16NNAN-NEXT: lsr z3.s, z1.s, #16193; NOBF16NNAN-NEXT: lsr z4.s, z0.s, #16194; NOBF16NNAN-NEXT: and z3.s, z3.s, #0x1195; NOBF16NNAN-NEXT: and z4.s, z4.s, #0x1196; NOBF16NNAN-NEXT: add z1.s, z1.s, z2.s197; NOBF16NNAN-NEXT: add z0.s, z0.s, z2.s198; NOBF16NNAN-NEXT: add z1.s, z3.s, z1.s199; NOBF16NNAN-NEXT: add z0.s, z4.s, z0.s200; NOBF16NNAN-NEXT: lsr z1.s, z1.s, #16201; NOBF16NNAN-NEXT: lsr z0.s, z0.s, #16202; NOBF16NNAN-NEXT: uzp1 z0.h, z0.h, z1.h203; NOBF16NNAN-NEXT: ret204;205; BF16-LABEL: fptrunc_nxv8f32_to_nxv8bf16:206; BF16: // %bb.0:207; BF16-NEXT: ptrue p0.s208; BF16-NEXT: bfcvt z1.h, p0/m, z1.s209; BF16-NEXT: bfcvt z0.h, p0/m, z0.s210; BF16-NEXT: uzp1 z0.h, z0.h, z1.h211; BF16-NEXT: ret212 %res = fptrunc <vscale x 8 x float> %a to <vscale x 8 x bfloat>213 ret <vscale x 8 x bfloat> %res214}215