Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Avx512 convert opt #3

Open
wants to merge 5 commits into
base: avx512-RR
Choose a base branch
from
Open

Avx512 convert opt #3

wants to merge 5 commits into from

Conversation

anthonycanino
Copy link
Owner

Overview

This PR demonstrates a few things which I think are useful for learnings (and optimize several cases below that ARM typically had optimized and beat us in micros):

  1. The creation of a table driven intrinsic, e.g., NI_AVX512DQ_VL_ConvertToDouble128, which allows to map a lowering between a method (though in this case, there are no frontend APIs added) and an argument type (for example, Vector128<long>) to a specific hardware instruction vcvtps2udq.

  2. The mapping of a vector method to a named intrinsic, for example, Vector128.ConvertToDouble(Vector128<ulong> v) to NI_AVX512DQ_VL_ConvertToDouble128.

  3. The mapping of a variable length vector method to a named intrinsic, for example Vector.ConvertToDouble(Vector<ulong> v) to NI_AVX512DQ_VL_ConvertToDouble128.

  4. The addition of several new AVX512 instructions to the instruction tables.

Not all intrinsics must map to a single instruction --- several will actually lower to a series of instructions, which we'd probably call it "codegen" versus a hardware intrinsic, though those terms are loosely defined.

Optimized Cases

Cases that have been optimized to use one of the single AVX512VL instructions...

        // -----------------------------------------
	// Cases are Vector long => double, ulong => double
	// -----------------------------------------

	// VCVTUQQ2PD
	[MethodImpl(MethodImplOptions.NoInlining)]
	public static Vector128<double> VLongToDouble(long i)
	{
		Vector128<long> v1 = Vector128.Create(i);
		return Vector128.ConvertToDouble(v1);
	}

	// VCVTQQ2PD
	[MethodImpl(MethodImplOptions.NoInlining)]
	public static Vector128<double> VUlongToDouble(ulong i)
	{
		Vector128<ulong> v1 = Vector128.Create(i);
		return Vector128.ConvertToDouble(v1);
	}

	// VCVTUQQ2PD
	[MethodImpl(MethodImplOptions.NoInlining)]
	public static Vector<double> VLongToDoubleVT(long i)
	{
		Vector<long> v1 = new Vector<long>(i);
		return Vector.ConvertToDouble(v1);
	}

	// VCVTQQ2PD
	[MethodImpl(MethodImplOptions.NoInlining)]
	public static Vector<double> VUlongToDoubleVT(ulong i)
	{
		Vector<ulong> v1 = new Vector<ulong>(i);
		return Vector.ConvertToDouble(v1);
	}

	// -----------------------------------------
	// Cases are Vector double => long
	// -----------------------------------------

	[MethodImpl(MethodImplOptions.NoInlining)]
	public static Vector128<long> VDoubleToLong(double i)
	{
		Vector128<double> v1 = Vector128.Create(i);
		return Vector128.ConvertToInt64(v1);
	}

	// VCVTUQQ2PD
	[MethodImpl(MethodImplOptions.NoInlining)]
	public static Vector<long> VDoubleToLongVT(double i)
	{
		Vector<double> v1 = new Vector<double>(i);
		return Vector.ConvertToInt64(v1);
	}

	// -----------------------------------------
	// Cases are Vector double => ulong
	// -----------------------------------------

	[MethodImpl(MethodImplOptions.NoInlining)]
	public static Vector128<ulong> VDoubleToUlong(double i)
	{
		Vector128<double> v1 = Vector128.Create(i);
		return Vector128.ConvertToUInt64(v1);
	}

	// VCVTUQQ2PD
	[MethodImpl(MethodImplOptions.NoInlining)]
	public static Vector<ulong> VDoubleToUlongVT(double i)
	{
		Vector<double> v1 = new Vector<double>(i);
		return Vector.ConvertToUInt64(v1);
	}

	// -----------------------------------------
	// Cases are Vector float => uint
	// -----------------------------------------

	[MethodImpl(MethodImplOptions.NoInlining)]
	public static Vector128<uint> VFloatToUint(float i)
	{
		Vector128<float> v1 = Vector128.Create(i);
		return Vector128.ConvertToUInt32(v1);
	}

	[MethodImpl(MethodImplOptions.NoInlining)]
	public static Vector<uint> VFloatToUintVT(float i)
	{
		Vector<float> v1 = new Vector<float>(i);
		return Vector.ConvertToUInt32(v1);
	}

	[MethodImpl(MethodImplOptions.NoInlining)]
	public static Vector128<float> VUintToFloat(uint i)
	{
		Vector128<uint> v1 = Vector128.Create(i);
		return Vector128.ConvertToSingle(v1);
	}

	[MethodImpl(MethodImplOptions.NoInlining)]
	public static Vector<float> VUintToFloatVT(uint i)
	{
		Vector<uint> v1 = new Vector<uint>(i);
		return Vector.ConvertToSingle(v1);
	}

anthonycanino pushed a commit that referenced this pull request Jul 6, 2023
…tnet#87189)

This fixes a startup crash on Big Sur:

> error: * Assertion at /Users/runner/work/1/s/src/mono/mono/utils/mono-hwcap-arm64.c:35, condition `res == 0' not met

Because sysctl can't find some of these options:

    $ sysctl hw.optional.armv8_crc32
    hw.optional.armv8_crc32: 1
    $ sysctl hw.optional.arm.FEAT_RDM
    sysctl: unknown oid 'hw.optional.arm.FEAT_RDM'
    $ sysctl hw.optional.arm.FEAT_DotProd
    sysctl: unknown oid 'hw.optional.arm.FEAT_DotProd'
    $ sysctl hw.optional.arm.FEAT_SHA1
    sysctl: unknown oid 'hw.optional.arm.FEAT_SHA1'
    $ sysctl hw.optional.arm.FEAT_SHA256
    sysctl: unknown oid 'hw.optional.arm.FEAT_SHA256'
    $ sysctl hw.optional.arm.FEAT_AES
    sysctl: unknown oid 'hw.optional.arm.FEAT_AES'

Full stack trace:

* thread #1, queue = 'com.apple.main-thread', stop reason = breakpoint 2.1
  * frame #0: 0x0000010ef37560 libmonosgen-2.0.dylib`monoeg_assertion_message
    frame #1: 0x0000010ef375cc libmonosgen-2.0.dylib`mono_assertion_message + 32
    frame #2: 0x0000010ef40d6c libmonosgen-2.0.dylib`mono_hwcap_arch_init + 544
    frame #3: 0x0000010ef54bd8 libmonosgen-2.0.dylib`mono_hwcap_init + 72
    frame #4: 0x0000010ee14dc0 libmonosgen-2.0.dylib`parse_optimizations + 52
    frame #5: 0x0000010edbed48 libmonosgen-2.0.dylib`mono_init
    frame #6: 0x0000010ee18968 libmonosgen-2.0.dylib`mono_jit_init_version
    frame #7: 0x0000010f48a300 libxamarin-dotnet-debug.dylib`xamarin_bridge_initialize + 216
    frame #8: 0x0000010f4900a4 libxamarin-dotnet-debug.dylib`xamarin_main + 376
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

1 participant