<html>
    <head>
      <base href="https://llvm.org/bugs/" />
    </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++ miscompile at -O1 with revision 274385"
   href="https://llvm.org/bugs/show_bug.cgi?id=30290">30290</a>
          </td>
        </tr>

        <tr>
          <th>Summary</th>
          <td>clang++ miscompile at -O1 with revision 274385
          </td>
        </tr>

        <tr>
          <th>Product</th>
          <td>clang
          </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>LLVM Codegen
          </td>
        </tr>

        <tr>
          <th>Assignee</th>
          <td>unassignedclangbugs@nondot.org
          </td>
        </tr>

        <tr>
          <th>Reporter</th>
          <td>warren_ristow@playstation.sony.com
          </td>
        </tr>

        <tr>
          <th>CC</th>
          <td>llvm-bugs@lists.llvm.org
          </td>
        </tr>

        <tr>
          <th>Classification</th>
          <td>Unclassified
          </td>
        </tr></table>
      <p>
        <div>
        <pre>We have encountered a miscompile for x86_64-unknown-linux-gnu, with
'-march=btver2' at optimization '-O1'.  In the test-cases I found, it passes
with optimizaiton lowered to -O0 or raised to -O2, and it also passes for the
default architecture.  I'd expect that the bug can also manifest at higher
optimization levels, but I haven't found an example.

I've reduced the failure to the test-case appended below, and found that the
failure began happening with r274385 (it still fails with current ToT,
r280692).
The failing and passing behaviors are:

  $ clang++ --version
  clang version 4.0.0 (trunk 280692)
  Target: x86_64-unknown-linux-gnu
  Thread model: posix
  InstalledDir: <....>
  $ clang++ -o test.elf -O1 -march=btver2 test.cpp
  $ ./test.elf
       input:    41  42  43  44  45
      output:    41  42  45  17  17
  FAIL
  $
  $ clang++ -o test.elf -O1               test.cpp
  $ ./test.elf
       input:    41  42  43  44  45
      output:    43  44  45  41  42
  PASS
  $
  $ clang++ -o test.elf -O2 -march=btver2 test.cpp
  $ ./test.elf
       input:    41  42  43  44  45
      output:    43  44  45  41  42
  PASS
  $

Although the failure of this test-case began happening with r274385 (as was
the case with the program this was reduced from), I _suspect_ that the
underlying bug is older than that, because in reducing the original program, I
also encountered a test-case that fails in a similar way with significantly
older compilers.  Specifically, I found a very similar test-case that fails
with llvm 3.6 (passes with llvm 3.5).  I'm guessing that the recent change of
r274385 is correct, and it's just that the old bug is now more likely to
manifest.  I haven't bisected down precisely when the older failure began to
happen.  I'll put that similar test-case that fails even with older compilers
in the next post here.  (I'm filing this against Clang / LLVM Codegen, because
that's what changed with r274385.  However, if my guess is right, that's
probably the wrong area.)

Note that <a class="bz_bug_link 
          bz_status_RESOLVED  bz_closed"
   title="RESOLVED INVALID - Dangling references after r274385 "[Temporary, Lifetime] Add lifetime marks for temporaries"?"
   href="show_bug.cgi?id=28603">bug 28603</a> is generally about failures appearing since r274385.  But
in the discussion there, the failing test-cases were all examples of broken
user-code that was exposed by r274385.  I believe the test-case below is legal
code, but as I said above, I'm suspicious that r274385 itself is just exposing
an older latent problem.


With that, here is the test-case that began failing with r274385:

//////////////////////////////// test.cpp ////////////////////////////////
extern "C" void printf(...);

int srcData[] = {41, 42, 43, 44, 45};
const int nElems = sizeof(srcData) / sizeof(srcData[0]);

struct Container {
  Container(int i) { mData = i; }
  int mData;
};

struct Wrapper {
  int unusedInt;
  long unusedLong;
  Wrapper(Container* p) : mPtr(p) {}
  Container* mPtr;
};

struct ContainerVector {
  Container* firstElem;
  Container* lastElem;
  ContainerVector() : firstElem(0), lastElem(0) { }
  Container* ptrToElem(int inx) { return firstElem + inx; }
  void allocVec(int n_elems) {
    Container* newVec = (Container*) operator new(sizeof(Container) * n_elems);
    firstElem = newVec;
    lastElem = newVec + n_elems;
    for (int i = 0; i < n_elems; ++i)
      ptrToElem(i)->mData = 17;
  }
};

static void printVec(ContainerVector cv, const char* msg)
{
  printf("%10s:  ", msg);
  for (int i = 0; i < nElems; ++i)
    printf(" %3d", cv.ptrToElem(i)->mData);
  printf("\n");
}

static Wrapper copy(Wrapper wSrcStart, Wrapper wSrcEnd, Wrapper wDst) {
  Container *cSrc, *cEnd, *cDst;
  cSrc = wSrcStart.mPtr;   cEnd = wSrcEnd.mPtr;   cDst = wDst.mPtr;
  for (; cSrc != cEnd; ++cDst, ++cSrc)
    *cDst = *cSrc;
  wDst.mPtr = cDst;
  return wDst;
}

static void copyWithRotateLeft(Wrapper wStartSrc, Wrapper wStartDstSrc,
                               Wrapper wEndSrc, Wrapper wDst) {
  wDst = copy(wStartDstSrc, wEndSrc, wDst);
  copy(wStartSrc, wStartDstSrc, wDst);
}

int main() {
  ContainerVector src, dst;
  src.allocVec(nElems);
  dst.allocVec(nElems);
  for (int i = 0; i < nElems; ++i)
    src.ptrToElem(i)->mData = srcData[i];
  printVec(src, "input");
  copyWithRotateLeft(Wrapper(src.firstElem), Wrapper(src.firstElem + 2),
                     Wrapper(src.lastElem), Wrapper(dst.firstElem));
  printVec(dst, "output");
  printf("%s\n", (((dst.ptrToElem(4))->mData != 42) ? "FAIL" : "PASS"));
}
//////////////////////////////////////////////////////////////////////////</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>