<html>
<head>
<base href="https://bugs.llvm.org/">
</head>
<body><table border="1" cellspacing="0" cellpadding="8">
<tr>
<th>Bug ID</th>
<td><a class="bz_bug_link
bz_status_NEW "
title="NEW - No dead loops cleanup after unroll/peeling creates more opportunities in default -O3 pipeline"
href="https://bugs.llvm.org/show_bug.cgi?id=36614">36614</a>
</td>
</tr>
<tr>
<th>Summary</th>
<td>No dead loops cleanup after unroll/peeling creates more opportunities in default -O3 pipeline
</td>
</tr>
<tr>
<th>Product</th>
<td>libraries
</td>
</tr>
<tr>
<th>Version</th>
<td>trunk
</td>
</tr>
<tr>
<th>Hardware</th>
<td>PC
</td>
</tr>
<tr>
<th>OS</th>
<td>Linux
</td>
</tr>
<tr>
<th>Status</th>
<td>NEW
</td>
</tr>
<tr>
<th>Severity</th>
<td>enhancement
</td>
</tr>
<tr>
<th>Priority</th>
<td>P
</td>
</tr>
<tr>
<th>Component</th>
<td>Scalar Optimizations
</td>
</tr>
<tr>
<th>Assignee</th>
<td>unassignedbugs@nondot.org
</td>
</tr>
<tr>
<th>Reporter</th>
<td>andrei.elovikov@intel.com
</td>
</tr>
<tr>
<th>CC</th>
<td>llvm-bugs@lists.llvm.org
</td>
</tr></table>
<p>
<div>
<pre>For the following example
$ cat a.ll
define float @foo() local_unnamed_addr {
entry:
br label %for.cond
for.cond: ; preds = %for.cond, %entry
%i.0 = phi i32 [ 0, %entry ], [ %inc, %for.cond ]
%c.0 = phi float [ 0.000000e+00, %entry ], [ 1.700000e+01, %for.cond ]
%cmp = icmp ult i32 %i.0, 999
%inc = add nuw nsw i32 %i.0, 1
br i1 %cmp, label %for.cond, label %for.end
for.end: ; preds = %for.cond
ret float %c.0
}
The dead loop is not completely eliminated
$ opt -O3 a.ll -S
; ModuleID = 'a.ll'
source_filename = "a.ll"
; Function Attrs: norecurse nounwind readnone
define float @foo() local_unnamed_addr #0 {
for.cond.peel.next:
br label %for.cond
for.cond: ; preds = %for.cond,
%for.cond.peel.next
%i.0 = phi i32 [ 1, %for.cond.peel.next ], [ %inc, %for.cond ]
%cmp = icmp ult i32 %i.0, 999
%inc = add nuw nsw i32 %i.0, 1
br i1 %cmp, label %for.cond, label %for.end, !llvm.loop !0
for.end: ; preds = %for.cond
ret float 1.700000e+01
}
attributes #0 = { norecurse nounwind readnone }
!0 = distinct !{!0, !1}
!1 = !{!"llvm.loop.unroll.disable"}
although -loop-deletion is capable of doing that
$ opt -O3 a.ll -S | opt -loop-deletion -S
; ModuleID = '<stdin>'
source_filename = "a.ll"
; Function Attrs: norecurse nounwind readnone
define float @foo() local_unnamed_addr #0 {
for.cond.peel.next:
br label %for.end
for.end: ; preds = %for.cond.peel.next
ret float 1.700000e+01
}
attributes #0 = { norecurse nounwind readnone }
This is because before the single instance of loop-deletion in -O3 pipeline the
IR is
; Preheader:
entry:
br label %for.cond
; Loop:
for.cond: ; preds = %for.cond, %entry
%i.0 = phi i32 [ 0, %entry ], [ %inc, %for.cond ]
%c.0 = phi float [ 0.000000e+00, %entry ], [ 1.700000e+01, %for.cond ]
%inc = add nuw nsw i32 %i.0, 1
%exitcond = icmp ne i32 %inc, 1000
br i1 %exitcond, label %for.cond, label %for.end
; Exit blocks
for.end: ; preds = %for.cond
%c.0.lcssa = phi float [ %c.0, %for.cond ]
ret float %c.0.lcssa
And the %c.0 use is eliminated only during the peeling inside unrolling, which
happens later than the loop-deletion:
*** IR Dump After Unroll loops ***
; Loop:
for.cond: ; preds = %for.cond,
%entry.peel.newph
%i.0 = phi i32 [ %inc.peel, %entry.peel.newph ], [ %inc, %for.cond ]
%inc = add nuw nsw i32 %i.0, 1
%exitcond = icmp ne i32 %inc, 1000
br i1 %exitcond, label %for.cond, label %for.end.loopexit, !llvm.loop !2
; Exit blocks
for.end.loopexit: ; preds = %for.cond
%c.0.lcssa.ph = phi float [ 1.700000e+01, %for.cond ]
br label %for.end
Corresponding code from the pass manager:
MPM.add(createLoopDeletionPass()); // Delete dead loops
if (EnableLoopInterchange) {
MPM.add(createLoopInterchangePass()); // Interchange loops
MPM.add(createCFGSimplificationPass());
}
if (!DisableUnrollLoops)
MPM.add(createSimpleLoopUnrollPass(OptLevel)); // Unroll small loops
addExtensionsToPM(EP_LoopOptimizerEnd, MPM);</pre>
</div>
</p>
<hr>
<span>You are receiving this mail because:</span>
<ul>
<li>You are on the CC list for the bug.</li>
</ul>
</body>
</html>