5 ms·
In the provided example, you can fix it without affecting any caller by changing the parameter types from “struct Vector” to “const struct Vector &” pass-by-ref
by bugbuddy 3y ago
In the provided example, you can fix it without affecting any caller by changing the parameter types from “struct Vector” to “const struct Vector &” pass-by-reference. A lot C++ code that I have seen where pointer bugs existed needlessly used pointers even when passing by reference could have worked while being easier and safer to use.
- giovannibajo1 3y agoThat will still require the compiler to serialize the three registers to the stack, to be able to pass the pointer to the structure to the callee. It seems like the described benefit is avoiding any serialization from registers to stack, which cannot be avoided with pass-by-reference.
- bugbuddy 3y agoBut that would only be possible if you write out all the struct fields you are accessing into function parameters. If the struct is complex with a lot of fields, then you would end up with a messy function signature. Also, I am sure there is a limit to how many parameters you can have before this optimization stops working.
- loeg 3y ago> But that would only be possible if you write out all the struct fields you are accessing into function parameters. If the struct is complex with a lot of fields, then you would end up with a messy function signature. This is the approach the article's author took.
- fsckboy 3y ago>That will still require the compiler to serialize the three registers to the stack, to be able to pass the pointer to the structure to the callee. why can't it simply pass a pointer to the struct (it's probably already on the stack) without rewriting the struct to the stack? isn't that what a reference is?
- kukkamario 3y agoBut it often isn't in the stack. This is a vector type so it is often modified and used as part of math operations. Each vector field is probably in some register because it was used to calculate something and then has to be stored back to stack to get valid data for the reference.
- fsckboy 3y agoif current values of source-code-struct fields are in registers, there are two options, that the calling function and struct is so small and so compiler optimized that there is no memory allocation for the struct, or there is an allocation and it's just dirty and not updated. Which means update it and call, or spill and call. You want to call a function that is not expecting its arguments to be in registers, and you don't have unlimited registers on this hardware at this time, so I don't understand all the hand-wringing about either option. I guess what I'm saying is that this is all being treated like "because we assume optimization and we know how optimization works, we're entitled to have what's important in registers all the time so things will go faster, so this must be a bug and we have to fix it." The actual solution is to inline the callee and rely on the compiler, switch to asm and hand guarantee, or create a new language that has register calling or data flow semantics that are different than what you have now. The conversation that's taking place here sounds to me like relying on undefined behaviors, something we used to do because we knew we could rely on them but you can't any more.
- kukkamario 3y agoNo. Actually that is the whole problem here. That is pretty much exactly what the compiler does thanks to ABI. ABI says that the value must be passed by pointer so it has to store it somewhere to get the pointer, which is exactly the same that would happen if we made that explicit by using const-ref. By changing to use separate arguments for the struct values, arguments can be passed in registers instead.
- gpderetta 3y agoon the other hand if the function is simple enough that the call overhead is significant, [[force_inline]] is an option.
- FeepingCreature 3y agoWhen I found this issue, it was in code that had twenty or thirty allocas to pass pointers to my byvals. Every function would start with a separate alloca for every parameter that was passed to a call. I always sort of assumed that LLVM would be good at cleaning that sort of thing up. It turns out... no, it isn't.
- 1letterunixname 3y agoThis was a C99 example, not a C++ one. In many environments, tools cannot be changed arbitrarily because of minimum inertia. If C++ were allowed, then more options are available including moved arguments to reduce copying.