[llvm] [LangRef] Specify that dereferenceable implies a spurious read (PR #218413)
Nikita Popov via llvm-commits
llvm-commits at lists.llvm.org
Mon Aug 24 06:47:31 PDT 2026
https://github.com/nikic created https://github.com/llvm/llvm-project/pull/218413
Specify `dereferenceable` in terms of performing a spurious read of `n` bytes at function entry/exit. This is necessary because dereferenceability is used to introduce spurious reads through speculation. For this it is not sufficient to know that such a read cannot trap: Introducing such a read may introduce a noalias violation. The annotation itself needs to perform a spurious read to justify introduction of further such reads.
It should be noted that this places a standardization constraint on restrict in C++ (or alternatively, may ultimately render the use of dereferenceable for C++ references non-viable). I don't believe there should be any issues in pure C code, because we don't mark C pointers dereferenceable.
That is, something like this needs to be UB in C++:
```
void foo(int &a, int *__restrict b) {
*b = 0;
}
foo(x, &x);
```
As far as I know, defining dereferenceable in this way is the only way to make the model coherent, unless we can come up with some magic way to have noalias with poison on load instead of IUB, which appears to be impossible.
Related discussion: https://discourse.llvm.org/t/interaction-of-noalias-and-dereferenceable/66979
>From a4e09d58f69f85c7759a2215c3d0dc09cf7a8ef7 Mon Sep 17 00:00:00 2001
From: Nikita Popov <npopov at redhat.com>
Date: Mon, 24 Aug 2026 15:34:12 +0200
Subject: [PATCH] [LangRef] Specify that dereferenceable implies a spurious
read
Specify `dereferenceable` in terms of performing a spurious read
of `n` bytes at function entry/exit. This is necessary because
dereferenceability is used to introduce spurious reads through
speculation. For this it is not sufficient to know that such a
read cannot trap: Introducing such a read may introduce a noalias
violation. The annotation itself needs to perform a spurious read
to justify introduction of further such reads.
It should be noted that this places a standardization constraint
on restrict in C++ (or else, may ultimately render dereferenceable
for C++ references non-viable). I don't believe there should be
any issues in C, because we don't mark C pointers dereferenceable.
---
llvm/docs/LangRef.md | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/llvm/docs/LangRef.md b/llvm/docs/LangRef.md
index e77076bb68158..537d82007863a 100644
--- a/llvm/docs/LangRef.md
+++ b/llvm/docs/LangRef.md
@@ -1669,6 +1669,10 @@ Currently, only the following parameter attributes are defined:
freed after that point. Other attributes such as `nofree` can be used
to exclude frees.
+ `dereferenceable` implies a spurious read of `n` bytes (on function entry
+ for arguments and exit for return values). In particular, the bytes are
+ considered read for the purpose of `noalias`.
+
(attr_dereferenceable_or_null)=
`dereferenceable_or_null(<n>)`
More information about the llvm-commits
mailing list