Mercurial > hg > CbC > CbC_llvm
comparison test/Transforms/InstCombine/shift-amount-reassociation-in-bittest.ll @ 147:c2174574ed3a
LLVM 10
author | Shinji KONO <kono@ie.u-ryukyu.ac.jp> |
---|---|
date | Wed, 14 Aug 2019 16:55:33 +0900 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
134:3a76565eade5 | 147:c2174574ed3a |
---|---|
1 ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py | |
2 ; RUN: opt %s -instcombine -S | FileCheck %s | |
3 | |
4 ; Given pattern: | |
5 ; icmp eq/ne (and ((x shift Q), (y oppositeshift K))), 0 | |
6 ; we should move shifts to the same hand of 'and', i.e. e.g. rewrite as | |
7 ; icmp eq/ne (and (((x shift Q) shift K), y)), 0 | |
8 ; We are only interested in opposite logical shifts here. | |
9 | |
10 ; Basic scalar test with constants | |
11 | |
12 define i1 @t0_const_lshr_shl_ne(i32 %x, i32 %y) { | |
13 ; CHECK-LABEL: @t0_const_lshr_shl_ne( | |
14 ; CHECK-NEXT: [[TMP1:%.*]] = lshr i32 [[X:%.*]], 2 | |
15 ; CHECK-NEXT: [[TMP2:%.*]] = and i32 [[TMP1]], [[Y:%.*]] | |
16 ; CHECK-NEXT: [[TMP3:%.*]] = icmp ne i32 [[TMP2]], 0 | |
17 ; CHECK-NEXT: ret i1 [[TMP3]] | |
18 ; | |
19 %t0 = lshr i32 %x, 1 | |
20 %t1 = shl i32 %y, 1 | |
21 %t2 = and i32 %t1, %t0 | |
22 %t3 = icmp ne i32 %t2, 0 | |
23 ret i1 %t3 | |
24 } | |
25 define i1 @t1_const_shl_lshr_ne(i32 %x, i32 %y) { | |
26 ; CHECK-LABEL: @t1_const_shl_lshr_ne( | |
27 ; CHECK-NEXT: [[TMP1:%.*]] = lshr i32 [[Y:%.*]], 2 | |
28 ; CHECK-NEXT: [[TMP2:%.*]] = and i32 [[TMP1]], [[X:%.*]] | |
29 ; CHECK-NEXT: [[TMP3:%.*]] = icmp ne i32 [[TMP2]], 0 | |
30 ; CHECK-NEXT: ret i1 [[TMP3]] | |
31 ; | |
32 %t0 = shl i32 %x, 1 | |
33 %t1 = lshr i32 %y, 1 | |
34 %t2 = and i32 %t1, %t0 | |
35 %t3 = icmp ne i32 %t2, 0 | |
36 ret i1 %t3 | |
37 } | |
38 | |
39 ; We are ok with 'eq' predicate too. | |
40 define i1 @t2_const_lshr_shl_eq(i32 %x, i32 %y) { | |
41 ; CHECK-LABEL: @t2_const_lshr_shl_eq( | |
42 ; CHECK-NEXT: [[TMP1:%.*]] = lshr i32 [[X:%.*]], 2 | |
43 ; CHECK-NEXT: [[TMP2:%.*]] = and i32 [[TMP1]], [[Y:%.*]] | |
44 ; CHECK-NEXT: [[TMP3:%.*]] = icmp eq i32 [[TMP2]], 0 | |
45 ; CHECK-NEXT: ret i1 [[TMP3]] | |
46 ; | |
47 %t0 = lshr i32 %x, 1 | |
48 %t1 = shl i32 %y, 1 | |
49 %t2 = and i32 %t1, %t0 | |
50 %t3 = icmp eq i32 %t2, 0 | |
51 ret i1 %t3 | |
52 } | |
53 | |
54 ; Basic scalar test with constants after folding | |
55 | |
56 define i1 @t3_const_after_fold_lshr_shl_ne(i32 %x, i32 %y, i32 %len) { | |
57 ; CHECK-LABEL: @t3_const_after_fold_lshr_shl_ne( | |
58 ; CHECK-NEXT: [[TMP1:%.*]] = lshr i32 [[X:%.*]], 31 | |
59 ; CHECK-NEXT: [[TMP2:%.*]] = and i32 [[TMP1]], [[Y:%.*]] | |
60 ; CHECK-NEXT: [[TMP3:%.*]] = icmp ne i32 [[TMP2]], 0 | |
61 ; CHECK-NEXT: ret i1 [[TMP3]] | |
62 ; | |
63 %t0 = sub i32 32, %len | |
64 %t1 = lshr i32 %x, %t0 | |
65 %t2 = add i32 %len, -1 | |
66 %t3 = shl i32 %y, %t2 | |
67 %t4 = and i32 %t1, %t3 | |
68 %t5 = icmp ne i32 %t4, 0 | |
69 ret i1 %t5 | |
70 } | |
71 define i1 @t4_const_after_fold_lshr_shl_ne(i32 %x, i32 %y, i32 %len) { | |
72 ; CHECK-LABEL: @t4_const_after_fold_lshr_shl_ne( | |
73 ; CHECK-NEXT: [[TMP1:%.*]] = lshr i32 [[Y:%.*]], 31 | |
74 ; CHECK-NEXT: [[TMP2:%.*]] = and i32 [[TMP1]], [[X:%.*]] | |
75 ; CHECK-NEXT: [[TMP3:%.*]] = icmp ne i32 [[TMP2]], 0 | |
76 ; CHECK-NEXT: ret i1 [[TMP3]] | |
77 ; | |
78 %t0 = sub i32 32, %len | |
79 %t1 = shl i32 %x, %t0 | |
80 %t2 = add i32 %len, -1 | |
81 %t3 = lshr i32 %y, %t2 | |
82 %t4 = and i32 %t1, %t3 | |
83 %t5 = icmp ne i32 %t4, 0 | |
84 ret i1 %t5 | |
85 } | |
86 | |
87 ; Completely variable shift amounts | |
88 | |
89 define i1 @t5_const_lshr_shl_ne(i32 %x, i32 %y, i32 %shamt0, i32 %shamt1) { | |
90 ; CHECK-LABEL: @t5_const_lshr_shl_ne( | |
91 ; CHECK-NEXT: [[T0:%.*]] = lshr i32 [[X:%.*]], [[SHAMT0:%.*]] | |
92 ; CHECK-NEXT: [[T1:%.*]] = shl i32 [[Y:%.*]], [[SHAMT1:%.*]] | |
93 ; CHECK-NEXT: [[T2:%.*]] = and i32 [[T1]], [[T0]] | |
94 ; CHECK-NEXT: [[T3:%.*]] = icmp ne i32 [[T2]], 0 | |
95 ; CHECK-NEXT: ret i1 [[T3]] | |
96 ; | |
97 %t0 = lshr i32 %x, %shamt0 | |
98 %t1 = shl i32 %y, %shamt1 | |
99 %t2 = and i32 %t1, %t0 | |
100 %t3 = icmp ne i32 %t2, 0 | |
101 ret i1 %t3 | |
102 } | |
103 define i1 @t6_const_shl_lshr_ne(i32 %x, i32 %y, i32 %shamt0, i32 %shamt1) { | |
104 ; CHECK-LABEL: @t6_const_shl_lshr_ne( | |
105 ; CHECK-NEXT: [[T0:%.*]] = shl i32 [[X:%.*]], [[SHAMT0:%.*]] | |
106 ; CHECK-NEXT: [[T1:%.*]] = lshr i32 [[Y:%.*]], [[SHAMT1:%.*]] | |
107 ; CHECK-NEXT: [[T2:%.*]] = and i32 [[T1]], [[T0]] | |
108 ; CHECK-NEXT: [[T3:%.*]] = icmp ne i32 [[T2]], 0 | |
109 ; CHECK-NEXT: ret i1 [[T3]] | |
110 ; | |
111 %t0 = shl i32 %x, %shamt0 | |
112 %t1 = lshr i32 %y, %shamt1 | |
113 %t2 = and i32 %t1, %t0 | |
114 %t3 = icmp ne i32 %t2, 0 | |
115 ret i1 %t3 | |
116 } | |
117 | |
118 ; Very basic vector tests | |
119 | |
120 define <2 x i1> @t7_const_lshr_shl_ne_vec_splat(<2 x i32> %x, <2 x i32> %y) { | |
121 ; CHECK-LABEL: @t7_const_lshr_shl_ne_vec_splat( | |
122 ; CHECK-NEXT: [[TMP1:%.*]] = lshr <2 x i32> [[X:%.*]], <i32 2, i32 2> | |
123 ; CHECK-NEXT: [[TMP2:%.*]] = and <2 x i32> [[TMP1]], [[Y:%.*]] | |
124 ; CHECK-NEXT: [[TMP3:%.*]] = icmp ne <2 x i32> [[TMP2]], zeroinitializer | |
125 ; CHECK-NEXT: ret <2 x i1> [[TMP3]] | |
126 ; | |
127 %t0 = lshr <2 x i32> %x, <i32 1, i32 1> | |
128 %t1 = shl <2 x i32> %y, <i32 1, i32 1> | |
129 %t2 = and <2 x i32> %t1, %t0 | |
130 %t3 = icmp ne <2 x i32> %t2, <i32 0, i32 0> | |
131 ret <2 x i1> %t3 | |
132 } | |
133 define <2 x i1> @t8_const_lshr_shl_ne_vec_nonsplat(<2 x i32> %x, <2 x i32> %y) { | |
134 ; CHECK-LABEL: @t8_const_lshr_shl_ne_vec_nonsplat( | |
135 ; CHECK-NEXT: [[TMP1:%.*]] = lshr <2 x i32> [[X:%.*]], <i32 4, i32 6> | |
136 ; CHECK-NEXT: [[TMP2:%.*]] = and <2 x i32> [[TMP1]], [[Y:%.*]] | |
137 ; CHECK-NEXT: [[TMP3:%.*]] = icmp ne <2 x i32> [[TMP2]], zeroinitializer | |
138 ; CHECK-NEXT: ret <2 x i1> [[TMP3]] | |
139 ; | |
140 %t0 = lshr <2 x i32> %x, <i32 1, i32 2> | |
141 %t1 = shl <2 x i32> %y, <i32 3, i32 4> | |
142 %t2 = and <2 x i32> %t1, %t0 | |
143 %t3 = icmp ne <2 x i32> %t2, <i32 0, i32 0> | |
144 ret <2 x i1> %t3 | |
145 } | |
146 define <3 x i1> @t9_const_lshr_shl_ne_vec_undef0(<3 x i32> %x, <3 x i32> %y) { | |
147 ; CHECK-LABEL: @t9_const_lshr_shl_ne_vec_undef0( | |
148 ; CHECK-NEXT: [[TMP1:%.*]] = lshr <3 x i32> [[X:%.*]], <i32 2, i32 undef, i32 2> | |
149 ; CHECK-NEXT: [[TMP2:%.*]] = and <3 x i32> [[TMP1]], [[Y:%.*]] | |
150 ; CHECK-NEXT: [[TMP3:%.*]] = icmp ne <3 x i32> [[TMP2]], zeroinitializer | |
151 ; CHECK-NEXT: ret <3 x i1> [[TMP3]] | |
152 ; | |
153 %t0 = lshr <3 x i32> %x, <i32 1, i32 undef, i32 1> | |
154 %t1 = shl <3 x i32> %y, <i32 1, i32 1, i32 1> | |
155 %t2 = and <3 x i32> %t1, %t0 | |
156 %t3 = icmp ne <3 x i32> %t2, <i32 0, i32 0, i32 0> | |
157 ret <3 x i1> %t3 | |
158 } | |
159 define <3 x i1> @t10_const_lshr_shl_ne_vec_undef1(<3 x i32> %x, <3 x i32> %y) { | |
160 ; CHECK-LABEL: @t10_const_lshr_shl_ne_vec_undef1( | |
161 ; CHECK-NEXT: [[TMP1:%.*]] = lshr <3 x i32> [[X:%.*]], <i32 2, i32 undef, i32 2> | |
162 ; CHECK-NEXT: [[TMP2:%.*]] = and <3 x i32> [[TMP1]], [[Y:%.*]] | |
163 ; CHECK-NEXT: [[TMP3:%.*]] = icmp ne <3 x i32> [[TMP2]], zeroinitializer | |
164 ; CHECK-NEXT: ret <3 x i1> [[TMP3]] | |
165 ; | |
166 %t0 = lshr <3 x i32> %x, <i32 1, i32 1, i32 1> | |
167 %t1 = shl <3 x i32> %y, <i32 1, i32 undef, i32 1> | |
168 %t2 = and <3 x i32> %t1, %t0 | |
169 %t3 = icmp ne <3 x i32> %t2, <i32 0, i32 0, i32 0> | |
170 ret <3 x i1> %t3 | |
171 } | |
172 define <3 x i1> @t11_const_lshr_shl_ne_vec_undef2(<3 x i32> %x, <3 x i32> %y) { | |
173 ; CHECK-LABEL: @t11_const_lshr_shl_ne_vec_undef2( | |
174 ; CHECK-NEXT: [[TMP1:%.*]] = lshr <3 x i32> [[X:%.*]], <i32 2, i32 2, i32 2> | |
175 ; CHECK-NEXT: [[TMP2:%.*]] = and <3 x i32> [[TMP1]], [[Y:%.*]] | |
176 ; CHECK-NEXT: [[TMP3:%.*]] = icmp ne <3 x i32> [[TMP2]], zeroinitializer | |
177 ; CHECK-NEXT: ret <3 x i1> [[TMP3]] | |
178 ; | |
179 %t0 = lshr <3 x i32> %x, <i32 1, i32 1, i32 1> | |
180 %t1 = shl <3 x i32> %y, <i32 1, i32 1, i32 1> | |
181 %t2 = and <3 x i32> %t1, %t0 | |
182 %t3 = icmp ne <3 x i32> %t2, <i32 0, i32 undef, i32 0> | |
183 ret <3 x i1> %t3 | |
184 } | |
185 define <3 x i1> @t12_const_lshr_shl_ne_vec_undef3(<3 x i32> %x, <3 x i32> %y) { | |
186 ; CHECK-LABEL: @t12_const_lshr_shl_ne_vec_undef3( | |
187 ; CHECK-NEXT: [[TMP1:%.*]] = lshr <3 x i32> [[X:%.*]], <i32 2, i32 undef, i32 2> | |
188 ; CHECK-NEXT: [[TMP2:%.*]] = and <3 x i32> [[TMP1]], [[Y:%.*]] | |
189 ; CHECK-NEXT: [[TMP3:%.*]] = icmp ne <3 x i32> [[TMP2]], zeroinitializer | |
190 ; CHECK-NEXT: ret <3 x i1> [[TMP3]] | |
191 ; | |
192 %t0 = lshr <3 x i32> %x, <i32 1, i32 undef, i32 1> | |
193 %t1 = shl <3 x i32> %y, <i32 1, i32 undef, i32 1> | |
194 %t2 = and <3 x i32> %t1, %t0 | |
195 %t3 = icmp ne <3 x i32> %t2, <i32 0, i32 0, i32 0> | |
196 ret <3 x i1> %t3 | |
197 } | |
198 define <3 x i1> @t13_const_lshr_shl_ne_vec_undef4(<3 x i32> %x, <3 x i32> %y) { | |
199 ; CHECK-LABEL: @t13_const_lshr_shl_ne_vec_undef4( | |
200 ; CHECK-NEXT: [[TMP1:%.*]] = lshr <3 x i32> [[X:%.*]], <i32 2, i32 undef, i32 2> | |
201 ; CHECK-NEXT: [[TMP2:%.*]] = and <3 x i32> [[TMP1]], [[Y:%.*]] | |
202 ; CHECK-NEXT: [[TMP3:%.*]] = icmp ne <3 x i32> [[TMP2]], zeroinitializer | |
203 ; CHECK-NEXT: ret <3 x i1> [[TMP3]] | |
204 ; | |
205 %t0 = lshr <3 x i32> %x, <i32 1, i32 1, i32 1> | |
206 %t1 = shl <3 x i32> %y, <i32 1, i32 undef, i32 1> | |
207 %t2 = and <3 x i32> %t1, %t0 | |
208 %t3 = icmp ne <3 x i32> %t2, <i32 0, i32 undef, i32 0> | |
209 ret <3 x i1> %t3 | |
210 } | |
211 define <3 x i1> @t14_const_lshr_shl_ne_vec_undef5(<3 x i32> %x, <3 x i32> %y) { | |
212 ; CHECK-LABEL: @t14_const_lshr_shl_ne_vec_undef5( | |
213 ; CHECK-NEXT: [[TMP1:%.*]] = lshr <3 x i32> [[X:%.*]], <i32 2, i32 undef, i32 2> | |
214 ; CHECK-NEXT: [[TMP2:%.*]] = and <3 x i32> [[TMP1]], [[Y:%.*]] | |
215 ; CHECK-NEXT: [[TMP3:%.*]] = icmp ne <3 x i32> [[TMP2]], zeroinitializer | |
216 ; CHECK-NEXT: ret <3 x i1> [[TMP3]] | |
217 ; | |
218 %t0 = lshr <3 x i32> %x, <i32 1, i32 undef, i32 1> | |
219 %t1 = shl <3 x i32> %y, <i32 1, i32 1, i32 1> | |
220 %t2 = and <3 x i32> %t1, %t0 | |
221 %t3 = icmp ne <3 x i32> %t2, <i32 0, i32 undef, i32 0> | |
222 ret <3 x i1> %t3 | |
223 } | |
224 define <3 x i1> @t15_const_lshr_shl_ne_vec_undef6(<3 x i32> %x, <3 x i32> %y) { | |
225 ; CHECK-LABEL: @t15_const_lshr_shl_ne_vec_undef6( | |
226 ; CHECK-NEXT: [[TMP1:%.*]] = lshr <3 x i32> [[X:%.*]], <i32 2, i32 undef, i32 2> | |
227 ; CHECK-NEXT: [[TMP2:%.*]] = and <3 x i32> [[TMP1]], [[Y:%.*]] | |
228 ; CHECK-NEXT: [[TMP3:%.*]] = icmp ne <3 x i32> [[TMP2]], zeroinitializer | |
229 ; CHECK-NEXT: ret <3 x i1> [[TMP3]] | |
230 ; | |
231 %t0 = lshr <3 x i32> %x, <i32 1, i32 undef, i32 1> | |
232 %t1 = shl <3 x i32> %y, <i32 1, i32 undef, i32 1> | |
233 %t2 = and <3 x i32> %t1, %t0 | |
234 %t3 = icmp ne <3 x i32> %t2, <i32 0, i32 undef, i32 0> | |
235 ret <3 x i1> %t3 | |
236 } | |
237 | |
238 ; Commutativity tests | |
239 | |
240 declare i32 @gen32() | |
241 | |
242 define i1 @t16_commutativity0(i32 %x) { | |
243 ; CHECK-LABEL: @t16_commutativity0( | |
244 ; CHECK-NEXT: [[Y:%.*]] = call i32 @gen32() | |
245 ; CHECK-NEXT: [[TMP1:%.*]] = lshr i32 [[X:%.*]], 2 | |
246 ; CHECK-NEXT: [[TMP2:%.*]] = and i32 [[TMP1]], [[Y]] | |
247 ; CHECK-NEXT: [[TMP3:%.*]] = icmp ne i32 [[TMP2]], 0 | |
248 ; CHECK-NEXT: ret i1 [[TMP3]] | |
249 ; | |
250 %y = call i32 @gen32() | |
251 %t0 = lshr i32 %x, 1 | |
252 %t1 = shl i32 %y, 1 | |
253 %t2 = and i32 %t1, %t0 | |
254 %t3 = icmp ne i32 %t2, 0 | |
255 ret i1 %t3 | |
256 } | |
257 | |
258 define i1 @t17_commutativity1(i32 %y) { | |
259 ; CHECK-LABEL: @t17_commutativity1( | |
260 ; CHECK-NEXT: [[X:%.*]] = call i32 @gen32() | |
261 ; CHECK-NEXT: [[TMP1:%.*]] = lshr i32 [[X]], 2 | |
262 ; CHECK-NEXT: [[TMP2:%.*]] = and i32 [[TMP1]], [[Y:%.*]] | |
263 ; CHECK-NEXT: [[TMP3:%.*]] = icmp ne i32 [[TMP2]], 0 | |
264 ; CHECK-NEXT: ret i1 [[TMP3]] | |
265 ; | |
266 %x = call i32 @gen32() | |
267 %t0 = lshr i32 %x, 1 | |
268 %t1 = shl i32 %y, 1 | |
269 %t2 = and i32 %t0, %t1 ; "swapped" | |
270 %t3 = icmp ne i32 %t2, 0 | |
271 ret i1 %t3 | |
272 } | |
273 | |
274 ; One-use tests | |
275 | |
276 declare void @use32(i32) | |
277 | |
278 define i1 @t18_const_oneuse0(i32 %x, i32 %y) { | |
279 ; CHECK-LABEL: @t18_const_oneuse0( | |
280 ; CHECK-NEXT: [[T0:%.*]] = lshr i32 [[X:%.*]], 1 | |
281 ; CHECK-NEXT: call void @use32(i32 [[T0]]) | |
282 ; CHECK-NEXT: [[TMP1:%.*]] = lshr i32 [[X]], 2 | |
283 ; CHECK-NEXT: [[TMP2:%.*]] = and i32 [[TMP1]], [[Y:%.*]] | |
284 ; CHECK-NEXT: [[TMP3:%.*]] = icmp ne i32 [[TMP2]], 0 | |
285 ; CHECK-NEXT: ret i1 [[TMP3]] | |
286 ; | |
287 %t0 = lshr i32 %x, 1 | |
288 call void @use32(i32 %t0) | |
289 %t1 = shl i32 %y, 1 | |
290 %t2 = and i32 %t1, %t0 | |
291 %t3 = icmp ne i32 %t2, 0 | |
292 ret i1 %t3 | |
293 } | |
294 define i1 @t19_const_oneuse1(i32 %x, i32 %y) { | |
295 ; CHECK-LABEL: @t19_const_oneuse1( | |
296 ; CHECK-NEXT: [[T1:%.*]] = shl i32 [[Y:%.*]], 1 | |
297 ; CHECK-NEXT: call void @use32(i32 [[T1]]) | |
298 ; CHECK-NEXT: [[TMP1:%.*]] = lshr i32 [[X:%.*]], 2 | |
299 ; CHECK-NEXT: [[TMP2:%.*]] = and i32 [[TMP1]], [[Y]] | |
300 ; CHECK-NEXT: [[TMP3:%.*]] = icmp ne i32 [[TMP2]], 0 | |
301 ; CHECK-NEXT: ret i1 [[TMP3]] | |
302 ; | |
303 %t0 = lshr i32 %x, 1 | |
304 %t1 = shl i32 %y, 1 | |
305 call void @use32(i32 %t1) | |
306 %t2 = and i32 %t1, %t0 | |
307 %t3 = icmp ne i32 %t2, 0 | |
308 ret i1 %t3 | |
309 } | |
310 define i1 @t20_const_oneuse2(i32 %x, i32 %y) { | |
311 ; CHECK-LABEL: @t20_const_oneuse2( | |
312 ; CHECK-NEXT: [[T0:%.*]] = lshr i32 [[X:%.*]], 1 | |
313 ; CHECK-NEXT: [[T1:%.*]] = shl i32 [[Y:%.*]], 1 | |
314 ; CHECK-NEXT: [[T2:%.*]] = and i32 [[T1]], [[T0]] | |
315 ; CHECK-NEXT: call void @use32(i32 [[T2]]) | |
316 ; CHECK-NEXT: [[T3:%.*]] = icmp ne i32 [[T2]], 0 | |
317 ; CHECK-NEXT: ret i1 [[T3]] | |
318 ; | |
319 %t0 = lshr i32 %x, 1 | |
320 %t1 = shl i32 %y, 1 | |
321 %t2 = and i32 %t1, %t0 | |
322 call void @use32(i32 %t2) | |
323 %t3 = icmp ne i32 %t2, 0 | |
324 ret i1 %t3 | |
325 } | |
326 define i1 @t21_const_oneuse3(i32 %x, i32 %y) { | |
327 ; CHECK-LABEL: @t21_const_oneuse3( | |
328 ; CHECK-NEXT: [[T0:%.*]] = lshr i32 [[X:%.*]], 1 | |
329 ; CHECK-NEXT: call void @use32(i32 [[T0]]) | |
330 ; CHECK-NEXT: [[T1:%.*]] = shl i32 [[Y:%.*]], 1 | |
331 ; CHECK-NEXT: call void @use32(i32 [[T1]]) | |
332 ; CHECK-NEXT: [[T2:%.*]] = and i32 [[T1]], [[T0]] | |
333 ; CHECK-NEXT: [[T3:%.*]] = icmp ne i32 [[T2]], 0 | |
334 ; CHECK-NEXT: ret i1 [[T3]] | |
335 ; | |
336 %t0 = lshr i32 %x, 1 | |
337 call void @use32(i32 %t0) | |
338 %t1 = shl i32 %y, 1 | |
339 call void @use32(i32 %t1) | |
340 %t2 = and i32 %t1, %t0 | |
341 %t3 = icmp ne i32 %t2, 0 | |
342 ret i1 %t3 | |
343 } | |
344 define i1 @t22_const_oneuse4(i32 %x, i32 %y) { | |
345 ; CHECK-LABEL: @t22_const_oneuse4( | |
346 ; CHECK-NEXT: [[T0:%.*]] = lshr i32 [[X:%.*]], 1 | |
347 ; CHECK-NEXT: call void @use32(i32 [[T0]]) | |
348 ; CHECK-NEXT: [[T1:%.*]] = shl i32 [[Y:%.*]], 1 | |
349 ; CHECK-NEXT: [[T2:%.*]] = and i32 [[T1]], [[T0]] | |
350 ; CHECK-NEXT: call void @use32(i32 [[T2]]) | |
351 ; CHECK-NEXT: [[T3:%.*]] = icmp ne i32 [[T2]], 0 | |
352 ; CHECK-NEXT: ret i1 [[T3]] | |
353 ; | |
354 %t0 = lshr i32 %x, 1 | |
355 call void @use32(i32 %t0) | |
356 %t1 = shl i32 %y, 1 | |
357 %t2 = and i32 %t1, %t0 | |
358 call void @use32(i32 %t2) | |
359 %t3 = icmp ne i32 %t2, 0 | |
360 ret i1 %t3 | |
361 } | |
362 define i1 @t23_const_oneuse5(i32 %x, i32 %y) { | |
363 ; CHECK-LABEL: @t23_const_oneuse5( | |
364 ; CHECK-NEXT: [[T0:%.*]] = lshr i32 [[X:%.*]], 1 | |
365 ; CHECK-NEXT: [[T1:%.*]] = shl i32 [[Y:%.*]], 1 | |
366 ; CHECK-NEXT: call void @use32(i32 [[T1]]) | |
367 ; CHECK-NEXT: [[T2:%.*]] = and i32 [[T1]], [[T0]] | |
368 ; CHECK-NEXT: call void @use32(i32 [[T2]]) | |
369 ; CHECK-NEXT: [[T3:%.*]] = icmp ne i32 [[T2]], 0 | |
370 ; CHECK-NEXT: ret i1 [[T3]] | |
371 ; | |
372 %t0 = lshr i32 %x, 1 | |
373 %t1 = shl i32 %y, 1 | |
374 call void @use32(i32 %t1) | |
375 %t2 = and i32 %t1, %t0 | |
376 call void @use32(i32 %t2) | |
377 %t3 = icmp ne i32 %t2, 0 | |
378 ret i1 %t3 | |
379 } | |
380 define i1 @t24_const_oneuse6(i32 %x, i32 %y) { | |
381 ; CHECK-LABEL: @t24_const_oneuse6( | |
382 ; CHECK-NEXT: [[T0:%.*]] = lshr i32 [[X:%.*]], 1 | |
383 ; CHECK-NEXT: call void @use32(i32 [[T0]]) | |
384 ; CHECK-NEXT: [[T1:%.*]] = shl i32 [[Y:%.*]], 1 | |
385 ; CHECK-NEXT: call void @use32(i32 [[T1]]) | |
386 ; CHECK-NEXT: [[T2:%.*]] = and i32 [[T1]], [[T0]] | |
387 ; CHECK-NEXT: call void @use32(i32 [[T2]]) | |
388 ; CHECK-NEXT: [[T3:%.*]] = icmp ne i32 [[T2]], 0 | |
389 ; CHECK-NEXT: ret i1 [[T3]] | |
390 ; | |
391 %t0 = lshr i32 %x, 1 | |
392 call void @use32(i32 %t0) | |
393 %t1 = shl i32 %y, 1 | |
394 call void @use32(i32 %t1) | |
395 %t2 = and i32 %t1, %t0 | |
396 call void @use32(i32 %t2) | |
397 %t3 = icmp ne i32 %t2, 0 | |
398 ret i1 %t3 | |
399 } | |
400 | |
401 define i1 @t25_var_oneuse0(i32 %x, i32 %y, i32 %shamt0, i32 %shamt1) { | |
402 ; CHECK-LABEL: @t25_var_oneuse0( | |
403 ; CHECK-NEXT: [[T0:%.*]] = lshr i32 [[X:%.*]], [[SHAMT0:%.*]] | |
404 ; CHECK-NEXT: call void @use32(i32 [[T0]]) | |
405 ; CHECK-NEXT: [[T1:%.*]] = shl i32 [[Y:%.*]], [[SHAMT1:%.*]] | |
406 ; CHECK-NEXT: [[T2:%.*]] = and i32 [[T1]], [[T0]] | |
407 ; CHECK-NEXT: [[T3:%.*]] = icmp ne i32 [[T2]], 0 | |
408 ; CHECK-NEXT: ret i1 [[T3]] | |
409 ; | |
410 %t0 = lshr i32 %x, %shamt0 | |
411 call void @use32(i32 %t0) | |
412 %t1 = shl i32 %y, %shamt1 | |
413 %t2 = and i32 %t1, %t0 | |
414 %t3 = icmp ne i32 %t2, 0 | |
415 ret i1 %t3 | |
416 } | |
417 define i1 @t26_var_oneuse1(i32 %x, i32 %y, i32 %shamt0, i32 %shamt1) { | |
418 ; CHECK-LABEL: @t26_var_oneuse1( | |
419 ; CHECK-NEXT: [[T0:%.*]] = lshr i32 [[X:%.*]], [[SHAMT0:%.*]] | |
420 ; CHECK-NEXT: [[T1:%.*]] = shl i32 [[Y:%.*]], [[SHAMT1:%.*]] | |
421 ; CHECK-NEXT: call void @use32(i32 [[T1]]) | |
422 ; CHECK-NEXT: [[T2:%.*]] = and i32 [[T1]], [[T0]] | |
423 ; CHECK-NEXT: [[T3:%.*]] = icmp ne i32 [[T2]], 0 | |
424 ; CHECK-NEXT: ret i1 [[T3]] | |
425 ; | |
426 %t0 = lshr i32 %x, %shamt0 | |
427 %t1 = shl i32 %y, %shamt1 | |
428 call void @use32(i32 %t1) | |
429 %t2 = and i32 %t1, %t0 | |
430 %t3 = icmp ne i32 %t2, 0 | |
431 ret i1 %t3 | |
432 } | |
433 define i1 @t27_var_oneuse2(i32 %x, i32 %y, i32 %shamt0, i32 %shamt1) { | |
434 ; CHECK-LABEL: @t27_var_oneuse2( | |
435 ; CHECK-NEXT: [[T0:%.*]] = lshr i32 [[X:%.*]], [[SHAMT0:%.*]] | |
436 ; CHECK-NEXT: [[T1:%.*]] = shl i32 [[Y:%.*]], [[SHAMT1:%.*]] | |
437 ; CHECK-NEXT: [[T2:%.*]] = and i32 [[T1]], [[T0]] | |
438 ; CHECK-NEXT: call void @use32(i32 [[T2]]) | |
439 ; CHECK-NEXT: [[T3:%.*]] = icmp ne i32 [[T2]], 0 | |
440 ; CHECK-NEXT: ret i1 [[T3]] | |
441 ; | |
442 %t0 = lshr i32 %x, %shamt0 | |
443 %t1 = shl i32 %y, %shamt1 | |
444 %t2 = and i32 %t1, %t0 | |
445 call void @use32(i32 %t2) | |
446 %t3 = icmp ne i32 %t2, 0 | |
447 ret i1 %t3 | |
448 } | |
449 define i1 @t28_var_oneuse3(i32 %x, i32 %y, i32 %shamt0, i32 %shamt1) { | |
450 ; CHECK-LABEL: @t28_var_oneuse3( | |
451 ; CHECK-NEXT: [[T0:%.*]] = lshr i32 [[X:%.*]], [[SHAMT0:%.*]] | |
452 ; CHECK-NEXT: call void @use32(i32 [[T0]]) | |
453 ; CHECK-NEXT: [[T1:%.*]] = shl i32 [[Y:%.*]], [[SHAMT1:%.*]] | |
454 ; CHECK-NEXT: call void @use32(i32 [[T1]]) | |
455 ; CHECK-NEXT: [[T2:%.*]] = and i32 [[T1]], [[T0]] | |
456 ; CHECK-NEXT: [[T3:%.*]] = icmp ne i32 [[T2]], 0 | |
457 ; CHECK-NEXT: ret i1 [[T3]] | |
458 ; | |
459 %t0 = lshr i32 %x, %shamt0 | |
460 call void @use32(i32 %t0) | |
461 %t1 = shl i32 %y, %shamt1 | |
462 call void @use32(i32 %t1) | |
463 %t2 = and i32 %t1, %t0 | |
464 %t3 = icmp ne i32 %t2, 0 | |
465 ret i1 %t3 | |
466 } | |
467 define i1 @t29_var_oneuse4(i32 %x, i32 %y, i32 %shamt0, i32 %shamt1) { | |
468 ; CHECK-LABEL: @t29_var_oneuse4( | |
469 ; CHECK-NEXT: [[T0:%.*]] = lshr i32 [[X:%.*]], [[SHAMT0:%.*]] | |
470 ; CHECK-NEXT: call void @use32(i32 [[T0]]) | |
471 ; CHECK-NEXT: [[T1:%.*]] = shl i32 [[Y:%.*]], [[SHAMT1:%.*]] | |
472 ; CHECK-NEXT: [[T2:%.*]] = and i32 [[T1]], [[T0]] | |
473 ; CHECK-NEXT: call void @use32(i32 [[T2]]) | |
474 ; CHECK-NEXT: [[T3:%.*]] = icmp ne i32 [[T2]], 0 | |
475 ; CHECK-NEXT: ret i1 [[T3]] | |
476 ; | |
477 %t0 = lshr i32 %x, %shamt0 | |
478 call void @use32(i32 %t0) | |
479 %t1 = shl i32 %y, %shamt1 | |
480 %t2 = and i32 %t1, %t0 | |
481 call void @use32(i32 %t2) | |
482 %t3 = icmp ne i32 %t2, 0 | |
483 ret i1 %t3 | |
484 } | |
485 define i1 @t30_var_oneuse5(i32 %x, i32 %y, i32 %shamt0, i32 %shamt1) { | |
486 ; CHECK-LABEL: @t30_var_oneuse5( | |
487 ; CHECK-NEXT: [[T0:%.*]] = lshr i32 [[X:%.*]], [[SHAMT0:%.*]] | |
488 ; CHECK-NEXT: [[T1:%.*]] = shl i32 [[Y:%.*]], [[SHAMT1:%.*]] | |
489 ; CHECK-NEXT: call void @use32(i32 [[T1]]) | |
490 ; CHECK-NEXT: [[T2:%.*]] = and i32 [[T1]], [[T0]] | |
491 ; CHECK-NEXT: call void @use32(i32 [[T2]]) | |
492 ; CHECK-NEXT: [[T3:%.*]] = icmp ne i32 [[T2]], 0 | |
493 ; CHECK-NEXT: ret i1 [[T3]] | |
494 ; | |
495 %t0 = lshr i32 %x, %shamt0 | |
496 %t1 = shl i32 %y, %shamt1 | |
497 call void @use32(i32 %t1) | |
498 %t2 = and i32 %t1, %t0 | |
499 call void @use32(i32 %t2) | |
500 %t3 = icmp ne i32 %t2, 0 | |
501 ret i1 %t3 | |
502 } | |
503 define i1 @t31_var_oneuse6(i32 %x, i32 %y, i32 %shamt0, i32 %shamt1) { | |
504 ; CHECK-LABEL: @t31_var_oneuse6( | |
505 ; CHECK-NEXT: [[T0:%.*]] = lshr i32 [[X:%.*]], [[SHAMT0:%.*]] | |
506 ; CHECK-NEXT: call void @use32(i32 [[T0]]) | |
507 ; CHECK-NEXT: [[T1:%.*]] = shl i32 [[Y:%.*]], [[SHAMT1:%.*]] | |
508 ; CHECK-NEXT: call void @use32(i32 [[T1]]) | |
509 ; CHECK-NEXT: [[T2:%.*]] = and i32 [[T1]], [[T0]] | |
510 ; CHECK-NEXT: call void @use32(i32 [[T2]]) | |
511 ; CHECK-NEXT: [[T3:%.*]] = icmp ne i32 [[T2]], 0 | |
512 ; CHECK-NEXT: ret i1 [[T3]] | |
513 ; | |
514 %t0 = lshr i32 %x, %shamt0 | |
515 call void @use32(i32 %t0) | |
516 %t1 = shl i32 %y, %shamt1 | |
517 call void @use32(i32 %t1) | |
518 %t2 = and i32 %t1, %t0 | |
519 call void @use32(i32 %t2) | |
520 %t3 = icmp ne i32 %t2, 0 | |
521 ret i1 %t3 | |
522 } | |
523 | |
524 ; Shift-of-const | |
525 | |
526 ; Ok, non-truncated shift is of constant; | |
527 define i1 @t32_shift_of_const_oneuse0(i32 %x, i32 %y, i32 %len) { | |
528 ; CHECK-LABEL: @t32_shift_of_const_oneuse0( | |
529 ; CHECK-NEXT: [[T0:%.*]] = sub i32 32, [[LEN:%.*]] | |
530 ; CHECK-NEXT: call void @use32(i32 [[T0]]) | |
531 ; CHECK-NEXT: [[T1:%.*]] = lshr i32 -52543054, [[T0]] | |
532 ; CHECK-NEXT: call void @use32(i32 [[T1]]) | |
533 ; CHECK-NEXT: [[T2:%.*]] = add i32 [[LEN]], -1 | |
534 ; CHECK-NEXT: call void @use32(i32 [[T2]]) | |
535 ; CHECK-NEXT: [[T3:%.*]] = shl i32 [[Y:%.*]], [[T2]] | |
536 ; CHECK-NEXT: call void @use32(i32 [[T3]]) | |
537 ; CHECK-NEXT: [[TMP1:%.*]] = and i32 [[Y]], 1 | |
538 ; CHECK-NEXT: [[TMP2:%.*]] = icmp ne i32 [[TMP1]], 0 | |
539 ; CHECK-NEXT: ret i1 [[TMP2]] | |
540 ; | |
541 %t0 = sub i32 32, %len | |
542 call void @use32(i32 %t0) | |
543 %t1 = lshr i32 4242424242, %t0 ; shift-of-constant | |
544 call void @use32(i32 %t1) | |
545 %t2 = add i32 %len, -1 | |
546 call void @use32(i32 %t2) | |
547 %t3 = shl i32 %y, %t2 | |
548 call void @use32(i32 %t3) | |
549 %t4 = and i32 %t1, %t3 ; no extra uses | |
550 %t5 = icmp ne i32 %t4, 0 | |
551 ret i1 %t5 | |
552 } | |
553 ; Ok, truncated shift is of constant; | |
554 define i1 @t33_shift_of_const_oneuse1(i32 %x, i32 %y, i32 %len) { | |
555 ; CHECK-LABEL: @t33_shift_of_const_oneuse1( | |
556 ; CHECK-NEXT: [[T0:%.*]] = sub i32 32, [[LEN:%.*]] | |
557 ; CHECK-NEXT: call void @use32(i32 [[T0]]) | |
558 ; CHECK-NEXT: [[T1:%.*]] = lshr i32 [[X:%.*]], [[T0]] | |
559 ; CHECK-NEXT: call void @use32(i32 [[T1]]) | |
560 ; CHECK-NEXT: [[T2:%.*]] = add i32 [[LEN]], -1 | |
561 ; CHECK-NEXT: call void @use32(i32 [[T2]]) | |
562 ; CHECK-NEXT: [[T3:%.*]] = shl i32 -52543054, [[T2]] | |
563 ; CHECK-NEXT: call void @use32(i32 [[T3]]) | |
564 ; CHECK-NEXT: ret i1 false | |
565 ; | |
566 %t0 = sub i32 32, %len | |
567 call void @use32(i32 %t0) | |
568 %t1 = lshr i32 %x, %t0 ; shift-of-constant | |
569 call void @use32(i32 %t1) | |
570 %t2 = add i32 %len, -1 | |
571 call void @use32(i32 %t2) | |
572 %t3 = shl i32 4242424242, %t2 | |
573 call void @use32(i32 %t3) | |
574 %t4 = and i32 %t1, %t3 ; no extra uses | |
575 %t5 = icmp ne i32 %t4, 0 | |
576 ret i1 %t5 | |
577 } | |
578 | |
579 ; Commutativity with extra uses | |
580 | |
581 define i1 @t34_commutativity0_oneuse0(i32 %x) { | |
582 ; CHECK-LABEL: @t34_commutativity0_oneuse0( | |
583 ; CHECK-NEXT: [[Y:%.*]] = call i32 @gen32() | |
584 ; CHECK-NEXT: [[T0:%.*]] = lshr i32 [[X:%.*]], 1 | |
585 ; CHECK-NEXT: call void @use32(i32 [[T0]]) | |
586 ; CHECK-NEXT: [[TMP1:%.*]] = lshr i32 [[X]], 2 | |
587 ; CHECK-NEXT: [[TMP2:%.*]] = and i32 [[TMP1]], [[Y]] | |
588 ; CHECK-NEXT: [[TMP3:%.*]] = icmp ne i32 [[TMP2]], 0 | |
589 ; CHECK-NEXT: ret i1 [[TMP3]] | |
590 ; | |
591 %y = call i32 @gen32() | |
592 %t0 = lshr i32 %x, 1 | |
593 call void @use32(i32 %t0) | |
594 %t1 = shl i32 %y, 1 | |
595 %t2 = and i32 %t1, %t0 | |
596 %t3 = icmp ne i32 %t2, 0 | |
597 ret i1 %t3 | |
598 } | |
599 define i1 @t35_commutativity0_oneuse1(i32 %x) { | |
600 ; CHECK-LABEL: @t35_commutativity0_oneuse1( | |
601 ; CHECK-NEXT: [[Y:%.*]] = call i32 @gen32() | |
602 ; CHECK-NEXT: [[T1:%.*]] = shl i32 [[Y]], 1 | |
603 ; CHECK-NEXT: call void @use32(i32 [[T1]]) | |
604 ; CHECK-NEXT: [[TMP1:%.*]] = lshr i32 [[X:%.*]], 2 | |
605 ; CHECK-NEXT: [[TMP2:%.*]] = and i32 [[TMP1]], [[Y]] | |
606 ; CHECK-NEXT: [[TMP3:%.*]] = icmp ne i32 [[TMP2]], 0 | |
607 ; CHECK-NEXT: ret i1 [[TMP3]] | |
608 ; | |
609 %y = call i32 @gen32() | |
610 %t0 = lshr i32 %x, 1 | |
611 %t1 = shl i32 %y, 1 | |
612 call void @use32(i32 %t1) | |
613 %t2 = and i32 %t1, %t0 | |
614 %t3 = icmp ne i32 %t2, 0 | |
615 ret i1 %t3 | |
616 } | |
617 | |
618 define i1 @t36_commutativity1_oneuse0(i32 %y) { | |
619 ; CHECK-LABEL: @t36_commutativity1_oneuse0( | |
620 ; CHECK-NEXT: [[X:%.*]] = call i32 @gen32() | |
621 ; CHECK-NEXT: [[T0:%.*]] = lshr i32 [[X]], 1 | |
622 ; CHECK-NEXT: call void @use32(i32 [[T0]]) | |
623 ; CHECK-NEXT: [[TMP1:%.*]] = lshr i32 [[X]], 2 | |
624 ; CHECK-NEXT: [[TMP2:%.*]] = and i32 [[TMP1]], [[Y:%.*]] | |
625 ; CHECK-NEXT: [[TMP3:%.*]] = icmp ne i32 [[TMP2]], 0 | |
626 ; CHECK-NEXT: ret i1 [[TMP3]] | |
627 ; | |
628 %x = call i32 @gen32() | |
629 %t0 = lshr i32 %x, 1 | |
630 call void @use32(i32 %t0) | |
631 %t1 = shl i32 %y, 1 | |
632 %t2 = and i32 %t0, %t1 ; "swapped" | |
633 %t3 = icmp ne i32 %t2, 0 | |
634 ret i1 %t3 | |
635 } | |
636 define i1 @t37_commutativity1_oneuse1(i32 %y) { | |
637 ; CHECK-LABEL: @t37_commutativity1_oneuse1( | |
638 ; CHECK-NEXT: [[X:%.*]] = call i32 @gen32() | |
639 ; CHECK-NEXT: [[T1:%.*]] = shl i32 [[Y:%.*]], 1 | |
640 ; CHECK-NEXT: call void @use32(i32 [[T1]]) | |
641 ; CHECK-NEXT: [[TMP1:%.*]] = lshr i32 [[X]], 2 | |
642 ; CHECK-NEXT: [[TMP2:%.*]] = and i32 [[TMP1]], [[Y]] | |
643 ; CHECK-NEXT: [[TMP3:%.*]] = icmp ne i32 [[TMP2]], 0 | |
644 ; CHECK-NEXT: ret i1 [[TMP3]] | |
645 ; | |
646 %x = call i32 @gen32() | |
647 %t0 = lshr i32 %x, 1 | |
648 %t1 = shl i32 %y, 1 | |
649 call void @use32(i32 %t1) | |
650 %t2 = and i32 %t0, %t1 ; "swapped" | |
651 %t3 = icmp ne i32 %t2, 0 | |
652 ret i1 %t3 | |
653 } | |
654 | |
655 ; Negative tests | |
656 define <2 x i1> @n38_overshift(<2 x i32> %x, <2 x i32> %y) { | |
657 ; CHECK-LABEL: @n38_overshift( | |
658 ; CHECK-NEXT: [[T0:%.*]] = lshr <2 x i32> [[X:%.*]], <i32 15, i32 1> | |
659 ; CHECK-NEXT: [[T1:%.*]] = shl <2 x i32> [[Y:%.*]], <i32 17, i32 1> | |
660 ; CHECK-NEXT: [[T2:%.*]] = and <2 x i32> [[T1]], [[T0]] | |
661 ; CHECK-NEXT: [[T3:%.*]] = icmp ne <2 x i32> [[T2]], zeroinitializer | |
662 ; CHECK-NEXT: ret <2 x i1> [[T3]] | |
663 ; | |
664 %t0 = lshr <2 x i32> %x, <i32 15, i32 1> | |
665 %t1 = shl <2 x i32> %y, <i32 17, i32 1> | |
666 %t2 = and <2 x i32> %t1, %t0 | |
667 %t3 = icmp ne <2 x i32> %t2, <i32 0, i32 0> | |
668 ret <2 x i1> %t3 | |
669 } | |
670 | |
671 ; As usual, don't crash given constantexpr's :/ | |
672 @f.a = internal global i16 0 | |
673 define i1 @constantexpr() { | |
674 entry: | |
675 %0 = load i16, i16* @f.a | |
676 %shr = ashr i16 %0, 1 | |
677 %shr1 = ashr i16 %shr, zext (i1 icmp ne (i16 ptrtoint (i16* @f.a to i16), i16 1) to i16) | |
678 %and = and i16 %shr1, 1 | |
679 %tobool = icmp ne i16 %and, 0 | |
680 ret i1 %tobool | |
681 } |