[SCEV] Mark AddExprs as nsw or nuw if legal

Summary:
This uses `ScalarEvolution::getRange` and not potentially control
dependent `nsw` and `nuw` bits on the arithmetic instruction.

Reviewers: atrick, hfinkel, nlewycky

Subscribers: llvm-commits, sanjoy

Differential Revision: http://reviews.llvm.org/D13613

llvm-svn: 251048
diff --git a/llvm/test/Analysis/ScalarEvolution/infer-prestart-no-wrap.ll b/llvm/test/Analysis/ScalarEvolution/infer-prestart-no-wrap.ll
index 078ca03..5c372b5 100644
--- a/llvm/test/Analysis/ScalarEvolution/infer-prestart-no-wrap.ll
+++ b/llvm/test/Analysis/ScalarEvolution/infer-prestart-no-wrap.ll
@@ -11,7 +11,7 @@
   %idx.inc = add nsw i32 %idx, 1
   %idx.inc.sext = sext i32 %idx.inc to i64
 ; CHECK: %idx.inc.sext = sext i32 %idx.inc to i64
-; CHECK-NEXT: -->  {(1 + (sext i32 %start to i64)),+,1}<nsw><%loop>
+; CHECK-NEXT: -->  {(1 + (sext i32 %start to i64))<nsw>,+,1}<nsw><%loop>
   %condition = icmp eq i32 %counter, 1
   %counter.inc = add i32 %counter, 1
   br i1 %condition, label %exit, label %loop
@@ -31,7 +31,7 @@
   %idx.inc = add nuw i32 %idx, 1
   %idx.inc.sext = zext i32 %idx.inc to i64
 ; CHECK: %idx.inc.sext = zext i32 %idx.inc to i64
-; CHECK-NEXT: -->  {(1 + (zext i32 %start to i64)),+,1}<nuw><%loop>
+; CHECK-NEXT: -->  {(1 + (zext i32 %start to i64))<nuw><nsw>,+,1}<nuw><%loop>
   %condition = icmp eq i32 %counter, 1
   %counter.inc = add i32 %counter, 1
   br i1 %condition, label %exit, label %loop
@@ -51,7 +51,7 @@
   %idx = phi i32 [ %start.real, %entry ], [ %idx.inc, %loop ]
   %idx.sext = sext i32 %idx to i64
 ; CHECK: %idx.sext = sext i32 %idx to i64
-; CHECK-NEXT:  -->  {(2 + (sext i32 (4 * %start) to i64)),+,2}<nsw><%loop>
+; CHECK-NEXT:  -->  {(2 + (sext i32 (4 * %start) to i64))<nsw>,+,2}<nsw><%loop>
   %idx.inc = add nsw i32 %idx, 2
   %condition = load i1, i1* %c
   br i1 %condition, label %exit, label %loop
@@ -71,7 +71,7 @@
   %idx = phi i8 [ %start.inc, %entry ], [ %idx.inc, %loop ]
   %idx.sext = sext i8 %idx to i16
 ; CHECK: %idx.sext = sext i8 %idx to i16
-; CHECK-NEXT: -->  {(1 + (sext i8 %start to i16)),+,1}<nsw><%loop>
+; CHECK-NEXT: -->  {(1 + (sext i8 %start to i16))<nsw>,+,1}<nsw><%loop>
   %idx.inc = add nsw i8 %idx, 1
   %condition = load volatile i1, i1* %c
   br i1 %condition, label %exit, label %loop
@@ -91,7 +91,7 @@
   %idx = phi i8 [ %start.inc, %entry ], [ %idx.inc, %loop ]
   %idx.zext = zext i8 %idx to i16
 ; CHECK: %idx.zext = zext i8 %idx to i16
-; CHECK-NEXT: -->  {(1 + (zext i8 %start to i16)),+,1}<nuw><%loop>
+; CHECK-NEXT: -->  {(1 + (zext i8 %start to i16))<nuw><nsw>,+,1}<nuw><%loop>
   %idx.inc = add nuw i8 %idx, 1
   %condition = load volatile i1, i1* %c
   br i1 %condition, label %exit, label %loop
