llvm.org GIT mirror llvm / c05a5c2
[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 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@251048 91177308-0d34-0410-b5e6-96231b3b80d8 Sanjoy Das 5 years ago
7 changed file(s) with 84 addition(s) and 15 deletion(s). Raw diff Collapse all Expand all
19201920 static SCEV::NoWrapFlags
19211921 StrengthenNoWrapFlags(ScalarEvolution *SE, SCEVTypes Type,
19221922 const SmallVectorImpl &Ops,
1923 SCEV::NoWrapFlags OldFlags) {
1923 SCEV::NoWrapFlags Flags) {
19241924 using namespace std::placeholders;
1925 typedef OverflowingBinaryOperator OBO;
19251926
19261927 bool CanAnalyze =
19271928 Type == scAddExpr || Type == scAddRecExpr || Type == scMulExpr;
19301931
19311932 int SignOrUnsignMask = SCEV::FlagNUW | SCEV::FlagNSW;
19321933 SCEV::NoWrapFlags SignOrUnsignWrap =
1933 ScalarEvolution::maskFlags(OldFlags, SignOrUnsignMask);
1934 ScalarEvolution::maskFlags(Flags, SignOrUnsignMask);
19341935
19351936 // If FlagNSW is true and all the operands are non-negative, infer FlagNUW.
19361937 auto IsKnownNonNegative =
19381939
19391940 if (SignOrUnsignWrap == SCEV::FlagNSW &&
19401941 std::all_of(Ops.begin(), Ops.end(), IsKnownNonNegative))
1941 return ScalarEvolution::setFlags(OldFlags,
1942 (SCEV::NoWrapFlags)SignOrUnsignMask);
1943
1944 return OldFlags;
1942 Flags =
1943 ScalarEvolution::setFlags(Flags, (SCEV::NoWrapFlags)SignOrUnsignMask);
1944
1945 SignOrUnsignWrap = ScalarEvolution::maskFlags(Flags, SignOrUnsignMask);
1946
1947 if (SignOrUnsignWrap != SignOrUnsignMask && Type == scAddExpr &&
1948 Ops.size() == 2 && isa(Ops[0])) {
1949
1950 // (A + C) --> (A + C) if the addition does not sign overflow
1951 // (A + C) --> (A + C) if the addition does not unsign overflow
1952
1953 const APInt &C = cast(Ops[0])->getValue()->getValue();
1954 if (!(SignOrUnsignWrap & SCEV::FlagNSW)) {
1955 auto NSWRegion =
1956 ConstantRange::makeNoWrapRegion(Instruction::Add, C, OBO::NoSignedWrap);
1957 if (NSWRegion.contains(SE->getSignedRange(Ops[1])))
1958 Flags = ScalarEvolution::setFlags(Flags, SCEV::FlagNSW);
1959 }
1960 if (!(SignOrUnsignWrap & SCEV::FlagNUW)) {
1961 auto NUWRegion =
1962 ConstantRange::makeNoWrapRegion(Instruction::Add, C,
1963 OBO::NoUnsignedWrap);
1964 if (NUWRegion.contains(SE->getUnsignedRange(Ops[1])))
1965 Flags = ScalarEvolution::setFlags(Flags, SCEV::FlagNUW);
1966 }
1967 }
1968
1969 return Flags;
19451970 }
19461971
19471972 /// getAddExpr - Get a canonical add expression, or something simpler if
1010 ; AddRec: {{{(56 + (8 * (-4 + (3 * %m)) * %o) + %A),+,(8 * %m * %o)}<%for.i>,+,(8 * %o)}<%for.j>,+,8}<%for.k>
1111 ; CHECK: Base offset: %A
1212 ; CHECK: ArrayDecl[UnknownSize][%m][%o] with elements of 8 bytes.
13 ; CHECK: ArrayRef[{3,+,1}w><%for.i>][{-4,+,1}<%for.j>][{7,+,1}<%for.k>]
13 ; CHECK: ArrayRef[{3,+,1}uw><%for.i>][{-4,+,1}<%for.j>][{7,+,1}<%for.k>]
1414
1515 define void @foo(i64 %n, i64 %m, i64 %o, double* %A) {
1616 entry:
1010 ; AddRec: {{{(56 + (8 * (-4 + (3 * %m)) * (%o + %p)) + %A),+,(8 * (%o + %p) * %m)}<%for.cond4.preheader.lr.ph.us>,+,(8 * (%o + %p))}<%for.body6.lr.ph.us.us>,+,8}<%for.body6.us.us>
1111 ; CHECK: Base offset: %A
1212 ; CHECK: ArrayDecl[UnknownSize][%m][(%o + %p)] with elements of 8 bytes.
13 ; CHECK: ArrayRef[{3,+,1}w><%for.cond4.preheader.lr.ph.us>][{-4,+,1}<%for.body6.lr.ph.us.us>][{7,+,1}<%for.body6.us.us>]
13 ; CHECK: ArrayRef[{3,+,1}uw><%for.cond4.preheader.lr.ph.us>][{-4,+,1}<%for.body6.lr.ph.us.us>][{7,+,1}<%for.body6.us.us>]
1414
1515 define void @foo(i64 %n, i64 %m, i64 %o, i64 %p, double* nocapture %A) nounwind uwtable {
1616 entry:
1010 %idx.inc = add nsw i32 %idx, 1
1111 %idx.inc.sext = sext i32 %idx.inc to i64
1212 ; CHECK: %idx.inc.sext = sext i32 %idx.inc to i64
13 ; CHECK-NEXT: --> {(1 + (sext i32 %start to i64)),+,1}<%loop>
13 ; CHECK-NEXT: --> {(1 + (sext i32 %start to i64)),+,1}<%loop>
1414 %condition = icmp eq i32 %counter, 1
1515 %counter.inc = add i32 %counter, 1
1616 br i1 %condition, label %exit, label %loop
3030 %idx.inc = add nuw i32 %idx, 1
3131 %idx.inc.sext = zext i32 %idx.inc to i64
3232 ; CHECK: %idx.inc.sext = zext i32 %idx.inc to i64
33 ; CHECK-NEXT: --> {(1 + (zext i32 %start to i64)),+,1}<%loop>
33 ; CHECK-NEXT: --> {(1 + (zext i32 %start to i64)),+,1}<%loop>
3434 %condition = icmp eq i32 %counter, 1
3535 %counter.inc = add i32 %counter, 1
3636 br i1 %condition, label %exit, label %loop
5050 %idx = phi i32 [ %start.real, %entry ], [ %idx.inc, %loop ]
5151 %idx.sext = sext i32 %idx to i64
5252 ; CHECK: %idx.sext = sext i32 %idx to i64
53 ; CHECK-NEXT: --> {(2 + (sext i32 (4 * %start) to i64)),+,2}<%loop>
53 ; CHECK-NEXT: --> {(2 + (sext i32 (4 * %start) to i64)),+,2}<%loop>
5454 %idx.inc = add nsw i32 %idx, 2
5555 %condition = load i1, i1* %c
5656 br i1 %condition, label %exit, label %loop
7070 %idx = phi i8 [ %start.inc, %entry ], [ %idx.inc, %loop ]
7171 %idx.sext = sext i8 %idx to i16
7272 ; CHECK: %idx.sext = sext i8 %idx to i16
73 ; CHECK-NEXT: --> {(1 + (sext i8 %start to i16)),+,1}<%loop>
73 ; CHECK-NEXT: --> {(1 + (sext i8 %start to i16)),+,1}<%loop>
7474 %idx.inc = add nsw i8 %idx, 1
7575 %condition = load volatile i1, i1* %c
7676 br i1 %condition, label %exit, label %loop
9090 %idx = phi i8 [ %start.inc, %entry ], [ %idx.inc, %loop ]
9191 %idx.zext = zext i8 %idx to i16
9292 ; CHECK: %idx.zext = zext i8 %idx to i16
93 ; CHECK-NEXT: --> {(1 + (zext i8 %start to i16)),+,1}<%loop>
93 ; CHECK-NEXT: --> {(1 + (zext i8 %start to i16)),+,1}<%loop>
9494 %idx.inc = add nuw i8 %idx, 1
9595 %condition = load volatile i1, i1* %c
9696 br i1 %condition, label %exit, label %loop
3232 %tmp9 = select i1 %tmp4, i64 %tmp5, i64 %tmp6
3333 ; min(N, i+3)
3434 ; CHECK: select i1 %tmp4, i64 %tmp5, i64 %tmp6
35 ; CHECK-NEXT: --> (-1 + (-1 * ((-1 + (-1 * (sext i32 {3,+,1}w><%bb1> to i64))) smax (-1 + (-1 * (sext i32 %N to i64))))))
35 ; CHECK-NEXT: --> (-1 + (-1 * ((-1 + (-1 * (sext i32 {3,+,1}uw><%bb1> to i64))) smax (-1 + (-1 * (sext i32 %N to i64))))))
3636 %tmp11 = getelementptr inbounds i32, i32* %A, i64 %tmp9
3737 %tmp12 = load i32, i32* %tmp11, align 4
3838 %tmp13 = shl nsw i32 %tmp12, 1
0 ; RUN: opt -S -analyze -scalar-evolution < %s | FileCheck %s
1
2 !0 = !{i8 0, i8 127}
3
4 define void @f0(i8* %len_addr) {
5 ; CHECK-LABEL: Classifying expressions for: @f0
6 entry:
7 %len = load i8, i8* %len_addr, !range !0
8 %len_norange = load i8, i8* %len_addr
9 ; CHECK: %len = load i8, i8* %len_addr, !range !0
10 ; CHECK-NEXT: --> %len U: [0,127) S: [0,127)
11 ; CHECK: %len_norange = load i8, i8* %len_addr
12 ; CHECK-NEXT: --> %len_norange U: full-set S: full-set
13
14 %t0 = add i8 %len, 1
15 %t1 = add i8 %len, 2
16 ; CHECK: %t0 = add i8 %len, 1
17 ; CHECK-NEXT: --> (1 + %len) U: [1,-128) S: [1,-128)
18 ; CHECK: %t1 = add i8 %len, 2
19 ; CHECK-NEXT: --> (2 + %len) U: [2,-127) S: [2,-127)
20
21 %t2 = sub i8 %len, 1
22 %t3 = sub i8 %len, 2
23 ; CHECK: %t2 = sub i8 %len, 1
24 ; CHECK-NEXT: --> (-1 + %len) U: [-1,126) S: [-1,126)
25 ; CHECK: %t3 = sub i8 %len, 2
26 ; CHECK-NEXT: --> (-2 + %len) U: [-2,125) S: [-2,125)
27
28 %q0 = add i8 %len_norange, 1
29 %q1 = add i8 %len_norange, 2
30 ; CHECK: %q0 = add i8 %len_norange, 1
31 ; CHECK-NEXT: --> (1 + %len_norange) U: full-set S: full-set
32 ; CHECK: %q1 = add i8 %len_norange, 2
33 ; CHECK-NEXT: --> (2 + %len_norange) U: full-set S: full-set
34
35 %q2 = sub i8 %len_norange, 1
36 %q3 = sub i8 %len_norange, 2
37 ; CHECK: %q2 = sub i8 %len_norange, 1
38 ; CHECK-NEXT: --> (-1 + %len_norange) U: full-set S: full-set
39 ; CHECK: %q3 = sub i8 %len_norange, 2
40 ; CHECK-NEXT: --> (-2 + %len_norange) U: full-set S: full-set
41
42 ret void
43 }
2727 ; sure they aren't marked as post-inc users.
2828 ;
2929 ; CHECK-LABEL: IV Users for loop %test2.loop
30 ; CHECK: %sext.us = {0,+,(16777216 + (-16777216 * %sub.us)),+,33554432}<%test2.loop> in %f = ashr i32 %sext.us, 24
30 ; CHECK: %sext.us = {0,+,(16777216 + (-16777216 * %sub.us)),+,33554432}<%test2.loop> in %f = ashr i32 %sext.us, 24
3131 define i32 @test2() {
3232 entry:
3333 br label %test2.loop