Uninitialized variables and mem2reg pass


I noticed a strage behavior of mem2reg pass when the code has an
uninitialized local variable dereference. Running the pass over the
following bytecode:

  %buf = alloca i32
  %val = load i32* %buf
  store i32 10, i32* %buf
  ret %val

produces the following result:

  ret i32 10

I would expect mem2reg to produce undef result instead:

  ret i32 undef

As behavior of the original code is undefined, in some sense the
generated bytecode is correct. However, such interpretation of
undefined code makes it impossible for LLVM-based verifiers (such as
KLEE) to find an uninitialized local variable bug in such examples. By
the way, if 10 is replaced by a non-constant, mem2reg pass will
produce "ret i32 undef" as a result, which is much closer to the
original code.

The problem lies in PromoteMem2Reg::RewriteSingleStoreAlloca function:
it explicitly avoids checking whether a load is dominated by a store
if an argument to the store is a constant. The comment in the code
("Non-instructions are always dominated") is incorrect as subsequent
code checks whether the load is dominated by the store instruction,
not by the stored value as implied by the comment. The attached patch
makes mem2reg pass produce "undef" result in both constant-value and
non-constant-value cases.

Mem2RegFixUninitialized.patch (1.46 KB)