Skip to content

Commit

Permalink
Enable detection of HW intrinsics (dotnet#6836)
Browse files Browse the repository at this point in the history
I took the liberty of marking the types containing the hardware intrinsics as [Intrinsic] to avoid doing a name check on everything in the system module. It feels like we should take advantage of this attribute in CoreCLR too.

This doesn't actually enable the support because RyuJIT unconditionally disables HW intrinsics for prejit (both CoreRT and CPAOT are considered prejit). We might want to do something about this on the RyuJIT side to address that (for CPAOT, to be able to pregenerate best code possible ahead of time, assuming a fixed ISA; and for CoreRT without JIT, where the concerns about AVX-SSE penalty don't apply). See conversation in dotnet/coreclr#21603
  • Loading branch information
MichalStrehovsky authored Jan 18, 2019
1 parent 055edb5 commit 3e5f5ec
Show file tree
Hide file tree
Showing 31 changed files with 156 additions and 5 deletions.
62 changes: 62 additions & 0 deletions src/ILCompiler.Compiler/src/Compiler/HardwareIntrinsicHelpers.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.

using System;

using Internal.TypeSystem;
using Internal.IL;
using Internal.IL.Stubs;

namespace ILCompiler
{
public static class HardwareIntrinsicHelpers
{
public static bool IsHardwareIntrinsic(MethodDesc method)
{
TypeDesc owningType = method.OwningType;

if (owningType.IsIntrinsic && owningType is MetadataType mdType)
{
TargetArchitecture targetArch = owningType.Context.Target.Architecture;

if (targetArch == TargetArchitecture.X64 || targetArch == TargetArchitecture.X86)
{
mdType = (MetadataType)mdType.ContainingType ?? mdType;
if (mdType.Namespace == "System.Runtime.Intrinsics.X86")
return true;
}
else if (targetArch == TargetArchitecture.ARM64)
{
if (mdType.Namespace == "System.Runtime.Intrinsics.Arm.Arm64")
return true;
}
}

return false;
}

public static MethodIL GetUnsupportedImplementationIL(MethodDesc method)
{
if (method.Name == "get_IsSupported")
{
return new ILStubMethodIL(method,
new byte[] {
(byte)ILOpcode.ldc_i4_0,
(byte)ILOpcode.ret
},
Array.Empty<LocalVariableDefinition>(), null);
}

MethodDesc throwPnse = method.Context.GetHelperEntryPoint("ThrowHelpers", "ThrowPlatformNotSupportedException");

return new ILStubMethodIL(method,
new byte[] {
(byte)ILOpcode.call, 1, 0, 0, 0,
(byte)ILOpcode.br_s, unchecked((byte)-7),
},
Array.Empty<LocalVariableDefinition>(),
new object[] { throwPnse });
}
}
}
1 change: 1 addition & 0 deletions src/ILCompiler.Compiler/src/ILCompiler.Compiler.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -134,6 +134,7 @@
<Compile Include="Compiler\DependencyAnalysis\ImportedNodeProvider.cs" />
<Compile Include="Compiler\FrameworkStringResourceBlockingPolicy.cs" />
<Compile Include="Compiler\GeneratingMetadataManager.cs" />
<Compile Include="Compiler\HardwareIntrinsicHelpers.cs" />
<Compile Include="Compiler\InternalCompilerErrorException.cs" />
<Compile Include="Compiler\ManifestResourceBlockingPolicy.cs" />
<Compile Include="Compiler\NoManifestResourceBlockingPolicy.cs" />
Expand Down
3 changes: 3 additions & 0 deletions src/ILCompiler.CppCodeGen/src/CppCodeGen/CppWriter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -658,6 +658,9 @@ public void CompileMethod(CppMethodCodeNode methodCodeNodeNeedingCode)
if (methodIL == null)
return;

if (HardwareIntrinsicHelpers.IsHardwareIntrinsic(method))
methodIL = HardwareIntrinsicHelpers.GetUnsupportedImplementationIL(method);

try
{
var ilImporter = new ILImporter(_compilation, this, method, methodIL);
Expand Down
6 changes: 5 additions & 1 deletion src/JitInterface/src/CorInfoImpl.cs
Original file line number Diff line number Diff line change
Expand Up @@ -642,7 +642,11 @@ private uint getMethodAttribsInternal(MethodDesc method)
// RyuJIT special cases this method; it would assert if it's not final
// and we might not have set the bit in the code above.
result |= CorInfoFlag.CORINFO_FLG_FINAL;
}
}

// Check for hardware intrinsics
if (HardwareIntrinsicHelpers.IsHardwareIntrinsic(method))
result |= CorInfoFlag.CORINFO_FLG_JIT_INTRINSIC;

result |= CorInfoFlag.CORINFO_FLG_NOSECURITYWRAP;

Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.

using System.Runtime.CompilerServices;
using System.Runtime.Intrinsics;

Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.

using System.Runtime.CompilerServices;
using System.Runtime.Intrinsics;

