]> granicus.if.org Git - llvm/commitdiff
[LoopDeletion] (cleanup, NFC) Make this test actually test what it
authorChandler Carruth <chandlerc@gmail.com>
Wed, 18 Jan 2017 02:29:35 +0000 (02:29 +0000)
committerChandler Carruth <chandlerc@gmail.com>
Wed, 18 Jan 2017 02:29:35 +0000 (02:29 +0000)
claims to test.

LoopSimplify was unifying the multiple exits in this test case, making
it never even test the multiple exit handling of LoopDeletion. Doh.

Now it works (thanks to a great idea from mkuper) and will fail if we
ever change something to make it stop working.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@292331 91177308-0d34-0410-b5e6-96231b3b80d8

test/Transforms/LoopDeletion/multiple-exits.ll

index dcf79057db541d96482a8ecc79df310c42f109c9..ad9a30601f328414f2aed79a2dd50141a0cd5890 100644 (file)
-; RUN: opt < %s -loop-deletion -S | FileCheck %s
+; Checks whether dead loops with multiple exits can be eliminated.
+; Note that we loop simplify and LCSSA over the test cases to make sure the
+; critical components remain after those passes and are visible to the loop
+; deletion pass.
+;
+; RUN: opt < %s -loop-simplify -lcssa -S | FileCheck %s --check-prefixes=CHECK,BEFORE
+; RUN: opt < %s -loop-deletion -S | FileCheck %s --check-prefixes=CHECK,AFTER
 
-; Checks whether dead loops with multiple exits can be eliminated
 
 define void @foo(i64 %n, i64 %m) nounwind {
 ; CHECK-LABEL: @foo(
-; CHECK:      entry:
-; CHECK-NEXT:   br label %return
 
-; CHECK:      return:
-; CHECK-NEXT:   ret void
 entry:
   br label %bb
+; CHECK:       entry:
+; BEFORE-NEXT:   br label %bb
+; AFTER-NEXT:    br label %return
 
 bb:
   %x.0 = phi i64 [ 0, %entry ], [ %t0, %bb2 ]
   %t0 = add i64 %x.0, 1
   %t1 = icmp slt i64 %x.0, %n
   br i1 %t1, label %bb2, label %return
+; BEFORE:      bb:
+; BEFORE:        br i1 {{.*}}, label %bb2, label %return
+; AFTER-NOT:   bb:
+; AFTER-NOT:     br
+
 bb2:
   %t2 = icmp slt i64 %x.0, %m
   br i1 %t1, label %bb, label %return
+; BEFORE:      bb2:
+; BEFORE:        br i1 {{.*}}, label %bb, label %return
+; AFTER-NOT:   bb2:
+; AFTER-NOT:     br
 
 return:
   ret void
+; CHECK:       return:
+; CHECK-NEXT:    ret void
 }
 
-define i64 @bar(i64 %n, i64 %m) nounwind {
-; CHECK-LABEL:  @bar(
-; CHECK: entry:
-; CHECK-NEXT:  br label %return
-
-; CHECK: return:
-; CHECK-NEXT:  ret i64 10
+define i64 @bar(i64 %n, i64 %m, i64 %maybe_zero) nounwind {
+; CHECK-LABEL: @bar(
 
 entry:
   br label %bb
+; CHECK:       entry:
+; BEFORE-NEXT:   br label %bb
+; AFTER-NEXT:    br label %return
 
 bb:
   %x.0 = phi i64 [ 0, %entry ], [ %t0, %bb3 ]
   %t0 = add i64 %x.0, 1
   %t1 = icmp slt i64 %x.0, %n
   br i1 %t1, label %bb2, label %return
+; BEFORE:      bb:
+; BEFORE:        br i1 {{.*}}, label %bb2, label %return
+; AFTER-NOT:   bb:
+; AFTER-NOT:     br
+
 bb2:
   %t2 = icmp slt i64 %x.0, %m
+  ; This unused division prevents unifying this loop exit path with others
+  ; because it can be deleted but cannot be hoisted.
+  %unused1 = udiv i64 42, %maybe_zero
   br i1 %t2, label %bb3, label %return
+; BEFORE:      bb2:
+; BEFORE:        br i1 {{.*}}, label %bb3, label %return
+; AFTER-NOT:   bb2:
+; AFTER-NOT:     br
+
 bb3:
   %t3 = icmp slt i64 %x.0, %m
+  ; This unused division prevents unifying this loop exit path with others
+  ; because it can be deleted but cannot be hoisted.
+  %unused2 = sdiv i64 42, %maybe_zero
   br i1 %t3, label %bb, label %return
+; BEFORE:      bb3:
+; BEFORE:        br i1 {{.*}}, label %bb, label %return
+; AFTER-NOT:   bb3:
+; AFTER-NOT:     br
 
 return:
   %x.lcssa = phi i64 [ 10, %bb ], [ 10, %bb2 ], [ 10, %bb3 ]
   ret i64 %x.lcssa
+; CHECK:       return:
+; BEFORE-NEXT:   %[[X:.*]] = phi i64 [ 10, %bb ], [ 10, %bb2 ], [ 10, %bb3 ]
+; AFTER-NEXT:    %[[X:.*]] = phi i64 [ 10, %entry ]
+; CHECK-NEXT:    ret i64 %[[X]]
 }
 
-define i64 @baz(i64 %n, i64 %m) nounwind {
+; This function has a loop which looks like @bar's but that cannot be deleted
+; because which path we exit through determines which value is selected.
+define i64 @baz(i64 %n, i64 %m, i64 %maybe_zero) nounwind {
 ; CHECK-LABEL:  @baz(
-; CHECK: return:
-; CHECK-NEXT:  %x.lcssa = phi i64 [ 12, %bb ], [ 10, %bb2 ]
-; CHECK-NEXT:  ret i64 %x.lcssa
 
 entry:
   br label %bb
+; CHECK:       entry:
+; CHECK-NEXT:    br label %bb
 
 bb:
   %x.0 = phi i64 [ 0, %entry ], [ %t0, %bb3 ]
   %t0 = add i64 %x.0, 1
   %t1 = icmp slt i64 %x.0, %n
   br i1 %t1, label %bb2, label %return
+; CHECK:       bb:
+; CHECK:         br i1 {{.*}}, label %bb2, label %return
+
 bb2:
   %t2 = icmp slt i64 %x.0, %m
+  ; This unused division prevents unifying this loop exit path with others
+  ; because it can be deleted but cannot be hoisted.
+  %unused1 = udiv i64 42, %maybe_zero
   br i1 %t2, label %bb3, label %return
+; CHECK:       bb2:
+; CHECK:         br i1 {{.*}}, label %bb3, label %return
+
 bb3:
   %t3 = icmp slt i64 %x.0, %m
+  ; This unused division prevents unifying this loop exit path with others
+  ; because it can be deleted but cannot be hoisted.
+  %unused2 = sdiv i64 42, %maybe_zero
   br i1 %t3, label %bb, label %return
+; CHECK:       bb3:
+; CHECK:         br i1 {{.*}}, label %bb, label %return
 
 return:
   %x.lcssa = phi i64 [ 12, %bb ], [ 10, %bb2 ], [ 10, %bb3 ]
   ret i64 %x.lcssa
+; CHECK: return:
+; CHECK-NEXT:  %[[X:.*]] = phi i64 [ 12, %bb ], [ 10, %bb2 ], [ 10, %bb3 ]
+; CHECK-NEXT:  ret i64 %[[X]]
 }