[llvm] LangRef: storing poison in memory is UB (PR #141339)
Yingwei Zheng via llvm-commits
llvm-commits at lists.llvm.org
Tue May 27 01:39:53 PDT 2025
dtcxzyw wrote:
I used to hit a rare miscompilation with rustlantis + llubi, which contains a store with poison value in the optimized IR. It is a miscompilation under both the current semantics (propagating poison in loaded values) and the proposed semantics (storing poison is an imm UB). Unfortunately, I did not keep the reproducer and made a workaround in llubi by treating it as a no-op.
Given the fact that a load in real hardware always preserves well-defined bytes in memory, I think it is possible to make load widening legal.
Currently, a poison byte in memory may infect the whole loaded non-vector single value. Instead of `loadV2(Ptr) = freeze(loadV1(Ptr))` discussed in
https://discourse.llvm.org/t/rfc-add-nopoison-attribute-metadata/79833/5, we can make the load instruction act as the following:
```
# Assume that Type is a non-vector single value type.
def loadV3(Ptr, Type):
Size = Type.sizeInBytes()
AllPoison = True
Bytes = []
for I in range(0, Size):
Byte = loadByte(Ptr + I)
if Byte != poison:
AllPoison = False
Bytes.append(Byte)
else:
# Freeze poison bytes instead of freezing the whole value.
Bytes.append(freeze(Byte))
if AllPoison:
return poison
return toVal(Bytes)
```
It still preserves poison in most cases, so that SROA does not need to insert freezes. I just have a glance at https://github.com/llvm/llvm-project/issues/52930 and it seems a feasible solution.
I am fine with warning frontend developers about the potential unexpected behavior of storing poison values. But making it an immediate UB does not improve the situation.
https://github.com/llvm/llvm-project/pull/141339
More information about the llvm-commits
mailing list