[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