[PATCH] D34311: [InstCombine] Don't replace allocas with globals if we can't prove that it's large enough.

Eli Friedman via Phabricator via llvm-commits llvm-commits at lists.llvm.org
Tue Jun 20 12:10:22 PDT 2017


efriedma added a comment.

Hmm, actually, thinking about it a bit more, I'm not sure this patch is right.

If you were to assume that out-of-bounds loads return undef rather than have undefined behavior, this patch would be unnecessary.  There's only one memcpy that writes to the alloca.  That memcpy writes N known bytes to the alloca.  Any other instruction which accesses the alloca is either reading one of those N bytes, or returns undef, so the returned values are consistent with reading directly from the global.

Of course, that isn't the world we live in; we can't speculate out-of-bounds loads.  Therefore, the safety check needs to make sure we aren't introducing any such loads.  There are a couple of ways to do that:

1. Prove that the constant pointer points to at least `sizeof(alloca type)` bytes of memory.  The loads in the rewritten code are out-of-bounds only if they were out-of-bounds in the original code.
2. Ensure that every load is dominated by the initializing memcpy, and the memcpy copies at least `sizeof(alloca type)` bytes of memory.  If the memcpy is copying too many bytes, it's immediately undefined behavior.  Any load dominated by the memcpy is one of the following: in-bounds in the original code, out-of-bounds in the original code, or dominated by undefined behavior.

This patch implements (2)... but only partially: it's missing the dominance check.  Testcase something like this:

  const char x[1] = { 3 };
  char z[10];
  int f(bool this_is_false) {
    char y[10];
    if (this_is_false) memcpy(y, x, 10); 
    memcpy(z, y, 10); 
  }



================
Comment at: lib/Transforms/InstCombine/InstCombineLoadStoreAlloca.cpp:175
+
+  uint64_t CopySize = CopyLength->getZExtValue();
+  assert(CopySize <= AllocaSize);
----------------
getZExtValue() will crash on very large lengths.


================
Comment at: lib/Transforms/InstCombine/InstCombineLoadStoreAlloca.cpp:176
+  uint64_t CopySize = CopyLength->getZExtValue();
+  assert(CopySize <= AllocaSize);
+  if (CopySize < AllocaSize)
----------------
This assertion doesn't seem justified; sure, the memcpy has undefined behavior, but that shouldn't crash the compiler.


https://reviews.llvm.org/D34311





More information about the llvm-commits mailing list