xref: /llvm-project/llvm/test/Transforms/VectorCombine/X86/shuffle-of-cmps.ll (revision 4a42658c1be47ea8cb6f26f7cb1d1aed258845fe)
1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 4
2; RUN: opt < %s -passes=vector-combine -S -mtriple=x86_64-- -mattr=sse2 | FileCheck %s --check-prefixes=CHECK,SSE,SSE2
3; RUN: opt < %s -passes=vector-combine -S -mtriple=x86_64-- -mattr=sse4.2 | FileCheck %s --check-prefixes=CHECK,SSE,SSE4
4; RUN: opt < %s -passes=vector-combine -S -mtriple=x86_64-- -mattr=avx2 | FileCheck %s --check-prefixes=CHECK,AVX2
5; RUN: opt < %s -passes=vector-combine -S -mtriple=x86_64-- -mattr=avx512vl | FileCheck %s --check-prefixes=CHECK,AVX512
6
7declare void @use(<4 x i1>)
8
9; icmp - eq v4i32 is cheap
10
11define <4 x i32> @shuf_icmp_eq_v4i32(<4 x i32> %x, <4 x i32> %y, <4 x i32> %z, <4 x i32> %w) {
12; SSE-LABEL: define <4 x i32> @shuf_icmp_eq_v4i32(
13; SSE-SAME: <4 x i32> [[X:%.*]], <4 x i32> [[Y:%.*]], <4 x i32> [[Z:%.*]], <4 x i32> [[W:%.*]]) #[[ATTR0:[0-9]+]] {
14; SSE-NEXT:    [[C0:%.*]] = icmp eq <4 x i32> [[X]], [[Y]]
15; SSE-NEXT:    [[C1:%.*]] = icmp eq <4 x i32> [[Z]], [[W]]
16; SSE-NEXT:    [[S:%.*]] = shufflevector <4 x i1> [[C0]], <4 x i1> [[C1]], <4 x i32> <i32 1, i32 3, i32 5, i32 7>
17; SSE-NEXT:    [[R:%.*]] = sext <4 x i1> [[S]] to <4 x i32>
18; SSE-NEXT:    ret <4 x i32> [[R]]
19;
20; AVX2-LABEL: define <4 x i32> @shuf_icmp_eq_v4i32(
21; AVX2-SAME: <4 x i32> [[X:%.*]], <4 x i32> [[Y:%.*]], <4 x i32> [[Z:%.*]], <4 x i32> [[W:%.*]]) #[[ATTR0:[0-9]+]] {
22; AVX2-NEXT:    [[C0:%.*]] = icmp eq <4 x i32> [[X]], [[Y]]
23; AVX2-NEXT:    [[C1:%.*]] = icmp eq <4 x i32> [[Z]], [[W]]
24; AVX2-NEXT:    [[S:%.*]] = shufflevector <4 x i1> [[C0]], <4 x i1> [[C1]], <4 x i32> <i32 1, i32 3, i32 5, i32 7>
25; AVX2-NEXT:    [[R:%.*]] = sext <4 x i1> [[S]] to <4 x i32>
26; AVX2-NEXT:    ret <4 x i32> [[R]]
27;
28; AVX512-LABEL: define <4 x i32> @shuf_icmp_eq_v4i32(
29; AVX512-SAME: <4 x i32> [[X:%.*]], <4 x i32> [[Y:%.*]], <4 x i32> [[Z:%.*]], <4 x i32> [[W:%.*]]) #[[ATTR0:[0-9]+]] {
30; AVX512-NEXT:    [[TMP1:%.*]] = shufflevector <4 x i32> [[X]], <4 x i32> [[Z]], <4 x i32> <i32 1, i32 3, i32 5, i32 7>
31; AVX512-NEXT:    [[TMP2:%.*]] = shufflevector <4 x i32> [[Y]], <4 x i32> [[W]], <4 x i32> <i32 1, i32 3, i32 5, i32 7>
32; AVX512-NEXT:    [[S:%.*]] = icmp eq <4 x i32> [[TMP1]], [[TMP2]]
33; AVX512-NEXT:    [[R:%.*]] = sext <4 x i1> [[S]] to <4 x i32>
34; AVX512-NEXT:    ret <4 x i32> [[R]]
35;
36  %c0 = icmp eq <4 x i32> %x, %y
37  %c1 = icmp eq <4 x i32> %z, %w
38  %s = shufflevector <4 x i1> %c0, <4 x i1> %c1, <4 x i32> <i32 1, i32 3, i32 5, i32 7>
39  %r = sext <4 x i1> %s to <4 x i32>
40  ret <4 x i32> %r
41}
42
43; icmp - eq v2i64 is only cheap on SSE4+ targets with PCMPEQQ
44
45define <2 x i64> @shuf_icmp_eq_v2i64(<2 x i64> %x, <2 x i64> %y, <2 x i64> %z, <2 x i64> %w) {
46; SSE2-LABEL: define <2 x i64> @shuf_icmp_eq_v2i64(
47; SSE2-SAME: <2 x i64> [[X:%.*]], <2 x i64> [[Y:%.*]], <2 x i64> [[Z:%.*]], <2 x i64> [[W:%.*]]) #[[ATTR0]] {
48; SSE2-NEXT:    [[TMP1:%.*]] = shufflevector <2 x i64> [[X]], <2 x i64> [[Z]], <2 x i32> <i32 1, i32 3>
49; SSE2-NEXT:    [[TMP2:%.*]] = shufflevector <2 x i64> [[Y]], <2 x i64> [[W]], <2 x i32> <i32 1, i32 3>
50; SSE2-NEXT:    [[S:%.*]] = icmp eq <2 x i64> [[TMP1]], [[TMP2]]
51; SSE2-NEXT:    [[R:%.*]] = sext <2 x i1> [[S]] to <2 x i64>
52; SSE2-NEXT:    ret <2 x i64> [[R]]
53;
54; SSE4-LABEL: define <2 x i64> @shuf_icmp_eq_v2i64(
55; SSE4-SAME: <2 x i64> [[X:%.*]], <2 x i64> [[Y:%.*]], <2 x i64> [[Z:%.*]], <2 x i64> [[W:%.*]]) #[[ATTR0]] {
56; SSE4-NEXT:    [[C0:%.*]] = icmp eq <2 x i64> [[X]], [[Y]]
57; SSE4-NEXT:    [[C1:%.*]] = icmp eq <2 x i64> [[Z]], [[W]]
58; SSE4-NEXT:    [[S:%.*]] = shufflevector <2 x i1> [[C0]], <2 x i1> [[C1]], <2 x i32> <i32 1, i32 3>
59; SSE4-NEXT:    [[R:%.*]] = sext <2 x i1> [[S]] to <2 x i64>
60; SSE4-NEXT:    ret <2 x i64> [[R]]
61;
62; AVX2-LABEL: define <2 x i64> @shuf_icmp_eq_v2i64(
63; AVX2-SAME: <2 x i64> [[X:%.*]], <2 x i64> [[Y:%.*]], <2 x i64> [[Z:%.*]], <2 x i64> [[W:%.*]]) #[[ATTR0]] {
64; AVX2-NEXT:    [[C0:%.*]] = icmp eq <2 x i64> [[X]], [[Y]]
65; AVX2-NEXT:    [[C1:%.*]] = icmp eq <2 x i64> [[Z]], [[W]]
66; AVX2-NEXT:    [[S:%.*]] = shufflevector <2 x i1> [[C0]], <2 x i1> [[C1]], <2 x i32> <i32 1, i32 3>
67; AVX2-NEXT:    [[R:%.*]] = sext <2 x i1> [[S]] to <2 x i64>
68; AVX2-NEXT:    ret <2 x i64> [[R]]
69;
70; AVX512-LABEL: define <2 x i64> @shuf_icmp_eq_v2i64(
71; AVX512-SAME: <2 x i64> [[X:%.*]], <2 x i64> [[Y:%.*]], <2 x i64> [[Z:%.*]], <2 x i64> [[W:%.*]]) #[[ATTR0]] {
72; AVX512-NEXT:    [[TMP1:%.*]] = shufflevector <2 x i64> [[X]], <2 x i64> [[Z]], <2 x i32> <i32 1, i32 3>
73; AVX512-NEXT:    [[TMP2:%.*]] = shufflevector <2 x i64> [[Y]], <2 x i64> [[W]], <2 x i32> <i32 1, i32 3>
74; AVX512-NEXT:    [[S:%.*]] = icmp eq <2 x i64> [[TMP1]], [[TMP2]]
75; AVX512-NEXT:    [[R:%.*]] = sext <2 x i1> [[S]] to <2 x i64>
76; AVX512-NEXT:    ret <2 x i64> [[R]]
77;
78  %c0 = icmp eq <2 x i64> %x, %y
79  %c1 = icmp eq <2 x i64> %z, %w
80  %s = shufflevector <2 x i1> %c0, <2 x i1> %c1, <2 x i32> <i32 1, i32 3>
81  %r = sext <2 x i1> %s to <2 x i64>
82  ret <2 x i64> %r
83}
84
85; icmp - ugt v4i32 is expensive
86
87define <4 x i32> @shuf_icmp_ugt_v4i32(<4 x i32> %x, <4 x i32> %y, <4 x i32> %z, <4 x i32> %w) {
88; CHECK-LABEL: define <4 x i32> @shuf_icmp_ugt_v4i32(
89; CHECK-SAME: <4 x i32> [[X:%.*]], <4 x i32> [[Y:%.*]], <4 x i32> [[Z:%.*]], <4 x i32> [[W:%.*]]) #[[ATTR0:[0-9]+]] {
90; CHECK-NEXT:    [[TMP1:%.*]] = shufflevector <4 x i32> [[X]], <4 x i32> [[Z]], <4 x i32> <i32 1, i32 3, i32 5, i32 7>
91; CHECK-NEXT:    [[TMP2:%.*]] = shufflevector <4 x i32> [[Y]], <4 x i32> [[W]], <4 x i32> <i32 1, i32 3, i32 5, i32 7>
92; CHECK-NEXT:    [[S:%.*]] = icmp ugt <4 x i32> [[TMP1]], [[TMP2]]
93; CHECK-NEXT:    [[R:%.*]] = sext <4 x i1> [[S]] to <4 x i32>
94; CHECK-NEXT:    ret <4 x i32> [[R]]
95;
96  %c0 = icmp ugt <4 x i32> %x, %y
97  %c1 = icmp ugt <4 x i32> %z, %w
98  %s = shufflevector <4 x i1> %c0, <4 x i1> %c1, <4 x i32> <i32 1, i32 3, i32 5, i32 7>
99  %r = sext <4 x i1> %s to <4 x i32>
100  ret <4 x i32> %r
101}
102
103; Common operand is op0 of the fcmps (CMPPS cheaper on SSE4+).
104
105define <4 x i32> @shuf_fcmp_oeq_v4i32(<4 x float> %x, <4 x float> %y, <4 x float> %z) {
106; SSE2-LABEL: define <4 x i32> @shuf_fcmp_oeq_v4i32(
107; SSE2-SAME: <4 x float> [[X:%.*]], <4 x float> [[Y:%.*]], <4 x float> [[Z:%.*]]) #[[ATTR0]] {
108; SSE2-NEXT:    [[TMP1:%.*]] = shufflevector <4 x float> [[X]], <4 x float> poison, <4 x i32> <i32 poison, i32 poison, i32 0, i32 0>
109; SSE2-NEXT:    [[TMP2:%.*]] = shufflevector <4 x float> [[Y]], <4 x float> [[Z]], <4 x i32> <i32 poison, i32 poison, i32 4, i32 0>
110; SSE2-NEXT:    [[S:%.*]] = fcmp oeq <4 x float> [[TMP1]], [[TMP2]]
111; SSE2-NEXT:    [[R:%.*]] = sext <4 x i1> [[S]] to <4 x i32>
112; SSE2-NEXT:    ret <4 x i32> [[R]]
113;
114; SSE4-LABEL: define <4 x i32> @shuf_fcmp_oeq_v4i32(
115; SSE4-SAME: <4 x float> [[X:%.*]], <4 x float> [[Y:%.*]], <4 x float> [[Z:%.*]]) #[[ATTR0]] {
116; SSE4-NEXT:    [[B0:%.*]] = fcmp oeq <4 x float> [[X]], [[Y]]
117; SSE4-NEXT:    [[B1:%.*]] = fcmp oeq <4 x float> [[X]], [[Z]]
118; SSE4-NEXT:    [[S:%.*]] = shufflevector <4 x i1> [[B0]], <4 x i1> [[B1]], <4 x i32> <i32 poison, i32 poison, i32 4, i32 0>
119; SSE4-NEXT:    [[R:%.*]] = sext <4 x i1> [[S]] to <4 x i32>
120; SSE4-NEXT:    ret <4 x i32> [[R]]
121;
122; AVX2-LABEL: define <4 x i32> @shuf_fcmp_oeq_v4i32(
123; AVX2-SAME: <4 x float> [[X:%.*]], <4 x float> [[Y:%.*]], <4 x float> [[Z:%.*]]) #[[ATTR0]] {
124; AVX2-NEXT:    [[B0:%.*]] = fcmp oeq <4 x float> [[X]], [[Y]]
125; AVX2-NEXT:    [[B1:%.*]] = fcmp oeq <4 x float> [[X]], [[Z]]
126; AVX2-NEXT:    [[S:%.*]] = shufflevector <4 x i1> [[B0]], <4 x i1> [[B1]], <4 x i32> <i32 poison, i32 poison, i32 4, i32 0>
127; AVX2-NEXT:    [[R:%.*]] = sext <4 x i1> [[S]] to <4 x i32>
128; AVX2-NEXT:    ret <4 x i32> [[R]]
129;
130; AVX512-LABEL: define <4 x i32> @shuf_fcmp_oeq_v4i32(
131; AVX512-SAME: <4 x float> [[X:%.*]], <4 x float> [[Y:%.*]], <4 x float> [[Z:%.*]]) #[[ATTR0]] {
132; AVX512-NEXT:    [[TMP1:%.*]] = shufflevector <4 x float> [[X]], <4 x float> poison, <4 x i32> <i32 poison, i32 poison, i32 0, i32 0>
133; AVX512-NEXT:    [[TMP2:%.*]] = shufflevector <4 x float> [[Y]], <4 x float> [[Z]], <4 x i32> <i32 poison, i32 poison, i32 4, i32 0>
134; AVX512-NEXT:    [[S:%.*]] = fcmp oeq <4 x float> [[TMP1]], [[TMP2]]
135; AVX512-NEXT:    [[R:%.*]] = sext <4 x i1> [[S]] to <4 x i32>
136; AVX512-NEXT:    ret <4 x i32> [[R]]
137;
138  %b0 = fcmp oeq <4 x float> %x, %y
139  %b1 = fcmp oeq <4 x float> %x, %z
140  %s = shufflevector <4 x i1> %b0, <4 x i1> %b1, <4 x i32> <i32 poison, i32 poison, i32 4, i32 0>
141  %r = sext <4 x i1> %s to <4 x i32>
142  ret <4 x i32> %r
143}
144
145; For commutative instructions, common operand may be swapped
146
147define <4 x i32> @shuf_fcmp_one_v4f32_swap(<4 x float> %x, <4 x float> %y, <4 x float> %z) {
148; CHECK-LABEL: define <4 x i32> @shuf_fcmp_one_v4f32_swap(
149; CHECK-SAME: <4 x float> [[X:%.*]], <4 x float> [[Y:%.*]], <4 x float> [[Z:%.*]]) #[[ATTR0]] {
150; CHECK-NEXT:    [[TMP1:%.*]] = shufflevector <4 x float> [[Y]], <4 x float> [[Z]], <4 x i32> <i32 0, i32 3, i32 4, i32 7>
151; CHECK-NEXT:    [[TMP2:%.*]] = shufflevector <4 x float> [[X]], <4 x float> poison, <4 x i32> <i32 0, i32 3, i32 0, i32 3>
152; CHECK-NEXT:    [[S:%.*]] = fcmp one <4 x float> [[TMP1]], [[TMP2]]
153; CHECK-NEXT:    [[R:%.*]] = sext <4 x i1> [[S]] to <4 x i32>
154; CHECK-NEXT:    ret <4 x i32> [[R]]
155;
156  %b0 = fcmp one <4 x float> %x, %y
157  %b1 = fcmp one <4 x float> %z, %x
158  %s = shufflevector <4 x i1> %b0, <4 x i1> %b1, <4 x i32> <i32 0, i32 3, i32 4, i32 7>
159  %r = sext <4 x i1> %s to <4 x i32>
160  ret <4 x i32> %r
161}
162
163; non-commutative pred, but common op0
164
165define <4 x i32> @shuf_icmp_sgt_v4i32_swap(<4 x i32> %x, <4 x i32> %y, <4 x i32> %z) {
166; SSE-LABEL: define <4 x i32> @shuf_icmp_sgt_v4i32_swap(
167; SSE-SAME: <4 x i32> [[X:%.*]], <4 x i32> [[Y:%.*]], <4 x i32> [[Z:%.*]]) #[[ATTR0]] {
168; SSE-NEXT:    [[B0:%.*]] = icmp sgt <4 x i32> [[X]], [[Y]]
169; SSE-NEXT:    [[B1:%.*]] = icmp sgt <4 x i32> [[X]], [[Z]]
170; SSE-NEXT:    [[S:%.*]] = shufflevector <4 x i1> [[B0]], <4 x i1> [[B1]], <4 x i32> <i32 3, i32 1, i32 1, i32 6>
171; SSE-NEXT:    [[R:%.*]] = sext <4 x i1> [[S]] to <4 x i32>
172; SSE-NEXT:    ret <4 x i32> [[R]]
173;
174; AVX2-LABEL: define <4 x i32> @shuf_icmp_sgt_v4i32_swap(
175; AVX2-SAME: <4 x i32> [[X:%.*]], <4 x i32> [[Y:%.*]], <4 x i32> [[Z:%.*]]) #[[ATTR0]] {
176; AVX2-NEXT:    [[B0:%.*]] = icmp sgt <4 x i32> [[X]], [[Y]]
177; AVX2-NEXT:    [[B1:%.*]] = icmp sgt <4 x i32> [[X]], [[Z]]
178; AVX2-NEXT:    [[S:%.*]] = shufflevector <4 x i1> [[B0]], <4 x i1> [[B1]], <4 x i32> <i32 3, i32 1, i32 1, i32 6>
179; AVX2-NEXT:    [[R:%.*]] = sext <4 x i1> [[S]] to <4 x i32>
180; AVX2-NEXT:    ret <4 x i32> [[R]]
181;
182; AVX512-LABEL: define <4 x i32> @shuf_icmp_sgt_v4i32_swap(
183; AVX512-SAME: <4 x i32> [[X:%.*]], <4 x i32> [[Y:%.*]], <4 x i32> [[Z:%.*]]) #[[ATTR0]] {
184; AVX512-NEXT:    [[TMP1:%.*]] = shufflevector <4 x i32> [[X]], <4 x i32> poison, <4 x i32> <i32 3, i32 1, i32 1, i32 2>
185; AVX512-NEXT:    [[TMP2:%.*]] = shufflevector <4 x i32> [[Y]], <4 x i32> [[Z]], <4 x i32> <i32 3, i32 1, i32 1, i32 6>
186; AVX512-NEXT:    [[S:%.*]] = icmp sgt <4 x i32> [[TMP1]], [[TMP2]]
187; AVX512-NEXT:    [[R:%.*]] = sext <4 x i1> [[S]] to <4 x i32>
188; AVX512-NEXT:    ret <4 x i32> [[R]]
189;
190  %b0 = icmp sgt <4 x i32> %x, %y
191  %b1 = icmp sgt <4 x i32> %x, %z
192  %s = shufflevector <4 x i1> %b0, <4 x i1> %b1, <4 x i32> <i32 3, i32 1, i32 1, i32 6>
193  %r = sext <4 x i1> %s to <4 x i32>
194  ret <4 x i32> %r
195}
196
197; negative test - mismatched opcodes
198
199define <2 x i64> @shuf_icmp_fcmp_v2i64_mismatch_opcode(<2 x i64> %x, <2 x i64> %y, <2 x double> %z, <2 x double> %w) {
200; CHECK-LABEL: define <2 x i64> @shuf_icmp_fcmp_v2i64_mismatch_opcode(
201; CHECK-SAME: <2 x i64> [[X:%.*]], <2 x i64> [[Y:%.*]], <2 x double> [[Z:%.*]], <2 x double> [[W:%.*]]) #[[ATTR0]] {
202; CHECK-NEXT:    [[B0:%.*]] = icmp eq <2 x i64> [[X]], [[Y]]
203; CHECK-NEXT:    [[B1:%.*]] = fcmp oeq <2 x double> [[Z]], [[W]]
204; CHECK-NEXT:    [[S:%.*]] = shufflevector <2 x i1> [[B0]], <2 x i1> [[B1]], <2 x i32> <i32 3, i32 0>
205; CHECK-NEXT:    [[R:%.*]] = sext <2 x i1> [[S]] to <2 x i64>
206; CHECK-NEXT:    ret <2 x i64> [[R]]
207;
208  %b0 = icmp eq <2 x i64> %x, %y
209  %b1 = fcmp oeq <2 x double> %z, %w
210  %s = shufflevector <2 x i1> %b0, <2 x i1> %b1, <2 x i32> <i32 3, i32 0>
211  %r = sext <2 x i1> %s to <2 x i64>
212  ret <2 x i64> %r
213}
214
215; negative test - mismatched predicates
216
217define <2 x i64> @shuf_icmp_eq_sgt_v2i64_mismatch_predicate(<2 x i64> %x, <2 x i64> %y, <2 x i64> %z) {
218; CHECK-LABEL: define <2 x i64> @shuf_icmp_eq_sgt_v2i64_mismatch_predicate(
219; CHECK-SAME: <2 x i64> [[X:%.*]], <2 x i64> [[Y:%.*]], <2 x i64> [[Z:%.*]]) #[[ATTR0]] {
220; CHECK-NEXT:    [[B0:%.*]] = icmp eq <2 x i64> [[X]], [[Y]]
221; CHECK-NEXT:    [[B1:%.*]] = icmp sgt <2 x i64> [[Z]], [[Y]]
222; CHECK-NEXT:    [[S:%.*]] = shufflevector <2 x i1> [[B0]], <2 x i1> [[B1]], <2 x i32> <i32 3, i32 0>
223; CHECK-NEXT:    [[R:%.*]] = sext <2 x i1> [[S]] to <2 x i64>
224; CHECK-NEXT:    ret <2 x i64> [[R]]
225;
226  %b0 = icmp eq <2 x i64> %x, %y
227  %b1 = icmp sgt <2 x i64> %z, %y
228  %s = shufflevector <2 x i1> %b0, <2 x i1> %b1, <2 x i32> <i32 3, i32 0>
229  %r = sext <2 x i1> %s to <2 x i64>
230  ret <2 x i64> %r
231}
232
233; negative test - mismatched types
234
235define <4 x i32> @shuf_icmp_eq_v4i64_v4i32_mismatch_type(<4 x i64> %x, <4 x i64> %y, <4 x i32> %z, <4 x i32> %w) {
236; CHECK-LABEL: define <4 x i32> @shuf_icmp_eq_v4i64_v4i32_mismatch_type(
237; CHECK-SAME: <4 x i64> [[X:%.*]], <4 x i64> [[Y:%.*]], <4 x i32> [[Z:%.*]], <4 x i32> [[W:%.*]]) #[[ATTR0]] {
238; CHECK-NEXT:    [[B0:%.*]] = icmp eq <4 x i64> [[X]], [[Y]]
239; CHECK-NEXT:    [[B1:%.*]] = icmp eq <4 x i32> [[Z]], [[W]]
240; CHECK-NEXT:    [[S:%.*]] = shufflevector <4 x i1> [[B0]], <4 x i1> [[B1]], <4 x i32> <i32 3, i32 1, i32 1, i32 6>
241; CHECK-NEXT:    [[R:%.*]] = sext <4 x i1> [[S]] to <4 x i32>
242; CHECK-NEXT:    ret <4 x i32> [[R]]
243;
244  %b0 = icmp eq <4 x i64> %x, %y
245  %b1 = icmp eq <4 x i32> %z, %w
246  %s = shufflevector <4 x i1> %b0, <4 x i1> %b1, <4 x i32> <i32 3, i32 1, i32 1, i32 6>
247  %r = sext <4 x i1> %s to <4 x i32>
248  ret <4 x i32> %r
249}
250
251; negative test - uses
252
253define <4 x i32> @shuf_icmp_ugt_v4i32_use(<4 x i32> %x, <4 x i32> %y, <4 x i32> %z, <4 x i32> %w) {
254; CHECK-LABEL: define <4 x i32> @shuf_icmp_ugt_v4i32_use(
255; CHECK-SAME: <4 x i32> [[X:%.*]], <4 x i32> [[Y:%.*]], <4 x i32> [[Z:%.*]], <4 x i32> [[W:%.*]]) #[[ATTR0]] {
256; CHECK-NEXT:    [[C0:%.*]] = icmp ugt <4 x i32> [[X]], [[Y]]
257; CHECK-NEXT:    [[C1:%.*]] = icmp ugt <4 x i32> [[Z]], [[W]]
258; CHECK-NEXT:    call void @use(<4 x i1> [[C0]])
259; CHECK-NEXT:    [[S:%.*]] = shufflevector <4 x i1> [[C0]], <4 x i1> [[C1]], <4 x i32> <i32 1, i32 3, i32 5, i32 7>
260; CHECK-NEXT:    [[R:%.*]] = sext <4 x i1> [[S]] to <4 x i32>
261; CHECK-NEXT:    ret <4 x i32> [[R]]
262;
263  %c0 = icmp ugt <4 x i32> %x, %y
264  %c1 = icmp ugt <4 x i32> %z, %w
265  call void @use(<4 x i1> %c0)
266  %s = shufflevector <4 x i1> %c0, <4 x i1> %c1, <4 x i32> <i32 1, i32 3, i32 5, i32 7>
267  %r = sext <4 x i1> %s to <4 x i32>
268  ret <4 x i32> %r
269}
270
271; PR121110 - don't merge equivalent (but not matching) predicates
272
273define <2 x i1> @PR121110() {
274; CHECK-LABEL: define <2 x i1> @PR121110(
275; CHECK-SAME: ) #[[ATTR0]] {
276; CHECK-NEXT:    [[UGT:%.*]] = icmp samesign ugt <2 x i32> zeroinitializer, zeroinitializer
277; CHECK-NEXT:    [[SGT:%.*]] = icmp sgt <2 x i32> zeroinitializer, <i32 6, i32 -4>
278; CHECK-NEXT:    [[RES:%.*]] = shufflevector <2 x i1> [[UGT]], <2 x i1> [[SGT]], <2 x i32> <i32 0, i32 3>
279; CHECK-NEXT:    ret <2 x i1> [[RES]]
280;
281  %ugt = icmp samesign ugt <2 x i32> < i32 0, i32 0 >, < i32 0, i32 0 >
282  %sgt = icmp sgt <2 x i32> < i32 0, i32 0 >, < i32 6, i32 4294967292 >
283  %res = shufflevector <2 x i1> %ugt, <2 x i1> %sgt, <2 x i32> <i32 0, i32 3>
284  ret <2 x i1> %res
285}
286
287define <2 x i1> @PR121110_commute() {
288; CHECK-LABEL: define <2 x i1> @PR121110_commute(
289; CHECK-SAME: ) #[[ATTR0]] {
290; CHECK-NEXT:    [[SGT:%.*]] = icmp sgt <2 x i32> zeroinitializer, <i32 6, i32 -4>
291; CHECK-NEXT:    [[UGT:%.*]] = icmp samesign ugt <2 x i32> zeroinitializer, zeroinitializer
292; CHECK-NEXT:    [[RES:%.*]] = shufflevector <2 x i1> [[SGT]], <2 x i1> [[UGT]], <2 x i32> <i32 0, i32 3>
293; CHECK-NEXT:    ret <2 x i1> [[RES]]
294;
295  %sgt = icmp sgt <2 x i32> < i32 0, i32 0 >, < i32 6, i32 4294967292 >
296  %ugt = icmp samesign ugt <2 x i32> < i32 0, i32 0 >, < i32 0, i32 0 >
297  %res = shufflevector <2 x i1> %sgt, <2 x i1> %ugt, <2 x i32> <i32 0, i32 3>
298  ret <2 x i1> %res
299}
300