[LoopUnswitch] Add test cases not partially unswitched due to cost.
authorFlorian Hahn <flo@fhahn.com>
Wed, 27 Jan 2021 12:24:13 +0000 (12:24 +0000)
committerFlorian Hahn <flo@fhahn.com>
Wed, 27 Jan 2021 13:10:33 +0000 (13:10 +0000)
This pre-commits tests for D95468.

llvm/test/Transforms/LoopUnswitch/partial-unswitch-cost.ll [new file with mode: 0644]

diff --git a/llvm/test/Transforms/LoopUnswitch/partial-unswitch-cost.ll b/llvm/test/Transforms/LoopUnswitch/partial-unswitch-cost.ll
new file mode 100644 (file)
index 0000000..6c93730
--- /dev/null
@@ -0,0 +1,402 @@
+; RUN: opt -loop-unswitch -loop-unswitch-threshold=10 -verify-dom-info -verify-memoryssa -S -enable-new-pm=0 %s | FileCheck %s
+
+declare void @clobber()
+
+; Test cases for partial unswitching, where the regular cost-model overestimates
+; the cost of unswitching, because it misses the fact that the unswitched paths
+; are no-ops.
+
+
+define i32 @no_partial_unswitch_size_too_large_no_mustprogress(i32* %ptr, i32 %N) {
+; CHECK-LABEL: @no_partial_unswitch_size_too_large_no_mustprogress
+; CHECK-LABEL: entry:
+; CHECK-NEXT:   br label %loop.header
+;
+entry:
+  br label %loop.header
+
+loop.header:
+  %iv = phi i32 [ 0, %entry ], [ %iv.next, %loop.latch ]
+  %lv = load i32, i32* %ptr
+  %sc = icmp eq i32 %lv, 100
+  br i1 %sc, label %noclobber, label %clobber
+
+noclobber:
+  br label %loop.latch
+
+clobber:
+  call void @clobber()
+  call void @clobber()
+  call void @clobber()
+  call void @clobber()
+  call void @clobber()
+  call void @clobber()
+  call void @clobber()
+  call void @clobber()
+  call void @clobber()
+  br label %loop.latch
+
+loop.latch:
+  %c = icmp ult i32 %iv, %N
+  %iv.next = add i32 %iv, 1
+  br i1 %c, label %loop.header, label %exit
+
+exit:
+  ret i32 10
+}
+
+define i32 @partial_unswitch_shortcut_mustprogress(i32* %ptr, i32 %N) mustprogress {
+; CHECK-LABEL: @partial_unswitch_shortcut_mustprogress
+; CHECK-LABEL: entry:
+; CHECK-NEXT:   br label %loop.header
+;
+entry:
+  br label %loop.header
+
+loop.header:
+  %iv = phi i32 [ 0, %entry ], [ %iv.next, %loop.latch ]
+  %lv = load i32, i32* %ptr
+  %sc = icmp eq i32 %lv, 100
+  br i1 %sc, label %noclobber, label %clobber
+
+noclobber:
+  br label %loop.latch
+
+clobber:
+  call void @clobber()
+  call void @clobber()
+  call void @clobber()
+  call void @clobber()
+  call void @clobber()
+  call void @clobber()
+  call void @clobber()
+  call void @clobber()
+  call void @clobber()
+  br label %loop.latch
+
+loop.latch:
+  %c = icmp ult i32 %iv, %N
+  %iv.next = add i32 %iv, 1
+  br i1 %c, label %loop.header, label %exit
+
+exit:
+  ret i32 10
+}
+
+define i32 @partial_unswitch_shortcut_mustprogress_single_exit_on_path(i32* %ptr, i32 %N) mustprogress {
+; CHECK-LABEL: @partial_unswitch_shortcut_mustprogress_single_exit_on_path
+; CHECK-LABEL: entry:
+; CHECK-NEXT:   br label %loop.header
+;
+entry:
+  br label %loop.header
+
+loop.header:
+  %iv = phi i32 [ 0, %entry ], [ %iv.next, %loop.latch ]
+  %lv = load i32, i32* %ptr
+  %sc = icmp eq i32 %lv, 100
+  br i1 %sc, label %noclobber, label %clobber
+
+noclobber:
+  %c.1 = icmp ult i32 %iv, 123
+  br i1 %c.1, label %loop.latch, label %exit.1
+
+clobber:
+  call void @clobber()
+  call void @clobber()
+  call void @clobber()
+  call void @clobber()
+  call void @clobber()
+  call void @clobber()
+  call void @clobber()
+  call void @clobber()
+  call void @clobber()
+  %c = icmp ult i32 %iv, %N
+  br i1 %c, label %loop.latch, label %exit.2
+
+loop.latch:
+  %iv.next = add i32 %iv, 1
+  br label %loop.header
+
+exit.1:
+  ret i32 10
+
+exit.2:
+  ret i32 10
+}
+
+define i32 @no_partial_unswitch_shortcut_mustprogress_no_exit_on_path(i32* %ptr, i32 %N) mustprogress {
+; CHECK-LABEL: @no_partial_unswitch_shortcut_mustprogress_no_exit_on_path
+; CHECK-LABEL: entry:
+; CHECK-NEXT:   br label %loop.header
+;
+entry:
+  br label %loop.header
+
+loop.header:
+  %iv = phi i32 [ 0, %entry ], [ %iv.next, %loop.latch ]
+  %lv = load i32, i32* %ptr
+  %sc = icmp eq i32 %lv, 100
+  br i1 %sc, label %noclobber, label %clobber
+
+noclobber:
+  br label %loop.latch
+
+clobber:
+  call void @clobber()
+  call void @clobber()
+  call void @clobber()
+  call void @clobber()
+  call void @clobber()
+  call void @clobber()
+  call void @clobber()
+  call void @clobber()
+  call void @clobber()
+  %c = icmp ult i32 %iv, %N
+  br i1 %c, label %loop.latch, label %exit
+
+loop.latch:
+  %iv.next = add i32 %iv, 1
+  br label %loop.header
+
+exit:
+  ret i32 10
+}
+
+define i32 @no_partial_unswitch_shortcut_mustprogress_exit_value_used(i32* %ptr, i32 %N) mustprogress {
+; CHECK-LABEL: @no_partial_unswitch_shortcut_mustprogress_exit_value_use
+; CHECK-LABEL: entry:
+; CHECK-NEXT:   br label %loop.header
+;
+entry:
+  br label %loop.header
+
+loop.header:
+  %iv = phi i32 [ 0, %entry ], [ %iv.next, %loop.latch ]
+  %red = phi i32 [ 0, %entry ], [ %red.next, %loop.latch ]
+  %lv = load i32, i32* %ptr
+  %sc = icmp eq i32 %lv, 100
+  br i1 %sc, label %noclobber, label %clobber
+
+noclobber:
+  %red.add = add i32 %red, %lv
+  br label %loop.latch
+
+clobber:
+  %red.mul = mul i32 %red, %lv
+  call void @clobber()
+  call void @clobber()
+  call void @clobber()
+  call void @clobber()
+  call void @clobber()
+  call void @clobber()
+  call void @clobber()
+  call void @clobber()
+  call void @clobber()
+  br label %loop.latch
+
+loop.latch:
+  %red.next = phi i32 [ %red.add, %noclobber ], [ %red.mul, %clobber ]
+  %c = icmp ult i32 %iv, %N
+  %iv.next = add i32 %iv, 1
+  br i1 %c, label %loop.header, label %exit
+
+exit:
+  ret i32 %red.next
+}
+
+define i32 @partial_unswitch_shortcut_multiple_exiting_blocks(i32* %ptr, i32 %N, i1 %ec.1) mustprogress {
+; CHECK-LABEL: @partial_unswitch_shortcut_multiple_exiting_blocks
+; CHECK-LABEL: entry:
+; CHECK-NEXT:   br label %loop.header
+;
+entry:
+  br label %loop.header
+
+loop.header:
+  %iv = phi i32 [ 0, %entry ], [ %iv.next, %loop.latch ]
+  %lv = load i32, i32* %ptr
+  %sc = icmp eq i32 %lv, 100
+  br i1 %sc, label %noclobber, label %clobber
+
+noclobber:
+  br i1 %ec.1, label %loop.latch, label %exit
+
+clobber:
+  call void @clobber()
+  call void @clobber()
+  call void @clobber()
+  call void @clobber()
+  call void @clobber()
+  call void @clobber()
+  call void @clobber()
+  call void @clobber()
+  call void @clobber()
+  br label %loop.latch
+
+loop.latch:
+  %c = icmp ult i32 %iv, %N
+  %iv.next = add i32 %iv, 1
+  br i1 %c, label %loop.header, label %exit
+
+exit:
+  ret i32 10
+}
+
+define i32 @no_partial_unswitch_shortcut_multiple_exit_blocks(i32* %ptr, i32 %N, i1 %ec.1) mustprogress {
+; CHECK-LABEL: @no_partial_unswitch_shortcut_multiple_exit_blocks
+; CHECK-LABEL: entry:
+; CHECK-NEXT:   br label %loop.header
+;
+entry:
+  br label %loop.header
+
+loop.header:
+  %iv = phi i32 [ 0, %entry ], [ %iv.next, %loop.latch ]
+  %lv = load i32, i32* %ptr
+  %sc = icmp eq i32 %lv, 100
+  br i1 %sc, label %noclobber, label %clobber
+
+noclobber:
+  br i1 %ec.1, label %loop.latch, label %exit.2
+
+clobber:
+  call void @clobber()
+  call void @clobber()
+  call void @clobber()
+  call void @clobber()
+  call void @clobber()
+  call void @clobber()
+  call void @clobber()
+  call void @clobber()
+  call void @clobber()
+  br label %loop.latch
+
+loop.latch:
+  %c = icmp ult i32 %iv, %N
+  %iv.next = add i32 %iv, 1
+  br i1 %c, label %loop.header, label %exit.1
+
+exit.1:
+  ret i32 10
+
+exit.2:
+  ret i32 20
+}
+
+define i32 @no_partial_unswitch_shortcut_mustprogress_store(i32* %ptr, i32* noalias %dst, i32 %N) mustprogress {
+; CHECK-LABEL: @no_partial_unswitch_shortcut_mustprogress_store
+; CHECK-LABEL: entry:
+; CHECK-NEXT:   br label %loop.header
+;
+entry:
+  br label %loop.header
+
+loop.header:
+  %iv = phi i32 [ 0, %entry ], [ %iv.next, %loop.latch ]
+  %lv = load i32, i32* %ptr
+  %sc = icmp eq i32 %lv, 100
+  br i1 %sc, label %noclobber, label %clobber
+
+noclobber:
+  store i32 0, i32* %dst
+  br label %loop.latch
+
+clobber:
+  call void @clobber()
+  call void @clobber()
+  call void @clobber()
+  call void @clobber()
+  call void @clobber()
+  call void @clobber()
+  call void @clobber()
+  call void @clobber()
+  call void @clobber()
+  br label %loop.latch
+
+loop.latch:
+  %c = icmp ult i32 %iv, %N
+  %iv.next = add i32 %iv, 1
+  br i1 %c, label %loop.header, label %exit
+
+exit:
+  ret i32 10
+}
+
+define i32 @no_partial_unswitch_shortcut_mustprogress_store2(i32* %ptr, i32* noalias %dst, i32 %N) mustprogress {
+; CHECK-LABEL: @no_partial_unswitch_shortcut_mustprogress_store
+; CHECK-LABEL: entry:
+; CHECK-NEXT:   br label %loop.header
+;
+entry:
+  br label %loop.header
+
+loop.header:
+  %iv = phi i32 [ 0, %entry ], [ %iv.next, %loop.latch ]
+  %lv = load i32, i32* %ptr
+  %sc = icmp eq i32 %lv, 100
+  br i1 %sc, label %noclobber, label %clobber
+
+noclobber:
+  br label %loop.latch
+
+clobber:
+  call void @clobber()
+  call void @clobber()
+  call void @clobber()
+  call void @clobber()
+  call void @clobber()
+  call void @clobber()
+  call void @clobber()
+  call void @clobber()
+  call void @clobber()
+  br label %loop.latch
+
+loop.latch:
+  store i32 0, i32* %dst
+  %c = icmp ult i32 %iv, %N
+  %iv.next = add i32 %iv, 1
+  br i1 %c, label %loop.header, label %exit
+
+exit:
+  ret i32 10
+}
+
+define i32 @no_partial_unswitch_shortcut_mustprogress_store3(i32* %ptr, i32* noalias %dst, i32 %N) mustprogress {
+; CHECK-LABEL: @no_partial_unswitch_shortcut_mustprogress_store
+; CHECK-LABEL: entry:
+; CHECK-NEXT:   br label %loop.header
+;
+entry:
+  br label %loop.header
+
+loop.header:
+  %iv = phi i32 [ 0, %entry ], [ %iv.next, %loop.latch ]
+  store i32 0, i32* %dst
+  %lv = load i32, i32* %ptr
+  %sc = icmp eq i32 %lv, 100
+  br i1 %sc, label %noclobber, label %clobber
+
+noclobber:
+  br label %loop.latch
+
+clobber:
+  call void @clobber()
+  call void @clobber()
+  call void @clobber()
+  call void @clobber()
+  call void @clobber()
+  call void @clobber()
+  call void @clobber()
+  call void @clobber()
+  call void @clobber()
+  br label %loop.latch
+
+loop.latch:
+  %c = icmp ult i32 %iv, %N
+  %iv.next = add i32 %iv, 1
+  br i1 %c, label %loop.header, label %exit
+
+exit:
+  ret i32 10
+}