Skip to content

Vector512.Shuffle does not produce optimal codegen in some case #115078

Description

@tfenise

Description

Code

static Vector512<byte> M1(Vector512<byte> v)
{
    Vector512<byte> s = Vector512.Create(0x01020304_05060708, 0x090A0B0C_0D0E0F00, 0x11121314_15161718, 0x191A1B1C_1D1E1F10,
                                         0x21222324_25262728, 0x292A2B2C_2D2E2F20, 0x31323334_35363738, 0x393A3B3C_3D3E3F30).AsByte();
    Vector512<byte> l_v = v;
    for (int i = 0; i < 100; i++)
    {
        l_v = Vector512.Shuffle(l_v, s);
    }
    return l_v;
}

static Vector512<byte> M2(Vector512<byte> v)
{
    Vector512<byte> l_v = v;
    for (int i = 0; i < 100; i++)
    {
        l_v = Vector512.Shuffle(l_v, Vector512.Create(0x01020304_05060708, 0x090A0B0C_0D0E0F00, 0x11121314_15161718, 0x191A1B1C_1D1E1F10,
                                                      0x21222324_25262728, 0x292A2B2C_2D2E2F20, 0x31323334_35363738, 0x393A3B3C_3D3E3F30).AsByte());
    }
    return l_v;
}

static Vector512<byte> M3(Vector512<byte> v)
{
    Vector512<byte> s = Vector512.Create(0x01020304_05060708, 0x090A0B0C_0D0E0F00, 0x11121314_15161718, 0x191A1B1C_1D1E1F10,
                                         0x21222324_25262728, 0x292A2B2C_2D2E2F20, 0x31323334_35363738, 0x393A3B3C_3D3E3F30).AsByte();
    Vector512<byte> l_v = v;
    l_v = Vector512.Shuffle(l_v, s);
    return l_v;
}

Codegen

; Assembly listing for method ConsoleApp1.Program:M1(System.Runtime.Intrinsics.Vector512`1[ubyte]):System.Runtime.Intrinsics.Vector512`1[ubyte] (Tier1)
; Emitting BLENDED_CODE for X64 with AVX512 - Windows
; Tier1 code
; optimized code
; optimized using Synthesized PGO
; rsp based frame
; fully interruptible
; with Synthesized PGO: fgCalledCount is 69

G_M000_IG01:                ;; offset=0x0000

G_M000_IG02:                ;; offset=0x0000
       vmovups  zmm0, zmmword ptr [reloc @RWD00]
       vmovups  zmm1, zmmword ptr [rdx]
       mov      eax, 100
       align    [0 bytes for IG03]

G_M000_IG03:                ;; offset=0x0015
       vpermb   zmm1, zmm0, zmm1
       vpcmpub  k1, zmm0, zmmword ptr [reloc @RWD64], 1
       vpmovm2b zmm2, k1
       vpandd   zmm1, zmm2, zmm1
       dec      eax
       jne      SHORT G_M000_IG03

G_M000_IG04:                ;; offset=0x0036
       vmovups  zmmword ptr [rcx], zmm1
       mov      rax, rcx

G_M000_IG05:                ;; offset=0x003F
       vzeroupper
       ret

RWD00   dq      0102030405060708h, 090A0B0C0D0E0F00h, 1112131415161718h, 191A1B1C1D1E1F10h, 2122232425262728h, 292A2B2C2D2E2F20h, 3132333435363738h, 393A3B3C3D3E3F30h
RWD64   dq      4040404040404040h, 4040404040404040h, 4040404040404040h, 4040404040404040h, 4040404040404040h, 4040404040404040h, 4040404040404040h, 4040404040404040h

; Total bytes of code 67

; Assembly listing for method ConsoleApp1.Program:M2(System.Runtime.Intrinsics.Vector512`1[ubyte]):System.Runtime.Intrinsics.Vector512`1[ubyte] (Tier1)
; Emitting BLENDED_CODE for X64 with AVX512 - Windows
; Tier1 code
; optimized code
; optimized using Synthesized PGO
; rsp based frame
; fully interruptible
; with Synthesized PGO: fgCalledCount is 72

G_M000_IG01:                ;; offset=0x0000

G_M000_IG02:                ;; offset=0x0000
       vmovups  zmm0, zmmword ptr [rdx]
       vmovups  zmm1, zmmword ptr [reloc @RWD00]
       mov      eax, 100
       align    [0 bytes for IG03]

G_M000_IG03:                ;; offset=0x0015
       vpshufb  zmm0, zmm0, zmm1
       dec      eax
       jne      SHORT G_M000_IG03

G_M000_IG04:                ;; offset=0x001F
       vmovups  zmmword ptr [rcx], zmm0
       mov      rax, rcx

G_M000_IG05:                ;; offset=0x0028
       vzeroupper
       ret

RWD00   dq      0102030405060708h, 090A0B0C0D0E0F00h, 1112131415161718h, 191A1B1C1D1E1F10h, 2122232425262728h, 292A2B2C2D2E2F20h, 3132333435363738h, 393A3B3C3D3E3F30h

; Total bytes of code 44

; Assembly listing for method ConsoleApp1.Program:M3(System.Runtime.Intrinsics.Vector512`1[ubyte]):System.Runtime.Intrinsics.Vector512`1[ubyte] (Tier1)
; Emitting BLENDED_CODE for X64 with AVX512 - Windows
; Tier1 code
; optimized code
; optimized using Synthesized PGO
; rsp based frame
; partially interruptible
; with Synthesized PGO: fgCalledCount is 100
; No PGO data

G_M000_IG01:                ;; offset=0x0000

G_M000_IG02:                ;; offset=0x0000
       vmovups  zmm0, zmmword ptr [rdx]
       vpshufb  zmm0, zmm0, zmmword ptr [reloc @RWD00]
       vmovups  zmmword ptr [rcx], zmm0
       mov      rax, rcx

G_M000_IG03:                ;; offset=0x0019
       vzeroupper
       ret

RWD00   dq      0102030405060708h, 090A0B0C0D0E0F00h, 1112131415161718h, 191A1B1C1D1E1F10h, 2122232425262728h, 292A2B2C2D2E2F20h, 3132333435363738h, 393A3B3C3D3E3F30h

; Total bytes of code 29

Note in M1, Vector512.Shuffle() generates the slower and less available(vpermb requires AVX512_VBMI) sequence of

       vpermb   zmm1, zmm0, zmm1
       vpcmpub  k1, zmm0, zmmword ptr [reloc @RWD64], 1
       vpmovm2b zmm2, k1
       vpandd   zmm1, zmm2, zmm1

but in M2 where s is inlined, or in M3 where the loop is removed, Vector512.Shuffle() generates the intended vpshufb.

As a side note, in the sequence

       vpmovm2b zmm2, k1
       vpandd   zmm1, zmm2, zmm1

it should just use something like vmovdqu8 zmm1 k1z, zmm1 to save an instruction.

Configuration

.NET 10.0.100-preview.5.25224.4
Windows 11, x64

Regression?

Not known.

Analysis

Encountered while preparing #115069. Related #72793. Possibly related #76781.

Metadata

Metadata

Assignees

No one assigned

    Labels

    area-CodeGen-coreclrCLR JIT compiler in src/coreclr/src/jit and related components such as SuperPMItenet-performancePerformance related issue

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions