Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 7 additions & 7 deletions src/coreclr/tools/Common/InstructionSetHelpers.cs
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ namespace System.CommandLine
internal static partial class Helpers
{
public static InstructionSetSupport ConfigureInstructionSetSupport(string instructionSet, int maxVectorTBitWidth, bool isVectorTOptimistic, TargetArchitecture targetArchitecture, TargetOS targetOS,
string mustNotBeMessage, string invalidImplicationMessage, Logger logger, bool optimizingForSize, bool isReadyToRun)
string mustNotBeMessage, string invalidImplicationMessage, Logger logger, bool allowOptimistic, bool isReadyToRun)
{
InstructionSetSupportBuilder instructionSetSupportBuilder = new(targetArchitecture);

Expand All @@ -31,7 +31,7 @@ public static InstructionSetSupport ConfigureInstructionSetSupport(string instru

if ((targetArchitecture == TargetArchitecture.X86) || (targetArchitecture == TargetArchitecture.X64))
{
if (isReadyToRun && (targetOS != TargetOS.OSX))
if (isReadyToRun && targetOS != TargetOS.OSX && targetOS != TargetOS.MacCatalyst)
{
// ReadyToRun can presume AVX2, BMI1, BMI2, F16C, FMA, LZCNT, and MOVBE
instructionSetSupportBuilder.AddSupportedInstructionSet("x86-64-v3");
Expand Down Expand Up @@ -67,6 +67,11 @@ public static InstructionSetSupport ConfigureInstructionSetSupport(string instru
instructionSetSupportBuilder.AddSupportedInstructionSet("armv8.2-a");
instructionSetSupportBuilder.AddSupportedInstructionSet("rcpc");
}
else if (targetOS is TargetOS.iOS or TargetOS.iOSSimulator or TargetOS.tvOS or TargetOS.tvOSSimulator)
{
// ReadyToRun on iOS/tvOS can only presume armv8.0-a
instructionSetSupportBuilder.AddSupportedInstructionSet("armv8-a");
}
else
{
// While Unix needs a lower baseline due to things like Raspberry PI
Expand All @@ -87,11 +92,6 @@ public static InstructionSetSupport ConfigureInstructionSetSupport(string instru
}
}

// Whether to allow optimistically expanding the instruction sets beyond what was specified.
// We seed this from optimizingForSize - if we're size-optimizing, we don't want to unnecessarily
// compile both branches of IsSupported checks.
bool allowOptimistic = !optimizingForSize;

bool throttleAvx512 = false;

if (instructionSet == "native")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -57,11 +57,12 @@ public partial class ReadyToRunCompilerContext : CompilerTypeSystemContext
public ReadyToRunCompilerContext(
TargetDetails details,
SharedGenericsMode genericsMode,
bool bubbleIncludesCorelib,
bool bubbleIncludesCoreModule,
InstructionSetSupport instructionSetSupport,
CompilerTypeSystemContext oldTypeSystemContext)
: base(details, genericsMode)
{
BubbleIncludesCoreModule = bubbleIncludesCoreModule;
InstructionSetSupport = instructionSetSupport;
_r2rFieldLayoutAlgorithm = new ReadyToRunMetadataFieldLayoutAlgorithm();
_systemObjectFieldLayoutAlgorithm = new SystemObjectFieldLayoutAlgorithm(_r2rFieldLayoutAlgorithm);
Expand Down Expand Up @@ -94,8 +95,28 @@ public ReadyToRunCompilerContext(
}
}

public bool BubbleIncludesCoreModule { get; }

public InstructionSetSupport InstructionSetSupport { get; }

public bool TargetAllowsRuntimeCodeGeneration
{
get
{
if (Target.OperatingSystem is TargetOS.iOS or TargetOS.iOSSimulator or TargetOS.MacCatalyst or TargetOS.tvOS or TargetOS.tvOSSimulator)
{
return false;
}

if (Target.Architecture is TargetArchitecture.Wasm32)
{
return false;
}

return true;
}
}

public override FieldLayoutAlgorithm GetLayoutAlgorithmForType(DefType type)
{
if (type.IsObject)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.

using System.Collections.Generic;

using Internal.TypeSystem;
using Internal.JitInterface;
using System.Diagnostics;

namespace ILCompiler
{
/// <summary>
/// Root all methods on supported hardware intrinsic classes.
/// </summary>
public class ReadyToRunHardwareIntrinsicRootProvider(ReadyToRunCompilerContext context) : ICompilationRootProvider
{
public void AddCompilationRoots(IRootingServiceProvider rootProvider)
{
InstructionSetSupport specifiedInstructionSet = context.InstructionSetSupport;
TargetArchitecture targetArch = context.Target.Architecture;

// Hardware intrinsics can only live in the system module.
foreach (MetadataType type in context.SystemModule.GetAllTypes())
{
InstructionSet instructionSet = InstructionSetParser.LookupPlatformIntrinsicInstructionSet(targetArch, type);

if (instructionSet == InstructionSet.ILLEGAL)
{
// Not a HardwareIntrinsics type for our platform.
continue;
}

if (specifiedInstructionSet.IsInstructionSetSupported(instructionSet))
{
foreach (MethodDesc method in type.GetMethods())
{
rootProvider.AddCompilationRoot(method, rootMinimalDependencies: false, "Hardware intrinsic method fallback implementation");
}
}
else
{
MethodDesc isSupportedMethod = type.GetMethod("get_IsSupported"u8, new MethodSignature(MethodSignatureFlags.Static, 0, context.GetWellKnownType(WellKnownType.Boolean), []));
if (isSupportedMethod is not null)
{
rootProvider.AddCompilationRoot(isSupportedMethod, rootMinimalDependencies: false, "IsSupported getter for unsupported hardware intrinsic");
}
}
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -189,6 +189,7 @@
<Compile Include="Compiler\Logger.cs" />
<Compile Include="Compiler\ReadyToRunVisibilityRootProvider.cs" />
<Compile Include="Compiler\ReadyToRunProfilingRootProvider.cs" />
<Compile Include="Compiler\ReadyToRunHardwareIntrinsicRootProvider.cs" />
<Compile Include="ObjectWriter\MapFileBuilder.cs" />
<Compile Include="CodeGen\ReadyToRunObjectWriter.cs" />
<Compile Include="Compiler\CompilationModuleGroup.ReadyToRun.cs" />
Expand Down
2 changes: 1 addition & 1 deletion src/coreclr/tools/aot/ILCompiler/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -108,7 +108,7 @@ public int Run()
TargetOS targetOS = Get(_command.TargetOS);
InstructionSetSupport instructionSetSupport = Helpers.ConfigureInstructionSetSupport(Get(_command.InstructionSet), Get(_command.MaxVectorTBitWidth), isVectorTOptimistic, targetArchitecture, targetOS,
"Unrecognized instruction set {0}", "Unsupported combination of instruction sets: {0}/{1}", logger,
optimizingForSize: _command.OptimizationMode == OptimizationMode.PreferSize,
allowOptimistic: _command.OptimizationMode != OptimizationMode.PreferSize,
isReadyToRun: false);

string systemModuleName = Get(_command.SystemModuleName);
Expand Down
22 changes: 21 additions & 1 deletion src/coreclr/tools/aot/crossgen2/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -85,9 +85,19 @@ public int Run()

TargetArchitecture targetArchitecture = Get(_command.TargetArchitecture);
TargetOS targetOS = Get(_command.TargetOS);
bool allowOptimistic = _command.OptimizationMode != OptimizationMode.PreferSize;

if (targetOS is TargetOS.iOS or TargetOS.tvOS or TargetOS.iOSSimulator or TargetOS.tvOSSimulator or TargetOS.MacCatalyst)
{
// These platforms do not support jitted code, so we want to ensure that we don't
// need to fall back to the interpreter for any hardware-intrinsic optimizations.
// Disable optimistic instruction sets by default.
allowOptimistic = false;
}

InstructionSetSupport instructionSetSupport = Helpers.ConfigureInstructionSetSupport(Get(_command.InstructionSet), Get(_command.MaxVectorTBitWidth), isVectorTOptimistic, targetArchitecture, targetOS,
SR.InstructionSetMustNotBe, SR.InstructionSetInvalidImplication, logger,
optimizingForSize: _command.OptimizationMode == OptimizationMode.PreferSize,
allowOptimistic: allowOptimistic,
isReadyToRun: true);
SharedGenericsMode genericsMode = SharedGenericsMode.CanonicalReferenceTypes;
var targetDetails = new TargetDetails(targetArchitecture, targetOS, Crossgen2RootCommand.IsArmel ? TargetAbi.NativeAotArmel : TargetAbi.NativeAot, instructionSetSupport.GetVectorTSimdVector());
Expand Down Expand Up @@ -562,6 +572,16 @@ private void RunSingleCompilation(Dictionary<string, string> inFilePaths, Instru
}
}
}

if (!typeSystemContext.TargetAllowsRuntimeCodeGeneration && typeSystemContext.BubbleIncludesCoreModule)
{
// For some platforms, we cannot JIT.
// As a result, we need to ensure that we have a fallback implementation for all hardware intrinsics
// that are marked as supported.
// Otherwise, the interpreter won't have an implementation it can call for any non-ReadyToRun code.
compilationRoots.Add(new ReadyToRunHardwareIntrinsicRootProvider(typeSystemContext));
}

// In single-file compilation mode, use the assembly's DebuggableAttribute to determine whether to optimize
// or produce debuggable code if an explicit optimization level was not specified on the command line
OptimizationMode optimizationMode = _command.OptimizationMode;
Expand Down
Loading