1 ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2 ; RUN: opt %s -instcombine -S | FileCheck %s
5 ; (x shiftopcode Q) shiftopcode K
6 ; we should rewrite it as
7 ; x shiftopcode (Q+K) iff (Q+K) u< bitwidth(x)
8 ; This is valid for any shift, but they must be identical.
9 ; THIS FOLD DOES *NOT* REQUIRE ANY 'exact'/'nuw'/`nsw` FLAGS!
13 define i32 @t0(i32 %x, i32 %y) {
15 ; CHECK-NEXT: [[T3:%.*]] = lshr i32 [[X:%.*]], 30
16 ; CHECK-NEXT: ret i32 [[T3]]
19 %t1 = lshr i32 %x, %t0
21 %t3 = lshr exact i32 %t1, %t2 ; while there, test that we don't propagate partial 'exact' flag
25 define <2 x i32> @t1_vec_splat(<2 x i32> %x, <2 x i32> %y) {
26 ; CHECK-LABEL: @t1_vec_splat(
27 ; CHECK-NEXT: [[T3:%.*]] = lshr <2 x i32> [[X:%.*]], <i32 30, i32 30>
28 ; CHECK-NEXT: ret <2 x i32> [[T3]]
30 %t0 = sub <2 x i32> <i32 32, i32 32>, %y
31 %t1 = lshr <2 x i32> %x, %t0
32 %t2 = add <2 x i32> %y, <i32 -2, i32 -2>
33 %t3 = lshr <2 x i32> %t1, %t2
37 define <2 x i32> @t2_vec_nonsplat(<2 x i32> %x, <2 x i32> %y) {
38 ; CHECK-LABEL: @t2_vec_nonsplat(
39 ; CHECK-NEXT: [[T3:%.*]] = lshr <2 x i32> [[X:%.*]], <i32 30, i32 30>
40 ; CHECK-NEXT: ret <2 x i32> [[T3]]
42 %t0 = sub <2 x i32> <i32 32, i32 30>, %y
43 %t1 = lshr <2 x i32> %x, %t0
44 %t2 = add <2 x i32> %y, <i32 -2, i32 0>
45 %t3 = lshr <2 x i32> %t1, %t2
51 define <3 x i32> @t3_vec_nonsplat_undef0(<3 x i32> %x, <3 x i32> %y) {
52 ; CHECK-LABEL: @t3_vec_nonsplat_undef0(
53 ; CHECK-NEXT: [[T3:%.*]] = lshr <3 x i32> [[X:%.*]], <i32 30, i32 undef, i32 30>
54 ; CHECK-NEXT: ret <3 x i32> [[T3]]
56 %t0 = sub <3 x i32> <i32 32, i32 undef, i32 32>, %y
57 %t1 = lshr <3 x i32> %x, %t0
58 %t2 = add <3 x i32> %y, <i32 -2, i32 -2, i32 -2>
59 %t3 = lshr <3 x i32> %t1, %t2
63 define <3 x i32> @t4_vec_nonsplat_undef1(<3 x i32> %x, <3 x i32> %y) {
64 ; CHECK-LABEL: @t4_vec_nonsplat_undef1(
65 ; CHECK-NEXT: [[T3:%.*]] = lshr <3 x i32> [[X:%.*]], <i32 30, i32 undef, i32 30>
66 ; CHECK-NEXT: ret <3 x i32> [[T3]]
68 %t0 = sub <3 x i32> <i32 32, i32 32, i32 32>, %y
69 %t1 = lshr <3 x i32> %x, %t0
70 %t2 = add <3 x i32> %y, <i32 -2, i32 undef, i32 -2>
71 %t3 = lshr <3 x i32> %t1, %t2
75 define <3 x i32> @t5_vec_nonsplat_undef1(<3 x i32> %x, <3 x i32> %y) {
76 ; CHECK-LABEL: @t5_vec_nonsplat_undef1(
77 ; CHECK-NEXT: [[T3:%.*]] = lshr <3 x i32> [[X:%.*]], <i32 30, i32 undef, i32 30>
78 ; CHECK-NEXT: ret <3 x i32> [[T3]]
80 %t0 = sub <3 x i32> <i32 32, i32 undef, i32 32>, %y
81 %t1 = lshr <3 x i32> %x, %t0
82 %t2 = add <3 x i32> %y, <i32 -2, i32 undef, i32 -2>
83 %t3 = lshr <3 x i32> %t1, %t2
87 ; Some other shift opcodes
88 define i32 @t6_shl(i32 %x, i32 %y) {
89 ; CHECK-LABEL: @t6_shl(
90 ; CHECK-NEXT: [[T3:%.*]] = shl i32 [[X:%.*]], 30
91 ; CHECK-NEXT: ret i32 [[T3]]
94 %t1 = shl nuw i32 %x, %t0 ; while there, test that we don't propagate partial 'nuw' flag
96 %t3 = shl nsw i32 %t1, %t2 ; while there, test that we don't propagate partial 'nsw' flag
99 define i32 @t7_ashr(i32 %x, i32 %y) {
100 ; CHECK-LABEL: @t7_ashr(
101 ; CHECK-NEXT: [[T3:%.*]] = ashr i32 [[X:%.*]], 30
102 ; CHECK-NEXT: ret i32 [[T3]]
105 %t1 = ashr exact i32 %x, %t0 ; while there, test that we don't propagate partial 'exact' flag
107 %t3 = ashr i32 %t1, %t2
111 ; If the same flag is present on both shifts, it can be kept.
112 define i32 @t8_lshr_exact_flag_preservation(i32 %x, i32 %y) {
113 ; CHECK-LABEL: @t8_lshr_exact_flag_preservation(
114 ; CHECK-NEXT: [[T3:%.*]] = lshr exact i32 [[X:%.*]], 30
115 ; CHECK-NEXT: ret i32 [[T3]]
118 %t1 = lshr exact i32 %x, %t0
120 %t3 = lshr exact i32 %t1, %t2
123 define i32 @t9_ashr_exact_flag_preservation(i32 %x, i32 %y) {
124 ; CHECK-LABEL: @t9_ashr_exact_flag_preservation(
125 ; CHECK-NEXT: [[T3:%.*]] = ashr exact i32 [[X:%.*]], 30
126 ; CHECK-NEXT: ret i32 [[T3]]
129 %t1 = ashr exact i32 %x, %t0
131 %t3 = ashr exact i32 %t1, %t2
134 define i32 @t10_shl_nuw_flag_preservation(i32 %x, i32 %y) {
135 ; CHECK-LABEL: @t10_shl_nuw_flag_preservation(
136 ; CHECK-NEXT: [[T3:%.*]] = shl nuw i32 [[X:%.*]], 30
137 ; CHECK-NEXT: ret i32 [[T3]]
140 %t1 = shl nuw i32 %x, %t0
142 %t3 = shl nuw nsw i32 %t1, %t2 ; only 'nuw' should be propagated.
145 define i32 @t11_shl_nsw_flag_preservation(i32 %x, i32 %y) {
146 ; CHECK-LABEL: @t11_shl_nsw_flag_preservation(
147 ; CHECK-NEXT: [[T3:%.*]] = shl nsw i32 [[X:%.*]], 30
148 ; CHECK-NEXT: ret i32 [[T3]]
151 %t1 = shl nsw i32 %x, %t0
153 %t3 = shl nsw nuw i32 %t1, %t2 ; only 'nuw' should be propagated.
157 ; Reduced from https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=15587
158 @X = external global i32
159 define i64 @constantexpr() {
160 ; CHECK-LABEL: @constantexpr(
161 ; CHECK-NEXT: ret i64 0
164 %L = load i64, i64* %A
165 %V = add i64 ptrtoint (i32* @X to i64), 0
167 %B4 = ashr i64 %B2, %L
168 %B = and i64 undef, %B4
172 ; No one-use tests since we will only produce a single instruction here.
176 ; Can't fold, total shift would be 32
177 define i32 @n12(i32 %x, i32 %y) {
179 ; CHECK-NEXT: [[T0:%.*]] = sub i32 30, [[Y:%.*]]
180 ; CHECK-NEXT: [[T1:%.*]] = lshr i32 [[X:%.*]], [[T0]]
181 ; CHECK-NEXT: [[T2:%.*]] = add i32 [[Y]], 2
182 ; CHECK-NEXT: [[T3:%.*]] = lshr i32 [[T1]], [[T2]]
183 ; CHECK-NEXT: ret i32 [[T3]]
186 %t1 = lshr i32 %x, %t0
188 %t3 = lshr i32 %t1, %t2
191 ; Can't fold, for second channel the shift would 32
192 define <2 x i32> @t13_vec(<2 x i32> %x, <2 x i32> %y) {
193 ; CHECK-LABEL: @t13_vec(
194 ; CHECK-NEXT: [[T0:%.*]] = sub <2 x i32> <i32 32, i32 30>, [[Y:%.*]]
195 ; CHECK-NEXT: [[T1:%.*]] = lshr <2 x i32> [[X:%.*]], [[T0]]
196 ; CHECK-NEXT: [[T2:%.*]] = add <2 x i32> [[Y]], <i32 -2, i32 2>
197 ; CHECK-NEXT: [[T3:%.*]] = lshr <2 x i32> [[T1]], [[T2]]
198 ; CHECK-NEXT: ret <2 x i32> [[T3]]
200 %t0 = sub <2 x i32> <i32 32, i32 30>, %y
201 %t1 = lshr <2 x i32> %x, %t0
202 %t2 = add <2 x i32> %y, <i32 -2, i32 2>
203 %t3 = lshr <2 x i32> %t1, %t2
207 ; If we have different right-shifts, in general, we can't do anything with it.
208 define i32 @n13(i32 %x, i32 %y) {
210 ; CHECK-NEXT: [[T0:%.*]] = sub i32 32, [[Y:%.*]]
211 ; CHECK-NEXT: [[T1:%.*]] = lshr i32 [[X:%.*]], [[T0]]
212 ; CHECK-NEXT: [[T2:%.*]] = add i32 [[Y]], -2
213 ; CHECK-NEXT: [[T3:%.*]] = ashr i32 [[T1]], [[T2]]
214 ; CHECK-NEXT: ret i32 [[T3]]
217 %t1 = lshr i32 %x, %t0
219 %t3 = ashr i32 %t1, %t2
222 define i32 @n14(i32 %x, i32 %y) {
224 ; CHECK-NEXT: [[T0:%.*]] = sub i32 32, [[Y:%.*]]
225 ; CHECK-NEXT: [[T1:%.*]] = lshr i32 [[X:%.*]], [[T0]]
226 ; CHECK-NEXT: [[T2:%.*]] = add i32 [[Y]], -1
227 ; CHECK-NEXT: [[T3:%.*]] = ashr i32 [[T1]], [[T2]]
228 ; CHECK-NEXT: ret i32 [[T3]]
231 %t1 = lshr i32 %x, %t0
233 %t3 = ashr i32 %t1, %t2
236 define i32 @n15(i32 %x, i32 %y) {
238 ; CHECK-NEXT: [[T0:%.*]] = sub i32 32, [[Y:%.*]]
239 ; CHECK-NEXT: [[T1:%.*]] = ashr i32 [[X:%.*]], [[T0]]
240 ; CHECK-NEXT: [[T2:%.*]] = add i32 [[Y]], -2
241 ; CHECK-NEXT: [[T3:%.*]] = lshr i32 [[T1]], [[T2]]
242 ; CHECK-NEXT: ret i32 [[T3]]
245 %t1 = ashr i32 %x, %t0
247 %t3 = lshr i32 %t1, %t2
250 define i32 @n16(i32 %x, i32 %y) {
252 ; CHECK-NEXT: [[T0:%.*]] = sub i32 32, [[Y:%.*]]
253 ; CHECK-NEXT: [[T1:%.*]] = ashr i32 [[X:%.*]], [[T0]]
254 ; CHECK-NEXT: [[T2:%.*]] = add i32 [[Y]], -1
255 ; CHECK-NEXT: [[T3:%.*]] = lshr i32 [[T1]], [[T2]]
256 ; CHECK-NEXT: ret i32 [[T3]]
259 %t1 = ashr i32 %x, %t0
261 %t3 = lshr i32 %t1, %t2
265 ; If the shift direction is different, then this should be handled elsewhere.
266 define i32 @n17(i32 %x, i32 %y) {
268 ; CHECK-NEXT: [[T0:%.*]] = sub i32 32, [[Y:%.*]]
269 ; CHECK-NEXT: [[T1:%.*]] = shl i32 [[X:%.*]], [[T0]]
270 ; CHECK-NEXT: [[T2:%.*]] = add i32 [[Y]], -1
271 ; CHECK-NEXT: [[T3:%.*]] = lshr i32 [[T1]], [[T2]]
272 ; CHECK-NEXT: ret i32 [[T3]]
275 %t1 = shl i32 %x, %t0
277 %t3 = lshr i32 %t1, %t2
280 define i32 @n18(i32 %x, i32 %y) {
282 ; CHECK-NEXT: [[T0:%.*]] = sub i32 32, [[Y:%.*]]
283 ; CHECK-NEXT: [[T1:%.*]] = shl i32 [[X:%.*]], [[T0]]
284 ; CHECK-NEXT: [[T2:%.*]] = add i32 [[Y]], -1
285 ; CHECK-NEXT: [[T3:%.*]] = ashr i32 [[T1]], [[T2]]
286 ; CHECK-NEXT: ret i32 [[T3]]
289 %t1 = shl i32 %x, %t0
291 %t3 = ashr i32 %t1, %t2
294 define i32 @n19(i32 %x, i32 %y) {
296 ; CHECK-NEXT: [[T0:%.*]] = sub i32 32, [[Y:%.*]]
297 ; CHECK-NEXT: [[T1:%.*]] = lshr i32 [[X:%.*]], [[T0]]
298 ; CHECK-NEXT: [[T2:%.*]] = add i32 [[Y]], -1
299 ; CHECK-NEXT: [[T3:%.*]] = shl i32 [[T1]], [[T2]]
300 ; CHECK-NEXT: ret i32 [[T3]]
303 %t1 = lshr i32 %x, %t0
305 %t3 = shl i32 %t1, %t2
308 define i32 @n20(i32 %x, i32 %y) {
310 ; CHECK-NEXT: [[T0:%.*]] = sub i32 32, [[Y:%.*]]
311 ; CHECK-NEXT: [[T1:%.*]] = ashr i32 [[X:%.*]], [[T0]]
312 ; CHECK-NEXT: [[T2:%.*]] = add i32 [[Y]], -1
313 ; CHECK-NEXT: [[T3:%.*]] = shl i32 [[T1]], [[T2]]
314 ; CHECK-NEXT: ret i32 [[T3]]
317 %t1 = ashr i32 %x, %t0
319 %t3 = shl i32 %t1, %t2