mirror of
https://github.com/RPCS3/llvm.git
synced 2026-07-22 03:35:35 -04:00
c8f9cf9e26
This goes back to a discussion about IR canonicalization. We'd like to preserve and convert more IR to 'select' than we currently do because that's likely the best choice in IR: http://lists.llvm.org/pipermail/llvm-dev/2016-September/105335.html ...but that's often not true for codegen, so we need to account for this pattern coming in to the backend and transform it to better DAG ops. Steps in this patch: 1. Add an EVT param to the existing convertSelectOfConstantsToMath() TLI hook to more finely enable this transform. Other targets will probably want that anyway to distinguish scalars from vectors. We're using that here to exclude AVX512 targets, but it may not be necessary. 2. Convert a vselect to ext+add. This eliminates a constant load/materialization, and the vector ext is often free. Implementing a more general fold using xor+and can be a follow-up for targets that don't have a legal vselect. It's also possible that we can remove the TLI hook for the special case fold implemented here because we're eliminating a constant, but it needs to be tested on other targets. Differential Revision: https://reviews.llvm.org/D36840 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@311731 91177308-0d34-0410-b5e6-96231b3b80d8
259 lines
8.8 KiB
LLVM
259 lines
8.8 KiB
LLVM
; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
|
|
; RUN: llc < %s -mtriple=x86_64-unknown-unknown -mattr=sse2 | FileCheck %s --check-prefix=ALL --check-prefix=SSE
|
|
; RUN: llc < %s -mtriple=x86_64-unknown-unknown -mattr=avx | FileCheck %s --check-prefix=ALL --check-prefix=AVX
|
|
|
|
; First, check the generic pattern for any 2 vector constants. Then, check special cases where
|
|
; the constants are all off-by-one. Finally, check the extra special cases where the constants
|
|
; include 0 or -1.
|
|
; Each minimal select test is repeated with a more typical pattern that includes a compare to
|
|
; generate the condition value.
|
|
|
|
; TODO: If we don't have blendv, this can definitely be improved. There's also a selection of
|
|
; chips where it makes sense to transform the general case blendv to 2 bit-ops. That should be
|
|
; a uarch-specfic transform. At some point (Ryzen?), the implementation should catch up to the
|
|
; architecture, so blendv is as fast as a single bit-op.
|
|
|
|
define <4 x i32> @sel_C1_or_C2_vec(<4 x i1> %cond) {
|
|
; SSE-LABEL: sel_C1_or_C2_vec:
|
|
; SSE: # BB#0:
|
|
; SSE-NEXT: pslld $31, %xmm0
|
|
; SSE-NEXT: psrad $31, %xmm0
|
|
; SSE-NEXT: movdqa %xmm0, %xmm1
|
|
; SSE-NEXT: pandn {{.*}}(%rip), %xmm1
|
|
; SSE-NEXT: pand {{.*}}(%rip), %xmm0
|
|
; SSE-NEXT: por %xmm1, %xmm0
|
|
; SSE-NEXT: retq
|
|
;
|
|
; AVX-LABEL: sel_C1_or_C2_vec:
|
|
; AVX: # BB#0:
|
|
; AVX-NEXT: vpslld $31, %xmm0, %xmm0
|
|
; AVX-NEXT: vmovaps {{.*#+}} xmm1 = [42,0,4294967294,4294967295]
|
|
; AVX-NEXT: vblendvps %xmm0, {{.*}}(%rip), %xmm1, %xmm0
|
|
; AVX-NEXT: retq
|
|
%add = select <4 x i1> %cond, <4 x i32> <i32 3000, i32 1, i32 -1, i32 0>, <4 x i32> <i32 42, i32 0, i32 -2, i32 -1>
|
|
ret <4 x i32> %add
|
|
}
|
|
|
|
define <4 x i32> @cmp_sel_C1_or_C2_vec(<4 x i32> %x, <4 x i32> %y) {
|
|
; SSE-LABEL: cmp_sel_C1_or_C2_vec:
|
|
; SSE: # BB#0:
|
|
; SSE-NEXT: pcmpeqd %xmm1, %xmm0
|
|
; SSE-NEXT: movdqa %xmm0, %xmm1
|
|
; SSE-NEXT: pandn {{.*}}(%rip), %xmm1
|
|
; SSE-NEXT: pand {{.*}}(%rip), %xmm0
|
|
; SSE-NEXT: por %xmm1, %xmm0
|
|
; SSE-NEXT: retq
|
|
;
|
|
; AVX-LABEL: cmp_sel_C1_or_C2_vec:
|
|
; AVX: # BB#0:
|
|
; AVX-NEXT: vpcmpeqd %xmm1, %xmm0, %xmm0
|
|
; AVX-NEXT: vmovaps {{.*#+}} xmm1 = [42,0,4294967294,4294967295]
|
|
; AVX-NEXT: vblendvps %xmm0, {{.*}}(%rip), %xmm1, %xmm0
|
|
; AVX-NEXT: retq
|
|
%cond = icmp eq <4 x i32> %x, %y
|
|
%add = select <4 x i1> %cond, <4 x i32> <i32 3000, i32 1, i32 -1, i32 0>, <4 x i32> <i32 42, i32 0, i32 -2, i32 -1>
|
|
ret <4 x i32> %add
|
|
}
|
|
|
|
define <4 x i32> @sel_Cplus1_or_C_vec(<4 x i1> %cond) {
|
|
; SSE-LABEL: sel_Cplus1_or_C_vec:
|
|
; SSE: # BB#0:
|
|
; SSE-NEXT: pand {{.*}}(%rip), %xmm0
|
|
; SSE-NEXT: paddd {{.*}}(%rip), %xmm0
|
|
; SSE-NEXT: retq
|
|
;
|
|
; AVX-LABEL: sel_Cplus1_or_C_vec:
|
|
; AVX: # BB#0:
|
|
; AVX-NEXT: vpand {{.*}}(%rip), %xmm0, %xmm0
|
|
; AVX-NEXT: vpaddd {{.*}}(%rip), %xmm0, %xmm0
|
|
; AVX-NEXT: retq
|
|
%add = select <4 x i1> %cond, <4 x i32> <i32 43, i32 1, i32 -1, i32 0>, <4 x i32> <i32 42, i32 0, i32 -2, i32 -1>
|
|
ret <4 x i32> %add
|
|
}
|
|
|
|
define <4 x i32> @cmp_sel_Cplus1_or_C_vec(<4 x i32> %x, <4 x i32> %y) {
|
|
; SSE-LABEL: cmp_sel_Cplus1_or_C_vec:
|
|
; SSE: # BB#0:
|
|
; SSE-NEXT: pcmpeqd %xmm1, %xmm0
|
|
; SSE-NEXT: movdqa {{.*#+}} xmm1 = [42,0,4294967294,4294967295]
|
|
; SSE-NEXT: psubd %xmm0, %xmm1
|
|
; SSE-NEXT: movdqa %xmm1, %xmm0
|
|
; SSE-NEXT: retq
|
|
;
|
|
; AVX-LABEL: cmp_sel_Cplus1_or_C_vec:
|
|
; AVX: # BB#0:
|
|
; AVX-NEXT: vpcmpeqd %xmm1, %xmm0, %xmm0
|
|
; AVX-NEXT: vmovdqa {{.*#+}} xmm1 = [42,0,4294967294,4294967295]
|
|
; AVX-NEXT: vpsubd %xmm0, %xmm1, %xmm0
|
|
; AVX-NEXT: retq
|
|
%cond = icmp eq <4 x i32> %x, %y
|
|
%add = select <4 x i1> %cond, <4 x i32> <i32 43, i32 1, i32 -1, i32 0>, <4 x i32> <i32 42, i32 0, i32 -2, i32 -1>
|
|
ret <4 x i32> %add
|
|
}
|
|
|
|
define <4 x i32> @sel_Cminus1_or_C_vec(<4 x i1> %cond) {
|
|
; SSE-LABEL: sel_Cminus1_or_C_vec:
|
|
; SSE: # BB#0:
|
|
; SSE-NEXT: pslld $31, %xmm0
|
|
; SSE-NEXT: psrad $31, %xmm0
|
|
; SSE-NEXT: paddd {{.*}}(%rip), %xmm0
|
|
; SSE-NEXT: retq
|
|
;
|
|
; AVX-LABEL: sel_Cminus1_or_C_vec:
|
|
; AVX: # BB#0:
|
|
; AVX-NEXT: vpslld $31, %xmm0, %xmm0
|
|
; AVX-NEXT: vpsrad $31, %xmm0, %xmm0
|
|
; AVX-NEXT: vpaddd {{.*}}(%rip), %xmm0, %xmm0
|
|
; AVX-NEXT: retq
|
|
%add = select <4 x i1> %cond, <4 x i32> <i32 43, i32 1, i32 -1, i32 0>, <4 x i32> <i32 44, i32 2, i32 0, i32 1>
|
|
ret <4 x i32> %add
|
|
}
|
|
|
|
define <4 x i32> @cmp_sel_Cminus1_or_C_vec(<4 x i32> %x, <4 x i32> %y) {
|
|
; SSE-LABEL: cmp_sel_Cminus1_or_C_vec:
|
|
; SSE: # BB#0:
|
|
; SSE-NEXT: pcmpeqd %xmm1, %xmm0
|
|
; SSE-NEXT: paddd {{.*}}(%rip), %xmm0
|
|
; SSE-NEXT: retq
|
|
;
|
|
; AVX-LABEL: cmp_sel_Cminus1_or_C_vec:
|
|
; AVX: # BB#0:
|
|
; AVX-NEXT: vpcmpeqd %xmm1, %xmm0, %xmm0
|
|
; AVX-NEXT: vpaddd {{.*}}(%rip), %xmm0, %xmm0
|
|
; AVX-NEXT: retq
|
|
%cond = icmp eq <4 x i32> %x, %y
|
|
%add = select <4 x i1> %cond, <4 x i32> <i32 43, i32 1, i32 -1, i32 0>, <4 x i32> <i32 44, i32 2, i32 0, i32 1>
|
|
ret <4 x i32> %add
|
|
}
|
|
|
|
define <4 x i32> @sel_minus1_or_0_vec(<4 x i1> %cond) {
|
|
; SSE-LABEL: sel_minus1_or_0_vec:
|
|
; SSE: # BB#0:
|
|
; SSE-NEXT: pslld $31, %xmm0
|
|
; SSE-NEXT: psrad $31, %xmm0
|
|
; SSE-NEXT: retq
|
|
;
|
|
; AVX-LABEL: sel_minus1_or_0_vec:
|
|
; AVX: # BB#0:
|
|
; AVX-NEXT: vpslld $31, %xmm0, %xmm0
|
|
; AVX-NEXT: vpsrad $31, %xmm0, %xmm0
|
|
; AVX-NEXT: retq
|
|
%add = select <4 x i1> %cond, <4 x i32> <i32 -1, i32 -1, i32 -1, i32 -1>, <4 x i32> <i32 0, i32 0, i32 0, i32 0>
|
|
ret <4 x i32> %add
|
|
}
|
|
|
|
define <4 x i32> @cmp_sel_minus1_or_0_vec(<4 x i32> %x, <4 x i32> %y) {
|
|
; SSE-LABEL: cmp_sel_minus1_or_0_vec:
|
|
; SSE: # BB#0:
|
|
; SSE-NEXT: pcmpeqd %xmm1, %xmm0
|
|
; SSE-NEXT: retq
|
|
;
|
|
; AVX-LABEL: cmp_sel_minus1_or_0_vec:
|
|
; AVX: # BB#0:
|
|
; AVX-NEXT: vpcmpeqd %xmm1, %xmm0, %xmm0
|
|
; AVX-NEXT: retq
|
|
%cond = icmp eq <4 x i32> %x, %y
|
|
%add = select <4 x i1> %cond, <4 x i32> <i32 -1, i32 -1, i32 -1, i32 -1>, <4 x i32> <i32 0, i32 0, i32 0, i32 0>
|
|
ret <4 x i32> %add
|
|
}
|
|
|
|
define <4 x i32> @sel_0_or_minus1_vec(<4 x i1> %cond) {
|
|
; SSE-LABEL: sel_0_or_minus1_vec:
|
|
; SSE: # BB#0:
|
|
; SSE-NEXT: pand {{.*}}(%rip), %xmm0
|
|
; SSE-NEXT: pcmpeqd %xmm1, %xmm1
|
|
; SSE-NEXT: paddd %xmm1, %xmm0
|
|
; SSE-NEXT: retq
|
|
;
|
|
; AVX-LABEL: sel_0_or_minus1_vec:
|
|
; AVX: # BB#0:
|
|
; AVX-NEXT: vpand {{.*}}(%rip), %xmm0, %xmm0
|
|
; AVX-NEXT: vpcmpeqd %xmm1, %xmm1, %xmm1
|
|
; AVX-NEXT: vpaddd %xmm1, %xmm0, %xmm0
|
|
; AVX-NEXT: retq
|
|
%add = select <4 x i1> %cond, <4 x i32> <i32 0, i32 0, i32 0, i32 0>, <4 x i32> <i32 -1, i32 -1, i32 -1, i32 -1>
|
|
ret <4 x i32> %add
|
|
}
|
|
|
|
define <4 x i32> @cmp_sel_0_or_minus1_vec(<4 x i32> %x, <4 x i32> %y) {
|
|
; SSE-LABEL: cmp_sel_0_or_minus1_vec:
|
|
; SSE: # BB#0:
|
|
; SSE-NEXT: pcmpeqd %xmm1, %xmm0
|
|
; SSE-NEXT: pcmpeqd %xmm1, %xmm1
|
|
; SSE-NEXT: pxor %xmm1, %xmm0
|
|
; SSE-NEXT: retq
|
|
;
|
|
; AVX-LABEL: cmp_sel_0_or_minus1_vec:
|
|
; AVX: # BB#0:
|
|
; AVX-NEXT: vpcmpeqd %xmm1, %xmm0, %xmm0
|
|
; AVX-NEXT: vpcmpeqd %xmm1, %xmm1, %xmm1
|
|
; AVX-NEXT: vpxor %xmm1, %xmm0, %xmm0
|
|
; AVX-NEXT: retq
|
|
%cond = icmp eq <4 x i32> %x, %y
|
|
%add = select <4 x i1> %cond, <4 x i32> <i32 0, i32 0, i32 0, i32 0>, <4 x i32> <i32 -1, i32 -1, i32 -1, i32 -1>
|
|
ret <4 x i32> %add
|
|
}
|
|
|
|
define <4 x i32> @sel_1_or_0_vec(<4 x i1> %cond) {
|
|
; SSE-LABEL: sel_1_or_0_vec:
|
|
; SSE: # BB#0:
|
|
; SSE-NEXT: andps {{.*}}(%rip), %xmm0
|
|
; SSE-NEXT: retq
|
|
;
|
|
; AVX-LABEL: sel_1_or_0_vec:
|
|
; AVX: # BB#0:
|
|
; AVX-NEXT: vandps {{.*}}(%rip), %xmm0, %xmm0
|
|
; AVX-NEXT: retq
|
|
%add = select <4 x i1> %cond, <4 x i32> <i32 1, i32 1, i32 1, i32 1>, <4 x i32> <i32 0, i32 0, i32 0, i32 0>
|
|
ret <4 x i32> %add
|
|
}
|
|
|
|
define <4 x i32> @cmp_sel_1_or_0_vec(<4 x i32> %x, <4 x i32> %y) {
|
|
; SSE-LABEL: cmp_sel_1_or_0_vec:
|
|
; SSE: # BB#0:
|
|
; SSE-NEXT: pcmpeqd %xmm1, %xmm0
|
|
; SSE-NEXT: psrld $31, %xmm0
|
|
; SSE-NEXT: retq
|
|
;
|
|
; AVX-LABEL: cmp_sel_1_or_0_vec:
|
|
; AVX: # BB#0:
|
|
; AVX-NEXT: vpcmpeqd %xmm1, %xmm0, %xmm0
|
|
; AVX-NEXT: vpsrld $31, %xmm0, %xmm0
|
|
; AVX-NEXT: retq
|
|
%cond = icmp eq <4 x i32> %x, %y
|
|
%add = select <4 x i1> %cond, <4 x i32> <i32 1, i32 1, i32 1, i32 1>, <4 x i32> <i32 0, i32 0, i32 0, i32 0>
|
|
ret <4 x i32> %add
|
|
}
|
|
|
|
define <4 x i32> @sel_0_or_1_vec(<4 x i1> %cond) {
|
|
; SSE-LABEL: sel_0_or_1_vec:
|
|
; SSE: # BB#0:
|
|
; SSE-NEXT: andnps {{.*}}(%rip), %xmm0
|
|
; SSE-NEXT: retq
|
|
;
|
|
; AVX-LABEL: sel_0_or_1_vec:
|
|
; AVX: # BB#0:
|
|
; AVX-NEXT: vandnps {{.*}}(%rip), %xmm0, %xmm0
|
|
; AVX-NEXT: retq
|
|
%add = select <4 x i1> %cond, <4 x i32> <i32 0, i32 0, i32 0, i32 0>, <4 x i32> <i32 1, i32 1, i32 1, i32 1>
|
|
ret <4 x i32> %add
|
|
}
|
|
|
|
define <4 x i32> @cmp_sel_0_or_1_vec(<4 x i32> %x, <4 x i32> %y) {
|
|
; SSE-LABEL: cmp_sel_0_or_1_vec:
|
|
; SSE: # BB#0:
|
|
; SSE-NEXT: pcmpeqd %xmm1, %xmm0
|
|
; SSE-NEXT: pandn {{.*}}(%rip), %xmm0
|
|
; SSE-NEXT: retq
|
|
;
|
|
; AVX-LABEL: cmp_sel_0_or_1_vec:
|
|
; AVX: # BB#0:
|
|
; AVX-NEXT: vpcmpeqd %xmm1, %xmm0, %xmm0
|
|
; AVX-NEXT: vpandn {{.*}}(%rip), %xmm0, %xmm0
|
|
; AVX-NEXT: retq
|
|
%cond = icmp eq <4 x i32> %x, %y
|
|
%add = select <4 x i1> %cond, <4 x i32> <i32 0, i32 0, i32 0, i32 0>, <4 x i32> <i32 1, i32 1, i32 1, i32 1>
|
|
ret <4 x i32> %add
|
|
}
|
|
|