On Fri, Apr 3, 2026 at 3:31 AM Andres Freund <[email protected]> wrote: > > I see a few options, but I need to hack on them for a while to figure > > out the tradeoffs, or what I'm missing... after the freeze. > > I've experimented a bunch with this, it seems we need the larger changes done > as part of the patchset for removing pointers from the expressions to actually > allow recent-ish LLVM to optimize this. I did verify that what we did didn't > have an effect with any other recent LLVM either.
Yeah, I noticed this connection as well, coming at it from a keyhole how-do-I-fix-THIS-problem angle. It seemed to me that where ExecInitFunc() builds the code to compute argument values to push into &fcinfo->args[argno].value (a palloc'd FunctionCallInfoData object), it might first alloca the space and store the collid etc (and after return, it could lifetime.end it, or maybe the eventual ret in the caller is enough but I don't see any reason not to lifetime.end it ASAP), and then the destination would become a pointer into that, and the most natural thing would be a stack pointer-relative one, and then you'd have removed a major source of non-cacheability of compiled expressions. It took me a while to grok the function argument layout, which is ... this might be a stretch... a bit like Fortran, neither a linear stack nor a spaghetti stack, but just a bag of variables ready to be used as functions arguments, with recursion not permitted. And also to grok the quirks of our V1 calls that compelled you to do it like that. But I'm still learning the secrets of this code and I may be way off base in these musings, I haven't actually tried anything and it sounds like I should keep out of your way... > The real fix here might be to have a separate calling convention for the very > common case of a scalar stable function with 1-3 arguments. We loose a fair > bit of efficiency even in interpreted execution due to ferrying arguments, > their nullness, and the nullness of the return value through memory. Yeah. I understand much better why you say that now. FunctionCallInfoData holds data with two different lifetimes, some of which might not be needed.
