#is converting parameters to a const pointer bad?
1 messages · Page 1 of 1 (latest)
the biggest downside i can think of (but i'm not sure if this is the one that you were reading about) is that making a parameter a pointer requires that the value be in memory
for small values that fit in registers, where in optimized code the caller probably already has it in registers rather than in memory, it's usually cheaper to keep the value in registers rather than store it in memory, calculate the address, pass that, and then have the callee load it
Main thing I can think of that would make this less performant is the compiler having to deal with aliasing
Since Zig doesn’t have a strict aliasing rule as far as I know, every pointer parameter can alias which would make this worse
yeah, you can specify noalias but most code doesn't
its possible for the optimizer to make a pointer parameter not a pointer if it determines it doesnt need to be
I love optimizers
wait noinline is broken 
lolwut
https://godbolt.org/z/PEsoWGMvq
this is what i was doing
thats super weird tho
It is not clear to me, what the semantic guarantees of @noInlineCall are. First of all, if the function that is being called is too simple inlining still occurs: // https://godbolt.org/z/IYjL0g exp...
silly llvm
no, it's not. LLVM is not allowed to inline the call, however the call itself can be removed
it's a pretty annoying distinction, but it's there
so it's zig's fault?
no, it's no-ones fault, this is how noinline works right now
if you were to put side-effects into two, it couldnt inline the call
well so noinline is designed incorrectly?
no, it works fine
noinline is not make_sure_the_call_exists
it means do not inline the call, if it exists
the optimizer is allowed to just remove the call
if you make two take a *volatile const u8, then it'll have side-effects when loading, and it wont be able to remove the call
it removed the call and replaced it with a copy of the function being called, how is that not inlining?
the call isnt doing anything
this is where there's a fine line. it didn't do that technically. what it did was solve what the function does, and then replace the call with it. it did not move the contents of the function into the call
it's a bit stupid, but this is how llvm gets away with this "technically" correct optimization
so like,
fn foo(x: u32, y: u32) u32 {
return x + y;
}
foo(10, 20)
->
fn foo() u32 {
return 30;
}
foo()
->
30
is not inlining, while
fn foo(x: u32, y: u32) u32 {
return x + y;
}
foo(10, 20);
->
10 + 20
->
30
is inlining
how is replacing foo() with 30 not inlining when replacing foo(10, 20) with 10 + 20 is
since 30 has been proven to be equal to foo(), the call itself can be removed in place of 30. the contents of foo isnt inlined.
see, https://godbolt.org/z/eda1be76P, where when you use it for two different things, it can no longer prove equalivance
i think i see the distinction you're drawing but i still think the end result is probably unfaithful to the intent of the programmer
anecdotally, i appreciate that zig's inline keyword is a guarantee, unlike in other languages, even if that probably allows people to use it to write worse code sometimes. i was expecting noinline to be similar, especially given the text "If the call is otherwise required to be inlined, a compile error is emitted instead." (technically that is not listed for noinline but rather for the .never_inline call modifier, but i was able to reproduce the same optimization using only .never_inline on a regular function). i'm sad noinline is not as powerful a tool as i thought to control the code that gets generated.