C.M1(System.String)
L0000: push rax
L0001: mov rax, 0x201b0fc3020
L000b: cmp rcx, [rax]
L000e: je short L0053
L0010: test rcx, rcx
L0013: je short L001b
L0015: cmp dword ptr [rcx+8], 0
L0019: je short L0022
L001b: xor eax, eax
L001d: add rsp, 8
L0021: ret
L0022: lea rdx, [rcx+0xc]
L0026: mov r8, 0x201b0fc3020
L0030: mov r8, [r8]
L0033: add r8, 0xc
L0037: mov [rsp], r8
L003b: mov ecx, [rcx+8]
L003e: add ecx, ecx
L0040: mov r8d, ecx
L0043: mov rcx, rdx
L0046: mov rdx, [rsp]
L004a: add rsp, 8
L004e: jmp 0x00007ffb1b5eafa0
L0053: mov eax, 1
L0058: jmp short L001d
C.M2(System.String)
L0000: test rcx, rcx
L0003: je short L0010
L0005: cmp dword ptr [rcx+8], 0
L0009: sete al
L000c: movzx eax, al
L000f: ret
L0010: xor eax, eax
L0012: ret
While a developer could have written a better check, I wonder if it'd be worthwhile special-casing a comparison against an empty string literal (both "" and string.Empty) in the JIT?
I tried enabling CA1820 ("Test for empty strings using string length") and it flagged more than 100 cases in a libraries build. Many of them were of the form
s == ""ors != "". These have measurably worse codegen than just doing a null and length check, e.g.https://sharplab.io/#v2:EYLgxg9gTgpgtADwGwBYA0AXEBDAzgWwB8ABAZgAJiAmcgYQFgAoAbyfPfIAcoBLAN2wYYlAIxJywCBAA25ALIiAFMREAGcgOkBXGAEpyAXgB8G7NuEGD5AETWA3Gw7d+g4SvGSZ8qsrWnz+sb+OuQ8uOQAdhAYkVrSsgBkCcEwAHQAMjARAOYYABaGVqoOjAC+QA===
producing
While a developer could have written a better check, I wonder if it'd be worthwhile special-casing a comparison against an empty string literal (both "" and string.Empty) in the JIT?
cc: @EgorBo