blob: d58097f77f6d3e062305d0558efcd9fe55751d07 [file]
; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 6
; RUN: llc -mtriple=aarch64-linux-unknown -mattr=+sve2p1 -o - < %s | FileCheck %s -check-prefixes=CHECK,CHECK-SVE
; RUN: llc -mtriple=aarch64-linux-unknown -mattr=+sme2 -force-streaming -o - < %s | FileCheck %s -check-prefixes=CHECK,CHECK-SME
; Tests extracting the first lane from the first segment of a
; predicate-as-counter while folds to a conditional set (CSET) based on the
; "FIRST_ACTIVE" status flags from the while.
;
; %while, %flags = WHILE_*_PRED_COUNTER .. ; predicate-as-counter while
; %first.segment = pext(%while, 0) ; predicate extract of segment 0
; %first.active = extract_elt(%first_segment, 0) ; extract first lane
;
; ->
;
; %while, %flags = WHILE_*_PRED_COUNTER .. ; predicate-as-counter while
; %first.active = cset(%flags, FIRST_ACTIVE)
; Note: FIRST_ACTIVE corresponds to the MI condition code (N == 1), and
; not(FIRST_ACTIVE) corresponds to the PL condition code (N == 0).
define i1 @whilege_first_active(i64 %a, i64 %b) {
; CHECK-LABEL: whilege_first_active:
; CHECK: // %bb.0:
; CHECK-NEXT: whilege pn8.b, x0, x1, vlx4
; CHECK-NEXT: cset w0, mi
; CHECK-NEXT: ret
%while = call target("aarch64.svcount") @llvm.aarch64.sve.whilege.c8(i64 %a, i64 %b, i32 4)
%pext = call <vscale x 16 x i1> @llvm.aarch64.sve.pext.nxv16i1(target("aarch64.svcount") %while, i32 0)
%bit = extractelement <vscale x 16 x i1> %pext, i64 0
ret i1 %bit
}
define i1 @whilegt_first_active(i64 %a, i64 %b) {
; CHECK-LABEL: whilegt_first_active:
; CHECK: // %bb.0:
; CHECK-NEXT: whilegt pn8.h, x0, x1, vlx4
; CHECK-NEXT: cset w0, mi
; CHECK-NEXT: ret
%while = call target("aarch64.svcount") @llvm.aarch64.sve.whilegt.c16(i64 %a, i64 %b, i32 4)
%pext = call <vscale x 8 x i1> @llvm.aarch64.sve.pext.nxv8i1(target("aarch64.svcount") %while, i32 0)
%bit = extractelement <vscale x 8 x i1> %pext, i64 0
ret i1 %bit
}
define i1 @whilelt_first_active(i64 %a, i64 %b) {
; CHECK-LABEL: whilelt_first_active:
; CHECK: // %bb.0:
; CHECK-NEXT: whilelt pn8.s, x0, x1, vlx4
; CHECK-NEXT: cset w0, mi
; CHECK-NEXT: ret
%while = call target("aarch64.svcount") @llvm.aarch64.sve.whilelt.c32(i64 %a, i64 %b, i32 4)
%pext = call <vscale x 4 x i1> @llvm.aarch64.sve.pext.nxv4i1(target("aarch64.svcount") %while, i32 0)
%bit = extractelement <vscale x 4 x i1> %pext, i64 0
ret i1 %bit
}
define i1 @whilele_first_active(i64 %a, i64 %b) {
; CHECK-LABEL: whilele_first_active:
; CHECK: // %bb.0:
; CHECK-NEXT: whilele pn8.d, x0, x1, vlx4
; CHECK-NEXT: cset w0, mi
; CHECK-NEXT: ret
%while = call target("aarch64.svcount") @llvm.aarch64.sve.whilele.c64(i64 %a, i64 %b, i32 4)
%pext = call <vscale x 2 x i1> @llvm.aarch64.sve.pext.nxv2i1(target("aarch64.svcount") %while, i32 0)
%bit = extractelement <vscale x 2 x i1> %pext, i64 0
ret i1 %bit
}
define i1 @whilehs_first_active(i64 %a, i64 %b) {
; CHECK-LABEL: whilehs_first_active:
; CHECK: // %bb.0:
; CHECK-NEXT: whilehs pn8.b, x0, x1, vlx4
; CHECK-NEXT: cset w0, mi
; CHECK-NEXT: ret
%while = call target("aarch64.svcount") @llvm.aarch64.sve.whilehs.c8(i64 %a, i64 %b, i32 4)
%pext = call <vscale x 16 x i1> @llvm.aarch64.sve.pext.nxv16i1(target("aarch64.svcount") %while, i32 0)
%bit = extractelement <vscale x 16 x i1> %pext, i64 0
ret i1 %bit
}
define i1 @whilehi_first_active(i64 %a, i64 %b) {
; CHECK-LABEL: whilehi_first_active:
; CHECK: // %bb.0:
; CHECK-NEXT: whilehi pn8.h, x0, x1, vlx4
; CHECK-NEXT: cset w0, mi
; CHECK-NEXT: ret
%while = call target("aarch64.svcount") @llvm.aarch64.sve.whilehi.c16(i64 %a, i64 %b, i32 4)
%pext = call <vscale x 8 x i1> @llvm.aarch64.sve.pext.nxv8i1(target("aarch64.svcount") %while, i32 0)
%bit = extractelement <vscale x 8 x i1> %pext, i64 0
ret i1 %bit
}
define i1 @whilelo_first_active(i64 %a, i64 %b) {
; CHECK-LABEL: whilelo_first_active:
; CHECK: // %bb.0:
; CHECK-NEXT: whilelo pn8.s, x0, x1, vlx4
; CHECK-NEXT: cset w0, mi
; CHECK-NEXT: ret
%while = call target("aarch64.svcount") @llvm.aarch64.sve.whilelo.c32(i64 %a, i64 %b, i32 4)
%pext = call <vscale x 4 x i1> @llvm.aarch64.sve.pext.nxv4i1(target("aarch64.svcount") %while, i32 0)
%bit = extractelement <vscale x 4 x i1> %pext, i64 0
ret i1 %bit
}
define i1 @whilels_first_active(i64 %a, i64 %b) {
; CHECK-LABEL: whilels_first_active:
; CHECK: // %bb.0:
; CHECK-NEXT: whilels pn8.d, x0, x1, vlx4
; CHECK-NEXT: cset w0, mi
; CHECK-NEXT: ret
%while = call target("aarch64.svcount") @llvm.aarch64.sve.whilels.c64(i64 %a, i64 %b, i32 4)
%pext = call <vscale x 2 x i1> @llvm.aarch64.sve.pext.nxv2i1(target("aarch64.svcount") %while, i32 0)
%bit = extractelement <vscale x 2 x i1> %pext, i64 0
ret i1 %bit
}
define void @whilege_first_active_branch(i64 %a, i64 %b) {
; CHECK-LABEL: whilege_first_active_branch:
; CHECK: // %bb.0: // %entry
; CHECK-NEXT: whilege pn8.b, x0, x1, vlx4
; CHECK-NEXT: cset w8, mi
; CHECK-NEXT: cbz w8, .LBB8_2
; CHECK-NEXT: // %bb.1: // %then
; CHECK-NEXT: //APP
; CHECK-NEXT: //NO_APP
; CHECK-NEXT: .LBB8_2: // %exit
; CHECK-NEXT: ret
entry:
%while = call target("aarch64.svcount") @llvm.aarch64.sve.whilege.c8(i64 %a, i64 %b, i32 4)
%pext = call <vscale x 16 x i1> @llvm.aarch64.sve.pext.nxv16i1(target("aarch64.svcount") %while, i32 0)
%bit = extractelement <vscale x 16 x i1> %pext, i64 0
br i1 %bit, label %then, label %exit
then:
tail call void asm sideeffect "", ""()
br label %exit
exit:
ret void
}
define void @whilelo_first_active_branch(i64 %a, i64 %b) {
; CHECK-LABEL: whilelo_first_active_branch:
; CHECK: // %bb.0: // %entry
; CHECK-NEXT: whilelo pn8.s, x0, x1, vlx4
; CHECK-NEXT: cset w8, mi
; CHECK-NEXT: tbnz w8, #0, .LBB9_2
; CHECK-NEXT: // %bb.1: // %then
; CHECK-NEXT: //APP
; CHECK-NEXT: //NO_APP
; CHECK-NEXT: .LBB9_2: // %exit
; CHECK-NEXT: ret
entry:
%while = call target("aarch64.svcount") @llvm.aarch64.sve.whilelo.c32(i64 %a, i64 %b, i32 4)
%pext = call <vscale x 4 x i1> @llvm.aarch64.sve.pext.nxv4i1(target("aarch64.svcount") %while, i32 0)
%bit = extractelement <vscale x 4 x i1> %pext, i64 0
br i1 %bit, label %exit, label %then
then:
tail call void asm sideeffect "", ""()
br label %exit
exit:
ret void
}
; Negative test: a nonzero pext offset does not match the first-active fold.
define i1 @whilelo_pext_nonzero_offset(i64 %a, i64 %b) {
; CHECK-LABEL: whilelo_pext_nonzero_offset:
; CHECK: // %bb.0:
; CHECK-NEXT: whilelo pn8.s, x0, x1, vlx4
; CHECK-NEXT: pext p0.s, pn8[1]
; CHECK-NEXT: mov z0.s, p0/z, #1 // =0x1
; CHECK-NEXT: fmov w8, s0
; CHECK-NEXT: and w0, w8, #0x1
; CHECK-NEXT: ret
%while = call target("aarch64.svcount") @llvm.aarch64.sve.whilelo.c32(i64 %a, i64 %b, i32 4)
%pext = call <vscale x 4 x i1> @llvm.aarch64.sve.pext.nxv4i1(target("aarch64.svcount") %while, i32 1)
%bit = extractelement <vscale x 4 x i1> %pext, i64 0
ret i1 %bit
}
; Negative test: extracting any element other than lane 0 does not match the first-active fold.
define i1 @whilelt_extractelement_nonzero_index(i64 %a, i64 %b) {
; CHECK-SVE-LABEL: whilelt_extractelement_nonzero_index:
; CHECK-SVE: // %bb.0:
; CHECK-SVE-NEXT: whilelt pn8.h, x0, x1, vlx4
; CHECK-SVE-NEXT: pext p0.h, pn8[0]
; CHECK-SVE-NEXT: mov z0.h, p0/z, #1 // =0x1
; CHECK-SVE-NEXT: umov w8, v0.h[1]
; CHECK-SVE-NEXT: and w0, w8, #0x1
; CHECK-SVE-NEXT: ret
;
; CHECK-SME-LABEL: whilelt_extractelement_nonzero_index:
; CHECK-SME: // %bb.0:
; CHECK-SME-NEXT: whilelt pn8.h, x0, x1, vlx4
; CHECK-SME-NEXT: pext p0.h, pn8[0]
; CHECK-SME-NEXT: mov z0.h, p0/z, #1 // =0x1
; CHECK-SME-NEXT: mov z0.h, z0.h[1]
; CHECK-SME-NEXT: fmov w8, s0
; CHECK-SME-NEXT: and w0, w8, #0x1
; CHECK-SME-NEXT: ret
%while = call target("aarch64.svcount") @llvm.aarch64.sve.whilelt.c16(i64 %a, i64 %b, i32 4)
%pext = call <vscale x 8 x i1> @llvm.aarch64.sve.pext.nxv8i1(target("aarch64.svcount") %while, i32 0)
%bit = extractelement <vscale x 8 x i1> %pext, i64 1
ret i1 %bit
}