307 lines · plain
1; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 42; RUN: llc -mtriple=aarch64 -mattr=+sve < %s -o - | FileCheck --check-prefixes=CHECK,SVE %s3; RUN: llc -mtriple=aarch64 -mattr=+sve2 < %s -o - | FileCheck --check-prefixes=CHECK,SVE2 %s4 5define <vscale x 2 x i64> @xar_nxv2i64_l(<vscale x 2 x i64> %x, <vscale x 2 x i64> %y) {6; SVE-LABEL: xar_nxv2i64_l:7; SVE: // %bb.0:8; SVE-NEXT: eor z0.d, z0.d, z1.d9; SVE-NEXT: lsr z1.d, z0.d, #410; SVE-NEXT: lsl z0.d, z0.d, #6011; SVE-NEXT: orr z0.d, z0.d, z1.d12; SVE-NEXT: ret13;14; SVE2-LABEL: xar_nxv2i64_l:15; SVE2: // %bb.0:16; SVE2-NEXT: xar z0.d, z0.d, z1.d, #417; SVE2-NEXT: ret18 %a = xor <vscale x 2 x i64> %x, %y19 %b = call <vscale x 2 x i64> @llvm.fshl.nxv2i64(<vscale x 2 x i64> %a, <vscale x 2 x i64> %a, <vscale x 2 x i64> splat (i64 60))20 ret <vscale x 2 x i64> %b21}22 23define <vscale x 2 x i64> @xar_nxv2i64_r(<vscale x 2 x i64> %x, <vscale x 2 x i64> %y) {24; SVE-LABEL: xar_nxv2i64_r:25; SVE: // %bb.0:26; SVE-NEXT: eor z0.d, z0.d, z1.d27; SVE-NEXT: lsl z1.d, z0.d, #6028; SVE-NEXT: lsr z0.d, z0.d, #429; SVE-NEXT: orr z0.d, z0.d, z1.d30; SVE-NEXT: ret31;32; SVE2-LABEL: xar_nxv2i64_r:33; SVE2: // %bb.0:34; SVE2-NEXT: xar z0.d, z0.d, z1.d, #435; SVE2-NEXT: ret36 %a = xor <vscale x 2 x i64> %x, %y37 %b = call <vscale x 2 x i64> @llvm.fshr.nxv2i64(<vscale x 2 x i64> %a, <vscale x 2 x i64> %a, <vscale x 2 x i64> splat (i64 4))38 ret <vscale x 2 x i64> %b39}40 41 42define <vscale x 4 x i32> @xar_nxv4i32_l(<vscale x 4 x i32> %x, <vscale x 4 x i32> %y) {43; SVE-LABEL: xar_nxv4i32_l:44; SVE: // %bb.0:45; SVE-NEXT: eor z0.d, z0.d, z1.d46; SVE-NEXT: lsr z1.s, z0.s, #447; SVE-NEXT: lsl z0.s, z0.s, #2848; SVE-NEXT: orr z0.d, z0.d, z1.d49; SVE-NEXT: ret50;51; SVE2-LABEL: xar_nxv4i32_l:52; SVE2: // %bb.0:53; SVE2-NEXT: xar z0.s, z0.s, z1.s, #454; SVE2-NEXT: ret55 %a = xor <vscale x 4 x i32> %x, %y56 %b = call <vscale x 4 x i32> @llvm.fshl.nxv4i32(<vscale x 4 x i32> %a, <vscale x 4 x i32> %a, <vscale x 4 x i32> splat (i32 28))57 ret <vscale x 4 x i32> %b58}59 60define <vscale x 4 x i32> @xar_nxv4i32_r(<vscale x 4 x i32> %x, <vscale x 4 x i32> %y) {61; SVE-LABEL: xar_nxv4i32_r:62; SVE: // %bb.0:63; SVE-NEXT: eor z0.d, z0.d, z1.d64; SVE-NEXT: lsl z1.s, z0.s, #2865; SVE-NEXT: lsr z0.s, z0.s, #466; SVE-NEXT: orr z0.d, z0.d, z1.d67; SVE-NEXT: ret68;69; SVE2-LABEL: xar_nxv4i32_r:70; SVE2: // %bb.0:71; SVE2-NEXT: xar z0.s, z0.s, z1.s, #472; SVE2-NEXT: ret73 %a = xor <vscale x 4 x i32> %x, %y74 %b = call <vscale x 4 x i32> @llvm.fshr.nxv4i32(<vscale x 4 x i32> %a, <vscale x 4 x i32> %a, <vscale x 4 x i32> splat (i32 4))75 ret <vscale x 4 x i32> %b76}77 78define <vscale x 8 x i16> @xar_nxv8i16_l(<vscale x 8 x i16> %x, <vscale x 8 x i16> %y) {79; SVE-LABEL: xar_nxv8i16_l:80; SVE: // %bb.0:81; SVE-NEXT: eor z0.d, z0.d, z1.d82; SVE-NEXT: lsr z1.h, z0.h, #483; SVE-NEXT: lsl z0.h, z0.h, #1284; SVE-NEXT: orr z0.d, z0.d, z1.d85; SVE-NEXT: ret86;87; SVE2-LABEL: xar_nxv8i16_l:88; SVE2: // %bb.0:89; SVE2-NEXT: xar z0.h, z0.h, z1.h, #490; SVE2-NEXT: ret91 %a = xor <vscale x 8 x i16> %x, %y92 %b = call <vscale x 8 x i16> @llvm.fshl.nxv8i16(<vscale x 8 x i16> %a, <vscale x 8 x i16> %a, <vscale x 8 x i16> splat (i16 12))93 ret <vscale x 8 x i16> %b94}95 96define <vscale x 8 x i16> @xar_nxv8i16_r(<vscale x 8 x i16> %x, <vscale x 8 x i16> %y) {97; SVE-LABEL: xar_nxv8i16_r:98; SVE: // %bb.0:99; SVE-NEXT: eor z0.d, z0.d, z1.d100; SVE-NEXT: lsl z1.h, z0.h, #12101; SVE-NEXT: lsr z0.h, z0.h, #4102; SVE-NEXT: orr z0.d, z0.d, z1.d103; SVE-NEXT: ret104;105; SVE2-LABEL: xar_nxv8i16_r:106; SVE2: // %bb.0:107; SVE2-NEXT: xar z0.h, z0.h, z1.h, #4108; SVE2-NEXT: ret109 %a = xor <vscale x 8 x i16> %x, %y110 %b = call <vscale x 8 x i16> @llvm.fshr.nxv8i16(<vscale x 8 x i16> %a, <vscale x 8 x i16> %a, <vscale x 8 x i16> splat (i16 4))111 ret <vscale x 8 x i16> %b112}113 114define <vscale x 16 x i8> @xar_nxv16i8_l(<vscale x 16 x i8> %x, <vscale x 16 x i8> %y) {115; SVE-LABEL: xar_nxv16i8_l:116; SVE: // %bb.0:117; SVE-NEXT: eor z0.d, z0.d, z1.d118; SVE-NEXT: lsr z1.b, z0.b, #4119; SVE-NEXT: lsl z0.b, z0.b, #4120; SVE-NEXT: orr z0.d, z0.d, z1.d121; SVE-NEXT: ret122;123; SVE2-LABEL: xar_nxv16i8_l:124; SVE2: // %bb.0:125; SVE2-NEXT: xar z0.b, z0.b, z1.b, #4126; SVE2-NEXT: ret127 %a = xor <vscale x 16 x i8> %x, %y128 %b = call <vscale x 16 x i8> @llvm.fshl.nxv16i8(<vscale x 16 x i8> %a, <vscale x 16 x i8> %a, <vscale x 16 x i8> splat (i8 4))129 ret <vscale x 16 x i8> %b130}131 132define <vscale x 16 x i8> @xar_nxv16i8_r(<vscale x 16 x i8> %x, <vscale x 16 x i8> %y) {133; SVE-LABEL: xar_nxv16i8_r:134; SVE: // %bb.0:135; SVE-NEXT: eor z0.d, z0.d, z1.d136; SVE-NEXT: lsl z1.b, z0.b, #4137; SVE-NEXT: lsr z0.b, z0.b, #4138; SVE-NEXT: orr z0.d, z0.d, z1.d139; SVE-NEXT: ret140;141; SVE2-LABEL: xar_nxv16i8_r:142; SVE2: // %bb.0:143; SVE2-NEXT: xar z0.b, z0.b, z1.b, #4144; SVE2-NEXT: ret145 %a = xor <vscale x 16 x i8> %x, %y146 %b = call <vscale x 16 x i8> @llvm.fshr.nxv16i8(<vscale x 16 x i8> %a, <vscale x 16 x i8> %a, <vscale x 16 x i8> splat (i8 4))147 ret <vscale x 16 x i8> %b148}149 150; Shift is not a constant.151define <vscale x 2 x i64> @xar_nxv2i64_l_neg1(<vscale x 2 x i64> %x, <vscale x 2 x i64> %y, <vscale x 2 x i64> %z) {152; CHECK-LABEL: xar_nxv2i64_l_neg1:153; CHECK: // %bb.0:154; CHECK-NEXT: mov z3.d, z2.d155; CHECK-NEXT: subr z2.d, z2.d, #0 // =0x0156; CHECK-NEXT: eor z0.d, z0.d, z1.d157; CHECK-NEXT: ptrue p0.d158; CHECK-NEXT: and z3.d, z3.d, #0x3f159; CHECK-NEXT: and z2.d, z2.d, #0x3f160; CHECK-NEXT: lslr z3.d, p0/m, z3.d, z0.d161; CHECK-NEXT: lsr z0.d, p0/m, z0.d, z2.d162; CHECK-NEXT: orr z0.d, z3.d, z0.d163; CHECK-NEXT: ret164 %a = xor <vscale x 2 x i64> %x, %y165 %b = call <vscale x 2 x i64> @llvm.fshl.nxv2i64(<vscale x 2 x i64> %a, <vscale x 2 x i64> %a, <vscale x 2 x i64> %z)166 ret <vscale x 2 x i64> %b167}168 169; OR instead of an XOR.170; TODO: We could use usra instruction here for SVE2.171define <vscale x 2 x i64> @xar_nxv2i64_l_neg2_1(<vscale x 2 x i64> %x, <vscale x 2 x i64> %y) {172; SVE-LABEL: xar_nxv2i64_l_neg2_1:173; SVE: // %bb.0:174; SVE-NEXT: orr z0.d, z0.d, z1.d175; SVE-NEXT: lsr z1.d, z0.d, #4176; SVE-NEXT: lsl z0.d, z0.d, #60177; SVE-NEXT: orr z0.d, z0.d, z1.d178; SVE-NEXT: ret179;180; SVE2-LABEL: xar_nxv2i64_l_neg2_1:181; SVE2: // %bb.0:182; SVE2-NEXT: movi v2.2d, #0000000000000000183; SVE2-NEXT: orr z0.d, z0.d, z1.d184; SVE2-NEXT: xar z0.d, z0.d, z2.d, #4185; SVE2-NEXT: ret186 %a = or <vscale x 2 x i64> %x, %y187 %b = call <vscale x 2 x i64> @llvm.fshl.nxv2i64(<vscale x 2 x i64> %a, <vscale x 2 x i64> %a, <vscale x 2 x i64> splat (i64 60))188 ret <vscale x 2 x i64> %b189}190 191define <vscale x 4 x i32> @xar_nxv2i32_l_neg2_2(<vscale x 4 x i32> %x, <vscale x 4 x i32> %y) {192; SVE-LABEL: xar_nxv2i32_l_neg2_2:193; SVE: // %bb.0:194; SVE-NEXT: orr z0.d, z0.d, z1.d195; SVE-NEXT: lsr z1.s, z0.s, #4196; SVE-NEXT: lsl z0.s, z0.s, #28197; SVE-NEXT: orr z0.d, z0.d, z1.d198; SVE-NEXT: ret199;200; SVE2-LABEL: xar_nxv2i32_l_neg2_2:201; SVE2: // %bb.0:202; SVE2-NEXT: movi v2.2d, #0000000000000000203; SVE2-NEXT: orr z0.d, z0.d, z1.d204; SVE2-NEXT: xar z0.s, z0.s, z2.s, #4205; SVE2-NEXT: ret206 %a = or <vscale x 4 x i32> %x, %y207 %b = call <vscale x 4 x i32> @llvm.fshl.nxv4i32(<vscale x 4 x i32> %a, <vscale x 4 x i32> %a, <vscale x 4 x i32> splat (i32 60))208 ret <vscale x 4 x i32> %b209}210 211define <vscale x 8 x i16> @xar_nxv2i16_l_neg2_3(<vscale x 8 x i16> %x, <vscale x 8 x i16> %y) {212; SVE-LABEL: xar_nxv2i16_l_neg2_3:213; SVE: // %bb.0:214; SVE-NEXT: orr z0.d, z0.d, z1.d215; SVE-NEXT: lsr z1.h, z0.h, #4216; SVE-NEXT: lsl z0.h, z0.h, #12217; SVE-NEXT: orr z0.d, z0.d, z1.d218; SVE-NEXT: ret219;220; SVE2-LABEL: xar_nxv2i16_l_neg2_3:221; SVE2: // %bb.0:222; SVE2-NEXT: movi v2.2d, #0000000000000000223; SVE2-NEXT: orr z0.d, z0.d, z1.d224; SVE2-NEXT: xar z0.h, z0.h, z2.h, #4225; SVE2-NEXT: ret226 %a = or <vscale x 8 x i16> %x, %y227 %b = call <vscale x 8 x i16> @llvm.fshl.nxv8i16(<vscale x 8 x i16> %a, <vscale x 8 x i16> %a, <vscale x 8 x i16> splat (i16 60))228 ret <vscale x 8 x i16> %b229}230 231define <vscale x 16 x i8> @xar_nxv2i8_l_neg2_4(<vscale x 16 x i8> %x, <vscale x 16 x i8> %y) {232; SVE-LABEL: xar_nxv2i8_l_neg2_4:233; SVE: // %bb.0:234; SVE-NEXT: orr z0.d, z0.d, z1.d235; SVE-NEXT: lsr z1.b, z0.b, #4236; SVE-NEXT: lsl z0.b, z0.b, #4237; SVE-NEXT: orr z0.d, z0.d, z1.d238; SVE-NEXT: ret239;240; SVE2-LABEL: xar_nxv2i8_l_neg2_4:241; SVE2: // %bb.0:242; SVE2-NEXT: movi v2.2d, #0000000000000000243; SVE2-NEXT: orr z0.d, z0.d, z1.d244; SVE2-NEXT: xar z0.b, z0.b, z2.b, #4245; SVE2-NEXT: ret246 %a = or <vscale x 16 x i8> %x, %y247 %b = call <vscale x 16 x i8> @llvm.fshl.nxv16i8(<vscale x 16 x i8> %a, <vscale x 16 x i8> %a, <vscale x 16 x i8> splat (i8 60))248 ret <vscale x 16 x i8> %b249}250 251; Rotate amount is 0.252define <vscale x 2 x i64> @xar_nxv2i64_l_neg3(<vscale x 2 x i64> %x, <vscale x 2 x i64> %y) {253; CHECK-LABEL: xar_nxv2i64_l_neg3:254; CHECK: // %bb.0:255; CHECK-NEXT: eor z0.d, z0.d, z1.d256; CHECK-NEXT: ret257 %a = xor <vscale x 2 x i64> %x, %y258 %b = call <vscale x 2 x i64> @llvm.fshl.nxv2i64(<vscale x 2 x i64> %a, <vscale x 2 x i64> %a, <vscale x 2 x i64> splat (i64 64))259 ret <vscale x 2 x i64> %b260}261 262; Uses individual shifts instead of funnel shifts, just one test.263define <vscale x 2 x i64> @xar_nxv2i64_shifts(<vscale x 2 x i64> %x, <vscale x 2 x i64> %y) {264; SVE-LABEL: xar_nxv2i64_shifts:265; SVE: // %bb.0:266; SVE-NEXT: eor z0.d, z0.d, z1.d267; SVE-NEXT: lsr z1.d, z0.d, #4268; SVE-NEXT: lsl z0.d, z0.d, #60269; SVE-NEXT: orr z0.d, z0.d, z1.d270; SVE-NEXT: ret271;272; SVE2-LABEL: xar_nxv2i64_shifts:273; SVE2: // %bb.0:274; SVE2-NEXT: xar z0.d, z0.d, z1.d, #4275; SVE2-NEXT: ret276 %xor = xor <vscale x 2 x i64> %x, %y277 %shl = shl <vscale x 2 x i64> %xor, splat (i64 60)278 %shr = lshr <vscale x 2 x i64> %xor, splat (i64 4)279 %or = or <vscale x 2 x i64> %shl, %shr280 ret <vscale x 2 x i64> %or281}282 283; Not a rotate operation as 60 + 3 != 64284define <vscale x 2 x i64> @xar_nxv2i64_shifts_neg(<vscale x 2 x i64> %x, <vscale x 2 x i64> %y) {285; CHECK-LABEL: xar_nxv2i64_shifts_neg:286; CHECK: // %bb.0:287; CHECK-NEXT: eor z0.d, z0.d, z1.d288; CHECK-NEXT: lsl z1.d, z0.d, #60289; CHECK-NEXT: lsr z0.d, z0.d, #3290; CHECK-NEXT: orr z0.d, z1.d, z0.d291; CHECK-NEXT: ret292 %xor = xor <vscale x 2 x i64> %x, %y293 %shl = shl <vscale x 2 x i64> %xor, splat (i64 60)294 %shr = lshr <vscale x 2 x i64> %xor, splat (i64 3)295 %or = or <vscale x 2 x i64> %shl, %shr296 ret <vscale x 2 x i64> %or297}298 299declare <vscale x 2 x i64> @llvm.fshl.nxv2i64(<vscale x 2 x i64>, <vscale x 2 x i64>, <vscale x 2 x i64>)300declare <vscale x 4 x i32> @llvm.fshl.nxv4i32(<vscale x 4 x i32>, <vscale x 4 x i32>, <vscale x 4 x i32>)301declare <vscale x 8 x i16> @llvm.fshl.nxv8i16(<vscale x 8 x i16>, <vscale x 8 x i16>, <vscale x 8 x i16>)302declare <vscale x 16 x i8> @llvm.fshl.nxv16i8(<vscale x 16 x i8>, <vscale x 16 x i8>, <vscale x 16 x i8>)303declare <vscale x 2 x i64> @llvm.fshr.nxv2i64(<vscale x 2 x i64>, <vscale x 2 x i64>, <vscale x 2 x i64>)304declare <vscale x 4 x i32> @llvm.fshr.nxv4i32(<vscale x 4 x i32>, <vscale x 4 x i32>, <vscale x 4 x i32>)305declare <vscale x 8 x i16> @llvm.fshr.nxv8i16(<vscale x 8 x i16>, <vscale x 8 x i16>, <vscale x 8 x i16>)306declare <vscale x 16 x i8> @llvm.fshr.nxv16i8(<vscale x 16 x i8>, <vscale x 16 x i8>, <vscale x 16 x i8>)307