mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2024-11-01 08:23:21 +01:00
fafe6e2851
Fixes rdar:14036816, PR16130. There is an opportunity to compute precise trip counts for 'or' expressions and multi-exit loops. rdar:14038809: Optimize trip count computation for multi-exit loops. To do this we need to record the fact that ExitLimit assumes NSW. When it does not we can safely assume that the loop trip count is the minimum ExitLimt across all subexpressions and loop exits. llvm-svn: 183060
473 lines
11 KiB
LLVM
473 lines
11 KiB
LLVM
; RUN: opt < %s -S -loop-unroll -verify-loop-info | FileCheck %s
|
|
;
|
|
; Unit tests for LoopInfo::updateUnloop.
|
|
|
|
declare i1 @check() nounwind
|
|
|
|
; Ensure that tail->inner is removed and rely on verify-loopinfo to
|
|
; check soundness.
|
|
;
|
|
; CHECK: @skiplevelexit
|
|
; CHECK: tail:
|
|
; CHECK-NOT: br
|
|
; CHECK: ret void
|
|
define void @skiplevelexit() nounwind {
|
|
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.
|
|
;
|
|
; CHECK: @unloopNested
|
|
; Outer loop control.
|
|
; CHECK: while.body:
|
|
; CHECK: br i1 %cmp3, label %if.then, label %if.end
|
|
; Inner loop control.
|
|
; CHECK: while.end14.i:
|
|
; CHECK: br i1 %call15.i, label %if.end.i, label %exit
|
|
; Middle loop control should no longer reach %while.cond.
|
|
; Now it is the outer loop backedge.
|
|
; CHECK: exit:
|
|
; CHECK: br label %while.cond.outer
|
|
define void @unloopNested() {
|
|
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.
|
|
; CHECKFIXME: @unloopDeepNested
|
|
; Inner-inner loop control.
|
|
; CHECKFIXME: while.cond.us.i:
|
|
; CHECKFIXME: br i1 %cmp.us.i, label %next_data.exit, label %while.body.us.i
|
|
; CHECKFIXME: if.then.us.i:
|
|
; CHECKFIXME: br label %while.cond.us.i
|
|
; Inner loop tail.
|
|
; CHECKFIXME: if.else.i:
|
|
; CHECKFIXME: br label %while.cond.outer.i
|
|
; Middle loop control (removed).
|
|
; CHECKFIXME: valid_data.exit:
|
|
; CHECKFIXME-NOT: br
|
|
; CHECKFIXME: %cmp = call zeroext i1 @check()
|
|
; Outer loop control.
|
|
; CHECKFIXME: copy_data.exit:
|
|
; CHECKFIXME: br i1 %cmp38, label %if.then39, label %while.cond.outer
|
|
; Outer-outer loop tail.
|
|
; CHECKFIXME: while.cond.outer.outer.backedge:
|
|
; CHECKFIXME: br label %while.cond.outer.outer
|
|
define void @unloopDeepNested() nounwind {
|
|
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.
|
|
;
|
|
; CHECK: @unloopIrreducible
|
|
; Irreducible loop.
|
|
; CHECK: for.inc117:
|
|
; CHECK: br label %for.cond103t
|
|
; Nested loop (removed).
|
|
; CHECK: for.inc159:
|
|
; CHECK: br label %for.inc163
|
|
define void @unloopIrreducible() nounwind {
|
|
|
|
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.
|
|
;
|
|
; CHECK: @unloopCriticalEdge
|
|
; CHECK: while.cond.outer.i.loopexit.split:
|
|
; CHECK: br label %while.body
|
|
; CHECK: while.body:
|
|
; CHECK: br label %for.end78
|
|
define void @unloopCriticalEdge() nounwind {
|
|
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.
|
|
; CHECK: while.body1694:
|
|
; CHECK: br label %while.cond1676
|
|
; CHECK: while.end1699:
|
|
; CHECK: br label %sw.default1711
|
|
define void @removeSubloopBlocks() nounwind {
|
|
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.
|
|
; CHECK: @removeSubloopBlocks2
|
|
; CHECK: for.cond3:
|
|
; CHECK-NOT: br
|
|
; CHECK: ret void
|
|
define void @removeSubloopBlocks2() nounwind {
|
|
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
|
|
}
|