xref: /llvm-project/llvm/test/Transforms/ConstraintElimination/monotonic-int-phis-decrement.ll (revision 56a3e49a00161f6ac71316e3c1f4d5069c916590)
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 @use(i1)
5declare void @llvm.assume(i1)
6
7define void @add_rec_decreasing_cond_true_constant(i8 noundef %len) {
8; CHECK-LABEL: define void @add_rec_decreasing_cond_true_constant(
9; CHECK-SAME: i8 noundef [[LEN:%.*]]) {
10; CHECK-NEXT:  entry:
11; CHECK-NEXT:    br label [[LOOP_HEADER:%.*]]
12; CHECK:       loop.header:
13; CHECK-NEXT:    [[K_0:%.*]] = phi i8 [ 4, [[ENTRY:%.*]] ], [ [[K_DEC:%.*]], [[LOOP_LATCH:%.*]] ]
14; CHECK-NEXT:    [[CMP2_NOT:%.*]] = icmp eq i8 [[K_0]], 0
15; CHECK-NEXT:    br i1 [[CMP2_NOT]], label [[EXIT:%.*]], label [[LOOP_LATCH]]
16; CHECK:       loop.latch:
17; CHECK-NEXT:    call void @use(i1 true)
18; CHECK-NEXT:    [[K_DEC]] = add i8 [[K_0]], -1
19; CHECK-NEXT:    br label [[LOOP_HEADER]]
20; CHECK:       exit:
21; CHECK-NEXT:    ret void
22;
23entry:
24  br label %loop.header
25
26loop.header:
27  %k.0 = phi i8 [ 4, %entry], [ %k.dec, %loop.latch ]
28  %cmp2.not = icmp eq i8 %k.0, 0
29  br i1 %cmp2.not, label %exit, label %loop.latch
30
31loop.latch:
32  %cmp.not.i = icmp ult i8 %k.0, 5
33  call void @use(i1 %cmp.not.i)
34  %k.dec = add i8 %k.0, -1
35  br label %loop.header
36
37exit:
38  ret void
39}
40
41define void @add_rec_decreasing_cond_not_true_constant(i8 noundef %len) {
42; CHECK-LABEL: define void @add_rec_decreasing_cond_not_true_constant(
43; CHECK-SAME: i8 noundef [[LEN:%.*]]) {
44; CHECK-NEXT:  entry:
45; CHECK-NEXT:    br label [[LOOP_HEADER:%.*]]
46; CHECK:       loop.header:
47; CHECK-NEXT:    [[K_0:%.*]] = phi i8 [ 4, [[ENTRY:%.*]] ], [ [[K_DEC:%.*]], [[LOOP_LATCH:%.*]] ]
48; CHECK-NEXT:    [[CMP2_NOT:%.*]] = icmp eq i8 [[K_0]], 0
49; CHECK-NEXT:    br i1 [[CMP2_NOT]], label [[EXIT:%.*]], label [[LOOP_LATCH]]
50; CHECK:       loop.latch:
51; CHECK-NEXT:    [[CMP_NOT_I:%.*]] = icmp ult i8 [[K_0]], 4
52; CHECK-NEXT:    call void @use(i1 [[CMP_NOT_I]])
53; CHECK-NEXT:    [[K_DEC]] = add i8 [[K_0]], -1
54; CHECK-NEXT:    br label [[LOOP_HEADER]]
55; CHECK:       exit:
56; CHECK-NEXT:    ret void
57;
58entry:
59  br label %loop.header
60
61loop.header:
62  %k.0 = phi i8 [ 4, %entry], [ %k.dec, %loop.latch ]
63  %cmp2.not = icmp eq i8 %k.0, 0
64  br i1 %cmp2.not, label %exit, label %loop.latch
65
66loop.latch:
67  %cmp.not.i = icmp ult i8 %k.0, 4
68  call void @use(i1 %cmp.not.i)
69  %k.dec = add i8 %k.0, -1
70  br label %loop.header
71
72exit:
73  ret void
74}
75
76define void @add_rec_decreasing_cond_true_start_signed_positive(i8 noundef %start) {
77; CHECK-LABEL: define void @add_rec_decreasing_cond_true_start_signed_positive(
78; CHECK-SAME: i8 noundef [[START:%.*]]) {
79; CHECK-NEXT:  entry:
80; CHECK-NEXT:    [[PRECOND:%.*]] = icmp sge i8 [[START]], 1
81; CHECK-NEXT:    call void @llvm.assume(i1 [[PRECOND]])
82; CHECK-NEXT:    [[START_1:%.*]] = add i8 [[START]], -1
83; CHECK-NEXT:    br label [[LOOP_HEADER:%.*]]
84; CHECK:       loop.header:
85; CHECK-NEXT:    [[K_0:%.*]] = phi i8 [ [[START_1]], [[ENTRY:%.*]] ], [ [[K_DEC:%.*]], [[LOOP_LATCH:%.*]] ]
86; CHECK-NEXT:    [[CMP2_NOT:%.*]] = icmp eq i8 [[K_0]], 0
87; CHECK-NEXT:    br i1 [[CMP2_NOT]], label [[EXIT:%.*]], label [[LOOP_LATCH]]
88; CHECK:       loop.latch:
89; CHECK-NEXT:    call void @use(i1 true)
90; CHECK-NEXT:    [[K_DEC]] = add i8 [[K_0]], -1
91; CHECK-NEXT:    br label [[LOOP_HEADER]]
92; CHECK:       exit:
93; CHECK-NEXT:    ret void
94;
95entry:
96  %precond = icmp sge i8 %start, 1
97  call void @llvm.assume(i1 %precond)
98  %start.1 = add i8 %start, -1
99  br label %loop.header
100
101loop.header:
102  %k.0 = phi i8 [ %start.1, %entry], [ %k.dec, %loop.latch ]
103  %cmp2.not = icmp eq i8 %k.0, 0
104  br i1 %cmp2.not, label %exit, label %loop.latch
105
106loop.latch:
107  %cmp.not.i = icmp ult i8 %k.0, %start
108  call void @use(i1 %cmp.not.i)
109  %k.dec = add i8 %k.0, -1
110  br label %loop.header
111
112exit:
113  ret void
114}
115
116define void @add_rec_decreasing_cond_not_true_start_signed_positive(i8 noundef %start) {
117; CHECK-LABEL: define void @add_rec_decreasing_cond_not_true_start_signed_positive(
118; CHECK-SAME: i8 noundef [[START:%.*]]) {
119; CHECK-NEXT:  entry:
120; CHECK-NEXT:    [[PRECOND:%.*]] = icmp sge i8 [[START]], 1
121; CHECK-NEXT:    call void @llvm.assume(i1 [[PRECOND]])
122; CHECK-NEXT:    br label [[LOOP_HEADER:%.*]]
123; CHECK:       loop.header:
124; CHECK-NEXT:    [[K_0:%.*]] = phi i8 [ [[START]], [[ENTRY:%.*]] ], [ [[K_DEC:%.*]], [[LOOP_LATCH:%.*]] ]
125; CHECK-NEXT:    [[CMP2_NOT:%.*]] = icmp eq i8 [[K_0]], 0
126; CHECK-NEXT:    br i1 [[CMP2_NOT]], label [[EXIT:%.*]], label [[LOOP_LATCH]]
127; CHECK:       loop.latch:
128; CHECK-NEXT:    [[CMP_NOT_I:%.*]] = icmp ult i8 [[K_0]], [[START]]
129; CHECK-NEXT:    call void @use(i1 [[CMP_NOT_I]])
130; CHECK-NEXT:    [[K_DEC]] = add i8 [[K_0]], -1
131; CHECK-NEXT:    br label [[LOOP_HEADER]]
132; CHECK:       exit:
133; CHECK-NEXT:    ret void
134;
135entry:
136  %precond = icmp sge i8 %start, 1
137  call void @llvm.assume(i1 %precond)
138  br label %loop.header
139
140loop.header:
141  %k.0 = phi i8 [ %start, %entry], [ %k.dec, %loop.latch ]
142  %cmp2.not = icmp eq i8 %k.0, 0
143  br i1 %cmp2.not, label %exit, label %loop.latch
144
145loop.latch:
146  %cmp.not.i = icmp ult i8 %k.0, %start
147  call void @use(i1 %cmp.not.i)
148  %k.dec = add i8 %k.0, -1
149  br label %loop.header
150
151exit:
152  ret void
153}
154
155define void @add_rec_decreasing_add_rec_positive_to_negative(i8 noundef %len) {
156; CHECK-LABEL: define void @add_rec_decreasing_add_rec_positive_to_negative(
157; CHECK-SAME: i8 noundef [[LEN:%.*]]) {
158; CHECK-NEXT:  entry:
159; CHECK-NEXT:    br label [[LOOP_HEADER:%.*]]
160; CHECK:       loop.header:
161; CHECK-NEXT:    [[K_0:%.*]] = phi i8 [ 4, [[ENTRY:%.*]] ], [ [[K_DEC:%.*]], [[LOOP_LATCH:%.*]] ]
162; CHECK-NEXT:    [[CMP2_NOT:%.*]] = icmp eq i8 [[K_0]], -2
163; CHECK-NEXT:    br i1 [[CMP2_NOT]], label [[EXIT:%.*]], label [[LOOP_LATCH]]
164; CHECK:       loop.latch:
165; CHECK-NEXT:    [[CMP_NOT_I:%.*]] = icmp ult i8 [[K_0]], 5
166; CHECK-NEXT:    call void @use(i1 [[CMP_NOT_I]])
167; CHECK-NEXT:    [[K_DEC]] = add i8 [[K_0]], -1
168; CHECK-NEXT:    br label [[LOOP_HEADER]]
169; CHECK:       exit:
170; CHECK-NEXT:    ret void
171;
172entry:
173  br label %loop.header
174
175loop.header:
176  %k.0 = phi i8 [ 4, %entry], [ %k.dec, %loop.latch ]
177  %cmp2.not = icmp eq i8 %k.0, -2
178  br i1 %cmp2.not, label %exit, label %loop.latch
179
180loop.latch:
181  %cmp.not.i = icmp ult i8 %k.0, 5
182  call void @use(i1 %cmp.not.i)
183  %k.dec = add i8 %k.0, -1
184  br label %loop.header
185
186exit:
187  ret void
188}
189
190define void @add_rec_decreasing_2_cond_true_constant(i8 noundef %len) {
191; CHECK-LABEL: define void @add_rec_decreasing_2_cond_true_constant(
192; CHECK-SAME: i8 noundef [[LEN:%.*]]) {
193; CHECK-NEXT:  entry:
194; CHECK-NEXT:    br label [[LOOP_HEADER:%.*]]
195; CHECK:       loop.header:
196; CHECK-NEXT:    [[K_0:%.*]] = phi i8 [ 4, [[ENTRY:%.*]] ], [ [[K_DEC:%.*]], [[LOOP_LATCH:%.*]] ]
197; CHECK-NEXT:    [[CMP2_NOT:%.*]] = icmp eq i8 [[K_0]], 0
198; CHECK-NEXT:    br i1 [[CMP2_NOT]], label [[EXIT:%.*]], label [[LOOP_LATCH]]
199; CHECK:       loop.latch:
200; CHECK-NEXT:    [[CMP_NOT_I:%.*]] = icmp ult i8 [[K_0]], 5
201; CHECK-NEXT:    call void @use(i1 [[CMP_NOT_I]])
202; CHECK-NEXT:    [[K_DEC]] = add i8 [[K_0]], -2
203; CHECK-NEXT:    br label [[LOOP_HEADER]]
204; CHECK:       exit:
205; CHECK-NEXT:    ret void
206;
207entry:
208  br label %loop.header
209
210loop.header:
211  %k.0 = phi i8 [ 4, %entry], [ %k.dec, %loop.latch ]
212  %cmp2.not = icmp eq i8 %k.0, 0
213  br i1 %cmp2.not, label %exit, label %loop.latch
214
215loop.latch:
216  %cmp.not.i = icmp ult i8 %k.0, 5
217  call void @use(i1 %cmp.not.i)
218  %k.dec = add i8 %k.0, -2
219  br label %loop.header
220
221exit:
222  ret void
223}
224
225define void @add_rec_decreasing_2_cond_not_true_constant(i8 noundef %len) {
226; CHECK-LABEL: define void @add_rec_decreasing_2_cond_not_true_constant(
227; CHECK-SAME: i8 noundef [[LEN:%.*]]) {
228; CHECK-NEXT:  entry:
229; CHECK-NEXT:    br label [[LOOP_HEADER:%.*]]
230; CHECK:       loop.header:
231; CHECK-NEXT:    [[K_0:%.*]] = phi i8 [ 5, [[ENTRY:%.*]] ], [ [[K_DEC:%.*]], [[LOOP_LATCH:%.*]] ]
232; CHECK-NEXT:    [[CMP2_NOT:%.*]] = icmp eq i8 [[K_0]], 0
233; CHECK-NEXT:    br i1 [[CMP2_NOT]], label [[EXIT:%.*]], label [[LOOP_LATCH]]
234; CHECK:       loop.latch:
235; CHECK-NEXT:    [[CMP_NOT_I:%.*]] = icmp ult i8 [[K_0]], 5
236; CHECK-NEXT:    call void @use(i1 [[CMP_NOT_I]])
237; CHECK-NEXT:    [[K_DEC]] = add i8 [[K_0]], -2
238; CHECK-NEXT:    br label [[LOOP_HEADER]]
239; CHECK:       exit:
240; CHECK-NEXT:    ret void
241;
242entry:
243  br label %loop.header
244
245loop.header:
246  %k.0 = phi i8 [ 5, %entry], [ %k.dec, %loop.latch ]
247  %cmp2.not = icmp eq i8 %k.0, 0
248  br i1 %cmp2.not, label %exit, label %loop.latch
249
250loop.latch:
251  %cmp.not.i = icmp ult i8 %k.0, 5
252  call void @use(i1 %cmp.not.i)
253  %k.dec = add i8 %k.0, -2
254  br label %loop.header
255
256exit:
257  ret void
258}
259