[llvm] r270695 - [SCEV] No-wrap flags are not propagated when folding "{S, +, X}+T ==> {S+T, +, X}"

Oleg Ranevskyy via llvm-commits llvm-commits at lists.llvm.org
Wed May 25 06:01:34 PDT 2016


Author: oleg
Date: Wed May 25 08:01:33 2016
New Revision: 270695

URL: http://llvm.org/viewvc/llvm-project?rev=270695&view=rev
Log:
[SCEV] No-wrap flags are not propagated when folding "{S,+,X}+T ==> {S+T,+,X}"

Summary:
**Description**

This makes `WidenIV::widenIVUse` (IndVarSimplify.cpp) fail to widen narrow IV uses in some cases. The latter affects IndVarSimplify which may not eliminate narrow IV's when there actually exists such a possibility, thereby producing ineffective code.

When `WidenIV::widenIVUse` gets a NarrowUse such as `{(-2 + %inc.lcssa),+,1}<nsw><%for.body3>`, it first tries to get a wide recurrence for it via the `getWideRecurrence` call.
`getWideRecurrence` returns recurrence like this: `{(sext i32 (-2 + %inc.lcssa) to i64),+,1}<nsw><%for.body3>`.

Then a wide use operation is generated by `cloneIVUser`. The generated wide use is evaluated to `{(-2 + (sext i32 %inc.lcssa to i64))<nsw>,+,1}<nsw><%for.body3>`, which is different from the `getWideRecurrence` result. `cloneIVUser` sees the difference and returns nullptr.

This patch also fixes the broken LLVM tests by adding missing <nsw> entries introduced by the correction.

**Minimal reproducer:**
```
int foo(int a, int b, int c);
int baz();

void bar()
{
   int arr[20];
   int i = 0;

   for (i = 0; i < 4; ++i)
     arr[i] = baz();

   for (; i < 20; ++i)
     arr[i] = foo(arr[i - 4], arr[i - 3], arr[i - 2]);
}
```

**Clang command line:**
```
clang++ -mllvm -debug -S -emit-llvm -O3 --target=aarch64-linux-elf test.cpp -o test.ir
```

**Expected result:**
The ` -mllvm -debug` log shows that all the IV's for the second `for` loop have been eliminated.

Reviewers: sanjoy

Subscribers: atrick, asl, aemerson, mzolotukhin, llvm-commits

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

Modified:
    llvm/trunk/lib/Analysis/ScalarEvolution.cpp
    llvm/trunk/test/Analysis/LoopAccessAnalysis/number-of-memchecks.ll
    llvm/trunk/test/Analysis/LoopAccessAnalysis/reverse-memcheck-bounds.ll
    llvm/trunk/test/Analysis/ScalarEvolution/flags-from-poison.ll
    llvm/trunk/test/Analysis/ScalarEvolution/nsw-offset-assume.ll
    llvm/trunk/test/Analysis/ScalarEvolution/nsw-offset.ll
    llvm/trunk/test/Analysis/ScalarEvolution/nsw.ll

