Replies: 2 comments
-
/cc: @EgorBo |
Beta Was this translation helpful? Give feedback.
0 replies
-
For comparison static bool StartsWith(string s) => s is { } && (s.StartsWith("ABCD", Ordinal) || s.StartsWith("EFGH", Ordinal)); Program.<<Main>$>g__StartsWith|0_0(System.String)
L0000: test rcx, rcx
L0003: je short L003c
L0005: cmp dword ptr [rcx+8], 4
L0009: jl short L0033
L000b: mov rax, [rcx+0xc]
L000f: mov rcx, 0x44004300420041
L0019: cmp rax, rcx
L001c: je short L0036
L001e: mov rcx, 0x48004700460045
L0028: cmp rax, rcx
L002b: sete al
L002e: movzx eax, al
L0031: jmp short L0035
L0033: xor eax, eax
L0035: ret
L0036: mov eax, 1
L003b: ret
L003c: xor eax, eax
L003e: ret And static bool EndsWith(string s) => s is { } && (s.EndsWith("ABCD", Ordinal) || s.EndsWith("EFGH", Ordinal));
static bool EndsWith2(string s) => s is { Length: >= 4 } && (s.EndsWith("ABCD", Ordinal) || s.EndsWith("EFGH", Ordinal)); Program.<<Main>$>g__EndsWith|0_1(System.String)
L0000: push rbx
L0001: sub rsp, 0x20
L0005: mov rbx, rcx
L0008: test rbx, rbx
L000b: je short L0066
L000d: mov rdx, 0x1e280070938
L0017: mov rdx, [rdx]
L001a: mov rcx, rbx
L001d: mov r8d, 4
L0023: mov rax, 0x7ffcbcde6130
L002d: call qword ptr [rax]
L002f: test eax, eax
L0031: jne short L005b
L0033: mov rdx, 0x1e280070968
L003d: mov rdx, [rdx]
L0040: mov rcx, rbx
L0043: mov r8d, 4
L0049: mov rax, 0x7ffcbcde6130
L0053: add rsp, 0x20
L0057: pop rbx
L0058: jmp qword ptr [rax]
L005b: mov eax, 1
L0060: add rsp, 0x20
L0064: pop rbx
L0065: ret
L0066: xor eax, eax
L0068: add rsp, 0x20
L006c: pop rbx
L006d: ret
Program.<<Main>$>g__EndsWith2|0_2(System.String)
L0000: push rbx
L0001: sub rsp, 0x20
L0005: mov rbx, rcx
L0008: test rbx, rbx
L000b: je short L006c
L000d: cmp dword ptr [rbx+8], 4
L0011: jl short L006c
L0013: mov rdx, 0x1e280070938
L001d: mov rdx, [rdx]
L0020: mov rcx, rbx
L0023: mov r8d, 4
L0029: mov rax, 0x7ffcbcde6130
L0033: call qword ptr [rax]
L0035: test eax, eax
L0037: jne short L0061
L0039: mov rdx, 0x1e280070968
L0043: mov rdx, [rdx]
L0046: mov rcx, rbx
L0049: mov r8d, 4
L004f: mov rax, 0x7ffcbcde6130
L0059: add rsp, 0x20
L005d: pop rbx
L005e: jmp qword ptr [rax]
L0061: mov eax, 1
L0066: add rsp, 0x20
L006a: pop rbx
L006b: ret
L006c: xor eax, eax
L006e: add rsp, 0x20
L0072: pop rbx
L0073: ret |
Beta Was this translation helpful? Give feedback.
0 replies
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
-
When looking at the generated ASM for
M1
,s
is null checked a single time, but itsLength
is checked before each comparison with the constant strings.As all the constant strings are of length 4, we can make a single length check on
s
.Doing this generates ASM where we only have a single null check and a single length check.
It is possible for the JIT to perform a similar reasoning?
// * Summary *
BenchmarkDotNet v0.13.12, Windows 10 (10.0.19045.4291/22H2/2022Update)
Intel Core i7-10750H CPU 2.60GHz, 1 CPU, 12 logical and 6 physical cores
.NET SDK 9.0.100-preview.3.24204.13
[Host] : .NET 9.0.0 (9.0.24.17209), X64 RyuJIT AVX2
DefaultJob : .NET 9.0.0 (9.0.24.17209), X64 RyuJIT AVX2
And similarly when doing unrolled case-insensitive string comparisons
M3
has 6or
, whileM4
has a single.Beta Was this translation helpful? Give feedback.
All reactions