<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 - mis-optimization in LoopSink"
href="https://bugs.llvm.org/show_bug.cgi?id=39695">39695</a>
</td>
</tr>
<tr>
<th>Summary</th>
<td>mis-optimization in LoopSink
</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>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>carrot@google.com
</td>
</tr>
<tr>
<th>CC</th>
<td>llvm-bugs@lists.llvm.org
</td>
</tr></table>
<p>
<div>
<pre>Optimize following code with
opt -S -loop-sink test1.ll
define i32 @foo(i32 %n, i8** %pp) !prof !0 {
entry:
%ptr = load i8*, i8** %pp, align 8 ; Should not be sinkied
store i8* null, i8** %pp, align 8 ; because of this store
br label %for.cond
for.cond: ; preds = %for.body, %entry
%i.0 = phi i32 [ 0, %entry ], [ %inc, %for.body ]
%cmp = icmp ult i32 %i.0, %n
br i1 %cmp, label %for.body, label %for.end, !prof !1
for.body: ; preds = %for.cond
%0 = sext i32 %i.0 to i64
%arrayidx = getelementptr inbounds i8, i8* %ptr, i64 %0
%1 = load i8, i8* %arrayidx, align 1
%or19 = call i8 @llvm.bitreverse.i8(i8 %1)
%v = sext i8 %or19 to i32
%inc = add i32 %i.0, %v
br label %for.cond
for.end: ; preds = %for.cond
ret i32 %i.0
}
declare i8 @llvm.bitreverse.i8(i8) #0
attributes #0 = { nounwind readnone speculatable }
!0 = !{!"function_entry_count", i64 1}
!1 = !{!"branch_weights", i32 1, i32 2000}
I got
define i32 @foo(i32 %n, i8** %pp) !prof !0 {
entry:
store i8* null, i8** %pp, align 8
br label %for.cond
for.cond: ; preds = %for.body, %entry
%i.0 = phi i32 [ 0, %entry ], [ %inc, %for.body ]
%cmp = icmp ult i32 %i.0, %n
br i1 %cmp, label %for.body, label %for.end, !prof !1
for.body: ; preds = %for.cond
%ptr = load i8*, i8** %pp, align 8 ; wrongly sinked
%0 = sext i32 %i.0 to i64
%arrayidx = getelementptr inbounds i8, i8* %ptr, i64 %0
%1 = load i8, i8* %arrayidx, align 1 ; seg fault!
%or19 = call i8 @llvm.bitreverse.i8(i8 %1)
%v = sext i8 %or19 to i32
%inc = add i32 %i.0, %v
br label %for.cond
for.end: ; preds = %for.cond
%i.0.lcssa = phi i32 [ %i.0, %for.cond ]
ret i32 %i.0.lcssa
}
In entry block load is followed by a store to the same address. After loop
sink, the load is moved into the loop, the stored value (null) instead of the
original value will be used.
The problem is when LoopSink calls canSinkOrHoistInst to check if an
instruction can be sunk into the loop, it only checks if loop body over writes
the memory, but it is not enough as demonstrated by this test case, all
instructions after sink candidate in loop preheader should also be checked.</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>