blob: 2061a9aac042e9fcc46db77a771d5d8167c09193 [file] [edit]
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 6
; RUN: opt < %s -passes='unify-loop-exits' -S | FileCheck %s
define void @loop_1_callbr(i1 %PredEntry, i1 %PredB, i1 %PredC, i1 %PredD) {
; CHECK-LABEL: define void @loop_1_callbr(
; CHECK-SAME: i1 [[PREDENTRY:%.*]], i1 [[PREDB:%.*]], i1 [[PREDC:%.*]], i1 [[PREDD:%.*]]) {
; CHECK-NEXT: [[ENTRY:.*:]]
; CHECK-NEXT: br i1 [[PREDENTRY]], label %[[A:.*]], label %[[G:.*]]
; CHECK: [[A]]:
; CHECK-NEXT: br label %[[B:.*]]
; CHECK: [[B]]:
; CHECK-NEXT: callbr void asm "", "r,!i,!i"(i1 [[PREDB]])
; CHECK-NEXT: to label %[[C:.*]] [label %[[B_TARGET_E:.*]], label %[[B_TARGET_E]]]
; CHECK: [[C]]:
; CHECK-NEXT: callbr void asm "", "r,!i"(i1 [[PREDC]])
; CHECK-NEXT: to label %[[D:.*]] [label %[[C_TARGET_F:.*]]]
; CHECK: [[D]]:
; CHECK-NEXT: callbr void asm "", "r,!i"(i1 [[PREDD]])
; CHECK-NEXT: to label %[[A]] [label %[[D_TARGET_F:.*]]]
; CHECK: [[E:.*]]:
; CHECK-NEXT: br label %[[EXIT:.*]]
; CHECK: [[F:.*]]:
; CHECK-NEXT: br label %[[EXIT]]
; CHECK: [[G]]:
; CHECK-NEXT: br label %[[F]]
; CHECK: [[EXIT]]:
; CHECK-NEXT: ret void
; CHECK: [[B_TARGET_E]]:
; CHECK-NEXT: br label %[[LOOP_EXIT_GUARD:.*]]
; CHECK: [[C_TARGET_F]]:
; CHECK-NEXT: br label %[[LOOP_EXIT_GUARD]]
; CHECK: [[D_TARGET_F]]:
; CHECK-NEXT: br label %[[LOOP_EXIT_GUARD]]
; CHECK: [[LOOP_EXIT_GUARD]]:
; CHECK-NEXT: [[GUARD_E:%.*]] = phi i1 [ true, %[[B_TARGET_E]] ], [ false, %[[C_TARGET_F]] ], [ false, %[[D_TARGET_F]] ]
; CHECK-NEXT: br i1 [[GUARD_E]], label %[[E]], label %[[F]]
;
entry:
br i1 %PredEntry, label %A, label %G
A:
br label %B
B:
callbr void asm "", "r,!i,!i"(i1 %PredB) to label %C [label %E, label %E]
C:
callbr void asm "", "r,!i"(i1 %PredC) to label %D [label %F]
D:
callbr void asm "", "r,!i"(i1 %PredD) to label %A [label %F]
E:
br label %exit
F:
br label %exit
G:
br label %F
exit:
ret void
}
define void @multiedge_both_callbr(i1 %Pred) {
; CHECK-LABEL: define void @multiedge_both_callbr(
; CHECK-SAME: i1 [[PRED:%.*]]) {
; CHECK-NEXT: [[ENTRY:.*:]]
; CHECK-NEXT: br label %[[LOOP:.*]]
; CHECK: [[LOOP]]:
; CHECK-NEXT: callbr void asm "", "r,!i"(i1 [[PRED]])
; CHECK-NEXT: to label %[[LOOP_NEXT:.*]] [label %[[LOOP_NEXT]]]
; CHECK: [[LOOP_NEXT]]:
; CHECK-NEXT: [[PHI_INTERNAL:%.*]] = phi i32 [ 1, %[[LOOP]] ], [ 1, %[[LOOP]] ]
; CHECK-NEXT: callbr void asm "", "r,!i,!i"(i1 [[PRED]])
; CHECK-NEXT: to label %[[LOOP]] [label %[[LOOP_NEXT_TARGET_EXIT:.*]], label %[[LOOP_NEXT_TARGET_EXIT]]]
; CHECK: [[EXIT:.*]]:
; CHECK-NEXT: [[PHI_EXTERNAL:%.*]] = phi i32 [ 2, %[[LOOP_NEXT_TARGET_EXIT]] ]
; CHECK-NEXT: ret void
; CHECK: [[LOOP_NEXT_TARGET_EXIT]]:
; CHECK-NEXT: br label %[[EXIT]]
;
entry:
br label %loop
loop:
callbr void asm "", "r,!i"(i1 %Pred) to label %loop.next [label %loop.next]
loop.next:
%phi.internal = phi i32 [ 1, %loop ], [ 1, %loop ]
callbr void asm "", "r,!i,!i"(i1 %Pred) to label %loop [label %exit, label %exit]
exit:
%phi.external = phi i32 [ 2, %loop.next ], [ 2, %loop.next ]
ret void
}
define i32 @multiedge_restore_ssa_callbr() {
; CHECK-LABEL: define i32 @multiedge_restore_ssa_callbr() {
; CHECK-NEXT: [[ENTRY:.*:]]
; CHECK-NEXT: br label %[[HEADER:.*]]
; CHECK: [[HEADER]]:
; CHECK-NEXT: [[VAL:%.*]] = add i32 0, 0
; CHECK-NEXT: callbr void asm "", "r,!i,!i"(i1 false)
; CHECK-NEXT: to label %[[HEADER_TARGET_EXIT1:.*]] [label %[[HEADER_TARGET_COMMON_RET:.*]], label %[[SECOND_EXITING:.*]]]
; CHECK: [[SECOND_EXITING]]:
; CHECK-NEXT: callbr void asm "", "r,!i,!i"(i1 false)
; CHECK-NEXT: to label %[[HEADER]] [label %[[SECOND_EXITING_TARGET_EXIT1:.*]], label %[[SECOND_EXITING_TARGET_COMMON_RET:.*]]]
; CHECK: [[COMMON_RET:.*]]:
; CHECK-NEXT: ret i32 0
; CHECK: [[EXIT1:.*]]:
; CHECK-NEXT: [[USE1:%.*]] = or i32 [[VAL_MOVED:%.*]], 0
; CHECK-NEXT: ret i32 0
; CHECK: [[HEADER_TARGET_EXIT1]]:
; CHECK-NEXT: br label %[[LOOP_EXIT_GUARD:.*]]
; CHECK: [[HEADER_TARGET_COMMON_RET]]:
; CHECK-NEXT: br label %[[LOOP_EXIT_GUARD]]
; CHECK: [[SECOND_EXITING_TARGET_EXIT1]]:
; CHECK-NEXT: br label %[[LOOP_EXIT_GUARD]]
; CHECK: [[SECOND_EXITING_TARGET_COMMON_RET]]:
; CHECK-NEXT: br label %[[LOOP_EXIT_GUARD]]
; CHECK: [[LOOP_EXIT_GUARD]]:
; CHECK-NEXT: [[VAL_MOVED]] = phi i32 [ [[VAL]], %[[HEADER_TARGET_EXIT1]] ], [ [[VAL]], %[[SECOND_EXITING_TARGET_EXIT1]] ], [ [[VAL]], %[[HEADER_TARGET_COMMON_RET]] ], [ [[VAL]], %[[SECOND_EXITING_TARGET_COMMON_RET]] ]
; CHECK-NEXT: [[GUARD_EXIT1:%.*]] = phi i1 [ true, %[[HEADER_TARGET_EXIT1]] ], [ false, %[[HEADER_TARGET_COMMON_RET]] ], [ true, %[[SECOND_EXITING_TARGET_EXIT1]] ], [ false, %[[SECOND_EXITING_TARGET_COMMON_RET]] ]
; CHECK-NEXT: br i1 [[GUARD_EXIT1]], label %[[EXIT1]], label %[[COMMON_RET]]
;
entry:
br label %header
header: ; preds = %second_exiting, %entry
%val = add i32 0, 0
callbr void asm "", "r,!i,!i"(i1 false) to label %exit1 [label %common.ret, label %second_exiting]
second_exiting: ; preds = %header
callbr void asm "", "r,!i,!i"(i1 false) to label %header [label %exit1, label %common.ret]
common.ret: ; preds = %second_exiting, %header
ret i32 0
exit1: ; preds = %second_exiting, %header
%use1 = or i32 %val, 0
ret i32 0
}