1 ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2 ; RUN: opt < %s -instcombine -S | FileCheck %s
4 target datalayout = "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-f32:32:32-f64:32:64-v64:64:64-v128:128:128-a0:0:64-f80:128:128-n8:16:32"
6 define i32 @test1(i32 %i) {
8 ; CHECK-NEXT: [[TMP12:%.*]] = call i32 @llvm.bswap.i32(i32 [[I:%.*]])
9 ; CHECK-NEXT: ret i32 [[TMP12]]
11 %tmp1 = lshr i32 %i, 24
12 %tmp3 = lshr i32 %i, 8
13 %tmp4 = and i32 %tmp3, 65280
14 %tmp5 = or i32 %tmp1, %tmp4
16 %tmp8 = and i32 %tmp7, 16711680
17 %tmp9 = or i32 %tmp5, %tmp8
18 %tmp11 = shl i32 %i, 24
19 %tmp12 = or i32 %tmp9, %tmp11
23 define i32 @test2(i32 %arg) {
24 ; CHECK-LABEL: @test2(
25 ; CHECK-NEXT: [[TMP14:%.*]] = call i32 @llvm.bswap.i32(i32 [[ARG:%.*]])
26 ; CHECK-NEXT: ret i32 [[TMP14]]
28 %tmp2 = shl i32 %arg, 24
29 %tmp4 = shl i32 %arg, 8
30 %tmp5 = and i32 %tmp4, 16711680
31 %tmp6 = or i32 %tmp2, %tmp5
32 %tmp8 = lshr i32 %arg, 8
33 %tmp9 = and i32 %tmp8, 65280
34 %tmp10 = or i32 %tmp6, %tmp9
35 %tmp12 = lshr i32 %arg, 24
36 %tmp14 = or i32 %tmp10, %tmp12
40 define i16 @test3(i16 %s) {
41 ; CHECK-LABEL: @test3(
42 ; CHECK-NEXT: [[TMP5:%.*]] = call i16 @llvm.bswap.i16(i16 [[S:%.*]])
43 ; CHECK-NEXT: ret i16 [[TMP5]]
45 %tmp2 = lshr i16 %s, 8
47 %tmp5 = or i16 %tmp2, %tmp4
51 define i16 @test4(i16 %s) {
52 ; CHECK-LABEL: @test4(
53 ; CHECK-NEXT: [[TMP5:%.*]] = call i16 @llvm.bswap.i16(i16 [[S:%.*]])
54 ; CHECK-NEXT: ret i16 [[TMP5]]
56 %tmp2 = lshr i16 %s, 8
58 %tmp5 = or i16 %tmp4, %tmp2
62 define i16 @test5(i16 %a) {
63 ; CHECK-LABEL: @test5(
64 ; CHECK-NEXT: [[TMP_UPGRD_3:%.*]] = call i16 @llvm.bswap.i16(i16 [[A:%.*]])
65 ; CHECK-NEXT: ret i16 [[TMP_UPGRD_3]]
67 %tmp = zext i16 %a to i32
68 %tmp1 = and i32 %tmp, 65280
69 %tmp2 = ashr i32 %tmp1, 8
70 %tmp2.upgrd.1 = trunc i32 %tmp2 to i16
71 %tmp4 = and i32 %tmp, 255
72 %tmp5 = shl i32 %tmp4, 8
73 %tmp5.upgrd.2 = trunc i32 %tmp5 to i16
74 %tmp.upgrd.3 = or i16 %tmp2.upgrd.1, %tmp5.upgrd.2
75 %tmp6 = bitcast i16 %tmp.upgrd.3 to i16
76 %tmp6.upgrd.4 = zext i16 %tmp6 to i32
77 %retval = trunc i32 %tmp6.upgrd.4 to i16
82 define i32 @test6(i32 %x) nounwind readnone {
83 ; CHECK-LABEL: @test6(
84 ; CHECK-NEXT: [[TMP7:%.*]] = call i32 @llvm.bswap.i32(i32 [[X:%.*]])
85 ; CHECK-NEXT: ret i32 [[TMP7]]
88 %x.mask = and i32 %x, 65280
89 %tmp1 = lshr i32 %x, 16
90 %tmp2 = and i32 %tmp1, 255
91 %tmp3 = or i32 %x.mask, %tmp
92 %tmp4 = or i32 %tmp3, %tmp2
93 %tmp5 = shl i32 %tmp4, 8
94 %tmp6 = lshr i32 %x, 24
95 %tmp7 = or i32 %tmp5, %tmp6
99 declare void @extra_use(i32)
101 ; swaphalf = (x << 16 | x >> 16)
102 ; ((swaphalf & 0x00ff00ff) << 8) | ((swaphalf >> 8) & 0x00ff00ff)
104 define i32 @bswap32_and_first(i32 %x) {
105 ; CHECK-LABEL: @bswap32_and_first(
106 ; CHECK-NEXT: [[BSWAP:%.*]] = call i32 @llvm.bswap.i32(i32 [[X:%.*]])
107 ; CHECK-NEXT: ret i32 [[BSWAP]]
109 %shl = shl i32 %x, 16
110 %shr = lshr i32 %x, 16
111 %swaphalf = or i32 %shl, %shr
112 %t = and i32 %swaphalf, 16711935
113 %tshl = shl nuw i32 %t, 8
114 %b = lshr i32 %swaphalf, 8
115 %band = and i32 %b, 16711935
116 %bswap = or i32 %tshl, %band
120 ; Extra use should not prevent matching to bswap.
121 ; swaphalf = (x << 16 | x >> 16)
122 ; ((swaphalf & 0x00ff00ff) << 8) | ((swaphalf >> 8) & 0x00ff00ff)
124 define i32 @bswap32_and_first_extra_use(i32 %x) {
125 ; CHECK-LABEL: @bswap32_and_first_extra_use(
126 ; CHECK-NEXT: [[SHL:%.*]] = shl i32 [[X:%.*]], 16
127 ; CHECK-NEXT: [[SHR:%.*]] = lshr i32 [[X]], 16
128 ; CHECK-NEXT: [[SWAPHALF:%.*]] = or i32 [[SHL]], [[SHR]]
129 ; CHECK-NEXT: [[T:%.*]] = and i32 [[SWAPHALF]], 16711935
130 ; CHECK-NEXT: [[BSWAP:%.*]] = call i32 @llvm.bswap.i32(i32 [[X]])
131 ; CHECK-NEXT: call void @extra_use(i32 [[T]])
132 ; CHECK-NEXT: ret i32 [[BSWAP]]
134 %shl = shl i32 %x, 16
135 %shr = lshr i32 %x, 16
136 %swaphalf = or i32 %shl, %shr
137 %t = and i32 %swaphalf, 16711935
138 %tshl = shl nuw i32 %t, 8
139 %b = lshr i32 %swaphalf, 8
140 %band = and i32 %b, 16711935
141 %bswap = or i32 %tshl, %band
142 call void @extra_use(i32 %t)
146 ; swaphalf = (x << 16 | x >> 16)
147 ; ((swaphalf << 8) & 0xff00ff00) | ((swaphalf >> 8) & 0x00ff00ff)
150 define i32 @bswap32_shl_first(i32 %x) {
151 ; CHECK-LABEL: @bswap32_shl_first(
152 ; CHECK-NEXT: [[BSWAP:%.*]] = call i32 @llvm.bswap.i32(i32 [[X:%.*]])
153 ; CHECK-NEXT: ret i32 [[BSWAP]]
155 %shl = shl i32 %x, 16
156 %shr = lshr i32 %x, 16
157 %swaphalf = or i32 %shl, %shr
158 %t = shl i32 %swaphalf, 8
159 %tand = and i32 %t, -16711936
160 %b = lshr i32 %swaphalf, 8
161 %band = and i32 %b, 16711935
162 %bswap = or i32 %tand, %band
166 ; Extra use should not prevent matching to bswap.
167 ; swaphalf = (x << 16 | x >> 16)
168 ; ((swaphalf << 8) & 0xff00ff00) | ((swaphalf >> 8) & 0x00ff00ff)
170 define i32 @bswap32_shl_first_extra_use(i32 %x) {
171 ; CHECK-LABEL: @bswap32_shl_first_extra_use(
172 ; CHECK-NEXT: [[SHL:%.*]] = shl i32 [[X:%.*]], 16
173 ; CHECK-NEXT: [[SHR:%.*]] = lshr i32 [[X]], 16
174 ; CHECK-NEXT: [[SWAPHALF:%.*]] = or i32 [[SHL]], [[SHR]]
175 ; CHECK-NEXT: [[T:%.*]] = shl i32 [[SWAPHALF]], 8
176 ; CHECK-NEXT: [[BSWAP:%.*]] = call i32 @llvm.bswap.i32(i32 [[X]])
177 ; CHECK-NEXT: call void @extra_use(i32 [[T]])
178 ; CHECK-NEXT: ret i32 [[BSWAP]]
180 %shl = shl i32 %x, 16
181 %shr = lshr i32 %x, 16
182 %swaphalf = or i32 %shl, %shr
183 %t = shl i32 %swaphalf, 8
184 %tand = and i32 %t, -16711936
185 %b = lshr i32 %swaphalf, 8
186 %band = and i32 %b, 16711935
187 %bswap = or i32 %tand, %band
188 call void @extra_use(i32 %t)
192 define i16 @test8(i16 %a) {
193 ; CHECK-LABEL: @test8(
194 ; CHECK-NEXT: [[REV:%.*]] = call i16 @llvm.bswap.i16(i16 [[A:%.*]])
195 ; CHECK-NEXT: ret i16 [[REV]]
197 %conv = zext i16 %a to i32
198 %shr = lshr i16 %a, 8
199 %shl = shl i32 %conv, 8
200 %conv1 = zext i16 %shr to i32
201 %or = or i32 %conv1, %shl
202 %conv2 = trunc i32 %or to i16
206 define i16 @test9(i16 %a) {
207 ; CHECK-LABEL: @test9(
208 ; CHECK-NEXT: [[REV:%.*]] = call i16 @llvm.bswap.i16(i16 [[A:%.*]])
209 ; CHECK-NEXT: ret i16 [[REV]]
211 %conv = zext i16 %a to i32
212 %shr = lshr i32 %conv, 8
213 %shl = shl i32 %conv, 8
214 %or = or i32 %shr, %shl
215 %conv2 = trunc i32 %or to i16
219 define i16 @test10(i32 %a) {
220 ; CHECK-LABEL: @test10(
221 ; CHECK-NEXT: [[TRUNC:%.*]] = trunc i32 [[A:%.*]] to i16
222 ; CHECK-NEXT: [[REV:%.*]] = call i16 @llvm.bswap.i16(i16 [[TRUNC]])
223 ; CHECK-NEXT: ret i16 [[REV]]
225 %shr1 = lshr i32 %a, 8
226 %and1 = and i32 %shr1, 255
227 %and2 = shl i32 %a, 8
228 %shl1 = and i32 %and2, 65280
229 %or = or i32 %and1, %shl1
230 %conv = trunc i32 %or to i16
234 define i32 @shuf_4bytes(<4 x i8> %x) {
235 ; CHECK-LABEL: @shuf_4bytes(
236 ; CHECK-NEXT: [[TMP1:%.*]] = bitcast <4 x i8> [[X:%.*]] to i32
237 ; CHECK-NEXT: [[CAST:%.*]] = call i32 @llvm.bswap.i32(i32 [[TMP1]])
238 ; CHECK-NEXT: ret i32 [[CAST]]
240 %bswap = shufflevector <4 x i8> %x, <4 x i8> undef, <4 x i32> <i32 3, i32 2, i32 1, i32 0>
241 %cast = bitcast <4 x i8> %bswap to i32
245 define i32 @shuf_load_4bytes(<4 x i8>* %p) {
246 ; CHECK-LABEL: @shuf_load_4bytes(
247 ; CHECK-NEXT: [[TMP1:%.*]] = bitcast <4 x i8>* [[P:%.*]] to i32*
248 ; CHECK-NEXT: [[X1:%.*]] = load i32, i32* [[TMP1]], align 4
249 ; CHECK-NEXT: [[CAST:%.*]] = call i32 @llvm.bswap.i32(i32 [[X1]])
250 ; CHECK-NEXT: ret i32 [[CAST]]
252 %x = load <4 x i8>, <4 x i8>* %p
253 %bswap = shufflevector <4 x i8> %x, <4 x i8> undef, <4 x i32> <i32 3, i32 2, i32 undef, i32 0>
254 %cast = bitcast <4 x i8> %bswap to i32
258 define i32 @shuf_bitcast_twice_4bytes(i32 %x) {
259 ; CHECK-LABEL: @shuf_bitcast_twice_4bytes(
260 ; CHECK-NEXT: [[CAST2:%.*]] = call i32 @llvm.bswap.i32(i32 [[X:%.*]])
261 ; CHECK-NEXT: ret i32 [[CAST2]]
263 %cast1 = bitcast i32 %x to <4 x i8>
264 %bswap = shufflevector <4 x i8> %cast1, <4 x i8> undef, <4 x i32> <i32 undef, i32 2, i32 1, i32 0>
265 %cast2 = bitcast <4 x i8> %bswap to i32
269 ; Negative test - extra use
270 declare void @use(<4 x i8>)
272 define i32 @shuf_4bytes_extra_use(<4 x i8> %x) {
273 ; CHECK-LABEL: @shuf_4bytes_extra_use(
274 ; CHECK-NEXT: [[BSWAP:%.*]] = shufflevector <4 x i8> [[X:%.*]], <4 x i8> undef, <4 x i32> <i32 3, i32 2, i32 1, i32 0>
275 ; CHECK-NEXT: call void @use(<4 x i8> [[BSWAP]])
276 ; CHECK-NEXT: [[CAST:%.*]] = bitcast <4 x i8> [[BSWAP]] to i32
277 ; CHECK-NEXT: ret i32 [[CAST]]
279 %bswap = shufflevector <4 x i8> %x, <4 x i8> undef, <4 x i32> <i32 3, i32 2, i32 1, i32 0>
280 call void @use(<4 x i8> %bswap)
281 %cast = bitcast <4 x i8> %bswap to i32
285 ; Negative test - scalar type is not in the data layout
287 define i128 @shuf_16bytes(<16 x i8> %x) {
288 ; CHECK-LABEL: @shuf_16bytes(
289 ; CHECK-NEXT: [[BSWAP:%.*]] = shufflevector <16 x i8> [[X:%.*]], <16 x i8> undef, <16 x i32> <i32 15, i32 14, i32 13, i32 12, i32 11, i32 10, i32 9, i32 8, i32 7, i32 6, i32 5, i32 4, i32 3, i32 2, i32 1, i32 0>
290 ; CHECK-NEXT: [[CAST:%.*]] = bitcast <16 x i8> [[BSWAP]] to i128
291 ; CHECK-NEXT: ret i128 [[CAST]]
293 %bswap = shufflevector <16 x i8> %x, <16 x i8> undef, <16 x i32> <i32 15, i32 14, i32 13, i32 12, i32 11, i32 10, i32 9, i32 8, i32 7, i32 6, i32 5, i32 4, i32 3, i32 2, i32 1, i32 0>
294 %cast = bitcast <16 x i8> %bswap to i128
298 ; Negative test - don't touch widening shuffles (for now)
300 define i32 @shuf_2bytes_widening(<2 x i8> %x) {
301 ; CHECK-LABEL: @shuf_2bytes_widening(
302 ; CHECK-NEXT: [[BSWAP:%.*]] = shufflevector <2 x i8> [[X:%.*]], <2 x i8> undef, <4 x i32> <i32 1, i32 0, i32 undef, i32 undef>
303 ; CHECK-NEXT: [[CAST:%.*]] = bitcast <4 x i8> [[BSWAP]] to i32
304 ; CHECK-NEXT: ret i32 [[CAST]]
306 %bswap = shufflevector <2 x i8> %x, <2 x i8> undef, <4 x i32> <i32 1, i32 0, i32 undef, i32 undef>
307 %cast = bitcast <4 x i8> %bswap to i32