Perf improvements to Span and Memory by GrabYourPitchforks · Pull Request #20771 · dotnet/coreclr (original) (raw)

return condition ? false : true

emits a branch

G_M61453_IG01:

G_M61453_IG02: 8BC7 mov eax, edi 8BFE mov edi, esi 4803C7 add rax, rdi 8BFA mov edi, edx 483BC7 cmp rax, rdi 7706 ja SHORT G_M61453_IG04 B801000000 mov eax, 1

G_M61453_IG03: C3 ret

G_M61453_IG04: 33C0 xor eax, eax

G_M61453_IG05: C3 ret

When written as just return cond the "setb al / movzx eax, al" is generated.

G_M61452_IG01:

G_M61452_IG02: 8BC7 mov eax, edi 8BFE mov edi, esi 4803C7 add rax, rdi 8BFA mov edi, edx 483BC7 cmp rax, rdi 0F96C0 setbe al 0FB6C0 movzx rax, al

G_M61452_IG03: C3 ret

But when this methods gets inlined, this patterns vanishes. Trivial example:

internal static bool IsRangeInBounds(int offset, int length, int availableLength) { return (ulong)(uint)offset + (ulong)(uint)length <= (ulong)(uint)availableLength; }

[MethodImpl(MethodImplOptions.NoInlining)] private static int Foo(int offset, int len, int availLen) { if (!IsRangeInBounds(offset, len, availLen)) Throw();

return availLen - (offset + len);

void Throw() => throw new Exception();

}

generates

G_M7900_IG01: 50 push rax

G_M7900_IG02: 8BC7 mov eax, edi 8BCE mov ecx, esi 4803C1 add rax, rcx 8BCA mov ecx, edx 483BC1 cmp rax, rcx 770B ja SHORT G_M7900_IG05

G_M7900_IG03: 03FE add edi, esi 8BC2 mov eax, edx 2BC7 sub eax, edi

G_M7900_IG04: 4883C408 add rsp, 8 C3 ret

G_M7900_IG05: E869F9FFFF call Program:g__Throw|7_0() CC int3