I have the following snippet:
static long F(long a, long b, long c, long d)
{
return a + b + c + d;
}
which generates:
<Program>$.<<Main>$>g__F|0_0(Int64, Int64, Int64, Int64)
L0000: add rdx, rcx
L0003: lea rax, [rdx+r8]
L0007: add rax, r9
L000a: ret
If I understand correctly from this (§ Out of order execution) manual: The code above translates to ((a + b) + c) + d. And to compute this the CPU has to wait for the 1st parenthesis and for the 2nd and so on. In here we see that LEA is in the middle which means that they can't be executed in parallel (if I understood that correctly). So what the writer suggests is:
writing parenthesis on "independent" pairs:
static long G(long a, long b, long c, long d)
{
return (a + b) + (c + d);
}
but this generates the same assembly:
<Program>$.<<Main>$>g__G|0_1(Int64, Int64, Int64, Int64)
L0000: add rdx, rcx
L0003: lea rax, [rdx+r8]
L0007: add rax, r9
L000a: ret
In contrast this is what GCC (O2) generates for C code:
int64_t
f(int64_t a, int64_t b, int64_t c, int64_t d) {
return a + b + c + d;
}
int64_t
g(int64_t a, int64_t b, int64_t c, int64_t d) {
return (a + b) + (c + d);
}
here is the output:
f:
add rcx, rdx ; I guess -O2 did the job for me.
add rcx, r8 ; I guess -O2 did the job for me.
lea rax, [rcx+r9]
ret
g:
add rcx, rdx
add r8, r9
lea rax, [rcx+r8]
ret
Question
- Did I understand the manual correctly? Should the 2
ADDs come with each other (noLEAin the middle)? If yes how can I hint theC#compiler to not ignore my parenthesis?