Semantics of null_pointer_is_valid: can null access inaccessible memory?

TL;DR: LLVM does the following transformation:

define i32 @src() null_pointer_is_valid {
  %V = load i32, ptr null
  ret i32 %V
}

define i32 @tgt() null_pointer_is_valid memory(inaccessiblemem: none) {
  %V = load i32, ptr null
  ret i32 %V
}

Alive2 right now isn’t happy about this transformation since it assumes that null may alias with inaccessible memory.
It’s true that any function can use the null pointer and access it. But the same reasoning holds for a inttoptr 0x42 pointer. Are we going to mark those as not accessing inaccessible memory as well? (I think we shouldn’t)

Any comments, opinions, etc?

Thanks!

cc @nikic

IMHO, inaccessible memory can only accessed via calls. If it is directly accessible from the module, it’s by definition not inaccessible memory.

That implies that every function for which we have a definition can be marked with memory(inaccessiblemem: none)?
Or does it propagate through the CFG (i.e., a caller of a function that may access inaccessible memory will itself be marked as potentially accessing such memory as well)?

The 2nd option sounds good to me.

2nd option, yes. If a function transitively can access inaccessible memory we can’t do much, but starting from the leafs we can propagate it.
The Attributor should do that already.

Makes sense, thanks!