xref: /llvm-project/llvm/test/Transforms/CorrelatedValuePropagation/cond-at-use.ll (revision eaa1b05c48c88ed6da6b8fc21d07f8417575a051)
1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2; RUN: opt -S -passes=correlated-propagation < %s | FileCheck %s
3
4declare void @use.i16(i16)
5declare i16 @llvm.usub.sat.i16(i16, i16)
6declare i16 @llvm.uadd.sat.i16(i16, i16)
7declare i16 @llvm.umin.i16(i16, i16)
8declare i16 @llvm.abs.i16(i16, i1)
9
10define i16 @sel_true_cond(i16 noundef %x) {
11; CHECK-LABEL: @sel_true_cond(
12; CHECK-NEXT:    [[SUB1:%.*]] = sub nuw i16 [[X:%.*]], 10
13; CHECK-NEXT:    [[CMP:%.*]] = icmp uge i16 [[X]], 10
14; CHECK-NEXT:    [[SEL:%.*]] = select i1 [[CMP]], i16 [[SUB1]], i16 42
15; CHECK-NEXT:    ret i16 [[SEL]]
16;
17  %sub = call i16 @llvm.usub.sat.i16(i16 %x, i16 10)
18  %cmp = icmp uge i16 %x, 10
19  %sel = select i1 %cmp, i16 %sub, i16 42
20  ret i16 %sel
21}
22
23define i16 @sel_true_cond_insufficient(i16 %x) {
24; CHECK-LABEL: @sel_true_cond_insufficient(
25; CHECK-NEXT:    [[SUB:%.*]] = call i16 @llvm.usub.sat.i16(i16 [[X:%.*]], i16 10)
26; CHECK-NEXT:    [[CMP:%.*]] = icmp uge i16 [[X]], 9
27; CHECK-NEXT:    [[SEL:%.*]] = select i1 [[CMP]], i16 [[SUB]], i16 42
28; CHECK-NEXT:    ret i16 [[SEL]]
29;
30  %sub = call i16 @llvm.usub.sat.i16(i16 %x, i16 10)
31  %cmp = icmp uge i16 %x, 9
32  %sel = select i1 %cmp, i16 %sub, i16 42
33  ret i16 %sel
34}
35
36define i16 @sel_true_cond_wrong_swap(i16 %x) {
37; CHECK-LABEL: @sel_true_cond_wrong_swap(
38; CHECK-NEXT:    [[SUB:%.*]] = call i16 @llvm.usub.sat.i16(i16 [[X:%.*]], i16 10)
39; CHECK-NEXT:    [[CMP:%.*]] = icmp uge i16 [[X]], 10
40; CHECK-NEXT:    [[SEL:%.*]] = select i1 [[CMP]], i16 42, i16 [[SUB]]
41; CHECK-NEXT:    ret i16 [[SEL]]
42;
43  %sub = call i16 @llvm.usub.sat.i16(i16 %x, i16 10)
44  %cmp = icmp uge i16 %x, 10
45  %sel = select i1 %cmp, i16 42, i16 %sub
46  ret i16 %sel
47}
48
49define i16 @sel_true_cond_wrong_op(i16 %x, i16 %y) {
50; CHECK-LABEL: @sel_true_cond_wrong_op(
51; CHECK-NEXT:    [[SUB:%.*]] = call i16 @llvm.usub.sat.i16(i16 [[X:%.*]], i16 10)
52; CHECK-NEXT:    [[CMP:%.*]] = icmp uge i16 [[Y:%.*]], 10
53; CHECK-NEXT:    [[SEL:%.*]] = select i1 [[CMP]], i16 [[SUB]], i16 42
54; CHECK-NEXT:    ret i16 [[SEL]]
55;
56  %sub = call i16 @llvm.usub.sat.i16(i16 %x, i16 10)
57  %cmp = icmp uge i16 %y, 10
58  %sel = select i1 %cmp, i16 %sub, i16 42
59  ret i16 %sel
60}
61
62define i16 @sel_true_cond_extra_use(i16 %x) {
63; CHECK-LABEL: @sel_true_cond_extra_use(
64; CHECK-NEXT:    [[SUB:%.*]] = call i16 @llvm.usub.sat.i16(i16 [[X:%.*]], i16 10)
65; CHECK-NEXT:    call void @use.i16(i16 [[SUB]])
66; CHECK-NEXT:    [[CMP:%.*]] = icmp uge i16 [[X]], 10
67; CHECK-NEXT:    [[SEL:%.*]] = select i1 [[CMP]], i16 [[SUB]], i16 42
68; CHECK-NEXT:    ret i16 [[SEL]]
69;
70  %sub = call i16 @llvm.usub.sat.i16(i16 %x, i16 10)
71  call void @use.i16(i16 %sub)
72  %cmp = icmp uge i16 %x, 10
73  %sel = select i1 %cmp, i16 %sub, i16 42
74  ret i16 %sel
75}
76
77define i16 @sel_true_cond_chain_speculatable(i16 noundef %x) {
78; CHECK-LABEL: @sel_true_cond_chain_speculatable(
79; CHECK-NEXT:    [[SUB1:%.*]] = add nuw i16 [[X:%.*]], 1
80; CHECK-NEXT:    [[EXTRA:%.*]] = mul i16 [[SUB1]], 3
81; CHECK-NEXT:    [[CMP:%.*]] = icmp ne i16 [[X]], -1
82; CHECK-NEXT:    [[SEL:%.*]] = select i1 [[CMP]], i16 [[EXTRA]], i16 42
83; CHECK-NEXT:    ret i16 [[SEL]]
84;
85  %sub = call i16 @llvm.uadd.sat.i16(i16 %x, i16 1)
86  %extra = mul i16 %sub, 3
87  %cmp = icmp ne i16 %x, -1
88  %sel = select i1 %cmp, i16 %extra, i16 42
89  ret i16 %sel
90}
91
92define i16 @sel_true_cond_chain_non_speculatable(i16 %x) {
93; CHECK-LABEL: @sel_true_cond_chain_non_speculatable(
94; CHECK-NEXT:    [[SUB:%.*]] = call i16 @llvm.uadd.sat.i16(i16 [[X:%.*]], i16 1)
95; CHECK-NEXT:    [[EXTRA:%.*]] = udiv i16 3, [[SUB]]
96; CHECK-NEXT:    [[CMP:%.*]] = icmp ne i16 [[X]], -1
97; CHECK-NEXT:    [[SEL:%.*]] = select i1 [[CMP]], i16 [[EXTRA]], i16 42
98; CHECK-NEXT:    ret i16 [[SEL]]
99;
100  %sub = call i16 @llvm.uadd.sat.i16(i16 %x, i16 1)
101  %extra = udiv i16 3, %sub
102  %cmp = icmp ne i16 %x, -1
103  %sel = select i1 %cmp, i16 %extra, i16 42
104  ret i16 %sel
105}
106
107; TODO: We could handle this case by raising the limit on the number of
108; instructions we look through.
109define i16 @sel_true_cond_longer_chain(i16 %x) {
110; CHECK-LABEL: @sel_true_cond_longer_chain(
111; CHECK-NEXT:    [[SUB:%.*]] = call i16 @llvm.uadd.sat.i16(i16 [[X:%.*]], i16 1)
112; CHECK-NEXT:    [[EXTRA:%.*]] = mul i16 [[SUB]], 3
113; CHECK-NEXT:    [[EXTRA2:%.*]] = xor i16 [[SUB]], 7
114; CHECK-NEXT:    [[CMP:%.*]] = icmp ne i16 [[X]], -1
115; CHECK-NEXT:    [[SEL:%.*]] = select i1 [[CMP]], i16 [[EXTRA2]], i16 42
116; CHECK-NEXT:    ret i16 [[SEL]]
117;
118  %sub = call i16 @llvm.uadd.sat.i16(i16 %x, i16 1)
119  %extra = mul i16 %sub, 3
120  %extra2 = xor i16 %sub, 7
121  %cmp = icmp ne i16 %x, -1
122  %sel = select i1 %cmp, i16 %extra2, i16 42
123  ret i16 %sel
124}
125
126define i16 @sel_false_cond(i16 noundef %x) {
127; CHECK-LABEL: @sel_false_cond(
128; CHECK-NEXT:    [[SUB1:%.*]] = sub nuw i16 [[X:%.*]], 10
129; CHECK-NEXT:    [[CMP:%.*]] = icmp ult i16 [[X]], 10
130; CHECK-NEXT:    [[SEL:%.*]] = select i1 [[CMP]], i16 42, i16 [[SUB1]]
131; CHECK-NEXT:    ret i16 [[SEL]]
132;
133  %sub = call i16 @llvm.usub.sat.i16(i16 %x, i16 10)
134  %cmp = icmp ult i16 %x, 10
135  %sel = select i1 %cmp, i16 42, i16 %sub
136  ret i16 %sel
137}
138
139define i16 @sel_false_cond_insufficient(i16 %x) {
140; CHECK-LABEL: @sel_false_cond_insufficient(
141; CHECK-NEXT:    [[SUB:%.*]] = call i16 @llvm.usub.sat.i16(i16 [[X:%.*]], i16 10)
142; CHECK-NEXT:    [[CMP:%.*]] = icmp ult i16 [[X]], 9
143; CHECK-NEXT:    [[SEL:%.*]] = select i1 [[CMP]], i16 42, i16 [[SUB]]
144; CHECK-NEXT:    ret i16 [[SEL]]
145;
146  %sub = call i16 @llvm.usub.sat.i16(i16 %x, i16 10)
147  %cmp = icmp ult i16 %x, 9
148  %sel = select i1 %cmp, i16 42, i16 %sub
149  ret i16 %sel
150}
151
152define i16 @phi_true_cond(i16 %x) {
153; CHECK-LABEL: @phi_true_cond(
154; CHECK-NEXT:  entry:
155; CHECK-NEXT:    [[SUB1:%.*]] = sub nuw i16 [[X:%.*]], 10
156; CHECK-NEXT:    [[CMP:%.*]] = icmp uge i16 [[X]], 10
157; CHECK-NEXT:    br i1 [[CMP]], label [[JOIN:%.*]], label [[SPLIT:%.*]]
158; CHECK:       split:
159; CHECK-NEXT:    br label [[JOIN]]
160; CHECK:       join:
161; CHECK-NEXT:    [[PHI:%.*]] = phi i16 [ [[SUB1]], [[ENTRY:%.*]] ], [ 42, [[SPLIT]] ]
162; CHECK-NEXT:    ret i16 [[PHI]]
163;
164entry:
165  %sub = call i16 @llvm.usub.sat.i16(i16 %x, i16 10)
166  %cmp = icmp uge i16 %x, 10
167  br i1 %cmp, label %join, label %split
168
169split:
170  br label %join
171
172join:
173  %phi = phi i16 [ %sub, %entry ], [ 42, %split ]
174  ret i16 %phi
175}
176
177define i16 @phi_true_cond_insufficient(i16 %x) {
178; CHECK-LABEL: @phi_true_cond_insufficient(
179; CHECK-NEXT:  entry:
180; CHECK-NEXT:    [[SUB:%.*]] = call i16 @llvm.usub.sat.i16(i16 [[X:%.*]], i16 10)
181; CHECK-NEXT:    [[CMP:%.*]] = icmp uge i16 [[X]], 9
182; CHECK-NEXT:    br i1 [[CMP]], label [[JOIN:%.*]], label [[SPLIT:%.*]]
183; CHECK:       split:
184; CHECK-NEXT:    br label [[JOIN]]
185; CHECK:       join:
186; CHECK-NEXT:    [[PHI:%.*]] = phi i16 [ [[SUB]], [[ENTRY:%.*]] ], [ 42, [[SPLIT]] ]
187; CHECK-NEXT:    ret i16 [[PHI]]
188;
189entry:
190  %sub = call i16 @llvm.usub.sat.i16(i16 %x, i16 10)
191  %cmp = icmp uge i16 %x, 9
192  br i1 %cmp, label %join, label %split
193
194split:
195  br label %join
196
197join:
198  %phi = phi i16 [ %sub, %entry ], [ 42, %split ]
199  ret i16 %phi
200}
201
202; TODO: We could handle this by using conditions that are not directly on the
203; phi edge.
204define i16 @phi_true_cond_non_local(i16 %x) {
205; CHECK-LABEL: @phi_true_cond_non_local(
206; CHECK-NEXT:  entry:
207; CHECK-NEXT:    [[SUB:%.*]] = call i16 @llvm.usub.sat.i16(i16 [[X:%.*]], i16 10)
208; CHECK-NEXT:    [[CMP:%.*]] = icmp uge i16 [[X]], 10
209; CHECK-NEXT:    br i1 [[CMP]], label [[SPLIT:%.*]], label [[JOIN:%.*]]
210; CHECK:       split:
211; CHECK-NEXT:    br label [[JOIN]]
212; CHECK:       join:
213; CHECK-NEXT:    [[PHI:%.*]] = phi i16 [ [[SUB]], [[SPLIT]] ], [ 42, [[ENTRY:%.*]] ]
214; CHECK-NEXT:    ret i16 [[PHI]]
215;
216entry:
217  %sub = call i16 @llvm.usub.sat.i16(i16 %x, i16 10)
218  %cmp = icmp uge i16 %x, 10
219  br i1 %cmp, label %split, label %join
220
221split:
222  br label %join
223
224join:
225  %phi = phi i16 [ %sub, %split ], [ 42, %entry ]
226  ret i16 %phi
227}
228
229define i16 @phi_false_cond(i16 %x) {
230; CHECK-LABEL: @phi_false_cond(
231; CHECK-NEXT:  entry:
232; CHECK-NEXT:    [[SUB1:%.*]] = sub nuw i16 [[X:%.*]], 10
233; CHECK-NEXT:    [[CMP:%.*]] = icmp ult i16 [[X]], 10
234; CHECK-NEXT:    br i1 [[CMP]], label [[SPLIT:%.*]], label [[JOIN:%.*]]
235; CHECK:       split:
236; CHECK-NEXT:    br label [[JOIN]]
237; CHECK:       join:
238; CHECK-NEXT:    [[PHI:%.*]] = phi i16 [ [[SUB1]], [[ENTRY:%.*]] ], [ 42, [[SPLIT]] ]
239; CHECK-NEXT:    ret i16 [[PHI]]
240;
241entry:
242  %sub = call i16 @llvm.usub.sat.i16(i16 %x, i16 10)
243  %cmp = icmp ult i16 %x, 10
244  br i1 %cmp, label %split, label %join
245
246split:
247  br label %join
248
249join:
250  %phi = phi i16 [ %sub, %entry ], [ 42, %split ]
251  ret i16 %phi
252}
253
254define i16 @phi_false_cond_insufficient(i16 %x) {
255; CHECK-LABEL: @phi_false_cond_insufficient(
256; CHECK-NEXT:  entry:
257; CHECK-NEXT:    [[SUB:%.*]] = call i16 @llvm.usub.sat.i16(i16 [[X:%.*]], i16 10)
258; CHECK-NEXT:    [[CMP:%.*]] = icmp ult i16 [[X]], 9
259; CHECK-NEXT:    br i1 [[CMP]], label [[SPLIT:%.*]], label [[JOIN:%.*]]
260; CHECK:       split:
261; CHECK-NEXT:    br label [[JOIN]]
262; CHECK:       join:
263; CHECK-NEXT:    [[PHI:%.*]] = phi i16 [ [[SUB]], [[ENTRY:%.*]] ], [ 42, [[SPLIT]] ]
264; CHECK-NEXT:    ret i16 [[PHI]]
265;
266entry:
267  %sub = call i16 @llvm.usub.sat.i16(i16 %x, i16 10)
268  %cmp = icmp ult i16 %x, 9
269  br i1 %cmp, label %split, label %join
270
271split:
272  br label %join
273
274join:
275  %phi = phi i16 [ %sub, %entry ], [ 42, %split ]
276  ret i16 %phi
277}
278
279; TODO: We could handle this by using conditions that are not directly on the
280; phi edge.
281define i16 @phi_false_cond_non_local(i16 %x) {
282; CHECK-LABEL: @phi_false_cond_non_local(
283; CHECK-NEXT:  entry:
284; CHECK-NEXT:    [[SUB:%.*]] = call i16 @llvm.usub.sat.i16(i16 [[X:%.*]], i16 10)
285; CHECK-NEXT:    [[CMP:%.*]] = icmp ult i16 [[X]], 10
286; CHECK-NEXT:    br i1 [[CMP]], label [[JOIN:%.*]], label [[SPLIT:%.*]]
287; CHECK:       split:
288; CHECK-NEXT:    br label [[JOIN]]
289; CHECK:       join:
290; CHECK-NEXT:    [[PHI:%.*]] = phi i16 [ [[SUB]], [[SPLIT]] ], [ 42, [[ENTRY:%.*]] ]
291; CHECK-NEXT:    ret i16 [[PHI]]
292;
293entry:
294  %sub = call i16 @llvm.usub.sat.i16(i16 %x, i16 10)
295  %cmp = icmp ult i16 %x, 10
296  br i1 %cmp, label %join, label %split
297
298split:
299  br label %join
300
301join:
302  %phi = phi i16 [ %sub, %split ], [ 42, %entry ]
303  ret i16 %phi
304}
305
306define i16 @loop_cond() {
307; CHECK-LABEL: @loop_cond(
308; CHECK-NEXT:  entry:
309; CHECK-NEXT:    br label [[LOOP:%.*]]
310; CHECK:       loop:
311; CHECK-NEXT:    [[IV:%.*]] = phi i16 [ 1000, [[ENTRY:%.*]] ], [ [[IV_NEXT1:%.*]], [[LOOP]] ]
312; CHECK-NEXT:    [[COUNT:%.*]] = phi i16 [ 0, [[ENTRY]] ], [ [[COUNT_NEXT:%.*]], [[LOOP]] ]
313; CHECK-NEXT:    [[CMP:%.*]] = icmp eq i16 [[IV]], 0
314; CHECK-NEXT:    [[IV_NEXT1]] = sub nuw i16 [[IV]], 1
315; CHECK-NEXT:    [[COUNT_NEXT]] = add i16 [[COUNT]], 1
316; CHECK-NEXT:    br i1 [[CMP]], label [[EXIT:%.*]], label [[LOOP]]
317; CHECK:       exit:
318; CHECK-NEXT:    ret i16 [[COUNT]]
319;
320entry:
321  br label %loop
322
323loop:
324  %iv = phi i16 [ 1000, %entry ], [ %iv.next, %loop ]
325  %count = phi i16 [ 0, %entry ], [ %count.next, %loop ]
326  %cmp = icmp eq i16 %iv, 0
327  %iv.next = call i16 @llvm.usub.sat.i16(i16 %iv, i16 1)
328  %count.next = add i16 %count, 1
329  br i1 %cmp, label %exit, label %loop
330
331exit:
332  ret i16 %count
333}
334
335define i16 @urem_elide(i16 noundef %x) {
336; CHECK-LABEL: @urem_elide(
337; CHECK-NEXT:    [[CMP:%.*]] = icmp ult i16 [[X:%.*]], 42
338; CHECK-NEXT:    [[SEL:%.*]] = select i1 [[CMP]], i16 [[X]], i16 24
339; CHECK-NEXT:    ret i16 [[SEL]]
340;
341  %urem = urem i16 %x, 42
342  %cmp = icmp ult i16 %x, 42
343  %sel = select i1 %cmp, i16 %urem, i16 24
344  ret i16 %sel
345}
346
347define i16 @urem_expand(i16 noundef %x) {
348; CHECK-LABEL: @urem_expand(
349; CHECK-NEXT:    [[UREM_UREM:%.*]] = sub nuw i16 [[X:%.*]], 42
350; CHECK-NEXT:    [[UREM_CMP:%.*]] = icmp ult i16 [[X]], 42
351; CHECK-NEXT:    [[UREM:%.*]] = select i1 [[UREM_CMP]], i16 [[X]], i16 [[UREM_UREM]]
352; CHECK-NEXT:    [[CMP:%.*]] = icmp ult i16 [[X]], 84
353; CHECK-NEXT:    [[SEL:%.*]] = select i1 [[CMP]], i16 [[UREM]], i16 24
354; CHECK-NEXT:    ret i16 [[SEL]]
355;
356  %urem = urem i16 %x, 42
357  %cmp = icmp ult i16 %x, 84
358  %sel = select i1 %cmp, i16 %urem, i16 24
359  ret i16 %sel
360}
361
362define i16 @urem_narrow(i16 noundef %x) {
363; CHECK-LABEL: @urem_narrow(
364; CHECK-NEXT:    [[UREM_LHS_TRUNC:%.*]] = trunc i16 [[X:%.*]] to i8
365; CHECK-NEXT:    [[UREM1:%.*]] = urem i8 [[UREM_LHS_TRUNC]], 42
366; CHECK-NEXT:    [[UREM_ZEXT:%.*]] = zext i8 [[UREM1]] to i16
367; CHECK-NEXT:    [[CMP:%.*]] = icmp ult i16 [[X]], 85
368; CHECK-NEXT:    [[SEL:%.*]] = select i1 [[CMP]], i16 [[UREM_ZEXT]], i16 24
369; CHECK-NEXT:    ret i16 [[SEL]]
370;
371  %urem = urem i16 %x, 42
372  %cmp = icmp ult i16 %x, 85
373  %sel = select i1 %cmp, i16 %urem, i16 24
374  ret i16 %sel
375}
376
377define i16 @urem_insufficient(i16 %x) {
378; CHECK-LABEL: @urem_insufficient(
379; CHECK-NEXT:    [[UREM:%.*]] = urem i16 [[X:%.*]], 42
380; CHECK-NEXT:    [[CMP:%.*]] = icmp ult i16 [[X]], 257
381; CHECK-NEXT:    [[SEL:%.*]] = select i1 [[CMP]], i16 [[UREM]], i16 24
382; CHECK-NEXT:    ret i16 [[SEL]]
383;
384  %urem = urem i16 %x, 42
385  %cmp = icmp ult i16 %x, 257
386  %sel = select i1 %cmp, i16 %urem, i16 24
387  ret i16 %sel
388}
389
390define i16 @srem_elide(i16 noundef %x) {
391; CHECK-LABEL: @srem_elide(
392; CHECK-NEXT:    [[CMP1:%.*]] = icmp slt i16 [[X:%.*]], 42
393; CHECK-NEXT:    [[CMP2:%.*]] = icmp sgt i16 [[X]], -42
394; CHECK-NEXT:    [[AND:%.*]] = and i1 [[CMP1]], [[CMP2]]
395; CHECK-NEXT:    [[SEL:%.*]] = select i1 [[AND]], i16 [[X]], i16 24
396; CHECK-NEXT:    ret i16 [[SEL]]
397;
398  %srem = srem i16 %x, 42
399  %cmp1 = icmp slt i16 %x, 42
400  %cmp2 = icmp sgt i16 %x, -42
401  %and = and i1 %cmp1, %cmp2
402  %sel = select i1 %and, i16 %srem, i16 24
403  ret i16 %sel
404}
405
406define i16 @srem_narrow(i16 noundef %x) {
407; CHECK-LABEL: @srem_narrow(
408; CHECK-NEXT:    [[SREM_LHS_TRUNC:%.*]] = trunc i16 [[X:%.*]] to i8
409; CHECK-NEXT:    [[SREM1:%.*]] = srem i8 [[SREM_LHS_TRUNC]], 42
410; CHECK-NEXT:    [[SREM_SEXT:%.*]] = sext i8 [[SREM1]] to i16
411; CHECK-NEXT:    [[CMP1:%.*]] = icmp slt i16 [[X]], 43
412; CHECK-NEXT:    [[CMP2:%.*]] = icmp sgt i16 [[X]], -43
413; CHECK-NEXT:    [[AND:%.*]] = and i1 [[CMP1]], [[CMP2]]
414; CHECK-NEXT:    [[SEL:%.*]] = select i1 [[AND]], i16 [[SREM_SEXT]], i16 24
415; CHECK-NEXT:    ret i16 [[SEL]]
416;
417  %srem = srem i16 %x, 42
418  %cmp1 = icmp slt i16 %x, 43
419  %cmp2 = icmp sgt i16 %x, -43
420  %and = and i1 %cmp1, %cmp2
421  %sel = select i1 %and, i16 %srem, i16 24
422  ret i16 %sel
423}
424
425define i16 @srem_convert(i16 noundef %x) {
426; CHECK-LABEL: @srem_convert(
427; CHECK-NEXT:    [[X_NONNEG:%.*]] = sub i16 0, [[X:%.*]]
428; CHECK-NEXT:    [[SREM1:%.*]] = urem i16 [[X_NONNEG]], 42
429; CHECK-NEXT:    [[SREM1_NEG:%.*]] = sub i16 0, [[SREM1]]
430; CHECK-NEXT:    [[CMP:%.*]] = icmp slt i16 [[X]], 0
431; CHECK-NEXT:    [[SEL:%.*]] = select i1 [[CMP]], i16 [[SREM1_NEG]], i16 24
432; CHECK-NEXT:    ret i16 [[SEL]]
433;
434  %srem = srem i16 %x, 42
435  %cmp = icmp slt i16 %x, 0
436  %sel = select i1 %cmp, i16 %srem, i16 24
437  ret i16 %sel
438}
439
440define i16 @sdiv_convert(i16 noundef %x) {
441; CHECK-LABEL: @sdiv_convert(
442; CHECK-NEXT:    [[X_NONNEG:%.*]] = sub i16 0, [[X:%.*]]
443; CHECK-NEXT:    [[SREM1:%.*]] = udiv i16 [[X_NONNEG]], 42
444; CHECK-NEXT:    [[SREM1_NEG:%.*]] = sub i16 0, [[SREM1]]
445; CHECK-NEXT:    [[CMP:%.*]] = icmp slt i16 [[X]], 0
446; CHECK-NEXT:    [[SEL:%.*]] = select i1 [[CMP]], i16 [[SREM1_NEG]], i16 24
447; CHECK-NEXT:    ret i16 [[SEL]]
448;
449  %srem = sdiv i16 %x, 42
450  %cmp = icmp slt i16 %x, 0
451  %sel = select i1 %cmp, i16 %srem, i16 24
452  ret i16 %sel
453}
454
455define i16 @abs_elide(i16 %x) {
456; CHECK-LABEL: @abs_elide(
457; CHECK-NEXT:    [[ABS:%.*]] = call i16 @llvm.abs.i16(i16 [[X:%.*]], i1 false)
458; CHECK-NEXT:    [[CMP:%.*]] = icmp ule i16 [[X]], -32768
459; CHECK-NEXT:    [[SEL:%.*]] = select i1 [[CMP]], i16 [[ABS]], i16 42
460; CHECK-NEXT:    ret i16 [[SEL]]
461;
462  %abs = call i16 @llvm.abs.i16(i16 %x, i1 false)
463  %cmp = icmp ule i16 %x, 32768
464  %sel = select i1 %cmp, i16 %abs, i16 42
465  ret i16 %sel
466}
467
468define i16 @abs_elide2(i16 %x) {
469; CHECK-LABEL: @abs_elide2(
470; CHECK-NEXT:    [[ABS:%.*]] = call i16 @llvm.abs.i16(i16 [[X:%.*]], i1 false)
471; CHECK-NEXT:    [[CMP:%.*]] = icmp sle i16 [[X]], 0
472; CHECK-NEXT:    [[SEL:%.*]] = select i1 [[CMP]], i16 [[ABS]], i16 42
473; CHECK-NEXT:    ret i16 [[SEL]]
474;
475  %abs = call i16 @llvm.abs.i16(i16 %x, i1 false)
476  %cmp = icmp sle i16 %x, 0
477  %sel = select i1 %cmp, i16 %abs, i16 42
478  ret i16 %sel
479}
480
481define i16 @abs_not_int_min(i16 %x) {
482; CHECK-LABEL: @abs_not_int_min(
483; CHECK-NEXT:    [[ABS:%.*]] = call i16 @llvm.abs.i16(i16 [[X:%.*]], i1 false)
484; CHECK-NEXT:    [[CMP:%.*]] = icmp ne i16 [[X]], -32768
485; CHECK-NEXT:    [[SEL:%.*]] = select i1 [[CMP]], i16 [[ABS]], i16 42
486; CHECK-NEXT:    ret i16 [[SEL]]
487;
488  %abs = call i16 @llvm.abs.i16(i16 %x, i1 false)
489  %cmp = icmp ne i16 %x, 32768
490  %sel = select i1 %cmp, i16 %abs, i16 42
491  ret i16 %sel
492}
493
494define i16 @umin_elide(i16 %x) {
495; CHECK-LABEL: @umin_elide(
496; CHECK-NEXT:    [[MIN:%.*]] = call i16 @llvm.umin.i16(i16 [[X:%.*]], i16 10)
497; CHECK-NEXT:    [[CMP:%.*]] = icmp ule i16 [[X]], 10
498; CHECK-NEXT:    [[SEL:%.*]] = select i1 [[CMP]], i16 [[MIN]], i16 42
499; CHECK-NEXT:    ret i16 [[SEL]]
500;
501  %min = call i16 @llvm.umin.i16(i16 %x, i16 10)
502  %cmp = icmp ule i16 %x, 10
503  %sel = select i1 %cmp, i16 %min, i16 42
504  ret i16 %sel
505}
506
507define i16 @ashr_convert(i16 noundef %x, i16 %y) {
508; CHECK-LABEL: @ashr_convert(
509; CHECK-NEXT:    [[ASHR:%.*]] = lshr i16 [[X:%.*]], [[Y:%.*]]
510; CHECK-NEXT:    [[CMP:%.*]] = icmp sge i16 [[X]], 0
511; CHECK-NEXT:    [[SEL:%.*]] = select i1 [[CMP]], i16 [[ASHR]], i16 24
512; CHECK-NEXT:    ret i16 [[SEL]]
513;
514  %ashr = ashr i16 %x, %y
515  %cmp = icmp sge i16 %x, 0
516  %sel = select i1 %cmp, i16 %ashr, i16 24
517  ret i16 %sel
518}
519
520define i32 @sext_convert(i16 noundef %x) {
521; CHECK-LABEL: @sext_convert(
522; CHECK-NEXT:    [[EXT:%.*]] = zext nneg i16 [[X:%.*]] to i32
523; CHECK-NEXT:    [[CMP:%.*]] = icmp sge i16 [[X]], 0
524; CHECK-NEXT:    [[SEL:%.*]] = select i1 [[CMP]], i32 [[EXT]], i32 24
525; CHECK-NEXT:    ret i32 [[SEL]]
526;
527  %ext = sext i16 %x to i32
528  %cmp = icmp sge i16 %x, 0
529  %sel = select i1 %cmp, i32 %ext, i32 24
530  ret i32 %sel
531}
532
533define i16 @infer_flags(i16 %x) {
534; CHECK-LABEL: @infer_flags(
535; CHECK-NEXT:    [[ADD:%.*]] = add i16 [[X:%.*]], 42
536; CHECK-NEXT:    [[CMP:%.*]] = icmp ult i16 [[X]], 100
537; CHECK-NEXT:    [[SEL:%.*]] = select i1 [[CMP]], i16 [[ADD]], i16 24
538; CHECK-NEXT:    ret i16 [[SEL]]
539;
540  %add = add i16 %x, 42
541  %cmp = icmp ult i16 %x, 100
542  %sel = select i1 %cmp, i16 %add, i16 24
543  ret i16 %sel
544}
545
546define i16 @and_elide(i16 noundef %x) {
547; CHECK-LABEL: @and_elide(
548; CHECK-NEXT:    [[CMP:%.*]] = icmp ult i16 [[X:%.*]], 8
549; CHECK-NEXT:    [[SEL:%.*]] = select i1 [[CMP]], i16 [[X]], i16 24
550; CHECK-NEXT:    ret i16 [[SEL]]
551;
552  %and = and i16 %x, 7
553  %cmp = icmp ult i16 %x, 8
554  %sel = select i1 %cmp, i16 %and, i16 24
555  ret i16 %sel
556}
557
558define i16 @cond_value_may_not_well_defined(i16 %x) {
559; CHECK-LABEL: @cond_value_may_not_well_defined(
560; CHECK-NEXT:    [[AND:%.*]] = and i16 [[X:%.*]], 7
561; CHECK-NEXT:    [[CMP:%.*]] = icmp ult i16 [[X]], 8
562; CHECK-NEXT:    [[SEL:%.*]] = select i1 [[CMP]], i16 [[AND]], i16 24
563; CHECK-NEXT:    ret i16 [[SEL]]
564;
565  %and = and i16 %x, 7
566  %cmp = icmp ult i16 %x, 8
567  %sel = select i1 %cmp, i16 %and, i16 24
568  ret i16 %sel
569}
570
571define i16 @and_elide_poison_flags(i16 noundef %a) {
572; CHECK-LABEL: @and_elide_poison_flags(
573; CHECK-NEXT:    [[X:%.*]] = add nuw i16 [[A:%.*]], 1
574; CHECK-NEXT:    [[CMP:%.*]] = icmp ult i16 [[X]], 8
575; CHECK-NEXT:    [[SEL:%.*]] = select i1 [[CMP]], i16 [[X]], i16 24
576; CHECK-NEXT:    ret i16 [[SEL]]
577;
578  %x = add nuw i16 %a, 1
579  %and = and i16 %x, 7
580  %cmp = icmp ult i16 %x, 8
581  %sel = select i1 %cmp, i16 %and, i16 24
582  ret i16 %sel
583}
584
585define i16 @and_elide_poison_flags_missing_noundef(i16 %a) {
586; CHECK-LABEL: @and_elide_poison_flags_missing_noundef(
587; CHECK-NEXT:    [[X:%.*]] = add nuw i16 [[A:%.*]], 1
588; CHECK-NEXT:    [[AND:%.*]] = and i16 [[X]], 7
589; CHECK-NEXT:    [[CMP:%.*]] = icmp ult i16 [[X]], 8
590; CHECK-NEXT:    [[SEL:%.*]] = select i1 [[CMP]], i16 [[AND]], i16 24
591; CHECK-NEXT:    ret i16 [[SEL]]
592;
593  %x = add nuw i16 %a, 1
594  %and = and i16 %x, 7
595  %cmp = icmp ult i16 %x, 8
596  %sel = select i1 %cmp, i16 %and, i16 24
597  ret i16 %sel
598}
599
600define i32 @pr87854(i32 noundef %x.1, i32 noundef %i) {
601; CHECK-LABEL: @pr87854(
602; CHECK-NEXT:    [[COND:%.*]] = icmp sgt i32 [[X_1:%.*]], -1
603; CHECK-NEXT:    tail call void @llvm.assume(i1 [[COND]])
604; CHECK-NEXT:    [[INBOUNDS:%.*]] = icmp ult i32 [[I:%.*]], [[X_1]]
605; CHECK-NEXT:    [[NEXT:%.*]] = add nuw i32 [[I]], 1
606; CHECK-NEXT:    [[SPEC_SELECT:%.*]] = select i1 [[INBOUNDS]], i32 [[NEXT]], i32 -1
607; CHECK-NEXT:    ret i32 [[SPEC_SELECT]]
608;
609  %cond = icmp sgt i32 %x.1, -1
610  tail call void @llvm.assume(i1 %cond)
611  %inbounds = icmp ult i32 %i, %x.1
612  %next = add i32 %i, 1
613  %spec.select = select i1 %inbounds, i32 %next, i32 -1
614  ret i32 %spec.select
615}
616
617define i64 @test_shl_nsw_at_use(i64 noundef %x) {
618; CHECK-LABEL: @test_shl_nsw_at_use(
619; CHECK-NEXT:    [[ADD:%.*]] = add i64 [[X:%.*]], 2147483648
620; CHECK-NEXT:    [[CMP:%.*]] = icmp ult i64 [[ADD]], 4294967296
621; CHECK-NEXT:    [[SHL:%.*]] = shl nsw i64 [[X]], 32
622; CHECK-NEXT:    [[SHR:%.*]] = ashr exact i64 [[SHL]], 32
623; CHECK-NEXT:    [[RES:%.*]] = select i1 [[CMP]], i64 [[SHR]], i64 0
624; CHECK-NEXT:    ret i64 [[RES]]
625;
626  %add = add i64 %x, 2147483648
627  %cmp = icmp ult i64 %add, 4294967296
628  %shl = shl i64 %x, 32
629  %shr = ashr exact i64 %shl, 32
630  %res = select i1 %cmp, i64 %shr, i64 0
631  ret i64 %res
632}
633
634define i1 @test_icmp_mod(i64 noundef %x) {
635; CHECK-LABEL: @test_icmp_mod(
636; CHECK-NEXT:  entry:
637; CHECK-NEXT:    [[REM:%.*]] = srem i64 [[X:%.*]], 86400
638; CHECK-NEXT:    [[CMP:%.*]] = icmp slt i64 [[REM]], 0
639; CHECK-NEXT:    [[COND:%.*]] = select i1 [[CMP]], i64 86400, i64 0
640; CHECK-NEXT:    [[ADD:%.*]] = add nsw i64 [[COND]], [[REM]]
641; CHECK-NEXT:    ret i1 false
642;
643entry:
644  %rem = srem i64 %x, 86400
645  %cmp = icmp slt i64 %rem, 0
646  %cond = select i1 %cmp, i64 86400, i64 0
647  %add = add nsw i64 %cond, %rem
648  %cmp1 = icmp ugt i64 %add, 86399
649  ret i1 %cmp1
650}
651
652define i1 @test_icmp_mod_commuted1(i64 noundef %x) {
653; CHECK-LABEL: @test_icmp_mod_commuted1(
654; CHECK-NEXT:  entry:
655; CHECK-NEXT:    [[REM:%.*]] = srem i64 [[X:%.*]], 86400
656; CHECK-NEXT:    [[CMP:%.*]] = icmp slt i64 [[REM]], 0
657; CHECK-NEXT:    [[COND:%.*]] = select i1 [[CMP]], i64 86400, i64 0
658; CHECK-NEXT:    [[ADD:%.*]] = add nsw i64 [[REM]], [[COND]]
659; CHECK-NEXT:    ret i1 false
660;
661entry:
662  %rem = srem i64 %x, 86400
663  %cmp = icmp slt i64 %rem, 0
664  %cond = select i1 %cmp, i64 86400, i64 0
665  %add = add nsw i64 %rem, %cond
666  %cmp1 = icmp ugt i64 %add, 86399
667  ret i1 %cmp1
668}
669
670define i1 @test_icmp_mod_commuted2(i64 noundef %x) {
671; CHECK-LABEL: @test_icmp_mod_commuted2(
672; CHECK-NEXT:  entry:
673; CHECK-NEXT:    [[REM:%.*]] = srem i64 [[X:%.*]], 86400
674; CHECK-NEXT:    [[CMP:%.*]] = icmp sgt i64 [[REM]], -1
675; CHECK-NEXT:    [[COND:%.*]] = select i1 [[CMP]], i64 0, i64 86400
676; CHECK-NEXT:    [[ADD:%.*]] = add nsw i64 [[COND]], [[REM]]
677; CHECK-NEXT:    ret i1 false
678;
679entry:
680  %rem = srem i64 %x, 86400
681  %cmp = icmp sgt i64 %rem, -1
682  %cond = select i1 %cmp, i64 0, i64 86400
683  %add = add nsw i64 %cond, %rem
684  %cmp1 = icmp ugt i64 %add, 86399
685  ret i1 %cmp1
686}
687
688define i1 @test_icmp_mod_undef(i64 %x) {
689; CHECK-LABEL: @test_icmp_mod_undef(
690; CHECK-NEXT:  entry:
691; CHECK-NEXT:    [[REM:%.*]] = srem i64 [[X:%.*]], 86400
692; CHECK-NEXT:    [[CMP:%.*]] = icmp slt i64 [[REM]], 0
693; CHECK-NEXT:    [[COND:%.*]] = select i1 [[CMP]], i64 86400, i64 0
694; CHECK-NEXT:    [[ADD:%.*]] = add nsw i64 [[COND]], [[REM]]
695; CHECK-NEXT:    [[CMP1:%.*]] = icmp ugt i64 [[ADD]], 86399
696; CHECK-NEXT:    ret i1 [[CMP1]]
697;
698entry:
699  %rem = srem i64 %x, 86400
700  %cmp = icmp slt i64 %rem, 0
701  %cond = select i1 %cmp, i64 86400, i64 0
702  %add = add nsw i64 %cond, %rem
703  %cmp1 = icmp ugt i64 %add, 86399
704  ret i1 %cmp1
705}
706
707define i1 @test_icmp_mod_wrong_range(i64 noundef %x) {
708; CHECK-LABEL: @test_icmp_mod_wrong_range(
709; CHECK-NEXT:  entry:
710; CHECK-NEXT:    [[REM:%.*]] = srem i64 [[X:%.*]], 86400
711; CHECK-NEXT:    [[CMP:%.*]] = icmp slt i64 [[REM]], 0
712; CHECK-NEXT:    [[COND:%.*]] = select i1 [[CMP]], i64 86401, i64 0
713; CHECK-NEXT:    [[ADD:%.*]] = add nsw i64 [[COND]], [[REM]]
714; CHECK-NEXT:    [[CMP1:%.*]] = icmp samesign ugt i64 [[ADD]], 86399
715; CHECK-NEXT:    ret i1 [[CMP1]]
716;
717entry:
718  %rem = srem i64 %x, 86400
719  %cmp = icmp slt i64 %rem, 0
720  %cond = select i1 %cmp, i64 86401, i64 0
721  %add = add nsw i64 %cond, %rem
722  %cmp1 = icmp ugt i64 %add, 86399
723  ret i1 %cmp1
724}
725