1 ; RUN: opt -disable-output "-passes=print<scalar-evolution>" < %s 2>&1 | FileCheck %s
3 target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
4 target triple = "x86_64-unknown-linux-gnu"
6 define void @f_sadd_0(ptr %a) {
7 ; CHECK-LABEL: Classifying expressions for: @f_sadd_0
11 for.cond.cleanup: ; preds = %cont
14 for.body: ; preds = %entry, %cont
15 ; CHECK: %i.04 = phi i32 [ 0, %entry ], [ %tmp2, %cont ]
16 ; CHECK-NEXT: --> {0,+,1}<nuw><nsw><%for.body> U: [0,16) S: [0,16)
18 %i.04 = phi i32 [ 0, %entry ], [ %tmp2, %cont ]
19 %idxprom = sext i32 %i.04 to i64
20 %arrayidx = getelementptr inbounds i8, ptr %a, i64 %idxprom
21 store i8 0, ptr %arrayidx, align 1
22 %tmp0 = tail call { i32, i1 } @llvm.sadd.with.overflow.i32(i32 %i.04, i32 1)
23 %tmp1 = extractvalue { i32, i1 } %tmp0, 1
24 br i1 %tmp1, label %trap, label %cont, !nosanitize !{}
26 trap: ; preds = %for.body
27 tail call void @llvm.trap() #2, !nosanitize !{}
28 unreachable, !nosanitize !{}
30 cont: ; preds = %for.body
31 %tmp2 = extractvalue { i32, i1 } %tmp0, 0
32 %cmp = icmp slt i32 %tmp2, 16
33 br i1 %cmp, label %for.body, label %for.cond.cleanup
34 ; CHECK: Loop %for.body: constant max backedge-taken count is 15
37 define void @f_sadd_1(ptr %a) {
38 ; CHECK-LABEL: Classifying expressions for: @f_sadd_1
42 for.cond.cleanup: ; preds = %cont
45 for.body: ; preds = %entry, %cont
46 ; CHECK: %i.04 = phi i32 [ 0, %entry ], [ %tmp2, %cont ]
47 ; CHECK-NEXT: --> {0,+,1}<nuw><nsw><%for.body> U: [0,16) S: [0,16)
49 ; SCEV can prove <nsw> for the above induction variable; but it does
50 ; not bother so before it sees the sext below since it is not a 100%
53 %i.04 = phi i32 [ 0, %entry ], [ %tmp2, %cont ]
54 %idxprom = sext i32 %i.04 to i64
55 %arrayidx = getelementptr inbounds i8, ptr %a, i64 %idxprom
56 store i8 0, ptr %arrayidx, align 1
57 %tmp0 = tail call { i32, i1 } @llvm.sadd.with.overflow.i32(i32 %i.04, i32 1)
58 %tmp1 = extractvalue { i32, i1 } %tmp0, 1
59 br i1 %tmp1, label %trap, label %cont, !nosanitize !{}
61 trap: ; preds = %for.body
65 cont: ; preds = %for.body
66 %tmp2 = extractvalue { i32, i1 } %tmp0, 0
67 %cmp = icmp slt i32 %tmp2, 16
68 br i1 %cmp, label %for.body, label %for.cond.cleanup
69 ; CHECK: Loop %for.body: constant max backedge-taken count is 15
72 define void @f_sadd_2(ptr %a, ptr %c) {
73 ; CHECK-LABEL: Classifying expressions for: @f_sadd_2
77 for.cond.cleanup: ; preds = %cont
80 for.body: ; preds = %entry, %cont
81 ; CHECK: %i.04 = phi i32 [ 0, %entry ], [ %tmp2, %cont ]
82 ; CHECK-NEXT: --> {0,+,1}<%for.body>
84 %i.04 = phi i32 [ 0, %entry ], [ %tmp2, %cont ]
85 %idxprom = sext i32 %i.04 to i64
86 %arrayidx = getelementptr inbounds i8, ptr %a, i64 %idxprom
87 store i8 0, ptr %arrayidx, align 1
88 %tmp0 = tail call { i32, i1 } @llvm.sadd.with.overflow.i32(i32 %i.04, i32 1)
89 %tmp1 = extractvalue { i32, i1 } %tmp0, 1
90 br i1 %tmp1, label %trap, label %cont, !nosanitize !{}
92 trap: ; preds = %for.body
96 cont: ; preds = %for.body
97 %tmp2 = extractvalue { i32, i1 } %tmp0, 0
98 %cond = load volatile i1, ptr %c
99 br i1 %cond, label %for.body, label %for.cond.cleanup
102 define void @f_sadd_3(ptr %a, ptr %c) {
103 ; CHECK-LABEL: Classifying expressions for: @f_sadd_3
107 for.cond.cleanup: ; preds = %cont
110 for.body: ; preds = %entry, %cont
111 ; CHECK: %i.04 = phi i32 [ 0, %entry ], [ %tmp2, %for.body ]
112 ; CHECK-NEXT: --> {0,+,1}<nuw><nsw><%for.body>
114 %i.04 = phi i32 [ 0, %entry ], [ %tmp2, %for.body ]
115 %idxprom = sext i32 %i.04 to i64
116 %arrayidx = getelementptr inbounds i8, ptr %a, i64 %idxprom
117 store i8 0, ptr %arrayidx, align 1
118 %tmp0 = tail call { i32, i1 } @llvm.sadd.with.overflow.i32(i32 %i.04, i32 1)
119 %tmp1 = extractvalue { i32, i1 } %tmp0, 1
120 %tmp2 = extractvalue { i32, i1 } %tmp0, 0
121 br i1 %tmp1, label %trap, label %for.body, !nosanitize !{}
123 trap: ; preds = %for.body
124 tail call void @llvm.trap() #2, !nosanitize !{}
125 unreachable, !nosanitize !{}
128 define void @f_sadd_4(ptr %a, ptr %c) {
129 ; CHECK-LABEL: Classifying expressions for: @f_sadd_4
133 for.cond.cleanup: ; preds = %cont
136 for.body: ; preds = %entry, %cont
137 ; CHECK: %i.04 = phi i32 [ 0, %entry ], [ %tmp2, %merge ]
138 ; CHECK-NEXT: --> {0,+,1}<nuw><nsw><%for.body>
140 %i.04 = phi i32 [ 0, %entry ], [ %tmp2, %merge ]
141 %idxprom = sext i32 %i.04 to i64
142 %arrayidx = getelementptr inbounds i8, ptr %a, i64 %idxprom
143 store i8 0, ptr %arrayidx, align 1
144 %tmp0 = tail call { i32, i1 } @llvm.sadd.with.overflow.i32(i32 %i.04, i32 1)
145 %tmp1 = extractvalue { i32, i1 } %tmp0, 1
146 %tmp2 = extractvalue { i32, i1 } %tmp0, 0
147 br i1 %tmp1, label %notrap, label %merge
153 %tmp3 = extractvalue { i32, i1 } %tmp0, 1
154 br i1 %tmp3, label %trap, label %for.body, !nosanitize !{}
156 trap: ; preds = %for.body
157 tail call void @llvm.trap() #2, !nosanitize !{}
158 unreachable, !nosanitize !{}
161 define void @f_sadd_may_overflow(ptr %a, ptr %c) {
162 ; CHECK-LABEL: Classifying expressions for: @f_sadd_may_overflow
166 for.cond.cleanup: ; preds = %cont
169 for.body: ; preds = %entry, %cont
170 ; CHECK: %i.04 = phi i32 [ 0, %entry ], [ %tmp1, %cont ]
171 ; CHECK-NEXT: --> {0,+,1}<%for.body> U: full-set S: full-set
173 %i.04 = phi i32 [ 0, %entry ], [ %tmp1, %cont ]
174 %idxprom = sext i32 %i.04 to i64
175 %arrayidx = getelementptr inbounds i8, ptr %a, i64 %idxprom
176 store i8 0, ptr %arrayidx, align 1
177 %tmp0 = tail call { i32, i1 } @llvm.sadd.with.overflow.i32(i32 %i.04, i32 1)
178 %cond1 = load volatile i1, ptr %c
179 br i1 %cond1, label %trap, label %cont, !nosanitize !{}
181 trap: ; preds = %for.body
182 tail call void @llvm.trap() #2, !nosanitize !{}
183 unreachable, !nosanitize !{}
185 cont: ; preds = %for.body
186 %tmp1 = extractvalue { i32, i1 } %tmp0, 0
187 %cond = load volatile i1, ptr %c
188 br i1 %cond, label %for.body, label %for.cond.cleanup
191 define void @f_uadd(ptr %a) {
192 ; CHECK-LABEL: Classifying expressions for: @f_uadd
196 for.cond.cleanup: ; preds = %cont
199 for.body: ; preds = %entry, %cont
200 ; CHECK: %i.04 = phi i32 [ 0, %entry ], [ %tmp2, %cont ]
201 ; CHECK-NEXT: --> {0,+,1}<nuw><nsw><%for.body> U: [0,16) S: [0,16)
203 %i.04 = phi i32 [ 0, %entry ], [ %tmp2, %cont ]
204 %idxprom = sext i32 %i.04 to i64
205 %arrayidx = getelementptr inbounds i8, ptr %a, i64 %idxprom
206 store i8 0, ptr %arrayidx, align 1
207 %tmp0 = tail call { i32, i1 } @llvm.uadd.with.overflow.i32(i32 %i.04, i32 1)
208 %tmp1 = extractvalue { i32, i1 } %tmp0, 1
209 br i1 %tmp1, label %trap, label %cont, !nosanitize !{}
211 trap: ; preds = %for.body
212 tail call void @llvm.trap(), !nosanitize !{}
213 unreachable, !nosanitize !{}
215 cont: ; preds = %for.body
216 %tmp2 = extractvalue { i32, i1 } %tmp0, 0
217 %cmp = icmp slt i32 %tmp2, 16
218 br i1 %cmp, label %for.body, label %for.cond.cleanup
219 ; CHECK: Loop %for.body: constant max backedge-taken count is 15
222 define void @f_ssub(ptr nocapture %a) {
223 ; CHECK-LABEL: Classifying expressions for: @f_ssub
227 for.cond.cleanup: ; preds = %cont
230 for.body: ; preds = %entry, %cont
231 ; CHECK: %i.04 = phi i32 [ 15, %entry ], [ %tmp2, %cont ]
232 ; CHECK-NEXT: --> {15,+,-1}<nsw><%for.body> U: [0,16) S: [0,16)
234 %i.04 = phi i32 [ 15, %entry ], [ %tmp2, %cont ]
235 %idxprom = sext i32 %i.04 to i64
236 %arrayidx = getelementptr inbounds i8, ptr %a, i64 %idxprom
237 store i8 0, ptr %arrayidx, align 1
238 %tmp0 = tail call { i32, i1 } @llvm.ssub.with.overflow.i32(i32 %i.04, i32 1)
239 %tmp1 = extractvalue { i32, i1 } %tmp0, 1
240 br i1 %tmp1, label %trap, label %cont, !nosanitize !{}
242 trap: ; preds = %for.body
243 tail call void @llvm.trap(), !nosanitize !{}
244 unreachable, !nosanitize !{}
246 cont: ; preds = %for.body
247 %tmp2 = extractvalue { i32, i1 } %tmp0, 0
248 %cmp = icmp sgt i32 %tmp2, -1
249 br i1 %cmp, label %for.body, label %for.cond.cleanup
250 ; CHECK: Loop %for.body: constant max backedge-taken count is 15
253 define void @f_usub(ptr nocapture %a) {
254 ; CHECK-LABEL: Classifying expressions for: @f_usub
258 for.cond.cleanup: ; preds = %cont
261 for.body: ; preds = %entry, %cont
262 ; CHECK: %i.04 = phi i32 [ 15, %entry ], [ %tmp2, %cont ]
263 ; CHECK-NEXT: --> {15,+,-1}<nsw><%for.body> U: [0,16) S: [0,16)
265 %i.04 = phi i32 [ 15, %entry ], [ %tmp2, %cont ]
266 %idxprom = sext i32 %i.04 to i64
267 %arrayidx = getelementptr inbounds i8, ptr %a, i64 %idxprom
268 store i8 0, ptr %arrayidx, align 1
269 %tmp0 = tail call { i32, i1 } @llvm.usub.with.overflow.i32(i32 %i.04, i32 1)
270 %tmp1 = extractvalue { i32, i1 } %tmp0, 1
271 br i1 %tmp1, label %trap, label %cont, !nosanitize !{}
273 trap: ; preds = %for.body
274 tail call void @llvm.trap(), !nosanitize !{}
275 unreachable, !nosanitize !{}
277 cont: ; preds = %for.body
278 %tmp2 = extractvalue { i32, i1 } %tmp0, 0
279 %cmp = icmp sgt i32 %tmp2, -1
280 br i1 %cmp, label %for.body, label %for.cond.cleanup
281 ; CHECK: Loop %for.body: constant max backedge-taken count is 15
284 define i32 @f_smul(i32 %val_a, i32 %val_b) {
285 ; CHECK-LABEL: Classifying expressions for: @f_smul
286 %agg = tail call { i32, i1 } @llvm.smul.with.overflow.i32(i32 %val_a, i32 %val_b)
287 ; CHECK: %mul = extractvalue { i32, i1 } %agg, 0
288 ; CHECK-NEXT: --> (%val_a * %val_b) U: full-set S: full-set
289 %mul = extractvalue { i32, i1 } %agg, 0
293 define i32 @f_umul(i32 %val_a, i32 %val_b) {
294 ; CHECK-LABEL: Classifying expressions for: @f_umul
295 %agg = tail call { i32, i1 } @llvm.umul.with.overflow.i32(i32 %val_a, i32 %val_b)
296 ; CHECK: %mul = extractvalue { i32, i1 } %agg, 0
297 ; CHECK-NEXT: --> (%val_a * %val_b) U: full-set S: full-set
298 %mul = extractvalue { i32, i1 } %agg, 0
302 declare { i32, i1 } @llvm.sadd.with.overflow.i32(i32, i32) nounwind readnone
303 declare { i32, i1 } @llvm.uadd.with.overflow.i32(i32, i32) nounwind readnone
304 declare { i32, i1 } @llvm.ssub.with.overflow.i32(i32, i32) nounwind readnone
305 declare { i32, i1 } @llvm.usub.with.overflow.i32(i32, i32) nounwind readnone
306 declare { i32, i1 } @llvm.smul.with.overflow.i32(i32, i32) nounwind readnone
307 declare { i32, i1 } @llvm.umul.with.overflow.i32(i32, i32) nounwind readnone
309 declare void @llvm.trap() #2