1
0
mirror of https://github.com/RPCS3/llvm-mirror.git synced 2024-11-25 04:02:41 +01:00
llvm-mirror/test/Transforms/IndVarSimplify/loop-invariant-conditions.ll
Sanjoy Das 4c063981c7 [IndVars] Make loop varying predicates loop invariant.
Summary:
Was D9784: "Remove loop variant range check when induction variable is
strictly increasing"

This change re-implements D9784 with the two differences:

 1. It does not use SCEVExpander and does not generate new
    instructions.  Instead, it does a quick local search for existing
    `llvm::Value`s that it needs when modifying the `icmp`
    instruction.

 2. It is more general -- it deals with both increasing and decreasing
    induction variables.

I've added all of the tests included with D9784, and two more.

As an example on what this change does (copied from D9784):

Given C code:

```
for (int i = M; i < N; i++) // i is known not to overflow
  if (i < 0) break;
  a[i] = 0;
}
```

This transformation produces:

```
for (int i = M; i < N; i++)
  if (M < 0) break;
  a[i] = 0;
}
```

Which can be unswitched into:

```
if (!(M < 0))
  for (int i = M; i < N; i++)
    a[i] = 0;
}
```

I went back and forth on whether the top level logic should live in
`SimplifyIndvar::eliminateIVComparison` or be put into its own
routine.  Right now I've put it under `eliminateIVComparison` because
even though the `icmp` is not *eliminated*, it no longer is an IV
comparison.  I'm open to putting it in its own helper routine if you
think that is better.

Reviewers: reames, nicholas, atrick

Subscribers: llvm-commits

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

llvm-svn: 243331
2015-07-27 21:42:49 +00:00

280 lines
7.9 KiB
LLVM

