Currently we consider loads of uninitialized memory to be undef. This is both sub-optimal and a source of miscompilations.
For example, instsimplify & newgvn convert phi(X, undef) -> X. This is wrong as X might be poison. We had the same issue with select but it has already been fixed.
Fixing this bug is related with uninit memory because sroa/mem2reg create phis with undef. And we need to be able to fold those away.
We have a patch for langref, sroa, mem2reg here: https://reviews.llvm.org/D104648
I have patches locally for InstSimplify & NewGVN to fix the phi issue mentioned above.
Changing the semantics of load of uninit memory breaks compatibility. Although most users won't notice, we would need to interface with the major frontends.
For clang, we would need to fix codegen of bit-fields as at the least the first field store loads uninit memory before masking it. The easy way is to just freeze the loaded value. Spill-over of poison from different fields is not an issue as if one field becomes poison is because some UB already happened in the program so we can spill over poison to neighboring fields.
Bitfields aren't very common, so this shouldn't be a major issue.
On LLVM's side, I believe the only issue is load widening. This must be either be removed at IR level, or we need to use vectors (or the byte type) for the widened type.
In summary, todo:
cc @aqjune @regehr @nikic @rotateright @LebedevRI @alinas
Currently we consider loads of uninitialized memory to be undef. This is both sub-optimal and a source of miscompilations.
For example, instsimplify & newgvn convert
phi(X, undef) -> X. This is wrong asXmight be poison. We had the same issue withselectbut it has already been fixed.Fixing this bug is related with uninit memory because sroa/mem2reg create phis with undef. And we need to be able to fold those away.
We have a patch for langref, sroa, mem2reg here: https://reviews.llvm.org/D104648
I have patches locally for InstSimplify & NewGVN to fix the phi issue mentioned above.
Changing the semantics of load of uninit memory breaks compatibility. Although most users won't notice, we would need to interface with the major frontends.
For clang, we would need to fix codegen of bit-fields as at the least the first field store loads uninit memory before masking it. The easy way is to just freeze the loaded value. Spill-over of poison from different fields is not an issue as if one field becomes poison is because some UB already happened in the program so we can spill over poison to neighboring fields.
Bitfields aren't very common, so this shouldn't be a major issue.
On LLVM's side, I believe the only issue is load widening. This must be either be removed at IR level, or we need to use vectors (or the byte type) for the widened type.
In summary, todo:
cc @aqjune @regehr @nikic @rotateright @LebedevRI @alinas