1; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
2; RUN: llc < %s -mtriple=x86_64-unknown-unknown -mattr=+avx | FileCheck %s
3
4; These are actually tests of ValueTracking, and so may have test coverage in InstCombine or other
5; IR opt passes, but ValueTracking also affects the backend via SelectionDAGBuilder::visitSelect().
6
7define <4 x i32> @smin_vec1(<4 x i32> %x) {
8; CHECK-LABEL: smin_vec1:
9; CHECK:       # %bb.0:
10; CHECK-NEXT:    vpcmpeqd %xmm1, %xmm1, %xmm1
11; CHECK-NEXT:    vpxor %xmm1, %xmm0, %xmm0
12; CHECK-NEXT:    vpminsd %xmm1, %xmm0, %xmm0
13; CHECK-NEXT:    retq
14  %not_x = xor <4 x i32> %x, <i32 -1, i32 -1, i32 -1, i32 -1>
15  %cmp = icmp sgt <4 x i32> %x, zeroinitializer
16  %sel = select <4 x i1> %cmp, <4 x i32> %not_x, <4 x i32> <i32 -1, i32 -1, i32 -1, i32 -1>
17  ret <4 x i32> %sel
18}
19
20define <4 x i32> @smin_vec2(<4 x i32> %x) {
21; CHECK-LABEL: smin_vec2:
22; CHECK:       # %bb.0:
23; CHECK-NEXT:    vpcmpeqd %xmm1, %xmm1, %xmm1
24; CHECK-NEXT:    vpxor %xmm1, %xmm0, %xmm0
25; CHECK-NEXT:    vpminsd %xmm1, %xmm0, %xmm0
26; CHECK-NEXT:    retq
27  %not_x = xor <4 x i32> %x, <i32 -1, i32 -1, i32 -1, i32 -1>
28  %cmp = icmp slt <4 x i32> %x, zeroinitializer
29  %sel = select <4 x i1> %cmp, <4 x i32> <i32 -1, i32 -1, i32 -1, i32 -1>, <4 x i32> %not_x
30  ret <4 x i32> %sel
31}
32
33; Z = X -nsw Y
34; (X >s Y) ? 0 : Z ==> (Z >s 0) ? 0 : Z ==> SMIN(Z, 0)
35define <4 x i32> @smin_vec3(<4 x i32> %x, <4 x i32> %y) {
36; CHECK-LABEL: smin_vec3:
37; CHECK:       # %bb.0:
38; CHECK-NEXT:    vpsubd %xmm1, %xmm0, %xmm0
39; CHECK-NEXT:    vpxor %xmm1, %xmm1, %xmm1
40; CHECK-NEXT:    vpminsd %xmm1, %xmm0, %xmm0
41; CHECK-NEXT:    retq
42  %sub = sub nsw <4 x i32> %x, %y
43  %cmp = icmp sgt <4 x i32> %x, %y
44  %sel = select <4 x i1> %cmp, <4 x i32> zeroinitializer, <4 x i32> %sub
45  ret <4 x i32> %sel
46}
47
48; Z = X -nsw Y
49; (X <s Y) ? Z : 0 ==> (Z <s 0) ? Z : 0 ==> SMIN(Z, 0)
50define <4 x i32> @smin_vec4(<4 x i32> %x, <4 x i32> %y) {
51; CHECK-LABEL: smin_vec4:
52; CHECK:       # %bb.0:
53; CHECK-NEXT:    vpsubd %xmm1, %xmm0, %xmm0
54; CHECK-NEXT:    vpxor %xmm1, %xmm1, %xmm1
55; CHECK-NEXT:    vpminsd %xmm1, %xmm0, %xmm0
56; CHECK-NEXT:    retq
57  %sub = sub nsw <4 x i32> %x, %y
58  %cmp = icmp slt <4 x i32> %x, %y
59  %sel = select <4 x i1> %cmp, <4 x i32> %sub, <4 x i32> zeroinitializer
60  ret <4 x i32> %sel
61}
62
63define <4 x i32> @smax_vec1(<4 x i32> %x) {
64; CHECK-LABEL: smax_vec1:
65; CHECK:       # %bb.0:
66; CHECK-NEXT:    vpcmpeqd %xmm1, %xmm1, %xmm1
67; CHECK-NEXT:    vpxor %xmm1, %xmm0, %xmm0
68; CHECK-NEXT:    vpmaxsd %xmm1, %xmm0, %xmm0
69; CHECK-NEXT:    retq
70  %not_x = xor <4 x i32> %x, <i32 -1, i32 -1, i32 -1, i32 -1>
71  %cmp = icmp slt <4 x i32> %x, zeroinitializer
72  %sel = select <4 x i1> %cmp, <4 x i32> %not_x, <4 x i32> <i32 -1, i32 -1, i32 -1, i32 -1>
73  ret <4 x i32> %sel
74}
75
76define <4 x i32> @smax_vec2(<4 x i32> %x) {
77; CHECK-LABEL: smax_vec2:
78; CHECK:       # %bb.0:
79; CHECK-NEXT:    vpcmpeqd %xmm1, %xmm1, %xmm1
80; CHECK-NEXT:    vpxor %xmm1, %xmm0, %xmm0
81; CHECK-NEXT:    vpmaxsd %xmm1, %xmm0, %xmm0
82; CHECK-NEXT:    retq
83  %not_x = xor <4 x i32> %x, <i32 -1, i32 -1, i32 -1, i32 -1>
84  %cmp = icmp sgt <4 x i32> %x, zeroinitializer
85  %sel = select <4 x i1> %cmp, <4 x i32> <i32 -1, i32 -1, i32 -1, i32 -1>, <4 x i32> %not_x
86  ret <4 x i32> %sel
87}
88
89; Z = X -nsw Y
90; (X <s Y) ? 0 : Z ==> (Z <s 0) ? 0 : Z ==> SMAX(Z, 0)
91define <4 x i32> @smax_vec3(<4 x i32> %x, <4 x i32> %y) {
92; CHECK-LABEL: smax_vec3:
93; CHECK:       # %bb.0:
94; CHECK-NEXT:    vpsubd %xmm1, %xmm0, %xmm0
95; CHECK-NEXT:    vpxor %xmm1, %xmm1, %xmm1
96; CHECK-NEXT:    vpmaxsd %xmm1, %xmm0, %xmm0
97; CHECK-NEXT:    retq
98  %sub = sub nsw <4 x i32> %x, %y
99  %cmp = icmp slt <4 x i32> %x, %y
100  %sel = select <4 x i1> %cmp, <4 x i32> zeroinitializer, <4 x i32> %sub
101  ret <4 x i32> %sel
102}
103
104; Z = X -nsw Y
105; (X >s Y) ? Z : 0 ==> (Z >s 0) ? Z : 0 ==> SMAX(Z, 0)
106define <4 x i32> @smax_vec4(<4 x i32> %x, <4 x i32> %y) {
107; CHECK-LABEL: smax_vec4:
108; CHECK:       # %bb.0:
109; CHECK-NEXT:    vpsubd %xmm1, %xmm0, %xmm0
110; CHECK-NEXT:    vpxor %xmm1, %xmm1, %xmm1
111; CHECK-NEXT:    vpmaxsd %xmm1, %xmm0, %xmm0
112; CHECK-NEXT:    retq
113  %sub = sub nsw <4 x i32> %x, %y
114  %cmp = icmp sgt <4 x i32> %x, %y
115  %sel = select <4 x i1> %cmp, <4 x i32> %sub, <4 x i32> zeroinitializer
116  ret <4 x i32> %sel
117}
118
119define <4 x i32> @umax_vec1(<4 x i32> %x) {
120; CHECK-LABEL: umax_vec1:
121; CHECK:       # %bb.0:
122; CHECK-NEXT:    vpmaxud {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm0, %xmm0
123; CHECK-NEXT:    retq
124  %cmp = icmp slt <4 x i32> %x, zeroinitializer
125  %sel = select <4 x i1> %cmp, <4 x i32> %x, <4 x i32> <i32 2147483647, i32 2147483647, i32 2147483647, i32 2147483647>
126  ret <4 x i32> %sel
127}
128
129define <4 x i32> @umax_vec2(<4 x i32> %x) {
130; CHECK-LABEL: umax_vec2:
131; CHECK:       # %bb.0:
132; CHECK-NEXT:    vpmaxud {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm0, %xmm0
133; CHECK-NEXT:    retq
134  %cmp = icmp sgt <4 x i32> %x, <i32 -1, i32 -1, i32 -1, i32 -1>
135  %sel = select <4 x i1> %cmp, <4 x i32> <i32 2147483648, i32 2147483648, i32 2147483648, i32 2147483648>, <4 x i32> %x
136  ret <4 x i32> %sel
137}
138
139define <4 x i32> @umin_vec1(<4 x i32> %x) {
140; CHECK-LABEL: umin_vec1:
141; CHECK:       # %bb.0:
142; CHECK-NEXT:    vpminud {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm0, %xmm0
143; CHECK-NEXT:    retq
144  %cmp = icmp slt <4 x i32> %x, zeroinitializer
145  %sel = select <4 x i1> %cmp, <4 x i32> <i32 2147483647, i32 2147483647, i32 2147483647, i32 2147483647>, <4 x i32> %x
146  ret <4 x i32> %sel
147}
148
149define <4 x i32> @umin_vec2(<4 x i32> %x) {
150; CHECK-LABEL: umin_vec2:
151; CHECK:       # %bb.0:
152; CHECK-NEXT:    vpminud {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm0, %xmm0
153; CHECK-NEXT:    retq
154  %cmp = icmp sgt <4 x i32> %x, <i32 -1, i32 -1, i32 -1, i32 -1>
155  %sel = select <4 x i1> %cmp, <4 x i32> %x, <4 x i32> <i32 2147483648, i32 2147483648, i32 2147483648, i32 2147483648>
156  ret <4 x i32> %sel
157}
158
159; The next 4 tests are value clamping with constants:
160; https://llvm.org/bugs/show_bug.cgi?id=31693
161
162; (X <s C1) ? C1 : SMIN(X, C2) ==> SMAX(SMIN(X, C2), C1)
163
164define <4 x i32> @clamp_signed1(<4 x i32> %x) {
165; CHECK-LABEL: clamp_signed1:
166; CHECK:       # %bb.0:
167; CHECK-NEXT:    vpminsd {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm0, %xmm0
168; CHECK-NEXT:    vpmaxsd {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm0, %xmm0
169; CHECK-NEXT:    retq
170  %cmp2 = icmp slt <4 x i32> %x, <i32 255, i32 255, i32 255, i32 255>
171  %min = select <4 x i1> %cmp2, <4 x i32> %x, <4 x i32><i32 255, i32 255, i32 255, i32 255>
172  %cmp1 = icmp slt <4 x i32> %x, <i32 15, i32 15, i32 15, i32 15>
173  %r = select <4 x i1> %cmp1, <4 x i32><i32 15, i32 15, i32 15, i32 15>, <4 x i32> %min
174  ret <4 x i32> %r
175}
176
177; (X >s C1) ? C1 : SMAX(X, C2) ==> SMIN(SMAX(X, C2), C1)
178
179define <4 x i32> @clamp_signed2(<4 x i32> %x) {
180; CHECK-LABEL: clamp_signed2:
181; CHECK:       # %bb.0:
182; CHECK-NEXT:    vpmaxsd {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm0, %xmm0
183; CHECK-NEXT:    vpminsd {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm0, %xmm0
184; CHECK-NEXT:    retq
185  %cmp2 = icmp sgt <4 x i32> %x, <i32 15, i32 15, i32 15, i32 15>
186  %max = select <4 x i1> %cmp2, <4 x i32> %x, <4 x i32><i32 15, i32 15, i32 15, i32 15>
187  %cmp1 = icmp sgt <4 x i32> %x, <i32 255, i32 255, i32 255, i32 255>
188  %r = select <4 x i1> %cmp1, <4 x i32><i32 255, i32 255, i32 255, i32 255>, <4 x i32> %max
189  ret <4 x i32> %r
190}
191
192; (X <u C1) ? C1 : UMIN(X, C2) ==> UMAX(UMIN(X, C2), C1)
193
194define <4 x i32> @clamp_unsigned1(<4 x i32> %x) {
195; CHECK-LABEL: clamp_unsigned1:
196; CHECK:       # %bb.0:
197; CHECK-NEXT:    vpminud {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm0, %xmm0
198; CHECK-NEXT:    vpmaxud {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm0, %xmm0
199; CHECK-NEXT:    retq
200  %cmp2 = icmp ult <4 x i32> %x, <i32 255, i32 255, i32 255, i32 255>
201  %min = select <4 x i1> %cmp2, <4 x i32> %x, <4 x i32><i32 255, i32 255, i32 255, i32 255>
202  %cmp1 = icmp ult <4 x i32> %x, <i32 15, i32 15, i32 15, i32 15>
203  %r = select <4 x i1> %cmp1, <4 x i32><i32 15, i32 15, i32 15, i32 15>, <4 x i32> %min
204  ret <4 x i32> %r
205}
206
207; (X >u C1) ? C1 : UMAX(X, C2) ==> UMIN(UMAX(X, C2), C1)
208
209define <4 x i32> @clamp_unsigned2(<4 x i32> %x) {
210; CHECK-LABEL: clamp_unsigned2:
211; CHECK:       # %bb.0:
212; CHECK-NEXT:    vpmaxud {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm0, %xmm0
213; CHECK-NEXT:    vpminud {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm0, %xmm0
214; CHECK-NEXT:    retq
215  %cmp2 = icmp ugt <4 x i32> %x, <i32 15, i32 15, i32 15, i32 15>
216  %max = select <4 x i1> %cmp2, <4 x i32> %x, <4 x i32><i32 15, i32 15, i32 15, i32 15>
217  %cmp1 = icmp ugt <4 x i32> %x, <i32 255, i32 255, i32 255, i32 255>
218  %r = select <4 x i1> %cmp1, <4 x i32><i32 255, i32 255, i32 255, i32 255>, <4 x i32> %max
219  ret <4 x i32> %r
220}
221
222define <4 x i32> @umin_not_ops(<4 x i32> %x) {
223; CHECK-LABEL: umin_not_ops:
224; CHECK:       # %bb.0:
225; CHECK-NEXT:    vpcmpeqd %xmm1, %xmm1, %xmm1
226; CHECK-NEXT:    vpxor %xmm1, %xmm0, %xmm0
227; CHECK-NEXT:    vpminud {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm0, %xmm0
228; CHECK-NEXT:    retq
229  %not_x = xor <4 x i32> %x, <i32 -1, i32 -1, i32 -1, i32 -1>
230  %cmp = icmp ugt <4 x i32> %x, <i32 4, i32 4, i32 4, i32 4>
231  %sel = select <4 x i1> %cmp, <4 x i32> %not_x, <4 x i32> <i32 -5, i32 -5, i32 -5, i32 -5>
232  ret <4 x i32> %sel
233}
234
235define <4 x i32> @wrong_pred_for_smin_with_subnsw(<4 x i32> %x, <4 x i32> %y) {
236; CHECK-LABEL: wrong_pred_for_smin_with_subnsw:
237; CHECK:       # %bb.0:
238; CHECK-NEXT:    vpsubd %xmm1, %xmm0, %xmm2
239; CHECK-NEXT:    vpminud %xmm1, %xmm0, %xmm1
240; CHECK-NEXT:    vpcmpeqd %xmm1, %xmm0, %xmm0
241; CHECK-NEXT:    vpand %xmm2, %xmm0, %xmm0
242; CHECK-NEXT:    retq
243  %sub = sub nsw <4 x i32> %x, %y
244  %cmp = icmp ugt <4 x i32> %x, %y
245  %sel = select <4 x i1> %cmp, <4 x i32> zeroinitializer, <4 x i32> %sub
246  ret <4 x i32> %sel
247}
248
249