diff options
| author | Artur Pilipenko <apilipenko@azulsystems.com> | 2016-10-19 18:59:03 +0000 |
|---|---|---|
| committer | Artur Pilipenko <apilipenko@azulsystems.com> | 2016-10-19 18:59:03 +0000 |
| commit | f2d5dc5dc6971c999c667bfd0ee6751deb9ef8de (patch) | |
| tree | 1e0c958afd098f7853a087c68b9d987c6a33efd4 /llvm/test | |
| parent | 16970a847c00e9fac94b60b2179209edb24593ea (diff) | |
| download | bcm5719-llvm-f2d5dc5dc6971c999c667bfd0ee6751deb9ef8de.tar.gz bcm5719-llvm-f2d5dc5dc6971c999c667bfd0ee6751deb9ef8de.zip | |
[IndVarSimplify] Use control-dependent range information to prove non-negativity
This change is motivated by the case when IndVarSimplify doesn't widen a comparison of IV increment because it can't prove IV increment being non-negative. We end up with a redundant trunc of the widened increment on this example.
for.body:
%i = phi i32 [ %start, %for.body.lr.ph ], [ %i.inc, %for.inc ]
%within_limits = icmp ult i32 %i, 64
br i1 %within_limits, label %continue, label %for.end
continue:
%i.i64 = zext i32 %i to i64
%arrayidx = getelementptr inbounds i32, i32* %base, i64 %i.i64
%val = load i32, i32* %arrayidx, align 4
br label %for.inc
for.inc:
%i.inc = add nsw nuw i32 %i, 1
%cmp = icmp slt i32 %i.inc, %limit
br i1 %cmp, label %for.body, label %for.end
There is a range check inside of the loop which guarantees the IV to be non-negative. NSW on the increment guarantees that the increment is also non-negative. Teach IndVarSimplify to use the range check to prove non-negativity of loop increments.
Reviewed By: sanjoy
Differential Revision: https://reviews.llvm.org/D25738
llvm-svn: 284629
Diffstat (limited to 'llvm/test')
| -rw-r--r-- | llvm/test/Transforms/IndVarSimplify/post-inc-range.ll | 175 |
1 files changed, 175 insertions, 0 deletions
diff --git a/llvm/test/Transforms/IndVarSimplify/post-inc-range.ll b/llvm/test/Transforms/IndVarSimplify/post-inc-range.ll new file mode 100644 index 00000000000..717f0611a74 --- /dev/null +++ b/llvm/test/Transforms/IndVarSimplify/post-inc-range.ll @@ -0,0 +1,175 @@ +; RUN: opt < %s -indvars -indvars-post-increment-ranges -S | FileCheck %s + +target datalayout = "p:64:64:64-n32:64" + +; When the IV in this loop is widened we want to widen this use as well: +; icmp slt i32 %i.inc, %limit +; In order to do this indvars need to prove that the narrow IV def (%i.inc) +; is not-negative from the range check inside of the loop. +define void @test(i32* %base, i32 %limit, i32 %start) { +; CHECK-LABEL: @test( +; CHECK-NOT: trunc + +for.body.lr.ph: + br label %for.body + +for.body: + %i = phi i32 [ %start, %for.body.lr.ph ], [ %i.inc, %for.inc ] + %within_limits = icmp ult i32 %i, 64 + br i1 %within_limits, label %continue, label %for.end + +continue: + %i.i64 = zext i32 %i to i64 + %arrayidx = getelementptr inbounds i32, i32* %base, i64 %i.i64 + %val = load i32, i32* %arrayidx, align 4 + br label %for.inc + +for.inc: + %i.inc = add nsw nuw i32 %i, 1 + %cmp = icmp slt i32 %i.inc, %limit + br i1 %cmp, label %for.body, label %for.end + +for.end: + br label %exit + +exit: + ret void +} + +define void @test_false_edge(i32* %base, i32 %limit, i32 %start) { +; CHECK-LABEL: @test_false_edge( +; CHECK-NOT: trunc + +for.body.lr.ph: + br label %for.body + +for.body: + %i = phi i32 [ %start, %for.body.lr.ph ], [ %i.inc, %for.inc ] + %out_of_bounds = icmp ugt i32 %i, 64 + br i1 %out_of_bounds, label %for.end, label %continue + +continue: + %i.i64 = zext i32 %i to i64 + %arrayidx = getelementptr inbounds i32, i32* %base, i64 %i.i64 + %val = load i32, i32* %arrayidx, align 4 + br label %for.inc + +for.inc: + %i.inc = add nsw nuw i32 %i, 1 + %cmp = icmp slt i32 %i.inc, %limit + br i1 %cmp, label %for.body, label %for.end + +for.end: + br label %exit + +exit: + ret void +} + +define void @test_range_metadata(i32* %array_length_ptr, i32* %base, + i32 %limit, i32 %start) { +; CHECK-LABEL: @test_range_metadata( +; CHECK-NOT: trunc + +for.body.lr.ph: + br label %for.body + +for.body: + %i = phi i32 [ %start, %for.body.lr.ph ], [ %i.inc, %for.inc ] + %array_length = load i32, i32* %array_length_ptr, !range !{i32 0, i32 64 } + %within_limits = icmp ult i32 %i, %array_length + br i1 %within_limits, label %continue, label %for.end + +continue: + %i.i64 = zext i32 %i to i64 + %arrayidx = getelementptr inbounds i32, i32* %base, i64 %i.i64 + %val = load i32, i32* %arrayidx, align 4 + br label %for.inc + +for.inc: + %i.inc = add nsw nuw i32 %i, 1 + %cmp = icmp slt i32 %i.inc, %limit + br i1 %cmp, label %for.body, label %for.end + +for.end: + br label %exit + +exit: + ret void +} + +; Negative version of the test above, we don't know anything about +; array_length_ptr range. +define void @test_neg(i32* %array_length_ptr, i32* %base, + i32 %limit, i32 %start) { +; CHECK-LABEL: @test_neg( +; CHECK: trunc i64 + +for.body.lr.ph: + br label %for.body + +for.body: + %i = phi i32 [ %start, %for.body.lr.ph ], [ %i.inc, %for.inc ] + %array_length = load i32, i32* %array_length_ptr + %within_limits = icmp ult i32 %i, %array_length + br i1 %within_limits, label %continue, label %for.end + +continue: + %i.i64 = zext i32 %i to i64 + %arrayidx = getelementptr inbounds i32, i32* %base, i64 %i.i64 + %val = load i32, i32* %arrayidx, align 4 + br label %for.inc + +for.inc: + %i.inc = add nsw nuw i32 %i, 1 + %cmp = icmp slt i32 %i.inc, %limit + br i1 %cmp, label %for.body, label %for.end + +for.end: + br label %exit + +exit: + ret void +} + +define void @test_transitive_use(i32* %base, i32 %limit, i32 %start) { +; CHECK-LABEL: @test_transitive_use( +; CHECK-NOT: trunc +; CHECK: %result = icmp slt i64 + +for.body.lr.ph: + br label %for.body + +for.body: + %i = phi i32 [ %start, %for.body.lr.ph ], [ %i.inc, %for.inc ] + %within_limits = icmp ult i32 %i, 64 + br i1 %within_limits, label %continue, label %for.end + +continue: + %i.mul.3 = mul nsw nuw i32 %i, 3 + %mul_within = icmp ult i32 %i.mul.3, 64 + br i1 %mul_within, label %guarded, label %continue.2 + +guarded: + %i.mul.3.inc = add nsw nuw i32 %i.mul.3, 1 + %result = icmp slt i32 %i.mul.3.inc, %limit + br i1 %result, label %continue.2, label %for.end + +continue.2: + %i.i64 = zext i32 %i to i64 + %arrayidx = getelementptr inbounds i32, i32* %base, i64 %i.i64 + %val = load i32, i32* %arrayidx, align 4 + br label %for.inc + +for.inc: + %i.inc = add nsw nuw i32 %i, 1 + %cmp = icmp slt i32 %i.inc, %limit + br i1 %cmp, label %for.body, label %for.end + + +for.end: + br label %exit + +exit: + ret void +} |

