<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 - Unnecessary load not eliminated"
   href="https://bugs.llvm.org/show_bug.cgi?id=47895">47895</a>
          </td>
        </tr>

        <tr>
          <th>Summary</th>
          <td>Unnecessary load not eliminated
          </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>david.bolvansky@gmail.com
          </td>
        </tr>

        <tr>
          <th>CC</th>
          <td>llvm-bugs@lists.llvm.org
          </td>
        </tr></table>
      <p>
        <div>
        <pre>Extracted from PR47887


Testcase:
void foo(int *p,int *q,int x) {
  *p=x;
  *q=x;
  if(*p!=x)  /* false */
    __builtin_abort();
}

Clang -O3:
foo(int*, int*, int):                            # @foo(int*, int*, int)
        push    rax
        mov     dword ptr [rdi], edx
        mov     dword ptr [rsi], edx
        cmp     dword ptr [rdi], edx
        jne     .LBB0_2
        pop     rax
        ret
.LBB0_2:
        call    abort

GCC can remove unnecessary load.
foo(int*, int*, int):
        mov     DWORD PTR [rdi], edx
        mov     DWORD PTR [rsi], edx
        ret


Analysis of the problem by Florian Hahn (thx!):
"In the case above neither of the stores is dead. The load is unnecessary, but
only because we store the same value to both p and q. `store i32 x, i32* q` may
alias `load p`, but it stores the same value as the store to p. 

We should be able to handle this with MemorySSA, possibly as an extension of
DSE, but it won't fit directly in the main elimination loop and will need some
extra code."</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>