xref: /llvm-project/llvm/test/Transforms/ConstraintElimination/reason-about-add-operands.ll (revision fbcf8a8cbb2461730bfd0603b396842925a88ef2)
1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 3
2; RUN: opt -p constraint-elimination -S %s | FileCheck %s
3
4declare void @llvm.assume(i1)
5
6define i1 @addition_with_extra_facts_and_args_ult_i64(i64 noundef %a, i64 noundef %b, i64 noundef %c) {
7; CHECK-LABEL: define i1 @addition_with_extra_facts_and_args_ult_i64(
8; CHECK-SAME: i64 noundef [[A:%.*]], i64 noundef [[B:%.*]], i64 noundef [[C:%.*]]) {
9; CHECK-NEXT:  entry:
10; CHECK-NEXT:    [[CMP_A:%.*]] = icmp ule i64 [[A]], 2048
11; CHECK-NEXT:    call void @llvm.assume(i1 [[CMP_A]])
12; CHECK-NEXT:    [[CMP_B:%.*]] = icmp ule i64 [[B]], 1024
13; CHECK-NEXT:    call void @llvm.assume(i1 [[CMP_B]])
14; CHECK-NEXT:    [[ADD:%.*]] = add nuw nsw i64 [[B]], [[A]]
15; CHECK-NEXT:    [[CMP_ADD:%.*]] = icmp ult i64 [[ADD]], [[C]]
16; CHECK-NEXT:    call void @llvm.assume(i1 [[CMP_ADD]])
17; CHECK-NEXT:    ret i1 true
18;
19entry:
20  %cmp.a = icmp ule i64 %a, 2048
21  call void @llvm.assume(i1 %cmp.a)
22  %cmp.b = icmp ule i64 %b, 1024
23  call void @llvm.assume(i1 %cmp.b)
24  %add = add nuw nsw i64 %b, %a
25  %cmp.add = icmp ult i64 %add, %c
26  call void @llvm.assume(i1 %cmp.add)
27  %t = icmp ult i64 %a, %c
28  ret i1 %t
29}
30
31define i1 @addition_with_extra_facts_and_args_ult_1(i16 noundef %a, i16 noundef %b, i16 noundef %c) {
32; CHECK-LABEL: define i1 @addition_with_extra_facts_and_args_ult_1(
33; CHECK-SAME: i16 noundef [[A:%.*]], i16 noundef [[B:%.*]], i16 noundef [[C:%.*]]) {
34; CHECK-NEXT:  entry:
35; CHECK-NEXT:    [[CMP_A:%.*]] = icmp ule i16 [[A]], 2048
36; CHECK-NEXT:    call void @llvm.assume(i1 [[CMP_A]])
37; CHECK-NEXT:    [[CMP_B:%.*]] = icmp ule i16 [[B]], 1024
38; CHECK-NEXT:    call void @llvm.assume(i1 [[CMP_B]])
39; CHECK-NEXT:    [[ADD:%.*]] = add nuw nsw i16 [[B]], [[A]]
40; CHECK-NEXT:    [[CMP_ADD:%.*]] = icmp ult i16 [[ADD]], [[C]]
41; CHECK-NEXT:    call void @llvm.assume(i1 [[CMP_ADD]])
42; CHECK-NEXT:    ret i1 true
43;
44entry:
45  %cmp.a = icmp ule i16 %a, 2048
46  call void @llvm.assume(i1 %cmp.a)
47  %cmp.b = icmp ule i16 %b, 1024
48  call void @llvm.assume(i1 %cmp.b)
49  %add = add nuw nsw i16 %b, %a
50  %cmp.add = icmp ult i16 %add, %c
51  call void @llvm.assume(i1 %cmp.add)
52  %t = icmp ult i16 %a, %c
53  ret i1 %t
54}
55
56define i1 @addition_with_extra_facts_and_args_ult_2(i16 noundef %a, i16 noundef %b, i16 noundef %c) {
57; CHECK-LABEL: define i1 @addition_with_extra_facts_and_args_ult_2(
58; CHECK-SAME: i16 noundef [[A:%.*]], i16 noundef [[B:%.*]], i16 noundef [[C:%.*]]) {
59; CHECK-NEXT:  entry:
60; CHECK-NEXT:    [[CMP_A:%.*]] = icmp ule i16 [[A]], 2048
61; CHECK-NEXT:    call void @llvm.assume(i1 [[CMP_A]])
62; CHECK-NEXT:    [[CMP_B:%.*]] = icmp ule i16 [[B]], 1024
63; CHECK-NEXT:    call void @llvm.assume(i1 [[CMP_B]])
64; CHECK-NEXT:    [[ADD:%.*]] = add nuw nsw i16 [[B]], [[A]]
65; CHECK-NEXT:    [[CMP_ADD:%.*]] = icmp ult i16 [[ADD]], [[C]]
66; CHECK-NEXT:    call void @llvm.assume(i1 [[CMP_ADD]])
67; CHECK-NEXT:    ret i1 true
68;
69entry:
70  %cmp.a = icmp ule i16 %a, 2048
71  call void @llvm.assume(i1 %cmp.a)
72  %cmp.b = icmp ule i16 %b, 1024
73  call void @llvm.assume(i1 %cmp.b)
74  %add = add nuw nsw i16 %b, %a
75  %cmp.add = icmp ult i16 %add, %c
76  call void @llvm.assume(i1 %cmp.add)
77  %t = icmp ult i16 %b, %c
78  ret i1 %t
79}
80
81define i1 @addition_with_extra_facts_and_args_ult_3(i16 noundef %a, i16 noundef %b, i16 noundef %c) {
82; CHECK-LABEL: define i1 @addition_with_extra_facts_and_args_ult_3(
83; CHECK-SAME: i16 noundef [[A:%.*]], i16 noundef [[B:%.*]], i16 noundef [[C:%.*]]) {
84; CHECK-NEXT:  entry:
85; CHECK-NEXT:    [[CMP_A:%.*]] = icmp ule i16 [[A]], 2048
86; CHECK-NEXT:    call void @llvm.assume(i1 [[CMP_A]])
87; CHECK-NEXT:    [[CMP_B:%.*]] = icmp ule i16 [[B]], 1024
88; CHECK-NEXT:    call void @llvm.assume(i1 [[CMP_B]])
89; CHECK-NEXT:    [[ADD:%.*]] = add nuw nsw i16 [[B]], [[A]]
90; CHECK-NEXT:    [[CMP_ADD:%.*]] = icmp ult i16 [[ADD]], [[C]]
91; CHECK-NEXT:    call void @llvm.assume(i1 [[CMP_ADD]])
92; CHECK-NEXT:    ret i1 false
93;
94entry:
95  %cmp.a = icmp ule i16 %a, 2048
96  call void @llvm.assume(i1 %cmp.a)
97  %cmp.b = icmp ule i16 %b, 1024
98  call void @llvm.assume(i1 %cmp.b)
99  %add = add nuw nsw i16 %b, %a
100  %cmp.add = icmp ult i16 %add, %c
101  call void @llvm.assume(i1 %cmp.add)
102  %f = icmp uge i16 %a, %c
103  ret i1 %f
104}
105
106define i1 @addition_with_extra_facts_and_args_ult_4(i16 noundef %a, i16 noundef %b, i16 noundef %c) {
107; CHECK-LABEL: define i1 @addition_with_extra_facts_and_args_ult_4(
108; CHECK-SAME: i16 noundef [[A:%.*]], i16 noundef [[B:%.*]], i16 noundef [[C:%.*]]) {
109; CHECK-NEXT:  entry:
110; CHECK-NEXT:    [[CMP_A:%.*]] = icmp ule i16 [[A]], 2048
111; CHECK-NEXT:    call void @llvm.assume(i1 [[CMP_A]])
112; CHECK-NEXT:    [[CMP_B:%.*]] = icmp ule i16 [[B]], 1024
113; CHECK-NEXT:    call void @llvm.assume(i1 [[CMP_B]])
114; CHECK-NEXT:    [[ADD:%.*]] = add nuw nsw i16 [[B]], [[A]]
115; CHECK-NEXT:    [[CMP_ADD:%.*]] = icmp ult i16 [[ADD]], [[C]]
116; CHECK-NEXT:    call void @llvm.assume(i1 [[CMP_ADD]])
117; CHECK-NEXT:    ret i1 false
118;
119entry:
120  %cmp.a = icmp ule i16 %a, 2048
121  call void @llvm.assume(i1 %cmp.a)
122  %cmp.b = icmp ule i16 %b, 1024
123  call void @llvm.assume(i1 %cmp.b)
124  %add = add nuw nsw i16 %b, %a
125  %cmp.add = icmp ult i16 %add, %c
126  call void @llvm.assume(i1 %cmp.add)
127  %f = icmp uge i16 %b, %c
128  ret i1 %f
129}
130
131define i1 @addition_with_extra_facts_and_args_ult_5(i16 noundef %a, i16 noundef %b, i16 noundef %c) {
132; CHECK-LABEL: define i1 @addition_with_extra_facts_and_args_ult_5(
133; CHECK-SAME: i16 noundef [[A:%.*]], i16 noundef [[B:%.*]], i16 noundef [[C:%.*]]) {
134; CHECK-NEXT:  entry:
135; CHECK-NEXT:    [[CMP_A:%.*]] = icmp ule i16 [[A]], 2048
136; CHECK-NEXT:    call void @llvm.assume(i1 [[CMP_A]])
137; CHECK-NEXT:    [[CMP_B:%.*]] = icmp ule i16 [[B]], 1024
138; CHECK-NEXT:    call void @llvm.assume(i1 [[CMP_B]])
139; CHECK-NEXT:    [[ADD:%.*]] = add nuw nsw i16 [[B]], [[A]]
140; CHECK-NEXT:    [[CMP_ADD:%.*]] = icmp ult i16 [[ADD]], [[C]]
141; CHECK-NEXT:    call void @llvm.assume(i1 [[CMP_ADD]])
142; CHECK-NEXT:    [[CMP:%.*]] = icmp uge i16 [[A]], 10
143; CHECK-NEXT:    ret i1 [[CMP]]
144;
145entry:
146  %cmp.a = icmp ule i16 %a, 2048
147  call void @llvm.assume(i1 %cmp.a)
148  %cmp.b = icmp ule i16 %b, 1024
149  call void @llvm.assume(i1 %cmp.b)
150  %add = add nuw nsw i16 %b, %a
151  %cmp.add = icmp ult i16 %add, %c
152  call void @llvm.assume(i1 %cmp.add)
153  %cmp = icmp uge i16 %a, 10
154  ret i1 %cmp
155}
156
157define i1 @addition_with_extra_facts_and_args_ult_6(i16 noundef %a, i16 noundef %b, i16 noundef %c) {
158; CHECK-LABEL: define i1 @addition_with_extra_facts_and_args_ult_6(
159; CHECK-SAME: i16 noundef [[A:%.*]], i16 noundef [[B:%.*]], i16 noundef [[C:%.*]]) {
160; CHECK-NEXT:  entry:
161; CHECK-NEXT:    [[CMP_A:%.*]] = icmp ule i16 [[A]], 2048
162; CHECK-NEXT:    call void @llvm.assume(i1 [[CMP_A]])
163; CHECK-NEXT:    [[CMP_B:%.*]] = icmp ule i16 [[B]], 1024
164; CHECK-NEXT:    call void @llvm.assume(i1 [[CMP_B]])
165; CHECK-NEXT:    [[ADD:%.*]] = add nuw nsw i16 [[B]], [[A]]
166; CHECK-NEXT:    [[CMP_ADD:%.*]] = icmp ult i16 [[ADD]], [[C]]
167; CHECK-NEXT:    call void @llvm.assume(i1 [[CMP_ADD]])
168; CHECK-NEXT:    [[CMP:%.*]] = icmp ult i16 [[A]], [[B]]
169; CHECK-NEXT:    ret i1 [[CMP]]
170;
171entry:
172  %cmp.a = icmp ule i16 %a, 2048
173  call void @llvm.assume(i1 %cmp.a)
174  %cmp.b = icmp ule i16 %b, 1024
175  call void @llvm.assume(i1 %cmp.b)
176  %add = add nuw nsw i16 %b, %a
177  %cmp.add = icmp ult i16 %add, %c
178  call void @llvm.assume(i1 %cmp.add)
179  %cmp = icmp ult i16 %a, %b
180  ret i1 %cmp
181}
182
183
184declare i16 @get()
185
186define i1 @addition_with_extra_facts_and_return_value_ult_1() {
187; CHECK-LABEL: define i1 @addition_with_extra_facts_and_return_value_ult_1() {
188; CHECK-NEXT:  entry:
189; CHECK-NEXT:    [[A:%.*]] = call i16 @get()
190; CHECK-NEXT:    [[B:%.*]] = call i16 @get()
191; CHECK-NEXT:    [[C:%.*]] = call i16 @get()
192; CHECK-NEXT:    [[CMP_A:%.*]] = icmp ule i16 [[A]], 2048
193; CHECK-NEXT:    call void @llvm.assume(i1 [[CMP_A]])
194; CHECK-NEXT:    [[CMP_B:%.*]] = icmp ule i16 [[B]], 1024
195; CHECK-NEXT:    call void @llvm.assume(i1 [[CMP_B]])
196; CHECK-NEXT:    [[ADD:%.*]] = add nuw nsw i16 [[B]], [[A]]
197; CHECK-NEXT:    [[CMP_ADD:%.*]] = icmp ult i16 [[ADD]], [[C]]
198; CHECK-NEXT:    call void @llvm.assume(i1 [[CMP_ADD]])
199; CHECK-NEXT:    ret i1 true
200;
201entry:
202  %a = call i16 @get()
203  %b = call i16 @get()
204  %c = call i16 @get()
205  %cmp.a = icmp ule i16 %a, 2048
206  call void @llvm.assume(i1 %cmp.a)
207  %cmp.b = icmp ule i16 %b, 1024
208  call void @llvm.assume(i1 %cmp.b)
209  %add = add nuw nsw i16 %b, %a
210  %cmp.add = icmp ult i16 %add, %c
211  call void @llvm.assume(i1 %cmp.add)
212  %t = icmp ult i16 %a, %c
213  ret i1 %t
214}
215
216define i1 @addition_with_extra_facts_and_return_value_ult_2() {
217; CHECK-LABEL: define i1 @addition_with_extra_facts_and_return_value_ult_2() {
218; CHECK-NEXT:  entry:
219; CHECK-NEXT:    [[A:%.*]] = call i16 @get()
220; CHECK-NEXT:    [[B:%.*]] = call i16 @get()
221; CHECK-NEXT:    [[C:%.*]] = call i16 @get()
222; CHECK-NEXT:    [[CMP_A:%.*]] = icmp ule i16 [[A]], 2048
223; CHECK-NEXT:    call void @llvm.assume(i1 [[CMP_A]])
224; CHECK-NEXT:    [[CMP_B:%.*]] = icmp ule i16 [[B]], 1024
225; CHECK-NEXT:    call void @llvm.assume(i1 [[CMP_B]])
226; CHECK-NEXT:    [[ADD:%.*]] = add nuw nsw i16 [[B]], [[A]]
227; CHECK-NEXT:    [[CMP_ADD:%.*]] = icmp ult i16 [[ADD]], [[C]]
228; CHECK-NEXT:    call void @llvm.assume(i1 [[CMP_ADD]])
229; CHECK-NEXT:    ret i1 false
230;
231entry:
232  %a = call i16 @get()
233  %b = call i16 @get()
234  %c = call i16 @get()
235  %cmp.a = icmp ule i16 %a, 2048
236  call void @llvm.assume(i1 %cmp.a)
237  %cmp.b = icmp ule i16 %b, 1024
238  call void @llvm.assume(i1 %cmp.b)
239  %add = add nuw nsw i16 %b, %a
240  %cmp.add = icmp ult i16 %add, %c
241  call void @llvm.assume(i1 %cmp.add)
242  %f = icmp uge i16 %a, %c
243  ret i1 %f
244}
245
246define i1 @addition_no_extra_facts_with_return_value_ult_1() {
247; CHECK-LABEL: define i1 @addition_no_extra_facts_with_return_value_ult_1() {
248; CHECK-NEXT:  entry:
249; CHECK-NEXT:    [[A:%.*]] = call i16 @get()
250; CHECK-NEXT:    [[B:%.*]] = call i16 @get()
251; CHECK-NEXT:    [[C:%.*]] = call i16 @get()
252; CHECK-NEXT:    [[ADD:%.*]] = add nuw nsw i16 [[B]], [[A]]
253; CHECK-NEXT:    [[CMP_ADD:%.*]] = icmp ult i16 [[ADD]], [[C]]
254; CHECK-NEXT:    call void @llvm.assume(i1 [[CMP_ADD]])
255; CHECK-NEXT:    ret i1 true
256;
257entry:
258  %a = call i16 @get()
259  %b = call i16 @get()
260  %c = call i16 @get()
261  %add = add nuw nsw i16 %b, %a
262  %cmp.add = icmp ult i16 %add, %c
263  call void @llvm.assume(i1 %cmp.add)
264  %t = icmp ult i16 %a, %c
265  ret i1 %t
266}
267
268define i1 @addition_no_extra_facts_with_return_value_ult_2() {
269; CHECK-LABEL: define i1 @addition_no_extra_facts_with_return_value_ult_2() {
270; CHECK-NEXT:  entry:
271; CHECK-NEXT:    [[A:%.*]] = call i16 @get()
272; CHECK-NEXT:    [[B:%.*]] = call i16 @get()
273; CHECK-NEXT:    [[C:%.*]] = call i16 @get()
274; CHECK-NEXT:    [[ADD:%.*]] = add nuw nsw i16 [[B]], [[A]]
275; CHECK-NEXT:    [[CMP_ADD:%.*]] = icmp ult i16 [[ADD]], [[C]]
276; CHECK-NEXT:    call void @llvm.assume(i1 [[CMP_ADD]])
277; CHECK-NEXT:    ret i1 false
278;
279entry:
280  %a = call i16 @get()
281  %b = call i16 @get()
282  %c = call i16 @get()
283  %add = add nuw nsw i16 %b, %a
284  %cmp.add = icmp ult i16 %add, %c
285  call void @llvm.assume(i1 %cmp.add)
286  %f = icmp uge i16 %a, %c
287  ret i1 %f
288}
289
290define i1 @addition_no_extra_facts_with_return_value_ult_3() {
291; CHECK-LABEL: define i1 @addition_no_extra_facts_with_return_value_ult_3() {
292; CHECK-NEXT:  entry:
293; CHECK-NEXT:    [[A:%.*]] = call i16 @get()
294; CHECK-NEXT:    [[B:%.*]] = call i16 @get()
295; CHECK-NEXT:    [[C:%.*]] = call i16 @get()
296; CHECK-NEXT:    [[ADD:%.*]] = add nuw nsw i16 [[B]], [[A]]
297; CHECK-NEXT:    [[CMP_ADD:%.*]] = icmp ult i16 [[ADD]], [[C]]
298; CHECK-NEXT:    call void @llvm.assume(i1 [[CMP_ADD]])
299; CHECK-NEXT:    [[CMP:%.*]] = icmp uge i16 [[A]], 9
300; CHECK-NEXT:    ret i1 [[CMP]]
301;
302entry:
303  %a = call i16 @get()
304  %b = call i16 @get()
305  %c = call i16 @get()
306  %add = add nuw nsw i16 %b, %a
307  %cmp.add = icmp ult i16 %add, %c
308  call void @llvm.assume(i1 %cmp.add)
309  %cmp = icmp uge i16 %a, 9
310  ret i1 %cmp
311}
312
313; Test for https://github.com/llvm/llvm-project/issues/63490.
314define i1 @assume_x_ugt_y_plus_y_via_shl_eq(i8 %x, i8 %y) {
315; CHECK-LABEL: define i1 @assume_x_ugt_y_plus_y_via_shl_eq(
316; CHECK-SAME: i8 [[X:%.*]], i8 [[Y:%.*]]) {
317; CHECK-NEXT:    [[S:%.*]] = shl nuw i8 [[Y]], 1
318; CHECK-NEXT:    [[C_1:%.*]] = icmp ugt i8 [[X]], [[S]]
319; CHECK-NEXT:    tail call void @llvm.assume(i1 [[C_1]])
320; CHECK-NEXT:    ret i1 false
321;
322  %s = shl nuw i8 %y, 1
323  %c.1 = icmp ugt i8 %x, %s
324  tail call void @llvm.assume(i1 %c.1)
325  %c.2 = icmp eq i8 %x, %y
326  ret i1 %c.2
327}
328
329define i1 @assume_x_ugt_y_plus_y_via_shl_eq_no_nuw(i8 %x, i8 %y) {
330; CHECK-LABEL: define i1 @assume_x_ugt_y_plus_y_via_shl_eq_no_nuw(
331; CHECK-SAME: i8 [[X:%.*]], i8 [[Y:%.*]]) {
332; CHECK-NEXT:    [[S:%.*]] = shl i8 [[Y]], 1
333; CHECK-NEXT:    [[C_1:%.*]] = icmp ugt i8 [[X]], [[S]]
334; CHECK-NEXT:    tail call void @llvm.assume(i1 [[C_1]])
335; CHECK-NEXT:    [[C_2:%.*]] = icmp eq i8 [[X]], [[Y]]
336; CHECK-NEXT:    ret i1 [[C_2]]
337;
338  %s = shl i8 %y, 1
339  %c.1 = icmp ugt i8 %x, %s
340  tail call void @llvm.assume(i1 %c.1)
341  %c.2 = icmp eq i8 %x, %y
342  ret i1 %c.2
343}
344
345define i1 @assume_x_ugt_y_plus_y_via_add_eq(i8 %x, i8 %y) {
346; CHECK-LABEL: define i1 @assume_x_ugt_y_plus_y_via_add_eq(
347; CHECK-SAME: i8 [[X:%.*]], i8 [[Y:%.*]]) {
348; CHECK-NEXT:    [[S:%.*]] = add nuw i8 [[Y]], [[Y]]
349; CHECK-NEXT:    [[C_1:%.*]] = icmp ugt i8 [[X]], [[S]]
350; CHECK-NEXT:    tail call void @llvm.assume(i1 [[C_1]])
351; CHECK-NEXT:    ret i1 false
352;
353  %s = add nuw i8 %y, %y
354  %c.1 = icmp ugt i8 %x, %s
355  tail call void @llvm.assume(i1 %c.1)
356  %c.2 = icmp eq i8 %x, %y
357  ret i1 %c.2
358}
359
360define i1 @assume_x_ugt_y_plus_y_via_add_eq_no_nuw(i8 %x, i8 %y) {
361; CHECK-LABEL: define i1 @assume_x_ugt_y_plus_y_via_add_eq_no_nuw(
362; CHECK-SAME: i8 [[X:%.*]], i8 [[Y:%.*]]) {
363; CHECK-NEXT:    [[S:%.*]] = add i8 [[Y]], [[Y]]
364; CHECK-NEXT:    [[C_1:%.*]] = icmp ugt i8 [[X]], [[S]]
365; CHECK-NEXT:    tail call void @llvm.assume(i1 [[C_1]])
366; CHECK-NEXT:    [[C_2:%.*]] = icmp eq i8 [[X]], [[Y]]
367; CHECK-NEXT:    ret i1 [[C_2]]
368;
369  %s = add i8 %y, %y
370  %c.1 = icmp ugt i8 %x, %s
371  tail call void @llvm.assume(i1 %c.1)
372  %c.2 = icmp eq i8 %x, %y
373  ret i1 %c.2
374}
375
376define i1 @assume_x_ugt_y_plus_y_via_shl_ne(i8 %x, i8 %y) {
377; CHECK-LABEL: define i1 @assume_x_ugt_y_plus_y_via_shl_ne(
378; CHECK-SAME: i8 [[X:%.*]], i8 [[Y:%.*]]) {
379; CHECK-NEXT:    [[S:%.*]] = shl nuw i8 [[Y]], 1
380; CHECK-NEXT:    [[C_1:%.*]] = icmp ugt i8 [[X]], [[S]]
381; CHECK-NEXT:    tail call void @llvm.assume(i1 [[C_1]])
382; CHECK-NEXT:    ret i1 true
383;
384  %s = shl nuw i8 %y, 1
385  %c.1 = icmp ugt i8 %x, %s
386  tail call void @llvm.assume(i1 %c.1)
387  %c.2 = icmp ne i8 %x, %y
388  ret i1 %c.2
389}
390