<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 - clang/llvm looses restrictness, resulting in wrong code"
   href="https://bugs.llvm.org/show_bug.cgi?id=39240">39240</a>
          </td>
        </tr>

        <tr>
          <th>Summary</th>
          <td>clang/llvm looses restrictness, resulting in wrong code
          </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>Windows NT
          </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>jeroen.dobbelaere@synopsys.com
          </td>
        </tr>

        <tr>
          <th>CC</th>
          <td>llvm-bugs@lists.llvm.org
          </td>
        </tr></table>
      <p>
        <div>
        <pre>clang/llvm implements argument restrictness by putting a 'noalias' on the the
restrict argument. When alias analysis traces the base object of a pointer to
two different base objects of which one is marked with 'noalias', it concludes
that these pointers do not alias.

This mapping results in wrong behavior according to the restrict specification:
(or my interpretation of it is wrong ;) ):

6.7.3.1, 4: 'every other lvalue used to access the value of X shall also have
its address based on P.'

where P is the restrict annotated pointer. This means that in following code
*tmp and *pA might alias:

  // Assume pA and pB point to the same set of objects X
  // restrict rules dictate that all accesses in the scope must happen through
  // the restrict pointer (pA) or a pointer based on it.
  int foo(int* __restrict pA, int* pB, int* pC) {
    int *tmp=pA; // tmp is based on pA 
    pA=pB; // pB also points into the set of objects X, but, accessing it must
happen through a pointer based on pA

    *tmp=42; // tmp points into the set of objects X
    *pA=43;  // pA points into the set of objects X
    *pC=99;  // pC does not point into the set of objects X
    return *tmp; // fail: needs a load !!! (either 42 or 43)
  }

results in:
  define dso_local i32 @foo(i32* noalias nocapture, i32* nocapture, i32*
nocapture) local_unnamed_addr #0 {
    store i32 42, i32* %0, align 4, !tbaa !2
    store i32 43, i32* %1, align 4, !tbaa !2
    store i32 99, i32* %2, align 4, !tbaa !2
    ret i32 42 ; WRONG! %0 must be reloaded
  }

But, clang/llvm assumes that *tmp and *pA will never alias, and propagates the
42.

NOTES:
- gcc has the same issue
- icc has the correct behavior
- for this example, moving the __restrict from pA to the pC argument, results
in equivalent code with the correct behavior.
- llvm + Hal Finkels local restrict patches has the correct behavior, IF the
restrict is made local:

  int foo(int* pA_, int* pB, int* pC) {
    int* __restrict pA=pA_;
    int *tmp=pA; // tmp is based on pA 
    ....

results in:
  define dso_local i32 @foo(i32* nocapture %pA_, i32* nocapture %pB, i32*
nocapture %pC) local_unnamed_addr #1 {
  entry:
    %0 = tail call i32* @llvm.noalias.p0i32(i32* %pA_, metadata !6)
    store i32 42, i32* %0, align 4, !tbaa !2, !noalias !6
    %1 = tail call i32* @llvm.noalias.p0i32(i32* %pB, metadata !6)
    store i32 43, i32* %1, align 4, !tbaa !2, !noalias !6
    store i32 99, i32* %pC, align 4, !tbaa !2, !noalias !6
    %2 = load i32, i32* %0, align 4, !tbaa !2, !noalias !6
    ret i32 %2
  }</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>