; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 6 ; RUN: llc < %s | FileCheck %s ; RUN: llc -mattr=+disable-distinct-predicate-dst-reg < %s | FileCheck %s --check-prefix=DISABLE-HINT target triple = "aarch64" ; ; Test that the destination register of the match/cmp instruction is different ; from the governing predicate register. ; define void @match_hint_distinct_pg_b(ptr %ptr, %a, %b) #0 { ; CHECK-LABEL: match_hint_distinct_pg_b: ; CHECK: // %bb.0: ; CHECK-NEXT: ptrue p0.b ; CHECK-NEXT: match p1.b, p0/z, z0.b, z1.b ; CHECK-NEXT: st1b { z0.b }, p1, [x0] ; CHECK-NEXT: ret ; ; DISABLE-HINT-LABEL: match_hint_distinct_pg_b: ; DISABLE-HINT: // %bb.0: ; DISABLE-HINT-NEXT: ptrue p0.b ; DISABLE-HINT-NEXT: match p0.b, p0/z, z0.b, z1.b ; DISABLE-HINT-NEXT: st1b { z0.b }, p0, [x0] ; DISABLE-HINT-NEXT: ret %match = tail call @llvm.aarch64.sve.match.nxv16i8( splat (i1 true), %a, %b) call void @llvm.masked.store( %a, ptr %ptr, %match) ret void } define void @match_hint_distinct_pg_h(ptr %ptr, %a, %b) #0 { ; CHECK-LABEL: match_hint_distinct_pg_h: ; CHECK: // %bb.0: ; CHECK-NEXT: ptrue p0.h ; CHECK-NEXT: match p1.h, p0/z, z0.h, z1.h ; CHECK-NEXT: st1h { z0.h }, p1, [x0] ; CHECK-NEXT: ret ; ; DISABLE-HINT-LABEL: match_hint_distinct_pg_h: ; DISABLE-HINT: // %bb.0: ; DISABLE-HINT-NEXT: ptrue p0.h ; DISABLE-HINT-NEXT: match p0.h, p0/z, z0.h, z1.h ; DISABLE-HINT-NEXT: st1h { z0.h }, p0, [x0] ; DISABLE-HINT-NEXT: ret %match = tail call @llvm.aarch64.sve.match.nxv16i8( splat (i1 true), %a, %b) call void @llvm.masked.store( %a, ptr %ptr, %match) ret void } define void @cmp_hint_distinct_pg_b(ptr %ptr, %a, %b) #0 { ; CHECK-LABEL: cmp_hint_distinct_pg_b: ; CHECK: // %bb.0: ; CHECK-NEXT: ptrue p0.b ; CHECK-NEXT: cmpeq p1.b, p0/z, z0.b, z1.b ; CHECK-NEXT: st1b { z0.b }, p1, [x0] ; CHECK-NEXT: ret ; ; DISABLE-HINT-LABEL: cmp_hint_distinct_pg_b: ; DISABLE-HINT: // %bb.0: ; DISABLE-HINT-NEXT: ptrue p0.b ; DISABLE-HINT-NEXT: cmpeq p0.b, p0/z, z0.b, z1.b ; DISABLE-HINT-NEXT: st1b { z0.b }, p0, [x0] ; DISABLE-HINT-NEXT: ret %cmp = icmp eq %a, %b call void @llvm.masked.store( %a, ptr %ptr, %cmp) ret void } define void @cmp_hint_distinct_pg_h(ptr %ptr, %a, %b) #0 { ; CHECK-LABEL: cmp_hint_distinct_pg_h: ; CHECK: // %bb.0: ; CHECK-NEXT: ptrue p0.h ; CHECK-NEXT: cmpeq p1.h, p0/z, z0.h, z1.h ; CHECK-NEXT: st1h { z0.h }, p1, [x0] ; CHECK-NEXT: ret ; ; DISABLE-HINT-LABEL: cmp_hint_distinct_pg_h: ; DISABLE-HINT: // %bb.0: ; DISABLE-HINT-NEXT: ptrue p0.h ; DISABLE-HINT-NEXT: cmpeq p0.h, p0/z, z0.h, z1.h ; DISABLE-HINT-NEXT: st1h { z0.h }, p0, [x0] ; DISABLE-HINT-NEXT: ret %cmp = icmp eq %a, %b call void @llvm.masked.store( %a, ptr %ptr, %cmp) ret void } define void @cmp_hint_distinct_pg_s(ptr %ptr, %a, %b) #0 { ; CHECK-LABEL: cmp_hint_distinct_pg_s: ; CHECK: // %bb.0: ; CHECK-NEXT: ptrue p0.s ; CHECK-NEXT: cmpeq p1.s, p0/z, z0.s, z1.s ; CHECK-NEXT: st1w { z0.s }, p1, [x0] ; CHECK-NEXT: ret ; ; DISABLE-HINT-LABEL: cmp_hint_distinct_pg_s: ; DISABLE-HINT: // %bb.0: ; DISABLE-HINT-NEXT: ptrue p0.s ; DISABLE-HINT-NEXT: cmpeq p0.s, p0/z, z0.s, z1.s ; DISABLE-HINT-NEXT: st1w { z0.s }, p0, [x0] ; DISABLE-HINT-NEXT: ret %cmp = icmp eq %a, %b call void @llvm.masked.store( %a, ptr %ptr, %cmp) ret void } define void @cmp_hint_distinct_pg_d(ptr %ptr, %a, %b) #0 { ; CHECK-LABEL: cmp_hint_distinct_pg_d: ; CHECK: // %bb.0: ; CHECK-NEXT: ptrue p0.d ; CHECK-NEXT: cmpeq p1.d, p0/z, z0.d, z1.d ; CHECK-NEXT: st1d { z0.d }, p1, [x0] ; CHECK-NEXT: ret ; ; DISABLE-HINT-LABEL: cmp_hint_distinct_pg_d: ; DISABLE-HINT: // %bb.0: ; DISABLE-HINT-NEXT: ptrue p0.d ; DISABLE-HINT-NEXT: cmpeq p0.d, p0/z, z0.d, z1.d ; DISABLE-HINT-NEXT: st1d { z0.d }, p0, [x0] ; DISABLE-HINT-NEXT: ret %cmp = icmp eq %a, %b call void @llvm.masked.store( %a, ptr %ptr, %cmp) ret void } ; ; Also test a case for the wide-element and immediate variants of CMP<> ; define void @wide_cmp_hint_distinct_pg_b(ptr %ptr, %pg, %a, %b) #0 { ; CHECK-LABEL: wide_cmp_hint_distinct_pg_b: ; CHECK: // %bb.0: ; CHECK-NEXT: cmpeq p1.b, p0/z, z0.b, z1.d ; CHECK-NEXT: st1b { z0.b }, p1, [x0] ; CHECK-NEXT: ret ; ; DISABLE-HINT-LABEL: wide_cmp_hint_distinct_pg_b: ; DISABLE-HINT: // %bb.0: ; DISABLE-HINT-NEXT: cmpeq p0.b, p0/z, z0.b, z1.d ; DISABLE-HINT-NEXT: st1b { z0.b }, p0, [x0] ; DISABLE-HINT-NEXT: ret %cmp = call @llvm.aarch64.sve.cmpeq.wide.nxv16i8( %pg, %a, %b) call void @llvm.masked.store( %a, ptr %ptr, %cmp) ret void } define void @imm_cmp_hint_distinct_pg_b(ptr %ptr, %pg, %a) #0 { ; CHECK-LABEL: imm_cmp_hint_distinct_pg_b: ; CHECK: // %bb.0: ; CHECK-NEXT: ptrue p0.b ; CHECK-NEXT: cmpeq p1.b, p0/z, z0.b, #12 ; CHECK-NEXT: st1b { z0.b }, p1, [x0] ; CHECK-NEXT: ret ; ; DISABLE-HINT-LABEL: imm_cmp_hint_distinct_pg_b: ; DISABLE-HINT: // %bb.0: ; DISABLE-HINT-NEXT: ptrue p0.b ; DISABLE-HINT-NEXT: cmpeq p0.b, p0/z, z0.b, #12 ; DISABLE-HINT-NEXT: st1b { z0.b }, p0, [x0] ; DISABLE-HINT-NEXT: ret %cmp = icmp eq %a, splat(i8 12) call void @llvm.masked.store( %a, ptr %ptr, %cmp) ret void } ; ; Some negative tests. ; ; Test that no different register is selected if that would introduce a mov. define @match_hint_dont_cause_extra_mov( %pg, %a, %b) #0 { ; CHECK-LABEL: match_hint_dont_cause_extra_mov: ; CHECK: // %bb.0: ; CHECK-NEXT: match p0.b, p0/z, z0.b, z1.b ; CHECK-NEXT: ret ; ; DISABLE-HINT-LABEL: match_hint_dont_cause_extra_mov: ; DISABLE-HINT: // %bb.0: ; DISABLE-HINT-NEXT: match p0.b, p0/z, z0.b, z1.b ; DISABLE-HINT-NEXT: ret %match = tail call @llvm.aarch64.sve.match.nxv16i8( %pg, %a, %b) ret %match } ; This is a case that is not yet supported, because at the point of constructing ; the hint for 'match' the all-true predicate is not yet allocated, so it can't ; choose a distinct register yet. This case could be support by looking through ; uses of the ptrue, but that may not be worth it because the ptrue is likely to ; have more than one use and this seems like an artificial case. define @unsupported_because_ptrue_not_yet_allocated(ptr %ptr, %a, %b) #0 { ; CHECK-LABEL: unsupported_because_ptrue_not_yet_allocated: ; CHECK: // %bb.0: ; CHECK-NEXT: ptrue p0.b ; CHECK-NEXT: match p0.b, p0/z, z0.b, z1.b ; CHECK-NEXT: ret ; ; DISABLE-HINT-LABEL: unsupported_because_ptrue_not_yet_allocated: ; DISABLE-HINT: // %bb.0: ; DISABLE-HINT-NEXT: ptrue p0.b ; DISABLE-HINT-NEXT: match p0.b, p0/z, z0.b, z1.b ; DISABLE-HINT-NEXT: ret %match = tail call @llvm.aarch64.sve.match.nxv16i8( splat (i1 true), %a, %b) ret %match } attributes #0 = { "target-features"="+sve2" }