<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 - LoopUnroll: runtime check introduces branch on poison if fn call doesn't return"
href="https://bugs.llvm.org/show_bug.cgi?id=51670">51670</a>
</td>
</tr>
<tr>
<th>Summary</th>
<td>LoopUnroll: runtime check introduces branch on poison if fn call doesn't return
</td>
</tr>
<tr>
<th>Product</th>
<td>libraries
</td>
</tr>
<tr>
<th>Version</th>
<td>trunk
</td>
</tr>
<tr>
<th>Hardware</th>
<td>All
</td>
</tr>
<tr>
<th>OS</th>
<td>All
</td>
</tr>
<tr>
<th>Status</th>
<td>NEW
</td>
</tr>
<tr>
<th>Keywords</th>
<td>miscompilation
</td>
</tr>
<tr>
<th>Severity</th>
<td>normal
</td>
</tr>
<tr>
<th>Priority</th>
<td>P
</td>
</tr>
<tr>
<th>Component</th>
<td>Loop Optimizer
</td>
</tr>
<tr>
<th>Assignee</th>
<td>unassignedbugs@nondot.org
</td>
</tr>
<tr>
<th>Reporter</th>
<td>nunoplopes@sapo.pt
</td>
</tr>
<tr>
<th>CC</th>
<td>atrick@apple.com, haicheng@codeaurora.org, llvm-bugs@lists.llvm.org, meheff@google.com, nikita.ppv@gmail.com, zhaoshiz@quicinc.com
</td>
</tr></table>
<p>
<div>
<pre>Test: Transforms/LoopUnroll/loop-remarks.ll
In the test below, @baz may not return. In that case, the source function will
not branch on the possibly poison %exitcond (poison if %n poison).
The target function always branches on %n regardless of whether @baz returns or
not.
The fix is to freeze %n if the code doesn't provably reach the branch.
define i32 @runtime(i32 %n) {
%entry:
br label %for.body
%for.body:
%s.06 = phi i32 [ 0, %entry ], [ %add1, %for.body ]
%i.05 = phi i32 [ 0, %entry ], [ %inc, %for.body ]
%add = add nsw i32 %i.05, 4
%call = call i32 @baz(i32 %add)
%add1 = add nsw i32 %call, %s.06
%inc = add nsw i32 %i.05, 1
%exitcond = icmp eq i32 %inc, %n
br i1 %exitcond, label %for.end, label %for.body
%for.end:
ret i32 %add1
}
=>
define i32 @runtime(i32 %n) {
%entry:
%0 = add i32 %n, 4294967295
%xtraiter = and i32 %n, 3
%1 = icmp ult i32 %0, 3
br i1 %1, label %for.end.unr-lcssa, label %entry.new
%entry.new:
%unroll_iter = sub i32 %n, %xtraiter
br label %for.body
%for.body:
%s.06 = phi i32 [ 0, %entry.new ], [ %add1.3, %for.body ]
%i.05 = phi i32 [ 0, %entry.new ], [ %inc.3, %for.body ]
%niter = phi i32 [ %unroll_iter, %entry.new ], [ %niter.nsub.3, %for.body ]
%add = add nsw i32 %i.05, 4
%call = call i32 @baz(i32 %add)
%add1 = add nsw i32 %call, %s.06
%inc = add nsw nuw i32 %i.05, 1
%niter.nsub = sub i32 %niter, 1
%add.1 = add nsw i32 %inc, 4
%call.1 = call i32 @baz(i32 %add.1)
%add1.1 = add nsw i32 %call.1, %add1
%inc.1 = add nsw nuw i32 %inc, 1
%niter.nsub.1 = sub i32 %niter.nsub, 1
%add.2 = add nsw i32 %inc.1, 4
%call.2 = call i32 @baz(i32 %add.2)
%add1.2 = add nsw i32 %call.2, %add1.1
%inc.2 = add nsw nuw i32 %inc.1, 1
%niter.nsub.2 = sub i32 %niter.nsub.1, 1
%add.3 = add nsw i32 %inc.2, 4
%call.3 = call i32 @baz(i32 %add.3)
%add1.3 = add nsw i32 %call.3, %add1.2
%inc.3 = add nsw i32 %inc.2, 1
%niter.nsub.3 = sub i32 %niter.nsub.2, 1
%niter.ncmp.3 = icmp eq i32 %niter.nsub.3, 0
br i1 %niter.ncmp.3, label %for.end.unr-lcssa.loopexit, label %for.body
%for.end.unr-lcssa.loopexit:
%add1.lcssa.ph.ph = phi i32 [ %add1.3, %for.body ]
%s.06.unr.ph = phi i32 [ %add1.3, %for.body ]
%i.05.unr.ph = phi i32 [ %inc.3, %for.body ]
br label %for.end.unr-lcssa
%for.end.unr-lcssa:
%add1.lcssa.ph = phi i32 [ undef, %entry ], [ %add1.lcssa.ph.ph,
%for.end.unr-lcssa.loopexit ]
%s.06.unr = phi i32 [ 0, %entry ], [ %s.06.unr.ph,
%for.end.unr-lcssa.loopexit ]
%i.05.unr = phi i32 [ 0, %entry ], [ %i.05.unr.ph,
%for.end.unr-lcssa.loopexit ]
%lcmp.mod = icmp ne i32 %xtraiter, 0
br i1 %lcmp.mod, label %for.body.epil.preheader, label %for.end
%for.body.epil.preheader:
br label %for.body.epil
%for.body.epil:
%add.epil = add nsw i32 %i.05.unr, 4
%call.epil = call i32 @baz(i32 %add.epil)
%add1.epil = add nsw i32 %call.epil, %s.06.unr
%inc.epil = add nsw i32 %i.05.unr, 1
%epil.iter.sub = sub i32 %xtraiter, 1
%epil.iter.cmp = icmp ne i32 %epil.iter.sub, 0
br i1 %epil.iter.cmp, label %for.body.epil.1, label %for.end.epilog-lcssa
%for.body.epil.1:
%add.epil.1 = add nsw i32 %inc.epil, 4
%call.epil.1 = call i32 @baz(i32 %add.epil.1)
%add1.epil.1 = add nsw i32 %call.epil.1, %add1.epil
%inc.epil.1 = add nsw i32 %inc.epil, 1
%epil.iter.sub.1 = sub i32 %epil.iter.sub, 1
%epil.iter.cmp.1 = icmp ne i32 %epil.iter.sub.1, 0
br i1 %epil.iter.cmp.1, label %for.body.epil.2, label %for.end.epilog-lcssa
%for.body.epil.2:
%add.epil.2 = add nsw i32 %inc.epil.1, 4
%call.epil.2 = call i32 @baz(i32 %add.epil.2)
%add1.epil.2 = add nsw i32 %call.epil.2, %add1.epil.1
br label %for.end.epilog-lcssa
%for.end.epilog-lcssa:
%add1.lcssa.ph1 = phi i32 [ %add1.epil, %for.body.epil ], [ %add1.epil.1,
%for.body.epil.1 ], [ %add1.epil.2, %for.body.epil.2 ]
br label %for.end
%for.end:
%add1.lcssa = phi i32 [ %add1.lcssa.ph, %for.end.unr-lcssa ], [
%add1.lcssa.ph1, %for.end.epilog-lcssa ]
ret i32 %add1.lcssa
}
Transformation doesn't verify!
ERROR: Source is more defined than target
Example:
i32 %n = poison
Source:
i32 %s.06 = #x00000000 (0)
i32 %i.05 = #x00000000 (0)
i32 %add = #x00000004 (4)
i32 %call = poison
i32 %add1 = poison
i32 %inc = #x00000001 (1)
i1 %exitcond = poison
Target:
i32 %0 = poison
i32 %xtraiter = poison
i1 %1 = poison</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>