llvm.org GIT mirror llvm / 7af26ab
[CVP] Remove some {s|u}add.with.overflow checks. Summary: This adds logic to CVP to remove some overflow checks. It uses LVI to remove operations with at least one constant. Specifically, this can remove many overflow intrinsics immediately following an overflow check in the source code, such as: if (x < INT_MAX) ... x + 1 ... Patch by Joel Galenson! Reviewers: sanjoy, regehr Reviewed By: sanjoy Subscribers: fhahn, pirama, srhines, llvm-commits Differential Revision: https://reviews.llvm.org/D39483 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@317911 91177308-0d34-0410-b5e6-96231b3b80d8 Sanjoy Das 1 year, 11 months ago
2 changed file(s) with 424 addition(s) and 0 deletion(s). Raw diff Collapse all Expand all
3030 #include "llvm/IR/InstrTypes.h"
3131 #include "llvm/IR/Instruction.h"
3232 #include "llvm/IR/Instructions.h"
33 #include "llvm/IR/IntrinsicInst.h"
34 #include "llvm/IR/IRBuilder.h"
3335 #include "llvm/IR/Operator.h"
3436 #include "llvm/IR/PassManager.h"
3537 #include "llvm/IR/Type.h"
5759 STATISTIC(NumSDivs, "Number of sdiv converted to udiv");
5860 STATISTIC(NumAShrs, "Number of ashr converted to lshr");
5961 STATISTIC(NumSRems, "Number of srem converted to urem");
62 STATISTIC(NumOverflows, "Number of overflow checks removed");
6063
6164 static cl::opt DontProcessAdds("cvp-dont-process-adds", cl::init(true));
6265
322325 return Changed;
323326 }
324327
328 // See if we can prove that the given overflow intrinsic will not overflow.
329 static bool willNotOverflow(IntrinsicInst *II, LazyValueInfo *LVI) {
330 using OBO = OverflowingBinaryOperator;
331 auto NoWrapOnAddition = [&] (Value *LHS, Value *RHS, unsigned NoWrapKind) {
332 ConstantRange RRange = LVI->getConstantRange(RHS, II->getParent(), II);
333 ConstantRange NWRegion = ConstantRange::makeGuaranteedNoWrapRegion(
334 BinaryOperator::Add, RRange, NoWrapKind);
335 // As an optimization, do not compute LRange if we do not need it.
336 if (NWRegion.isEmptySet())
337 return false;
338 ConstantRange LRange = LVI->getConstantRange(LHS, II->getParent(), II);
339 return NWRegion.contains(LRange);
340 };
341 switch (II->getIntrinsicID()) {
342 default:
343 break;
344 case Intrinsic::uadd_with_overflow:
345 return NoWrapOnAddition(II->getOperand(0), II->getOperand(1),
346 OBO::NoUnsignedWrap);
347 case Intrinsic::sadd_with_overflow:
348 return NoWrapOnAddition(II->getOperand(0), II->getOperand(1),
349 OBO::NoSignedWrap);
350 }
351 return false;
352 }
353
354 static void processOverflowIntrinsic(IntrinsicInst *II) {
355 Value *NewOp = nullptr;
356 switch (II->getIntrinsicID()) {
357 default:
358 llvm_unreachable("Illegal instruction.");
359 case Intrinsic::uadd_with_overflow:
360 case Intrinsic::sadd_with_overflow:
361 NewOp = BinaryOperator::CreateAdd(II->getOperand(0), II->getOperand(1),
362 II->getName(), II);
363 break;
364 }
365 ++NumOverflows;
366 IRBuilder<> B(II);
367 Value *NewI = B.CreateInsertValue(UndefValue::get(II->getType()), NewOp, 0);
368 NewI = B.CreateInsertValue(NewI, ConstantInt::getFalse(II->getContext()), 1);
369 II->replaceAllUsesWith(NewI);
370 II->eraseFromParent();
371 }
372
325373 /// Infer nonnull attributes for the arguments at the specified callsite.
326374 static bool processCallSite(CallSite CS, LazyValueInfo *LVI) {
327375 SmallVector ArgNos;
328376 unsigned ArgNo = 0;
377
378 if (IntrinsicInst *II = dyn_cast(CS.getInstruction())) {
379 if (willNotOverflow(II, LVI)) {
380 processOverflowIntrinsic(II);
381 return true;
382 }
383 }
329384
330385 for (Value *V : CS.args()) {
331386 PointerType *Type = dyn_cast(V->getType());
0 ; RUN: opt -S -correlated-propagation < %s | FileCheck %s
1
2 declare { i32, i1 } @llvm.sadd.with.overflow.i32(i32, i32)
3
4 declare { i32, i1 } @llvm.ssub.with.overflow.i32(i32, i32)
5
6 declare { i32, i1 } @llvm.uadd.with.overflow.i32(i32, i32)
7
8 declare { i32, i1 } @llvm.usub.with.overflow.i32(i32, i32)
9
10 declare void @llvm.trap()
11
12
13 define i32 @signed_add(i32 %x, i32 %y) {
14 ; CHECK-LABEL: @signed_add(
15 ; CHECK: @llvm.ssub.with.overflow.i32
16 ; CHECK: @llvm.ssub.with.overflow.i32
17 ; CHECK: @llvm.sadd.with.overflow.i32
18 entry:
19 %cmp = icmp sgt i32 %y, 0
20 br i1 %cmp, label %land.lhs.true, label %lor.lhs.false
21
22 land.lhs.true: ; preds = %entry
23 %0 = tail call { i32, i1 } @llvm.ssub.with.overflow.i32(i32 2147483647, i32 %y)
24 %1 = extractvalue { i32, i1 } %0, 1
25 br i1 %1, label %trap, label %cont
26
27 trap: ; preds = %land.lhs.true, %land.lhs.true3, %cond.false
28 tail call void @llvm.trap()
29 unreachable
30
31 cont: ; preds = %land.lhs.true
32 %2 = extractvalue { i32, i1 } %0, 0
33 %cmp1 = icmp slt i32 %2, %x
34 br i1 %cmp1, label %cond.end, label %cond.false
35
36 lor.lhs.false: ; preds = %entry
37 %cmp2 = icmp slt i32 %y, 0
38 br i1 %cmp2, label %land.lhs.true3, label %cond.false
39
40 land.lhs.true3: ; preds = %lor.lhs.false
41 %3 = tail call { i32, i1 } @llvm.ssub.with.overflow.i32(i32 -2147483648, i32 %y)
42 %4 = extractvalue { i32, i1 } %3, 1
43 br i1 %4, label %trap, label %cont4
44
45 cont4: ; preds = %land.lhs.true3
46 %5 = extractvalue { i32, i1 } %3, 0
47 %cmp5 = icmp sgt i32 %5, %x
48 br i1 %cmp5, label %cond.end, label %cond.false
49
50 cond.false: ; preds = %cont, %cont4, %lor.lhs.false
51 %6 = tail call { i32, i1 } @llvm.sadd.with.overflow.i32(i32 %x, i32 %y)
52 %7 = extractvalue { i32, i1 } %6, 0
53 %8 = extractvalue { i32, i1 } %6, 1
54 br i1 %8, label %trap, label %cond.end
55
56 cond.end: ; preds = %cond.false, %cont, %cont4
57 %cond = phi i32 [ 0, %cont4 ], [ 0, %cont ], [ %7, %cond.false ]
58 ret i32 %cond
59 }
60
61 define i32 @unsigned_add(i32 %x, i32 %y) {
62 ; CHECK-LABEL: @unsigned_add(
63 ; CHECK: @llvm.usub.with.overflow.i32
64 ; CHECK: @llvm.uadd.with.overflow.i32
65 entry:
66 %0 = tail call { i32, i1 } @llvm.usub.with.overflow.i32(i32 -1, i32 %y)
67 %1 = extractvalue { i32, i1 } %0, 1
68 br i1 %1, label %trap, label %cont
69
70 trap: ; preds = %cond.false, %entry
71 tail call void @llvm.trap()
72 unreachable
73
74 cont: ; preds = %entry
75 %2 = extractvalue { i32, i1 } %0, 0
76 %cmp1 = icmp ult i32 %2, %x
77 br i1 %cmp1, label %cond.end, label %cond.false
78
79 cond.false: ; preds = %cont
80 %3 = tail call { i32, i1 } @llvm.uadd.with.overflow.i32(i32 %x, i32 %y)
81 %4 = extractvalue { i32, i1 } %3, 0
82 %5 = extractvalue { i32, i1 } %3, 1
83 br i1 %5, label %trap, label %cond.end
84
85 cond.end: ; preds = %cond.false, %cont
86 %cond = phi i32 [ 0, %cont ], [ %4, %cond.false ]
87 ret i32 %cond
88 }
89
90 define i32 @signed_sub(i32 %x, i32 %y) {
91 ; CHECK-LABEL: @signed_sub(
92 ; CHECK-NOT: @llvm.sadd.with.overflow.i32
93 ; CHECK: @llvm.ssub.with.overflow.i32
94 entry:
95 %cmp = icmp slt i32 %y, 0
96 br i1 %cmp, label %land.lhs.true, label %lor.lhs.false
97
98 land.lhs.true: ; preds = %entry
99 %0 = tail call { i32, i1 } @llvm.sadd.with.overflow.i32(i32 %y, i32 2147483647)
100 %1 = extractvalue { i32, i1 } %0, 1
101 br i1 %1, label %trap, label %cont
102
103 trap: ; preds = %land.lhs.true, %land.lhs.true3, %cond.false
104 tail call void @llvm.trap()
105 unreachable
106
107 cont: ; preds = %land.lhs.true
108 %2 = extractvalue { i32, i1 } %0, 0
109 %cmp1 = icmp slt i32 %2, %x
110 br i1 %cmp1, label %cond.end, label %cond.false
111
112 lor.lhs.false: ; preds = %entry
113 %cmp2 = icmp eq i32 %y, 0
114 br i1 %cmp2, label %cond.false, label %land.lhs.true3
115
116 land.lhs.true3: ; preds = %lor.lhs.false
117 %3 = tail call { i32, i1 } @llvm.sadd.with.overflow.i32(i32 %y, i32 -2147483648)
118 %4 = extractvalue { i32, i1 } %3, 1
119 br i1 %4, label %trap, label %cont4
120
121 cont4: ; preds = %land.lhs.true3
122 %5 = extractvalue { i32, i1 } %3, 0
123 %cmp5 = icmp sgt i32 %5, %x
124 br i1 %cmp5, label %cond.end, label %cond.false
125
126 cond.false: ; preds = %lor.lhs.false, %cont, %cont4
127 %6 = tail call { i32, i1 } @llvm.ssub.with.overflow.i32(i32 %x, i32 %y)
128 %7 = extractvalue { i32, i1 } %6, 0
129 %8 = extractvalue { i32, i1 } %6, 1
130 br i1 %8, label %trap, label %cond.end
131
132 cond.end: ; preds = %cond.false, %cont, %cont4
133 %cond = phi i32 [ 0, %cont4 ], [ 0, %cont ], [ %7, %cond.false ]
134 ret i32 %cond
135 }
136
137 define i32 @unsigned_sub(i32 %x, i32 %y) {
138 ; CHECK-LABEL: @unsigned_sub(
139 ; CHECK: @llvm.usub.with.overflow.i32
140 entry:
141 %cmp = icmp ult i32 %x, %y
142 br i1 %cmp, label %cond.end, label %cond.false
143
144 cond.false: ; preds = %entry
145 %0 = tail call { i32, i1 } @llvm.usub.with.overflow.i32(i32 %x, i32 %y)
146 %1 = extractvalue { i32, i1 } %0, 0
147 %2 = extractvalue { i32, i1 } %0, 1
148 br i1 %2, label %trap, label %cond.end
149
150 trap: ; preds = %cond.false
151 tail call void @llvm.trap()
152 unreachable
153
154 cond.end: ; preds = %cond.false, %entry
155 %cond = phi i32 [ 0, %entry ], [ %1, %cond.false ]
156 ret i32 %cond
157 }
158
159 define i32 @signed_add_r1(i32 %x) {
160 ; CHECK-LABEL: @signed_add_r1(
161 ; CHECK-NOT: @llvm.sadd.with.overflow.i32
162 entry:
163 %cmp = icmp eq i32 %x, 2147483647
164 br i1 %cmp, label %cond.end, label %cond.false
165
166 cond.false: ; preds = %entry
167 %0 = tail call { i32, i1 } @llvm.sadd.with.overflow.i32(i32 %x, i32 1)
168 %1 = extractvalue { i32, i1 } %0, 0
169 %2 = extractvalue { i32, i1 } %0, 1
170 br i1 %2, label %trap, label %cond.end
171
172 trap: ; preds = %cond.false
173 tail call void @llvm.trap()
174 unreachable
175
176 cond.end: ; preds = %cond.false, %entry
177 %cond = phi i32 [ 0, %entry ], [ %1, %cond.false ]
178 ret i32 %cond
179 }
180
181 define i32 @unsigned_add_r1(i32 %x) {
182 ; CHECK-LABEL: @unsigned_add_r1(
183 ; CHECK-NOT: @llvm.uadd.with.overflow.i32
184 entry:
185 %cmp = icmp eq i32 %x, -1
186 br i1 %cmp, label %cond.end, label %cond.false
187
188 cond.false: ; preds = %entry
189 %0 = tail call { i32, i1 } @llvm.uadd.with.overflow.i32(i32 %x, i32 1)
190 %1 = extractvalue { i32, i1 } %0, 0
191 %2 = extractvalue { i32, i1 } %0, 1
192 br i1 %2, label %trap, label %cond.end
193
194 trap: ; preds = %cond.false
195 tail call void @llvm.trap()
196 unreachable
197
198 cond.end: ; preds = %cond.false, %entry
199 %cond = phi i32 [ 0, %entry ], [ %1, %cond.false ]
200 ret i32 %cond
201 }
202
203 define i32 @signed_sub_r1(i32 %x) {
204 ; CHECK-LABEL: @signed_sub_r1(
205 ; CHECK: @llvm.ssub.with.overflow.i32
206 entry:
207 %cmp = icmp eq i32 %x, -2147483648
208 br i1 %cmp, label %cond.end, label %cond.false
209
210 cond.false: ; preds = %entry
211 %0 = tail call { i32, i1 } @llvm.ssub.with.overflow.i32(i32 %x, i32 1)
212 %1 = extractvalue { i32, i1 } %0, 0
213 %2 = extractvalue { i32, i1 } %0, 1
214 br i1 %2, label %trap, label %cond.end
215
216 trap: ; preds = %cond.false
217 tail call void @llvm.trap()
218 unreachable
219
220 cond.end: ; preds = %cond.false, %entry
221 %cond = phi i32 [ 0, %entry ], [ %1, %cond.false ]
222 ret i32 %cond
223 }
224
225 define i32 @unsigned_sub_r1(i32 %x) {
226 ; CHECK-LABEL: @unsigned_sub_r1(
227 ; CHECK: @llvm.usub.with.overflow.i32
228 entry:
229 %cmp = icmp eq i32 %x, 0
230 br i1 %cmp, label %cond.end, label %cond.false
231
232 cond.false: ; preds = %entry
233 %0 = tail call { i32, i1 } @llvm.usub.with.overflow.i32(i32 %x, i32 1)
234 %1 = extractvalue { i32, i1 } %0, 0
235 %2 = extractvalue { i32, i1 } %0, 1
236 br i1 %2, label %trap, label %cond.end
237
238 trap: ; preds = %cond.false
239 tail call void @llvm.trap()
240 unreachable
241
242 cond.end: ; preds = %cond.false, %entry
243 %cond = phi i32 [ 0, %entry ], [ %1, %cond.false ]
244 ret i32 %cond
245 }
246
247 define i32 @signed_add_rn1(i32 %x) {
248 ; CHECK-LABEL: @signed_add_rn1(
249 ; CHECK-NOT: @llvm.sadd.with.overflow.i32
250 entry:
251 %cmp = icmp eq i32 %x, -2147483648
252 br i1 %cmp, label %cond.end, label %cond.false
253
254 cond.false: ; preds = %entry
255 %0 = tail call { i32, i1 } @llvm.sadd.with.overflow.i32(i32 %x, i32 -1)
256 %1 = extractvalue { i32, i1 } %0, 0
257 %2 = extractvalue { i32, i1 } %0, 1
258 br i1 %2, label %trap, label %cond.end
259
260 trap: ; preds = %cond.false
261 tail call void @llvm.trap()
262 unreachable
263
264 cond.end: ; preds = %cond.false, %entry
265 %cond = phi i32 [ 0, %entry ], [ %1, %cond.false ]
266 ret i32 %cond
267 }
268
269 define i32 @signed_sub_rn1(i32 %x) {
270 ; CHECK-LABEL: @signed_sub_rn1(
271 ; CHECK: @llvm.ssub.with.overflow.i32
272 entry:
273 %cmp = icmp eq i32 %x, 2147483647
274 br i1 %cmp, label %cond.end, label %cond.false
275
276 cond.false: ; preds = %entry
277 %0 = tail call { i32, i1 } @llvm.ssub.with.overflow.i32(i32 %x, i32 -1)
278 %1 = extractvalue { i32, i1 } %0, 0
279 %2 = extractvalue { i32, i1 } %0, 1
280 br i1 %2, label %trap, label %cond.end
281
282 trap: ; preds = %cond.false
283 tail call void @llvm.trap()
284 unreachable
285
286 cond.end: ; preds = %cond.false, %entry
287 %cond = phi i32 [ 0, %entry ], [ %1, %cond.false ]
288 ret i32 %cond
289 }
290
291 declare i32 @bar(i32)
292
293 define void @unsigned_loop(i32 %i) {
294 ; CHECK-LABEL: @unsigned_loop(
295 ; CHECK: @llvm.usub.with.overflow.i32
296 entry:
297 %cmp3 = icmp eq i32 %i, 0
298 br i1 %cmp3, label %while.end, label %while.body.preheader
299
300 while.body.preheader: ; preds = %entry
301 br label %while.body
302
303 while.body: ; preds = %while.body.preheader, %cont
304 %i.addr.04 = phi i32 [ %2, %cont ], [ %i, %while.body.preheader ]
305 %call = tail call i32 @bar(i32 %i.addr.04)
306 %0 = tail call { i32, i1 } @llvm.usub.with.overflow.i32(i32 %i.addr.04, i32 1)
307 %1 = extractvalue { i32, i1 } %0, 1
308 br i1 %1, label %trap, label %cont
309
310 trap: ; preds = %while.body
311 tail call void @llvm.trap()
312 unreachable
313
314 cont: ; preds = %while.body
315 %2 = extractvalue { i32, i1 } %0, 0
316 %cmp = icmp eq i32 %2, 0
317 br i1 %cmp, label %while.end, label %while.body
318
319 while.end: ; preds = %cont, %entry
320 ret void
321 }
322
323 define void @intrinsic_into_phi(i32 %n) {
324 ; CHECK-LABEL: @intrinsic_into_phi(
325 ; CHECK: @llvm.sadd.with.overflow.i32
326 ; CHECK-NOT: @llvm.sadd.with.overflow.i32
327 entry:
328 br label %cont
329
330 for.cond: ; preds = %while.end
331 %0 = tail call { i32, i1 } @llvm.sadd.with.overflow.i32(i32 %.lcssa, i32 1)
332 %1 = extractvalue { i32, i1 } %0, 1
333 br i1 %1, label %trap, label %cont
334
335 trap: ; preds = %for.cond, %while.body
336 tail call void @llvm.trap()
337 unreachable
338
339 cont: ; preds = %entry, %for.cond
340 %2 = phi { i32, i1 } [ zeroinitializer, %entry ], [ %0, %for.cond ]
341 %3 = extractvalue { i32, i1 } %2, 0
342 %call9 = tail call i32 @bar(i32 %3)
343 %tobool10 = icmp eq i32 %call9, 0
344 br i1 %tobool10, label %while.end, label %while.body.preheader
345
346 while.body.preheader: ; preds = %cont
347 br label %while.body
348
349 while.cond: ; preds = %while.body
350 %4 = extractvalue { i32, i1 } %6, 0
351 %call = tail call i32 @bar(i32 %4)
352 %tobool = icmp eq i32 %call, 0
353 br i1 %tobool, label %while.end, label %while.body
354
355 while.body: ; preds = %while.body.preheader, %while.cond
356 %5 = phi i32 [ %4, %while.cond ], [ %3, %while.body.preheader ]
357 %6 = tail call { i32, i1 } @llvm.sadd.with.overflow.i32(i32 %5, i32 1)
358 %7 = extractvalue { i32, i1 } %6, 1
359 br i1 %7, label %trap, label %while.cond
360
361 while.end: ; preds = %while.cond, %cont
362 %.lcssa = phi i32 [ %3, %cont ], [ %4, %while.cond ]
363 %cmp = icmp slt i32 %.lcssa, %n
364 br i1 %cmp, label %for.cond, label %cleanup2
365
366 cleanup2: ; preds = %while.end
367 ret void
368 }