xref: /llvm-project/llvm/test/Transforms/InstCombine/rem.ll (revision 10f315dc9c96ec2413881ab55a285e35d80def88)
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(i32)
5
6define i64 @rem_signed(i64 %x1, i64 %y2) {
7; CHECK-LABEL: @rem_signed(
8; CHECK-NEXT:    [[X1_FR:%.*]] = freeze i64 [[X1:%.*]]
9; CHECK-NEXT:    [[TMP1:%.*]] = srem i64 [[X1_FR]], [[Y2:%.*]]
10; CHECK-NEXT:    ret i64 [[TMP1]]
11;
12  %r = sdiv i64 %x1, %y2
13  %r7 = mul i64 %r, %y2
14  %r8 = sub i64 %x1, %r7
15  ret i64 %r8
16}
17
18define <4 x i32> @rem_signed_vec(<4 x i32> %t, <4 x i32> %u) {
19; CHECK-LABEL: @rem_signed_vec(
20; CHECK-NEXT:    [[T_FR:%.*]] = freeze <4 x i32> [[T:%.*]]
21; CHECK-NEXT:    [[TMP1:%.*]] = srem <4 x i32> [[T_FR]], [[U:%.*]]
22; CHECK-NEXT:    ret <4 x i32> [[TMP1]]
23;
24  %k = sdiv <4 x i32> %t, %u
25  %l = mul <4 x i32> %k, %u
26  %m = sub <4 x i32> %t, %l
27  ret <4 x i32> %m
28}
29
30define i64 @rem_unsigned(i64 %x1, i64 %y2) {
31; CHECK-LABEL: @rem_unsigned(
32; CHECK-NEXT:    [[X1_FR:%.*]] = freeze i64 [[X1:%.*]]
33; CHECK-NEXT:    [[TMP1:%.*]] = urem i64 [[X1_FR]], [[Y2:%.*]]
34; CHECK-NEXT:    ret i64 [[TMP1]]
35;
36  %r = udiv i64 %x1, %y2
37  %r7 = mul i64 %r, %y2
38  %r8 = sub i64 %x1, %r7
39  ret i64 %r8
40}
41
42; PR28672 - https://llvm.org/bugs/show_bug.cgi?id=28672
43
44define i8 @big_divisor(i8 %x) {
45; CHECK-LABEL: @big_divisor(
46; CHECK-NEXT:    [[X_FR:%.*]] = freeze i8 [[X:%.*]]
47; CHECK-NEXT:    [[TMP1:%.*]] = icmp ult i8 [[X_FR]], -127
48; CHECK-NEXT:    [[TMP2:%.*]] = add i8 [[X_FR]], 127
49; CHECK-NEXT:    [[REM:%.*]] = select i1 [[TMP1]], i8 [[X_FR]], i8 [[TMP2]]
50; CHECK-NEXT:    ret i8 [[REM]]
51;
52  %rem = urem i8 %x, 129
53  ret i8 %rem
54}
55
56define i5 @biggest_divisor(i5 %x) {
57; CHECK-LABEL: @biggest_divisor(
58; CHECK-NEXT:    [[X_FR:%.*]] = freeze i5 [[X:%.*]]
59; CHECK-NEXT:    [[DOTNOT:%.*]] = icmp eq i5 [[X_FR]], -1
60; CHECK-NEXT:    [[REM:%.*]] = select i1 [[DOTNOT]], i5 0, i5 [[X_FR]]
61; CHECK-NEXT:    ret i5 [[REM]]
62;
63  %rem = urem i5 %x, -1
64  ret i5 %rem
65}
66
67define i8 @urem_with_sext_bool_divisor(i1 %x, i8 %y) {
68; CHECK-LABEL: @urem_with_sext_bool_divisor(
69; CHECK-NEXT:    [[Y_FROZEN:%.*]] = freeze i8 [[Y:%.*]]
70; CHECK-NEXT:    [[TMP1:%.*]] = icmp eq i8 [[Y_FROZEN]], -1
71; CHECK-NEXT:    [[REM:%.*]] = select i1 [[TMP1]], i8 0, i8 [[Y_FROZEN]]
72; CHECK-NEXT:    ret i8 [[REM]]
73;
74  %s = sext i1 %x to i8
75  %rem = urem i8 %y, %s
76  ret i8 %rem
77}
78
79define <2 x i8> @urem_with_sext_bool_divisor_vec(<2 x i1> %x, <2 x i8> %y) {
80; CHECK-LABEL: @urem_with_sext_bool_divisor_vec(
81; CHECK-NEXT:    [[Y_FROZEN:%.*]] = freeze <2 x i8> [[Y:%.*]]
82; CHECK-NEXT:    [[TMP1:%.*]] = icmp eq <2 x i8> [[Y_FROZEN]], splat (i8 -1)
83; CHECK-NEXT:    [[REM:%.*]] = select <2 x i1> [[TMP1]], <2 x i8> zeroinitializer, <2 x i8> [[Y_FROZEN]]
84; CHECK-NEXT:    ret <2 x i8> [[REM]]
85;
86  %s = sext <2 x i1> %x to <2 x i8>
87  %rem = urem <2 x i8> %y, %s
88  ret <2 x i8> %rem
89}
90
91define <2 x i4> @big_divisor_vec(<2 x i4> %x) {
92; CHECK-LABEL: @big_divisor_vec(
93; CHECK-NEXT:    [[X_FR:%.*]] = freeze <2 x i4> [[X:%.*]]
94; CHECK-NEXT:    [[TMP1:%.*]] = icmp ult <2 x i4> [[X_FR]], splat (i4 -3)
95; CHECK-NEXT:    [[TMP2:%.*]] = add <2 x i4> [[X_FR]], splat (i4 3)
96; CHECK-NEXT:    [[REM:%.*]] = select <2 x i1> [[TMP1]], <2 x i4> [[X_FR]], <2 x i4> [[TMP2]]
97; CHECK-NEXT:    ret <2 x i4> [[REM]]
98;
99  %rem = urem <2 x i4> %x, <i4 13, i4 13>
100  ret <2 x i4> %rem
101}
102
103define i8 @urem1(i8 %x, i8 %y) {
104; CHECK-LABEL: @urem1(
105; CHECK-NEXT:    [[X_FR:%.*]] = freeze i8 [[X:%.*]]
106; CHECK-NEXT:    [[TMP1:%.*]] = urem i8 [[X_FR]], [[Y:%.*]]
107; CHECK-NEXT:    ret i8 [[TMP1]]
108;
109  %A = udiv i8 %x, %y
110  %B = mul i8 %A, %y
111  %C = sub i8 %x, %B
112  ret i8 %C
113}
114
115define i8 @srem1(i8 %x, i8 %y) {
116; CHECK-LABEL: @srem1(
117; CHECK-NEXT:    [[X_FR:%.*]] = freeze i8 [[X:%.*]]
118; CHECK-NEXT:    [[TMP1:%.*]] = srem i8 [[X_FR]], [[Y:%.*]]
119; CHECK-NEXT:    ret i8 [[TMP1]]
120;
121  %A = sdiv i8 %x, %y
122  %B = mul i8 %A, %y
123  %C = sub i8 %x, %B
124  ret i8 %C
125}
126
127define i8 @urem2(i8 %x, i8 %y) {
128; CHECK-LABEL: @urem2(
129; CHECK-NEXT:    [[X_FR:%.*]] = freeze i8 [[X:%.*]]
130; CHECK-NEXT:    [[TMP1:%.*]] = urem i8 [[X_FR]], [[Y:%.*]]
131; CHECK-NEXT:    [[C:%.*]] = sub i8 0, [[TMP1]]
132; CHECK-NEXT:    ret i8 [[C]]
133;
134  %A = udiv i8 %x, %y
135  %B = mul i8 %A, %y
136  %C = sub i8 %B, %x
137  ret i8 %C
138}
139
140define i8 @urem3(i8 %x) {
141; CHECK-LABEL: @urem3(
142; CHECK-NEXT:    [[X_FR:%.*]] = freeze i8 [[X:%.*]]
143; CHECK-NEXT:    [[TMP1:%.*]] = urem i8 [[X_FR]], 3
144; CHECK-NEXT:    [[B_NEG:%.*]] = sub nuw i8 [[X_FR]], [[TMP1]]
145; CHECK-NEXT:    [[C:%.*]] = add i8 [[B_NEG]], [[X_FR]]
146; CHECK-NEXT:    ret i8 [[C]]
147;
148  %A = udiv i8 %x, 3
149  %B = mul i8 %A, -3
150  %C = sub i8 %x, %B
151  ret i8 %C
152}
153
154; (((X / Y) * Y) / Y) -> X / Y
155
156define i32 @sdiv_mul_sdiv(i32 %x, i32 %y) {
157; CHECK-LABEL: @sdiv_mul_sdiv(
158; CHECK-NEXT:    [[X_FR:%.*]] = freeze i32 [[X:%.*]]
159; CHECK-NEXT:    [[R:%.*]] = sdiv i32 [[X_FR]], [[Y:%.*]]
160; CHECK-NEXT:    ret i32 [[R]]
161;
162  %div = sdiv i32 %x, %y
163  %mul = mul i32 %div, %y
164  %r = sdiv i32 %mul, %y
165  ret i32 %r
166}
167
168; (((X / Y) * Y) / Y) -> X / Y
169
170define i32 @udiv_mul_udiv(i32 %x, i32 %y) {
171; CHECK-LABEL: @udiv_mul_udiv(
172; CHECK-NEXT:    [[X_FR:%.*]] = freeze i32 [[X:%.*]]
173; CHECK-NEXT:    [[R:%.*]] = udiv i32 [[X_FR]], [[Y:%.*]]
174; CHECK-NEXT:    ret i32 [[R]]
175;
176  %div = udiv i32 %x, %y
177  %mul = mul i32 %div, %y
178  %r = udiv i32 %mul, %y
179  ret i32 %r
180}
181
182define i32 @test1(i32 %A) {
183; CHECK-LABEL: @test1(
184; CHECK-NEXT:    ret i32 0
185;
186  %B = srem i32 %A, 1	; ISA constant 0
187  ret i32 %B
188}
189
190define i32 @test3(i32 %A) {
191; CHECK-LABEL: @test3(
192; CHECK-NEXT:    [[B:%.*]] = and i32 [[A:%.*]], 7
193; CHECK-NEXT:    ret i32 [[B]]
194;
195  %B = urem i32 %A, 8
196  ret i32 %B
197}
198
199define <2 x i32> @vec_power_of_2_constant_splat_divisor(<2 x i32> %A) {
200; CHECK-LABEL: @vec_power_of_2_constant_splat_divisor(
201; CHECK-NEXT:    [[B:%.*]] = and <2 x i32> [[A:%.*]], splat (i32 7)
202; CHECK-NEXT:    ret <2 x i32> [[B]]
203;
204  %B = urem <2 x i32> %A, <i32 8, i32 8>
205  ret <2 x i32> %B
206}
207
208define <2 x i19> @weird_vec_power_of_2_constant_splat_divisor(<2 x i19> %A) {
209; CHECK-LABEL: @weird_vec_power_of_2_constant_splat_divisor(
210; CHECK-NEXT:    [[B:%.*]] = and <2 x i19> [[A:%.*]], splat (i19 7)
211; CHECK-NEXT:    ret <2 x i19> [[B]]
212;
213  %B = urem <2 x i19> %A, <i19 8, i19 8>
214  ret <2 x i19> %B
215}
216
217define i1 @test3a(i32 %A) {
218; CHECK-LABEL: @test3a(
219; CHECK-NEXT:    [[TMP1:%.*]] = and i32 [[A:%.*]], 7
220; CHECK-NEXT:    [[C:%.*]] = icmp ne i32 [[TMP1]], 0
221; CHECK-NEXT:    ret i1 [[C]]
222;
223  %B = srem i32 %A, -8
224  %C = icmp ne i32 %B, 0
225  ret i1 %C
226}
227
228define <2 x i1> @test3a_vec(<2 x i32> %A) {
229; CHECK-LABEL: @test3a_vec(
230; CHECK-NEXT:    [[TMP1:%.*]] = and <2 x i32> [[A:%.*]], splat (i32 7)
231; CHECK-NEXT:    [[C:%.*]] = icmp ne <2 x i32> [[TMP1]], zeroinitializer
232; CHECK-NEXT:    ret <2 x i1> [[C]]
233;
234  %B = srem <2 x i32> %A, <i32 -8, i32 -8>
235  %C = icmp ne <2 x i32> %B, zeroinitializer
236  ret <2 x i1> %C
237}
238
239define i32 @test4(i32 %X, i1 %C) {
240; CHECK-LABEL: @test4(
241; CHECK-NEXT:    [[TMP1:%.*]] = select i1 [[C:%.*]], i32 0, i32 7
242; CHECK-NEXT:    [[R:%.*]] = and i32 [[X:%.*]], [[TMP1]]
243; CHECK-NEXT:    ret i32 [[R]]
244;
245  %V = select i1 %C, i32 1, i32 8
246  %R = urem i32 %X, %V
247  ret i32 %R
248}
249
250define i32 @test5(i32 %X, i8 %B) {
251; CHECK-LABEL: @test5(
252; CHECK-NEXT:    [[SHIFT_UPGRD_1:%.*]] = zext nneg i8 [[B:%.*]] to i32
253; CHECK-NEXT:    [[AMT:%.*]] = shl nuw i32 32, [[SHIFT_UPGRD_1]]
254; CHECK-NEXT:    [[TMP1:%.*]] = add i32 [[AMT]], -1
255; CHECK-NEXT:    [[V:%.*]] = and i32 [[X:%.*]], [[TMP1]]
256; CHECK-NEXT:    ret i32 [[V]]
257;
258  %shift.upgrd.1 = zext i8 %B to i32
259  %Amt = shl i32 32, %shift.upgrd.1
260  %V = urem i32 %X, %Amt
261  ret i32 %V
262}
263
264define i32 @test6(i32 %A) {
265; CHECK-LABEL: @test6(
266; CHECK-NEXT:    ret i32 poison
267;
268  %B = srem i32 %A, 0	;; undef
269  ret i32 %B
270}
271
272define i32 @test7(i32 %A) {
273; CHECK-LABEL: @test7(
274; CHECK-NEXT:    ret i32 0
275;
276  %B = mul i32 %A, 8
277  %C = srem i32 %B, 4
278  ret i32 %C
279}
280
281define i32 @test8(i32 %A) {
282; CHECK-LABEL: @test8(
283; CHECK-NEXT:    ret i32 0
284;
285  %B = shl i32 %A, 4
286  %C = srem i32 %B, 8
287  ret i32 %C
288}
289
290define i32 @test9(i32 %A) {
291; CHECK-LABEL: @test9(
292; CHECK-NEXT:    ret i32 0
293;
294  %B = mul i32 %A, 64
295  %C = urem i32 %B, 32
296  ret i32 %C
297}
298
299define i32 @test10(i8 %c) {
300; CHECK-LABEL: @test10(
301; CHECK-NEXT:    ret i32 0
302;
303  %tmp.1 = zext i8 %c to i32
304  %tmp.2 = mul i32 %tmp.1, 4
305  %tmp.3 = sext i32 %tmp.2 to i64
306  %tmp.5 = urem i64 %tmp.3, 4
307  %tmp.6 = trunc i64 %tmp.5 to i32
308  ret i32 %tmp.6
309}
310
311define i32 @test11(i32 %i) {
312; CHECK-LABEL: @test11(
313; CHECK-NEXT:    ret i32 0
314;
315  %tmp.1 = and i32 %i, -2
316  %tmp.3 = mul i32 %tmp.1, 2
317  %tmp.5 = urem i32 %tmp.3, 4
318  ret i32 %tmp.5
319}
320
321define i32 @test12(i32 %i) {
322; CHECK-LABEL: @test12(
323; CHECK-NEXT:    ret i32 0
324;
325  %tmp.1 = and i32 %i, -4
326  %tmp.5 = srem i32 %tmp.1, 2
327  ret i32 %tmp.5
328}
329
330define i32 @test13(i32 %i) {
331; CHECK-LABEL: @test13(
332; CHECK-NEXT:    ret i32 0
333;
334  %x = srem i32 %i, %i
335  ret i32 %x
336}
337
338define i64 @test14(i64 %x, i32 %y) {
339; CHECK-LABEL: @test14(
340; CHECK-NEXT:    [[SHL:%.*]] = shl nuw i32 1, [[Y:%.*]]
341; CHECK-NEXT:    [[ZEXT:%.*]] = zext i32 [[SHL]] to i64
342; CHECK-NEXT:    [[TMP1:%.*]] = add nsw i64 [[ZEXT]], -1
343; CHECK-NEXT:    [[UREM:%.*]] = and i64 [[X:%.*]], [[TMP1]]
344; CHECK-NEXT:    ret i64 [[UREM]]
345;
346  %shl = shl i32 1, %y
347  %zext = zext i32 %shl to i64
348  %urem = urem i64 %x, %zext
349  ret i64 %urem
350}
351
352define i64 @test15(i32 %x, i32 %y) {
353; CHECK-LABEL: @test15(
354; CHECK-NEXT:    [[NOTMASK:%.*]] = shl nsw i32 -1, [[Y:%.*]]
355; CHECK-NEXT:    [[TMP1:%.*]] = xor i32 [[NOTMASK]], -1
356; CHECK-NEXT:    [[TMP2:%.*]] = and i32 [[X:%.*]], [[TMP1]]
357; CHECK-NEXT:    [[UREM:%.*]] = zext nneg i32 [[TMP2]] to i64
358; CHECK-NEXT:    ret i64 [[UREM]]
359;
360  %shl = shl i32 1, %y
361  %zext0 = zext i32 %shl to i64
362  %zext1 = zext i32 %x to i64
363  %urem = urem i64 %zext1, %zext0
364  ret i64 %urem
365}
366
367define i32 @test16(i32 %x, i32 %y) {
368; CHECK-LABEL: @test16(
369; CHECK-NEXT:    [[SHR:%.*]] = lshr i32 [[Y:%.*]], 11
370; CHECK-NEXT:    [[AND:%.*]] = and i32 [[SHR]], 4
371; CHECK-NEXT:    [[TMP1:%.*]] = or disjoint i32 [[AND]], 3
372; CHECK-NEXT:    [[REM:%.*]] = and i32 [[X:%.*]], [[TMP1]]
373; CHECK-NEXT:    ret i32 [[REM]]
374;
375  %shr = lshr i32 %y, 11
376  %and = and i32 %shr, 4
377  %add = add i32 %and, 4
378  %rem = urem i32 %x, %add
379  ret i32 %rem
380}
381
382define i32 @test17(i32 %X) {
383; CHECK-LABEL: @test17(
384; CHECK-NEXT:    [[TMP1:%.*]] = icmp ne i32 [[X:%.*]], 1
385; CHECK-NEXT:    [[A:%.*]] = zext i1 [[TMP1]] to i32
386; CHECK-NEXT:    ret i32 [[A]]
387;
388  %A = urem i32 1, %X
389  ret i32 %A
390}
391
392define i32 @test18(i16 %x, i32 %y) {
393; CHECK-LABEL: @test18(
394; CHECK-NEXT:    [[TMP1:%.*]] = and i16 [[X:%.*]], 4
395; CHECK-NEXT:    [[DOTNOT:%.*]] = icmp eq i16 [[TMP1]], 0
396; CHECK-NEXT:    [[TMP2:%.*]] = select i1 [[DOTNOT]], i32 63, i32 31
397; CHECK-NEXT:    [[TMP3:%.*]] = and i32 [[Y:%.*]], [[TMP2]]
398; CHECK-NEXT:    ret i32 [[TMP3]]
399;
400  %1 = and i16 %x, 4
401  %2 = icmp ne i16 %1, 0
402  %3 = select i1 %2, i32 32, i32 64
403  %4 = urem i32 %y, %3
404  ret i32 %4
405}
406
407define i32 @test19(i32 %x, i32 %y) {
408; CHECK-LABEL: @test19(
409; CHECK-NEXT:    [[A:%.*]] = shl nuw i32 1, [[X:%.*]]
410; CHECK-NEXT:    [[B:%.*]] = shl nuw i32 1, [[Y:%.*]]
411; CHECK-NEXT:    [[C:%.*]] = and i32 [[A]], [[B]]
412; CHECK-NEXT:    [[D:%.*]] = add i32 [[C]], [[A]]
413; CHECK-NEXT:    [[TMP1:%.*]] = add i32 [[D]], -1
414; CHECK-NEXT:    [[E:%.*]] = and i32 [[Y]], [[TMP1]]
415; CHECK-NEXT:    ret i32 [[E]]
416;
417  %A = shl i32 1, %x
418  %B = shl i32 1, %y
419  %C = and i32 %A, %B
420  %D = add i32 %C, %A
421  %E = urem i32 %y, %D
422  ret i32 %E
423}
424
425define i32 @test19_commutative0(i32 %x, i32 %y) {
426; CHECK-LABEL: @test19_commutative0(
427; CHECK-NEXT:    [[A:%.*]] = shl nuw i32 1, [[X:%.*]]
428; CHECK-NEXT:    [[B:%.*]] = shl nuw i32 1, [[Y:%.*]]
429; CHECK-NEXT:    [[C:%.*]] = and i32 [[B]], [[A]]
430; CHECK-NEXT:    [[D:%.*]] = add i32 [[C]], [[A]]
431; CHECK-NEXT:    [[TMP1:%.*]] = add i32 [[D]], -1
432; CHECK-NEXT:    [[E:%.*]] = and i32 [[Y]], [[TMP1]]
433; CHECK-NEXT:    ret i32 [[E]]
434;
435  %A = shl i32 1, %x
436  %B = shl i32 1, %y
437  %C = and i32 %B, %A ; swapped
438  %D = add i32 %C, %A
439  %E = urem i32 %y, %D
440  ret i32 %E
441}
442
443define i32 @test19_commutative1(i32 %x, i32 %y) {
444; CHECK-LABEL: @test19_commutative1(
445; CHECK-NEXT:    [[A:%.*]] = shl nuw i32 1, [[X:%.*]]
446; CHECK-NEXT:    [[B:%.*]] = shl nuw i32 1, [[Y:%.*]]
447; CHECK-NEXT:    [[C:%.*]] = and i32 [[A]], [[B]]
448; CHECK-NEXT:    [[D:%.*]] = add i32 [[A]], [[C]]
449; CHECK-NEXT:    [[TMP1:%.*]] = add i32 [[D]], -1
450; CHECK-NEXT:    [[E:%.*]] = and i32 [[Y]], [[TMP1]]
451; CHECK-NEXT:    ret i32 [[E]]
452;
453  %A = shl i32 1, %x
454  %B = shl i32 1, %y
455  %C = and i32 %A, %B
456  %D = add i32 %A, %C ; swapped
457  %E = urem i32 %y, %D
458  ret i32 %E
459}
460
461define i32 @test19_commutative2(i32 %x, i32 %y) {
462; CHECK-LABEL: @test19_commutative2(
463; CHECK-NEXT:    [[A:%.*]] = shl nuw i32 1, [[X:%.*]]
464; CHECK-NEXT:    [[B:%.*]] = shl nuw i32 1, [[Y:%.*]]
465; CHECK-NEXT:    [[C:%.*]] = and i32 [[B]], [[A]]
466; CHECK-NEXT:    [[D:%.*]] = add i32 [[A]], [[C]]
467; CHECK-NEXT:    [[TMP1:%.*]] = add i32 [[D]], -1
468; CHECK-NEXT:    [[E:%.*]] = and i32 [[Y]], [[TMP1]]
469; CHECK-NEXT:    ret i32 [[E]]
470;
471  %A = shl i32 1, %x
472  %B = shl i32 1, %y
473  %C = and i32 %B, %A ; swapped
474  %D = add i32 %A, %C ; swapped
475  %E = urem i32 %y, %D
476  ret i32 %E
477}
478
479define <2 x i64> @test20(<2 x i64> %X, <2 x i1> %C) {
480; CHECK-LABEL: @test20(
481; CHECK-NEXT:    [[R:%.*]] = select <2 x i1> [[C:%.*]], <2 x i64> <i64 1, i64 2>, <2 x i64> zeroinitializer
482; CHECK-NEXT:    ret <2 x i64> [[R]]
483;
484  %V = select <2 x i1> %C, <2 x i64> <i64 1, i64 2>, <2 x i64> <i64 8, i64 9>
485  %R = urem <2 x i64> %V, <i64 2, i64 3>
486  ret <2 x i64> %R
487}
488
489define i32 @test21(i1 %c0, ptr %p) {
490; CHECK-LABEL: @test21(
491; CHECK-NEXT:  entry:
492; CHECK-NEXT:    br i1 [[C0:%.*]], label [[IF_THEN:%.*]], label [[IF_END:%.*]]
493; CHECK:       if.then:
494; CHECK-NEXT:    [[V:%.*]] = load volatile i32, ptr [[P:%.*]], align 4
495; CHECK-NEXT:    [[TMP0:%.*]] = srem i32 [[V]], 5
496; CHECK-NEXT:    br label [[IF_END]]
497; CHECK:       if.end:
498; CHECK-NEXT:    [[LHS:%.*]] = phi i32 [ [[TMP0]], [[IF_THEN]] ], [ 0, [[ENTRY:%.*]] ]
499; CHECK-NEXT:    ret i32 [[LHS]]
500;
501entry:
502  br i1 %c0, label %if.then, label %if.end
503
504if.then:
505  %v = load volatile i32, ptr %p
506  br label %if.end
507
508if.end:
509  %lhs = phi i32 [ %v, %if.then ], [ 5, %entry ]
510  %rem = srem i32 %lhs, 5
511  ret i32 %rem
512}
513
514@a = common global [5 x i16] zeroinitializer, align 2
515@b = common global i16 0, align 2
516
517define i32 @pr27968_0(i1 %c0, ptr %p) {
518; CHECK-LABEL: @pr27968_0(
519; CHECK-NEXT:  entry:
520; CHECK-NEXT:    br i1 [[C0:%.*]], label [[IF_THEN:%.*]], label [[IF_END:%.*]]
521; CHECK:       if.then:
522; CHECK-NEXT:    [[V:%.*]] = load volatile i32, ptr [[P:%.*]], align 4
523; CHECK-NEXT:    br label [[IF_END]]
524; CHECK:       if.end:
525; CHECK-NEXT:    [[CMP:%.*]] = icmp eq ptr getelementptr inbounds nuw (i8, ptr @a, i64 8), @b
526; CHECK-NEXT:    br i1 [[CMP]], label [[REM_IS_SAFE:%.*]], label [[REM_IS_UNSAFE:%.*]]
527; CHECK:       rem.is.safe:
528; CHECK-NEXT:    ret i32 0
529; CHECK:       rem.is.unsafe:
530; CHECK-NEXT:    ret i32 0
531;
532entry:
533  br i1 %c0, label %if.then, label %if.end
534
535if.then:
536  %v = load volatile i32, ptr %p
537  br label %if.end
538
539if.end:
540  %lhs = phi i32 [ %v, %if.then ], [ 5, %entry ]
541  %cmp = icmp eq ptr getelementptr inbounds ([5 x i16], ptr @a, i64 0, i64 4), @b
542  br i1 %cmp, label %rem.is.safe, label %rem.is.unsafe
543
544rem.is.safe:
545  %ext = zext i1 %cmp to i32
546  %rem = srem i32 %lhs, %ext
547  ret i32 %rem
548
549rem.is.unsafe:
550  ret i32 0
551}
552
553define i32 @pr27968_1(i1 %c0, i1 %always_false, ptr %p) {
554; CHECK-LABEL: @pr27968_1(
555; CHECK-NEXT:  entry:
556; CHECK-NEXT:    br i1 [[C0:%.*]], label [[IF_THEN:%.*]], label [[IF_END:%.*]]
557; CHECK:       if.then:
558; CHECK-NEXT:    [[V:%.*]] = load volatile i32, ptr [[P:%.*]], align 4
559; CHECK-NEXT:    br label [[IF_END]]
560; CHECK:       if.end:
561; CHECK-NEXT:    [[LHS:%.*]] = phi i32 [ [[V]], [[IF_THEN]] ], [ 5, [[ENTRY:%.*]] ]
562; CHECK-NEXT:    br i1 [[ALWAYS_FALSE:%.*]], label [[REM_IS_SAFE:%.*]], label [[REM_IS_UNSAFE:%.*]]
563; CHECK:       rem.is.safe:
564; CHECK-NEXT:    [[REM:%.*]] = srem i32 [[LHS]], -2147483648
565; CHECK-NEXT:    ret i32 [[REM]]
566; CHECK:       rem.is.unsafe:
567; CHECK-NEXT:    ret i32 0
568;
569entry:
570  br i1 %c0, label %if.then, label %if.end
571
572if.then:
573  %v = load volatile i32, ptr %p
574  br label %if.end
575
576if.end:
577  %lhs = phi i32 [ %v, %if.then ], [ 5, %entry ]
578  br i1 %always_false, label %rem.is.safe, label %rem.is.unsafe
579
580rem.is.safe:
581  %rem = srem i32 %lhs, -2147483648
582  ret i32 %rem
583
584rem.is.unsafe:
585  ret i32 0
586}
587
588define i32 @pr27968_2(i1 %c0, ptr %p) {
589; CHECK-LABEL: @pr27968_2(
590; CHECK-NEXT:  entry:
591; CHECK-NEXT:    br i1 [[C0:%.*]], label [[IF_THEN:%.*]], label [[IF_END:%.*]]
592; CHECK:       if.then:
593; CHECK-NEXT:    [[V:%.*]] = load volatile i32, ptr [[P:%.*]], align 4
594; CHECK-NEXT:    br label [[IF_END]]
595; CHECK:       if.end:
596; CHECK-NEXT:    [[CMP:%.*]] = icmp eq ptr getelementptr inbounds nuw (i8, ptr @a, i64 8), @b
597; CHECK-NEXT:    br i1 [[CMP]], label [[REM_IS_SAFE:%.*]], label [[REM_IS_UNSAFE:%.*]]
598; CHECK:       rem.is.safe:
599; CHECK-NEXT:    ret i32 0
600; CHECK:       rem.is.unsafe:
601; CHECK-NEXT:    ret i32 0
602;
603entry:
604  br i1 %c0, label %if.then, label %if.end
605
606if.then:
607  %v = load volatile i32, ptr %p
608  br label %if.end
609
610if.end:
611  %lhs = phi i32 [ %v, %if.then ], [ 5, %entry ]
612  %cmp = icmp eq ptr getelementptr inbounds ([5 x i16], ptr @a, i64 0, i64 4), @b
613  br i1 %cmp, label %rem.is.safe, label %rem.is.unsafe
614
615rem.is.safe:
616  %ext = zext i1 %cmp to i32
617  %rem = urem i32 %lhs, %ext
618  ret i32 %rem
619
620rem.is.unsafe:
621  ret i32 0
622}
623
624define i32 @pr27968_3(i1 %c0, i1 %always_false, ptr %p) {
625; CHECK-LABEL: @pr27968_3(
626; CHECK-NEXT:  entry:
627; CHECK-NEXT:    br i1 [[C0:%.*]], label [[IF_THEN:%.*]], label [[IF_END:%.*]]
628; CHECK:       if.then:
629; CHECK-NEXT:    [[V:%.*]] = load volatile i32, ptr [[P:%.*]], align 4
630; CHECK-NEXT:    [[TMP0:%.*]] = and i32 [[V]], 2147483647
631; CHECK-NEXT:    br label [[IF_END]]
632; CHECK:       if.end:
633; CHECK-NEXT:    [[LHS:%.*]] = phi i32 [ [[TMP0]], [[IF_THEN]] ], [ 5, [[ENTRY:%.*]] ]
634; CHECK-NEXT:    br i1 [[ALWAYS_FALSE:%.*]], label [[REM_IS_SAFE:%.*]], label [[REM_IS_UNSAFE:%.*]]
635; CHECK:       rem.is.safe:
636; CHECK-NEXT:    ret i32 [[LHS]]
637; CHECK:       rem.is.unsafe:
638; CHECK-NEXT:    ret i32 0
639;
640entry:
641  br i1 %c0, label %if.then, label %if.end
642
643if.then:
644  %v = load volatile i32, ptr %p
645  br label %if.end
646
647if.end:
648  %lhs = phi i32 [ %v, %if.then ], [ 5, %entry ]
649  br i1 %always_false, label %rem.is.safe, label %rem.is.unsafe
650
651rem.is.safe:
652  %rem = urem i32 %lhs, -2147483648
653  ret i32 %rem
654
655rem.is.unsafe:
656  ret i32 0
657}
658
659define i32 @test22(i32 %A) {
660; CHECK-LABEL: @test22(
661; CHECK-NEXT:    [[AND:%.*]] = and i32 [[A:%.*]], 2147483647
662; CHECK-NEXT:    [[MUL:%.*]] = urem i32 [[AND]], 2147483647
663; CHECK-NEXT:    ret i32 [[MUL]]
664;
665  %and = and i32 %A, 2147483647
666  %mul = srem i32 %and, 2147483647
667  ret i32 %mul
668}
669
670define <2 x i32> @test23(<2 x i32> %A) {
671; CHECK-LABEL: @test23(
672; CHECK-NEXT:    [[AND:%.*]] = and <2 x i32> [[A:%.*]], splat (i32 2147483647)
673; CHECK-NEXT:    [[MUL:%.*]] = urem <2 x i32> [[AND]], splat (i32 2147483647)
674; CHECK-NEXT:    ret <2 x i32> [[MUL]]
675;
676  %and = and <2 x i32> %A, <i32 2147483647, i32 2147483647>
677  %mul = srem <2 x i32> %and, <i32 2147483647, i32 2147483647>
678  ret <2 x i32> %mul
679}
680
681define i1 @test24(i32 %A) {
682; CHECK-LABEL: @test24(
683; CHECK-NEXT:    [[B:%.*]] = and i32 [[A:%.*]], 2147483647
684; CHECK-NEXT:    [[C:%.*]] = icmp ne i32 [[B]], 0
685; CHECK-NEXT:    ret i1 [[C]]
686;
687  %B = urem i32 %A, 2147483648 ; signbit
688  %C = icmp ne i32 %B, 0
689  ret i1 %C
690}
691
692define <2 x i1> @test24_vec(<2 x i32> %A) {
693; CHECK-LABEL: @test24_vec(
694; CHECK-NEXT:    [[B:%.*]] = and <2 x i32> [[A:%.*]], splat (i32 2147483647)
695; CHECK-NEXT:    [[C:%.*]] = icmp ne <2 x i32> [[B]], zeroinitializer
696; CHECK-NEXT:    ret <2 x i1> [[C]]
697;
698  %B = urem <2 x i32> %A, <i32 2147483648, i32 2147483648>
699  %C = icmp ne <2 x i32> %B, zeroinitializer
700  ret <2 x i1> %C
701}
702
703define i1 @test25(i32 %A) {
704; CHECK-LABEL: @test25(
705; CHECK-NEXT:    [[TMP1:%.*]] = and i32 [[A:%.*]], 2147483647
706; CHECK-NEXT:    [[C:%.*]] = icmp ne i32 [[TMP1]], 0
707; CHECK-NEXT:    ret i1 [[C]]
708;
709  %B = srem i32 %A, 2147483648 ; signbit
710  %C = icmp ne i32 %B, 0
711  ret i1 %C
712}
713
714define <2 x i1> @test25_vec(<2 x i32> %A) {
715; CHECK-LABEL: @test25_vec(
716; CHECK-NEXT:    [[TMP1:%.*]] = and <2 x i32> [[A:%.*]], splat (i32 2147483647)
717; CHECK-NEXT:    [[C:%.*]] = icmp ne <2 x i32> [[TMP1]], zeroinitializer
718; CHECK-NEXT:    ret <2 x i1> [[C]]
719;
720  %B = srem <2 x i32> %A, <i32 2147483648, i32 2147483648>
721  %C = icmp ne <2 x i32> %B, zeroinitializer
722  ret <2 x i1> %C
723}
724
725define i1 @test26(i32 %A, i32 %B) {
726; CHECK-LABEL: @test26(
727; CHECK-NEXT:    [[NOTMASK:%.*]] = shl nsw i32 -1, [[B:%.*]]
728; CHECK-NEXT:    [[TMP1:%.*]] = xor i32 [[NOTMASK]], -1
729; CHECK-NEXT:    [[TMP2:%.*]] = and i32 [[A:%.*]], [[TMP1]]
730; CHECK-NEXT:    [[E:%.*]] = icmp ne i32 [[TMP2]], 0
731; CHECK-NEXT:    ret i1 [[E]]
732;
733  %C = shl i32 1, %B ; not a constant
734  %D = srem i32 %A, %C
735  %E = icmp ne i32 %D, 0
736  ret i1 %E
737}
738
739define i1 @test27(i32 %A, ptr %remdst) {
740; CHECK-LABEL: @test27(
741; CHECK-NEXT:    [[B:%.*]] = srem i32 [[A:%.*]], -2147483648
742; CHECK-NEXT:    store i32 [[B]], ptr [[REMDST:%.*]], align 1
743; CHECK-NEXT:    [[C:%.*]] = icmp ne i32 [[B]], 0
744; CHECK-NEXT:    ret i1 [[C]]
745;
746  %B = srem i32 %A, 2147483648 ; signbit
747  store i32 %B, ptr %remdst, align 1 ; extra use of rem
748  %C = icmp ne i32 %B, 0
749  ret i1 %C
750}
751
752define i1 @test28(i32 %A) {
753; CHECK-LABEL: @test28(
754; CHECK-NEXT:    [[TMP1:%.*]] = and i32 [[A:%.*]], 2147483647
755; CHECK-NEXT:    [[C:%.*]] = icmp eq i32 [[TMP1]], 0
756; CHECK-NEXT:    ret i1 [[C]]
757;
758  %B = srem i32 %A, 2147483648 ; signbit
759  %C = icmp eq i32 %B, 0 ; another equality predicate
760  ret i1 %C
761}
762
763define i1 @positive_and_odd_eq(i32 %A) {
764; CHECK-LABEL: @positive_and_odd_eq(
765; CHECK-NEXT:    [[TMP1:%.*]] = and i32 [[A:%.*]], -2147483647
766; CHECK-NEXT:    [[C:%.*]] = icmp eq i32 [[TMP1]], 1
767; CHECK-NEXT:    ret i1 [[C]]
768;
769  %B = srem i32 %A, 2
770  %C = icmp eq i32 %B, 1
771  ret i1 %C
772}
773
774define i1 @negative_and_odd_eq(i32 %A) {
775; CHECK-LABEL: @negative_and_odd_eq(
776; CHECK-NEXT:    [[B:%.*]] = srem i32 [[A:%.*]], 2
777; CHECK-NEXT:    [[C:%.*]] = icmp eq i32 [[B]], -1
778; CHECK-NEXT:    ret i1 [[C]]
779;
780  %B = srem i32 %A, 2
781  %C = icmp eq i32 %B, -1
782  ret i1 %C
783}
784
785define i1 @positive_and_odd_ne(i32 %A) {
786; CHECK-LABEL: @positive_and_odd_ne(
787; CHECK-NEXT:    [[TMP1:%.*]] = and i32 [[A:%.*]], -2147483647
788; CHECK-NEXT:    [[C:%.*]] = icmp ne i32 [[TMP1]], 1
789; CHECK-NEXT:    ret i1 [[C]]
790;
791  %B = srem i32 %A, 2
792  %C = icmp ne i32 %B, 1
793  ret i1 %C
794}
795
796define i1 @negative_and_odd_ne(i32 %A) {
797; CHECK-LABEL: @negative_and_odd_ne(
798; CHECK-NEXT:    [[B:%.*]] = srem i32 [[A:%.*]], 2
799; CHECK-NEXT:    [[C:%.*]] = icmp ne i32 [[B]], -1
800; CHECK-NEXT:    ret i1 [[C]]
801;
802  %B = srem i32 %A, 2
803  %C = icmp ne i32 %B, -1
804  ret i1 %C
805}
806
807; FP division-by-zero is not UB.
808
809define double @PR34870(i1 %cond, double %x, double %y) {
810; CHECK-LABEL: @PR34870(
811; CHECK-NEXT:    [[SEL:%.*]] = select i1 [[COND:%.*]], double [[Y:%.*]], double 0.000000e+00
812; CHECK-NEXT:    [[FMOD:%.*]] = frem double [[X:%.*]], [[SEL]]
813; CHECK-NEXT:    ret double [[FMOD]]
814;
815  %sel = select i1 %cond, double %y, double 0.0
816  %fmod = frem double %x, %sel
817  ret double %fmod
818}
819
820define i32 @srem_constant_dividend_select_of_constants_divisor(i1 %b) {
821; CHECK-LABEL: @srem_constant_dividend_select_of_constants_divisor(
822; CHECK-NEXT:    [[R:%.*]] = select i1 [[B:%.*]], i32 6, i32 0
823; CHECK-NEXT:    ret i32 [[R]]
824;
825  %s = select i1 %b, i32 12, i32 -3
826  %r = srem i32 42, %s
827  ret i32 %r
828}
829
830define i32 @srem_constant_dividend_select_of_constants_divisor_use(i1 %b) {
831; CHECK-LABEL: @srem_constant_dividend_select_of_constants_divisor_use(
832; CHECK-NEXT:    [[S:%.*]] = select i1 [[B:%.*]], i32 12, i32 -3
833; CHECK-NEXT:    call void @use(i32 [[S]])
834; CHECK-NEXT:    [[R:%.*]] = select i1 [[B]], i32 6, i32 0
835; CHECK-NEXT:    ret i32 [[R]]
836;
837  %s = select i1 %b, i32 12, i32 -3
838  call void @use(i32 %s)
839  %r = srem i32 42, %s
840  ret i32 %r
841}
842
843; Rem-by-0 is immediate UB, so select is simplified.
844
845define i32 @srem_constant_dividend_select_of_constants_divisor_0_arm(i1 %b) {
846; CHECK-LABEL: @srem_constant_dividend_select_of_constants_divisor_0_arm(
847; CHECK-NEXT:    ret i32 6
848;
849  %s = select i1 %b, i32 12, i32 0
850  %r = srem i32 42, %s
851  ret i32 %r
852}
853
854; negative test - not safe to speculate rem with variable divisor
855
856define i32 @srem_constant_dividend_select_divisor1(i1 %b, i32 %x) {
857; CHECK-LABEL: @srem_constant_dividend_select_divisor1(
858; CHECK-NEXT:    [[S:%.*]] = select i1 [[B:%.*]], i32 [[X:%.*]], i32 -3
859; CHECK-NEXT:    [[R:%.*]] = srem i32 42, [[S]]
860; CHECK-NEXT:    ret i32 [[R]]
861;
862  %s = select i1 %b, i32 %x, i32 -3
863  %r = srem i32 42, %s
864  ret i32 %r
865}
866
867; negative test - not safe to speculate rem with variable divisor
868
869define i32 @srem_constant_dividend_select_divisor2(i1 %b, i32 %x) {
870; CHECK-LABEL: @srem_constant_dividend_select_divisor2(
871; CHECK-NEXT:    [[S:%.*]] = select i1 [[B:%.*]], i32 12, i32 [[X:%.*]]
872; CHECK-NEXT:    [[R:%.*]] = srem i32 42, [[S]]
873; CHECK-NEXT:    ret i32 [[R]]
874;
875  %s = select i1 %b, i32 12, i32 %x
876  %r = srem i32 42, %s
877  ret i32 %r
878}
879
880define <2 x i8> @srem_constant_dividend_select_of_constants_divisor_vec(i1 %b) {
881; CHECK-LABEL: @srem_constant_dividend_select_of_constants_divisor_vec(
882; CHECK-NEXT:    [[R:%.*]] = select i1 [[B:%.*]], <2 x i8> <i8 6, i8 -2>, <2 x i8> <i8 2, i8 -2>
883; CHECK-NEXT:    ret <2 x i8> [[R]]
884;
885  %s = select i1 %b, <2 x i8> <i8 12, i8 -5>, <2 x i8> <i8 -4, i8 4>
886  %r = srem <2 x i8> <i8 42, i8 -42>, %s
887  ret <2 x i8> %r
888}
889
890; Rem-by-0 element is immediate UB, so select is simplified.
891
892define <2 x i8> @srem_constant_dividend_select_of_constants_divisor_vec_ub1(i1 %b) {
893; CHECK-LABEL: @srem_constant_dividend_select_of_constants_divisor_vec_ub1(
894; CHECK-NEXT:    ret <2 x i8> <i8 2, i8 -2>
895;
896  %s = select i1 %b, <2 x i8> <i8 0, i8 -5>, <2 x i8> <i8 -4, i8 4>
897  %r = srem <2 x i8> <i8 42, i8 -42>, %s
898  ret <2 x i8> %r
899}
900
901; SMIN % -1 element is poison.
902
903define <2 x i8> @srem_constant_dividend_select_of_constants_divisor_vec_ub2(i1 %b) {
904; CHECK-LABEL: @srem_constant_dividend_select_of_constants_divisor_vec_ub2(
905; CHECK-NEXT:    [[R:%.*]] = select i1 [[B:%.*]], <2 x i8> <i8 6, i8 -3>, <2 x i8> <i8 2, i8 poison>
906; CHECK-NEXT:    ret <2 x i8> [[R]]
907;
908  %s = select i1 %b, <2 x i8> <i8 12, i8 -5>, <2 x i8> <i8 -4, i8 -1>
909  %r = srem <2 x i8> <i8 42, i8 -128>, %s
910  ret <2 x i8> %r
911}
912
913; negative test - must have constant dividend
914
915define i32 @srem_select_of_constants_divisor(i1 %b, i32 %x) {
916; CHECK-LABEL: @srem_select_of_constants_divisor(
917; CHECK-NEXT:    [[S:%.*]] = select i1 [[B:%.*]], i32 12, i32 -3
918; CHECK-NEXT:    [[R:%.*]] = srem i32 [[X:%.*]], [[S]]
919; CHECK-NEXT:    ret i32 [[R]]
920;
921  %s = select i1 %b, i32 12, i32 -3
922  %r = srem i32 %x, %s
923  ret i32 %r
924}
925
926define i32 @urem_constant_dividend_select_of_constants_divisor(i1 %b) {
927; CHECK-LABEL: @urem_constant_dividend_select_of_constants_divisor(
928; CHECK-NEXT:    [[R:%.*]] = select i1 [[B:%.*]], i32 6, i32 42
929; CHECK-NEXT:    ret i32 [[R]]
930;
931  %s = select i1 %b, i32 12, i32 -3
932  %r = urem i32 42, %s
933  ret i32 %r
934}
935
936define i32 @urem_constant_dividend_select_of_constants_divisor_use(i1 %b) {
937; CHECK-LABEL: @urem_constant_dividend_select_of_constants_divisor_use(
938; CHECK-NEXT:    [[S:%.*]] = select i1 [[B:%.*]], i32 12, i32 -3
939; CHECK-NEXT:    call void @use(i32 [[S]])
940; CHECK-NEXT:    [[R:%.*]] = select i1 [[B]], i32 6, i32 42
941; CHECK-NEXT:    ret i32 [[R]]
942;
943  %s = select i1 %b, i32 12, i32 -3
944  call void @use(i32 %s)
945  %r = urem i32 42, %s
946  ret i32 %r
947}
948
949; Rem-by-0 is immediate UB, so select is simplified.
950
951define i32 @urem_constant_dividend_select_of_constants_divisor_0_arm(i1 %b) {
952; CHECK-LABEL: @urem_constant_dividend_select_of_constants_divisor_0_arm(
953; CHECK-NEXT:    ret i32 6
954;
955  %s = select i1 %b, i32 12, i32 0
956  %r = urem i32 42, %s
957  ret i32 %r
958}
959
960; negative test - not safe to speculate rem with variable divisor
961
962define i32 @urem_constant_dividend_select_divisor1(i1 %b, i32 %x) {
963; CHECK-LABEL: @urem_constant_dividend_select_divisor1(
964; CHECK-NEXT:    [[S:%.*]] = select i1 [[B:%.*]], i32 [[X:%.*]], i32 -3
965; CHECK-NEXT:    [[R:%.*]] = urem i32 42, [[S]]
966; CHECK-NEXT:    ret i32 [[R]]
967;
968  %s = select i1 %b, i32 %x, i32 -3
969  %r = urem i32 42, %s
970  ret i32 %r
971}
972
973; negative test - not safe to speculate rem with variable divisor
974
975define i32 @urem_constant_dividend_select_divisor2(i1 %b, i32 %x) {
976; CHECK-LABEL: @urem_constant_dividend_select_divisor2(
977; CHECK-NEXT:    [[S:%.*]] = select i1 [[B:%.*]], i32 12, i32 [[X:%.*]]
978; CHECK-NEXT:    [[R:%.*]] = urem i32 42, [[S]]
979; CHECK-NEXT:    ret i32 [[R]]
980;
981  %s = select i1 %b, i32 12, i32 %x
982  %r = urem i32 42, %s
983  ret i32 %r
984}
985
986define <2 x i8> @urem_constant_dividend_select_of_constants_divisor_vec(i1 %b) {
987; CHECK-LABEL: @urem_constant_dividend_select_of_constants_divisor_vec(
988; CHECK-NEXT:    [[R:%.*]] = select i1 [[B:%.*]], <2 x i8> <i8 6, i8 -42>, <2 x i8> <i8 42, i8 2>
989; CHECK-NEXT:    ret <2 x i8> [[R]]
990;
991  %s = select i1 %b, <2 x i8> <i8 12, i8 -5>, <2 x i8> <i8 -4, i8 4>
992  %r = urem <2 x i8> <i8 42, i8 -42>, %s
993  ret <2 x i8> %r
994}
995
996; Rem-by-0 element is immediate UB, so select is simplified.
997
998define <2 x i8> @urem_constant_dividend_select_of_constants_divisor_vec_ub1(i1 %b) {
999; CHECK-LABEL: @urem_constant_dividend_select_of_constants_divisor_vec_ub1(
1000; CHECK-NEXT:    [[R:%.*]] = select i1 [[B:%.*]], <2 x i8> <i8 poison, i8 -42>, <2 x i8> <i8 42, i8 2>
1001; CHECK-NEXT:    ret <2 x i8> [[R]]
1002;
1003  %s = select i1 %b, <2 x i8> <i8 0, i8 -5>, <2 x i8> <i8 -4, i8 4>
1004  %r = urem <2 x i8> <i8 42, i8 -42>, %s
1005  ret <2 x i8> %r
1006}
1007
1008; There's no unsigned equivalent to "SMIN % -1", so this is just the usual constant folding.
1009
1010define <2 x i8> @urem_constant_dividend_select_of_constants_divisor_vec_ub2(i1 %b) {
1011; CHECK-LABEL: @urem_constant_dividend_select_of_constants_divisor_vec_ub2(
1012; CHECK-NEXT:    [[R:%.*]] = select i1 [[B:%.*]], <2 x i8> <i8 6, i8 -128>, <2 x i8> <i8 42, i8 -128>
1013; CHECK-NEXT:    ret <2 x i8> [[R]]
1014;
1015  %s = select i1 %b, <2 x i8> <i8 12, i8 -5>, <2 x i8> <i8 -4, i8 -1>
1016  %r = urem <2 x i8> <i8 42, i8 -128>, %s
1017  ret <2 x i8> %r
1018}
1019
1020; negative test - must have constant dividend
1021
1022define i32 @urem_select_of_constants_divisor(i1 %b, i32 %x) {
1023; CHECK-LABEL: @urem_select_of_constants_divisor(
1024; CHECK-NEXT:    [[S:%.*]] = select i1 [[B:%.*]], i32 12, i32 -3
1025; CHECK-NEXT:    [[R:%.*]] = urem i32 [[X:%.*]], [[S]]
1026; CHECK-NEXT:    ret i32 [[R]]
1027;
1028  %s = select i1 %b, i32 12, i32 -3
1029  %r = urem i32 %x, %s
1030  ret i32 %r
1031}
1032
1033; https://alive2.llvm.org/ce/z/bh2KHm
1034define <2 x i32> @PR62401(<2 x i1> %x, <2 x i32> %y) {
1035; CHECK-LABEL: @PR62401(
1036; CHECK-NEXT:    [[Y_FROZEN:%.*]] = freeze <2 x i32> [[Y:%.*]]
1037; CHECK-NEXT:    [[TMP1:%.*]] = icmp eq <2 x i32> [[Y_FROZEN]], splat (i32 -1)
1038; CHECK-NEXT:    [[R:%.*]] = select <2 x i1> [[TMP1]], <2 x i32> zeroinitializer, <2 x i32> [[Y_FROZEN]]
1039; CHECK-NEXT:    ret <2 x i32> [[R]]
1040;
1041  %sext.i1 = sext <2 x i1> %x to <2 x i32>
1042  %r = urem <2 x i32> %y, %sext.i1
1043  ret <2 x i32> %r
1044}
1045
1046define i16 @rem_pow2_or_zero(i16 %x, i16 %y) {
1047; CHECK-LABEL: @rem_pow2_or_zero(
1048; CHECK-NEXT:    [[POPCNT:%.*]] = call range(i16 1, 17) i16 @llvm.ctpop.i16(i16 [[Y:%.*]])
1049; CHECK-NEXT:    [[COND:%.*]] = icmp samesign ult i16 [[POPCNT]], 2
1050; CHECK-NEXT:    tail call void @llvm.assume(i1 [[COND]])
1051; CHECK-NEXT:    [[TMP1:%.*]] = add i16 [[Y]], -1
1052; CHECK-NEXT:    [[REM:%.*]] = and i16 [[X:%.*]], [[TMP1]]
1053; CHECK-NEXT:    ret i16 [[REM]]
1054;
1055  %popcnt = call i16 @llvm.ctpop.i16(i16 %y)
1056  %cond = icmp ult i16 %popcnt, 2
1057  tail call void @llvm.assume(i1 %cond)
1058  %rem = urem i16 %x, %y
1059  ret i16 %rem
1060}
1061
1062define i16 @rem_pow2(i16 %x, i16 %y) {
1063; CHECK-LABEL: @rem_pow2(
1064; CHECK-NEXT:    [[POPCNT:%.*]] = call range(i16 1, 17) i16 @llvm.ctpop.i16(i16 [[Y:%.*]])
1065; CHECK-NEXT:    [[COND:%.*]] = icmp eq i16 [[POPCNT]], 1
1066; CHECK-NEXT:    tail call void @llvm.assume(i1 [[COND]])
1067; CHECK-NEXT:    [[TMP1:%.*]] = add i16 [[Y]], -1
1068; CHECK-NEXT:    [[REM:%.*]] = and i16 [[X:%.*]], [[TMP1]]
1069; CHECK-NEXT:    ret i16 [[REM]]
1070;
1071  %popcnt = call i16 @llvm.ctpop.i16(i16 %y)
1072  %cond = icmp eq i16 %popcnt, 1
1073  tail call void @llvm.assume(i1 %cond)
1074  %rem = urem i16 %x, %y
1075  ret i16 %rem
1076}
1077
1078define i64 @rem_pow2_domcond(i64 %a, i64 %b) {
1079; CHECK-LABEL: @rem_pow2_domcond(
1080; CHECK-NEXT:  start:
1081; CHECK-NEXT:    [[CPOP:%.*]] = call range(i64 0, 65) i64 @llvm.ctpop.i64(i64 [[B:%.*]])
1082; CHECK-NEXT:    [[COND:%.*]] = icmp eq i64 [[CPOP]], 1
1083; CHECK-NEXT:    br i1 [[COND]], label [[BB1:%.*]], label [[BB2:%.*]]
1084; CHECK:       bb1:
1085; CHECK-NEXT:    [[TMP0:%.*]] = add i64 [[B]], -1
1086; CHECK-NEXT:    [[REM:%.*]] = and i64 [[A:%.*]], [[TMP0]]
1087; CHECK-NEXT:    ret i64 [[REM]]
1088; CHECK:       bb2:
1089; CHECK-NEXT:    ret i64 0
1090;
1091start:
1092  %cpop = call i64 @llvm.ctpop.i64(i64 %b)
1093  %cond = icmp eq i64 %cpop, 1
1094  br i1 %cond, label %bb1, label %bb2
1095
1096bb1:
1097  %rem = urem i64 %a, %b
1098  ret i64 %rem
1099
1100bb2:
1101  ret i64 0
1102}
1103
1104define i64 @rem_pow2_domcond_in_else(i64 %a, i64 %b) {
1105; CHECK-LABEL: @rem_pow2_domcond_in_else(
1106; CHECK-NEXT:  start:
1107; CHECK-NEXT:    [[CPOP:%.*]] = call range(i64 0, 65) i64 @llvm.ctpop.i64(i64 [[B:%.*]])
1108; CHECK-NEXT:    [[COND_NOT:%.*]] = icmp eq i64 [[CPOP]], 1
1109; CHECK-NEXT:    br i1 [[COND_NOT]], label [[BB1:%.*]], label [[BB2:%.*]]
1110; CHECK:       bb1:
1111; CHECK-NEXT:    [[TMP0:%.*]] = add i64 [[B]], -1
1112; CHECK-NEXT:    [[REM:%.*]] = and i64 [[A:%.*]], [[TMP0]]
1113; CHECK-NEXT:    ret i64 [[REM]]
1114; CHECK:       bb2:
1115; CHECK-NEXT:    ret i64 0
1116;
1117start:
1118  %cpop = call i64 @llvm.ctpop.i64(i64 %b)
1119  %cond = icmp ne i64 %cpop, 1
1120  br i1 %cond, label %bb2, label %bb1
1121
1122bb1:
1123  %rem = urem i64 %a, %b
1124  ret i64 %rem
1125
1126bb2:
1127  ret i64 0
1128}
1129
1130define i64 @rem_pow2_or_zero_domcond(i64 %a, i64 %b) {
1131; CHECK-LABEL: @rem_pow2_or_zero_domcond(
1132; CHECK-NEXT:  start:
1133; CHECK-NEXT:    [[CPOP:%.*]] = call range(i64 0, 65) i64 @llvm.ctpop.i64(i64 [[B:%.*]])
1134; CHECK-NEXT:    [[COND:%.*]] = icmp samesign ult i64 [[CPOP]], 2
1135; CHECK-NEXT:    br i1 [[COND]], label [[BB1:%.*]], label [[BB2:%.*]]
1136; CHECK:       bb1:
1137; CHECK-NEXT:    [[TMP0:%.*]] = add i64 [[B]], -1
1138; CHECK-NEXT:    [[REM:%.*]] = and i64 [[A:%.*]], [[TMP0]]
1139; CHECK-NEXT:    ret i64 [[REM]]
1140; CHECK:       bb2:
1141; CHECK-NEXT:    ret i64 0
1142;
1143start:
1144  %cpop = call i64 @llvm.ctpop.i64(i64 %b)
1145  %cond = icmp ult i64 %cpop, 2
1146  br i1 %cond, label %bb1, label %bb2
1147
1148bb1:
1149  %rem = urem i64 %a, %b
1150  ret i64 %rem
1151
1152bb2:
1153  ret i64 0
1154}
1155
1156define i64 @rem_pow2_non_domcond(i64 %a, i64 %b) {
1157; CHECK-LABEL: @rem_pow2_non_domcond(
1158; CHECK-NEXT:  start:
1159; CHECK-NEXT:    [[CPOP:%.*]] = call range(i64 0, 65) i64 @llvm.ctpop.i64(i64 [[B:%.*]])
1160; CHECK-NEXT:    [[COND_NOT:%.*]] = icmp eq i64 [[CPOP]], 1
1161; CHECK-NEXT:    br i1 [[COND_NOT]], label [[BB1:%.*]], label [[BB2:%.*]]
1162; CHECK:       bb1:
1163; CHECK-NEXT:    [[REM:%.*]] = urem i64 [[A:%.*]], [[B]]
1164; CHECK-NEXT:    ret i64 [[REM]]
1165; CHECK:       bb2:
1166; CHECK-NEXT:    br label [[BB1]]
1167;
1168start:
1169  %cpop = call i64 @llvm.ctpop.i64(i64 %b)
1170  %cond = icmp ne i64 %cpop, 1
1171  br i1 %cond, label %bb2, label %bb1
1172
1173bb1:
1174  %rem = urem i64 %a, %b
1175  ret i64 %rem
1176
1177bb2:
1178  br label %bb1
1179}
1180