-
Notifications
You must be signed in to change notification settings - Fork 5.3k
Description
Description
When working on my program performance optimization and inspecting the generated code, I came across the following issue. Here is a small piece of C# code and what it gets compiled into:
`
S s = default;
ref int r = ref s.i;
r += 1;
r = r + 1;
ref S rs = ref s;
rs.i += 1; // this line generates some stupid machine code (esp. 'cmp' opcode)
rs.i = rs.i + 1; // while this line compiles perfectly
s.i += 1; // this allocates a redundant var on stack
s.i = s.i + 1; // ok
public struct S
{
public int i;
}
`
The Disassembly output shows this:
`
ref int r = ref s.i;
00007FF9DC807164 lea rcx,[rbp+48h]
00007FF9DC807168 mov qword ptr [rbp+40h],rcx
r += 1;
00007FF9DC80716C mov rcx,qword ptr [rbp+40h]
00007FF9DC807170 inc dword ptr [rcx]
r = r + 1;
00007FF9DC807172 mov rcx,qword ptr [rbp+40h]
00007FF9DC807176 inc dword ptr [rcx]
ref S rs = ref s;
00007FF9DC807178 lea rcx,[rbp+48h]
00007FF9DC80717C mov qword ptr [rbp+38h],rcx
rs.i += 1; // this line generates some stupid machine code (esp. 'cmp' opcode)
00007FF9DC807180 mov rcx,qword ptr [rbp+38h]
00007FF9DC807184 cmp byte ptr [rcx],cl
00007FF9DC807186 mov rcx,qword ptr [rbp+38h]
00007FF9DC80718A mov qword ptr [rbp+30h],rcx
00007FF9DC80718E mov rcx,qword ptr [rbp+30h]
00007FF9DC807192 inc dword ptr [rcx]
rs.i = rs.i + 1; // while this line compiles perfectly
00007FF9DC807194 mov rcx,qword ptr [rbp+38h]
00007FF9DC807198 inc dword ptr [rcx]
s.i += 1; // this allocates a redundant var on stack
00007FF9DC80719A lea rcx,[rbp+48h]
00007FF9DC80719E mov qword ptr [rbp+28h],rcx
00007FF9DC8071A2 mov rcx,qword ptr [rbp+28h]
00007FF9DC8071A6 inc dword ptr [rcx]
s.i = s.i + 1; // ok
00007FF9DC8071A8 mov ecx,dword ptr [rbp+48h]
00007FF9DC8071AB inc ecx
00007FF9DC8071AD mov dword ptr [rbp+48h],ecx
`
It follows then, that using compound assignment ops with struct refs leads to sub-optimal code compared to equivalent unfolded assignment statement.
Configuration
.NET 8.0 (C# 12.0), Visual C 17.9.4
OS: Windows 10
Arch: x64
Regression?
No