Skip to content

Commit 1c11f72

Browse files
authored
[NFC] [IndVarSimplify] add overflowing tests (#159877)
Also use UTC for test instead.
1 parent 739425b commit 1c11f72

File tree

1 file changed

+244
-24
lines changed

1 file changed

+244
-24
lines changed

llvm/test/Transforms/IndVarSimplify/X86/overflow-intrinsics.ll

Lines changed: 244 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,29 @@
1+
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 6
12
; RUN: opt -S -passes=indvars < %s | FileCheck %s
23

34
target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
45
target triple = "x86_64-unknown-linux-gnu"
56

67
define void @f_sadd(ptr %a) {
7-
; CHECK-LABEL: @f_sadd(
8+
; CHECK-LABEL: define void @f_sadd(
9+
; CHECK-SAME: ptr [[A:%.*]]) {
10+
; CHECK-NEXT: [[ENTRY:.*]]:
11+
; CHECK-NEXT: br label %[[FOR_BODY:.*]]
12+
; CHECK: [[FOR_COND_CLEANUP:.*]]:
13+
; CHECK-NEXT: ret void
14+
; CHECK: [[FOR_BODY]]:
15+
; CHECK-NEXT: [[INDVARS_IV:%.*]] = phi i64 [ [[INDVARS_IV_NEXT:%.*]], %[[CONT:.*]] ], [ 0, %[[ENTRY]] ]
16+
; CHECK-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds i8, ptr [[A]], i64 [[INDVARS_IV]]
17+
; CHECK-NEXT: store i8 0, ptr [[ARRAYIDX]], align 1
18+
; CHECK-NEXT: [[INDVARS_IV_NEXT]] = add nuw nsw i64 [[INDVARS_IV]], 1
19+
; CHECK-NEXT: br i1 false, label %[[TRAP:.*]], label %[[CONT]], !nosanitize [[META0:![0-9]+]]
20+
; CHECK: [[TRAP]]:
21+
; CHECK-NEXT: tail call void @llvm.trap(), !nosanitize [[META0]]
22+
; CHECK-NEXT: unreachable, !nosanitize [[META0]]
23+
; CHECK: [[CONT]]:
24+
; CHECK-NEXT: [[EXITCOND:%.*]] = icmp ne i64 [[INDVARS_IV_NEXT]], 16
25+
; CHECK-NEXT: br i1 [[EXITCOND]], label %[[FOR_BODY]], label %[[FOR_COND_CLEANUP]]
26+
;
827
entry:
928
br label %for.body
1029

@@ -18,9 +37,6 @@ for.body: ; preds = %entry, %cont
1837
store i8 0, ptr %arrayidx, align 1
1938
%0 = tail call { i32, i1 } @llvm.sadd.with.overflow.i32(i32 %i.04, i32 1)
2039
%1 = extractvalue { i32, i1 } %0, 1
21-
; CHECK: for.body:
22-
; CHECK-NOT: @llvm.sadd.with.overflow
23-
; CHECK: br i1 false, label %trap, label %cont, !nosanitize !0
2440
br i1 %1, label %trap, label %cont, !nosanitize !{}
2541

2642
trap: ; preds = %for.body
@@ -33,8 +49,71 @@ cont: ; preds = %for.body
3349
br i1 %cmp, label %for.body, label %for.cond.cleanup
3450
}
3551

52+
define void @f_sadd_overflow(ptr %a) {
53+
; CHECK-LABEL: define void @f_sadd_overflow(
54+
; CHECK-SAME: ptr [[A:%.*]]) {
55+
; CHECK-NEXT: [[ENTRY:.*]]:
56+
; CHECK-NEXT: br label %[[FOR_BODY:.*]]
57+
; CHECK: [[FOR_COND_CLEANUP:.*]]:
58+
; CHECK-NEXT: ret void
59+
; CHECK: [[FOR_BODY]]:
60+
; CHECK-NEXT: [[INDVARS_IV:%.*]] = phi i64 [ [[INDVARS_IV_NEXT:%.*]], %[[CONT:.*]] ], [ 2147483645, %[[ENTRY]] ]
61+
; CHECK-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds i8, ptr [[A]], i64 [[INDVARS_IV]]
62+
; CHECK-NEXT: store i8 0, ptr [[ARRAYIDX]], align 1
63+
; CHECK-NEXT: [[EXITCOND:%.*]] = icmp eq i64 [[INDVARS_IV]], 2147483647
64+
; CHECK-NEXT: br i1 [[EXITCOND]], label %[[TRAP:.*]], label %[[CONT]], !nosanitize [[META0]]
65+
; CHECK: [[TRAP]]:
66+
; CHECK-NEXT: tail call void @llvm.trap(), !nosanitize [[META0]]
67+
; CHECK-NEXT: unreachable, !nosanitize [[META0]]
68+
; CHECK: [[CONT]]:
69+
; CHECK-NEXT: [[INDVARS_IV_NEXT]] = add nuw nsw i64 [[INDVARS_IV]], 1
70+
; CHECK-NEXT: br i1 true, label %[[FOR_BODY]], label %[[FOR_COND_CLEANUP]]
71+
;
72+
entry:
73+
br label %for.body
74+
75+
for.cond.cleanup: ; preds = %cont
76+
ret void
77+
78+
for.body: ; preds = %entry, %cont
79+
%i.04 = phi i32 [ 2147483645, %entry ], [ %2, %cont ]
80+
%idxprom = sext i32 %i.04 to i64
81+
%arrayidx = getelementptr inbounds i8, ptr %a, i64 %idxprom
82+
store i8 0, ptr %arrayidx, align 1
83+
%0 = tail call { i32, i1 } @llvm.sadd.with.overflow.i32(i32 %i.04, i32 1)
84+
%1 = extractvalue { i32, i1 } %0, 1
85+
br i1 %1, label %trap, label %cont, !nosanitize !{}
86+
87+
trap: ; preds = %for.body
88+
tail call void @llvm.trap() #2, !nosanitize !{}
89+
unreachable, !nosanitize !{}
90+
91+
cont: ; preds = %for.body
92+
%2 = extractvalue { i32, i1 } %0, 0
93+
%cmp = icmp sle i32 %2, 2147483647
94+
br i1 %cmp, label %for.body, label %for.cond.cleanup
95+
}
96+
3697
define void @f_uadd(ptr %a) {
37-
; CHECK-LABEL: @f_uadd(
98+
; CHECK-LABEL: define void @f_uadd(
99+
; CHECK-SAME: ptr [[A:%.*]]) {
100+
; CHECK-NEXT: [[ENTRY:.*]]:
101+
; CHECK-NEXT: br label %[[FOR_BODY:.*]]
102+
; CHECK: [[FOR_COND_CLEANUP:.*]]:
103+
; CHECK-NEXT: ret void
104+
; CHECK: [[FOR_BODY]]:
105+
; CHECK-NEXT: [[INDVARS_IV:%.*]] = phi i64 [ [[INDVARS_IV_NEXT:%.*]], %[[CONT:.*]] ], [ 0, %[[ENTRY]] ]
106+
; CHECK-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds i8, ptr [[A]], i64 [[INDVARS_IV]]
107+
; CHECK-NEXT: store i8 0, ptr [[ARRAYIDX]], align 1
108+
; CHECK-NEXT: [[INDVARS_IV_NEXT]] = add nuw nsw i64 [[INDVARS_IV]], 1
109+
; CHECK-NEXT: br i1 false, label %[[TRAP:.*]], label %[[CONT]], !nosanitize [[META0]]
110+
; CHECK: [[TRAP]]:
111+
; CHECK-NEXT: tail call void @llvm.trap(), !nosanitize [[META0]]
112+
; CHECK-NEXT: unreachable, !nosanitize [[META0]]
113+
; CHECK: [[CONT]]:
114+
; CHECK-NEXT: [[EXITCOND:%.*]] = icmp ne i64 [[INDVARS_IV_NEXT]], 16
115+
; CHECK-NEXT: br i1 [[EXITCOND]], label %[[FOR_BODY]], label %[[FOR_COND_CLEANUP]]
116+
;
38117
entry:
39118
br label %for.body
40119

@@ -48,9 +127,6 @@ for.body: ; preds = %entry, %cont
48127
store i8 0, ptr %arrayidx, align 1
49128
%0 = tail call { i32, i1 } @llvm.uadd.with.overflow.i32(i32 %i.04, i32 1)
50129
%1 = extractvalue { i32, i1 } %0, 1
51-
; CHECK: for.body:
52-
; CHECK-NOT: @llvm.uadd.with.overflow
53-
; CHECK: br i1 false, label %trap, label %cont, !nosanitize !0
54130
br i1 %1, label %trap, label %cont, !nosanitize !{}
55131

56132
trap: ; preds = %for.body
@@ -63,8 +139,71 @@ cont: ; preds = %for.body
63139
br i1 %cmp, label %for.body, label %for.cond.cleanup
64140
}
65141

142+
define void @f_uadd_overflow(ptr %a) {
143+
; CHECK-LABEL: define void @f_uadd_overflow(
144+
; CHECK-SAME: ptr [[A:%.*]]) {
145+
; CHECK-NEXT: [[ENTRY:.*]]:
146+
; CHECK-NEXT: br label %[[FOR_BODY:.*]]
147+
; CHECK: [[FOR_COND_CLEANUP:.*]]:
148+
; CHECK-NEXT: ret void
149+
; CHECK: [[FOR_BODY]]:
150+
; CHECK-NEXT: [[INDVARS_IV:%.*]] = phi i64 [ [[INDVARS_IV_NEXT:%.*]], %[[CONT:.*]] ], [ -6, %[[ENTRY]] ]
151+
; CHECK-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds i8, ptr [[A]], i64 [[INDVARS_IV]]
152+
; CHECK-NEXT: store i8 0, ptr [[ARRAYIDX]], align 1
153+
; CHECK-NEXT: [[EXITCOND:%.*]] = icmp eq i64 [[INDVARS_IV]], -1
154+
; CHECK-NEXT: br i1 [[EXITCOND]], label %[[TRAP:.*]], label %[[CONT]], !nosanitize [[META0]]
155+
; CHECK: [[TRAP]]:
156+
; CHECK-NEXT: tail call void @llvm.trap(), !nosanitize [[META0]]
157+
; CHECK-NEXT: unreachable, !nosanitize [[META0]]
158+
; CHECK: [[CONT]]:
159+
; CHECK-NEXT: [[INDVARS_IV_NEXT]] = add nsw i64 [[INDVARS_IV]], 1
160+
; CHECK-NEXT: br i1 true, label %[[FOR_BODY]], label %[[FOR_COND_CLEANUP]]
161+
;
162+
entry:
163+
br label %for.body
164+
165+
for.cond.cleanup: ; preds = %cont
166+
ret void
167+
168+
for.body: ; preds = %entry, %cont
169+
%i.04 = phi i32 [ 4294967290, %entry ], [ %2, %cont ]
170+
%idxprom = sext i32 %i.04 to i64
171+
%arrayidx = getelementptr inbounds i8, ptr %a, i64 %idxprom
172+
store i8 0, ptr %arrayidx, align 1
173+
%0 = tail call { i32, i1 } @llvm.uadd.with.overflow.i32(i32 %i.04, i32 1)
174+
%1 = extractvalue { i32, i1 } %0, 1
175+
br i1 %1, label %trap, label %cont, !nosanitize !{}
176+
177+
trap: ; preds = %for.body
178+
tail call void @llvm.trap(), !nosanitize !{}
179+
unreachable, !nosanitize !{}
180+
181+
cont: ; preds = %for.body
182+
%2 = extractvalue { i32, i1 } %0, 0
183+
%cmp = icmp ule i32 %2, 4294967295
184+
br i1 %cmp, label %for.body, label %for.cond.cleanup
185+
}
186+
66187
define void @f_ssub(ptr nocapture %a) {
67-
; CHECK-LABEL: @f_ssub(
188+
; CHECK-LABEL: define void @f_ssub(
189+
; CHECK-SAME: ptr captures(none) [[A:%.*]]) {
190+
; CHECK-NEXT: [[ENTRY:.*]]:
191+
; CHECK-NEXT: br label %[[FOR_BODY:.*]]
192+
; CHECK: [[FOR_COND_CLEANUP:.*]]:
193+
; CHECK-NEXT: ret void
194+
; CHECK: [[FOR_BODY]]:
195+
; CHECK-NEXT: [[INDVARS_IV:%.*]] = phi i64 [ [[INDVARS_IV_NEXT:%.*]], %[[CONT:.*]] ], [ 15, %[[ENTRY]] ]
196+
; CHECK-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds i8, ptr [[A]], i64 [[INDVARS_IV]]
197+
; CHECK-NEXT: store i8 0, ptr [[ARRAYIDX]], align 1
198+
; CHECK-NEXT: [[INDVARS_IV_NEXT]] = add nsw i64 [[INDVARS_IV]], -1
199+
; CHECK-NEXT: br i1 false, label %[[TRAP:.*]], label %[[CONT]], !nosanitize [[META0]]
200+
; CHECK: [[TRAP]]:
201+
; CHECK-NEXT: tail call void @llvm.trap(), !nosanitize [[META0]]
202+
; CHECK-NEXT: unreachable, !nosanitize [[META0]]
203+
; CHECK: [[CONT]]:
204+
; CHECK-NEXT: [[CMP:%.*]] = icmp sgt i64 [[INDVARS_IV_NEXT]], -1
205+
; CHECK-NEXT: br i1 [[CMP]], label %[[FOR_BODY]], label %[[FOR_COND_CLEANUP]]
206+
;
68207
entry:
69208
br label %for.body
70209

@@ -78,9 +217,6 @@ for.body: ; preds = %entry, %cont
78217
store i8 0, ptr %arrayidx, align 1
79218
%0 = tail call { i32, i1 } @llvm.ssub.with.overflow.i32(i32 %i.04, i32 1)
80219
%1 = extractvalue { i32, i1 } %0, 1
81-
; CHECK: for.body:
82-
; CHECK-NOT: @llvm.ssub.with.overflow.i32
83-
; CHECK: br i1 false, label %trap, label %cont, !nosanitize !0
84220
br i1 %1, label %trap, label %cont, !nosanitize !{}
85221

86222
trap: ; preds = %for.body
@@ -93,8 +229,76 @@ cont: ; preds = %for.body
93229
br i1 %cmp, label %for.body, label %for.cond.cleanup
94230
}
95231

232+
; It is theoretically possible to replace the `ssub.with.overflow` with a
233+
; condition on the IV, but SCEV cannot represent non-unsigned-wrapping
234+
; subtraction operations.
235+
define void @f_ssub_overflow(ptr nocapture %a) {
236+
; CHECK-LABEL: define void @f_ssub_overflow(
237+
; CHECK-SAME: ptr captures(none) [[A:%.*]]) {
238+
; CHECK-NEXT: [[ENTRY:.*]]:
239+
; CHECK-NEXT: br label %[[FOR_BODY:.*]]
240+
; CHECK: [[FOR_COND_CLEANUP:.*]]:
241+
; CHECK-NEXT: ret void
242+
; CHECK: [[FOR_BODY]]:
243+
; CHECK-NEXT: [[INDVARS_IV:%.*]] = phi i64 [ [[INDVARS_IV_NEXT:%.*]], %[[CONT:.*]] ], [ -2147483642, %[[ENTRY]] ]
244+
; CHECK-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds i8, ptr [[A]], i64 [[INDVARS_IV]]
245+
; CHECK-NEXT: store i8 0, ptr [[ARRAYIDX]], align 1
246+
; CHECK-NEXT: [[TMP0:%.*]] = trunc nsw i64 [[INDVARS_IV]] to i32
247+
; CHECK-NEXT: [[TMP1:%.*]] = tail call { i32, i1 } @llvm.ssub.with.overflow.i32(i32 [[TMP0]], i32 1)
248+
; CHECK-NEXT: [[TMP2:%.*]] = extractvalue { i32, i1 } [[TMP1]], 1
249+
; CHECK-NEXT: br i1 [[TMP2]], label %[[TRAP:.*]], label %[[CONT]], !nosanitize [[META0]]
250+
; CHECK: [[TRAP]]:
251+
; CHECK-NEXT: tail call void @llvm.trap(), !nosanitize [[META0]]
252+
; CHECK-NEXT: unreachable, !nosanitize [[META0]]
253+
; CHECK: [[CONT]]:
254+
; CHECK-NEXT: [[INDVARS_IV_NEXT]] = add nsw i64 [[INDVARS_IV]], -1
255+
; CHECK-NEXT: br i1 true, label %[[FOR_BODY]], label %[[FOR_COND_CLEANUP]]
256+
;
257+
entry:
258+
br label %for.body
259+
260+
for.cond.cleanup: ; preds = %cont
261+
ret void
262+
263+
for.body: ; preds = %entry, %cont
264+
%i.04 = phi i32 [ -2147483642, %entry ], [ %2, %cont ]
265+
%idxprom = sext i32 %i.04 to i64
266+
%arrayidx = getelementptr inbounds i8, ptr %a, i64 %idxprom
267+
store i8 0, ptr %arrayidx, align 1
268+
%0 = tail call { i32, i1 } @llvm.ssub.with.overflow.i32(i32 %i.04, i32 1)
269+
%1 = extractvalue { i32, i1 } %0, 1
270+
br i1 %1, label %trap, label %cont, !nosanitize !{}
271+
272+
trap: ; preds = %for.body
273+
tail call void @llvm.trap(), !nosanitize !{}
274+
unreachable, !nosanitize !{}
275+
276+
cont: ; preds = %for.body
277+
%2 = extractvalue { i32, i1 } %0, 0
278+
%cmp = icmp sge i32 %2, -2147483648
279+
br i1 %cmp, label %for.body, label %for.cond.cleanup
280+
}
281+
96282
define void @f_usub(ptr nocapture %a) {
97-
; CHECK-LABEL: @f_usub(
283+
; CHECK-LABEL: define void @f_usub(
284+
; CHECK-SAME: ptr captures(none) [[A:%.*]]) {
285+
; CHECK-NEXT: [[ENTRY:.*]]:
286+
; CHECK-NEXT: br label %[[FOR_BODY:.*]]
287+
; CHECK: [[FOR_COND_CLEANUP:.*]]:
288+
; CHECK-NEXT: ret void
289+
; CHECK: [[FOR_BODY]]:
290+
; CHECK-NEXT: [[INDVARS_IV:%.*]] = phi i64 [ [[INDVARS_IV_NEXT:%.*]], %[[CONT:.*]] ], [ 15, %[[ENTRY]] ]
291+
; CHECK-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds i8, ptr [[A]], i64 [[INDVARS_IV]]
292+
; CHECK-NEXT: store i8 0, ptr [[ARRAYIDX]], align 1
293+
; CHECK-NEXT: [[INDVARS_IV_NEXT]] = add nsw i64 [[INDVARS_IV]], -1
294+
; CHECK-NEXT: br i1 false, label %[[TRAP:.*]], label %[[CONT]], !nosanitize [[META0]]
295+
; CHECK: [[TRAP]]:
296+
; CHECK-NEXT: tail call void @llvm.trap(), !nosanitize [[META0]]
297+
; CHECK-NEXT: unreachable, !nosanitize [[META0]]
298+
; CHECK: [[CONT]]:
299+
; CHECK-NEXT: [[CMP:%.*]] = icmp samesign ugt i64 [[INDVARS_IV_NEXT]], 0
300+
; CHECK-NEXT: br i1 [[CMP]], label %[[FOR_BODY]], label %[[FOR_COND_CLEANUP]]
301+
;
98302
entry:
99303
br label %for.body
100304

@@ -109,9 +313,6 @@ for.body: ; preds = %entry, %cont
109313
%0 = tail call { i32, i1 } @llvm.usub.with.overflow.i32(i32 %i.04, i32 1)
110314
%1 = extractvalue { i32, i1 } %0, 1
111315

112-
; CHECK: for.body:
113-
; CHECK-NOT: @llvm.usub.with.overflow.i32
114-
; CHECK: br i1 false, label %trap, label %cont, !nosanitize !0
115316
br i1 %1, label %trap, label %cont, !nosanitize !{}
116317

117318
trap: ; preds = %for.body
@@ -124,8 +325,31 @@ cont: ; preds = %for.body
124325
br i1 %cmp, label %for.body, label %for.cond.cleanup
125326
}
126327

328+
; It is theoretically possible to replace the `usub.with.overflow` with a
329+
; condition on the IV, but SCEV cannot represent non-unsigned-wrapping
330+
; subtraction operations.
127331
define void @f_usub_overflow(ptr nocapture %a) {
128-
; CHECK-LABEL: @f_usub_overflow(
332+
; CHECK-LABEL: define void @f_usub_overflow(
333+
; CHECK-SAME: ptr captures(none) [[A:%.*]]) {
334+
; CHECK-NEXT: [[ENTRY:.*]]:
335+
; CHECK-NEXT: br label %[[FOR_BODY:.*]]
336+
; CHECK: [[FOR_COND_CLEANUP:.*]]:
337+
; CHECK-NEXT: ret void
338+
; CHECK: [[FOR_BODY]]:
339+
; CHECK-NEXT: [[INDVARS_IV:%.*]] = phi i64 [ [[INDVARS_IV_NEXT:%.*]], %[[CONT:.*]] ], [ 15, %[[ENTRY]] ]
340+
; CHECK-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds i8, ptr [[A]], i64 [[INDVARS_IV]]
341+
; CHECK-NEXT: store i8 0, ptr [[ARRAYIDX]], align 1
342+
; CHECK-NEXT: [[TMP0:%.*]] = trunc nuw nsw i64 [[INDVARS_IV]] to i32
343+
; CHECK-NEXT: [[TMP1:%.*]] = tail call { i32, i1 } @llvm.usub.with.overflow.i32(i32 [[TMP0]], i32 1)
344+
; CHECK-NEXT: [[TMP2:%.*]] = extractvalue { i32, i1 } [[TMP1]], 1
345+
; CHECK-NEXT: br i1 [[TMP2]], label %[[TRAP:.*]], label %[[CONT]], !nosanitize [[META0]]
346+
; CHECK: [[TRAP]]:
347+
; CHECK-NEXT: tail call void @llvm.trap(), !nosanitize [[META0]]
348+
; CHECK-NEXT: unreachable, !nosanitize [[META0]]
349+
; CHECK: [[CONT]]:
350+
; CHECK-NEXT: [[INDVARS_IV_NEXT]] = add nsw i64 [[INDVARS_IV]], -1
351+
; CHECK-NEXT: br i1 true, label %[[FOR_BODY]], label %[[FOR_COND_CLEANUP]]
352+
;
129353
entry:
130354
br label %for.body
131355

@@ -139,13 +363,6 @@ for.body: ; preds = %entry, %cont
139363
store i8 0, ptr %arrayidx, align 1
140364
%0 = tail call { i32, i1 } @llvm.usub.with.overflow.i32(i32 %i.04, i32 1)
141365
%1 = extractvalue { i32, i1 } %0, 1
142-
143-
; It is theoretically possible to prove this, but SCEV cannot
144-
; represent non-unsigned-wrapping subtraction operations.
145-
146-
; CHECK: for.body:
147-
; CHECK: [[COND:%[^ ]+]] = extractvalue { i32, i1 } %1, 1
148-
; CHECK-NEXT: br i1 [[COND]], label %trap, label %cont, !nosanitize !0
149366
br i1 %1, label %trap, label %cont, !nosanitize !{}
150367

151368
trap: ; preds = %for.body
@@ -166,3 +383,6 @@ declare { i32, i1 } @llvm.smul.with.overflow.i32(i32, i32) nounwind readnone
166383
declare { i32, i1 } @llvm.umul.with.overflow.i32(i32, i32) nounwind readnone
167384

168385
declare void @llvm.trap() #2
386+
;.
387+
; CHECK: [[META0]] = !{}
388+
;.

0 commit comments

Comments
 (0)