Expand All @@ -9,6 +13,7 @@ namespace System.Runtime.Intrinsics.Arm.Arm64
/// Arm64 CPU indicate support for this feature by setting
/// ID_AA64ISAR0_EL1.AES is 1 or better
/// </summary>
[Intrinsic]
[CLSCompliant(false)]
public static class Aes
{
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.

using System.Runtime.CompilerServices;
using System.Runtime.Intrinsics;


namespace System.Runtime.Intrinsics.Arm.Arm64
{
/// <summary>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,14 +1,18 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.

using System.Runtime.CompilerServices;
using System.Runtime.Intrinsics;


namespace System.Runtime.Intrinsics.Arm.Arm64
{
/// <summary>
/// This class provides access to the Arm64 Base intrinsics
///
/// These intrinsics are supported by all Arm64 CPUs
/// </summary>
[Intrinsic]
[CLSCompliant(false)]
public static class Base
{
Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.

using System.Runtime.CompilerServices;
using System.Runtime.Intrinsics;

Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.

using System.Runtime.CompilerServices;
using System.Runtime.Intrinsics;

Expand All @@ -9,6 +13,7 @@ namespace System.Runtime.Intrinsics.Arm.Arm64
/// Arm64 CPU indicate support for this feature by setting
/// ID_AA64ISAR0_EL1.SHA1 is 1 or better
/// </summary>
[Intrinsic]
[CLSCompliant(false)]
public static class Sha1
{
Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.

using System.Runtime.CompilerServices;
using System.Runtime.Intrinsics;

Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.

using System.Runtime.CompilerServices;
using System.Runtime.Intrinsics;

Expand All @@ -9,6 +13,7 @@ namespace System.Runtime.Intrinsics.Arm.Arm64
/// Arm64 CPU indicate support for this feature by setting
/// ID_AA64ISAR0_EL1.SHA2 is 1 or better
/// </summary>
[Intrinsic]
[CLSCompliant(false)]
public static class Sha256
{
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.

using System.Runtime.CompilerServices;
using System.Runtime.Intrinsics;


namespace System.Runtime.Intrinsics.Arm.Arm64
{
/// <summary>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.

using System.Runtime.CompilerServices;
using System.Runtime.Intrinsics;


namespace System.Runtime.Intrinsics.Arm.Arm64
{
/// <summary>
Expand All @@ -10,6 +13,7 @@ namespace System.Runtime.Intrinsics.Arm.Arm64
/// Arm64 CPU indicate support for this feature by setting
/// ID_AA64PFR0_EL1.AdvSIMD == 0 or better.
/// </summary>
[Intrinsic]
[CLSCompliant(false)]
public static class Simd
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,15 @@
// See the LICENSE file in the project root for more information.

using System;
using System.Runtime.CompilerServices;
using System.Runtime.Intrinsics;

namespace System.Runtime.Intrinsics.X86
{
/// <summary>
/// This class provides access to Intel AES hardware instructions via intrinsics
/// </summary>
[Intrinsic]
[CLSCompliant(false)]
public abstract class Aes : Sse2
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
// See the LICENSE file in the project root for more information.

using System;
using System.Runtime.CompilerServices;
using System.Runtime.Intrinsics;
using Internal.Runtime.CompilerServices;

Expand All @@ -11,6 +12,7 @@ namespace System.Runtime.Intrinsics.X86
/// <summary>
/// This class provides access to Intel AVX hardware instructions via intrinsics
/// </summary>
[Intrinsic]
[CLSCompliant(false)]
public abstract class Avx : Sse42
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,15 @@
// See the LICENSE file in the project root for more information.

using System;
using System.Runtime.CompilerServices;
using System.Runtime.Intrinsics;

namespace System.Runtime.Intrinsics.X86
{
/// <summary>
/// This class provides access to Intel AVX2 hardware instructions via intrinsics
/// </summary>
[Intrinsic]
[CLSCompliant(false)]
public abstract class Avx2 : Avx
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,20 +3,23 @@
// See the LICENSE file in the project root for more information.

using System;
using System.Runtime.CompilerServices;
using System.Runtime.Intrinsics;

namespace System.Runtime.Intrinsics.X86
{
/// <summary>
/// This class provides access to Intel BMI1 hardware instructions via intrinsics
/// </summary>
[Intrinsic]
[CLSCompliant(false)]
public abstract class Bmi1
{
internal Bmi1() { }

public static bool IsSupported { get => IsSupported; }

[Intrinsic]
public abstract class X64
{
internal X64() { }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,20 +3,23 @@
// See the LICENSE file in the project root for more information.

using System;
using System.Runtime.CompilerServices;
using System.Runtime.Intrinsics;

namespace System.Runtime.Intrinsics.X86
{
/// <summary>
/// This class provides access to Intel BMI2 hardware instructions via intrinsics
/// </summary>
[Intrinsic]
[CLSCompliant(false)]
public abstract class Bmi2
{
internal Bmi2() { }

public static bool IsSupported { get => IsSupported; }

[Intrinsic]
public abstract class X64
{
internal X64() { }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,15 @@
// See the LICENSE file in the project root for more information.

using System;
using System.Runtime.CompilerServices;
using System.Runtime.Intrinsics;

namespace System.Runtime.Intrinsics.X86
{
/// <summary>
/// This class provides access to Intel FMA hardware instructions via intrinsics
/// </summary>
[Intrinsic]
[CLSCompliant(false)]
public abstract class Fma : Avx
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,20 +3,23 @@
// See the LICENSE file in the project root for more information.

using System;
using System.Runtime.CompilerServices;
using System.Runtime.Intrinsics;

namespace System.Runtime.Intrinsics.X86
{
/// <summary>
/// This class provides access to Intel LZCNT hardware instructions via intrinsics
/// </summary>
[Intrinsic]
[CLSCompliant(false)]
public abstract class Lzcnt
{
internal Lzcnt() { }

public static bool IsSupported { get => IsSupported; }

[Intrinsic]
public abstract class X64
{
internal X64() { }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,15 @@
// See the LICENSE file in the project root for more information.

using System;
using System.Runtime.CompilerServices;
using System.Runtime.Intrinsics;

namespace System.Runtime.Intrinsics.X86
{
/// <summary>
/// This class provides access to Intel PCLMULQDQ hardware instructions via intrinsics
/// </summary>
[Intrinsic]
[CLSCompliant(false)]
public abstract class Pclmulqdq : Sse2
{
Expand Down
Loading

0 comments on commit 3e5f5ec

Please sign in to comment.