diff --git a/llvm/test/Analysis/ScalarEvolution/min-max-exprs.ll b/llvm/test/Analysis/ScalarEvolution/min-max-exprs.ll
index a4be9c1..e8c1e33 100644
--- a/llvm/test/Analysis/ScalarEvolution/min-max-exprs.ll
+++ b/llvm/test/Analysis/ScalarEvolution/min-max-exprs.ll
@@ -33,7 +33,7 @@
   %tmp9 = select i1 %tmp4, i64 %tmp5, i64 %tmp6
 ;                  min(N, i+3)
 ; CHECK:           select i1 %tmp4, i64 %tmp5, i64 %tmp6
-; CHECK-NEXT:  --> (-1 + (-1 * ((-1 + (-1 * (sext i32 {3,+,1}<nw><%bb1> to i64))<nsw>) smax (-1 + (-1 * (sext i32 %N to i64))<nsw>)))<nsw>)
+; CHECK-NEXT:  --> (-1 + (-1 * ((-1 + (-1 * (sext i32 {3,+,1}<nuw><%bb1> to i64))<nsw>)<nsw> smax (-1 + (-1 * (sext i32 %N to i64))<nsw>)<nsw>))<nsw>)<nsw>
   %tmp11 = getelementptr inbounds i32, i32* %A, i64 %tmp9
   %tmp12 = load i32, i32* %tmp11, align 4
   %tmp13 = shl nsw i32 %tmp12, 1
diff --git a/llvm/test/Analysis/ScalarEvolution/no-wrap-add-exprs.ll b/llvm/test/Analysis/ScalarEvolution/no-wrap-add-exprs.ll
new file mode 100644
index 0000000..49a4f4f
--- /dev/null
+++ b/llvm/test/Analysis/ScalarEvolution/no-wrap-add-exprs.ll
@@ -0,0 +1,44 @@
+; RUN: opt -S -analyze -scalar-evolution < %s | FileCheck %s
+
+!0 = !{i8 0, i8 127}
+
+define void @f0(i8* %len_addr) {
+; CHECK-LABEL: Classifying expressions for: @f0
+ entry:
+  %len = load i8, i8* %len_addr, !range !0
+  %len_norange = load i8, i8* %len_addr
+; CHECK:  %len = load i8, i8* %len_addr, !range !0
+; CHECK-NEXT:  -->  %len U: [0,127) S: [0,127)
+; CHECK:  %len_norange = load i8, i8* %len_addr
+; CHECK-NEXT:  -->  %len_norange U: full-set S: full-set
+
+  %t0 = add i8 %len, 1
+  %t1 = add i8 %len, 2
+; CHECK:  %t0 = add i8 %len, 1
+; CHECK-NEXT:  -->  (1 + %len)<nuw><nsw> U: [1,-128) S: [1,-128)
+; CHECK:  %t1 = add i8 %len, 2
+; CHECK-NEXT:  -->  (2 + %len)<nuw> U: [2,-127) S: [2,-127)
+
+  %t2 = sub i8 %len, 1
+  %t3 = sub i8 %len, 2
+; CHECK:  %t2 = sub i8 %len, 1
+; CHECK-NEXT:  -->  (-1 + %len)<nsw> U: [-1,126) S: [-1,126)
+; CHECK:  %t3 = sub i8 %len, 2
+; CHECK-NEXT:  -->  (-2 + %len)<nsw> U: [-2,125) S: [-2,125)
+
+  %q0 = add i8 %len_norange, 1
+  %q1 = add i8 %len_norange, 2
+; CHECK:  %q0 = add i8 %len_norange, 1
+; CHECK-NEXT:  -->  (1 + %len_norange) U: full-set S: full-set
+; CHECK:  %q1 = add i8 %len_norange, 2
+; CHECK-NEXT:  -->  (2 + %len_norange) U: full-set S: full-set
+
+  %q2 = sub i8 %len_norange, 1
+  %q3 = sub i8 %len_norange, 2
+; CHECK:  %q2 = sub i8 %len_norange, 1
+; CHECK-NEXT:  -->  (-1 + %len_norange) U: full-set S: full-set
+; CHECK:  %q3 = sub i8 %len_norange, 2
+; CHECK-NEXT:  -->  (-2 + %len_norange) U: full-set S: full-set
+
+  ret void
+}