Hey, I am trying to understand how noalias
works and need some clarification.
The current Zig documentation sadly isn’t very helpful:
The noalias keyword.
TODO add documentation for noalias
The LLVM docs state the following about noalias:
This indicates that memory locations accessed via pointer values based on the argument or return value are not also accessed, during the execution of the function, via pointer values not based on the argument or return value. This guarantee only holds for memory locations that are modified, by any means, during the execution of the function.
and about pointer aliasing:
A pointer value is associated with the addresses associated with any value it is based on.
A pointer value formed from a scalar
getelementptr
operation is based on the pointer-typed operand of thegetelementptr
.
The pointer in lane l of the result of a vectorgetelementptr
operation is based on the pointer in lane l of the vector-of-pointers-typed operand of thegetelementptr
.
This is where I am a little confused. In contrast to C restrict
, Zig noalias
is per-parameter, not per-pointer.
For example what’s happening here?
export fn aliasing(noalias ptr: *const [3]*[16]u64) u64 {
var res: u64 = 0;
for (ptr) |p| {
for (p) |i| {
res += i;
}
}
return res;
}
Does noalias
only cover the actual pointer values pointed to by ptr or does it also cover the u64
these pointers point to recusively? Are the u64
arrays still based on ptr
?
Looking at the LLVM IR:
define dso_local i64 @aliasing(ptr noalias nocapture nonnull readonly align 8 %0) local_unnamed_addr {
Entry:
%1 = load ptr, ptr %0, align 8
%2 = load <16 x i64>, ptr %1, align 8
%3 = getelementptr inbounds nuw i8, ptr %0, i64 8
%4 = load ptr, ptr %3, align 8
%5 = getelementptr inbounds nuw i8, ptr %0, i64 16
%6 = load ptr, ptr %5, align 8
%7 = load <16 x i64>, ptr %4, align 8
%8 = load <16 x i64>, ptr %6, align 8
[...]
are the load <16 x i64>
instructions still based on ptr
?
In other words, is noalias
applied recursively to nested pointers, as if they were all marked restrict
, or only to the top level pointer?