Skip to content

Consider special-casing == "" in the JIT? #63719

Description

@stephentoub

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 == "" or s != "". These have measurably worse codegen than just doing a null and length check, e.g.
https://sharplab.io/#v2:EYLgxg9gTgpgtADwGwBYA0AXEBDAzgWwB8ABAZgAJiAmcgYQFgAoAbyfPfIAcoBLAN2wYYlAIxJywCBAA25ALIiAFMREAGcgOkBXGAEpyAXgB8G7NuEGD5AETWA3Gw7d+g4SvGSZ8qsrWnz+sb+OuQ8uOQAdhAYkVrSsgBkCcEwAHQAMjARAOYYABaGVqoOjAC+QA===

public class C
{
    private static bool M1(string value) => value == "";
    private static bool M2(string value) => value is not null && value.Length == 0;
}

producing

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?

cc: @EgorBo

Metadata

Metadata

Assignees

No one assigned

    Labels

    area-CodeGen-coreclrCLR JIT compiler in src/coreclr/src/jit and related components such as SuperPMIuntriagedNew issue has not been triaged by the area owner

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions