llvm-project/llvm/test/CodeGen/PowerPC/memcmp32_fixsize.ll
zhijian lin 55aff64d2c
[PowerPC] fold i128 equality/inequality compares of two loads into a vectorized compare using vcmpequb.p when Altivec is available (#158657)
The patch add 16 bytes load size for function
PPCTTIImpl::enableMemCmpExpansion and fold i128 equality/inequality
compares of two loads into a vectorized compare using vcmpequb.p when
Altivec is available.

Rationale:
A scalar i128 SETCC (eq/ne) normally lowers to multiple scalar ops. On
VSX-capable subtargets, we can instead reinterpret the i128 loads as
v16i8 vectors and use the Altive vcmpequb.p instruction to perform a
full 128-bit equality check in a single vector compare.

Example Result:
This transformation replaces memcmp(a, b, 16) with two vector loads and
one vector compare instruction.
2025-11-13 10:06:36 -05:00

59 lines
2.4 KiB
LLVM

; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 5
; RUN: llc -mcpu=pwr8 -ppc-asm-full-reg-names -mtriple=powerpc-ibm-aix < %s | \
; RUN: FileCheck %s --check-prefix=CHECK-AIX32-P8
; RUN: llc -mcpu=pwr10 -ppc-asm-full-reg-names -mtriple=powerpc-ibm-aix < %s | \
; RUN: FileCheck %s --check-prefix=CHECK-AIX32-P10
; RUN: llc -mcpu=pwr8 -ppc-asm-full-reg-names -mtriple=powerpcle-unknown-linux-gnu < %s | \
; RUN: FileCheck %s --check-prefix=CHECK-LINUX32-P8
; RUN: llc -mcpu=pwr10 -ppc-asm-full-reg-names -mtriple=powerpcle-unknown-linux-gnu < %s | \
; RUN: FileCheck %s --check-prefix=CHECK-LINUX32-P10
define dso_local signext range(i32 0, 2) i32 @cmpeq16(ptr noundef readonly captures(none) %a, ptr noundef readonly captures(none) %b) {
; CHECK-AIX32-P8-LABEL: cmpeq16:
; CHECK-AIX32-P8: # %bb.0: # %entry
; CHECK-AIX32-P8-NEXT: lxvw4x vs34, 0, r4
; CHECK-AIX32-P8-NEXT: lxvw4x vs35, 0, r3
; CHECK-AIX32-P8-NEXT: vcmpequb. v2, v3, v2
; CHECK-AIX32-P8-NEXT: mfocrf r3, 2
; CHECK-AIX32-P8-NEXT: rlwinm r3, r3, 25, 31, 31
; CHECK-AIX32-P8-NEXT: blr
;
; CHECK-AIX32-P10-LABEL: cmpeq16:
; CHECK-AIX32-P10: # %bb.0: # %entry
; CHECK-AIX32-P10-NEXT: lxv vs34, 0(r4)
; CHECK-AIX32-P10-NEXT: lxv vs35, 0(r3)
; CHECK-AIX32-P10-NEXT: vcmpequb. v2, v3, v2
; CHECK-AIX32-P10-NEXT: setbc r3, 4*cr6+lt
; CHECK-AIX32-P10-NEXT: blr
;
; CHECK-LINUX32-P8-LABEL: cmpeq16:
; CHECK-LINUX32-P8: # %bb.0: # %entry
; CHECK-LINUX32-P8-NEXT: lxvd2x vs0, 0, r4
; CHECK-LINUX32-P8-NEXT: xxswapd vs34, vs0
; CHECK-LINUX32-P8-NEXT: lxvd2x vs0, 0, r3
; CHECK-LINUX32-P8-NEXT: xxswapd vs35, vs0
; CHECK-LINUX32-P8-NEXT: vcmpequb. v2, v3, v2
; CHECK-LINUX32-P8-NEXT: mfocrf r3, 2
; CHECK-LINUX32-P8-NEXT: rlwinm r3, r3, 25, 31, 31
; CHECK-LINUX32-P8-NEXT: blr
;
; CHECK-LINUX32-P10-LABEL: cmpeq16:
; CHECK-LINUX32-P10: # %bb.0: # %entry
; CHECK-LINUX32-P10-NEXT: lxv vs34, 0(r4)
; CHECK-LINUX32-P10-NEXT: lxv vs35, 0(r3)
; CHECK-LINUX32-P10-NEXT: vcmpequb. v2, v3, v2
; CHECK-LINUX32-P10-NEXT: setbc r3, 4*cr6+lt
; CHECK-LINUX32-P10-NEXT: blr
entry:
%bcmp = tail call i32 @bcmp(ptr noundef nonnull dereferenceable(16) %a, ptr noundef nonnull dereferenceable(16) %b, i32 16)
%cmp = icmp eq i32 %bcmp, 0
%conv = zext i1 %cmp to i32
ret i32 %conv
}
declare signext i32 @bcmp(ptr captures(none), ptr captures(none), i32)