1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2; RUN: opt -instcombine -S < %s | FileCheck %s
3
4define float @foo1(float %a) {
5; CHECK-LABEL: @foo1(
6; CHECK-NEXT:    [[B:%.*]] = fcmp ogt float [[A:%.*]], 0.000000e+00
7; CHECK-NEXT:    [[C:%.*]] = select i1 [[B]], float [[A]], float 0.000000e+00
8; CHECK-NEXT:    [[D:%.*]] = fcmp olt float [[C]], 1.000000e+00
9; CHECK-NEXT:    [[F:%.*]] = select i1 [[D]], float [[C]], float 1.000000e+00
10; CHECK-NEXT:    ret float [[F]]
11;
12  %b = fcmp ogt float %a, 0.0
13  %c = select i1 %b, float %a, float 0.0
14  %d = fcmp olt float %c, 1.0
15  %f = select i1 %d, float %c, float 1.0
16  ret float %f
17}
18
19define float @foo2(float %a) {
20; CHECK-LABEL: @foo2(
21; CHECK-NEXT:    [[B:%.*]] = fcmp ogt float [[A:%.*]], 0.000000e+00
22; CHECK-NEXT:    [[C:%.*]] = select i1 [[B]], float [[A]], float 0.000000e+00
23; CHECK-NEXT:    [[D:%.*]] = fcmp olt float [[C]], 1.000000e+00
24; CHECK-NEXT:    [[E:%.*]] = select i1 [[B]], float [[A]], float 0.000000e+00
25; CHECK-NEXT:    [[F:%.*]] = select i1 [[D]], float [[E]], float 1.000000e+00
26; CHECK-NEXT:    ret float [[F]]
27;
28  %b = fcmp ogt float %a, 0.0
29  %c = select i1 %b, float %a, float 0.0
30  %d = fcmp olt float %c, 1.0
31  %e = select i1 %b, float %a, float 0.0
32  %f = select i1 %d, float %e, float 1.0
33  ret float %f
34}
35
36define <2 x i32> @foo3(<2 x i1> %vec_bool, i1 %bool, <2 x i32> %V) {
37; CHECK-LABEL: @foo3(
38; CHECK-NEXT:    [[SEL0:%.*]] = select <2 x i1> [[VEC_BOOL:%.*]], <2 x i32> zeroinitializer, <2 x i32> [[V:%.*]]
39; CHECK-NEXT:    [[SEL1:%.*]] = select i1 [[BOOL:%.*]], <2 x i32> [[SEL0]], <2 x i32> [[V]]
40; CHECK-NEXT:    ret <2 x i32> [[SEL1]]
41;
42  %sel0 = select <2 x i1> %vec_bool, <2 x i32> zeroinitializer, <2 x i32> %V
43  %sel1 = select i1 %bool, <2 x i32> %sel0, <2 x i32> %V
44  ret <2 x i32> %sel1
45}
46
47; Four variations of (select (select-shuffle)) with a common operand.
48
49define <4 x i8> @sel_shuf_commute0(<4 x i8> %x, <4 x i8> %y, <4 x i1> %cmp) {
50; CHECK-LABEL: @sel_shuf_commute0(
51; CHECK-NEXT:    [[SEL:%.*]] = select <4 x i1> [[CMP:%.*]], <4 x i8> [[Y:%.*]], <4 x i8> [[X:%.*]]
52; CHECK-NEXT:    [[R:%.*]] = shufflevector <4 x i8> [[X]], <4 x i8> [[SEL]], <4 x i32> <i32 0, i32 5, i32 2, i32 7>
53; CHECK-NEXT:    ret <4 x i8> [[R]]
54;
55  %blend = shufflevector <4 x i8> %x, <4 x i8> %y, <4 x i32> <i32 0, i32 5, i32 2, i32 7>
56  %r = select <4 x i1> %cmp, <4 x i8> %blend, <4 x i8> %x
57  ret <4 x i8> %r
58}
59
60; Weird types are ok.
61
62define <5 x i9> @sel_shuf_commute1(<5 x i9> %x, <5 x i9> %y, <5 x i1> %cmp) {
63; CHECK-LABEL: @sel_shuf_commute1(
64; CHECK-NEXT:    [[SEL:%.*]] = select <5 x i1> [[CMP:%.*]], <5 x i9> [[X:%.*]], <5 x i9> [[Y:%.*]]
65; CHECK-NEXT:    [[R:%.*]] = shufflevector <5 x i9> [[SEL]], <5 x i9> [[Y]], <5 x i32> <i32 0, i32 6, i32 2, i32 8, i32 9>
66; CHECK-NEXT:    ret <5 x i9> [[R]]
67;
68  %blend = shufflevector <5 x i9> %x, <5 x i9> %y, <5 x i32> <i32 0, i32 6, i32 2, i32 8, i32 9>
69  %r = select <5 x i1> %cmp, <5 x i9> %blend, <5 x i9> %y
70  ret <5 x i9> %r
71}
72
73define <4 x float> @sel_shuf_commute2(<4 x float> %x, <4 x float> %y, <4 x i1> %cmp) {
74; CHECK-LABEL: @sel_shuf_commute2(
75; CHECK-NEXT:    [[SEL:%.*]] = select <4 x i1> [[CMP:%.*]], <4 x float> [[X:%.*]], <4 x float> [[Y:%.*]]
76; CHECK-NEXT:    [[R:%.*]] = shufflevector <4 x float> [[X]], <4 x float> [[SEL]], <4 x i32> <i32 0, i32 1, i32 2, i32 7>
77; CHECK-NEXT:    ret <4 x float> [[R]]
78;
79  %blend = shufflevector <4 x float> %x, <4 x float> %y, <4 x i32> <i32 0, i32 1, i32 2, i32 7>
80  %r = select <4 x i1> %cmp, <4 x float> %x, <4 x float> %blend
81  ret <4 x float> %r
82}
83
84; Scalar condition is ok.
85
86define <4 x i8> @sel_shuf_commute3(<4 x i8> %x, <4 x i8> %y, i1 %cmp) {
87; CHECK-LABEL: @sel_shuf_commute3(
88; CHECK-NEXT:    [[SEL:%.*]] = select i1 [[CMP:%.*]], <4 x i8> [[Y:%.*]], <4 x i8> [[X:%.*]]
89; CHECK-NEXT:    [[R:%.*]] = shufflevector <4 x i8> [[SEL]], <4 x i8> [[Y]], <4 x i32> <i32 0, i32 5, i32 2, i32 3>
90; CHECK-NEXT:    ret <4 x i8> [[R]]
91;
92  %blend = shufflevector <4 x i8> %x, <4 x i8> %y, <4 x i32> <i32 0, i32 5, i32 2, i32 3>
93  %r = select i1 %cmp, <4 x i8> %y, <4 x i8> %blend
94  ret <4 x i8> %r
95}
96
97declare void @use(<4 x i8>)
98
99; Negative test - extra use would require another instruction.
100
101define <4 x i8> @sel_shuf_use(<4 x i8> %x, <4 x i8> %y, <4 x i1> %cmp) {
102; CHECK-LABEL: @sel_shuf_use(
103; CHECK-NEXT:    [[BLEND:%.*]] = shufflevector <4 x i8> [[X:%.*]], <4 x i8> [[Y:%.*]], <4 x i32> <i32 0, i32 5, i32 2, i32 7>
104; CHECK-NEXT:    call void @use(<4 x i8> [[BLEND]])
105; CHECK-NEXT:    [[R:%.*]] = select <4 x i1> [[CMP:%.*]], <4 x i8> [[BLEND]], <4 x i8> [[X]]
106; CHECK-NEXT:    ret <4 x i8> [[R]]
107;
108  %blend = shufflevector <4 x i8> %x, <4 x i8> %y, <4 x i32> <i32 0, i32 5, i32 2, i32 7>
109  call void @use(<4 x i8> %blend)
110  %r = select <4 x i1> %cmp, <4 x i8> %blend, <4 x i8> %x
111  ret <4 x i8> %r
112}
113
114; Negative test - undef in shuffle mask prevents transform.
115
116define <4 x i8> @sel_shuf_undef(<4 x i8> %x, <4 x i8> %y, <4 x i1> %cmp) {
117; CHECK-LABEL: @sel_shuf_undef(
118; CHECK-NEXT:    [[BLEND:%.*]] = shufflevector <4 x i8> [[X:%.*]], <4 x i8> [[Y:%.*]], <4 x i32> <i32 0, i32 5, i32 2, i32 undef>
119; CHECK-NEXT:    [[R:%.*]] = select <4 x i1> [[CMP:%.*]], <4 x i8> [[BLEND]], <4 x i8> [[Y]]
120; CHECK-NEXT:    ret <4 x i8> [[R]]
121;
122  %blend = shufflevector <4 x i8> %x, <4 x i8> %y, <4 x i32> <i32 0, i32 5, i32 2, i32 undef>
123  %r = select <4 x i1> %cmp, <4 x i8> %blend, <4 x i8> %y
124  ret <4 x i8> %r
125}
126
127; Negative test - not a "select shuffle"
128
129define <4 x i8> @sel_shuf_not(<4 x i8> %x, <4 x i8> %y, <4 x i1> %cmp) {
130; CHECK-LABEL: @sel_shuf_not(
131; CHECK-NEXT:    [[NOTBLEND:%.*]] = shufflevector <4 x i8> [[X:%.*]], <4 x i8> [[Y:%.*]], <4 x i32> <i32 0, i32 5, i32 2, i32 6>
132; CHECK-NEXT:    [[R:%.*]] = select <4 x i1> [[CMP:%.*]], <4 x i8> [[NOTBLEND]], <4 x i8> [[Y]]
133; CHECK-NEXT:    ret <4 x i8> [[R]]
134;
135  %notblend = shufflevector <4 x i8> %x, <4 x i8> %y, <4 x i32> <i32 0, i32 5, i32 2, i32 6>
136  %r = select <4 x i1> %cmp, <4 x i8> %notblend, <4 x i8> %y
137  ret <4 x i8> %r
138}
139
140; Negative test - must shuffle one of the select operands
141
142define <4 x i8> @sel_shuf_no_common_operand(<4 x i8> %x, <4 x i8> %y, <4 x i1> %cmp, <4 x i8> %z) {
143; CHECK-LABEL: @sel_shuf_no_common_operand(
144; CHECK-NEXT:    [[BLEND:%.*]] = shufflevector <4 x i8> [[X:%.*]], <4 x i8> [[Y:%.*]], <4 x i32> <i32 0, i32 5, i32 2, i32 3>
145; CHECK-NEXT:    [[R:%.*]] = select <4 x i1> [[CMP:%.*]], <4 x i8> [[Z:%.*]], <4 x i8> [[BLEND]]
146; CHECK-NEXT:    ret <4 x i8> [[R]]
147;
148  %blend = shufflevector <4 x i8> %x, <4 x i8> %y, <4 x i32> <i32 0, i32 5, i32 2, i32 3>
149  %r = select <4 x i1> %cmp, <4 x i8> %z, <4 x i8> %blend
150  ret <4 x i8> %r
151}
152
153; Negative test - don't crash (this is not a select shuffle because it changes vector length)
154
155define <2 x i8> @sel_shuf_narrowing_commute1(<4 x i8> %x, <4 x i8> %y, <2 x i8> %x2, <2 x i1> %cmp) {
156; CHECK-LABEL: @sel_shuf_narrowing_commute1(
157; CHECK-NEXT:    [[BLEND:%.*]] = shufflevector <4 x i8> [[X:%.*]], <4 x i8> [[Y:%.*]], <2 x i32> <i32 0, i32 5>
158; CHECK-NEXT:    [[R:%.*]] = select <2 x i1> [[CMP:%.*]], <2 x i8> [[BLEND]], <2 x i8> [[X2:%.*]]
159; CHECK-NEXT:    ret <2 x i8> [[R]]
160;
161  %blend = shufflevector <4 x i8> %x, <4 x i8> %y, <2 x i32> <i32 0, i32 5>
162  %r = select <2 x i1> %cmp, <2 x i8> %blend, <2 x i8> %x2
163  ret <2 x i8> %r
164}
165
166; Negative test - don't crash (this is not a select shuffle because it changes vector length)
167
168define <2 x i8> @sel_shuf_narrowing_commute2(<4 x i8> %x, <4 x i8> %y, <2 x i8> %x2, <2 x i1> %cmp) {
169; CHECK-LABEL: @sel_shuf_narrowing_commute2(
170; CHECK-NEXT:    [[BLEND:%.*]] = shufflevector <4 x i8> [[X:%.*]], <4 x i8> [[Y:%.*]], <2 x i32> <i32 0, i32 5>
171; CHECK-NEXT:    [[R:%.*]] = select <2 x i1> [[CMP:%.*]], <2 x i8> [[X2:%.*]], <2 x i8> [[BLEND]]
172; CHECK-NEXT:    ret <2 x i8> [[R]]
173;
174  %blend = shufflevector <4 x i8> %x, <4 x i8> %y, <2 x i32> <i32 0, i32 5>
175  %r = select <2 x i1> %cmp, <2 x i8> %x2, <2 x i8> %blend
176  ret <2 x i8> %r
177}
178