Related Threads:
- [llvm-dev] [RFC] How to manifest information in LLVM-IR, or, revisiting llvm.assume
- Discourse: @llvm.assume blocks optimization (#71609)
1. Summary
This RFC proposes a new memory location category, fresh, for the LLVM IR memory(...) function attribute. The fresh location models a call-private, non-aliasing side-effect sink: effects written to fresh are guaranteed not to interact with any other memory location, including other fresh accesses from different calls.
Only none (the default) and write are meaningful for fresh; read and readwrite are semantically invalid and will be rejected.
The primary motivation is to unblock optimizations that are currently pessimized by @llvm.assume and its outlined counterpart "assume_fn" , as extensively discussed in Discourse #71609.
2 Prior Art: assume_mem
Johannes Doerfert proposed memory(assume_mem: write) as an intermediate step in Discourse #71609. This isolates assume side effects from regular memory, malloc, and global state. However, assume_mem is still a shared abstract location: multiple @llvm.assume calls all write to the same assume_mem, so the compiler must still reason about ordering and interference between them.
We need a stronger guarantee.
3. Design: memory(fresh)
3.1 Semantics
fresh introduces a new IRMemLocation that behaves unlike any existing location category (argmem , inaccessiblemem , errnomem , target_mem , etc.).
Core axiom:
Every call site has its own private
freshlocation. Two accesses tofreshfrom different call sites never alias, regardless of the access type.
This means:
fresh: writefrom Call A does not aliasfresh: writefrom Call B.fresh: writedoes not alias any other memory location (includingargmem,inaccessiblemem,Other, etc.).- There is no “read” from a
freshlocation that yields data written by another call.
3.2 Legal and Illegal Forms
Because fresh is a private sink that is never observable by other operations, reading from it is meaningless :
| Form | Status | Rationale |
|---|---|---|
memory(fresh: none) |
Legal (default) | No fresh access. |
memory(fresh: write) |
Legal | Side effects sink into a private hole. |
memory(fresh: read) |
Iilegal | No prior data exists in a fresh location; reading is undefined/self-referential. |
memory(fresh: readwrite) |
Iilegal | The read component is meaningless. |
Parser/verifier will reject fresh: read and fresh: readwrite .
3.3 Alias Analysis Rules
The implementation introduces specialized handling within BasicAliasAnalysis (and potentially AAResults) to exploit the independence guarantee of fresh memory:
When analyzing two memory locations, if both LocA and LocB are marked as fresh, the alias analysis must report AliasResult::NoAlias unconditionally. This holds true even when both locations originate from different invocations of the same function, as each fresh allocation denotes a distinct, non-overlapping region of memory.
This behavior represents a fundamental departure from assume_mem. Under assume_mem, multiple calls may still reference a shared abstract memory location, leaving room for potential interference between them. In contrast, fresh provides a hard independence guarantee: any two fresh locations are strictly disjoint, enabling the alias analyzer to definitively rule out aliasing without further context or analysis.