-
-
Notifications
You must be signed in to change notification settings - Fork 2.7k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
sometimes there is an unwanted memcpy when passing large structs by-value #17580
Comments
This code looks pretty similar to #15685, might be the same issue. Glad to see that it gets priority.
I tried changing to const pointer in your code, but that didn't appear to change the llvm-ir at all. fn method(foo: *const Foo, index: usize) bool {
return (&foo.array)[noop(index)];
} So I think this is also related to array access inside a struct and not purely the passing by value. |
Fix reverted in 9d5a133. |
…ers" This reverts commit 2ab7893. Premature merge - apologies for the disruption. Reopens ziglang#15685 Reopens ziglang#17580
…ers" This reverts commit 2ab7893. Premature merge - apologies for the disruption. Reopens ziglang#15685 Reopens ziglang#17580
The example above can be futher reduced down to var array: [100]bool = undefined;
fn noop(index: usize) usize {
return index;
}
export fn method(index: usize) bool {
return array[noop(index)];
} which exhibits the problem, and var array: [100]bool = undefined;
fn noop(index: usize) usize {
return index;
}
export fn method(index: usize) bool {
const hello = noop(index);
return array[hello];
} that does not. The AIR emitted by the first example has the |
Okay these are my findings from investigating this way too much. I was wrong in my post above. Consider the following code snippet: var array: [100]bool = undefined;
fn noop(index: usize) usize {
return index;
}
export fn method(index: usize) bool {
return array[noop(index)];
} This corresponds to the following AIR
There's kind of an implicit pass-by-value going on here. If I understand the semantics of zig correctly the behavior we want is that the The only way I see to elide the |
Good sleuthing - you've reached essentially the same conclusion I came to when I briefly looked at this. In essence, the logic is operating completely correctly by the current widely understood semantics. The way we solve this issue likely has wide-reaching implications for the language design surrounding aliasing, PRO, etc. @andrewrk - since this issue is a high priority, it might be worth having a one-time compiler / language design meeting to discuss how to solve it? Whatever we decide will have spec implications. |
I think I just stepped into that problem while trying to optimize code by using I can try to give a reproducible example if needed, but currently PS: The bit_set was 100bytes in size |
I encountered the exact same problem here, which was infortunate because I wanted to try using the bitset for performance reasons and it was very puzzling where the memcpy came from. |
Zig Version:
0.12.0-dev.1103+7a9500fd80
This reduced code snippet results in an unwanted memcpy when passing a large struct by value:
The alloca and memcpy are undesirable. With this change, it goes away:
Temporary workaround is to pass by const pointer instead. However, we don't want Zig users to get used to doing this, or they will never kick the habit even when this issue is fixed, which is why I am making this a high priority issue, and denying any more requests to do the workaround in the standard library.
After fixing this, revert 90a877f.
Related:
ArrayBitSet
by*const
instead of by value #14129The text was updated successfully, but these errors were encountered: