xref: /llvm-project/llvm/test/Transforms/InstCombine/shufflevec-bitcast.ll (revision a5f34155339b4c01357462da95aac62291ed7ec8)
1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2; RUN: opt < %s -passes=instcombine -S | FileCheck %s
3
4declare void @use(<4 x i16>)
5
6define void @test(<16 x i8> %w, ptr %o1, ptr %o2) {
7; CHECK-LABEL: @test(
8; CHECK-NEXT:    [[V_BC:%.*]] = bitcast <16 x i8> [[W:%.*]] to <4 x i32>
9; CHECK-NEXT:    [[V_EXTRACT:%.*]] = extractelement <4 x i32> [[V_BC]], i64 3
10; CHECK-NEXT:    [[V_BC1:%.*]] = bitcast <16 x i8> [[W]] to <4 x float>
11; CHECK-NEXT:    [[V_EXTRACT2:%.*]] = extractelement <4 x float> [[V_BC1]], i64 3
12; CHECK-NEXT:    store i32 [[V_EXTRACT]], ptr [[O1:%.*]], align 4
13; CHECK-NEXT:    store float [[V_EXTRACT2]], ptr [[O2:%.*]], align 4
14; CHECK-NEXT:    ret void
15;
16  %v = shufflevector <16 x i8> %w, <16 x i8> undef, <4 x i32> <i32 12, i32 13, i32 14, i32 15>
17  %f = bitcast <4 x i8> %v to float
18  %i = bitcast <4 x i8> %v to i32
19  store i32 %i, ptr %o1, align 4
20  store float %f, ptr %o2, align 4
21  ret void
22}
23
24; Shuffle-of-bitcast-splat --> splat-bitcast
25
26define <4 x i16> @splat_bitcast_operand(<8 x i8> %x) {
27; CHECK-LABEL: @splat_bitcast_operand(
28; CHECK-NEXT:    [[S1:%.*]] = shufflevector <8 x i8> [[X:%.*]], <8 x i8> poison, <8 x i32> <i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1>
29; CHECK-NEXT:    [[S2:%.*]] = bitcast <8 x i8> [[S1]] to <4 x i16>
30; CHECK-NEXT:    ret <4 x i16> [[S2]]
31;
32  %s1 = shufflevector <8 x i8> %x, <8 x i8> undef, <8 x i32> <i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1>
33  %bc = bitcast <8 x i8> %s1 to <4 x i16>
34  %s2 = shufflevector <4 x i16> %bc, <4 x i16> undef, <4 x i32> <i32 0, i32 2, i32 1, i32 0>
35  ret <4 x i16> %s2
36}
37
38; Shuffle-of-bitcast-splat --> splat-bitcast
39
40define <4 x i16> @splat_bitcast_operand_uses(<8 x i8> %x) {
41; CHECK-LABEL: @splat_bitcast_operand_uses(
42; CHECK-NEXT:    [[S1:%.*]] = shufflevector <8 x i8> [[X:%.*]], <8 x i8> poison, <8 x i32> <i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1>
43; CHECK-NEXT:    [[BC:%.*]] = bitcast <8 x i8> [[S1]] to <4 x i16>
44; CHECK-NEXT:    call void @use(<4 x i16> [[BC]])
45; CHECK-NEXT:    [[S2:%.*]] = bitcast <8 x i8> [[S1]] to <4 x i16>
46; CHECK-NEXT:    ret <4 x i16> [[S2]]
47;
48  %s1 = shufflevector <8 x i8> %x, <8 x i8> undef, <8 x i32> <i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1>
49  %bc = bitcast <8 x i8> %s1 to <4 x i16>
50  call void @use(<4 x i16> %bc)
51  %s2 = shufflevector <4 x i16> %bc, <4 x i16> undef, <4 x i32> <i32 0, i32 2, i32 1, i32 0>
52  ret <4 x i16> %s2
53}
54
55; Shuffle-of-bitcast-splat --> splat-bitcast
56
57define <4 x i32> @splat_bitcast_operand_same_size_src_elt(<4 x float> %x) {
58; CHECK-LABEL: @splat_bitcast_operand_same_size_src_elt(
59; CHECK-NEXT:    [[TMP1:%.*]] = bitcast <4 x float> [[X:%.*]] to <4 x i32>
60; CHECK-NEXT:    [[BC:%.*]] = shufflevector <4 x i32> [[TMP1]], <4 x i32> poison, <4 x i32> <i32 2, i32 2, i32 2, i32 2>
61; CHECK-NEXT:    ret <4 x i32> [[BC]]
62;
63  %s1 = shufflevector <4 x float> %x, <4 x float> undef, <4 x i32> <i32 2, i32 2, i32 2, i32 2>
64  %bc = bitcast <4 x float> %s1 to <4 x i32>
65  %s2 = shufflevector <4 x i32> %bc, <4 x i32> undef, <4 x i32> <i32 0, i32 2, i32 1, i32 0>
66  ret <4 x i32> %s2
67}
68
69; Scaled mask is inverse of first mask.
70
71define <4 x i32> @shuf_bitcast_operand(<16 x i8> %x) {
72; CHECK-LABEL: @shuf_bitcast_operand(
73; CHECK-NEXT:    [[S2:%.*]] = bitcast <16 x i8> [[X:%.*]] to <4 x i32>
74; CHECK-NEXT:    ret <4 x i32> [[S2]]
75;
76  %s1 = shufflevector <16 x i8> %x, <16 x i8> undef, <16 x i32> <i32 12, i32 13, i32 14, i32 15, i32 8, i32 9, i32 10, i32 11, i32 4, i32 5, i32 6, i32 7, i32 0, i32 1, i32 2, i32 3>
77  %bc = bitcast <16 x i8> %s1 to <4 x i32>
78  %s2 = shufflevector <4 x i32> %bc, <4 x i32> undef, <4 x i32> <i32 3, i32 2, i32 1, i32 0>
79  ret <4 x i32> %s2
80}
81
82; TODO: Could allow fold for length-changing shuffles.
83
84define <5 x i16> @splat_bitcast_operand_change_type(<8 x i8> %x) {
85; CHECK-LABEL: @splat_bitcast_operand_change_type(
86; CHECK-NEXT:    [[S1:%.*]] = shufflevector <8 x i8> [[X:%.*]], <8 x i8> poison, <8 x i32> <i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1>
87; CHECK-NEXT:    [[BC:%.*]] = bitcast <8 x i8> [[S1]] to <4 x i16>
88; CHECK-NEXT:    [[S2:%.*]] = shufflevector <4 x i16> [[BC]], <4 x i16> poison, <5 x i32> <i32 0, i32 2, i32 1, i32 0, i32 3>
89; CHECK-NEXT:    ret <5 x i16> [[S2]]
90;
91  %s1 = shufflevector <8 x i8> %x, <8 x i8> undef, <8 x i32> <i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1>
92  %bc = bitcast <8 x i8> %s1 to <4 x i16>
93  %s2 = shufflevector <4 x i16> %bc, <4 x i16> undef, <5 x i32> <i32 0, i32 2, i32 1, i32 0, i32 3>
94  ret <5 x i16> %s2
95}
96
97; Shuffle-of-bitcast-splat --> splat-bitcast
98
99define <4 x i16> @splat_bitcast_operand_wider_src_elt(<2 x i32> %x) {
100; CHECK-LABEL: @splat_bitcast_operand_wider_src_elt(
101; CHECK-NEXT:    [[S1:%.*]] = shufflevector <2 x i32> [[X:%.*]], <2 x i32> poison, <2 x i32> <i32 1, i32 1>
102; CHECK-NEXT:    [[S2:%.*]] = bitcast <2 x i32> [[S1]] to <4 x i16>
103; CHECK-NEXT:    ret <4 x i16> [[S2]]
104;
105  %s1 = shufflevector <2 x i32> %x, <2 x i32> undef, <2 x i32> <i32 1, i32 1>
106  %bc = bitcast <2 x i32> %s1 to <4 x i16>
107  %s2 = shufflevector <4 x i16> %bc, <4 x i16> undef, <4 x i32> <i32 0, i32 1, i32 0, i32 1>
108  ret <4 x i16> %s2
109}
110
111; Shuffle-of-bitcast-splat --> splat-bitcast
112
113define <4 x i16> @splat_bitcast_operand_wider_src_elt_uses(<2 x i32> %x) {
114; CHECK-LABEL: @splat_bitcast_operand_wider_src_elt_uses(
115; CHECK-NEXT:    [[S1:%.*]] = shufflevector <2 x i32> [[X:%.*]], <2 x i32> poison, <2 x i32> <i32 1, i32 1>
116; CHECK-NEXT:    [[BC:%.*]] = bitcast <2 x i32> [[S1]] to <4 x i16>
117; CHECK-NEXT:    call void @use(<4 x i16> [[BC]])
118; CHECK-NEXT:    [[S2:%.*]] = bitcast <2 x i32> [[S1]] to <4 x i16>
119; CHECK-NEXT:    ret <4 x i16> [[S2]]
120;
121  %s1 = shufflevector <2 x i32> %x, <2 x i32> undef, <2 x i32> <i32 1, i32 1>
122  %bc = bitcast <2 x i32> %s1 to <4 x i16>
123  call void @use(<4 x i16> %bc)
124  %s2 = shufflevector <4 x i16> %bc, <4 x i16> undef, <4 x i32> <i32 0, i32 1, i32 0, i32 1>
125  ret <4 x i16> %s2
126}
127
128; Scaled mask is inverse of first mask.
129
130define <16 x i8> @shuf_bitcast_operand_wider_src(<4 x i32> %x) {
131; CHECK-LABEL: @shuf_bitcast_operand_wider_src(
132; CHECK-NEXT:    [[S2:%.*]] = bitcast <4 x i32> [[X:%.*]] to <16 x i8>
133; CHECK-NEXT:    ret <16 x i8> [[S2]]
134;
135  %s1 = shufflevector <4 x i32> %x, <4 x i32> undef, <4 x i32> <i32 3, i32 2, i32 1, i32 0>
136  %bc = bitcast <4 x i32> %s1 to <16 x i8>
137  %s2 = shufflevector <16 x i8> %bc, <16 x i8> undef, <16 x i32> <i32 12, i32 13, i32 14, i32 15, i32 8, i32 9, i32 10, i32 11, i32 4, i32 5, i32 6, i32 7, i32 0, i32 1, i32 2, i32 3>
138  ret <16 x i8> %s2
139}
140
141; Negative test - the 2nd mask can't be widened
142
143define <16 x i8> @shuf_bitcast_operand_cannot_widen(<4 x i32> %x) {
144; CHECK-LABEL: @shuf_bitcast_operand_cannot_widen(
145; CHECK-NEXT:    [[S1:%.*]] = shufflevector <4 x i32> [[X:%.*]], <4 x i32> poison, <4 x i32> <i32 3, i32 2, i32 1, i32 0>
146; CHECK-NEXT:    [[BC:%.*]] = bitcast <4 x i32> [[S1]] to <16 x i8>
147; CHECK-NEXT:    [[S2:%.*]] = shufflevector <16 x i8> [[BC]], <16 x i8> poison, <16 x i32> <i32 12, i32 13, i32 12, i32 13, i32 8, i32 9, i32 10, i32 11, i32 4, i32 5, i32 6, i32 7, i32 0, i32 1, i32 2, i32 3>
148; CHECK-NEXT:    ret <16 x i8> [[S2]]
149;
150  %s1 = shufflevector <4 x i32> %x, <4 x i32> undef, <4 x i32> <i32 3, i32 2, i32 1, i32 0>
151  %bc = bitcast <4 x i32> %s1 to <16 x i8>
152  %s2 = shufflevector <16 x i8> %bc, <16 x i8> undef, <16 x i32> <i32 12, i32 13, i32 12, i32 13, i32 8, i32 9, i32 10, i32 11, i32 4, i32 5, i32 6, i32 7, i32 0, i32 1, i32 2, i32 3>
153  ret <16 x i8> %s2
154}
155
156; Negative test - the 2nd mask can't be widened
157
158define <16 x i8> @shuf_bitcast_operand_cannot_widen_undef(<4 x i32> %x) {
159; CHECK-LABEL: @shuf_bitcast_operand_cannot_widen_undef(
160; CHECK-NEXT:    [[S1:%.*]] = shufflevector <4 x i32> [[X:%.*]], <4 x i32> poison, <4 x i32> <i32 3, i32 2, i32 1, i32 0>
161; CHECK-NEXT:    [[BC:%.*]] = bitcast <4 x i32> [[S1]] to <16 x i8>
162; CHECK-NEXT:    [[S2:%.*]] = shufflevector <16 x i8> [[BC]], <16 x i8> poison, <16 x i32> <i32 12, i32 poison, i32 14, i32 15, i32 8, i32 9, i32 10, i32 11, i32 4, i32 5, i32 6, i32 7, i32 0, i32 1, i32 2, i32 3>
163; CHECK-NEXT:    ret <16 x i8> [[S2]]
164;
165  %s1 = shufflevector <4 x i32> %x, <4 x i32> undef, <4 x i32> <i32 3, i32 2, i32 1, i32 0>
166  %bc = bitcast <4 x i32> %s1 to <16 x i8>
167  %s2 = shufflevector <16 x i8> %bc, <16 x i8> undef, <16 x i32> <i32 12, i32 undef, i32 14, i32 15, i32 8, i32 9, i32 10, i32 11, i32 4, i32 5, i32 6, i32 7, i32 0, i32 1, i32 2, i32 3>
168  ret <16 x i8> %s2
169}
170
171define <2 x i4> @shuf_bitcast_insert(<2 x i8> %v, i8 %x) {
172; CHECK-LABEL: @shuf_bitcast_insert(
173; CHECK-NEXT:    [[R:%.*]] = bitcast i8 [[X:%.*]] to <2 x i4>
174; CHECK-NEXT:    ret <2 x i4> [[R]]
175;
176  %i = insertelement <2 x i8> %v, i8 %x, i32 0
177  %b = bitcast <2 x i8> %i to <4 x i4>
178  %r = shufflevector <4 x i4> %b, <4 x i4> undef, <2 x i32> <i32 0, i32 1>
179  ret <2 x i4> %r
180}
181
182define <2 x i4> @shuf_bitcast_inserti_use1(<2 x i8> %v, i8 %x, ptr %p) {
183; CHECK-LABEL: @shuf_bitcast_inserti_use1(
184; CHECK-NEXT:    [[I:%.*]] = insertelement <2 x i8> [[V:%.*]], i8 [[X:%.*]], i64 0
185; CHECK-NEXT:    store <2 x i8> [[I]], ptr [[P:%.*]], align 2
186; CHECK-NEXT:    [[R:%.*]] = bitcast i8 [[X]] to <2 x i4>
187; CHECK-NEXT:    ret <2 x i4> [[R]]
188;
189  %i = insertelement <2 x i8> %v, i8 %x, i32 0
190  store <2 x i8> %i, ptr %p
191  %b = bitcast <2 x i8> %i to <4 x i4>
192  %r = shufflevector <4 x i4> %b, <4 x i4> undef, <2 x i32> <i32 0, i32 1>
193  ret <2 x i4> %r
194}
195
196define <2 x i4> @shuf_bitcast_insert_use2(<2 x i8> %v, i8 %x, ptr %p) {
197; CHECK-LABEL: @shuf_bitcast_insert_use2(
198; CHECK-NEXT:    [[I:%.*]] = insertelement <2 x i8> [[V:%.*]], i8 [[X:%.*]], i64 0
199; CHECK-NEXT:    store <2 x i8> [[I]], ptr [[P:%.*]], align 2
200; CHECK-NEXT:    [[R:%.*]] = bitcast i8 [[X]] to <2 x i4>
201; CHECK-NEXT:    ret <2 x i4> [[R]]
202;
203  %i = insertelement <2 x i8> %v, i8 %x, i32 0
204  %b = bitcast <2 x i8> %i to <4 x i4>
205  store <4 x i4> %b, ptr %p
206  %r = shufflevector <4 x i4> %b, <4 x i4> undef, <2 x i32> <i32 0, i32 1>
207  ret <2 x i4> %r
208}
209
210; negative test - but demanded elements reduces this.
211
212define <2 x i4> @shuf_bitcast_insert_wrong_index(<2 x i8> %v, i8 %x) {
213; CHECK-LABEL: @shuf_bitcast_insert_wrong_index(
214; CHECK-NEXT:    [[B:%.*]] = bitcast <2 x i8> [[V:%.*]] to <4 x i4>
215; CHECK-NEXT:    [[R:%.*]] = shufflevector <4 x i4> [[B]], <4 x i4> poison, <2 x i32> <i32 0, i32 1>
216; CHECK-NEXT:    ret <2 x i4> [[R]]
217;
218  %i = insertelement <2 x i8> %v, i8 %x, i32 1
219  %b = bitcast <2 x i8> %i to <4 x i4>
220  %r = shufflevector <4 x i4> %b, <4 x i4> undef, <2 x i32> <i32 0, i32 1>
221  ret <2 x i4> %r
222}
223
224; negative test
225
226define <3 x i4> @shuf_bitcast_wrong_size(<2 x i8> %v, i8 %x) {
227; CHECK-LABEL: @shuf_bitcast_wrong_size(
228; CHECK-NEXT:    [[I:%.*]] = insertelement <2 x i8> [[V:%.*]], i8 [[X:%.*]], i64 0
229; CHECK-NEXT:    [[B:%.*]] = bitcast <2 x i8> [[I]] to <4 x i4>
230; CHECK-NEXT:    [[R:%.*]] = shufflevector <4 x i4> [[B]], <4 x i4> poison, <3 x i32> <i32 0, i32 1, i32 2>
231; CHECK-NEXT:    ret <3 x i4> [[R]]
232;
233  %i = insertelement <2 x i8> %v, i8 %x, i32 0
234  %b = bitcast <2 x i8> %i to <4 x i4>
235  %r = shufflevector <4 x i4> %b, <4 x i4> undef, <3 x i32> <i32 0, i32 1, i32 2>
236  ret <3 x i4> %r
237}
238