This is a more general alternative/extension to D102635. Rather than handling the special case of "header exit with non-exiting latch", this unrolls against the smallest exact trip count from any exit. The latch exit is no longer treated as priviledged when it comes to full unrolling. The motivating case is in full-unroll-one-unpredictable-exit.ll. Here the header exit is an IV-based exit, while the latch exit is a data comparison. This kind of loop does not get rotated, because the latch is already exiting, and loop rotation doesn't try to distinguish IV-based/analyzable latches. Differential Revision: https://reviews.llvm.org/D102982
671 lines
21 KiB
LLVM
671 lines
21 KiB
LLVM
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
|
|
; RUN: opt < %s -S -loop-unroll -verify-loop-info | FileCheck %s
|
|
; RUN: opt < %s -S -passes='require<opt-remark-emit>,loop-unroll,verify<loops>' | FileCheck %s
|
|
;
|
|
; Unit tests for LoopInfo::markAsRemoved.
|
|
|
|
declare i1 @check() nounwind
|
|
|
|
; Ensure that tail->inner is removed and rely on verify-loopinfo to
|
|
; check soundness.
|
|
define void @skiplevelexit() nounwind {
|
|
; CHECK-LABEL: @skiplevelexit(
|
|
; CHECK-NEXT: entry:
|
|
; CHECK-NEXT: br label [[OUTER:%.*]]
|
|
; CHECK: outer:
|
|
; CHECK-NEXT: br label [[INNER:%.*]]
|
|
; CHECK: inner:
|
|
; CHECK-NEXT: [[TMP0:%.*]] = call zeroext i1 @check()
|
|
; CHECK-NEXT: br i1 true, label [[OUTER_BACKEDGE:%.*]], label [[TAIL:%.*]]
|
|
; CHECK: tail:
|
|
; CHECK-NEXT: ret void
|
|
; CHECK: outer.backedge:
|
|
; CHECK-NEXT: br label [[OUTER]]
|
|
;
|
|
entry:
|
|
br label %outer
|
|
|
|
outer:
|
|
br label %inner
|
|
|
|
inner:
|
|
%iv = phi i32 [ 0, %outer ], [ %inc, %tail ]
|
|
%inc = add i32 %iv, 1
|
|
call zeroext i1 @check()
|
|
br i1 true, label %outer.backedge, label %tail
|
|
|
|
tail:
|
|
br i1 false, label %inner, label %exit
|
|
|
|
outer.backedge:
|
|
br label %outer
|
|
|
|
exit:
|
|
ret void
|
|
}
|
|
|
|
; Remove the middle loop of a triply nested loop tree.
|
|
; Ensure that only the middle loop is removed and rely on verify-loopinfo to
|
|
; check soundness.
|
|
define void @unloopNested() {
|
|
; CHECK-LABEL: @unloopNested(
|
|
; CHECK-NEXT: entry:
|
|
; CHECK-NEXT: br label [[WHILE_COND_OUTER:%.*]]
|
|
; CHECK: while.cond.outer:
|
|
; CHECK-NEXT: br label [[WHILE_COND:%.*]]
|
|
; CHECK: while.cond:
|
|
; CHECK-NEXT: [[CMP:%.*]] = call zeroext i1 @check()
|
|
; CHECK-NEXT: br i1 [[CMP]], label [[WHILE_BODY:%.*]], label [[WHILE_END:%.*]]
|
|
; CHECK: while.body:
|
|
; CHECK-NEXT: [[CMP3:%.*]] = call zeroext i1 @check()
|
|
; CHECK-NEXT: br i1 [[CMP3]], label [[IF_THEN:%.*]], label [[IF_END:%.*]]
|
|
; CHECK: if.then:
|
|
; CHECK-NEXT: br label [[RETURN:%.*]]
|
|
; CHECK: if.end:
|
|
; CHECK-NEXT: [[CMP_I48:%.*]] = call zeroext i1 @check()
|
|
; CHECK-NEXT: br i1 [[CMP_I48]], label [[IF_THEN_I:%.*]], label [[IF_ELSE20_I:%.*]]
|
|
; CHECK: if.then.i:
|
|
; CHECK-NEXT: [[CMP8_I:%.*]] = call zeroext i1 @check()
|
|
; CHECK-NEXT: br i1 [[CMP8_I]], label [[MERGE:%.*]], label [[IF_ELSE_I:%.*]]
|
|
; CHECK: if.else.i:
|
|
; CHECK-NEXT: br label [[MERGE]]
|
|
; CHECK: if.else20.i:
|
|
; CHECK-NEXT: [[CMP25_I:%.*]] = call zeroext i1 @check()
|
|
; CHECK-NEXT: br i1 [[CMP25_I]], label [[MERGE]], label [[IF_ELSE28_I:%.*]]
|
|
; CHECK: if.else28.i:
|
|
; CHECK-NEXT: br label [[MERGE]]
|
|
; CHECK: merge:
|
|
; CHECK-NEXT: br label [[WHILE_COND2_I:%.*]]
|
|
; CHECK: while.cond2.i:
|
|
; CHECK-NEXT: [[CMP_I:%.*]] = call zeroext i1 @check()
|
|
; CHECK-NEXT: br i1 [[CMP_I]], label [[WHILE_COND2_BACKEDGE_I:%.*]], label [[WHILE_END_I:%.*]]
|
|
; CHECK: while.cond2.backedge.i:
|
|
; CHECK-NEXT: br label [[WHILE_COND2_I]]
|
|
; CHECK: while.end.i:
|
|
; CHECK-NEXT: [[CMP1114_I:%.*]] = call zeroext i1 @check()
|
|
; CHECK-NEXT: br i1 [[CMP1114_I]], label [[WHILE_BODY12_LR_PH_I:%.*]], label [[WHILE_END14_I:%.*]]
|
|
; CHECK: while.body12.lr.ph.i:
|
|
; CHECK-NEXT: br label [[WHILE_END14_I]]
|
|
; CHECK: while.end14.i:
|
|
; CHECK-NEXT: [[CALL15_I:%.*]] = call zeroext i1 @check()
|
|
; CHECK-NEXT: br i1 [[CALL15_I]], label [[IF_END_I:%.*]], label [[EXIT:%.*]]
|
|
; CHECK: if.end.i:
|
|
; CHECK-NEXT: br label [[WHILE_COND2_BACKEDGE_I]]
|
|
; CHECK: exit:
|
|
; CHECK-NEXT: br label [[WHILE_COND_OUTER]]
|
|
; CHECK: while.end:
|
|
; CHECK-NEXT: br label [[RETURN]]
|
|
; CHECK: return:
|
|
; CHECK-NEXT: ret void
|
|
;
|
|
entry:
|
|
br label %while.cond.outer
|
|
|
|
while.cond.outer:
|
|
br label %while.cond
|
|
|
|
while.cond:
|
|
%cmp = call zeroext i1 @check()
|
|
br i1 %cmp, label %while.body, label %while.end
|
|
|
|
while.body:
|
|
%cmp3 = call zeroext i1 @check()
|
|
br i1 %cmp3, label %if.then, label %if.end
|
|
|
|
if.then:
|
|
br label %return
|
|
|
|
if.end:
|
|
%cmp.i48 = call zeroext i1 @check()
|
|
br i1 %cmp.i48, label %if.then.i, label %if.else20.i
|
|
|
|
if.then.i:
|
|
%cmp8.i = call zeroext i1 @check()
|
|
br i1 %cmp8.i, label %merge, label %if.else.i
|
|
|
|
if.else.i:
|
|
br label %merge
|
|
|
|
if.else20.i:
|
|
%cmp25.i = call zeroext i1 @check()
|
|
br i1 %cmp25.i, label %merge, label %if.else28.i
|
|
|
|
if.else28.i:
|
|
br label %merge
|
|
|
|
merge:
|
|
br label %while.cond2.i
|
|
|
|
while.cond2.i:
|
|
%cmp.i = call zeroext i1 @check()
|
|
br i1 %cmp.i, label %while.cond2.backedge.i, label %while.end.i
|
|
|
|
while.cond2.backedge.i:
|
|
br label %while.cond2.i
|
|
|
|
while.end.i:
|
|
%cmp1114.i = call zeroext i1 @check()
|
|
br i1 %cmp1114.i, label %while.body12.lr.ph.i, label %while.end14.i
|
|
|
|
while.body12.lr.ph.i:
|
|
br label %while.end14.i
|
|
|
|
while.end14.i:
|
|
%call15.i = call zeroext i1 @check()
|
|
br i1 %call15.i, label %if.end.i, label %exit
|
|
|
|
if.end.i:
|
|
br label %while.cond2.backedge.i
|
|
|
|
exit:
|
|
br i1 false, label %while.cond, label %if.else
|
|
|
|
if.else:
|
|
br label %while.cond.outer
|
|
|
|
while.end:
|
|
br label %return
|
|
|
|
return:
|
|
ret void
|
|
}
|
|
|
|
; Remove the middle loop of a deeply nested loop tree.
|
|
; Ensure that only the middle loop is removed and rely on verify-loopinfo to
|
|
; check soundness.
|
|
;
|
|
; This test must be disabled until trip count computation can be optimized...
|
|
; rdar:14038809 [SCEV]: Optimize trip count computation for multi-exit loops.
|
|
define void @unloopDeepNested() nounwind {
|
|
; CHECK-LABEL: @unloopDeepNested(
|
|
; CHECK-NEXT: for.cond8.preheader.i:
|
|
; CHECK-NEXT: [[CMP113_I:%.*]] = call zeroext i1 @check()
|
|
; CHECK-NEXT: br i1 [[CMP113_I]], label [[MAKE_DATA_EXIT:%.*]], label [[FOR_BODY13_LR_PH_I:%.*]]
|
|
; CHECK: for.body13.lr.ph.i:
|
|
; CHECK-NEXT: br label [[MAKE_DATA_EXIT]]
|
|
; CHECK: make_data.exit:
|
|
; CHECK-NEXT: br label [[WHILE_COND_OUTER_OUTER:%.*]]
|
|
; CHECK: while.cond.outer.outer:
|
|
; CHECK-NEXT: br label [[WHILE_COND_OUTER:%.*]]
|
|
; CHECK: while.cond.outer:
|
|
; CHECK-NEXT: br label [[WHILE_COND:%.*]]
|
|
; CHECK: while.cond:
|
|
; CHECK-NEXT: br label [[WHILE_COND_OUTER_I:%.*]]
|
|
; CHECK: while.cond.outer.i:
|
|
; CHECK-NEXT: [[TMP192_PH_I:%.*]] = call zeroext i1 @check()
|
|
; CHECK-NEXT: br i1 [[TMP192_PH_I]], label [[WHILE_COND_OUTER_SPLIT_US_I:%.*]], label [[WHILE_BODY_LOOPEXIT:%.*]]
|
|
; CHECK: while.cond.outer.split.us.i:
|
|
; CHECK-NEXT: br label [[WHILE_COND_US_I:%.*]]
|
|
; CHECK: while.cond.us.i:
|
|
; CHECK-NEXT: [[CMP_US_I:%.*]] = call zeroext i1 @check()
|
|
; CHECK-NEXT: br i1 [[CMP_US_I]], label [[NEXT_DATA_EXIT:%.*]], label [[WHILE_BODY_US_I:%.*]]
|
|
; CHECK: while.body.us.i:
|
|
; CHECK-NEXT: [[CMP7_US_I:%.*]] = call zeroext i1 @check()
|
|
; CHECK-NEXT: br i1 [[CMP7_US_I]], label [[IF_THEN_US_I:%.*]], label [[IF_ELSE_I:%.*]]
|
|
; CHECK: if.then.us.i:
|
|
; CHECK-NEXT: br label [[WHILE_COND_US_I]]
|
|
; CHECK: if.else.i:
|
|
; CHECK-NEXT: br label [[WHILE_COND_OUTER_I]]
|
|
; CHECK: next_data.exit:
|
|
; CHECK-NEXT: [[TMP192_PH_I_LCSSA28:%.*]] = call zeroext i1 @check()
|
|
; CHECK-NEXT: br i1 [[TMP192_PH_I_LCSSA28]], label [[WHILE_END:%.*]], label [[WHILE_BODY:%.*]]
|
|
; CHECK: while.body.loopexit:
|
|
; CHECK-NEXT: br label [[WHILE_BODY]]
|
|
; CHECK: while.body:
|
|
; CHECK-NEXT: br label [[WHILE_COND_I:%.*]]
|
|
; CHECK: while.cond.i:
|
|
; CHECK-NEXT: [[CMP_I:%.*]] = call zeroext i1 @check()
|
|
; CHECK-NEXT: br i1 [[CMP_I]], label [[VALID_DATA_EXIT:%.*]], label [[WHILE_BODY_I:%.*]]
|
|
; CHECK: while.body.i:
|
|
; CHECK-NEXT: [[CMP7_I:%.*]] = call zeroext i1 @check()
|
|
; CHECK-NEXT: br i1 [[CMP7_I]], label [[VALID_DATA_EXIT]], label [[IF_END_I:%.*]]
|
|
; CHECK: if.end.i:
|
|
; CHECK-NEXT: br label [[WHILE_COND_I]]
|
|
; CHECK: valid_data.exit:
|
|
; CHECK-NEXT: [[CMP:%.*]] = call zeroext i1 @check()
|
|
; CHECK-NEXT: br i1 [[CMP]], label [[IF_THEN12:%.*]], label [[IF_END:%.*]]
|
|
; CHECK: if.then12:
|
|
; CHECK-NEXT: br label [[IF_END]]
|
|
; CHECK: if.end:
|
|
; CHECK-NEXT: [[TOBOOL3_I:%.*]] = call zeroext i1 @check()
|
|
; CHECK-NEXT: br i1 [[TOBOOL3_I]], label [[COPY_DATA_EXIT:%.*]], label [[WHILE_BODY_LR_PH_I:%.*]]
|
|
; CHECK: while.body.lr.ph.i:
|
|
; CHECK-NEXT: br label [[COPY_DATA_EXIT]]
|
|
; CHECK: copy_data.exit:
|
|
; CHECK-NEXT: [[CMP38:%.*]] = call zeroext i1 @check()
|
|
; CHECK-NEXT: br i1 [[CMP38]], label [[IF_THEN39:%.*]], label [[WHILE_COND_OUTER]]
|
|
; CHECK: if.then39:
|
|
; CHECK-NEXT: [[CMP5_I:%.*]] = call zeroext i1 @check()
|
|
; CHECK-NEXT: br i1 [[CMP5_I]], label [[WHILE_COND_OUTER_OUTER_BACKEDGE:%.*]], label [[FOR_COND8_PREHEADER_I8_THREAD:%.*]]
|
|
; CHECK: for.cond8.preheader.i8.thread:
|
|
; CHECK-NEXT: br label [[WHILE_COND_OUTER_OUTER_BACKEDGE]]
|
|
; CHECK: while.cond.outer.outer.backedge:
|
|
; CHECK-NEXT: br label [[WHILE_COND_OUTER_OUTER]]
|
|
; CHECK: while.end:
|
|
; CHECK-NEXT: ret void
|
|
;
|
|
for.cond8.preheader.i:
|
|
%cmp113.i = call zeroext i1 @check()
|
|
br i1 %cmp113.i, label %make_data.exit, label %for.body13.lr.ph.i
|
|
|
|
for.body13.lr.ph.i:
|
|
br label %make_data.exit
|
|
|
|
make_data.exit:
|
|
br label %while.cond.outer.outer
|
|
|
|
while.cond.outer.outer:
|
|
br label %while.cond.outer
|
|
|
|
while.cond.outer:
|
|
br label %while.cond
|
|
|
|
while.cond:
|
|
br label %while.cond.outer.i
|
|
|
|
while.cond.outer.i:
|
|
%tmp192.ph.i = call zeroext i1 @check()
|
|
br i1 %tmp192.ph.i, label %while.cond.outer.split.us.i, label %while.body.loopexit
|
|
|
|
while.cond.outer.split.us.i:
|
|
br label %while.cond.us.i
|
|
|
|
while.cond.us.i:
|
|
%cmp.us.i = call zeroext i1 @check()
|
|
br i1 %cmp.us.i, label %next_data.exit, label %while.body.us.i
|
|
|
|
while.body.us.i:
|
|
%cmp7.us.i = call zeroext i1 @check()
|
|
br i1 %cmp7.us.i, label %if.then.us.i, label %if.else.i
|
|
|
|
if.then.us.i:
|
|
br label %while.cond.us.i
|
|
|
|
if.else.i:
|
|
br label %while.cond.outer.i
|
|
|
|
next_data.exit:
|
|
%tmp192.ph.i.lcssa28 = call zeroext i1 @check()
|
|
br i1 %tmp192.ph.i.lcssa28, label %while.end, label %while.body
|
|
|
|
while.body.loopexit:
|
|
br label %while.body
|
|
|
|
while.body:
|
|
br label %while.cond.i
|
|
|
|
while.cond.i:
|
|
%cmp.i = call zeroext i1 @check()
|
|
br i1 %cmp.i, label %valid_data.exit, label %while.body.i
|
|
|
|
while.body.i:
|
|
%cmp7.i = call zeroext i1 @check()
|
|
br i1 %cmp7.i, label %valid_data.exit, label %if.end.i
|
|
|
|
if.end.i:
|
|
br label %while.cond.i
|
|
|
|
valid_data.exit:
|
|
br i1 true, label %if.then, label %while.cond
|
|
|
|
if.then:
|
|
%cmp = call zeroext i1 @check()
|
|
br i1 %cmp, label %if.then12, label %if.end
|
|
|
|
if.then12:
|
|
br label %if.end
|
|
|
|
if.end:
|
|
%tobool3.i = call zeroext i1 @check()
|
|
br i1 %tobool3.i, label %copy_data.exit, label %while.body.lr.ph.i
|
|
|
|
while.body.lr.ph.i:
|
|
br label %copy_data.exit
|
|
|
|
copy_data.exit:
|
|
%cmp38 = call zeroext i1 @check()
|
|
br i1 %cmp38, label %if.then39, label %while.cond.outer
|
|
|
|
if.then39:
|
|
%cmp5.i = call zeroext i1 @check()
|
|
br i1 %cmp5.i, label %while.cond.outer.outer.backedge, label %for.cond8.preheader.i8.thread
|
|
|
|
for.cond8.preheader.i8.thread:
|
|
br label %while.cond.outer.outer.backedge
|
|
|
|
while.cond.outer.outer.backedge:
|
|
br label %while.cond.outer.outer
|
|
|
|
while.end:
|
|
ret void
|
|
}
|
|
|
|
; Remove a nested loop with irreducible control flow.
|
|
; Ensure that only the middle loop is removed and rely on verify-loopinfo to
|
|
; check soundness.
|
|
define void @unloopIrreducible() nounwind {
|
|
; CHECK-LABEL: @unloopIrreducible(
|
|
; CHECK-NEXT: entry:
|
|
; CHECK-NEXT: br label [[FOR_BODY:%.*]]
|
|
; CHECK: for.body:
|
|
; CHECK-NEXT: [[CMP2113:%.*]] = call zeroext i1 @check()
|
|
; CHECK-NEXT: br i1 [[CMP2113]], label [[FOR_BODY22_LR_PH:%.*]], label [[FOR_INC163:%.*]]
|
|
; CHECK: for.body22.lr.ph:
|
|
; CHECK-NEXT: br label [[FOR_BODY22:%.*]]
|
|
; CHECK: for.body22:
|
|
; CHECK-NEXT: br label [[FOR_BODY33:%.*]]
|
|
; CHECK: for.body33:
|
|
; CHECK-NEXT: br label [[FOR_END:%.*]]
|
|
; CHECK: for.end:
|
|
; CHECK-NEXT: [[CMP424:%.*]] = call zeroext i1 @check()
|
|
; CHECK-NEXT: br i1 [[CMP424]], label [[FOR_BODY43_LR_PH:%.*]], label [[FOR_END93:%.*]]
|
|
; CHECK: for.body43.lr.ph:
|
|
; CHECK-NEXT: br label [[FOR_END93]]
|
|
; CHECK: for.end93:
|
|
; CHECK-NEXT: [[CMP96:%.*]] = call zeroext i1 @check()
|
|
; CHECK-NEXT: br i1 [[CMP96]], label [[IF_THEN97:%.*]], label [[FOR_COND103:%.*]]
|
|
; CHECK: if.then97:
|
|
; CHECK-NEXT: br label [[FOR_COND103T:%.*]]
|
|
; CHECK: for.cond103t:
|
|
; CHECK-NEXT: br label [[FOR_COND103]]
|
|
; CHECK: for.cond103:
|
|
; CHECK-NEXT: [[CMP105:%.*]] = call zeroext i1 @check()
|
|
; CHECK-NEXT: br i1 [[CMP105]], label [[FOR_BODY106:%.*]], label [[FOR_END120:%.*]]
|
|
; CHECK: for.body106:
|
|
; CHECK-NEXT: [[CMP108:%.*]] = call zeroext i1 @check()
|
|
; CHECK-NEXT: br i1 [[CMP108]], label [[IF_THEN109:%.*]], label [[FOR_INC117:%.*]]
|
|
; CHECK: if.then109:
|
|
; CHECK-NEXT: br label [[FOR_INC117]]
|
|
; CHECK: for.inc117:
|
|
; CHECK-NEXT: br label [[FOR_COND103T]]
|
|
; CHECK: for.end120:
|
|
; CHECK-NEXT: br label [[FOR_INC159:%.*]]
|
|
; CHECK: for.inc159:
|
|
; CHECK-NEXT: br label [[FOR_INC163]]
|
|
; CHECK: for.inc163:
|
|
; CHECK-NEXT: [[CMP12:%.*]] = call zeroext i1 @check()
|
|
; CHECK-NEXT: br i1 [[CMP12]], label [[FOR_BODY]], label [[FOR_END166:%.*]]
|
|
; CHECK: for.end166:
|
|
; CHECK-NEXT: ret void
|
|
;
|
|
entry:
|
|
br label %for.body
|
|
|
|
for.body:
|
|
%cmp2113 = call zeroext i1 @check()
|
|
br i1 %cmp2113, label %for.body22.lr.ph, label %for.inc163
|
|
|
|
for.body22.lr.ph:
|
|
br label %for.body22
|
|
|
|
for.body22:
|
|
br label %for.body33
|
|
|
|
for.body33:
|
|
br label %for.end
|
|
|
|
for.end:
|
|
%cmp424 = call zeroext i1 @check()
|
|
br i1 %cmp424, label %for.body43.lr.ph, label %for.end93
|
|
|
|
for.body43.lr.ph:
|
|
br label %for.end93
|
|
|
|
for.end93:
|
|
%cmp96 = call zeroext i1 @check()
|
|
br i1 %cmp96, label %if.then97, label %for.cond103
|
|
|
|
if.then97:
|
|
br label %for.cond103t
|
|
|
|
for.cond103t:
|
|
br label %for.cond103
|
|
|
|
for.cond103:
|
|
%cmp105 = call zeroext i1 @check()
|
|
br i1 %cmp105, label %for.body106, label %for.end120
|
|
|
|
for.body106:
|
|
%cmp108 = call zeroext i1 @check()
|
|
br i1 %cmp108, label %if.then109, label %for.inc117
|
|
|
|
if.then109:
|
|
br label %for.inc117
|
|
|
|
for.inc117:
|
|
br label %for.cond103t
|
|
|
|
for.end120:
|
|
br label %for.inc159
|
|
|
|
for.inc159:
|
|
br i1 false, label %for.body22, label %for.cond15.for.inc163_crit_edge
|
|
|
|
for.cond15.for.inc163_crit_edge:
|
|
br label %for.inc163
|
|
|
|
for.inc163:
|
|
%cmp12 = call zeroext i1 @check()
|
|
br i1 %cmp12, label %for.body, label %for.end166
|
|
|
|
for.end166:
|
|
ret void
|
|
|
|
}
|
|
|
|
; Remove a loop whose exit branches into a sibling loop.
|
|
; Ensure that only the loop is removed and rely on verify-loopinfo to
|
|
; check soundness.
|
|
define void @unloopCriticalEdge() nounwind {
|
|
; CHECK-LABEL: @unloopCriticalEdge(
|
|
; CHECK-NEXT: entry:
|
|
; CHECK-NEXT: br label [[FOR_COND31:%.*]]
|
|
; CHECK: for.cond31:
|
|
; CHECK-NEXT: br i1 false, label [[FOR_BODY35:%.*]], label [[FOR_END94:%.*]]
|
|
; CHECK: for.body35:
|
|
; CHECK-NEXT: br label [[WHILE_COND_I_PREHEADER:%.*]]
|
|
; CHECK: while.cond.i.preheader:
|
|
; CHECK-NEXT: br i1 undef, label [[WHILE_COND_I_PREHEADER_SPLIT:%.*]], label [[WHILE_COND_OUTER_I_LOOPEXIT_SPLIT:%.*]]
|
|
; CHECK: while.cond.i.preheader.split:
|
|
; CHECK-NEXT: br label [[WHILE_COND_I:%.*]]
|
|
; CHECK: while.cond.i:
|
|
; CHECK-NEXT: br i1 true, label [[WHILE_COND_I]], label [[WHILE_COND_OUTER_I_LOOPEXIT:%.*]]
|
|
; CHECK: while.cond.outer.i.loopexit:
|
|
; CHECK-NEXT: br label [[WHILE_COND_OUTER_I_LOOPEXIT_SPLIT]]
|
|
; CHECK: while.cond.outer.i.loopexit.split:
|
|
; CHECK-NEXT: br label [[WHILE_BODY:%.*]]
|
|
; CHECK: while.body:
|
|
; CHECK-NEXT: br label [[FOR_END78:%.*]]
|
|
; CHECK: for.end78:
|
|
; CHECK-NEXT: br i1 false, label [[PROC2_EXIT:%.*]], label [[FOR_COND_I_PREHEADER:%.*]]
|
|
; CHECK: for.cond.i.preheader:
|
|
; CHECK-NEXT: br label [[FOR_COND_I:%.*]]
|
|
; CHECK: for.cond.i:
|
|
; CHECK-NEXT: br label [[FOR_COND_I]]
|
|
; CHECK: Proc2.exit:
|
|
; CHECK-NEXT: unreachable
|
|
; CHECK: for.end94:
|
|
; CHECK-NEXT: ret void
|
|
;
|
|
entry:
|
|
br label %for.cond31
|
|
|
|
for.cond31:
|
|
br i1 undef, label %for.body35, label %for.end94
|
|
|
|
for.body35:
|
|
br label %while.cond.i.preheader
|
|
|
|
while.cond.i.preheader:
|
|
br i1 undef, label %while.cond.i.preheader.split, label %while.cond.outer.i.loopexit.split
|
|
|
|
while.cond.i.preheader.split:
|
|
br label %while.cond.i
|
|
|
|
while.cond.i:
|
|
br i1 true, label %while.cond.i, label %while.cond.outer.i.loopexit
|
|
|
|
while.cond.outer.i.loopexit:
|
|
br label %while.cond.outer.i.loopexit.split
|
|
|
|
while.cond.outer.i.loopexit.split:
|
|
br i1 false, label %while.cond.i.preheader, label %Func2.exit
|
|
|
|
Func2.exit:
|
|
br label %while.body
|
|
|
|
while.body:
|
|
br i1 false, label %while.body, label %while.end
|
|
|
|
while.end:
|
|
br label %for.end78
|
|
|
|
for.end78:
|
|
br i1 undef, label %Proc2.exit, label %for.cond.i.preheader
|
|
|
|
for.cond.i.preheader:
|
|
br label %for.cond.i
|
|
|
|
for.cond.i:
|
|
br label %for.cond.i
|
|
|
|
Proc2.exit:
|
|
br label %for.cond31
|
|
|
|
for.end94:
|
|
ret void
|
|
}
|
|
|
|
; Test UnloopUpdater::removeBlocksFromAncestors.
|
|
;
|
|
; Check that the loop backedge is removed from the middle loop 1699,
|
|
; but not the inner loop 1676.
|
|
define void @removeSubloopBlocks() nounwind {
|
|
; CHECK-LABEL: @removeSubloopBlocks(
|
|
; CHECK-NEXT: entry:
|
|
; CHECK-NEXT: br label [[TRYAGAIN_OUTER:%.*]]
|
|
; CHECK: tryagain.outer:
|
|
; CHECK-NEXT: br label [[TRYAGAIN:%.*]]
|
|
; CHECK: tryagain:
|
|
; CHECK-NEXT: br i1 false, label [[SW_BB1669:%.*]], label [[SW_BB304:%.*]]
|
|
; CHECK: sw.bb304:
|
|
; CHECK-NEXT: ret void
|
|
; CHECK: sw.bb1669:
|
|
; CHECK-NEXT: br i1 true, label [[SW_DEFAULT1711:%.*]], label [[WHILE_COND1676_PREHEADER:%.*]]
|
|
; CHECK: while.cond1676.preheader:
|
|
; CHECK-NEXT: br label [[WHILE_COND1676:%.*]]
|
|
; CHECK: while.cond1676:
|
|
; CHECK-NEXT: br i1 true, label [[WHILE_END1699:%.*]], label [[WHILE_BODY1694:%.*]]
|
|
; CHECK: while.body1694:
|
|
; CHECK-NEXT: unreachable
|
|
; CHECK: while.end1699:
|
|
; CHECK-NEXT: br label [[SW_DEFAULT1711]]
|
|
; CHECK: sw.default1711:
|
|
; CHECK-NEXT: br label [[DEFCHAR:%.*]]
|
|
; CHECK: defchar:
|
|
; CHECK-NEXT: br i1 undef, label [[IF_END2413:%.*]], label [[IF_THEN2368:%.*]]
|
|
; CHECK: if.then2368:
|
|
; CHECK-NEXT: unreachable
|
|
; CHECK: if.end2413:
|
|
; CHECK-NEXT: unreachable
|
|
;
|
|
entry:
|
|
br label %tryagain.outer
|
|
|
|
tryagain.outer: ; preds = %sw.bb304, %entry
|
|
br label %tryagain
|
|
|
|
tryagain: ; preds = %while.end1699, %tryagain.outer
|
|
br i1 undef, label %sw.bb1669, label %sw.bb304
|
|
|
|
sw.bb304: ; preds = %tryagain
|
|
br i1 undef, label %return, label %tryagain.outer
|
|
|
|
sw.bb1669: ; preds = %tryagain
|
|
br i1 undef, label %sw.default1711, label %while.cond1676
|
|
|
|
while.cond1676: ; preds = %while.body1694, %sw.bb1669
|
|
br i1 undef, label %while.end1699, label %while.body1694
|
|
|
|
while.body1694: ; preds = %while.cond1676
|
|
br label %while.cond1676
|
|
|
|
while.end1699: ; preds = %while.cond1676
|
|
br i1 false, label %tryagain, label %sw.default1711
|
|
|
|
sw.default1711: ; preds = %while.end1699, %sw.bb1669, %tryagain
|
|
br label %defchar
|
|
|
|
defchar: ; preds = %sw.default1711, %sw.bb376
|
|
br i1 undef, label %if.end2413, label %if.then2368
|
|
|
|
if.then2368: ; preds = %defchar
|
|
unreachable
|
|
|
|
if.end2413: ; preds = %defchar
|
|
unreachable
|
|
|
|
return: ; preds = %sw.bb304
|
|
ret void
|
|
}
|
|
|
|
; PR11335: the most deeply nested block should be removed from the outer loop.
|
|
define void @removeSubloopBlocks2() nounwind {
|
|
; CHECK-LABEL: @removeSubloopBlocks2(
|
|
; CHECK-NEXT: entry:
|
|
; CHECK-NEXT: [[TOBOOL_I:%.*]] = icmp ne i32 undef, 0
|
|
; CHECK-NEXT: br label [[LBL_616:%.*]]
|
|
; CHECK: lbl_616.loopexit:
|
|
; CHECK-NEXT: br label [[LBL_616]]
|
|
; CHECK: lbl_616:
|
|
; CHECK-NEXT: br label [[FOR_COND:%.*]]
|
|
; CHECK: for.cond:
|
|
; CHECK-NEXT: br i1 false, label [[FOR_COND1_PREHEADER:%.*]], label [[LBL_616_LOOPEXIT:%.*]]
|
|
; CHECK: for.cond1.preheader:
|
|
; CHECK-NEXT: br label [[FOR_COND1:%.*]]
|
|
; CHECK: for.cond1.loopexit:
|
|
; CHECK-NEXT: unreachable
|
|
; CHECK: for.cond1:
|
|
; CHECK-NEXT: br i1 false, label [[FOR_BODY2:%.*]], label [[FOR_COND3:%.*]]
|
|
; CHECK: for.body2:
|
|
; CHECK-NEXT: br label [[FOR_COND_I:%.*]]
|
|
; CHECK: for.cond.i:
|
|
; CHECK-NEXT: br i1 [[TOBOOL_I]], label [[FOR_COND_I]], label [[FOR_COND1_LOOPEXIT:%.*]]
|
|
; CHECK: for.cond3:
|
|
; CHECK-NEXT: ret void
|
|
;
|
|
entry:
|
|
%tobool.i = icmp ne i32 undef, 0
|
|
br label %lbl_616
|
|
|
|
lbl_616.loopexit: ; preds = %for.cond
|
|
br label %lbl_616
|
|
|
|
lbl_616: ; preds = %lbl_616.loopexit, %entry
|
|
br label %for.cond
|
|
|
|
for.cond: ; preds = %for.cond3, %lbl_616
|
|
br i1 false, label %for.cond1.preheader, label %lbl_616.loopexit
|
|
|
|
for.cond1.preheader: ; preds = %for.cond
|
|
br label %for.cond1
|
|
|
|
for.cond1.loopexit: ; preds = %for.cond.i
|
|
br label %for.cond1
|
|
|
|
for.cond1: ; preds = %for.cond1.loopexit, %for.cond1.preheader
|
|
br i1 false, label %for.body2, label %for.cond3
|
|
|
|
for.body2: ; preds = %for.cond1
|
|
br label %for.cond.i
|
|
|
|
for.cond.i: ; preds = %for.cond.i, %for.body2
|
|
br i1 %tobool.i, label %for.cond.i, label %for.cond1.loopexit
|
|
|
|
for.cond3: ; preds = %for.cond1
|
|
br i1 false, label %for.cond, label %if.end
|
|
|
|
if.end: ; preds = %for.cond3
|
|
ret void
|
|
}
|