Skip to content

Inconsistent inlining of IndexOfAny vs IndexOfAnyExcept helpers #76843

@MihaZupan

Description

@MihaZupan

The (ReadOnlySpan<T> span, ReadOnlySpan<T> values) overloads of different IndexOfAny helpers have inconsistent inlining hints:

[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static int IndexOfAny<T>(this ReadOnlySpan<T> span, ReadOnlySpan<T> values) where T : IEquatable<T>?

[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static int LastIndexOfAny<T>(this ReadOnlySpan<T> span, ReadOnlySpan<T> values) where T : IEquatable<T>?

vs.
/// </returns>
public static int IndexOfAnyExcept<T>(this ReadOnlySpan<T> span, ReadOnlySpan<T> values) where T : IEquatable<T>?

/// </returns>
public static int LastIndexOfAnyExcept<T>(this ReadOnlySpan<T> span, ReadOnlySpan<T> values) where T : IEquatable<T>?


From @stephentoub in #76740 (comment):

a) we should make these consistent, and b) we should seriously reconsider the aggressive inlining that's on there (or consider how IsKnownConstant could be used here). If the values passed is a constant, then the JIT can do a good job of trimming away all of these branches. But if it's not, it results in significant code bloat to the call site, e.g. this:

private static bool Contains(string text, string values) =>
    text.AsSpan().IndexOfAny(values) >= 0;

results in this:

; Assembly listing for method ConsoleApp15.Program:Contains(System.String,System.String):bool
; Emitting BLENDED_CODE for X64 CPU with AVX - Windows
; optimized code
; rsp based frame
; partially interruptible
; No PGO data
; 2 inlinees with PGO data; 23 single block inlinees; 1 inlinees without PGO data

G_M000_IG01:                ;; offset=0000H
       4883EC48             sub      rsp, 72
 
G_M000_IG02:                ;; offset=0004H
       4885C9               test     rcx, rcx
       7475                 je       SHORT G_M000_IG10
 
G_M000_IG03:                ;; offset=0009H
       4C8D410C             lea      r8, bword ptr [rcx+0CH]
       8B4908               mov      ecx, dword ptr [rcx+08H]
 
G_M000_IG04:                ;; offset=0010H
       8BC1                 mov      eax, ecx
       4885D2               test     rdx, rdx
       7442                 je       SHORT G_M000_IG08
 
G_M000_IG05:                ;; offset=0017H
       488D4A0C             lea      rcx, bword ptr [rdx+0CH]
       448B4A08             mov      r9d, dword ptr [rdx+08H]
 
G_M000_IG06:                ;; offset=001FH
       8BD0                 mov      edx, eax
       89542444             mov      dword ptr [rsp+44H], edx
       48894C2438           mov      bword ptr [rsp+38H], rcx
       4183F905             cmp      r9d, 5
       0F871B010000         ja       G_M000_IG15
       418BC1               mov      eax, r9d
       4C8D0D2A010000       lea      r9, [reloc @RWD00]
       458B0C81             mov      r9d, dword ptr [r9+4*rax]
       4C8D15BBFFFFFF       lea      r10, G_M000_IG02
       4D03CA               add      r9, r10
       41FFE1               jmp      r9
 
G_M000_IG07:                ;; offset=004FH
       B8FFFFFFFF           mov      eax, -1
       E904010000           jmp      G_M000_IG16
 
G_M000_IG08:                ;; offset=0059H
       33C9                 xor      rcx, rcx
       4533C9               xor      r9d, r9d
       EBBF                 jmp      SHORT G_M000_IG06
 
G_M000_IG09:                ;; offset=0060H
       488B4C2438           mov      rcx, bword ptr [rsp+38H]
       480FBF01             movsx    rax, word  ptr [rcx]
       498BC8               mov      rcx, r8
       8BD0                 mov      edx, eax
       448B442444           mov      r8d, dword ptr [rsp+44H]
       FF1587A32000         call     [System.SpanHelpers:IndexOfValueType[short,DontNegate`1[short]](byref,short,int):int]
       E9DF000000           jmp      G_M000_IG16
 
G_M000_IG10:                ;; offset=007EH
       33C9                 xor      rcx, rcx
       4533C0               xor      r8d, r8d
       4987C8               xchg     rcx, r8
       EB88                 jmp      SHORT G_M000_IG04
 
G_M000_IG11:                ;; offset=0088H
       488B4C2438           mov      rcx, bword ptr [rsp+38H]
       4C0FBF09             movsx    r9, word  ptr [rcx]
       480FBF4102           movsx    rax, word  ptr [rcx+02H]
       498BC8               mov      rcx, r8
       418BD1               mov      edx, r9d
       448BC0               mov      r8d, eax
       448B4C2444           mov      r9d, dword ptr [rsp+44H]
       FF15BEBE2000         call     [System.SpanHelpers:IndexOfAnyValueType[short,DontNegate`1[short]](byref,short,short,int):int]
       E9AE000000           jmp      G_M000_IG16
 