Modified: llvm/trunk/lib/Analysis/ScalarEvolution.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Analysis/ScalarEvolution.cpp?rev=270695&r1=270694&r2=270695&view=diff
==============================================================================
--- llvm/trunk/lib/Analysis/ScalarEvolution.cpp (original)
+++ llvm/trunk/lib/Analysis/ScalarEvolution.cpp Wed May 25 08:01:33 2016
@@ -2306,7 +2306,10 @@ const SCEV *ScalarEvolution::getAddExpr(
 
       SmallVector<const SCEV *, 4> AddRecOps(AddRec->op_begin(),
                                              AddRec->op_end());
-      AddRecOps[0] = getAddExpr(LIOps);
+      // This follows from the fact that the no-wrap flags on the outer add
+      // expression are applicable on the 0th iteration, when the add recurrence
+      // will be equal to its start value.
+      AddRecOps[0] = getAddExpr(LIOps, Flags);
 
       // Build the new addrec. Propagate the NUW and NSW flags if both the
       // outer add and the inner addrec are guaranteed to have no overflow.

Modified: llvm/trunk/test/Analysis/LoopAccessAnalysis/number-of-memchecks.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Analysis/LoopAccessAnalysis/number-of-memchecks.ll?rev=270695&r1=270694&r2=270695&view=diff
==============================================================================
--- llvm/trunk/test/Analysis/LoopAccessAnalysis/number-of-memchecks.ll (original)
+++ llvm/trunk/test/Analysis/LoopAccessAnalysis/number-of-memchecks.ll Wed May 25 08:01:33 2016
@@ -96,11 +96,11 @@ for.end:
 ; CHECK-NEXT:   Grouped accesses:
 ; CHECK-NEXT:    Group {{.*}}[[ZERO]]:
 ; CHECK-NEXT:       (Low: %c High: (78 + %c))
-; CHECK-NEXT:         Member: {(2 + %c),+,4}
+; CHECK-NEXT:         Member: {(2 + %c)<nsw>,+,4}
 ; CHECK-NEXT:         Member: {%c,+,4}
 ; CHECK-NEXT:     Group {{.*}}[[ONE]]:
 ; CHECK-NEXT:       (Low: %a High: (40 + %a))
-; CHECK-NEXT:         Member: {(2 + %a),+,2}
+; CHECK-NEXT:         Member: {(2 + %a)<nsw>,+,2}
 ; CHECK-NEXT:         Member: {%a,+,2}
 ; CHECK-NEXT:     Group {{.*}}[[TWO]]:
 ; CHECK-NEXT:       (Low: %b High: (38 + %b))
@@ -168,7 +168,7 @@ for.end:
 ; CHECK-NEXT:   Grouped accesses:
 ; CHECK-NEXT:     Group {{.*}}[[ZERO]]:
 ; CHECK-NEXT:       (Low: %c High: (78 + %c))
-; CHECK-NEXT:         Member: {(2 + %c),+,4}
+; CHECK-NEXT:         Member: {(2 + %c)<nsw>,+,4}
 ; CHECK-NEXT:         Member: {%c,+,4}
 ; CHECK-NEXT:     Group {{.*}}[[ONE]]:
 ; CHECK-NEXT:       (Low: %a High: (40 + %a))
@@ -246,8 +246,8 @@ for.end:
 ; CHECK-NEXT:       %arrayidxA2 = getelementptr i16, i16* %a, i64 %ind2
 ; CHECK-NEXT:   Grouped accesses:
 ; CHECK-NEXT:     Group {{.*}}[[ZERO]]:
-; CHECK-NEXT:       (Low: ((2 * %offset) + %a) High: (9998 + (2 * %offset) + %a))
-; CHECK-NEXT:         Member: {((2 * %offset) + %a),+,2}<nsw><%for.body>
+; CHECK-NEXT:       (Low: ((2 * %offset) + %a)<nsw> High: (9998 + (2 * %offset) + %a))
+; CHECK-NEXT:         Member: {((2 * %offset) + %a)<nsw>,+,2}<nsw><%for.body>
 ; CHECK-NEXT:     Group {{.*}}[[ONE]]:
 ; CHECK-NEXT:       (Low: %a High: (9998 + %a))
 ; CHECK-NEXT:         Member: {%a,+,2}<%for.body>

Modified: llvm/trunk/test/Analysis/LoopAccessAnalysis/reverse-memcheck-bounds.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Analysis/LoopAccessAnalysis/reverse-memcheck-bounds.ll?rev=270695&r1=270694&r2=270695&view=diff
==============================================================================
--- llvm/trunk/test/Analysis/LoopAccessAnalysis/reverse-memcheck-bounds.ll (original)
+++ llvm/trunk/test/Analysis/LoopAccessAnalysis/reverse-memcheck-bounds.ll Wed May 25 08:01:33 2016
@@ -15,7 +15,7 @@ target datalayout = "e-m:e-i64:64-i128:1
 target triple = "aarch64--linux-gnueabi"
 
 ; CHECK: function 'f':
-; CHECK: (Low: (20000 + %a) High: (60000 + %a))
+; CHECK: (Low: (20000 + %a) High: (60000 + %a)<nsw>)
 
 @B = common global i32* null, align 8
 @A = common global i32* null, align 8
@@ -58,7 +58,7 @@ for.end:
 ; Here it is not obvious what the limits are, since 'step' could be negative.
 
 ; CHECK: Low: (-1 + (-1 * ((-60001 + (-1 * %a)) umax (-60001 + (40000 * %step) + (-1 * %a)))))
-; CHECK: High: ((60000 + %a) umax (60000 + (-40000 * %step) + %a))
+; CHECK: High: ((60000 + %a)<nsw> umax (60000 + (-40000 * %step) + %a))
 
 define void @g(i64 %step) {
 entry:

Modified: llvm/trunk/test/Analysis/ScalarEvolution/flags-from-poison.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Analysis/ScalarEvolution/flags-from-poison.ll?rev=270695&r1=270694&r2=270695&view=diff
==============================================================================
--- llvm/trunk/test/Analysis/ScalarEvolution/flags-from-poison.ll (original)
+++ llvm/trunk/test/Analysis/ScalarEvolution/flags-from-poison.ll Wed May 25 08:01:33 2016
@@ -420,7 +420,7 @@ loop:
 
   %j = add nsw i32 %i, 1
 ; CHECK: %index32 =
-; CHECK: --> {(1 + %offset),+,1}<nsw>
+; CHECK: --> {(1 + %offset)<nsw>,+,1}<nsw>
   %index32 = add nsw i32 %j, %offset
 
   %ptr = getelementptr inbounds float, float* %input, i32 %index32
@@ -562,7 +562,7 @@ loop:
   %i = phi i32 [ %nexti, %loop ], [ %start, %entry ]
 
 ; CHECK: %index32 =
-; CHECK: --> {((-1 * %halfsub)<nsw> + %start),+,1}<nsw>
+; CHECK: --> {((-1 * %halfsub)<nsw> + %start)<nsw>,+,1}<nsw>
   %index32 = sub nsw i32 %i, %halfsub
   %index64 = sext i32 %index32 to i64
 
@@ -621,7 +621,7 @@ loop:
 
   %j = add nsw i32 %i, 1
 ; CHECK: %index32 =
-; CHECK: --> {(1 + (-1 * %offset)),+,1}<nsw>
+; CHECK: --> {(1 + (-1 * %offset))<nsw>,+,1}<nsw>
   %index32 = sub nsw i32 %j, %offset
 
   %ptr = getelementptr inbounds float, float* %input, i32 %index32

Modified: llvm/trunk/test/Analysis/ScalarEvolution/nsw-offset-assume.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Analysis/ScalarEvolution/nsw-offset-assume.ll?rev=270695&r1=270694&r2=270695&view=diff
==============================================================================
--- llvm/trunk/test/Analysis/ScalarEvolution/nsw-offset-assume.ll (original)
+++ llvm/trunk/test/Analysis/ScalarEvolution/nsw-offset-assume.ll Wed May 25 08:01:33 2016
@@ -39,7 +39,7 @@ bb:
   %8 = sext i32 %7 to i64                         ; <i64> [#uses=1]
 
 ; CHECK: %9 = getelementptr inbounds double, double* %q, i64 %8
-; CHECK: {(8 + %q),+,16}<nsw><%bb>
+; CHECK: {(8 + %q)<nsw>,+,16}<nsw><%bb>
   %9 = getelementptr inbounds double, double* %q, i64 %8  ; <double*> [#uses=1]
 
 ; Artificially repeat the above three instructions, this time using
@@ -51,7 +51,7 @@ bb:
   %t8 = sext i32 %t7 to i64                         ; <i64> [#uses=1]
 
 ; CHECK: %t9 = getelementptr inbounds double, double* %q, i64 %t8
-; CHECK: {(8 + %q),+,16}<nsw><%bb>
+; CHECK: {(8 + %q)<nsw>,+,16}<nsw><%bb>
   %t9 = getelementptr inbounds double, double* %q, i64 %t8  ; <double*> [#uses=1]
 
   %10 = load double, double* %9, align 8                  ; <double> [#uses=1]

Modified: llvm/trunk/test/Analysis/ScalarEvolution/nsw-offset.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Analysis/ScalarEvolution/nsw-offset.ll?rev=270695&r1=270694&r2=270695&view=diff
==============================================================================
--- llvm/trunk/test/Analysis/ScalarEvolution/nsw-offset.ll (original)
+++ llvm/trunk/test/Analysis/ScalarEvolution/nsw-offset.ll Wed May 25 08:01:33 2016
@@ -37,7 +37,7 @@ bb:
   %8 = sext i32 %7 to i64                         ; <i64> [#uses=1]
 
 ; CHECK: %9 = getelementptr inbounds double, double* %q, i64 %8
-; CHECK: {(8 + %q),+,16}<nsw><%bb>
+; CHECK: {(8 + %q)<nsw>,+,16}<nsw><%bb>
   %9 = getelementptr inbounds double, double* %q, i64 %8  ; <double*> [#uses=1]
 
 ; Artificially repeat the above three instructions, this time using
@@ -49,7 +49,7 @@ bb:
   %t8 = sext i32 %t7 to i64                         ; <i64> [#uses=1]
 
 ; CHECK: %t9 = getelementptr inbounds double, double* %q, i64 %t8
-; CHECK: {(8 + %q),+,16}<nsw><%bb>
+; CHECK: {(8 + %q)<nsw>,+,16}<nsw><%bb>
   %t9 = getelementptr inbounds double, double* %q, i64 %t8  ; <double*> [#uses=1]
 
   %10 = load double, double* %9, align 8                  ; <double> [#uses=1]

Modified: llvm/trunk/test/Analysis/ScalarEvolution/nsw.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Analysis/ScalarEvolution/nsw.ll?rev=270695&r1=270694&r2=270695&view=diff
==============================================================================
--- llvm/trunk/test/Analysis/ScalarEvolution/nsw.ll (original)
+++ llvm/trunk/test/Analysis/ScalarEvolution/nsw.ll Wed May 25 08:01:33 2016
@@ -66,7 +66,7 @@ for.body.i.i:
   store i32 0, i32* %__first.addr.02.i.i, align 4
   %ptrincdec.i.i = getelementptr inbounds i32, i32* %__first.addr.02.i.i, i64 1
 ; CHECK: %ptrincdec.i.i
-; CHECK-NEXT: -->  {(4 + %begin),+,4}<nuw><%for.body.i.i>
+; CHECK-NEXT: -->  {(4 + %begin)<nsw>,+,4}<nuw><%for.body.i.i>
   %cmp.i.i = icmp eq i32* %ptrincdec.i.i, %end
   br i1 %cmp.i.i, label %for.cond.for.end_crit_edge.i.i, label %for.body.i.i
 
@@ -92,7 +92,7 @@ for.body.i.i:
 ; CHECK: {1,+,1}<nuw><nsw><%for.body.i.i>
   %ptrincdec.i.i = getelementptr inbounds i32, i32* %begin, i64 %tmp
 ; CHECK: %ptrincdec.i.i =
-; CHECK: {(4 + %begin),+,4}<nsw><%for.body.i.i>
+; CHECK: {(4 + %begin)<nsw>,+,4}<nsw><%for.body.i.i>
   %__first.addr.08.i.i = getelementptr inbounds i32, i32* %begin, i64 %indvar.i.i
 ; CHECK: %__first.addr.08.i.i
 ; CHECK: {%begin,+,4}<nsw><%for.body.i.i>
@@ -124,7 +124,7 @@ exit:
 }
 
 ; CHECK-LABEL: PR12375
-; CHECK: -->  {(4 + %arg),+,4}<nuw><%bb1>{{ U: [^ ]+ S: [^ ]+}}{{ *}}Exits: (8 + %arg)<nsw>
+; CHECK: -->  {(4 + %arg)<nsw>,+,4}<nuw><%bb1>{{ U: [^ ]+ S: [^ ]+}}{{ *}}Exits: (8 + %arg)<nsw>
 define i32 @PR12375(i32* readnone %arg) {
 bb:
   %tmp = getelementptr inbounds i32, i32* %arg, i64 2
@@ -143,7 +143,7 @@ bb7:
 }
 
 ; CHECK-LABEL: PR12376
-; CHECK: -->  {(4 + %arg),+,4}<nuw><%bb2>{{ U: [^ ]+ S: [^ ]+}}{{ *}}Exits: (4 + (4 * ((3 + (-1 * %arg) + (%arg umax %arg1)) /u 4)) + %arg)
+; CHECK: -->  {(4 + %arg)<nsw>,+,4}<nuw><%bb2>{{ U: [^ ]+ S: [^ ]+}}{{ *}}Exits: (4 + (4 * ((3 + (-1 * %arg) + (%arg umax %arg1)) /u 4)) + %arg)
 define void @PR12376(i32* nocapture %arg, i32* nocapture %arg1)  {
 bb:
   br label %bb2
@@ -176,4 +176,27 @@ for.body:
 
 for.end:
   ret void
+}
+
+; This test checks if no-wrap flags are propagated when folding {S,+,X}+T ==> {S+T,+,X}
+; CHECK-LABEL: test4
+; CHECK: %idxprom
+; CHECK-NEXT: -->  {(-2 + (sext i32 %arg to i64))<nsw>,+,1}<nsw><%for.body>
+define void @test4(i32 %arg) {
+entry:
+  %array = alloca [10 x i32], align 4
+  br label %for.body
+
+for.body:
+  %index = phi i32 [ %inc5, %for.body ], [ %arg, %entry ]
+  %sub = add nsw i32 %index, -2
+  %idxprom = sext i32 %sub to i64
+  %arrayidx = getelementptr inbounds [10 x i32], [10 x i32]* %array, i64 0, i64 %idxprom
+  %data = load i32, i32* %arrayidx, align 4
+  %inc5 = add nsw i32 %index, 1
+  %cmp2 = icmp slt i32 %inc5, 10
+  br i1 %cmp2, label %for.body, label %for.end
+
+for.end:
+  ret void
 }




More information about the llvm-commits mailing list