<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 - GVNHoist hoists a load above a null check"
href="https://bugs.llvm.org/show_bug.cgi?id=46874">46874</a>
</td>
</tr>
<tr>
<th>Summary</th>
<td>GVNHoist hoists a load above a null check
</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>All
</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>Scalar Optimizations
</td>
</tr>
<tr>
<th>Assignee</th>
<td>unassignedbugs@nondot.org
</td>
</tr>
<tr>
<th>Reporter</th>
<td>chang-sun.lin.jr@intel.com
</td>
</tr>
<tr>
<th>CC</th>
<td>llvm-bugs@lists.llvm.org
</td>
</tr></table>
<p>
<div>
<pre>Created <span class=""><a href="attachment.cgi?id=23782" name="attach_23782" title="reproducer">attachment 23782</a> <a href="attachment.cgi?id=23782&action=edit" title="reproducer">[details]</a></span>
reproducer
In the attached .ll file, GVNHoist hoists a load above its null check.
opt --gvn-hoist hoistbug.ll -S > bad.ll
clang -O0 bad.ll
./a.out
<segv>
There are two loads in the function "foo", in different blocks, with the same
address %p. Both load-blocks are guarded by conditional null checks. The first
load-block also has a conditional branch in it that goes directly to the second
load-block.
entry:
%cmp.not = icmp eq i32* %p, null
br i1 %cmp.not, label %if.end3, label %if.then
if.then:
%0 = load %p…
br … %if.end3, %if2
if.end3:
…
br i1 %cmp.not, label %if.end11, label %if2
if2:
%1 = load %p…
br … %if.end11, %end
if.end11:
…
end:
The PDOM tree looks like:
Inorder PostDominator Tree: DFSNumbers invalid: 0 slow queries.
[1] <<exit node>> {4294967295,4294967295} [0]
[2] %end {4294967295,4294967295} [1]
[3] %if2 {4294967295,4294967295} [2] ; lower load block
[3] %if.then {4294967295,4294967295} [2] ; upper load block
[3] %entry {4294967295,4294967295} [2] ; null check for upper load
[3] %if.end3 {4294967295,4294967295} [2] ; null check for lower load
[3] %if.end11 {4294967295,4294967295} [2]
Roots: %end
GVNHoist traverses the blocks in depth-first PDOM order. It hits the two load
blocks %if2 and %if.then, and pushes the loads on the stack, %1 and %0
respectively. When it processes the upper load-block %if.then, it correctly
places a chiarg (%if.then, %0) into its precedessor, %entry. %0 is popped off
the stack. The problem is that %1 remains at the top of the stack while it
traverses the other pdom siblings. When it gets to %if.end3, the other
successor of %entry, it places a chiarg (%if.end3, %1) into %entry, even though
%1 is not anticipable in %if.end3. It looks like the stacks should be popped
when we “backtrack” in the PDOM tree traversal, or maybe an extra pdom check
needs to be done before inserting a chiarg.</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>