; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 5 ; RUN: llc -mtriple aarch64-linux-gnu %s -o - | FileCheck %s --check-prefixes=CHECK,CHECK-SD ; RUN: llc -mtriple aarch64-linux-gnu %s -o - -global-isel -global-isel-abort=2 2>&1 | FileCheck %s --check-prefixes=CHECK,CHECK-GI ; CHECK-GI: warning: Instruction selection used fallback path for any_of_select_vf2 ; CHECK-GI-NEXT: warning: Instruction selection used fallback path for any_of_select_vf32 ;; An 'AnyOf' reduction (vector.reduce.or) is instcombined to a bitcast to an ;; integer of a bitwidth equal to the number of lanes being reduced, then ;; compared against zero. To select between vectors for NEON, we then need to ;; broadcast the result, but we must be careful when the bitwidth of the scalar ;; result is smaller than the element size of the vectors being selected. We ;; don't want to end up with scalarization. define <4 x i32> @any_of_select_vf4(<4 x i32> %mask, <4 x i32> %a, <4 x i32> %b) { ; CHECK-SD-LABEL: any_of_select_vf4: ; CHECK-SD: // %bb.0: ; CHECK-SD-NEXT: cmlt v0.4s, v0.4s, #0 ; CHECK-SD-NEXT: movi d3, #0000000000000000 ; CHECK-SD-NEXT: addp d0, v0.2d ; CHECK-SD-NEXT: cmeq v0.2d, v0.2d, v3.2d ; CHECK-SD-NEXT: dup v0.2d, v0.d[0] ; CHECK-SD-NEXT: bsl v0.16b, v1.16b, v2.16b ; CHECK-SD-NEXT: ret ; ; CHECK-GI-LABEL: any_of_select_vf4: ; CHECK-GI: // %bb.0: ; CHECK-GI-NEXT: sub sp, sp, #16 ; CHECK-GI-NEXT: .cfi_def_cfa_offset 16 ; CHECK-GI-NEXT: cmlt v0.4s, v0.4s, #0 ; CHECK-GI-NEXT: mov w8, v0.s[1] ; CHECK-GI-NEXT: mov w9, v0.s[2] ; CHECK-GI-NEXT: fmov w11, s0 ; CHECK-GI-NEXT: mov w10, v0.s[3] ; CHECK-GI-NEXT: and w8, w8, #0x1 ; CHECK-GI-NEXT: bfi w11, w8, #1, #31 ; CHECK-GI-NEXT: and w8, w9, #0x1 ; CHECK-GI-NEXT: and w9, w10, #0x1 ; CHECK-GI-NEXT: orr w8, w11, w8, lsl #2 ; CHECK-GI-NEXT: orr w8, w8, w9, lsl #3 ; CHECK-GI-NEXT: strb w8, [sp, #15] ; CHECK-GI-NEXT: and w8, w8, #0xff ; CHECK-GI-NEXT: tst w8, #0xf ; CHECK-GI-NEXT: cset w8, eq ; CHECK-GI-NEXT: sbfx w8, w8, #0, #1 ; CHECK-GI-NEXT: dup v0.4s, w8 ; CHECK-GI-NEXT: bsl v0.16b, v1.16b, v2.16b ; CHECK-GI-NEXT: add sp, sp, #16 ; CHECK-GI-NEXT: ret %cmp = icmp slt <4 x i32> %mask, zeroinitializer %cmp.bc = bitcast <4 x i1> %cmp to i4 %cmp.bc.not = icmp eq i4 %cmp.bc, 0 %res = select i1 %cmp.bc.not, <4 x i32> %a, <4 x i32> %b ret <4 x i32> %res } define <4 x i8> @any_of_select_v4i8(<4 x i32> %mask, <4 x i8> %a, <4 x i8> %b) { ; CHECK-SD-LABEL: any_of_select_v4i8: ; CHECK-SD: // %bb.0: ; CHECK-SD-NEXT: cmlt v0.4s, v0.4s, #0 ; CHECK-SD-NEXT: movi d3, #0000000000000000 ; CHECK-SD-NEXT: addp d0, v0.2d ; CHECK-SD-NEXT: cmeq d0, d0, d3 ; CHECK-SD-NEXT: bsl v0.8b, v1.8b, v2.8b ; CHECK-SD-NEXT: ret ; ; CHECK-GI-LABEL: any_of_select_v4i8: ; CHECK-GI: // %bb.0: ; CHECK-GI-NEXT: sub sp, sp, #16 ; CHECK-GI-NEXT: .cfi_def_cfa_offset 16 ; CHECK-GI-NEXT: cmlt v0.4s, v0.4s, #0 ; CHECK-GI-NEXT: mov w8, v0.s[1] ; CHECK-GI-NEXT: mov w9, v0.s[2] ; CHECK-GI-NEXT: fmov w11, s0 ; CHECK-GI-NEXT: mov w10, v0.s[3] ; CHECK-GI-NEXT: and w8, w8, #0x1 ; CHECK-GI-NEXT: bfi w11, w8, #1, #31 ; CHECK-GI-NEXT: and w8, w9, #0x1 ; CHECK-GI-NEXT: and w9, w10, #0x1 ; CHECK-GI-NEXT: orr w8, w11, w8, lsl #2 ; CHECK-GI-NEXT: orr w8, w8, w9, lsl #3 ; CHECK-GI-NEXT: mov w9, #255 // =0xff ; CHECK-GI-NEXT: fmov s3, w9 ; CHECK-GI-NEXT: strb w8, [sp, #15] ; CHECK-GI-NEXT: and w8, w8, #0xff ; CHECK-GI-NEXT: tst w8, #0xf ; CHECK-GI-NEXT: cset w8, eq ; CHECK-GI-NEXT: mov v3.h[1], w9 ; CHECK-GI-NEXT: sbfx w8, w8, #0, #1 ; CHECK-GI-NEXT: fmov s0, w8 ; CHECK-GI-NEXT: mov v3.h[2], w9 ; CHECK-GI-NEXT: uzp1 v0.8b, v0.8b, v0.8b ; CHECK-GI-NEXT: mov v3.h[3], w9 ; CHECK-GI-NEXT: dup v0.8b, v0.b[0] ; CHECK-GI-NEXT: zip1 v0.8b, v0.8b, v0.8b ; CHECK-GI-NEXT: eor v3.8b, v0.8b, v3.8b ; CHECK-GI-NEXT: and v0.8b, v1.8b, v0.8b ; CHECK-GI-NEXT: and v1.8b, v2.8b, v3.8b ; CHECK-GI-NEXT: orr v0.8b, v0.8b, v1.8b ; CHECK-GI-NEXT: add sp, sp, #16 ; CHECK-GI-NEXT: ret %cmp = icmp slt <4 x i32> %mask, zeroinitializer %cmp.bc = bitcast <4 x i1> %cmp to i4 %cmp.bc.not = icmp eq i4 %cmp.bc, 0 %res = select i1 %cmp.bc.not, <4 x i8> %a, <4 x i8> %b ret <4 x i8> %res } define <2 x i64> @any_of_select_vf2(<2 x i64> %mask, <2 x i64> %a, <2 x i64> %b) { ; CHECK-LABEL: any_of_select_vf2: ; CHECK: // %bb.0: ; CHECK-NEXT: cmlt v0.2d, v0.2d, #0 ; CHECK-NEXT: movi d3, #0000000000000000 ; CHECK-NEXT: addp d0, v0.2d ; CHECK-NEXT: cmeq v0.2d, v0.2d, v3.2d ; CHECK-NEXT: dup v0.2d, v0.d[0] ; CHECK-NEXT: bsl v0.16b, v1.16b, v2.16b ; CHECK-NEXT: ret %cmp = icmp slt <2 x i64> %mask, zeroinitializer %cmp.bc = bitcast <2 x i1> %cmp to i2 %cmp.bc.not = icmp eq i2 %cmp.bc, 0 %res = select i1 %cmp.bc.not, <2 x i64> %a, <2 x i64> %b ret <2 x i64> %res } define <32 x i8> @any_of_select_vf32(<32 x i8> %mask, <32 x i8> %a, <32 x i8> %b) { ; CHECK-LABEL: any_of_select_vf32: ; CHECK: // %bb.0: ; CHECK-NEXT: orr v0.16b, v0.16b, v1.16b ; CHECK-NEXT: cmlt v0.16b, v0.16b, #0 ; CHECK-NEXT: umaxv b0, v0.16b ; CHECK-NEXT: fmov w8, s0 ; CHECK-NEXT: tst w8, #0x1 ; CHECK-NEXT: csetm w8, ne ; CHECK-NEXT: dup v1.16b, w8 ; CHECK-NEXT: mov v0.16b, v1.16b ; CHECK-NEXT: bsl v1.16b, v5.16b, v3.16b ; CHECK-NEXT: bsl v0.16b, v4.16b, v2.16b ; CHECK-NEXT: ret %cmp = icmp slt <32 x i8> %mask, zeroinitializer %cmp.bc = bitcast <32 x i1> %cmp to i32 %cmp.bc.not = icmp eq i32 %cmp.bc, 0 %res = select i1 %cmp.bc.not, <32 x i8> %a, <32 x i8> %b ret <32 x i8> %res }