4 ms·
do people think this is insightful? do you? > conventions are stupid all conventions are stupid when examined through the lens of an isolated island dweller.
by almostgotcaught 2y ago
do people think this is insightful? do you?
> conventions are stupid
all conventions are stupid when examined through the lens of an isolated island dweller. you might as well be saying something like "you only need to drive on the left-hand side of the road when you're driving on public roads".
- userbinator 2y agoCompilers were stupid, and that's how we ended up with this constant overhead of inefficiency long after they could've done better; it's only within the last decade or so that "custom calling conventions" started being even considered.
- almostgotcaught 2y agoCalling conventions have no more to do with dumb or smart compilers than driving on the left-hand side of the road has to do with dumb or smart urban planners.
- userbinator 2y agoOf course they do. An Asm programmer will naturally use the appropriate registers to minimise data movement (see also: PC BIOS interface - no stupid stack shit) depending on the circumstances, a stupid compiler will just push everything on the stack. A more intelligent compiler will behave more like the human programmer and decide how to pass parameters and save or restore registers on a case-by-case basis.
- almostgotcaught 2y ago[flagged]
- josephg 2y agoI think you two are arguing past each other. Calling conventions are obviously needed for syscalls and dynamically linked libraries. I don't think anyone is denying that. But most function calls aren't made to shared code. Almost all function calls are made to private functions, which exist within a binary, and are under the control of the compiler. If I steelman the person you're arguing with, I think what they're claiming that adhering to any specific calling convention for internal functions results in a lot of dumb assembly. For example, imagine I have a C program where function a() calls b(). So long as b is confined to my binary, the "calling convention" of b doesn't matter. All that matters is that the compiler knows how to call it, and pass all the arguments. The compiler could jump to the function or call it. It could put parameters in registers or leave them on the stack. An awful lot of executed instructions exist to move parameters into the correct registers, save whatever was using those registers before the call, and restore them afterwards. If we imagine this simple C code: int do_stuff(int a, int b, int c, int d) { int i = 1000; i += func1(a, b); // a, b passed in rdi, rsi. i += func2(c, d); // Call to func2 overwrites rdi & rsi. return i; } If both func1 and func2 are forced to use the same calling convention, between calls to func1 and func2, the CPU needs to place c and d into whatever registers a and b were in a moment ago. But modern CPUs have lots of registers. If the compiler were more clever, it could just use different registers for the arguments of both functions and avoid shuffling everything around. Godbolt: https://c.godbolt.org/z/zqxbb447e https://c.godbolt.org/z/zqxbb447e (Aside: Its weird how different the assembly is between GCC and clang in this example!) But - moving values between registers (or between a register and the stack) is crazy fast anyway. I'd love to see some benchmarks showing how much of a difference this optimisation would make in practice.
- userbinator 2y agoYou get it. That's exactly what I'm referring to. But - moving values between registers (or between a register and the stack) is crazy fast anyway. I'd love to see some benchmarks showing how much of a difference this optimisation would make in practice. It's fast, but the instructions still occupy space in caches, memory, and decoders; space that could've been used for other more valuable instructions. The problem is that the typical microbenchmarks don't show this sort of inefficiency (and on the other hand makes questionable-at-large options like loop unrolling seem great), because they're too small to see the effects of the waste.