; RUN: opt -S -indvars %s | FileCheck %s
target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
target triple = "x86_64-unknown-linux-gnu"
define void @test1(i64 %start) {
; CHECK-LABEL: @test1
entry:
br label %loop
loop:
%indvars.iv = phi i64 [ %start, %entry ], [ %indvars.iv.next, %loop ]
%indvars.iv.next = add nsw i64 %indvars.iv, 1
; CHECK: %cmp1 = icmp slt i64 %start, -1
%cmp1 = icmp slt i64 %indvars.iv, -1
br i1 %cmp1, label %for.end, label %loop
for.end: ; preds = %if.end, %entry
ret void
}
define void @test2(i64 %start) {
; CHECK-LABEL: @test2
entry:
br label %loop
loop:
%indvars.iv = phi i64 [ %start, %entry ], [ %indvars.iv.next, %loop ]
%indvars.iv.next = add nsw i64 %indvars.iv, 1
; CHECK: %cmp1 = icmp sle i64 %start, -1
%cmp1 = icmp sle i64 %indvars.iv, -1
br i1 %cmp1, label %for.end, label %loop
for.end: ; preds = %if.end, %entry
ret void
}
; As long as the test dominates the backedge, we're good
define void @test3(i64 %start) {
; CHECK-LABEL: @test3
entry:
br label %loop
loop:
%indvars.iv = phi i64 [ %start, %entry ], [ %indvars.iv.next, %backedge ]
%indvars.iv.next = add nsw i64 %indvars.iv, 1
%cmp = icmp eq i64 %indvars.iv.next, 25
br i1 %cmp, label %backedge, label %for.end
backedge:
; prevent flattening, needed to make sure we're testing what we intend
call void @foo()
; CHECK: %cmp1 = icmp slt i64 %start, -1
%cmp1 = icmp slt i64 %indvars.iv, -1
br i1 %cmp1, label %for.end, label %loop
for.end: ; preds = %if.end, %entry
ret void
}
define void @test4(i64 %start) {
; CHECK-LABEL: @test4
entry:
br label %loop
loop:
%indvars.iv = phi i64 [ %start, %entry ], [ %indvars.iv.next, %backedge ]
%indvars.iv.next = add nsw i64 %indvars.iv, 1
%cmp = icmp eq i64 %indvars.iv.next, 25
br i1 %cmp, label %backedge, label %for.end
backedge:
; prevent flattening, needed to make sure we're testing what we intend
call void @foo()
; CHECK: %cmp1 = icmp sgt i64 %start, -1
%cmp1 = icmp sgt i64 %indvars.iv, -1
br i1 %cmp1, label %loop, label %for.end
for.end: ; preds = %if.end, %entry
ret void
}
define void @test5(i64 %start) {
; CHECK-LABEL: @test5
entry:
br label %loop
loop:
%indvars.iv = phi i64 [ %start, %entry ], [ %indvars.iv.next, %backedge ]
%indvars.iv.next = add nuw i64 %indvars.iv, 1
%cmp = icmp eq i64 %indvars.iv.next, 25
br i1 %cmp, label %backedge, label %for.end
backedge:
; prevent flattening, needed to make sure we're testing what we intend
call void @foo()
; CHECK: %cmp1 = icmp ugt i64 %start, 100
%cmp1 = icmp ugt i64 %indvars.iv, 100
br i1 %cmp1, label %loop, label %for.end
for.end: ; preds = %if.end, %entry
ret void
}
define void @test6(i64 %start) {
; CHECK-LABEL: @test6
entry:
br label %loop
loop:
%indvars.iv = phi i64 [ %start, %entry ], [ %indvars.iv.next, %backedge ]
%indvars.iv.next = add nuw i64 %indvars.iv, 1
%cmp = icmp eq i64 %indvars.iv.next, 25
br i1 %cmp, label %backedge, label %for.end
backedge:
; prevent flattening, needed to make sure we're testing what we intend
call void @foo()
; CHECK: %cmp1 = icmp ult i64 %start, 100
%cmp1 = icmp ult i64 %indvars.iv, 100
br i1 %cmp1, label %for.end, label %loop
for.end: ; preds = %if.end, %entry
ret void
}
define void @test7(i64 %start, i64* %inc_ptr) {
; CHECK-LABEL: @test7
entry:
%inc = load i64, i64* %inc_ptr, !range !0
%ok = icmp sge i64 %inc, 0
br i1 %ok, label %loop, label %for.end
loop:
%indvars.iv = phi i64 [ %start, %entry ], [ %indvars.iv.next, %loop ]
%indvars.iv.next = add nsw i64 %indvars.iv, %inc
; CHECK: %cmp1 = icmp slt i64 %start, -1
%cmp1 = icmp slt i64 %indvars.iv, -1
br i1 %cmp1, label %for.end, label %loop
for.end: ; preds = %if.end, %entry
ret void
}
!0 = !{i64 0, i64 100}
; Negative test - we can't show that the internal branch executes, so we can't
; fold the test to a loop invariant one.
define void @test1_neg(i64 %start) {
; CHECK-LABEL: @test1_neg
entry:
br label %loop
loop:
%indvars.iv = phi i64 [ %start, %entry ], [ %indvars.iv.next, %backedge ]
%indvars.iv.next = add nsw i64 %indvars.iv, 1
%cmp = icmp eq i64 %indvars.iv.next, 25
br i1 %cmp, label %backedge, label %skip
skip:
; prevent flattening, needed to make sure we're testing what we intend
call void @foo()
; CHECK: %cmp1 = icmp slt i64 %indvars.iv, -1
%cmp1 = icmp slt i64 %indvars.iv, -1
br i1 %cmp1, label %for.end, label %backedge
backedge:
; prevent flattening, needed to make sure we're testing what we intend
call void @foo()
br label %loop
for.end: ; preds = %if.end, %entry
ret void
}
; Slightly subtle version of @test4 where the icmp dominates the backedge,
; but the exit branch doesn't.
define void @test2_neg(i64 %start) {
; CHECK-LABEL: @test2_neg
entry:
br label %loop
loop:
%indvars.iv = phi i64 [ %start, %entry ], [ %indvars.iv.next, %backedge ]
%indvars.iv.next = add nsw i64 %indvars.iv, 1
%cmp = icmp eq i64 %indvars.iv.next, 25
; CHECK: %cmp1 = icmp slt i64 %indvars.iv, -1
%cmp1 = icmp slt i64 %indvars.iv, -1
br i1 %cmp, label %backedge, label %skip
skip:
; prevent flattening, needed to make sure we're testing what we intend
call void @foo()
br i1 %cmp1, label %for.end, label %backedge
backedge:
; prevent flattening, needed to make sure we're testing what we intend
call void @foo()
br label %loop
for.end: ; preds = %if.end, %entry
ret void
}
; The branch has to exit the loop if the condition is true
define void @test3_neg(i64 %start) {
; CHECK-LABEL: @test3_neg
entry:
br label %loop
loop:
%indvars.iv = phi i64 [ %start, %entry ], [ %indvars.iv.next, %loop ]
%indvars.iv.next = add nsw i64 %indvars.iv, 1
; CHECK: %cmp1 = icmp slt i64 %indvars.iv, -1
%cmp1 = icmp slt i64 %indvars.iv, -1
br i1 %cmp1, label %loop, label %for.end
for.end: ; preds = %if.end, %entry
ret void
}
define void @test4_neg(i64 %start) {
; CHECK-LABEL: @test4_neg
entry:
br label %loop
loop:
%indvars.iv = phi i64 [ %start, %entry ], [ %indvars.iv.next, %backedge ]
%indvars.iv.next = add nsw i64 %indvars.iv, 1
%cmp = icmp eq i64 %indvars.iv.next, 25
br i1 %cmp, label %backedge, label %for.end
backedge:
; prevent flattening, needed to make sure we're testing what we intend
call void @foo()
; CHECK: %cmp1 = icmp sgt i64 %indvars.iv, -1
%cmp1 = icmp sgt i64 %indvars.iv, -1
; %cmp1 can be made loop invariant only if the branch below goes to
; %the header when %cmp1 is true.
br i1 %cmp1, label %for.end, label %loop
for.end: ; preds = %if.end, %entry
ret void
}
define void @test5_neg(i64 %start, i64 %inc) {
; CHECK-LABEL: @test5_neg
entry:
br label %loop
loop:
%indvars.iv = phi i64 [ %start, %entry ], [ %indvars.iv.next, %loop ]
%indvars.iv.next = add nsw i64 %indvars.iv, %inc
; CHECK: %cmp1 = icmp slt i64 %indvars.iv, -1
%cmp1 = icmp slt i64 %indvars.iv, -1
br i1 %cmp1, label %for.end, label %loop
for.end: ; preds = %if.end, %entry
ret void
}
define void @test8(i64 %start, i64* %inc_ptr) {
; CHECK-LABEL: @test8
entry:
%inc = load i64, i64* %inc_ptr, !range !1
%ok = icmp sge i64 %inc, 0
br i1 %ok, label %loop, label %for.end
loop:
%indvars.iv = phi i64 [ %start, %entry ], [ %indvars.iv.next, %loop ]
%indvars.iv.next = add nsw i64 %indvars.iv, %inc
; CHECK: %cmp1 = icmp slt i64 %indvars.iv, -1
%cmp1 = icmp slt i64 %indvars.iv, -1
br i1 %cmp1, label %for.end, label %loop
for.end: ; preds = %if.end, %entry
ret void
}
!1 = !{i64 -1, i64 100}
declare void @foo()