G_M000_IG12:                ;; offset=00AFH
       488B4C2438           mov      rcx, bword ptr [rsp+38H]
       4C0FBF09             movsx    r9, word  ptr [rcx]
       480FBF4102           movsx    rax, word  ptr [rcx+02H]
       4C0FBF5104           movsx    r10, word  ptr [rcx+04H]
       89542420             mov      dword ptr [rsp+20H], edx
       498BC8               mov      rcx, r8
       418BD1               mov      edx, r9d
       448BC0               mov      r8d, eax
       458BCA               mov      r9d, r10d
       FF1570C62000         call     [System.SpanHelpers:IndexOfAnyValueType[short,DontNegate`1[short]](byref,short,short,short,int):int]
       E980000000           jmp      G_M000_IG16
 
G_M000_IG13:                ;; offset=00DDH
       488B4C2438           mov      rcx, bword ptr [rsp+38H]
       4C0FBF09             movsx    r9, word  ptr [rcx]
       480FBF4102           movsx    rax, word  ptr [rcx+02H]
       4C0FBF5104           movsx    r10, word  ptr [rcx+04H]
       480FBF4906           movsx    rcx, word  ptr [rcx+06H]
       894C2420             mov      dword ptr [rsp+20H], ecx
       89542428             mov      dword ptr [rsp+28H], edx
       498BC8               mov      rcx, r8
       418BD1               mov      edx, r9d
       448BC0               mov      r8d, eax
       458BCA               mov      r9d, r10d
       FF1559DE2000         call     [System.SpanHelpers:IndexOfAnyValueType[short,DontNegate`1[short]](byref,short,short,short,short,int):int]
       EB4C                 jmp      SHORT G_M000_IG16
 
G_M000_IG14:                ;; offset=0111H
       488B4C2438           mov      rcx, bword ptr [rsp+38H]
       4C0FBF09             movsx    r9, word  ptr [rcx]
       480FBF4102           movsx    rax, word  ptr [rcx+02H]
       4C0FBF5104           movsx    r10, word  ptr [rcx+04H]
       4C0FBF5906           movsx    r11, word  ptr [rcx+06H]
       480FBF4908           movsx    rcx, word  ptr [rcx+08H]
       44895C2420           mov      dword ptr [rsp+20H], r11d
       894C2428             mov      dword ptr [rsp+28H], ecx
       89542430             mov      dword ptr [rsp+30H], edx
       498BC8               mov      rcx, r8
       418BD1               mov      edx, r9d
       448BC0               mov      r8d, eax
       458BCA               mov      r9d, r10d
       FF154B842000         call     [System.SpanHelpers:IndexOfAnyValueType[short](byref,short,short,short,short,short,int):int]
       EB0E                 jmp      SHORT G_M000_IG16
 
G_M000_IG15:                ;; offset=014FH
       498BC8               mov      rcx, r8
       4C8B442438           mov      r8, bword ptr [rsp+38H]
       FF15A3222000         call     [System.MemoryExtensions:IndexOfAnyProbabilistic(byref,int,byref,int):int]
 
G_M000_IG16:                ;; offset=015DH
       F7D0                 not      eax
       C1E81F               shr      eax, 31
 
G_M000_IG17:                ;; offset=0162H
       4883C448             add      rsp, 72
       C3                   ret      
 
RWD00  	dd	0000004Bh ; case G_M000_IG07
       	dd	0000005Ch ; case G_M000_IG09
       	dd	00000084h ; case G_M000_IG11
       	dd	000000ABh ; case G_M000_IG12
       	dd	000000D9h ; case G_M000_IG13
       	dd	0000010Dh ; case G_M000_IG14

; Total bytes of code 359

cc: @EgorBo

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions