Files
clang-p2996/llvm/test/Transforms/LoopSimplifyCFG/constant-fold-branch.ll
Alina Sbirlea d2d3244363 [LoopSimplifyCFG] Update MemorySSA after r353911.
Summary:
MemorySSA is not properly updated in LoopSimplifyCFG after recent changes. Use SplitBlock utility to resolve that and clear all updates once handleDeadExits is finished.
All updates that follow are removal of edges which are safe to handle via the removeEdge() API.
Also, deleting dead blocks is done correctly as is, i.e. delete from MemorySSA before updating the CFG and DT.

Reviewers: mkazantsev, rtereshin

Subscribers: sanjoy, jlebar, Prazek, george.burgess.iv, llvm-commits

Tags: #llvm

Differential Revision: https://reviews.llvm.org/D58524

llvm-svn: 354613
2019-02-21 19:54:05 +00:00

2775 lines
90 KiB
LLVM

; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
; REQUIRES: asserts
; RUN: opt -S -enable-loop-simplifycfg-term-folding=true -loop-simplifycfg -verify-loop-info -verify-dom-info -verify-loop-lcssa < %s | FileCheck %s
; RUN: opt -S -enable-loop-simplifycfg-term-folding=true -passes='require<domtree>,loop(simplify-cfg)' -verify-loop-info -verify-dom-info -verify-loop-lcssa < %s | FileCheck %s
; RUN: opt -S -enable-loop-simplifycfg-term-folding=true -loop-simplifycfg -enable-mssa-loop-dependency=true -verify-memoryssa -verify-loop-info -verify-dom-info -verify-loop-lcssa < %s | FileCheck %s
target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128-ni:1"
; Make sure that we can eliminate a provably dead backedge.
define i32 @dead_backedge_test_branch_loop(i32 %end) {
; CHECK-LABEL: @dead_backedge_test_branch_loop(
; CHECK-NEXT: preheader:
; CHECK-NEXT: br label [[HEADER:%.*]]
; CHECK: header:
; CHECK-NEXT: [[I:%.*]] = phi i32 [ 0, [[PREHEADER:%.*]] ], [ [[I_BE:%.*]], [[HEADER_BACKEDGE:%.*]] ]
; CHECK-NEXT: [[I_1:%.*]] = add i32 [[I]], 1
; CHECK-NEXT: [[CMP1:%.*]] = icmp slt i32 [[I_1]], 100
; CHECK-NEXT: br i1 [[CMP1]], label [[HEADER_BACKEDGE]], label [[DEAD_BACKEDGE:%.*]]
; CHECK: header.backedge:
; CHECK-NEXT: [[I_BE]] = phi i32 [ [[I_1]], [[HEADER]] ], [ [[I_2:%.*]], [[DEAD_BACKEDGE]] ]
; CHECK-NEXT: br label [[HEADER]]
; CHECK: dead_backedge:
; CHECK-NEXT: [[I_2]] = add i32 [[I_1]], 10
; CHECK-NEXT: br i1 false, label [[HEADER_BACKEDGE]], label [[EXIT:%.*]]
; CHECK: exit:
; CHECK-NEXT: [[I_2_LCSSA:%.*]] = phi i32 [ [[I_2]], [[DEAD_BACKEDGE]] ]
; CHECK-NEXT: ret i32 [[I_2_LCSSA]]
;
preheader:
br label %header
header:
%i = phi i32 [0, %preheader], [%i.1, %header], [%i.2, %dead_backedge]
%i.1 = add i32 %i, 1
%cmp1 = icmp slt i32 %i.1, 100
br i1 %cmp1, label %header, label %dead_backedge
dead_backedge:
%i.2 = add i32 %i.1, 10
br i1 false, label %header, label %exit
exit:
ret i32 %i.2
}
; Make sure that we can eliminate a provably dead backedge with switch.
define i32 @dead_backedge_test_switch_loop(i32 %end) {
; CHECK-LABEL: @dead_backedge_test_switch_loop(
; CHECK-NEXT: preheader:
; CHECK-NEXT: br label [[HEADER:%.*]]
; CHECK: header:
; CHECK-NEXT: [[I:%.*]] = phi i32 [ 0, [[PREHEADER:%.*]] ], [ [[I_BE:%.*]], [[HEADER_BACKEDGE:%.*]] ]
; CHECK-NEXT: [[I_1:%.*]] = add i32 [[I]], 1
; CHECK-NEXT: [[CMP1:%.*]] = icmp slt i32 [[I_1]], 100
; CHECK-NEXT: br i1 [[CMP1]], label [[HEADER_BACKEDGE]], label [[DEAD_BACKEDGE:%.*]]
; CHECK: header.backedge:
; CHECK-NEXT: [[I_BE]] = phi i32 [ [[I_1]], [[HEADER]] ], [ [[I_2:%.*]], [[DEAD_BACKEDGE]] ]
; CHECK-NEXT: br label [[HEADER]]
; CHECK: dead_backedge:
; CHECK-NEXT: [[I_2]] = add i32 [[I_1]], 10
; CHECK-NEXT: switch i32 1, label [[EXIT:%.*]] [
; CHECK-NEXT: i32 0, label [[HEADER_BACKEDGE]]
; CHECK-NEXT: ]
; CHECK: exit:
; CHECK-NEXT: [[I_2_LCSSA:%.*]] = phi i32 [ [[I_2]], [[DEAD_BACKEDGE]] ]
; CHECK-NEXT: ret i32 [[I_2_LCSSA]]
;
preheader:
br label %header
header:
%i = phi i32 [0, %preheader], [%i.1, %header], [%i.2, %dead_backedge]
%i.1 = add i32 %i, 1
%cmp1 = icmp slt i32 %i.1, 100
br i1 %cmp1, label %header, label %dead_backedge
dead_backedge:
%i.2 = add i32 %i.1, 10
switch i32 1, label %exit [i32 0, label %header]
exit:
ret i32 %i.2
}
; Check that we can eliminate a triangle.
define i32 @dead_block_test_branch_loop(i32 %end) {
; CHECK-LABEL: @dead_block_test_branch_loop(
; CHECK-NEXT: preheader:
; CHECK-NEXT: br label [[HEADER:%.*]]
; CHECK: header:
; CHECK-NEXT: [[I:%.*]] = phi i32 [ 0, [[PREHEADER:%.*]] ], [ [[I_INC:%.*]], [[HEADER]] ]
; CHECK-NEXT: [[I_INC]] = add i32 [[I]], 1
; CHECK-NEXT: [[CMP:%.*]] = icmp slt i32 [[I_INC]], [[END:%.*]]
; CHECK-NEXT: br i1 [[CMP]], label [[HEADER]], label [[EXIT:%.*]]
; CHECK: exit:
; CHECK-NEXT: [[I_INC_LCSSA:%.*]] = phi i32 [ [[I_INC]], [[HEADER]] ]
; CHECK-NEXT: ret i32 [[I_INC_LCSSA]]
;
preheader:
br label %header
header:
%i = phi i32 [0, %preheader], [%i.inc, %backedge]
br i1 true, label %backedge, label %dead
dead:
%i.2 = add i32 %i, 1
br label %backedge
backedge:
%i.1 = phi i32 [%i, %header], [%i.2, %dead]
%i.inc = add i32 %i.1, 1
%cmp = icmp slt i32 %i.inc, %end
br i1 %cmp, label %header, label %exit
exit:
ret i32 %i.inc
}
; Check that we can eliminate dead branches of a switch.
define i32 @dead_block_test_switch_loop(i32 %end) {
; CHECK-LABEL: @dead_block_test_switch_loop(
; CHECK-NEXT: preheader:
; CHECK-NEXT: br label [[HEADER:%.*]]
; CHECK: header:
; CHECK-NEXT: [[I:%.*]] = phi i32 [ 0, [[PREHEADER:%.*]] ], [ [[I_INC:%.*]], [[HEADER]] ]
; CHECK-NEXT: [[I_INC]] = add i32 [[I]], 1
; CHECK-NEXT: [[CMP:%.*]] = icmp slt i32 [[I_INC]], [[END:%.*]]
; CHECK-NEXT: br i1 [[CMP]], label [[HEADER]], label [[EXIT:%.*]]
; CHECK: exit:
; CHECK-NEXT: [[I_INC_LCSSA:%.*]] = phi i32 [ [[I_INC]], [[HEADER]] ]
; CHECK-NEXT: ret i32 [[I_INC_LCSSA]]
;
preheader:
br label %header
header:
%i = phi i32 [0, %preheader], [%i.inc, %backedge]
switch i32 1, label %dead [i32 0, label %dead
i32 1, label %backedge
i32 2, label %dead]
dead:
%i.2 = add i32 %i, 1
br label %backedge
backedge:
%i.1 = phi i32 [%i, %header], [%i.2, %dead]
%i.inc = add i32 %i.1, 1
%cmp = icmp slt i32 %i.inc, %end
br i1 %cmp, label %header, label %exit
exit:
ret i32 %i.inc
}
; Check that we can eliminate several dead blocks.
define i32 @dead_block_propogate_test_branch_loop(i32 %end) {
; CHECK-LABEL: @dead_block_propogate_test_branch_loop(
; CHECK-NEXT: preheader:
; CHECK-NEXT: br label [[HEADER:%.*]]
; CHECK: header:
; CHECK-NEXT: [[I:%.*]] = phi i32 [ 0, [[PREHEADER:%.*]] ], [ [[I_INC:%.*]], [[HEADER]] ]
; CHECK-NEXT: [[I_INC]] = add i32 [[I]], 1
; CHECK-NEXT: [[CMP:%.*]] = icmp slt i32 [[I_INC]], [[END:%.*]]
; CHECK-NEXT: br i1 [[CMP]], label [[HEADER]], label [[EXIT:%.*]]
; CHECK: exit:
; CHECK-NEXT: [[I_INC_LCSSA:%.*]] = phi i32 [ [[I_INC]], [[HEADER]] ]
; CHECK-NEXT: ret i32 [[I_INC_LCSSA]]
;
preheader:
br label %header
header:
%i = phi i32 [0, %preheader], [%i.inc, %backedge]
br i1 true, label %backedge, label %dead
dead:
%i.2 = add i32 %i, 1
br label %dummy
dummy:
br label %backedge
backedge:
%i.1 = phi i32 [%i, %header], [%i.2, %dummy]
%i.inc = add i32 %i.1, 1
%cmp = icmp slt i32 %i.inc, %end
br i1 %cmp, label %header, label %exit
exit:
ret i32 %i.inc
}
; Check that we can eliminate several blocks while removing a switch.
define i32 @dead_block_propogate_test_switch_loop(i32 %end) {
; CHECK-LABEL: @dead_block_propogate_test_switch_loop(
; CHECK-NEXT: preheader:
; CHECK-NEXT: br label [[HEADER:%.*]]
; CHECK: header:
; CHECK-NEXT: [[I:%.*]] = phi i32 [ 0, [[PREHEADER:%.*]] ], [ [[I_INC:%.*]], [[HEADER]] ]
; CHECK-NEXT: [[I_INC]] = add i32 [[I]], 1
; CHECK-NEXT: [[CMP:%.*]] = icmp slt i32 [[I_INC]], [[END:%.*]]
; CHECK-NEXT: br i1 [[CMP]], label [[HEADER]], label [[EXIT:%.*]]
; CHECK: exit:
; CHECK-NEXT: [[I_INC_LCSSA:%.*]] = phi i32 [ [[I_INC]], [[HEADER]] ]
; CHECK-NEXT: ret i32 [[I_INC_LCSSA]]
;
preheader:
br label %header
header:
%i = phi i32 [0, %preheader], [%i.inc, %backedge]
switch i32 1, label %dead [i32 0, label %dead
i32 1, label %backedge
i32 2, label %dead]
dead:
%i.2 = add i32 %i, 1
br label %dummy
dummy:
br label %backedge
backedge:
%i.1 = phi i32 [%i, %header], [%i.2, %dummy]
%i.inc = add i32 %i.1, 1
%cmp = icmp slt i32 %i.inc, %end
br i1 %cmp, label %header, label %exit
exit:
ret i32 %i.inc
}
; Check that we preserve static reachibility of a dead exit block while deleting
; a branch.
define i32 @dead_exit_test_branch_loop(i32 %end) {
; CHECK-LABEL: @dead_exit_test_branch_loop(
; CHECK-NEXT: preheader:
; CHECK-NEXT: switch i32 0, label [[PREHEADER_SPLIT:%.*]] [
; CHECK-NEXT: i32 1, label [[DEAD:%.*]]
; CHECK-NEXT: ]
; CHECK: preheader.split:
; CHECK-NEXT: br label [[HEADER:%.*]]
; CHECK: header:
; CHECK-NEXT: [[I:%.*]] = phi i32 [ 0, [[PREHEADER_SPLIT]] ], [ [[I_INC:%.*]], [[HEADER]] ]
; CHECK-NEXT: [[I_INC]] = add i32 [[I]], 1
; CHECK-NEXT: [[CMP:%.*]] = icmp slt i32 [[I_INC]], [[END:%.*]]
; CHECK-NEXT: br i1 [[CMP]], label [[HEADER]], label [[EXIT_LOOPEXIT:%.*]]
; CHECK: dead:
; CHECK-NEXT: br label [[DUMMY:%.*]]
; CHECK: dummy:
; CHECK-NEXT: br label [[EXIT:%.*]]
; CHECK: exit.loopexit:
; CHECK-NEXT: [[I_INC_LCSSA:%.*]] = phi i32 [ [[I_INC]], [[HEADER]] ]
; CHECK-NEXT: br label [[EXIT]]
; CHECK: exit:
; CHECK-NEXT: [[I_1:%.*]] = phi i32 [ undef, [[DUMMY]] ], [ [[I_INC_LCSSA]], [[EXIT_LOOPEXIT]] ]
; CHECK-NEXT: ret i32 [[I_1]]
;
preheader:
br label %header
header:
%i = phi i32 [0, %preheader], [%i.inc, %backedge]
br i1 true, label %backedge, label %dead
dead:
br label %dummy
dummy:
br label %exit
backedge:
%i.inc = add i32 %i, 1
%cmp = icmp slt i32 %i.inc, %end
br i1 %cmp, label %header, label %exit
exit:
%i.1 = phi i32 [%i.inc, %backedge], [%i, %dummy]
ret i32 %i.1
}
; Check that we preserve static reachibility of a dead exit block while deleting
; a switch.
define i32 @dead_exit_test_switch_loop(i32 %end) {
; CHECK-LABEL: @dead_exit_test_switch_loop(
; CHECK-NEXT: preheader:
; CHECK-NEXT: switch i32 0, label [[PREHEADER_SPLIT:%.*]] [
; CHECK-NEXT: i32 1, label [[DEAD:%.*]]
; CHECK-NEXT: ]
; CHECK: preheader.split:
; CHECK-NEXT: br label [[HEADER:%.*]]
; CHECK: header:
; CHECK-NEXT: [[I:%.*]] = phi i32 [ 0, [[PREHEADER_SPLIT]] ], [ [[I_INC:%.*]], [[HEADER]] ]
; CHECK-NEXT: [[I_INC]] = add i32 [[I]], 1
; CHECK-NEXT: [[CMP:%.*]] = icmp slt i32 [[I_INC]], [[END:%.*]]
; CHECK-NEXT: br i1 [[CMP]], label [[HEADER]], label [[EXIT_LOOPEXIT:%.*]]
; CHECK: dead:
; CHECK-NEXT: br label [[DUMMY:%.*]]
; CHECK: dummy:
; CHECK-NEXT: br label [[EXIT:%.*]]
; CHECK: exit.loopexit:
; CHECK-NEXT: [[I_INC_LCSSA:%.*]] = phi i32 [ [[I_INC]], [[HEADER]] ]
; CHECK-NEXT: br label [[EXIT]]
; CHECK: exit:
; CHECK-NEXT: [[I_1:%.*]] = phi i32 [ undef, [[DUMMY]] ], [ [[I_INC_LCSSA]], [[EXIT_LOOPEXIT]] ]
; CHECK-NEXT: ret i32 [[I_1]]
;
preheader:
br label %header
header:
%i = phi i32 [0, %preheader], [%i.inc, %backedge]
switch i32 1, label %dead [i32 0, label %dead
i32 1, label %backedge
i32 2, label %dead]
dead:
br label %dummy
dummy:
br label %exit
backedge:
%i.inc = add i32 %i, 1
%cmp = icmp slt i32 %i.inc, %end
br i1 %cmp, label %header, label %exit
exit:
%i.1 = phi i32 [%i.inc, %backedge], [%i, %dummy]
ret i32 %i.1
}
; Check that we can completely eliminate the current loop, branch case.
define i32 @dead_loop_test_branch_loop(i32 %end) {
; CHECK-LABEL: @dead_loop_test_branch_loop(
; CHECK-NEXT: preheader:
; CHECK-NEXT: br label [[HEADER:%.*]]
; CHECK: header:
; CHECK-NEXT: [[I:%.*]] = phi i32 [ 0, [[PREHEADER:%.*]] ], [ [[I_INC:%.*]], [[BACKEDGE:%.*]] ]
; CHECK-NEXT: br i1 true, label [[BACKEDGE]], label [[DEAD:%.*]]
; CHECK: dead:
; CHECK-NEXT: [[I_2:%.*]] = add i32 [[I]], 1
; CHECK-NEXT: br label [[BACKEDGE]]
; CHECK: backedge:
; CHECK-NEXT: [[I_1:%.*]] = phi i32 [ [[I]], [[HEADER]] ], [ [[I_2]], [[DEAD]] ]
; CHECK-NEXT: [[I_INC]] = add i32 [[I_1]], 1
; CHECK-NEXT: [[CMP:%.*]] = icmp slt i32 [[I_INC]], [[END:%.*]]
; CHECK-NEXT: br i1 false, label [[HEADER]], label [[EXIT:%.*]]
; CHECK: exit:
; CHECK-NEXT: [[I_INC_LCSSA:%.*]] = phi i32 [ [[I_INC]], [[BACKEDGE]] ]
; CHECK-NEXT: ret i32 [[I_INC_LCSSA]]
;
preheader:
br label %header
header:
%i = phi i32 [0, %preheader], [%i.inc, %backedge]
br i1 true, label %backedge, label %dead
dead:
%i.2 = add i32 %i, 1
br label %dummy
dummy:
br label %backedge
backedge:
%i.1 = phi i32 [%i, %header], [%i.2, %dummy]
%i.inc = add i32 %i.1, 1
%cmp = icmp slt i32 %i.inc, %end
br i1 false, label %header, label %exit
exit:
ret i32 %i.inc
}
; Check that we can completely eliminate the current loop, switch case.
define i32 @dead_loop_test_switch_loop(i32 %end) {
; CHECK-LABEL: @dead_loop_test_switch_loop(
; CHECK-NEXT: preheader:
; CHECK-NEXT: br label [[HEADER:%.*]]
; CHECK: header:
; CHECK-NEXT: [[I:%.*]] = phi i32 [ 0, [[PREHEADER:%.*]] ], [ [[I_INC:%.*]], [[BACKEDGE:%.*]] ]
; CHECK-NEXT: switch i32 1, label [[DEAD:%.*]] [
; CHECK-NEXT: i32 0, label [[DEAD]]
; CHECK-NEXT: i32 1, label [[BACKEDGE]]
; CHECK-NEXT: i32 2, label [[DEAD]]
; CHECK-NEXT: ]
; CHECK: dead:
; CHECK-NEXT: [[I_2:%.*]] = add i32 [[I]], 1
; CHECK-NEXT: br label [[BACKEDGE]]
; CHECK: backedge:
; CHECK-NEXT: [[I_1:%.*]] = phi i32 [ [[I]], [[HEADER]] ], [ [[I_2]], [[DEAD]] ]
; CHECK-NEXT: [[I_INC]] = add i32 [[I_1]], 1
; CHECK-NEXT: [[CMP:%.*]] = icmp slt i32 [[I_INC]], [[END:%.*]]
; CHECK-NEXT: br i1 false, label [[HEADER]], label [[EXIT:%.*]]
; CHECK: exit:
; CHECK-NEXT: [[I_INC_LCSSA:%.*]] = phi i32 [ [[I_INC]], [[BACKEDGE]] ]
; CHECK-NEXT: ret i32 [[I_INC_LCSSA]]
;
preheader:
br label %header
header:
%i = phi i32 [0, %preheader], [%i.inc, %backedge]
switch i32 1, label %dead [i32 0, label %dead
i32 1, label %backedge
i32 2, label %dead]
dead:
%i.2 = add i32 %i, 1
br label %dummy
dummy:
br label %backedge
backedge:
%i.1 = phi i32 [%i, %header], [%i.2, %dummy]
%i.inc = add i32 %i.1, 1
%cmp = icmp slt i32 %i.inc, %end
br i1 false, label %header, label %exit
exit:
ret i32 %i.inc
}
; Check that we can delete a dead inner loop entirely.
define i32 @dead_sub_loop_test_branch_loop(i32 %end) {
; CHECK-LABEL: @dead_sub_loop_test_branch_loop(
; CHECK-NEXT: preheader:
; CHECK-NEXT: br label [[HEADER:%.*]]
; CHECK: header:
; CHECK-NEXT: [[I:%.*]] = phi i32 [ 0, [[PREHEADER:%.*]] ], [ [[I_INC:%.*]], [[EXIT_A:%.*]] ]
; CHECK-NEXT: br label [[LIVE_LOOP:%.*]]
; CHECK: live_loop:
; CHECK-NEXT: [[A:%.*]] = phi i32 [ 0, [[HEADER]] ], [ [[A_INC:%.*]], [[LIVE_LOOP]] ]
; CHECK-NEXT: [[A_INC]] = add i32 [[A]], 1
; CHECK-NEXT: [[CMP_A:%.*]] = icmp slt i32 [[A_INC]], [[END:%.*]]
; CHECK-NEXT: br i1 [[CMP_A]], label [[LIVE_LOOP]], label [[EXIT_A]]
; CHECK: exit.a:
; CHECK-NEXT: [[I_INC]] = add i32 [[I]], 1
; CHECK-NEXT: [[CMP:%.*]] = icmp slt i32 [[I_INC]], [[END]]
; CHECK-NEXT: br i1 [[CMP]], label [[HEADER]], label [[EXIT:%.*]]
; CHECK: exit:
; CHECK-NEXT: [[I_INC_LCSSA:%.*]] = phi i32 [ [[I_INC]], [[EXIT_A]] ]
; CHECK-NEXT: ret i32 [[I_INC_LCSSA]]
;
preheader:
br label %header
header:
%i = phi i32 [0, %preheader], [%i.inc, %backedge]
br i1 true, label %live_preheader, label %dead_preheader
live_preheader:
br label %live_loop
live_loop:
%a = phi i32 [0, %live_preheader], [%a.inc, %live_loop]
%a.inc = add i32 %a, 1
%cmp.a = icmp slt i32 %a.inc, %end
br i1 %cmp.a, label %live_loop, label %exit.a
exit.a:
br label %backedge
dead_preheader:
br label %dead_loop
dead_loop:
%b = phi i32 [0, %dead_preheader], [%b.inc, %dead_loop]
%b.inc = add i32 %b, 1
%cmp.b = icmp slt i32 %b.inc, %end
br i1 %cmp.b, label %dead_loop, label %exit.b
exit.b:
br label %backedge
backedge:
%i.inc = add i32 %i, 1
%cmp = icmp slt i32 %i.inc, %end
br i1 %cmp, label %header, label %exit
exit:
ret i32 %i.inc
}
define i32 @dead_sub_loop_test_switch_loop(i32 %end) {
; CHECK-LABEL: @dead_sub_loop_test_switch_loop(
; CHECK-NEXT: preheader:
; CHECK-NEXT: br label [[HEADER:%.*]]
; CHECK: header:
; CHECK-NEXT: [[I:%.*]] = phi i32 [ 0, [[PREHEADER:%.*]] ], [ [[I_INC:%.*]], [[EXIT_A:%.*]] ]
; CHECK-NEXT: br label [[LIVE_LOOP:%.*]]
; CHECK: live_loop:
; CHECK-NEXT: [[A:%.*]] = phi i32 [ 0, [[HEADER]] ], [ [[A_INC:%.*]], [[LIVE_LOOP]] ]
; CHECK-NEXT: [[A_INC]] = add i32 [[A]], 1
; CHECK-NEXT: [[CMP_A:%.*]] = icmp slt i32 [[A_INC]], [[END:%.*]]
; CHECK-NEXT: br i1 [[CMP_A]], label [[LIVE_LOOP]], label [[EXIT_A]]
; CHECK: exit.a:
; CHECK-NEXT: [[I_INC]] = add i32 [[I]], 1
; CHECK-NEXT: [[CMP:%.*]] = icmp slt i32 [[I_INC]], [[END]]
; CHECK-NEXT: br i1 [[CMP]], label [[HEADER]], label [[EXIT:%.*]]
; CHECK: exit:
; CHECK-NEXT: [[I_INC_LCSSA:%.*]] = phi i32 [ [[I_INC]], [[EXIT_A]] ]
; CHECK-NEXT: ret i32 [[I_INC_LCSSA]]
;
preheader:
br label %header
header:
%i = phi i32 [0, %preheader], [%i.inc, %backedge]
switch i32 1, label %dead_preheader [i32 0, label %dead_preheader
i32 1, label %live_preheader
i32 2, label %dead_preheader]
live_preheader:
br label %live_loop
live_loop:
%a = phi i32 [0, %live_preheader], [%a.inc, %live_loop]
%a.inc = add i32 %a, 1
%cmp.a = icmp slt i32 %a.inc, %end
br i1 %cmp.a, label %live_loop, label %exit.a
exit.a:
br label %backedge
dead_preheader:
br label %dead_loop
dead_loop:
%b = phi i32 [0, %dead_preheader], [%b.inc, %dead_loop]
%b.inc = add i32 %b, 1
%cmp.b = icmp slt i32 %b.inc, %end
br i1 %cmp.b, label %dead_loop, label %exit.b
exit.b:
br label %backedge
backedge:
%i.inc = add i32 %i, 1
%cmp = icmp slt i32 %i.inc, %end
br i1 %cmp, label %header, label %exit
exit:
ret i32 %i.inc
}
; Check that we preserve static reachability of an exit block even if we prove
; that the loop is infinite. Branch case.
define i32 @inf_loop_test_branch_loop(i32 %end) {
; CHECK-LABEL: @inf_loop_test_branch_loop(
; CHECK-NEXT: preheader:
; CHECK-NEXT: switch i32 0, label [[PREHEADER_SPLIT:%.*]] [
; CHECK-NEXT: i32 1, label [[EXIT:%.*]]
; CHECK-NEXT: ]
; CHECK: preheader.split:
; CHECK-NEXT: br label [[HEADER:%.*]]
; CHECK: header:
; CHECK-NEXT: [[I:%.*]] = phi i32 [ 0, [[PREHEADER_SPLIT]] ], [ [[I_INC:%.*]], [[HEADER]] ]
; CHECK-NEXT: [[I_INC]] = add i32 [[I]], 1
; CHECK-NEXT: [[CMP:%.*]] = icmp slt i32 [[I_INC]], [[END:%.*]]
; CHECK-NEXT: br label [[HEADER]]
; CHECK: exit:
; CHECK-NEXT: ret i32 undef
;
preheader:
br label %header
header:
%i = phi i32 [0, %preheader], [%i.inc, %backedge]
br i1 true, label %backedge, label %dead
dead:
%i.2 = add i32 %i, 1
br label %dummy
dummy:
br label %backedge
backedge:
%i.1 = phi i32 [%i, %header], [%i.2, %dummy]
%i.inc = add i32 %i.1, 1
%cmp = icmp slt i32 %i.inc, %end
br i1 true, label %header, label %exit
exit:
ret i32 %i.inc
}
define i32 @inf_loop_test_switch_loop(i32 %end) {
; CHECK-LABEL: @inf_loop_test_switch_loop(
; CHECK-NEXT: preheader:
; CHECK-NEXT: switch i32 0, label [[PREHEADER_SPLIT:%.*]] [
; CHECK-NEXT: i32 1, label [[EXIT:%.*]]
; CHECK-NEXT: ]
; CHECK: preheader.split:
; CHECK-NEXT: br label [[HEADER:%.*]]
; CHECK: header:
; CHECK-NEXT: [[I:%.*]] = phi i32 [ 0, [[PREHEADER_SPLIT]] ], [ [[I_INC:%.*]], [[HEADER]] ]
; CHECK-NEXT: [[I_INC]] = add i32 [[I]], 1
; CHECK-NEXT: [[CMP:%.*]] = icmp slt i32 [[I_INC]], [[END:%.*]]
; CHECK-NEXT: br label [[HEADER]]
; CHECK: exit:
; CHECK-NEXT: ret i32 undef
;
preheader:
br label %header
header:
%i = phi i32 [0, %preheader], [%i.inc, %backedge]
switch i32 1, label %dead [i32 0, label %dead
i32 1, label %backedge
i32 2, label %dead]
dead:
%i.2 = add i32 %i, 1
br label %dummy
dummy:
br label %backedge
backedge:
%i.1 = phi i32 [%i, %header], [%i.2, %dummy]
%i.inc = add i32 %i.1, 1
%cmp = icmp slt i32 %i.inc, %end
br i1 true, label %header, label %exit
exit:
ret i32 %i.inc
}
; Check that when the block is not actually dead, we don't remove it.
define i32 @live_block_test_branch_loop(i1 %c, i32 %end) {
; CHECK-LABEL: @live_block_test_branch_loop(
; CHECK-NEXT: preheader:
; CHECK-NEXT: br label [[HEADER:%.*]]
; CHECK: header:
; CHECK-NEXT: [[I:%.*]] = phi i32 [ 0, [[PREHEADER:%.*]] ], [ [[I_INC:%.*]], [[BACKEDGE:%.*]] ]
; CHECK-NEXT: br i1 [[C:%.*]], label [[CHECK:%.*]], label [[LIVE:%.*]]
; CHECK: check:
; CHECK-NEXT: br label [[BACKEDGE]]
; CHECK: live:
; CHECK-NEXT: [[I_2:%.*]] = add i32 [[I]], 1
; CHECK-NEXT: br label [[BACKEDGE]]
; CHECK: backedge:
; CHECK-NEXT: [[I_1:%.*]] = phi i32 [ [[I]], [[CHECK]] ], [ [[I_2]], [[LIVE]] ]
; CHECK-NEXT: [[I_INC]] = add i32 [[I_1]], 1
; CHECK-NEXT: [[CMP:%.*]] = icmp slt i32 [[I_INC]], [[END:%.*]]
; CHECK-NEXT: br i1 [[CMP]], label [[HEADER]], label [[EXIT:%.*]]
; CHECK: exit:
; CHECK-NEXT: [[I_INC_LCSSA:%.*]] = phi i32 [ [[I_INC]], [[BACKEDGE]] ]
; CHECK-NEXT: ret i32 [[I_INC_LCSSA]]
;
preheader:
br label %header
header:
%i = phi i32 [0, %preheader], [%i.inc, %backedge]
br i1 %c, label %check, label %live
check:
br i1 true, label %backedge, label %live
live:
%i.2 = add i32 %i, 1
br label %backedge
backedge:
%i.1 = phi i32 [%i, %check], [%i.2, %live]
%i.inc = add i32 %i.1, 1
%cmp = icmp slt i32 %i.inc, %end
br i1 %cmp, label %header, label %exit
exit:
ret i32 %i.inc
}
; Check that when the block is not actually dead, we don't remove it. Version
; with Phi node.
define i32 @live_block_test_branch_loop_phis(i1 %c, i32 %end) {
; CHECK-LABEL: @live_block_test_branch_loop_phis(
; CHECK-NEXT: preheader:
; CHECK-NEXT: br label [[HEADER:%.*]]
; CHECK: header:
; CHECK-NEXT: [[I:%.*]] = phi i32 [ 0, [[PREHEADER:%.*]] ], [ [[I_INC:%.*]], [[BACKEDGE:%.*]] ]
; CHECK-NEXT: br i1 [[C:%.*]], label [[CHECK:%.*]], label [[LIVE:%.*]]
; CHECK: check:
; CHECK-NEXT: br label [[BACKEDGE]]
; CHECK: live:
; CHECK-NEXT: [[I_2:%.*]] = add i32 [[I]], 1
; CHECK-NEXT: br label [[BACKEDGE]]
; CHECK: backedge:
; CHECK-NEXT: [[I_1:%.*]] = phi i32 [ [[I]], [[CHECK]] ], [ [[I_2]], [[LIVE]] ]
; CHECK-NEXT: [[I_INC]] = add i32 [[I_1]], 1
; CHECK-NEXT: [[CMP:%.*]] = icmp slt i32 [[I_INC]], [[END:%.*]]
; CHECK-NEXT: br i1 [[CMP]], label [[HEADER]], label [[EXIT:%.*]]
; CHECK: exit:
; CHECK-NEXT: [[I_INC_LCSSA:%.*]] = phi i32 [ [[I_INC]], [[BACKEDGE]] ]
; CHECK-NEXT: ret i32 [[I_INC_LCSSA]]
;
preheader:
br label %header
header:
%i = phi i32 [0, %preheader], [%i.inc, %backedge]
br i1 %c, label %check, label %live
check:
br i1 true, label %backedge, label %live
live:
%phi = phi i32 [ 1, %header ], [ -1, %check ]
%i.2 = add i32 %i, %phi
br label %backedge
backedge:
%i.1 = phi i32 [%i, %check], [%i.2, %live]
%i.inc = add i32 %i.1, 1
%cmp = icmp slt i32 %i.inc, %end
br i1 %cmp, label %header, label %exit
exit:
ret i32 %i.inc
}
define i32 @live_block_test_switch_loop(i1 %c, i32 %end) {
; CHECK-LABEL: @live_block_test_switch_loop(
; CHECK-NEXT: preheader:
; CHECK-NEXT: br label [[HEADER:%.*]]
; CHECK: header:
; CHECK-NEXT: [[I:%.*]] = phi i32 [ 0, [[PREHEADER:%.*]] ], [ [[I_INC:%.*]], [[BACKEDGE:%.*]] ]
; CHECK-NEXT: br i1 [[C:%.*]], label [[CHECK:%.*]], label [[LIVE:%.*]]
; CHECK: check:
; CHECK-NEXT: br label [[BACKEDGE]]
; CHECK: live:
; CHECK-NEXT: [[I_2:%.*]] = add i32 [[I]], 1
; CHECK-NEXT: br label [[BACKEDGE]]
; CHECK: backedge:
; CHECK-NEXT: [[I_1:%.*]] = phi i32 [ [[I]], [[CHECK]] ], [ [[I_2]], [[LIVE]] ]
; CHECK-NEXT: [[I_INC]] = add i32 [[I_1]], 1
; CHECK-NEXT: [[CMP:%.*]] = icmp slt i32 [[I_INC]], [[END:%.*]]
; CHECK-NEXT: br i1 [[CMP]], label [[HEADER]], label [[EXIT:%.*]]
; CHECK: exit:
; CHECK-NEXT: [[I_INC_LCSSA:%.*]] = phi i32 [ [[I_INC]], [[BACKEDGE]] ]
; CHECK-NEXT: ret i32 [[I_INC_LCSSA]]
;
preheader:
br label %header
header:
%i = phi i32 [0, %preheader], [%i.inc, %backedge]
br i1 %c, label %check, label %live
check:
switch i32 1, label %live [i32 0, label %live
i32 1, label %backedge
i32 2, label %live]
live:
%i.2 = add i32 %i, 1
br label %backedge
backedge:
%i.1 = phi i32 [%i, %check], [%i.2, %live]
%i.inc = add i32 %i.1, 1
%cmp = icmp slt i32 %i.inc, %end
br i1 %cmp, label %header, label %exit
exit:
ret i32 %i.inc
}
define i32 @live_block_test_switch_loop_phis(i1 %c, i32 %end) {
; CHECK-LABEL: @live_block_test_switch_loop_phis(
; CHECK-NEXT: preheader:
; CHECK-NEXT: br label [[HEADER:%.*]]
; CHECK: header:
; CHECK-NEXT: [[I:%.*]] = phi i32 [ 0, [[PREHEADER:%.*]] ], [ [[I_INC:%.*]], [[BACKEDGE:%.*]] ]
; CHECK-NEXT: br i1 [[C:%.*]], label [[CHECK:%.*]], label [[LIVE:%.*]]
; CHECK: check:
; CHECK-NEXT: br label [[BACKEDGE]]
; CHECK: live:
; CHECK-NEXT: [[I_2:%.*]] = add i32 [[I]], 1
; CHECK-NEXT: br label [[BACKEDGE]]
; CHECK: backedge:
; CHECK-NEXT: [[I_1:%.*]] = phi i32 [ [[I]], [[CHECK]] ], [ [[I_2]], [[LIVE]] ]
; CHECK-NEXT: [[I_INC]] = add i32 [[I_1]], 1
; CHECK-NEXT: [[CMP:%.*]] = icmp slt i32 [[I_INC]], [[END:%.*]]
; CHECK-NEXT: br i1 [[CMP]], label [[HEADER]], label [[EXIT:%.*]]
; CHECK: exit:
; CHECK-NEXT: [[I_INC_LCSSA:%.*]] = phi i32 [ [[I_INC]], [[BACKEDGE]] ]
; CHECK-NEXT: ret i32 [[I_INC_LCSSA]]
;
preheader:
br label %header
header:
%i = phi i32 [0, %preheader], [%i.inc, %backedge]
br i1 %c, label %check, label %live
check:
switch i32 1, label %live [i32 0, label %live
i32 1, label %backedge
i32 2, label %live]
live:
%phi = phi i32 [ 1, %header ], [ -1, %check ], [ -1, %check ], [ -1, %check ]
%i.2 = add i32 %i, %phi
br label %backedge
backedge:
%i.1 = phi i32 [%i, %check], [%i.2, %live]
%i.inc = add i32 %i.1, 1
%cmp = icmp slt i32 %i.inc, %end
br i1 %cmp, label %header, label %exit
exit:
ret i32 %i.inc
}
; Check that we can remove part of blocks of inner loop while the loop still
; preserves, in presence of outer loop.
define i32 @partial_sub_loop_test_branch_loop(i32 %end) {
; CHECK-LABEL: @partial_sub_loop_test_branch_loop(
; CHECK-NEXT: entry:
; CHECK-NEXT: br label [[OUTER_HEADER:%.*]]
; CHECK: outer_header:
; CHECK-NEXT: [[J:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[J_INC:%.*]], [[OUTER_BACKEDGE:%.*]] ]
; CHECK-NEXT: br label [[HEADER:%.*]]
; CHECK: header:
; CHECK-NEXT: [[I:%.*]] = phi i32 [ 0, [[OUTER_HEADER]] ], [ [[I_INC:%.*]], [[HEADER]] ]
; CHECK-NEXT: [[I_INC]] = add i32 [[I]], 1
; CHECK-NEXT: [[CMP:%.*]] = icmp slt i32 [[I_INC]], [[END:%.*]]
; CHECK-NEXT: br i1 [[CMP]], label [[HEADER]], label [[OUTER_BACKEDGE]]
; CHECK: outer_backedge:
; CHECK-NEXT: [[I_INC_LCSSA:%.*]] = phi i32 [ [[I_INC]], [[HEADER]] ]
; CHECK-NEXT: [[J_INC]] = add i32 [[J]], 1
; CHECK-NEXT: [[CMP_J:%.*]] = icmp slt i32 [[J_INC]], [[END]]
; CHECK-NEXT: br i1 [[CMP_J]], label [[OUTER_HEADER]], label [[EXIT:%.*]]
; CHECK: exit:
; CHECK-NEXT: [[I_INC_LCSSA_LCSSA:%.*]] = phi i32 [ [[I_INC_LCSSA]], [[OUTER_BACKEDGE]] ]
; CHECK-NEXT: ret i32 [[I_INC_LCSSA_LCSSA]]
;
entry:
br label %outer_header
outer_header:
%j = phi i32 [0, %entry], [%j.inc, %outer_backedge]
br label %preheader
preheader:
br label %header
header:
%i = phi i32 [0, %preheader], [%i.inc, %backedge]
br i1 true, label %backedge, label %dead
dead:
%i.2 = add i32 %i, 1
br label %backedge
backedge:
%i.1 = phi i32 [%i, %header], [%i.2, %dead]
%i.inc = add i32 %i.1, 1
%cmp = icmp slt i32 %i.inc, %end
br i1 %cmp, label %header, label %outer_backedge
outer_backedge:
%j.inc = add i32 %j, 1
%cmp.j = icmp slt i32 %j.inc, %end
br i1 %cmp.j, label %outer_header, label %exit
exit:
ret i32 %i.inc
}
define i32 @partial_sub_loop_test_switch_loop(i32 %end) {
; CHECK-LABEL: @partial_sub_loop_test_switch_loop(
; CHECK-NEXT: entry:
; CHECK-NEXT: br label [[OUTER_HEADER:%.*]]
; CHECK: outer_header:
; CHECK-NEXT: [[J:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[J_INC:%.*]], [[OUTER_BACKEDGE:%.*]] ]
; CHECK-NEXT: br label [[HEADER:%.*]]
; CHECK: header:
; CHECK-NEXT: [[I:%.*]] = phi i32 [ 0, [[OUTER_HEADER]] ], [ [[I_INC:%.*]], [[HEADER]] ]
; CHECK-NEXT: [[I_INC]] = add i32 [[I]], 1
; CHECK-NEXT: [[CMP:%.*]] = icmp slt i32 [[I_INC]], [[END:%.*]]
; CHECK-NEXT: br i1 [[CMP]], label [[HEADER]], label [[OUTER_BACKEDGE]]
; CHECK: outer_backedge:
; CHECK-NEXT: [[I_INC_LCSSA:%.*]] = phi i32 [ [[I_INC]], [[HEADER]] ]
; CHECK-NEXT: [[J_INC]] = add i32 [[J]], 1
; CHECK-NEXT: [[CMP_J:%.*]] = icmp slt i32 [[J_INC]], [[END]]
; CHECK-NEXT: br i1 [[CMP_J]], label [[OUTER_HEADER]], label [[EXIT:%.*]]
; CHECK: exit:
; CHECK-NEXT: [[I_INC_LCSSA_LCSSA:%.*]] = phi i32 [ [[I_INC_LCSSA]], [[OUTER_BACKEDGE]] ]
; CHECK-NEXT: ret i32 [[I_INC_LCSSA_LCSSA]]
;
entry:
br label %outer_header
outer_header:
%j = phi i32 [0, %entry], [%j.inc, %outer_backedge]
br label %preheader
preheader:
br label %header
header:
%i = phi i32 [0, %preheader], [%i.inc, %backedge]
switch i32 1, label %dead [i32 0, label %dead
i32 1, label %backedge
i32 2, label %dead]
dead:
%i.2 = add i32 %i, 1
br label %backedge
backedge:
%i.1 = phi i32 [%i, %header], [%i.2, %dead]
%i.inc = add i32 %i.1, 1
%cmp = icmp slt i32 %i.inc, %end
br i1 %cmp, label %header, label %outer_backedge
outer_backedge:
%j.inc = add i32 %j, 1
%cmp.j = icmp slt i32 %j.inc, %end
br i1 %cmp.j, label %outer_header, label %exit
exit:
ret i32 %i.inc
}
; Check that we can completely delete inner loop and preserve the outer loop.
define i32 @full_sub_loop_test_branch_loop(i32 %end) {
; CHECK-LABEL: @full_sub_loop_test_branch_loop(
; CHECK-NEXT: entry:
; CHECK-NEXT: br label [[OUTER_HEADER:%.*]]
; CHECK: outer_header:
; CHECK-NEXT: [[J:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[J_INC:%.*]], [[OUTER_BACKEDGE:%.*]] ]
; CHECK-NEXT: br label [[HEADER:%.*]]
; CHECK: header:
; CHECK-NEXT: [[I:%.*]] = phi i32 [ 0, [[OUTER_HEADER]] ], [ [[I_INC:%.*]], [[BACKEDGE:%.*]] ]
; CHECK-NEXT: [[MUL:%.*]] = mul i32 [[I]], [[I]]
; CHECK-NEXT: br i1 false, label [[BACKEDGE]], label [[DEAD:%.*]]
; CHECK: dead:
; CHECK-NEXT: [[I_2:%.*]] = add i32 [[I]], 1
; CHECK-NEXT: br label [[BACKEDGE]]
; CHECK: backedge:
; CHECK-NEXT: [[I_1:%.*]] = phi i32 [ [[I]], [[HEADER]] ], [ [[I_2]], [[DEAD]] ]
; CHECK-NEXT: [[I_INC]] = add i32 [[I_1]], 1
; CHECK-NEXT: br i1 false, label [[HEADER]], label [[OUTER_BACKEDGE]]
; CHECK: outer_backedge:
; CHECK-NEXT: [[I_INC_LCSSA:%.*]] = phi i32 [ [[I_INC]], [[BACKEDGE]] ]
; CHECK-NEXT: [[J_INC]] = add i32 [[J]], 1
; CHECK-NEXT: [[CMP_J:%.*]] = icmp slt i32 [[J_INC]], [[END:%.*]]
; CHECK-NEXT: br i1 [[CMP_J]], label [[OUTER_HEADER]], label [[EXIT:%.*]]
; CHECK: exit:
; CHECK-NEXT: [[I_INC_LCSSA_LCSSA:%.*]] = phi i32 [ [[I_INC_LCSSA]], [[OUTER_BACKEDGE]] ]
; CHECK-NEXT: ret i32 [[I_INC_LCSSA_LCSSA]]
;
entry:
br label %outer_header
outer_header:
%j = phi i32 [0, %entry], [%j.inc, %outer_backedge]
br label %preheader
preheader:
br label %header
header:
%i = phi i32 [0, %preheader], [%i.inc, %backedge]
br label %live_part
live_part:
%mul = mul i32 %i, %i
br i1 false, label %backedge, label %dead
dead:
%i.2 = add i32 %i, 1
br label %backedge
backedge:
%i.1 = phi i32 [%i, %live_part], [%i.2, %dead]
%i.inc = add i32 %i.1, 1
br i1 false, label %header, label %outer_backedge
outer_backedge:
%j.inc = add i32 %j, 1
%cmp.j = icmp slt i32 %j.inc, %end
br i1 %cmp.j, label %outer_header, label %exit
exit:
ret i32 %i.inc
}
define i32 @full_sub_loop_test_switch_loop(i32 %end) {
; CHECK-LABEL: @full_sub_loop_test_switch_loop(
; CHECK-NEXT: entry:
; CHECK-NEXT: br label [[OUTER_HEADER:%.*]]
; CHECK: outer_header:
; CHECK-NEXT: [[J:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[J_INC:%.*]], [[OUTER_BACKEDGE:%.*]] ]
; CHECK-NEXT: br label [[HEADER:%.*]]
; CHECK: header:
; CHECK-NEXT: [[I:%.*]] = phi i32 [ 0, [[OUTER_HEADER]] ], [ [[I_INC:%.*]], [[BACKEDGE:%.*]] ]
; CHECK-NEXT: [[MUL:%.*]] = mul i32 [[I]], [[I]]
; CHECK-NEXT: switch i32 1, label [[DEAD:%.*]] [
; CHECK-NEXT: i32 0, label [[BACKEDGE]]
; CHECK-NEXT: ]
; CHECK: dead:
; CHECK-NEXT: [[I_2:%.*]] = add i32 [[I]], 1
; CHECK-NEXT: br label [[BACKEDGE]]
; CHECK: backedge:
; CHECK-NEXT: [[I_1:%.*]] = phi i32 [ [[I]], [[HEADER]] ], [ [[I_2]], [[DEAD]] ]
; CHECK-NEXT: [[I_INC]] = add i32 [[I_1]], 1
; CHECK-NEXT: switch i32 1, label [[OUTER_BACKEDGE]] [
; CHECK-NEXT: i32 0, label [[HEADER]]
; CHECK-NEXT: ]
; CHECK: outer_backedge:
; CHECK-NEXT: [[I_INC_LCSSA:%.*]] = phi i32 [ [[I_INC]], [[BACKEDGE]] ]
; CHECK-NEXT: [[J_INC]] = add i32 [[J]], 1
; CHECK-NEXT: [[CMP_J:%.*]] = icmp slt i32 [[J_INC]], [[END:%.*]]
; CHECK-NEXT: br i1 [[CMP_J]], label [[OUTER_HEADER]], label [[EXIT:%.*]]
; CHECK: exit:
; CHECK-NEXT: [[I_INC_LCSSA_LCSSA:%.*]] = phi i32 [ [[I_INC_LCSSA]], [[OUTER_BACKEDGE]] ]
; CHECK-NEXT: ret i32 [[I_INC_LCSSA_LCSSA]]
;
entry:
br label %outer_header
outer_header:
%j = phi i32 [0, %entry], [%j.inc, %outer_backedge]
br label %preheader
preheader:
br label %header
header:
%i = phi i32 [0, %preheader], [%i.inc, %backedge]
br label %live_part
live_part:
%mul = mul i32 %i, %i
switch i32 1, label %dead [i32 0, label %backedge]
dead:
%i.2 = add i32 %i, 1
br label %backedge
backedge:
%i.1 = phi i32 [%i, %live_part], [%i.2, %dead]
%i.inc = add i32 %i.1, 1
switch i32 1, label %outer_backedge [i32 0, label %header]
outer_backedge:
%j.inc = add i32 %j, 1
%cmp.j = icmp slt i32 %j.inc, %end
br i1 %cmp.j, label %outer_header, label %exit
exit:
ret i32 %i.inc
}
; Inverted condition in live_part.
define i32 @full_sub_loop_test_branch_loop_inverse_1(i32 %end) {
; CHECK-LABEL: @full_sub_loop_test_branch_loop_inverse_1(
; CHECK-NEXT: entry:
; CHECK-NEXT: br label [[OUTER_HEADER:%.*]]
; CHECK: outer_header:
; CHECK-NEXT: [[J:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[J_INC:%.*]], [[OUTER_BACKEDGE:%.*]] ]
; CHECK-NEXT: br label [[HEADER:%.*]]
; CHECK: header:
; CHECK-NEXT: [[I:%.*]] = phi i32 [ 0, [[OUTER_HEADER]] ], [ [[I_INC:%.*]], [[BACKEDGE:%.*]] ]
; CHECK-NEXT: [[MUL:%.*]] = mul i32 [[I]], [[I]]
; CHECK-NEXT: br i1 true, label [[BACKEDGE]], label [[DEAD:%.*]]
; CHECK: dead:
; CHECK-NEXT: [[I_2:%.*]] = add i32 [[I]], 1
; CHECK-NEXT: br label [[BACKEDGE]]
; CHECK: backedge:
; CHECK-NEXT: [[I_1:%.*]] = phi i32 [ [[I]], [[HEADER]] ], [ [[I_2]], [[DEAD]] ]
; CHECK-NEXT: [[I_INC]] = add i32 [[I_1]], 1
; CHECK-NEXT: br i1 false, label [[HEADER]], label [[OUTER_BACKEDGE]]
; CHECK: outer_backedge:
; CHECK-NEXT: [[I_INC_LCSSA:%.*]] = phi i32 [ [[I_INC]], [[BACKEDGE]] ]
; CHECK-NEXT: [[J_INC]] = add i32 [[J]], 1
; CHECK-NEXT: [[CMP_J:%.*]] = icmp slt i32 [[J_INC]], [[END:%.*]]
; CHECK-NEXT: br i1 [[CMP_J]], label [[OUTER_HEADER]], label [[EXIT:%.*]]
; CHECK: exit:
; CHECK-NEXT: [[I_INC_LCSSA_LCSSA:%.*]] = phi i32 [ [[I_INC_LCSSA]], [[OUTER_BACKEDGE]] ]
; CHECK-NEXT: ret i32 [[I_INC_LCSSA_LCSSA]]
;
entry:
br label %outer_header
outer_header:
%j = phi i32 [0, %entry], [%j.inc, %outer_backedge]
br label %preheader
preheader:
br label %header
header:
%i = phi i32 [0, %preheader], [%i.inc, %backedge]
br label %live_part
live_part:
%mul = mul i32 %i, %i
br i1 true, label %backedge, label %dead
dead:
%i.2 = add i32 %i, 1
br label %backedge
backedge:
%i.1 = phi i32 [%i, %live_part], [%i.2, %dead]
%i.inc = add i32 %i.1, 1
br i1 false, label %header, label %outer_backedge
outer_backedge:
%j.inc = add i32 %j, 1
%cmp.j = icmp slt i32 %j.inc, %end
br i1 %cmp.j, label %outer_header, label %exit
exit:
ret i32 %i.inc
}
define i32 @full_sub_loop_test_switch_loop_inverse_1(i32 %end) {
; CHECK-LABEL: @full_sub_loop_test_switch_loop_inverse_1(
; CHECK-NEXT: entry:
; CHECK-NEXT: br label [[OUTER_HEADER:%.*]]
; CHECK: outer_header:
; CHECK-NEXT: [[J:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[J_INC:%.*]], [[OUTER_BACKEDGE:%.*]] ]
; CHECK-NEXT: br label [[HEADER:%.*]]
; CHECK: header:
; CHECK-NEXT: [[I:%.*]] = phi i32 [ 0, [[OUTER_HEADER]] ], [ [[I_INC:%.*]], [[BACKEDGE:%.*]] ]
; CHECK-NEXT: [[MUL:%.*]] = mul i32 [[I]], [[I]]
; CHECK-NEXT: switch i32 1, label [[BACKEDGE]] [
; CHECK-NEXT: i32 0, label [[DEAD:%.*]]
; CHECK-NEXT: ]
; CHECK: dead:
; CHECK-NEXT: [[I_2:%.*]] = add i32 [[I]], 1
; CHECK-NEXT: br label [[BACKEDGE]]
; CHECK: backedge:
; CHECK-NEXT: [[I_1:%.*]] = phi i32 [ [[I]], [[HEADER]] ], [ [[I_2]], [[DEAD]] ]
; CHECK-NEXT: [[I_INC]] = add i32 [[I_1]], 1
; CHECK-NEXT: switch i32 1, label [[OUTER_BACKEDGE]] [
; CHECK-NEXT: i32 0, label [[HEADER]]
; CHECK-NEXT: ]
; CHECK: outer_backedge:
; CHECK-NEXT: [[I_INC_LCSSA:%.*]] = phi i32 [ [[I_INC]], [[BACKEDGE]] ]
; CHECK-NEXT: [[J_INC]] = add i32 [[J]], 1
; CHECK-NEXT: [[CMP_J:%.*]] = icmp slt i32 [[J_INC]], [[END:%.*]]
; CHECK-NEXT: br i1 [[CMP_J]], label [[OUTER_HEADER]], label [[EXIT:%.*]]
; CHECK: exit:
; CHECK-NEXT: [[I_INC_LCSSA_LCSSA:%.*]] = phi i32 [ [[I_INC_LCSSA]], [[OUTER_BACKEDGE]] ]
; CHECK-NEXT: ret i32 [[I_INC_LCSSA_LCSSA]]
;
entry:
br label %outer_header
outer_header:
%j = phi i32 [0, %entry], [%j.inc, %outer_backedge]
br label %preheader
preheader:
br label %header
header:
%i = phi i32 [0, %preheader], [%i.inc, %backedge]
br label %live_part
live_part:
%mul = mul i32 %i, %i
switch i32 1, label %backedge [i32 0, label %dead]
dead:
%i.2 = add i32 %i, 1
br label %backedge
backedge:
%i.1 = phi i32 [%i, %live_part], [%i.2, %dead]
%i.inc = add i32 %i.1, 1
switch i32 1, label %outer_backedge [i32 0, label %header]
outer_backedge:
%j.inc = add i32 %j, 1
%cmp.j = icmp slt i32 %j.inc, %end
br i1 %cmp.j, label %outer_header, label %exit
exit:
ret i32 %i.inc
}
define i32 @full_sub_loop_test_branch_loop_inverse_2(i32 %end) {
; CHECK-LABEL: @full_sub_loop_test_branch_loop_inverse_2(
; CHECK-NEXT: entry:
; CHECK-NEXT: br label [[OUTER_HEADER:%.*]]
; CHECK: outer_header:
; CHECK-NEXT: [[J:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[J_INC:%.*]], [[OUTER_BACKEDGE:%.*]] ]
; CHECK-NEXT: switch i32 0, label [[PREHEADER_SPLIT:%.*]] [
; CHECK-NEXT: i32 1, label [[OUTER_BACKEDGE]]
; CHECK-NEXT: ]
; CHECK: preheader.split:
; CHECK-NEXT: br label [[HEADER:%.*]]
; CHECK: header:
; CHECK-NEXT: [[I:%.*]] = phi i32 [ 0, [[PREHEADER_SPLIT]] ], [ [[I_INC:%.*]], [[HEADER]] ]
; CHECK-NEXT: [[MUL:%.*]] = mul i32 [[I]], [[I]]
; CHECK-NEXT: [[I_2:%.*]] = add i32 [[I]], 1
; CHECK-NEXT: [[I_INC]] = add i32 [[I_2]], 1
; CHECK-NEXT: br label [[HEADER]]
; CHECK: outer_backedge:
; CHECK-NEXT: [[J_INC]] = add i32 [[J]], 1
; CHECK-NEXT: [[CMP_J:%.*]] = icmp slt i32 [[J_INC]], [[END:%.*]]
; CHECK-NEXT: br i1 [[CMP_J]], label [[OUTER_HEADER]], label [[EXIT:%.*]]
; CHECK: exit:
; CHECK-NEXT: [[I_INC_LCSSA_LCSSA:%.*]] = phi i32 [ undef, [[OUTER_BACKEDGE]] ]
; CHECK-NEXT: ret i32 [[I_INC_LCSSA_LCSSA]]
;
entry:
br label %outer_header
outer_header:
%j = phi i32 [0, %entry], [%j.inc, %outer_backedge]
br label %preheader
preheader:
br label %header
header:
%i = phi i32 [0, %preheader], [%i.inc, %backedge]
br label %live_part
live_part:
%mul = mul i32 %i, %i
br i1 false, label %backedge, label %dead
dead:
%i.2 = add i32 %i, 1
br label %backedge
backedge:
%i.1 = phi i32 [%i, %live_part], [%i.2, %dead]
%i.inc = add i32 %i.1, 1
br i1 true, label %header, label %outer_backedge
outer_backedge:
%j.inc = add i32 %j, 1
%cmp.j = icmp slt i32 %j.inc, %end
br i1 %cmp.j, label %outer_header, label %exit
exit:
ret i32 %i.inc
}
define i32 @full_sub_loop_test_switch_loop_inverse_2(i32 %end) {
; CHECK-LABEL: @full_sub_loop_test_switch_loop_inverse_2(
; CHECK-NEXT: entry:
; CHECK-NEXT: br label [[OUTER_HEADER:%.*]]
; CHECK: outer_header:
; CHECK-NEXT: [[J:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[J_INC:%.*]], [[OUTER_BACKEDGE:%.*]] ]
; CHECK-NEXT: switch i32 0, label [[PREHEADER_SPLIT:%.*]] [
; CHECK-NEXT: i32 1, label [[OUTER_BACKEDGE]]
; CHECK-NEXT: ]
; CHECK: preheader.split:
; CHECK-NEXT: br label [[HEADER:%.*]]
; CHECK: header:
; CHECK-NEXT: [[I:%.*]] = phi i32 [ 0, [[PREHEADER_SPLIT]] ], [ [[I_INC:%.*]], [[HEADER]] ]
; CHECK-NEXT: [[MUL:%.*]] = mul i32 [[I]], [[I]]
; CHECK-NEXT: [[I_2:%.*]] = add i32 [[I]], 1
; CHECK-NEXT: [[I_INC]] = add i32 [[I_2]], 1
; CHECK-NEXT: br label [[HEADER]]
; CHECK: outer_backedge:
; CHECK-NEXT: [[J_INC]] = add i32 [[J]], 1
; CHECK-NEXT: [[CMP_J:%.*]] = icmp slt i32 [[J_INC]], [[END:%.*]]
; CHECK-NEXT: br i1 [[CMP_J]], label [[OUTER_HEADER]], label [[EXIT:%.*]]
; CHECK: exit:
; CHECK-NEXT: [[I_INC_LCSSA_LCSSA:%.*]] = phi i32 [ undef, [[OUTER_BACKEDGE]] ]
; CHECK-NEXT: ret i32 [[I_INC_LCSSA_LCSSA]]
;
entry:
br label %outer_header
outer_header:
%j = phi i32 [0, %entry], [%j.inc, %outer_backedge]
br label %preheader
preheader:
br label %header
header:
%i = phi i32 [0, %preheader], [%i.inc, %backedge]
br label %live_part
live_part:
%mul = mul i32 %i, %i
switch i32 1, label %dead [i32 0, label %backedge]
dead:
%i.2 = add i32 %i, 1
br label %backedge
backedge:
%i.1 = phi i32 [%i, %live_part], [%i.2, %dead]
%i.inc = add i32 %i.1, 1
switch i32 1, label %header [i32 0, label %outer_backedge]
outer_backedge:
%j.inc = add i32 %j, 1
%cmp.j = icmp slt i32 %j.inc, %end
br i1 %cmp.j, label %outer_header, label %exit
exit:
ret i32 %i.inc
}
define i32 @full_sub_loop_test_branch_loop_inverse_3(i32 %end) {
; CHECK-LABEL: @full_sub_loop_test_branch_loop_inverse_3(
; CHECK-NEXT: entry:
; CHECK-NEXT: br label [[OUTER_HEADER:%.*]]
; CHECK: outer_header:
; CHECK-NEXT: [[J:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[J_INC:%.*]], [[OUTER_BACKEDGE:%.*]] ]
; CHECK-NEXT: switch i32 0, label [[PREHEADER_SPLIT:%.*]] [
; CHECK-NEXT: i32 1, label [[OUTER_BACKEDGE]]
; CHECK-NEXT: ]
; CHECK: preheader.split:
; CHECK-NEXT: br label [[HEADER:%.*]]
; CHECK: header:
; CHECK-NEXT: [[I:%.*]] = phi i32 [ 0, [[PREHEADER_SPLIT]] ], [ [[I_INC:%.*]], [[HEADER]] ]
; CHECK-NEXT: [[MUL:%.*]] = mul i32 [[I]], [[I]]
; CHECK-NEXT: [[I_INC]] = add i32 [[I]], 1
; CHECK-NEXT: br label [[HEADER]]
; CHECK: outer_backedge:
; CHECK-NEXT: [[J_INC]] = add i32 [[J]], 1
; CHECK-NEXT: [[CMP_J:%.*]] = icmp slt i32 [[J_INC]], [[END:%.*]]
; CHECK-NEXT: br i1 [[CMP_J]], label [[OUTER_HEADER]], label [[EXIT:%.*]]
; CHECK: exit:
; CHECK-NEXT: [[I_INC_LCSSA_LCSSA:%.*]] = phi i32 [ undef, [[OUTER_BACKEDGE]] ]
; CHECK-NEXT: ret i32 [[I_INC_LCSSA_LCSSA]]
;
entry:
br label %outer_header
outer_header:
%j = phi i32 [0, %entry], [%j.inc, %outer_backedge]
br label %preheader
preheader:
br label %header
header:
%i = phi i32 [0, %preheader], [%i.inc, %backedge]
br label %live_part
live_part:
%mul = mul i32 %i, %i
br i1 true, label %backedge, label %dead
dead:
%i.2 = add i32 %i, 1
br label %backedge
backedge:
%i.1 = phi i32 [%i, %live_part], [%i.2, %dead]
%i.inc = add i32 %i.1, 1
br i1 true, label %header, label %outer_backedge
outer_backedge:
%j.inc = add i32 %j, 1
%cmp.j = icmp slt i32 %j.inc, %end
br i1 %cmp.j, label %outer_header, label %exit
exit:
ret i32 %i.inc
}
define i32 @full_sub_loop_test_switch_loop_inverse_3(i32 %end) {
; CHECK-LABEL: @full_sub_loop_test_switch_loop_inverse_3(
; CHECK-NEXT: entry:
; CHECK-NEXT: br label [[OUTER_HEADER:%.*]]
; CHECK: outer_header:
; CHECK-NEXT: [[J:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[J_INC:%.*]], [[OUTER_BACKEDGE:%.*]] ]
; CHECK-NEXT: switch i32 0, label [[PREHEADER_SPLIT:%.*]] [
; CHECK-NEXT: i32 1, label [[OUTER_BACKEDGE]]
; CHECK-NEXT: ]
; CHECK: preheader.split:
; CHECK-NEXT: br label [[HEADER:%.*]]
; CHECK: header:
; CHECK-NEXT: [[I:%.*]] = phi i32 [ 0, [[PREHEADER_SPLIT]] ], [ [[I_INC:%.*]], [[HEADER]] ]
; CHECK-NEXT: [[MUL:%.*]] = mul i32 [[I]], [[I]]
; CHECK-NEXT: [[I_INC]] = add i32 [[I]], 1
; CHECK-NEXT: br label [[HEADER]]
; CHECK: outer_backedge:
; CHECK-NEXT: [[J_INC]] = add i32 [[J]], 1
; CHECK-NEXT: [[CMP_J:%.*]] = icmp slt i32 [[J_INC]], [[END:%.*]]
; CHECK-NEXT: br i1 [[CMP_J]], label [[OUTER_HEADER]], label [[EXIT:%.*]]
; CHECK: exit:
; CHECK-NEXT: [[I_INC_LCSSA_LCSSA:%.*]] = phi i32 [ undef, [[OUTER_BACKEDGE]] ]
; CHECK-NEXT: ret i32 [[I_INC_LCSSA_LCSSA]]
;
entry:
br label %outer_header
outer_header:
%j = phi i32 [0, %entry], [%j.inc, %outer_backedge]
br label %preheader
preheader:
br label %header
header:
%i = phi i32 [0, %preheader], [%i.inc, %backedge]
br label %live_part
live_part:
%mul = mul i32 %i, %i
switch i32 1, label %backedge [i32 0, label %dead]
dead:
%i.2 = add i32 %i, 1
br label %backedge
backedge:
%i.1 = phi i32 [%i, %live_part], [%i.2, %dead]
%i.inc = add i32 %i.1, 1
switch i32 1, label %header [i32 0, label %outer_backedge]
outer_backedge:
%j.inc = add i32 %j, 1
%cmp.j = icmp slt i32 %j.inc, %end
br i1 %cmp.j, label %outer_header, label %exit
exit:
ret i32 %i.inc
}
define i32 @exit_branch_from_inner_to_grandparent(i1 %cond1, i1 %cond2, i32 %N) {
; CHECK-LABEL: @exit_branch_from_inner_to_grandparent(
; CHECK-NEXT: preheader:
; CHECK-NEXT: br label [[LOOP_1:%.*]]
; CHECK: loop_1:
; CHECK-NEXT: [[I:%.*]] = phi i32 [ 0, [[PREHEADER:%.*]] ], [ [[I_NEXT:%.*]], [[LOOP_1_BACKEDGE:%.*]] ]
; CHECK-NEXT: br label [[LOOP_2:%.*]]
; CHECK: loop_2:
; CHECK-NEXT: [[J:%.*]] = phi i32 [ 0, [[LOOP_1]] ], [ [[J_NEXT:%.*]], [[LOOP_2_BACKEDGE:%.*]] ]
; CHECK-NEXT: switch i32 0, label [[LOOP_2_SPLIT:%.*]] [
; CHECK-NEXT: i32 1, label [[LOOP_2_BACKEDGE]]
; CHECK-NEXT: ]
; CHECK: loop_2.split:
; CHECK-NEXT: br label [[LOOP_3:%.*]]
; CHECK: loop_3:
; CHECK-NEXT: [[K:%.*]] = phi i32 [ 0, [[LOOP_2_SPLIT]] ], [ [[K_NEXT:%.*]], [[LOOP_3_BACKEDGE:%.*]] ]
; CHECK-NEXT: br i1 [[COND1:%.*]], label [[LOOP_3_BACKEDGE]], label [[LOOP_1_BACKEDGE_LOOPEXIT:%.*]]
; CHECK: loop_3_backedge:
; CHECK-NEXT: [[K_NEXT]] = add i32 [[K]], 1
; CHECK-NEXT: br label [[LOOP_3]]
; CHECK: loop_2_backedge:
; CHECK-NEXT: [[J_NEXT]] = add i32 [[J]], 1
; CHECK-NEXT: [[C_2:%.*]] = icmp slt i32 [[J_NEXT]], [[N:%.*]]
; CHECK-NEXT: br i1 [[C_2]], label [[LOOP_2]], label [[LOOP_1_BACKEDGE_LOOPEXIT1:%.*]]
; CHECK: loop_1_backedge.loopexit:
; CHECK-NEXT: br label [[LOOP_1_BACKEDGE]]
; CHECK: loop_1_backedge.loopexit1:
; CHECK-NEXT: br label [[LOOP_1_BACKEDGE]]
; CHECK: loop_1_backedge:
; CHECK-NEXT: [[I_NEXT]] = add i32 [[I]], 1
; CHECK-NEXT: [[C_1:%.*]] = icmp slt i32 [[I_NEXT]], [[N]]
; CHECK-NEXT: br i1 [[C_1]], label [[LOOP_1]], label [[EXIT:%.*]]
; CHECK: exit:
; CHECK-NEXT: [[I_LCSSA:%.*]] = phi i32 [ [[I]], [[LOOP_1_BACKEDGE]] ]
; CHECK-NEXT: ret i32 [[I_LCSSA]]
;
preheader:
br label %loop_1
loop_1:
%i = phi i32 [ 0, %preheader ], [ %i.next, %loop_1_backedge ]
br label %loop_2
loop_2:
%j = phi i32 [ 0, %loop_1 ], [ %j.next, %loop_2_backedge ]
br label %loop_3
loop_3:
%k = phi i32 [ 0, %loop_2 ], [ %k.next, %loop_3_backedge ]
br i1 %cond1, label %loop_3_backedge, label %loop_1_backedge
loop_3_backedge:
%k.next = add i32 %k, 1
br i1 true, label %loop_3, label %loop_2_backedge
loop_2_backedge:
%j.next = add i32 %j, 1
%c_2 = icmp slt i32 %j.next, %N
br i1 %c_2, label %loop_2, label %loop_1_backedge
loop_1_backedge:
%i.next = add i32 %i, 1
%c_1 = icmp slt i32 %i.next, %N
br i1 %c_1, label %loop_1, label %exit
exit:
ret i32 %i
}
define i32 @exit_switch_from_inner_to_grandparent(i1 %cond1, i1 %cond2, i32 %N) {
; CHECK-LABEL: @exit_switch_from_inner_to_grandparent(
; CHECK-NEXT: preheader:
; CHECK-NEXT: br label [[LOOP_1:%.*]]
; CHECK: loop_1:
; CHECK-NEXT: [[I:%.*]] = phi i32 [ 0, [[PREHEADER:%.*]] ], [ [[I_NEXT:%.*]], [[LOOP_1_BACKEDGE:%.*]] ]
; CHECK-NEXT: br label [[LOOP_2:%.*]]
; CHECK: loop_2:
; CHECK-NEXT: [[J:%.*]] = phi i32 [ 0, [[LOOP_1]] ], [ [[J_NEXT:%.*]], [[LOOP_2_BACKEDGE:%.*]] ]
; CHECK-NEXT: switch i32 0, label [[LOOP_2_SPLIT:%.*]] [
; CHECK-NEXT: i32 1, label [[LOOP_2_BACKEDGE]]
; CHECK-NEXT: ]
; CHECK: loop_2.split:
; CHECK-NEXT: br label [[LOOP_3:%.*]]
; CHECK: loop_3:
; CHECK-NEXT: [[K:%.*]] = phi i32 [ 0, [[LOOP_2_SPLIT]] ], [ [[K_NEXT:%.*]], [[LOOP_3_BACKEDGE:%.*]] ]
; CHECK-NEXT: br i1 [[COND1:%.*]], label [[LOOP_3_BACKEDGE]], label [[LOOP_1_BACKEDGE_LOOPEXIT:%.*]]
; CHECK: loop_3_backedge:
; CHECK-NEXT: [[K_NEXT]] = add i32 [[K]], 1
; CHECK-NEXT: br label [[LOOP_3]]
; CHECK: loop_2_backedge:
; CHECK-NEXT: [[J_NEXT]] = add i32 [[J]], 1
; CHECK-NEXT: [[C_2:%.*]] = icmp slt i32 [[J_NEXT]], [[N:%.*]]
; CHECK-NEXT: br i1 [[C_2]], label [[LOOP_2]], label [[LOOP_1_BACKEDGE_LOOPEXIT1:%.*]]
; CHECK: loop_1_backedge.loopexit:
; CHECK-NEXT: br label [[LOOP_1_BACKEDGE]]
; CHECK: loop_1_backedge.loopexit1:
; CHECK-NEXT: br label [[LOOP_1_BACKEDGE]]
; CHECK: loop_1_backedge:
; CHECK-NEXT: [[I_NEXT]] = add i32 [[I]], 1
; CHECK-NEXT: [[C_1:%.*]] = icmp slt i32 [[I_NEXT]], [[N]]
; CHECK-NEXT: br i1 [[C_1]], label [[LOOP_1]], label [[EXIT:%.*]]
; CHECK: exit:
; CHECK-NEXT: [[I_LCSSA:%.*]] = phi i32 [ [[I]], [[LOOP_1_BACKEDGE]] ]
; CHECK-NEXT: ret i32 [[I_LCSSA]]
;
preheader:
br label %loop_1
loop_1:
%i = phi i32 [ 0, %preheader ], [ %i.next, %loop_1_backedge ]
br label %loop_2
loop_2:
%j = phi i32 [ 0, %loop_1 ], [ %j.next, %loop_2_backedge ]
br label %loop_3
loop_3:
%k = phi i32 [ 0, %loop_2 ], [ %k.next, %loop_3_backedge ]
br i1 %cond1, label %loop_3_backedge, label %loop_1_backedge
loop_3_backedge:
%k.next = add i32 %k, 1
switch i32 1, label %loop_3 [i32 0, label %loop_2_backedge]
loop_2_backedge:
%j.next = add i32 %j, 1
%c_2 = icmp slt i32 %j.next, %N
br i1 %c_2, label %loop_2, label %loop_1_backedge
loop_1_backedge:
%i.next = add i32 %i, 1
%c_1 = icmp slt i32 %i.next, %N
br i1 %c_1, label %loop_1, label %exit
exit:
ret i32 %i
}
define i32 @intermediate_branch_from_inner_to_grandparent(i1 %cond1, i1 %cond2, i32 %N) {
; CHECK-LABEL: @intermediate_branch_from_inner_to_grandparent(
; CHECK-NEXT: preheader:
; CHECK-NEXT: br label [[LOOP_1:%.*]]
; CHECK: loop_1:
; CHECK-NEXT: [[I:%.*]] = phi i32 [ 0, [[PREHEADER:%.*]] ], [ [[I_NEXT:%.*]], [[LOOP_1_BACKEDGE:%.*]] ]
; CHECK-NEXT: br label [[LOOP_2:%.*]]
; CHECK: loop_2:
; CHECK-NEXT: [[J:%.*]] = phi i32 [ 0, [[LOOP_1]] ], [ [[J_NEXT:%.*]], [[LOOP_2_BACKEDGE:%.*]] ]
; CHECK-NEXT: br label [[LOOP_3:%.*]]
; CHECK: loop_3:
; CHECK-NEXT: [[K:%.*]] = phi i32 [ 0, [[LOOP_2]] ], [ [[K_NEXT:%.*]], [[LOOP_3_BACKEDGE:%.*]] ]
; CHECK-NEXT: br i1 [[COND1:%.*]], label [[LOOP_3_BACKEDGE]], label [[INTERMEDIATE:%.*]]
; CHECK: intermediate:
; CHECK-NEXT: br i1 false, label [[LOOP_3_BACKEDGE]], label [[LOOP_1_BACKEDGE_LOOPEXIT:%.*]]
; CHECK: loop_3_backedge:
; CHECK-NEXT: [[K_NEXT]] = add i32 [[K]], 1
; CHECK-NEXT: br i1 [[COND2:%.*]], label [[LOOP_3]], label [[LOOP_2_BACKEDGE]]
; CHECK: loop_2_backedge:
; CHECK-NEXT: [[J_NEXT]] = add i32 [[J]], 1
; CHECK-NEXT: [[C_2:%.*]] = icmp slt i32 [[J_NEXT]], [[N:%.*]]
; CHECK-NEXT: br i1 [[C_2]], label [[LOOP_2]], label [[LOOP_1_BACKEDGE_LOOPEXIT1:%.*]]
; CHECK: loop_1_backedge.loopexit:
; CHECK-NEXT: br label [[LOOP_1_BACKEDGE]]
; CHECK: loop_1_backedge.loopexit1:
; CHECK-NEXT: br label [[LOOP_1_BACKEDGE]]
; CHECK: loop_1_backedge:
; CHECK-NEXT: [[I_NEXT]] = add i32 [[I]], 1
; CHECK-NEXT: [[C_1:%.*]] = icmp slt i32 [[I_NEXT]], [[N]]
; CHECK-NEXT: br i1 [[C_1]], label [[LOOP_1]], label [[EXIT:%.*]]
; CHECK: exit:
; CHECK-NEXT: [[I_LCSSA:%.*]] = phi i32 [ [[I]], [[LOOP_1_BACKEDGE]] ]
; CHECK-NEXT: ret i32 [[I_LCSSA]]
;
preheader:
br label %loop_1
loop_1:
%i = phi i32 [ 0, %preheader ], [ %i.next, %loop_1_backedge ]
br label %loop_2
loop_2:
%j = phi i32 [ 0, %loop_1 ], [ %j.next, %loop_2_backedge ]
br label %loop_3
loop_3:
%k = phi i32 [ 0, %loop_2 ], [ %k.next, %loop_3_backedge ]
br i1 %cond1, label %loop_3_backedge, label %intermediate
intermediate:
br i1 false, label %loop_3_backedge, label %loop_1_backedge
loop_3_backedge:
%k.next = add i32 %k, 1
br i1 %cond2, label %loop_3, label %loop_2_backedge
loop_2_backedge:
%j.next = add i32 %j, 1
%c_2 = icmp slt i32 %j.next, %N
br i1 %c_2, label %loop_2, label %loop_1_backedge
loop_1_backedge:
%i.next = add i32 %i, 1
%c_1 = icmp slt i32 %i.next, %N
br i1 %c_1, label %loop_1, label %exit
exit:
ret i32 %i
}
define i32 @intermediate_switch_from_inner_to_grandparent(i1 %cond1, i1 %cond2, i32 %N) {
; CHECK-LABEL: @intermediate_switch_from_inner_to_grandparent(
; CHECK-NEXT: preheader:
; CHECK-NEXT: br label [[LOOP_1:%.*]]
; CHECK: loop_1:
; CHECK-NEXT: [[I:%.*]] = phi i32 [ 0, [[PREHEADER:%.*]] ], [ [[I_NEXT:%.*]], [[LOOP_1_BACKEDGE:%.*]] ]
; CHECK-NEXT: br label [[LOOP_2:%.*]]
; CHECK: loop_2:
; CHECK-NEXT: [[J:%.*]] = phi i32 [ 0, [[LOOP_1]] ], [ [[J_NEXT:%.*]], [[LOOP_2_BACKEDGE:%.*]] ]
; CHECK-NEXT: br label [[LOOP_3:%.*]]
; CHECK: loop_3:
; CHECK-NEXT: [[K:%.*]] = phi i32 [ 0, [[LOOP_2]] ], [ [[K_NEXT:%.*]], [[LOOP_3_BACKEDGE:%.*]] ]
; CHECK-NEXT: br i1 [[COND1:%.*]], label [[LOOP_3_BACKEDGE]], label [[INTERMEDIATE:%.*]]
; CHECK: intermediate:
; CHECK-NEXT: switch i32 1, label [[LOOP_1_BACKEDGE_LOOPEXIT:%.*]] [
; CHECK-NEXT: i32 0, label [[LOOP_3_BACKEDGE]]
; CHECK-NEXT: ]
; CHECK: loop_3_backedge:
; CHECK-NEXT: [[K_NEXT]] = add i32 [[K]], 1
; CHECK-NEXT: br i1 [[COND2:%.*]], label [[LOOP_3]], label [[LOOP_2_BACKEDGE]]
; CHECK: loop_2_backedge:
; CHECK-NEXT: [[J_NEXT]] = add i32 [[J]], 1
; CHECK-NEXT: [[C_2:%.*]] = icmp slt i32 [[J_NEXT]], [[N:%.*]]
; CHECK-NEXT: br i1 [[C_2]], label [[LOOP_2]], label [[LOOP_1_BACKEDGE_LOOPEXIT1:%.*]]
; CHECK: loop_1_backedge.loopexit:
; CHECK-NEXT: br label [[LOOP_1_BACKEDGE]]
; CHECK: loop_1_backedge.loopexit1:
; CHECK-NEXT: br label [[LOOP_1_BACKEDGE]]
; CHECK: loop_1_backedge:
; CHECK-NEXT: [[I_NEXT]] = add i32 [[I]], 1
; CHECK-NEXT: [[C_1:%.*]] = icmp slt i32 [[I_NEXT]], [[N]]
; CHECK-NEXT: br i1 [[C_1]], label [[LOOP_1]], label [[EXIT:%.*]]
; CHECK: exit:
; CHECK-NEXT: [[I_LCSSA:%.*]] = phi i32 [ [[I]], [[LOOP_1_BACKEDGE]] ]
; CHECK-NEXT: ret i32 [[I_LCSSA]]
;
preheader:
br label %loop_1
loop_1:
%i = phi i32 [ 0, %preheader ], [ %i.next, %loop_1_backedge ]
br label %loop_2
loop_2:
%j = phi i32 [ 0, %loop_1 ], [ %j.next, %loop_2_backedge ]
br label %loop_3
loop_3:
%k = phi i32 [ 0, %loop_2 ], [ %k.next, %loop_3_backedge ]
br i1 %cond1, label %loop_3_backedge, label %intermediate
intermediate:
switch i32 1, label %loop_1_backedge [i32 0, label %loop_3_backedge]
loop_3_backedge:
%k.next = add i32 %k, 1
br i1 %cond2, label %loop_3, label %loop_2_backedge
loop_2_backedge:
%j.next = add i32 %j, 1
%c_2 = icmp slt i32 %j.next, %N
br i1 %c_2, label %loop_2, label %loop_1_backedge
loop_1_backedge:
%i.next = add i32 %i, 1
%c_1 = icmp slt i32 %i.next, %N
br i1 %c_1, label %loop_1, label %exit
exit:
ret i32 %i
}
define i32 @intermediate_branch_from_inner_to_parent(i1 %cond1, i1 %cond2, i32 %N) {
; CHECK-LABEL: @intermediate_branch_from_inner_to_parent(
; CHECK-NEXT: preheader:
; CHECK-NEXT: br label [[LOOP_1:%.*]]
; CHECK: loop_1:
; CHECK-NEXT: [[I:%.*]] = phi i32 [ 0, [[PREHEADER:%.*]] ], [ [[I_NEXT:%.*]], [[LOOP_1_BACKEDGE:%.*]] ]
; CHECK-NEXT: br label [[LOOP_2:%.*]]
; CHECK: loop_2:
; CHECK-NEXT: [[J:%.*]] = phi i32 [ 0, [[LOOP_1]] ], [ [[J_NEXT:%.*]], [[LOOP_2_BACKEDGE:%.*]] ]
; CHECK-NEXT: br label [[LOOP_3:%.*]]
; CHECK: loop_3:
; CHECK-NEXT: [[K:%.*]] = phi i32 [ 0, [[LOOP_2]] ], [ [[K_NEXT:%.*]], [[LOOP_3_BACKEDGE:%.*]] ]
; CHECK-NEXT: br i1 [[COND1:%.*]], label [[LOOP_3_BACKEDGE]], label [[INTERMEDIATE:%.*]]
; CHECK: intermediate:
; CHECK-NEXT: br i1 false, label [[LOOP_3_BACKEDGE]], label [[LOOP_2_BACKEDGE]]
; CHECK: loop_3_backedge:
; CHECK-NEXT: [[K_NEXT]] = add i32 [[K]], 1
; CHECK-NEXT: br i1 [[COND2:%.*]], label [[LOOP_3]], label [[LOOP_2_BACKEDGE]]
; CHECK: loop_2_backedge:
; CHECK-NEXT: [[J_NEXT]] = add i32 [[J]], 1
; CHECK-NEXT: [[C_2:%.*]] = icmp slt i32 [[J_NEXT]], [[N:%.*]]
; CHECK-NEXT: br i1 [[C_2]], label [[LOOP_2]], label [[LOOP_1_BACKEDGE]]
; CHECK: loop_1_backedge:
; CHECK-NEXT: [[I_NEXT]] = add i32 [[I]], 1
; CHECK-NEXT: [[C_1:%.*]] = icmp slt i32 [[I_NEXT]], [[N]]
; CHECK-NEXT: br i1 [[C_1]], label [[LOOP_1]], label [[EXIT:%.*]]
; CHECK: exit:
; CHECK-NEXT: [[I_LCSSA:%.*]] = phi i32 [ [[I]], [[LOOP_1_BACKEDGE]] ]
; CHECK-NEXT: ret i32 [[I_LCSSA]]
;
preheader:
br label %loop_1
loop_1:
%i = phi i32 [ 0, %preheader ], [ %i.next, %loop_1_backedge ]
br label %loop_2
loop_2:
%j = phi i32 [ 0, %loop_1 ], [ %j.next, %loop_2_backedge ]
br label %loop_3
loop_3:
%k = phi i32 [ 0, %loop_2 ], [ %k.next, %loop_3_backedge ]
br i1 %cond1, label %loop_3_backedge, label %intermediate
intermediate:
br i1 false, label %loop_3_backedge, label %loop_2_backedge
loop_3_backedge:
%k.next = add i32 %k, 1
br i1 %cond2, label %loop_3, label %loop_2_backedge
loop_2_backedge:
%j.next = add i32 %j, 1
%c_2 = icmp slt i32 %j.next, %N
br i1 %c_2, label %loop_2, label %loop_1_backedge
loop_1_backedge:
%i.next = add i32 %i, 1
%c_1 = icmp slt i32 %i.next, %N
br i1 %c_1, label %loop_1, label %exit
exit:
ret i32 %i
}
define i32 @intermediate_switch_from_inner_to_parent(i1 %cond1, i1 %cond2, i32 %N) {
; CHECK-LABEL: @intermediate_switch_from_inner_to_parent(
; CHECK-NEXT: preheader:
; CHECK-NEXT: br label [[LOOP_1:%.*]]
; CHECK: loop_1:
; CHECK-NEXT: [[I:%.*]] = phi i32 [ 0, [[PREHEADER:%.*]] ], [ [[I_NEXT:%.*]], [[LOOP_1_BACKEDGE:%.*]] ]
; CHECK-NEXT: br label [[LOOP_2:%.*]]
; CHECK: loop_2:
; CHECK-NEXT: [[J:%.*]] = phi i32 [ 0, [[LOOP_1]] ], [ [[J_NEXT:%.*]], [[LOOP_2_BACKEDGE:%.*]] ]
; CHECK-NEXT: br label [[LOOP_3:%.*]]
; CHECK: loop_3:
; CHECK-NEXT: [[K:%.*]] = phi i32 [ 0, [[LOOP_2]] ], [ [[K_NEXT:%.*]], [[LOOP_3_BACKEDGE:%.*]] ]
; CHECK-NEXT: br i1 [[COND1:%.*]], label [[LOOP_3_BACKEDGE]], label [[INTERMEDIATE:%.*]]
; CHECK: intermediate:
; CHECK-NEXT: switch i32 1, label [[LOOP_2_BACKEDGE]] [
; CHECK-NEXT: i32 0, label [[LOOP_3_BACKEDGE]]
; CHECK-NEXT: ]
; CHECK: loop_3_backedge:
; CHECK-NEXT: [[K_NEXT]] = add i32 [[K]], 1
; CHECK-NEXT: br i1 [[COND2:%.*]], label [[LOOP_3]], label [[LOOP_2_BACKEDGE]]
; CHECK: loop_2_backedge:
; CHECK-NEXT: [[J_NEXT]] = add i32 [[J]], 1
; CHECK-NEXT: [[C_2:%.*]] = icmp slt i32 [[J_NEXT]], [[N:%.*]]
; CHECK-NEXT: br i1 [[C_2]], label [[LOOP_2]], label [[LOOP_1_BACKEDGE]]
; CHECK: loop_1_backedge:
; CHECK-NEXT: [[I_NEXT]] = add i32 [[I]], 1
; CHECK-NEXT: [[C_1:%.*]] = icmp slt i32 [[I_NEXT]], [[N]]
; CHECK-NEXT: br i1 [[C_1]], label [[LOOP_1]], label [[EXIT:%.*]]
; CHECK: exit:
; CHECK-NEXT: [[I_LCSSA:%.*]] = phi i32 [ [[I]], [[LOOP_1_BACKEDGE]] ]
; CHECK-NEXT: ret i32 [[I_LCSSA]]
;
preheader:
br label %loop_1
loop_1:
%i = phi i32 [ 0, %preheader ], [ %i.next, %loop_1_backedge ]
br label %loop_2
loop_2:
%j = phi i32 [ 0, %loop_1 ], [ %j.next, %loop_2_backedge ]
br label %loop_3
loop_3:
%k = phi i32 [ 0, %loop_2 ], [ %k.next, %loop_3_backedge ]
br i1 %cond1, label %loop_3_backedge, label %intermediate
intermediate:
switch i32 1, label %loop_2_backedge [i32 0, label %loop_3_backedge]
loop_3_backedge:
%k.next = add i32 %k, 1
br i1 %cond2, label %loop_3, label %loop_2_backedge
loop_2_backedge:
%j.next = add i32 %j, 1
%c_2 = icmp slt i32 %j.next, %N
br i1 %c_2, label %loop_2, label %loop_1_backedge
loop_1_backedge:
%i.next = add i32 %i, 1
%c_1 = icmp slt i32 %i.next, %N
br i1 %c_1, label %loop_1, label %exit
exit:
ret i32 %i
}
define i32 @intermediate_subloop_branch_from_inner_to_grandparent(i1 %cond1, i1 %cond2, i1 %cond3, i32 %N) {
; CHECK-LABEL: @intermediate_subloop_branch_from_inner_to_grandparent(
; CHECK-NEXT: preheader:
; CHECK-NEXT: br label [[LOOP_1:%.*]]
; CHECK: loop_1:
; CHECK-NEXT: [[I:%.*]] = phi i32 [ 0, [[PREHEADER:%.*]] ], [ [[I_NEXT:%.*]], [[LOOP_1_BACKEDGE:%.*]] ]
; CHECK-NEXT: br label [[LOOP_2:%.*]]
; CHECK: loop_2:
; CHECK-NEXT: [[J:%.*]] = phi i32 [ 0, [[LOOP_1]] ], [ [[J_NEXT:%.*]], [[LOOP_2_BACKEDGE:%.*]] ]
; CHECK-NEXT: br label [[LOOP_3:%.*]]
; CHECK: loop_3:
; CHECK-NEXT: [[K:%.*]] = phi i32 [ 0, [[LOOP_2]] ], [ [[K_NEXT:%.*]], [[LOOP_3_BACKEDGE:%.*]] ]
; CHECK-NEXT: br i1 [[COND1:%.*]], label [[LOOP_3_BACKEDGE]], label [[INTERMEDIATE:%.*]]
; CHECK: intermediate:
; CHECK-NEXT: br label [[INTERMEDIATE_LOOP:%.*]]
; CHECK: intermediate_loop:
; CHECK-NEXT: br i1 [[COND3:%.*]], label [[INTERMEDIATE_LOOP]], label [[INTERMEDIATE_EXIT:%.*]]
; CHECK: intermediate_exit:
; CHECK-NEXT: br i1 false, label [[LOOP_3_BACKEDGE]], label [[LOOP_1_BACKEDGE_LOOPEXIT:%.*]]
; CHECK: loop_3_backedge:
; CHECK-NEXT: [[K_NEXT]] = add i32 [[K]], 1
; CHECK-NEXT: br i1 [[COND2:%.*]], label [[LOOP_3]], label [[LOOP_2_BACKEDGE]]
; CHECK: loop_2_backedge:
; CHECK-NEXT: [[J_NEXT]] = add i32 [[J]], 1
; CHECK-NEXT: [[C_2:%.*]] = icmp slt i32 [[J_NEXT]], [[N:%.*]]
; CHECK-NEXT: br i1 [[C_2]], label [[LOOP_2]], label [[LOOP_1_BACKEDGE_LOOPEXIT1:%.*]]
; CHECK: loop_1_backedge.loopexit:
; CHECK-NEXT: br label [[LOOP_1_BACKEDGE]]
; CHECK: loop_1_backedge.loopexit1:
; CHECK-NEXT: br label [[LOOP_1_BACKEDGE]]
; CHECK: loop_1_backedge:
; CHECK-NEXT: [[I_NEXT]] = add i32 [[I]], 1
; CHECK-NEXT: [[C_1:%.*]] = icmp slt i32 [[I_NEXT]], [[N]]
; CHECK-NEXT: br i1 [[C_1]], label [[LOOP_1]], label [[EXIT:%.*]]
; CHECK: exit:
; CHECK-NEXT: [[I_LCSSA:%.*]] = phi i32 [ [[I]], [[LOOP_1_BACKEDGE]] ]
; CHECK-NEXT: ret i32 [[I_LCSSA]]
;
preheader:
br label %loop_1
loop_1:
%i = phi i32 [ 0, %preheader ], [ %i.next, %loop_1_backedge ]
br label %loop_2
loop_2:
%j = phi i32 [ 0, %loop_1 ], [ %j.next, %loop_2_backedge ]
br label %loop_3
loop_3:
%k = phi i32 [ 0, %loop_2 ], [ %k.next, %loop_3_backedge ]
br i1 %cond1, label %loop_3_backedge, label %intermediate
intermediate:
br label %intermediate_loop
intermediate_loop:
br i1 %cond3, label %intermediate_loop, label %intermediate_exit
intermediate_exit:
br i1 false, label %loop_3_backedge, label %loop_1_backedge
loop_3_backedge:
%k.next = add i32 %k, 1
br i1 %cond2, label %loop_3, label %loop_2_backedge
loop_2_backedge:
%j.next = add i32 %j, 1
%c_2 = icmp slt i32 %j.next, %N
br i1 %c_2, label %loop_2, label %loop_1_backedge
loop_1_backedge:
%i.next = add i32 %i, 1
%c_1 = icmp slt i32 %i.next, %N
br i1 %c_1, label %loop_1, label %exit
exit:
ret i32 %i
}
define i32 @intermediate_subloop_switch_from_inner_to_grandparent(i1 %cond1, i1 %cond2, i1 %cond3, i32 %N) {
; CHECK-LABEL: @intermediate_subloop_switch_from_inner_to_grandparent(
; CHECK-NEXT: preheader:
; CHECK-NEXT: br label [[LOOP_1:%.*]]
; CHECK: loop_1:
; CHECK-NEXT: [[I:%.*]] = phi i32 [ 0, [[PREHEADER:%.*]] ], [ [[I_NEXT:%.*]], [[LOOP_1_BACKEDGE:%.*]] ]
; CHECK-NEXT: br label [[LOOP_2:%.*]]
; CHECK: loop_2:
; CHECK-NEXT: [[J:%.*]] = phi i32 [ 0, [[LOOP_1]] ], [ [[J_NEXT:%.*]], [[LOOP_2_BACKEDGE:%.*]] ]
; CHECK-NEXT: br label [[LOOP_3:%.*]]
; CHECK: loop_3:
; CHECK-NEXT: [[K:%.*]] = phi i32 [ 0, [[LOOP_2]] ], [ [[K_NEXT:%.*]], [[LOOP_3_BACKEDGE:%.*]] ]
; CHECK-NEXT: br i1 [[COND1:%.*]], label [[LOOP_3_BACKEDGE]], label [[INTERMEDIATE:%.*]]
; CHECK: intermediate:
; CHECK-NEXT: br label [[INTERMEDIATE_LOOP:%.*]]
; CHECK: intermediate_loop:
; CHECK-NEXT: br i1 [[COND3:%.*]], label [[INTERMEDIATE_LOOP]], label [[INTERMEDIATE_EXIT:%.*]]
; CHECK: intermediate_exit:
; CHECK-NEXT: switch i32 1, label [[LOOP_1_BACKEDGE_LOOPEXIT:%.*]] [
; CHECK-NEXT: i32 0, label [[LOOP_3_BACKEDGE]]
; CHECK-NEXT: ]
; CHECK: loop_3_backedge:
; CHECK-NEXT: [[K_NEXT]] = add i32 [[K]], 1
; CHECK-NEXT: br i1 [[COND2:%.*]], label [[LOOP_3]], label [[LOOP_2_BACKEDGE]]
; CHECK: loop_2_backedge:
; CHECK-NEXT: [[J_NEXT]] = add i32 [[J]], 1
; CHECK-NEXT: [[C_2:%.*]] = icmp slt i32 [[J_NEXT]], [[N:%.*]]
; CHECK-NEXT: br i1 [[C_2]], label [[LOOP_2]], label [[LOOP_1_BACKEDGE_LOOPEXIT1:%.*]]
; CHECK: loop_1_backedge.loopexit:
; CHECK-NEXT: br label [[LOOP_1_BACKEDGE]]
; CHECK: loop_1_backedge.loopexit1:
; CHECK-NEXT: br label [[LOOP_1_BACKEDGE]]
; CHECK: loop_1_backedge:
; CHECK-NEXT: [[I_NEXT]] = add i32 [[I]], 1
; CHECK-NEXT: [[C_1:%.*]] = icmp slt i32 [[I_NEXT]], [[N]]
; CHECK-NEXT: br i1 [[C_1]], label [[LOOP_1]], label [[EXIT:%.*]]
; CHECK: exit:
; CHECK-NEXT: [[I_LCSSA:%.*]] = phi i32 [ [[I]], [[LOOP_1_BACKEDGE]] ]
; CHECK-NEXT: ret i32 [[I_LCSSA]]
;
preheader:
br label %loop_1
loop_1:
%i = phi i32 [ 0, %preheader ], [ %i.next, %loop_1_backedge ]
br label %loop_2
loop_2:
%j = phi i32 [ 0, %loop_1 ], [ %j.next, %loop_2_backedge ]
br label %loop_3
loop_3:
%k = phi i32 [ 0, %loop_2 ], [ %k.next, %loop_3_backedge ]
br i1 %cond1, label %loop_3_backedge, label %intermediate
intermediate:
br label %intermediate_loop
intermediate_loop:
br i1 %cond3, label %intermediate_loop, label %intermediate_exit
intermediate_exit:
switch i32 1, label %loop_1_backedge [i32 0, label %loop_3_backedge]
loop_3_backedge:
%k.next = add i32 %k, 1
br i1 %cond2, label %loop_3, label %loop_2_backedge
loop_2_backedge:
%j.next = add i32 %j, 1
%c_2 = icmp slt i32 %j.next, %N
br i1 %c_2, label %loop_2, label %loop_1_backedge
loop_1_backedge:
%i.next = add i32 %i, 1
%c_1 = icmp slt i32 %i.next, %N
br i1 %c_1, label %loop_1, label %exit
exit:
ret i32 %i
}
define i32 @intermediate_subloop_branch_from_inner_to_parent(i1 %cond1, i1 %cond2, i1 %cond3, i32 %N) {
; CHECK-LABEL: @intermediate_subloop_branch_from_inner_to_parent(
; CHECK-NEXT: preheader:
; CHECK-NEXT: br label [[LOOP_1:%.*]]
; CHECK: loop_1:
; CHECK-NEXT: [[I:%.*]] = phi i32 [ 0, [[PREHEADER:%.*]] ], [ [[I_NEXT:%.*]], [[LOOP_1_BACKEDGE:%.*]] ]
; CHECK-NEXT: br label [[LOOP_2:%.*]]
; CHECK: loop_2:
; CHECK-NEXT: [[J:%.*]] = phi i32 [ 0, [[LOOP_1]] ], [ [[J_NEXT:%.*]], [[LOOP_2_BACKEDGE:%.*]] ]
; CHECK-NEXT: br label [[LOOP_3:%.*]]
; CHECK: loop_3:
; CHECK-NEXT: [[K:%.*]] = phi i32 [ 0, [[LOOP_2]] ], [ [[K_NEXT:%.*]], [[LOOP_3_BACKEDGE:%.*]] ]
; CHECK-NEXT: br i1 [[COND1:%.*]], label [[LOOP_3_BACKEDGE]], label [[INTERMEDIATE:%.*]]
; CHECK: intermediate:
; CHECK-NEXT: br label [[INTERMEDIATE_LOOP:%.*]]
; CHECK: intermediate_loop:
; CHECK-NEXT: br i1 [[COND3:%.*]], label [[INTERMEDIATE_LOOP]], label [[INTERMEDIATE_EXIT:%.*]]
; CHECK: intermediate_exit:
; CHECK-NEXT: br i1 false, label [[LOOP_3_BACKEDGE]], label [[LOOP_2_BACKEDGE]]
; CHECK: loop_3_backedge:
; CHECK-NEXT: [[K_NEXT]] = add i32 [[K]], 1
; CHECK-NEXT: br i1 [[COND2:%.*]], label [[LOOP_3]], label [[LOOP_2_BACKEDGE]]
; CHECK: loop_2_backedge:
; CHECK-NEXT: [[J_NEXT]] = add i32 [[J]], 1
; CHECK-NEXT: [[C_2:%.*]] = icmp slt i32 [[J_NEXT]], [[N:%.*]]
; CHECK-NEXT: br i1 [[C_2]], label [[LOOP_2]], label [[LOOP_1_BACKEDGE]]
; CHECK: loop_1_backedge:
; CHECK-NEXT: [[I_NEXT]] = add i32 [[I]], 1
; CHECK-NEXT: [[C_1:%.*]] = icmp slt i32 [[I_NEXT]], [[N]]
; CHECK-NEXT: br i1 [[C_1]], label [[LOOP_1]], label [[EXIT:%.*]]
; CHECK: exit:
; CHECK-NEXT: [[I_LCSSA:%.*]] = phi i32 [ [[I]], [[LOOP_1_BACKEDGE]] ]
; CHECK-NEXT: ret i32 [[I_LCSSA]]
;
preheader:
br label %loop_1
loop_1:
%i = phi i32 [ 0, %preheader ], [ %i.next, %loop_1_backedge ]
br label %loop_2
loop_2:
%j = phi i32 [ 0, %loop_1 ], [ %j.next, %loop_2_backedge ]
br label %loop_3
loop_3:
%k = phi i32 [ 0, %loop_2 ], [ %k.next, %loop_3_backedge ]
br i1 %cond1, label %loop_3_backedge, label %intermediate
intermediate:
br label %intermediate_loop
intermediate_loop:
br i1 %cond3, label %intermediate_loop, label %intermediate_exit
intermediate_exit:
br i1 false, label %loop_3_backedge, label %loop_2_backedge
loop_3_backedge:
%k.next = add i32 %k, 1
br i1 %cond2, label %loop_3, label %loop_2_backedge
loop_2_backedge:
%j.next = add i32 %j, 1
%c_2 = icmp slt i32 %j.next, %N
br i1 %c_2, label %loop_2, label %loop_1_backedge
loop_1_backedge:
%i.next = add i32 %i, 1
%c_1 = icmp slt i32 %i.next, %N
br i1 %c_1, label %loop_1, label %exit
exit:
ret i32 %i
}
define i32 @intermediate_subloop_switch_from_inner_to_parent(i1 %cond1, i1 %cond2, i1 %cond3, i32 %N) {
; CHECK-LABEL: @intermediate_subloop_switch_from_inner_to_parent(
; CHECK-NEXT: preheader:
; CHECK-NEXT: br label [[LOOP_1:%.*]]
; CHECK: loop_1:
; CHECK-NEXT: [[I:%.*]] = phi i32 [ 0, [[PREHEADER:%.*]] ], [ [[I_NEXT:%.*]], [[LOOP_1_BACKEDGE:%.*]] ]
; CHECK-NEXT: br label [[LOOP_2:%.*]]
; CHECK: loop_2:
; CHECK-NEXT: [[J:%.*]] = phi i32 [ 0, [[LOOP_1]] ], [ [[J_NEXT:%.*]], [[LOOP_2_BACKEDGE:%.*]] ]
; CHECK-NEXT: br label [[LOOP_3:%.*]]
; CHECK: loop_3:
; CHECK-NEXT: [[K:%.*]] = phi i32 [ 0, [[LOOP_2]] ], [ [[K_NEXT:%.*]], [[LOOP_3_BACKEDGE:%.*]] ]
; CHECK-NEXT: br i1 [[COND1:%.*]], label [[LOOP_3_BACKEDGE]], label [[INTERMEDIATE:%.*]]
; CHECK: intermediate:
; CHECK-NEXT: br label [[INTERMEDIATE_LOOP:%.*]]
; CHECK: intermediate_loop:
; CHECK-NEXT: br i1 [[COND3:%.*]], label [[INTERMEDIATE_LOOP]], label [[INTERMEDIATE_EXIT:%.*]]
; CHECK: intermediate_exit:
; CHECK-NEXT: switch i32 1, label [[LOOP_2_BACKEDGE]] [
; CHECK-NEXT: i32 0, label [[LOOP_3_BACKEDGE]]
; CHECK-NEXT: ]
; CHECK: loop_3_backedge:
; CHECK-NEXT: [[K_NEXT]] = add i32 [[K]], 1
; CHECK-NEXT: br i1 [[COND2:%.*]], label [[LOOP_3]], label [[LOOP_2_BACKEDGE]]
; CHECK: loop_2_backedge:
; CHECK-NEXT: [[J_NEXT]] = add i32 [[J]], 1
; CHECK-NEXT: [[C_2:%.*]] = icmp slt i32 [[J_NEXT]], [[N:%.*]]
; CHECK-NEXT: br i1 [[C_2]], label [[LOOP_2]], label [[LOOP_1_BACKEDGE]]
; CHECK: loop_1_backedge:
; CHECK-NEXT: [[I_NEXT]] = add i32 [[I]], 1
; CHECK-NEXT: [[C_1:%.*]] = icmp slt i32 [[I_NEXT]], [[N]]
; CHECK-NEXT: br i1 [[C_1]], label [[LOOP_1]], label [[EXIT:%.*]]
; CHECK: exit:
; CHECK-NEXT: [[I_LCSSA:%.*]] = phi i32 [ [[I]], [[LOOP_1_BACKEDGE]] ]
; CHECK-NEXT: ret i32 [[I_LCSSA]]
;
preheader:
br label %loop_1
loop_1:
%i = phi i32 [ 0, %preheader ], [ %i.next, %loop_1_backedge ]
br label %loop_2
loop_2:
%j = phi i32 [ 0, %loop_1 ], [ %j.next, %loop_2_backedge ]
br label %loop_3
loop_3:
%k = phi i32 [ 0, %loop_2 ], [ %k.next, %loop_3_backedge ]
br i1 %cond1, label %loop_3_backedge, label %intermediate
intermediate:
br label %intermediate_loop
intermediate_loop:
br i1 %cond3, label %intermediate_loop, label %intermediate_exit
intermediate_exit:
switch i32 1, label %loop_2_backedge [i32 0, label %loop_3_backedge]
loop_3_backedge:
%k.next = add i32 %k, 1
br i1 %cond2, label %loop_3, label %loop_2_backedge
loop_2_backedge:
%j.next = add i32 %j, 1
%c_2 = icmp slt i32 %j.next, %N
br i1 %c_2, label %loop_2, label %loop_1_backedge
loop_1_backedge:
%i.next = add i32 %i, 1
%c_1 = icmp slt i32 %i.next, %N
br i1 %c_1, label %loop_1, label %exit
exit:
ret i32 %i
}
define i32 @intermediate_complex_subloop_branch_from_inner_to_parent(i1 %cond1, i1 %cond2, i1 %cond3, i32 %N) {
; CHECK-LABEL: @intermediate_complex_subloop_branch_from_inner_to_parent(
; CHECK-NEXT: preheader:
; CHECK-NEXT: br label [[LOOP_1:%.*]]
; CHECK: loop_1:
; CHECK-NEXT: [[I:%.*]] = phi i32 [ 0, [[PREHEADER:%.*]] ], [ [[I_NEXT:%.*]], [[LOOP_1_BACKEDGE:%.*]] ]
; CHECK-NEXT: br label [[LOOP_2:%.*]]
; CHECK: loop_2:
; CHECK-NEXT: [[J:%.*]] = phi i32 [ 0, [[LOOP_1]] ], [ [[J_NEXT:%.*]], [[LOOP_2_BACKEDGE:%.*]] ]
; CHECK-NEXT: br label [[LOOP_3:%.*]]
; CHECK: loop_3:
; CHECK-NEXT: [[K:%.*]] = phi i32 [ 0, [[LOOP_2]] ], [ [[K_NEXT:%.*]], [[LOOP_3_BACKEDGE:%.*]] ]
; CHECK-NEXT: br i1 [[COND1:%.*]], label [[LOOP_3_BACKEDGE]], label [[INTERMEDIATE:%.*]]
; CHECK: intermediate:
; CHECK-NEXT: br label [[INTERMEDIATE_LOOP:%.*]]
; CHECK: intermediate_loop:
; CHECK-NEXT: br i1 [[COND3:%.*]], label [[INTERMEDIATE_LOOP_BACKEDGE:%.*]], label [[INTERMEDIATE_BLOCK:%.*]]
; CHECK: intermediate_loop.backedge:
; CHECK-NEXT: br label [[INTERMEDIATE_LOOP]]
; CHECK: intermediate_block:
; CHECK-NEXT: br i1 [[COND2:%.*]], label [[INTERMEDIATE_LOOP_BACKEDGE]], label [[INTERMEDIATE_EXIT:%.*]]
; CHECK: intermediate_exit:
; CHECK-NEXT: br i1 false, label [[LOOP_3_BACKEDGE]], label [[LOOP_2_BACKEDGE]]
; CHECK: loop_3_backedge:
; CHECK-NEXT: [[K_NEXT]] = add i32 [[K]], 1
; CHECK-NEXT: br i1 [[COND2]], label [[LOOP_3]], label [[LOOP_2_BACKEDGE]]
; CHECK: loop_2_backedge:
; CHECK-NEXT: [[J_NEXT]] = add i32 [[J]], 1
; CHECK-NEXT: [[C_2:%.*]] = icmp slt i32 [[J_NEXT]], [[N:%.*]]
; CHECK-NEXT: br i1 [[C_2]], label [[LOOP_2]], label [[LOOP_1_BACKEDGE]]
; CHECK: loop_1_backedge:
; CHECK-NEXT: [[I_NEXT]] = add i32 [[I]], 1
; CHECK-NEXT: [[C_1:%.*]] = icmp slt i32 [[I_NEXT]], [[N]]
; CHECK-NEXT: br i1 [[C_1]], label [[LOOP_1]], label [[EXIT:%.*]]
; CHECK: exit:
; CHECK-NEXT: [[I_LCSSA:%.*]] = phi i32 [ [[I]], [[LOOP_1_BACKEDGE]] ]
; CHECK-NEXT: ret i32 [[I_LCSSA]]
;
preheader:
br label %loop_1
loop_1:
%i = phi i32 [ 0, %preheader ], [ %i.next, %loop_1_backedge ]
br label %loop_2
loop_2:
%j = phi i32 [ 0, %loop_1 ], [ %j.next, %loop_2_backedge ]
br label %loop_3
loop_3:
%k = phi i32 [ 0, %loop_2 ], [ %k.next, %loop_3_backedge ]
br i1 %cond1, label %loop_3_backedge, label %intermediate
intermediate:
br label %intermediate_loop
intermediate_loop:
br i1 %cond3, label %intermediate_loop, label %intermediate_block
intermediate_block:
br i1 %cond2, label %intermediate_loop, label %intermediate_exit
intermediate_exit:
br i1 false, label %loop_3_backedge, label %loop_2_backedge
loop_3_backedge:
%k.next = add i32 %k, 1
br i1 %cond2, label %loop_3, label %loop_2_backedge
loop_2_backedge:
%j.next = add i32 %j, 1
%c_2 = icmp slt i32 %j.next, %N
br i1 %c_2, label %loop_2, label %loop_1_backedge
loop_1_backedge:
%i.next = add i32 %i, 1
%c_1 = icmp slt i32 %i.next, %N
br i1 %c_1, label %loop_1, label %exit
exit:
ret i32 %i
}
define i32 @intermediate_complex_subloop_switch_from_inner_to_parent(i1 %cond1, i1 %cond2, i1 %cond3, i32 %N) {
; CHECK-LABEL: @intermediate_complex_subloop_switch_from_inner_to_parent(
; CHECK-NEXT: preheader:
; CHECK-NEXT: br label [[LOOP_1:%.*]]
; CHECK: loop_1:
; CHECK-NEXT: [[I:%.*]] = phi i32 [ 0, [[PREHEADER:%.*]] ], [ [[I_NEXT:%.*]], [[LOOP_1_BACKEDGE:%.*]] ]
; CHECK-NEXT: br label [[LOOP_2:%.*]]
; CHECK: loop_2:
; CHECK-NEXT: [[J:%.*]] = phi i32 [ 0, [[LOOP_1]] ], [ [[J_NEXT:%.*]], [[LOOP_2_BACKEDGE:%.*]] ]
; CHECK-NEXT: br label [[LOOP_3:%.*]]
; CHECK: loop_3:
; CHECK-NEXT: [[K:%.*]] = phi i32 [ 0, [[LOOP_2]] ], [ [[K_NEXT:%.*]], [[LOOP_3_BACKEDGE:%.*]] ]
; CHECK-NEXT: br i1 [[COND1:%.*]], label [[LOOP_3_BACKEDGE]], label [[INTERMEDIATE:%.*]]
; CHECK: intermediate:
; CHECK-NEXT: br label [[INTERMEDIATE_LOOP:%.*]]
; CHECK: intermediate_loop:
; CHECK-NEXT: br i1 [[COND3:%.*]], label [[INTERMEDIATE_LOOP_BACKEDGE:%.*]], label [[INTERMEDIATE_BLOCK:%.*]]
; CHECK: intermediate_loop.backedge:
; CHECK-NEXT: br label [[INTERMEDIATE_LOOP]]
; CHECK: intermediate_block:
; CHECK-NEXT: br i1 [[COND2:%.*]], label [[INTERMEDIATE_LOOP_BACKEDGE]], label [[INTERMEDIATE_EXIT:%.*]]
; CHECK: intermediate_exit:
; CHECK-NEXT: switch i32 1, label [[LOOP_2_BACKEDGE]] [
; CHECK-NEXT: i32 0, label [[LOOP_3_BACKEDGE]]
; CHECK-NEXT: ]
; CHECK: loop_3_backedge:
; CHECK-NEXT: [[K_NEXT]] = add i32 [[K]], 1
; CHECK-NEXT: br i1 [[COND2]], label [[LOOP_3]], label [[LOOP_2_BACKEDGE]]
; CHECK: loop_2_backedge:
; CHECK-NEXT: [[J_NEXT]] = add i32 [[J]], 1
; CHECK-NEXT: [[C_2:%.*]] = icmp slt i32 [[J_NEXT]], [[N:%.*]]
; CHECK-NEXT: br i1 [[C_2]], label [[LOOP_2]], label [[LOOP_1_BACKEDGE]]
; CHECK: loop_1_backedge:
; CHECK-NEXT: [[I_NEXT]] = add i32 [[I]], 1
; CHECK-NEXT: [[C_1:%.*]] = icmp slt i32 [[I_NEXT]], [[N]]
; CHECK-NEXT: br i1 [[C_1]], label [[LOOP_1]], label [[EXIT:%.*]]
; CHECK: exit:
; CHECK-NEXT: [[I_LCSSA:%.*]] = phi i32 [ [[I]], [[LOOP_1_BACKEDGE]] ]
; CHECK-NEXT: ret i32 [[I_LCSSA]]
;
preheader:
br label %loop_1
loop_1:
%i = phi i32 [ 0, %preheader ], [ %i.next, %loop_1_backedge ]
br label %loop_2
loop_2:
%j = phi i32 [ 0, %loop_1 ], [ %j.next, %loop_2_backedge ]
br label %loop_3
loop_3:
%k = phi i32 [ 0, %loop_2 ], [ %k.next, %loop_3_backedge ]
br i1 %cond1, label %loop_3_backedge, label %intermediate
intermediate:
br label %intermediate_loop
intermediate_loop:
br i1 %cond3, label %intermediate_loop, label %intermediate_block
intermediate_block:
br i1 %cond2, label %intermediate_loop, label %intermediate_exit
intermediate_exit:
switch i32 1, label %loop_2_backedge [i32 0, label %loop_3_backedge]
loop_3_backedge:
%k.next = add i32 %k, 1
br i1 %cond2, label %loop_3, label %loop_2_backedge
loop_2_backedge:
%j.next = add i32 %j, 1
%c_2 = icmp slt i32 %j.next, %N
br i1 %c_2, label %loop_2, label %loop_1_backedge
loop_1_backedge:
%i.next = add i32 %i, 1
%c_1 = icmp slt i32 %i.next, %N
br i1 %c_1, label %loop_1, label %exit
exit:
ret i32 %i
}
define i32 @intermediate_complex_subloop_branch_from_inner_to_grandparent(i1 %cond1, i1 %cond2, i1 %cond3, i32 %N) {
; CHECK-LABEL: @intermediate_complex_subloop_branch_from_inner_to_grandparent(
; CHECK-NEXT: preheader:
; CHECK-NEXT: br label [[LOOP_1:%.*]]
; CHECK: loop_1:
; CHECK-NEXT: [[I:%.*]] = phi i32 [ 0, [[PREHEADER:%.*]] ], [ [[I_NEXT:%.*]], [[LOOP_1_BACKEDGE:%.*]] ]
; CHECK-NEXT: br label [[LOOP_2:%.*]]
; CHECK: loop_2:
; CHECK-NEXT: [[J:%.*]] = phi i32 [ 0, [[LOOP_1]] ], [ [[J_NEXT:%.*]], [[LOOP_2_BACKEDGE:%.*]] ]
; CHECK-NEXT: br label [[LOOP_3:%.*]]
; CHECK: loop_3:
; CHECK-NEXT: [[K:%.*]] = phi i32 [ 0, [[LOOP_2]] ], [ [[K_NEXT:%.*]], [[LOOP_3_BACKEDGE:%.*]] ]
; CHECK-NEXT: br i1 [[COND1:%.*]], label [[LOOP_3_BACKEDGE]], label [[INTERMEDIATE:%.*]]
; CHECK: intermediate:
; CHECK-NEXT: br label [[INTERMEDIATE_LOOP:%.*]]
; CHECK: intermediate_loop:
; CHECK-NEXT: br i1 [[COND3:%.*]], label [[INTERMEDIATE_LOOP_BACKEDGE:%.*]], label [[INTERMEDIATE_BLOCK:%.*]]
; CHECK: intermediate_loop.backedge:
; CHECK-NEXT: br label [[INTERMEDIATE_LOOP]]
; CHECK: intermediate_block:
; CHECK-NEXT: br i1 [[COND2:%.*]], label [[INTERMEDIATE_LOOP_BACKEDGE]], label [[INTERMEDIATE_EXIT:%.*]]
; CHECK: intermediate_exit:
; CHECK-NEXT: br i1 false, label [[LOOP_3_BACKEDGE]], label [[LOOP_1_BACKEDGE_LOOPEXIT:%.*]]
; CHECK: loop_3_backedge:
; CHECK-NEXT: [[K_NEXT]] = add i32 [[K]], 1
; CHECK-NEXT: br i1 [[COND2]], label [[LOOP_3]], label [[LOOP_2_BACKEDGE]]
; CHECK: loop_2_backedge:
; CHECK-NEXT: [[J_NEXT]] = add i32 [[J]], 1
; CHECK-NEXT: [[C_2:%.*]] = icmp slt i32 [[J_NEXT]], [[N:%.*]]
; CHECK-NEXT: br i1 [[C_2]], label [[LOOP_2]], label [[LOOP_1_BACKEDGE_LOOPEXIT1:%.*]]
; CHECK: loop_1_backedge.loopexit:
; CHECK-NEXT: br label [[LOOP_1_BACKEDGE]]
; CHECK: loop_1_backedge.loopexit1:
; CHECK-NEXT: br label [[LOOP_1_BACKEDGE]]
; CHECK: loop_1_backedge:
; CHECK-NEXT: [[I_NEXT]] = add i32 [[I]], 1
; CHECK-NEXT: [[C_1:%.*]] = icmp slt i32 [[I_NEXT]], [[N]]
; CHECK-NEXT: br i1 [[C_1]], label [[LOOP_1]], label [[EXIT:%.*]]
; CHECK: exit:
; CHECK-NEXT: [[I_LCSSA:%.*]] = phi i32 [ [[I]], [[LOOP_1_BACKEDGE]] ]
; CHECK-NEXT: ret i32 [[I_LCSSA]]
;
preheader:
br label %loop_1
loop_1:
%i = phi i32 [ 0, %preheader ], [ %i.next, %loop_1_backedge ]
br label %loop_2
loop_2:
%j = phi i32 [ 0, %loop_1 ], [ %j.next, %loop_2_backedge ]
br label %loop_3
loop_3:
%k = phi i32 [ 0, %loop_2 ], [ %k.next, %loop_3_backedge ]
br i1 %cond1, label %loop_3_backedge, label %intermediate
intermediate:
br label %intermediate_loop
intermediate_loop:
br i1 %cond3, label %intermediate_loop, label %intermediate_block
intermediate_block:
br i1 %cond2, label %intermediate_loop, label %intermediate_exit
intermediate_exit:
br i1 false, label %loop_3_backedge, label %loop_1_backedge
loop_3_backedge:
%k.next = add i32 %k, 1
br i1 %cond2, label %loop_3, label %loop_2_backedge
loop_2_backedge:
%j.next = add i32 %j, 1
%c_2 = icmp slt i32 %j.next, %N
br i1 %c_2, label %loop_2, label %loop_1_backedge
loop_1_backedge:
%i.next = add i32 %i, 1
%c_1 = icmp slt i32 %i.next, %N
br i1 %c_1, label %loop_1, label %exit
exit:
ret i32 %i
}
define i32 @intermediate_complex_subloop_switch_from_inner_to_grandparent(i1 %cond1, i1 %cond2, i1 %cond3, i32 %N) {
; CHECK-LABEL: @intermediate_complex_subloop_switch_from_inner_to_grandparent(
; CHECK-NEXT: preheader:
; CHECK-NEXT: br label [[LOOP_1:%.*]]
; CHECK: loop_1:
; CHECK-NEXT: [[I:%.*]] = phi i32 [ 0, [[PREHEADER:%.*]] ], [ [[I_NEXT:%.*]], [[LOOP_1_BACKEDGE:%.*]] ]
; CHECK-NEXT: br label [[LOOP_2:%.*]]
; CHECK: loop_2:
; CHECK-NEXT: [[J:%.*]] = phi i32 [ 0, [[LOOP_1]] ], [ [[J_NEXT:%.*]], [[LOOP_2_BACKEDGE:%.*]] ]
; CHECK-NEXT: br label [[LOOP_3:%.*]]
; CHECK: loop_3:
; CHECK-NEXT: [[K:%.*]] = phi i32 [ 0, [[LOOP_2]] ], [ [[K_NEXT:%.*]], [[LOOP_3_BACKEDGE:%.*]] ]
; CHECK-NEXT: br i1 [[COND1:%.*]], label [[LOOP_3_BACKEDGE]], label [[INTERMEDIATE:%.*]]
; CHECK: intermediate:
; CHECK-NEXT: br label [[INTERMEDIATE_LOOP:%.*]]
; CHECK: intermediate_loop:
; CHECK-NEXT: br i1 [[COND3:%.*]], label [[INTERMEDIATE_LOOP_BACKEDGE:%.*]], label [[INTERMEDIATE_BLOCK:%.*]]
; CHECK: intermediate_loop.backedge:
; CHECK-NEXT: br label [[INTERMEDIATE_LOOP]]
; CHECK: intermediate_block:
; CHECK-NEXT: br i1 [[COND2:%.*]], label [[INTERMEDIATE_LOOP_BACKEDGE]], label [[INTERMEDIATE_EXIT:%.*]]
; CHECK: intermediate_exit:
; CHECK-NEXT: switch i32 1, label [[LOOP_1_BACKEDGE_LOOPEXIT:%.*]] [
; CHECK-NEXT: i32 0, label [[LOOP_3_BACKEDGE]]
; CHECK-NEXT: ]
; CHECK: loop_3_backedge:
; CHECK-NEXT: [[K_NEXT]] = add i32 [[K]], 1
; CHECK-NEXT: br i1 [[COND2]], label [[LOOP_3]], label [[LOOP_2_BACKEDGE]]
; CHECK: loop_2_backedge:
; CHECK-NEXT: [[J_NEXT]] = add i32 [[J]], 1
; CHECK-NEXT: [[C_2:%.*]] = icmp slt i32 [[J_NEXT]], [[N:%.*]]
; CHECK-NEXT: br i1 [[C_2]], label [[LOOP_2]], label [[LOOP_1_BACKEDGE_LOOPEXIT1:%.*]]
; CHECK: loop_1_backedge.loopexit:
; CHECK-NEXT: br label [[LOOP_1_BACKEDGE]]
; CHECK: loop_1_backedge.loopexit1:
; CHECK-NEXT: br label [[LOOP_1_BACKEDGE]]
; CHECK: loop_1_backedge:
; CHECK-NEXT: [[I_NEXT]] = add i32 [[I]], 1
; CHECK-NEXT: [[C_1:%.*]] = icmp slt i32 [[I_NEXT]], [[N]]
; CHECK-NEXT: br i1 [[C_1]], label [[LOOP_1]], label [[EXIT:%.*]]
; CHECK: exit:
; CHECK-NEXT: [[I_LCSSA:%.*]] = phi i32 [ [[I]], [[LOOP_1_BACKEDGE]] ]
; CHECK-NEXT: ret i32 [[I_LCSSA]]
;
preheader:
br label %loop_1
loop_1:
%i = phi i32 [ 0, %preheader ], [ %i.next, %loop_1_backedge ]
br label %loop_2
loop_2:
%j = phi i32 [ 0, %loop_1 ], [ %j.next, %loop_2_backedge ]
br label %loop_3
loop_3:
%k = phi i32 [ 0, %loop_2 ], [ %k.next, %loop_3_backedge ]
br i1 %cond1, label %loop_3_backedge, label %intermediate
intermediate:
br label %intermediate_loop
intermediate_loop:
br i1 %cond3, label %intermediate_loop, label %intermediate_block
intermediate_block:
br i1 %cond2, label %intermediate_loop, label %intermediate_exit
intermediate_exit:
switch i32 1, label %loop_1_backedge [i32 0, label %loop_3_backedge]
loop_3_backedge:
%k.next = add i32 %k, 1
br i1 %cond2, label %loop_3, label %loop_2_backedge
loop_2_backedge:
%j.next = add i32 %j, 1
%c_2 = icmp slt i32 %j.next, %N
br i1 %c_2, label %loop_2, label %loop_1_backedge
loop_1_backedge:
%i.next = add i32 %i, 1
%c_1 = icmp slt i32 %i.next, %N
br i1 %c_1, label %loop_1, label %exit
exit:
ret i32 %i
}
define i32 @complex_dead_subloop_branch(i1 %cond1, i1 %cond2, i1 %cond3) {
; CHECK-LABEL: @complex_dead_subloop_branch(
; CHECK-NEXT: entry:
; CHECK-NEXT: br label [[LOOP:%.*]]
; CHECK: loop:
; CHECK-NEXT: br i1 [[COND3:%.*]], label [[LOOP]], label [[EXIT:%.*]]
; CHECK: exit:
; CHECK-NEXT: [[RESULT_LCSSA:%.*]] = phi i32 [ 0, [[LOOP]] ]
; CHECK-NEXT: ret i32 [[RESULT_LCSSA]]
;
entry:
br label %loop
loop:
br i1 true, label %latch, label %subloop
subloop:
br i1 %cond1, label %x, label %y
x:
br label %subloop_latch
y:
br label %subloop_latch
subloop_latch:
%dead_phi = phi i32 [ 1, %x ], [ 2, %y ]
br i1 %cond2, label %latch, label %subloop
latch:
%result = phi i32 [ 0, %loop ], [ %dead_phi, %subloop_latch ]
br i1 %cond3, label %loop, label %exit
exit:
ret i32 %result
}
define i32 @complex_dead_subloop_switch(i1 %cond1, i1 %cond2, i1 %cond3) {
; CHECK-LABEL: @complex_dead_subloop_switch(
; CHECK-NEXT: entry:
; CHECK-NEXT: br label [[LOOP:%.*]]
; CHECK: loop:
; CHECK-NEXT: br i1 [[COND3:%.*]], label [[LOOP]], label [[EXIT:%.*]]
; CHECK: exit:
; CHECK-NEXT: [[RESULT_LCSSA:%.*]] = phi i32 [ 0, [[LOOP]] ]
; CHECK-NEXT: ret i32 [[RESULT_LCSSA]]
;
entry:
br label %loop
loop:
switch i32 1, label %latch [ i32 0, label %subloop ]
subloop:
br i1 %cond1, label %x, label %y
x:
br label %subloop_latch
y:
br label %subloop_latch
subloop_latch:
%dead_phi = phi i32 [ 1, %x ], [ 2, %y ]
br i1 %cond2, label %latch, label %subloop
latch:
%result = phi i32 [ 0, %loop ], [ %dead_phi, %subloop_latch ]
br i1 %cond3, label %loop, label %exit
exit:
ret i32 %result
}
define void @test_crash_01() {
; CHECK-LABEL: @test_crash_01(
; CHECK-NEXT: bb:
; CHECK-NEXT: br label [[BB1:%.*]]
; CHECK: bb1:
; CHECK-NEXT: br i1 undef, label [[BB17:%.*]], label [[BB2:%.*]]
; CHECK: bb2:
; CHECK-NEXT: switch i32 0, label [[BB2_SPLIT:%.*]] [
; CHECK-NEXT: i32 1, label [[BB19:%.*]]
; CHECK-NEXT: ]
; CHECK: bb2.split:
; CHECK-NEXT: br label [[BB3:%.*]]
; CHECK: bb3:
; CHECK-NEXT: switch i32 undef, label [[BB16:%.*]] [
; CHECK-NEXT: i32 0, label [[BB15:%.*]]
; CHECK-NEXT: i32 1, label [[BB14:%.*]]
; CHECK-NEXT: i32 2, label [[BB13:%.*]]
; CHECK-NEXT: i32 3, label [[BB12:%.*]]
; CHECK-NEXT: i32 4, label [[BB11:%.*]]
; CHECK-NEXT: i32 5, label [[BB8:%.*]]
; CHECK-NEXT: i32 6, label [[BB10:%.*]]
; CHECK-NEXT: i32 7, label [[BB9:%.*]]
; CHECK-NEXT: i32 8, label [[BB7:%.*]]
; CHECK-NEXT: ]
; CHECK: bb7:
; CHECK-NEXT: unreachable
; CHECK: bb8:
; CHECK-NEXT: switch i32 undef, label [[BB28:%.*]] [
; CHECK-NEXT: i32 0, label [[BB27:%.*]]
; CHECK-NEXT: i32 1, label [[BB26:%.*]]
; CHECK-NEXT: i32 2, label [[BB23:%.*]]
; CHECK-NEXT: i32 3, label [[BB24:%.*]]
; CHECK-NEXT: i32 4, label [[BB25:%.*]]
; CHECK-NEXT: i32 5, label [[BB29:%.*]]
; CHECK-NEXT: i32 6, label [[BB22:%.*]]
; CHECK-NEXT: i32 7, label [[BB20:%.*]]
; CHECK-NEXT: i32 8, label [[BB21:%.*]]
; CHECK-NEXT: ]
; CHECK: bb9:
; CHECK-NEXT: unreachable
; CHECK: bb10:
; CHECK-NEXT: unreachable
; CHECK: bb11:
; CHECK-NEXT: br label [[BB8]]
; CHECK: bb12:
; CHECK-NEXT: unreachable
; CHECK: bb13:
; CHECK-NEXT: unreachable
; CHECK: bb14:
; CHECK-NEXT: unreachable
; CHECK: bb15:
; CHECK-NEXT: unreachable
; CHECK: bb16:
; CHECK-NEXT: unreachable
; CHECK: bb17:
; CHECK-NEXT: ret void
; CHECK: bb19:
; CHECK-NEXT: ret void
; CHECK: bb20:
; CHECK-NEXT: unreachable
; CHECK: bb21:
; CHECK-NEXT: unreachable
; CHECK: bb22:
; CHECK-NEXT: unreachable
; CHECK: bb23:
; CHECK-NEXT: unreachable
; CHECK: bb24:
; CHECK-NEXT: unreachable
; CHECK: bb25:
; CHECK-NEXT: unreachable
; CHECK: bb26:
; CHECK-NEXT: unreachable
; CHECK: bb27:
; CHECK-NEXT: unreachable
; CHECK: bb28:
; CHECK-NEXT: unreachable
; CHECK: bb29:
; CHECK-NEXT: br label [[BB3]]
;
bb:
br label %bb1
bb1: ; preds = %bb
br i1 undef, label %bb17, label %bb2
bb2: ; preds = %bb1
br label %bb3
bb3: ; preds = %bb6, %bb2
br label %bb4
bb4: ; preds = %bb3
switch i32 0, label %bb5 [
i32 1, label %bb19
i32 2, label %bb18
]
bb5: ; preds = %bb4
switch i32 undef, label %bb16 [
i32 0, label %bb15
i32 1, label %bb14
i32 2, label %bb13
i32 3, label %bb12
i32 4, label %bb11
i32 5, label %bb8
i32 6, label %bb10
i32 7, label %bb9
i32 8, label %bb7
]
bb6: ; preds = %bb29, %bb18
br label %bb3
bb7: ; preds = %bb5
unreachable
bb8: ; preds = %bb11, %bb5
switch i32 undef, label %bb28 [
i32 0, label %bb27
i32 1, label %bb26
i32 2, label %bb23
i32 3, label %bb24
i32 4, label %bb25
i32 5, label %bb29
i32 6, label %bb22
i32 7, label %bb20
i32 8, label %bb21
]
bb9: ; preds = %bb5
unreachable
bb10: ; preds = %bb5
unreachable
bb11: ; preds = %bb5
br label %bb8
bb12: ; preds = %bb5
unreachable
bb13: ; preds = %bb5
unreachable
bb14: ; preds = %bb5
unreachable
bb15: ; preds = %bb5
unreachable
bb16: ; preds = %bb5
unreachable
bb17: ; preds = %bb1
ret void
bb18: ; preds = %bb4
br label %bb6
bb19: ; preds = %bb4
ret void
bb20: ; preds = %bb8
unreachable
bb21: ; preds = %bb8
unreachable
bb22: ; preds = %bb8
unreachable
bb23: ; preds = %bb8
unreachable
bb24: ; preds = %bb8
unreachable
bb25: ; preds = %bb8
unreachable
bb26: ; preds = %bb8
unreachable
bb27: ; preds = %bb8
unreachable
bb28: ; preds = %bb8
unreachable
bb29: ; preds = %bb8
br label %bb6
}