dotnet / runtime

.NET is a cross-platform runtime for cloud, mobile, desktop, and IoT apps.
https://docs.microsoft.com/dotnet/core/
MIT License
15.25k stars 4.73k forks source link

Recognize Shift(vec, vec(8)) and replace with Shift(vec, 8) #99009

Open hypeartist opened 8 months ago

hypeartist commented 8 months ago
    public static Vector<uint> Method(Vector<uint> v)
    {
        return Method<Struct>(v);
    }

    public static Vector<uint> Method<TStruct>(Vector<uint> v) where TStruct : IInterface
    {
        return v << TStruct.Shift;
    }

    public interface IInterface
    {
        public static abstract int Shift { get; }
    }

    public struct Struct : IInterface
    {
        public static int Shift => 8;
    }

Actual codegen:

C.Method(System.Numerics.Vector`1<UInt32>)
    L0000: vzeroupper
    L0003: vmovups ymm0, [rdx]
    L0007: mov eax, 8
    L000c: vmovd xmm1, eax
    L0010: vpslld ymm0, ymm0, xmm1
    L0014: vmovups [rcx], ymm0
    L0018: mov rax, rcx
    L001b: vzeroupper
    L001e: ret

Expected codegen:

C.Method(System.Numerics.Vector`1<UInt32>)
    L0000: vzeroupper
    L0003: vmovups ymm0, [rdx]
    L0007: vpslld ymm0, ymm0, 8
    L000c: vmovups [rcx], ymm0
    L0010: mov rax, rcx
    L0013: vzeroupper
    L0016: ret
ghost commented 8 months ago

Tagging subscribers to this area: @JulieLeeMSFT, @jakobbotsch See info in area-owners.md if you want to be subscribed.

Issue Details
```csharp public static Vector Method(Vector v) { return Method(v); } public static Vector Method(Vector v) where TStruct : IInterface { return v << TStruct.Shift; } public interface IInterface { public static abstract int Shift { get; } } public struct Struct : IInterface { public static int Shift => 8; } ``` Actual codegen: ```asm C.Method(System.Numerics.Vector`1) L0000: vzeroupper L0003: vmovups ymm0, [rdx] L0007: mov eax, 8 L000c: vmovd xmm1, eax L0010: vpslld ymm0, ymm0, xmm1 L0014: vmovups [rcx], ymm0 L0018: mov rax, rcx L001b: vzeroupper L001e: ret ``` Expected codegen: ```asm C.Method(System.Numerics.Vector`1) L0000: vzeroupper L0003: vmovups ymm0, [rdx] L0007: vpslld ymm0, ymm0, 8 L000c: vmovups [rcx], ymm0 L0010: mov rax, rcx L0013: vzeroupper L0016: ret ```
Author: hypeartist
Assignees: -
Labels: `area-CodeGen-coreclr`, `untriaged`
Milestone: -
colejohnson66 commented 8 months ago

Hardcoded constants work fine, but static getters don't.

class Test
{
    static Vector<uint> Method(Vector<uint> v)
    {
        return v << 8;
    }

    [JitGeneric(typeof(Struct))]
    static Vector<uint> Method<TStruct>(Vector<uint> v) where TStruct : IInterface
    {
        return v << TStruct.Shift;
    }
}
Test.Method(System.Numerics.Vector`1<UInt32>)
    L0000: vzeroupper
    L0003: vmovups ymm0, [rdx]
    L0007: vpslld ymm0, ymm0, 8
    L000c: vmovups [rcx], ymm0
    L0010: mov rax, rcx
    L0013: vzeroupper
    L0016: ret

Test.Method[[Struct, _]](System.Numerics.Vector`1<UInt32>)
    L0000: vzeroupper
    L0003: vmovups ymm0, [rdx]
    L0007: mov eax, 8
    L000c: vmovd xmm1, eax
    L0010: vpslld ymm0, ymm0, xmm1
    L0014: vmovups [rcx], ymm0
    L0018: mov rax, rcx
    L001b: vzeroupper
    L001e: ret