2015-07-16 22:02:58 +08:00
|
|
|
; RUN: opt -loop-accesses -analyze < %s | FileCheck %s
|
2016-07-03 05:18:40 +08:00
|
|
|
; RUN: opt -passes='loop(print-access-info)' -disable-output < %s 2>&1 | FileCheck %s
|
2015-07-16 22:02:58 +08:00
|
|
|
|
|
|
|
; The runtime memory check code and the access grouping
|
|
|
|
; algorithm both assume that the start and end values
|
|
|
|
; for an access range are ordered (start <= stop).
|
|
|
|
; When generating checks for accesses with negative stride
|
|
|
|
; we need to take this into account and swap the interval
|
|
|
|
; ends.
|
|
|
|
;
|
|
|
|
; for (i = 0; i < 10000; i++) {
|
|
|
|
; B[i] = A[15000 - i] * 3;
|
|
|
|
; }
|
|
|
|
|
|
|
|
target datalayout = "e-m:e-i64:64-i128:128-n32:64-S128"
|
|
|
|
target triple = "aarch64--linux-gnueabi"
|
|
|
|
|
|
|
|
; CHECK: function 'f':
|
[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
llvm-svn: 270695
2016-05-25 21:01:33 +08:00
|
|
|
; CHECK: (Low: (20000 + %a) High: (60000 + %a)<nsw>)
|
2015-07-16 22:02:58 +08:00
|
|
|
|
|
|
|
@B = common global i32* null, align 8
|
|
|
|
@A = common global i32* null, align 8
|
|
|
|
|
|
|
|
define void @f() {
|
|
|
|
entry:
|
|
|
|
%a = load i32*, i32** @A, align 8
|
|
|
|
%b = load i32*, i32** @B, align 8
|
|
|
|
br label %for.body
|
|
|
|
|
|
|
|
for.body: ; preds = %for.body, %entry
|
|
|
|
%idx = phi i64 [ 0, %entry ], [ %add, %for.body ]
|
|
|
|
%negidx = sub i64 15000, %idx
|
|
|
|
|
|
|
|
%arrayidxA0 = getelementptr inbounds i32, i32* %a, i64 %negidx
|
|
|
|
%loadA0 = load i32, i32* %arrayidxA0, align 2
|
|
|
|
|
|
|
|
%res = mul i32 %loadA0, 3
|
|
|
|
|
|
|
|
%add = add nuw nsw i64 %idx, 1
|
|
|
|
|
|
|
|
%arrayidxB = getelementptr inbounds i32, i32* %b, i64 %idx
|
|
|
|
store i32 %res, i32* %arrayidxB, align 2
|
|
|
|
|
|
|
|
%exitcond = icmp eq i64 %idx, 10000
|
|
|
|
br i1 %exitcond, label %for.end, label %for.body
|
|
|
|
|
|
|
|
for.end: ; preds = %for.body
|
|
|
|
ret void
|
|
|
|
}
|
|
|
|
|
|
|
|
; CHECK: function 'g':
|
|
|
|
; When the stride is not constant, we are forced to do umin/umax to get
|
|
|
|
; the interval limits.
|
|
|
|
|
|
|
|
; for (i = 0; i < 10000; i++) {
|
|
|
|
; B[i] = A[15000 - step * i] * 3;
|
|
|
|
; }
|
|
|
|
|
|
|
|
; 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)))))
|
[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
llvm-svn: 270695
2016-05-25 21:01:33 +08:00
|
|
|
; CHECK: High: ((60000 + %a)<nsw> umax (60000 + (-40000 * %step) + %a))
|
2015-07-16 22:02:58 +08:00
|
|
|
|
|
|
|
define void @g(i64 %step) {
|
|
|
|
entry:
|
|
|
|
%a = load i32*, i32** @A, align 8
|
|
|
|
%b = load i32*, i32** @B, align 8
|
|
|
|
br label %for.body
|
|
|
|
|
|
|
|
for.body: ; preds = %for.body, %entry
|
|
|
|
%idx = phi i64 [ 0, %entry ], [ %add, %for.body ]
|
|
|
|
%idx_mul = mul i64 %idx, %step
|
|
|
|
%negidx = sub i64 15000, %idx_mul
|
|
|
|
|
|
|
|
%arrayidxA0 = getelementptr inbounds i32, i32* %a, i64 %negidx
|
|
|
|
%loadA0 = load i32, i32* %arrayidxA0, align 2
|
|
|
|
|
|
|
|
%res = mul i32 %loadA0, 3
|
|
|
|
|
|
|
|
%add = add nuw nsw i64 %idx, 1
|
|
|
|
|
|
|
|
%arrayidxB = getelementptr inbounds i32, i32* %b, i64 %idx
|
|
|
|
store i32 %res, i32* %arrayidxB, align 2
|
|
|
|
|
|
|
|
%exitcond = icmp eq i64 %idx, 10000
|
|
|
|
br i1 %exitcond, label %for.end, label %for.body
|
|
|
|
|
|
|
|
for.end: ; preds = %for.body
|
|
|
|
ret void
|
|
|
|
}
|