1 ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2 ; RUN: opt < %s -passes=instcombine -S | FileCheck %s
6 define i64 @match_unsigned(i64 %x) {
7 ; CHECK-LABEL: @match_unsigned(
8 ; CHECK-NEXT: [[UREM:%.*]] = urem i64 [[X:%.*]], 19136
9 ; CHECK-NEXT: ret i64 [[UREM]]
12 %t1 = udiv i64 %x, 299
13 %t2 = urem i64 %t1, 64
14 %t3 = mul i64 %t2, 299
19 define <2 x i64> @match_unsigned_vector(<2 x i64> %x) {
20 ; CHECK-LABEL: @match_unsigned_vector(
22 ; CHECK-NEXT: [[UREM:%.*]] = urem <2 x i64> [[X:%.*]], splat (i64 19136)
23 ; CHECK-NEXT: ret <2 x i64> [[UREM]]
26 %tmp = urem <2 x i64> %x, <i64 299, i64 299>
27 %tmp1 = udiv <2 x i64> %x, <i64 299, i64 299>
28 %tmp2 = urem <2 x i64> %tmp1, <i64 64, i64 64>
29 %tmp3 = mul <2 x i64> %tmp2, <i64 299, i64 299>
30 %tmp4 = add <2 x i64> %tmp, %tmp3
33 define i64 @match_andAsRem_lshrAsDiv_shlAsMul(i64 %x) {
34 ; CHECK-LABEL: @match_andAsRem_lshrAsDiv_shlAsMul(
35 ; CHECK-NEXT: [[UREM:%.*]] = urem i64 [[X:%.*]], 576
36 ; CHECK-NEXT: ret i64 [[UREM]]
46 define i64 @match_signed(i64 %x) {
47 ; CHECK-LABEL: @match_signed(
48 ; CHECK-NEXT: [[SREM1:%.*]] = srem i64 [[X:%.*]], 172224
49 ; CHECK-NEXT: ret i64 [[SREM1]]
52 %t1 = sdiv i64 %x, 299
53 %t2 = srem i64 %t1, 64
54 %t3 = sdiv i64 %x, 19136
56 %t5 = mul i64 %t2, 299
58 %t7 = mul i64 %t4, 19136
59 %t8 = add i64 %t6, %t7
63 define <2 x i64> @match_signed_vector(<2 x i64> %x) {
64 ; CHECK-LABEL: @match_signed_vector(
66 ; CHECK-NEXT: [[SREM1:%.*]] = srem <2 x i64> [[X:%.*]], splat (i64 172224)
67 ; CHECK-NEXT: ret <2 x i64> [[SREM1]]
70 %tmp = srem <2 x i64> %x, <i64 299, i64 299>
71 %tmp1 = sdiv <2 x i64> %x, <i64 299, i64 299>
72 %tmp2 = srem <2 x i64> %tmp1, <i64 64, i64 64>
73 %tmp3 = sdiv <2 x i64> %x, <i64 19136, i64 19136>
74 %tmp4 = srem <2 x i64> %tmp3, <i64 9, i64 9>
75 %tmp5 = mul <2 x i64> %tmp2, <i64 299, i64 299>
76 %tmp6 = add <2 x i64> %tmp, %tmp5
77 %tmp7 = mul <2 x i64> %tmp4, <i64 19136, i64 19136>
78 %tmp8 = add <2 x i64> %tmp6, %tmp7
82 define i64 @not_match_inconsistent_signs(i64 %x) {
83 ; CHECK-LABEL: @not_match_inconsistent_signs(
84 ; CHECK-NEXT: [[T:%.*]] = urem i64 [[X:%.*]], 299
85 ; CHECK-NEXT: [[T1:%.*]] = sdiv i64 [[X]], 299
86 ; CHECK-NEXT: [[T2:%.*]] = and i64 [[T1]], 63
87 ; CHECK-NEXT: [[T3:%.*]] = mul nuw nsw i64 [[T2]], 299
88 ; CHECK-NEXT: [[T4:%.*]] = add nuw nsw i64 [[T]], [[T3]]
89 ; CHECK-NEXT: ret i64 [[T4]]
92 %t1 = sdiv i64 %x, 299
93 %t2 = urem i64 %t1, 64
94 %t3 = mul i64 %t2, 299
99 define i64 @not_match_inconsistent_values(i64 %x) {
100 ; CHECK-LABEL: @not_match_inconsistent_values(
101 ; CHECK-NEXT: [[T:%.*]] = urem i64 [[X:%.*]], 299
102 ; CHECK-NEXT: [[T1:%.*]] = udiv i64 [[X]], 29
103 ; CHECK-NEXT: [[T2:%.*]] = and i64 [[T1]], 63
104 ; CHECK-NEXT: [[T3:%.*]] = mul nuw nsw i64 [[T2]], 299
105 ; CHECK-NEXT: [[T4:%.*]] = add nuw nsw i64 [[T]], [[T3]]
106 ; CHECK-NEXT: ret i64 [[T4]]
108 %t = urem i64 %x, 299
109 %t1 = udiv i64 %x, 29
110 %t2 = urem i64 %t1, 64
111 %t3 = mul i64 %t2, 299
112 %t4 = add i64 %t, %t3
116 define i32 @not_match_overflow(i32 %x) {
117 ; CHECK-LABEL: @not_match_overflow(
118 ; CHECK-NEXT: [[X_FR:%.*]] = freeze i32 [[X:%.*]]
119 ; CHECK-NEXT: [[T:%.*]] = urem i32 [[X_FR]], 299
120 ; CHECK-NEXT: [[TMP1:%.*]] = urem i32 [[X_FR]], 299
121 ; CHECK-NEXT: [[T3:%.*]] = sub nuw i32 [[X_FR]], [[TMP1]]
122 ; CHECK-NEXT: [[T4:%.*]] = add i32 [[T]], [[T3]]
123 ; CHECK-NEXT: ret i32 [[T4]]
125 %t = urem i32 %x, 299
126 %t1 = udiv i32 %x, 299
127 %t2 = urem i32 %t1, 147483647
128 %t3 = mul i32 %t2, 299
129 %t4 = add i32 %t, %t3
133 ; Tests from PR76128.
134 define i32 @fold_add_udiv_urem(i32 noundef %val) {
135 ; CHECK-LABEL: @fold_add_udiv_urem(
137 ; CHECK-NEXT: [[DIV:%.*]] = udiv i32 [[VAL:%.*]], 10
138 ; CHECK-NEXT: [[TMP0:%.*]] = mul nuw i32 [[DIV]], 6
139 ; CHECK-NEXT: [[ADD:%.*]] = add i32 [[TMP0]], [[VAL]]
140 ; CHECK-NEXT: ret i32 [[ADD]]
143 %div = udiv i32 %val, 10
144 %shl = shl i32 %div, 4
145 %rem = urem i32 %val, 10
146 %add = add i32 %shl, %rem
149 define i32 @fold_add_sdiv_srem(i32 noundef %val) {
150 ; CHECK-LABEL: @fold_add_sdiv_srem(
152 ; CHECK-NEXT: [[DIV:%.*]] = sdiv i32 [[VAL:%.*]], 10
153 ; CHECK-NEXT: [[TMP0:%.*]] = mul nsw i32 [[DIV]], 6
154 ; CHECK-NEXT: [[ADD:%.*]] = add i32 [[TMP0]], [[VAL]]
155 ; CHECK-NEXT: ret i32 [[ADD]]
158 %div = sdiv i32 %val, 10
159 %shl = shl i32 %div, 4
160 %rem = srem i32 %val, 10
161 %add = add i32 %shl, %rem
164 define i32 @fold_add_udiv_urem_to_mul(i32 noundef %val) {
165 ; CHECK-LABEL: @fold_add_udiv_urem_to_mul(
167 ; CHECK-NEXT: [[ADD:%.*]] = mul i32 [[VAL:%.*]], 3
168 ; CHECK-NEXT: ret i32 [[ADD]]
171 %div = udiv i32 %val, 7
172 %mul1 = mul i32 %div, 21
173 %rem = urem i32 %val, 7
174 %mul2 = mul i32 %rem, 3
175 %add = add i32 %mul1, %mul2
178 define i32 @fold_add_udiv_urem_to_mul_multiuse(i32 noundef %val) {
179 ; CHECK-LABEL: @fold_add_udiv_urem_to_mul_multiuse(
181 ; CHECK-NEXT: [[REM:%.*]] = urem i32 [[VAL:%.*]], 7
182 ; CHECK-NEXT: call void @use(i32 [[REM]])
183 ; CHECK-NEXT: [[ADD:%.*]] = mul i32 [[VAL]], 3
184 ; CHECK-NEXT: ret i32 [[ADD]]
187 %div = udiv i32 %val, 7
188 %mul1 = mul i32 %div, 21
189 %rem = urem i32 %val, 7
190 call void @use(i32 %rem)
191 %mul2 = mul i32 %rem, 3
192 %add = add i32 %mul1, %mul2
195 define i32 @fold_add_udiv_urem_commuted(i32 noundef %val) {
196 ; CHECK-LABEL: @fold_add_udiv_urem_commuted(
198 ; CHECK-NEXT: [[DIV:%.*]] = udiv i32 [[VAL:%.*]], 10
199 ; CHECK-NEXT: [[TMP0:%.*]] = mul nuw i32 [[DIV]], 6
200 ; CHECK-NEXT: [[ADD:%.*]] = add i32 [[TMP0]], [[VAL]]
201 ; CHECK-NEXT: ret i32 [[ADD]]
204 %div = udiv i32 %val, 10
205 %shl = shl i32 %div, 4
206 %rem = urem i32 %val, 10
207 %add = add i32 %rem, %shl
210 define i32 @fold_add_udiv_urem_or_disjoint(i32 noundef %val) {
211 ; CHECK-LABEL: @fold_add_udiv_urem_or_disjoint(
213 ; CHECK-NEXT: [[DIV:%.*]] = udiv i32 [[VAL:%.*]], 10
214 ; CHECK-NEXT: [[TMP0:%.*]] = mul nuw i32 [[DIV]], 6
215 ; CHECK-NEXT: [[ADD:%.*]] = add i32 [[TMP0]], [[VAL]]
216 ; CHECK-NEXT: ret i32 [[ADD]]
219 %div = udiv i32 %val, 10
220 %shl = shl i32 %div, 4
221 %rem = urem i32 %val, 10
222 %add = or disjoint i32 %shl, %rem
226 define i32 @fold_add_udiv_urem_without_noundef(i32 %val) {
227 ; CHECK-LABEL: @fold_add_udiv_urem_without_noundef(
229 ; CHECK-NEXT: [[DIV:%.*]] = udiv i32 [[VAL:%.*]], 10
230 ; CHECK-NEXT: [[SHL:%.*]] = shl i32 [[DIV]], 4
231 ; CHECK-NEXT: [[REM:%.*]] = urem i32 [[VAL]], 10
232 ; CHECK-NEXT: [[ADD:%.*]] = or disjoint i32 [[SHL]], [[REM]]
233 ; CHECK-NEXT: ret i32 [[ADD]]
236 %div = udiv i32 %val, 10
237 %shl = shl i32 %div, 4
238 %rem = urem i32 %val, 10
239 %add = add i32 %shl, %rem
242 define i32 @fold_add_udiv_urem_multiuse_mul(i32 noundef %val) {
243 ; CHECK-LABEL: @fold_add_udiv_urem_multiuse_mul(
245 ; CHECK-NEXT: [[DIV:%.*]] = udiv i32 [[VAL:%.*]], 10
246 ; CHECK-NEXT: [[SHL:%.*]] = shl i32 [[DIV]], 4
247 ; CHECK-NEXT: call void @use(i32 [[SHL]])
248 ; CHECK-NEXT: [[REM:%.*]] = urem i32 [[VAL]], 10
249 ; CHECK-NEXT: [[ADD:%.*]] = or disjoint i32 [[SHL]], [[REM]]
250 ; CHECK-NEXT: ret i32 [[ADD]]
253 %div = udiv i32 %val, 10
254 %shl = shl i32 %div, 4
255 call void @use(i32 %shl)
256 %rem = urem i32 %val, 10
257 %add = add i32 %shl, %rem
260 define i32 @fold_add_udiv_srem(i32 noundef %val) {
261 ; CHECK-LABEL: @fold_add_udiv_srem(
263 ; CHECK-NEXT: [[DIV:%.*]] = udiv i32 [[VAL:%.*]], 10
264 ; CHECK-NEXT: [[SHL:%.*]] = shl i32 [[DIV]], 4
265 ; CHECK-NEXT: [[REM:%.*]] = srem i32 [[VAL]], 10
266 ; CHECK-NEXT: [[ADD:%.*]] = add i32 [[SHL]], [[REM]]
267 ; CHECK-NEXT: ret i32 [[ADD]]
270 %div = udiv i32 %val, 10
271 %shl = shl i32 %div, 4
272 %rem = srem i32 %val, 10
273 %add = add i32 %shl, %rem
276 define i32 @fold_add_udiv_urem_non_constant(i32 noundef %val, i32 noundef %c) {
277 ; CHECK-LABEL: @fold_add_udiv_urem_non_constant(
279 ; CHECK-NEXT: [[DIV:%.*]] = udiv i32 [[VAL:%.*]], [[C:%.*]]
280 ; CHECK-NEXT: [[SHL:%.*]] = shl i32 [[DIV]], 4
281 ; CHECK-NEXT: [[REM:%.*]] = urem i32 [[VAL]], [[C]]
282 ; CHECK-NEXT: [[ADD:%.*]] = add i32 [[SHL]], [[REM]]
283 ; CHECK-NEXT: ret i32 [[ADD]]
286 %div = udiv i32 %val, %c
287 %shl = shl i32 %div, 4
288 %rem = urem i32 %val, %c
289 %add = add i32 %shl, %rem