llvm.org GIT mirror llvm / f7b6243
Teach CorrelatedValuePropagation to mark adds as no wrap This is a resubmission of previously reverted r277592. It was hitting overly strong assertion in getConstantRange which was relaxed in r278217. Use LVI to prove that adds do not wrap. The change is motivated by https://llvm.org/bugs/show_bug.cgi?id=28620 bug and it's the first step to fix that problem. Reviewed By: sanjoy Differential Revision: http://reviews.llvm.org/D23059 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@278220 91177308-0d34-0410-b5e6-96231b3b80d8 Artur Pilipenko 3 years ago
2 changed file(s) with 148 addition(s) and 0 deletion(s). Raw diff Collapse all Expand all
1717 #include "llvm/Analysis/InstructionSimplify.h"
1818 #include "llvm/Analysis/LazyValueInfo.h"
1919 #include "llvm/IR/CFG.h"
20 #include "llvm/IR/ConstantRange.h"
2021 #include "llvm/IR/Constants.h"
2122 #include "llvm/IR/Function.h"
2223 #include "llvm/IR/Instructions.h"
380381 return true;
381382 }
382383
384 static bool processAdd(BinaryOperator *AddOp, LazyValueInfo *LVI) {
385 typedef OverflowingBinaryOperator OBO;
386
387 if (AddOp->getType()->isVectorTy() || hasLocalDefs(AddOp))
388 return false;
389
390 bool NSW = AddOp->hasNoSignedWrap();
391 bool NUW = AddOp->hasNoUnsignedWrap();
392 if (NSW && NUW)
393 return false;
394
395 BasicBlock *BB = AddOp->getParent();
396
397 Value *LHS = AddOp->getOperand(0);
398 Value *RHS = AddOp->getOperand(1);
399
400 ConstantRange LRange = LVI->getConstantRange(LHS, BB, AddOp);
401
402 // Initialize RRange only if we need it. If we know that guaranteed no wrap
403 // range for the given LHS range is empty don't spend time calculating the
404 // range for the RHS.
405 Optional RRange;
406 auto LazyRRange = [&] () {
407 if (!RRange)
408 RRange = LVI->getConstantRange(RHS, BB, AddOp);
409 return RRange.getValue();
410 };
411
412 bool Changed = false;
413 if (!NUW) {
414 ConstantRange NUWRange =
415 LRange.makeGuaranteedNoWrapRegion(BinaryOperator::Add, LRange,
416 OBO::NoUnsignedWrap);
417 if (!NUWRange.isEmptySet()) {
418 bool NewNUW = NUWRange.contains(LazyRRange());
419 AddOp->setHasNoUnsignedWrap(NewNUW);
420 Changed |= NewNUW;
421 }
422 }
423 if (!NSW) {
424 ConstantRange NSWRange =
425 LRange.makeGuaranteedNoWrapRegion(BinaryOperator::Add, LRange,
426 OBO::NoSignedWrap);
427 if (!NSWRange.isEmptySet()) {
428 bool NewNSW = NSWRange.contains(LazyRRange());
429 AddOp->setHasNoSignedWrap(NewNSW);
430 Changed |= NewNSW;
431 }
432 }
433
434 return Changed;
435 }
436
383437 static Constant *getConstantAt(Value *V, Instruction *At, LazyValueInfo *LVI) {
384438 if (Constant *C = LVI->getConstant(V, At->getParent(), At))
385439 return C;
434488 break;
435489 case Instruction::SDiv:
436490 BBChanged |= processSDiv(cast(II), LVI);
491 break;
492 case Instruction::Add:
493 BBChanged |= processAdd(cast(II), LVI);
437494 break;
438495 }
439496 }
0 ; RUN: opt < %s -correlated-propagation -S | FileCheck %s
1
2 ; CHECK-LABEL: @test0(
3 define void @test0(i32 %a) {
4 entry:
5 %cmp = icmp slt i32 %a, 100
6 br i1 %cmp, label %bb, label %exit
7
8 bb:
9 ; CHECK: %add = add nsw i32 %a, 1
10 %add = add i32 %a, 1
11 br label %exit
12
13 exit:
14 ret void
15 }
16
17 ; CHECK-LABEL: @test1(
18 define void @test1(i32 %a) {
19 entry:
20 %cmp = icmp ult i32 %a, 100
21 br i1 %cmp, label %bb, label %exit
22
23 bb:
24 ; CHECK: %add = add nuw nsw i32 %a, 1
25 %add = add i32 %a, 1
26 br label %exit
27
28 exit:
29 ret void
30 }
31
32 ; CHECK-LABEL: @test2(
33 define void @test2(i32 %a) {
34 entry:
35 %cmp = icmp ult i32 %a, -1
36 br i1 %cmp, label %bb, label %exit
37
38 bb:
39 ; CHECK: %add = add nuw i32 %a, 1
40 %add = add i32 %a, 1
41 br label %exit
42
43 exit:
44 ret void
45 }
46
47 ; CHECK-LABEL: @test3(
48 define void @test3(i32 %a) {
49 entry:
50 %cmp = icmp ule i32 %a, -1
51 br i1 %cmp, label %bb, label %exit
52
53 bb:
54 ; CHECK: %add = add i32 %a, 1
55 %add = add i32 %a, 1
56 br label %exit
57
58 exit:
59 ret void
60 }
61
62 ; CHECK-LABEL: @test4(
63 define void @test4(i32 %a) {
64 entry:
65 %cmp = icmp slt i32 %a, 2147483647
66 br i1 %cmp, label %bb, label %exit
67
68 bb:
69 ; CHECK: %add = add nsw i32 %a, 1
70 %add = add i32 %a, 1
71 br label %exit
72
73 exit:
74 ret void
75 }
76
77 ; CHECK-LABEL: @test5(
78 define void @test5(i32 %a) {
79 entry:
80 %cmp = icmp sle i32 %a, 2147483647
81 br i1 %cmp, label %bb, label %exit
82
83 bb:
84 ; CHECK: %add = add i32 %a, 1
85 %add = add i32 %a, 1
86 br label %exit
87
88 exit:
89 ret void
90 }