<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>