@@ -33,6 +33,35 @@ cont: ; preds = %for.body
3333 br i1 %cmp , label %for.body , label %for.cond.cleanup
3434}
3535
36+ define void @f_sadd_overflow (ptr %a ) {
37+ ; CHECK-LABEL: @f_sadd_overflow(
38+ entry:
39+ br label %for.body
40+
41+ for.cond.cleanup: ; preds = %cont
42+ ret void
43+
44+ for.body: ; preds = %entry, %cont
45+ %i.04 = phi i32 [ 2147483645 , %entry ], [ %2 , %cont ]
46+ %idxprom = sext i32 %i.04 to i64
47+ %arrayidx = getelementptr inbounds i8 , ptr %a , i64 %idxprom
48+ store i8 0 , ptr %arrayidx , align 1
49+ %0 = tail call { i32 , i1 } @llvm.sadd.with.overflow.i32 (i32 %i.04 , i32 1 )
50+ %1 = extractvalue { i32 , i1 } %0 , 1
51+ ; CHECK: cont:
52+ ; CHECK: br i1 true, label %for.body, label %for.cond.cleanup
53+ br i1 %1 , label %trap , label %cont , !nosanitize !{}
54+
55+ trap: ; preds = %for.body
56+ tail call void @llvm.trap () #2 , !nosanitize !{}
57+ unreachable , !nosanitize !{}
58+
59+ cont: ; preds = %for.body
60+ %2 = extractvalue { i32 , i1 } %0 , 0
61+ %cmp = icmp sle i32 %2 , 2147483647
62+ br i1 %cmp , label %for.body , label %for.cond.cleanup
63+ }
64+
3665define void @f_uadd (ptr %a ) {
3766; CHECK-LABEL: @f_uadd(
3867entry:
@@ -63,6 +92,36 @@ cont: ; preds = %for.body
6392 br i1 %cmp , label %for.body , label %for.cond.cleanup
6493}
6594
95+ define void @f_uadd_overflow (ptr %a ) {
96+ ; CHECK-LABEL: @f_uadd_overflow(
97+ entry:
98+ br label %for.body
99+
100+ for.cond.cleanup: ; preds = %cont
101+ ret void
102+
103+ for.body: ; preds = %entry, %cont
104+ %i.04 = phi i32 [ 4294967290 , %entry ], [ %2 , %cont ]
105+ %idxprom = sext i32 %i.04 to i64
106+ %arrayidx = getelementptr inbounds i8 , ptr %a , i64 %idxprom
107+ store i8 0 , ptr %arrayidx , align 1
108+ %0 = tail call { i32 , i1 } @llvm.uadd.with.overflow.i32 (i32 %i.04 , i32 1 )
109+ %1 = extractvalue { i32 , i1 } %0 , 1
110+ ; CHECK: cont:
111+ ; CHECK: br i1 true, label %for.body, label %for.cond.cleanup
112+ br i1 %1 , label %trap , label %cont , !nosanitize !{}
113+
114+ trap: ; preds = %for.body
115+ tail call void @llvm.trap (), !nosanitize !{}
116+ unreachable , !nosanitize !{}
117+
118+ cont: ; preds = %for.body
119+ %2 = extractvalue { i32 , i1 } %0 , 0
120+ %cmp = icmp ule i32 %2 , 4294967295
121+ br i1 %cmp , label %for.body , label %for.cond.cleanup
122+ }
123+
124+
66125define void @f_ssub (ptr nocapture %a ) {
67126; CHECK-LABEL: @f_ssub(
68127entry:
@@ -78,6 +137,9 @@ for.body: ; preds = %entry, %cont
78137 store i8 0 , ptr %arrayidx , align 1
79138 %0 = tail call { i32 , i1 } @llvm.ssub.with.overflow.i32 (i32 %i.04 , i32 1 )
80139 %1 = extractvalue { i32 , i1 } %0 , 1
140+ ; It is theoretically possible to prove this, but SCEV cannot
141+ ; represent non-unsigned-wrapping subtraction operations.
142+
81143; CHECK: for.body:
82144; CHECK-NOT: @llvm.ssub.with.overflow.i32
83145; CHECK: br i1 false, label %trap, label %cont, !nosanitize !0
@@ -93,6 +155,37 @@ cont: ; preds = %for.body
93155 br i1 %cmp , label %for.body , label %for.cond.cleanup
94156}
95157
158+ define void @f_ssub_overflow (ptr nocapture %a ) {
159+ ; CHECK-LABEL: @f_ssub_overflow(
160+ entry:
161+ br label %for.body
162+
163+ for.cond.cleanup: ; preds = %cont
164+ ret void
165+
166+ for.body: ; preds = %entry, %cont
167+ %i.04 = phi i32 [ -2147483642 , %entry ], [ %2 , %cont ]
168+ %idxprom = sext i32 %i.04 to i64
169+ %arrayidx = getelementptr inbounds i8 , ptr %a , i64 %idxprom
170+ store i8 0 , ptr %arrayidx , align 1
171+ %0 = tail call { i32 , i1 } @llvm.ssub.with.overflow.i32 (i32 %i.04 , i32 1 )
172+ %1 = extractvalue { i32 , i1 } %0 , 1
173+ ; CHECK: [[COND:%[^ ]+]] = extractvalue { i32, i1 } %1, 1
174+ ; CHECK-NEXT: br i1 [[COND]], label %trap, label %cont, !nosanitize !0
175+ ; CHECK: cont:
176+ ; CHECK: br i1 true, label %for.body, label %for.cond.cleanup
177+ br i1 %1 , label %trap , label %cont , !nosanitize !{}
178+
179+ trap: ; preds = %for.body
180+ tail call void @llvm.trap (), !nosanitize !{}
181+ unreachable , !nosanitize !{}
182+
183+ cont: ; preds = %for.body
184+ %2 = extractvalue { i32 , i1 } %0 , 0
185+ %cmp = icmp sge i32 %2 , -2147483648
186+ br i1 %cmp , label %for.body , label %for.cond.cleanup
187+ }
188+
96189define void @f_usub (ptr nocapture %a ) {
97190; CHECK-LABEL: @f_usub(
98191entry:
@@ -109,12 +202,45 @@ for.body: ; preds = %entry, %cont
109202 %0 = tail call { i32 , i1 } @llvm.usub.with.overflow.i32 (i32 %i.04 , i32 1 )
110203 %1 = extractvalue { i32 , i1 } %0 , 1
111204
205+ ; CHECK: for.body:
206+ ; CHECK-NOT: @llvm.usub.with.overflow.i32
207+ ; CHECK: br i1 false, label %trap, label %cont, !nosanitize !0
208+ br i1 %1 , label %trap , label %cont , !nosanitize !{}
209+
210+ trap: ; preds = %for.body
211+ tail call void @llvm.trap (), !nosanitize !{}
212+ unreachable , !nosanitize !{}
213+
214+ cont: ; preds = %for.body
215+ %2 = extractvalue { i32 , i1 } %0 , 0
216+ %cmp = icmp sgt i32 %2 , 0
217+ br i1 %cmp , label %for.body , label %for.cond.cleanup
218+ }
219+
220+ define void @f_usub_overflow (ptr nocapture %a ) {
221+ ; CHECK-LABEL: @f_usub_overflow(
222+ entry:
223+ br label %for.body
224+
225+ for.cond.cleanup: ; preds = %cont
226+ ret void
227+
228+ for.body: ; preds = %entry, %cont
229+ %i.04 = phi i32 [ 15 , %entry ], [ %2 , %cont ]
230+ %idxprom = sext i32 %i.04 to i64
231+ %arrayidx = getelementptr inbounds i8 , ptr %a , i64 %idxprom
232+ store i8 0 , ptr %arrayidx , align 1
233+ %0 = tail call { i32 , i1 } @llvm.usub.with.overflow.i32 (i32 %i.04 , i32 1 )
234+ %1 = extractvalue { i32 , i1 } %0 , 1
235+
112236; It is theoretically possible to prove this, but SCEV cannot
113237; represent non-unsigned-wrapping subtraction operations.
114238
115239; CHECK: for.body:
116240; CHECK: [[COND:%[^ ]+]] = extractvalue { i32, i1 } %1, 1
117241; CHECK-NEXT: br i1 [[COND]], label %trap, label %cont, !nosanitize !0
242+ ; CHECK: cont:
243+ ; CHECK: br i1 true, label %for.body, label %for.cond.cleanup
118244 br i1 %1 , label %trap , label %cont , !nosanitize !{}
119245
120246trap: ; preds = %for.body
0 commit comments