forked from OSchip/llvm-project
427 lines
9.9 KiB
LLVM
427 lines
9.9 KiB
LLVM
; 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: [[LV:%[0-9]+]] = load i32, i32* %ptr, align 4
|
|
; CHECK-NEXT: [[C:%[0-9]+]] = icmp eq i32 [[LV]], 100
|
|
; CHECK-NEXT: br i1 [[C]], label %[[CRIT_TO_EXIT:[a-z._]+]], label %[[CRIT_TO_HEADER:[a-z._]+]]
|
|
;
|
|
; CHECK: [[CRIT_TO_HEADER]]:
|
|
; CHECK-NEXT: br label %loop.header
|
|
;
|
|
; CHECK: [[CRIT_TO_EXIT]]:
|
|
; CHECK-NEXT: br label %exit
|
|
;
|
|
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: [[LV:%[0-9]+]] = load i32, i32* %ptr, align 4
|
|
; CHECK-NEXT: [[C:%[0-9]+]] = icmp eq i32 [[LV]], 100
|
|
; CHECK-NEXT: br i1 [[C]], label %[[CRIT_TO_EXIT:.+]], label %[[CRIT_TO_HEADER:[a-z._]+]]
|
|
;
|
|
; CHECK: [[CRIT_TO_HEADER]]:
|
|
; CHECK-NEXT: br label %loop.header
|
|
;
|
|
; CHECK: [[CRIT_TO_EXIT]]:
|
|
; CHECK-NEXT: br label %exit
|
|
;
|
|
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: [[LV:%[0-9]+]] = load i32, i32* %ptr, align 4
|
|
; CHECK-NEXT: [[C:%[0-9]+]] = icmp eq i32 [[LV]], 100
|
|
; CHECK-NEXT: br i1 [[C]], label %[[CRIT_TO_EXIT:.+]], label %[[CRIT_TO_HEADER:[a-z._]+]]
|
|
;
|
|
; CHECK: [[CRIT_TO_HEADER]]:
|
|
; CHECK-NEXT: br label %loop.header
|
|
;
|
|
; CHECK: [[CRIT_TO_EXIT]]:
|
|
; CHECK-NEXT: br label %exit
|
|
;
|
|
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
|
|
}
|