diff --git a/src/coreclr/tools/Common/Compiler/InstructionSetSupport.cs b/src/coreclr/tools/Common/Compiler/InstructionSetSupport.cs index 2f35f083f24d2ed7a011e899bff602b638962bc7..cab9ca34d5bc71450967b53e788cdea98959c4ec 100644 --- a/src/coreclr/tools/Common/Compiler/InstructionSetSupport.cs +++ b/src/coreclr/tools/Common/Compiler/InstructionSetSupport.cs @@ -191,6 +191,27 @@ public InstructionSetSupportBuilder(TargetArchitecture architecture) /// returns "false" if instruction set isn't valid on this architecture public bool AddSupportedInstructionSet(string instructionSet) { + // First, check if it's a "known cpu family" group of instruction sets e.g. "haswell" + var sets = InstructionSetFlags.CpuNameToInstructionSets(instructionSet, _architecture); + if (sets != null) + { + foreach (string set in sets) + { + if (!s_instructionSetSupport[_architecture].ContainsKey(set)) + { + // Groups can contain other groups + if (AddSupportedInstructionSet(set)) + { + continue; + } + return false; + } + _supportedInstructionSets.Add(set); + _unsupportedInstructionSets.Remove(set); + } + return true; + } + if (!s_instructionSetSupport[_architecture].ContainsKey(instructionSet)) return false; diff --git a/src/coreclr/tools/Common/JitInterface/CorInfoInstructionSet.cs b/src/coreclr/tools/Common/JitInterface/CorInfoInstructionSet.cs index 8e82477d4f2028c05106c541af827af70b35080f..b3c266dc01c7b745d566694601d1bda64ce92f73 100644 --- a/src/coreclr/tools/Common/JitInterface/CorInfoInstructionSet.cs +++ b/src/coreclr/tools/Common/JitInterface/CorInfoInstructionSet.cs @@ -752,6 +752,32 @@ private static InstructionSetFlags ExpandInstructionSetByReverseImplicationHelpe return resultflags; } + private static Dictionary<(string, TargetArchitecture), string> AllInstructionSetGroups { get; } = new() + { + { ("x86-x64", TargetArchitecture.X64), "sse2" }, + { ("x86-x64", TargetArchitecture.X86), "sse2" }, + { ("x86-x64-v2", TargetArchitecture.X64), "sse4.2 popcnt" }, + { ("x86-x64-v2", TargetArchitecture.X86), "sse4.2 popcnt" }, + { ("x86-x64-v3", TargetArchitecture.X64), "x86-x64-v2 avx2 bmi bmi2 lzcnt movbe fma" }, + { ("x86-x64-v3", TargetArchitecture.X86), "x86-x64-v2 avx2 bmi bmi2 lzcnt movbe fma" }, + { ("skylake", TargetArchitecture.X64), "x86-x64-v3" }, + { ("skylake", TargetArchitecture.X86), "x86-x64-v3" }, + { ("armv8-a", TargetArchitecture.ARM64), "neon" }, + { ("armv8.1-a", TargetArchitecture.ARM64), "armv8-a lse crc rdma" }, + { ("armv8.2-a", TargetArchitecture.ARM64), "armv8.1-a" }, + { ("armv8.3-a", TargetArchitecture.ARM64), "armv8.2-a rcpc" }, + { ("armv8.4-a", TargetArchitecture.ARM64), "armv8.3-a dotprod" }, + { ("armv8.5-a", TargetArchitecture.ARM64), "armv8.4-a" }, + { ("armv8.6-a", TargetArchitecture.ARM64), "armv8.5-a" }, + { ("apple-m1", TargetArchitecture.ARM64), "armv8.5-a" }, + }; + + public static IEnumerable AllCpuNames => + AllInstructionSetGroups.Keys.Select(key => key.Item1).Distinct(); + + public static IEnumerable CpuNameToInstructionSets(string cpu, TargetArchitecture arch) => + AllInstructionSetGroups.TryGetValue((cpu, arch), out string value) ? value.Split(' ') : null; + public struct InstructionSetInfo { public readonly string Name; diff --git a/src/coreclr/tools/Common/JitInterface/ThunkGenerator/InstructionSetDesc.txt b/src/coreclr/tools/Common/JitInterface/ThunkGenerator/InstructionSetDesc.txt index bab454dd4dbe34dd605e0231403b0c739e6fa626..327d4b7140b8be34b1887bec1a266d164ad03c82 100644 --- a/src/coreclr/tools/Common/JitInterface/ThunkGenerator/InstructionSetDesc.txt +++ b/src/coreclr/tools/Common/JitInterface/ThunkGenerator/InstructionSetDesc.txt @@ -134,3 +134,22 @@ implication ,ARM64 ,Sha1 ,ArmBase implication ,ARM64 ,Sha256 ,ArmBase implication ,ARM64 ,Vector64 ,AdvSimd implication ,ARM64 ,Vector128 ,AdvSimd + + +; ,name and aliases ,archs ,lower baselines included by implication +; +instructionsetgroup ,x86-x64 ,X64 X86 ,sse2 +instructionsetgroup ,x86-x64-v2 ,X64 X86 ,sse4.2 popcnt +instructionsetgroup ,x86-x64-v3 ,X64 X86 ,x86-x64-v2 avx2 bmi bmi2 lzcnt movbe fma +instructionsetgroup ,skylake ,X64 X86 ,x86-x64-v3 + +instructionsetgroup ,armv8-a ,ARM64 ,neon +instructionsetgroup ,armv8.1-a ,ARM64 ,armv8-a lse crc rdma +instructionsetgroup ,armv8.2-a ,ARM64 ,armv8.1-a +instructionsetgroup ,armv8.3-a ,ARM64 ,armv8.2-a rcpc +instructionsetgroup ,armv8.4-a ,ARM64 ,armv8.3-a dotprod +instructionsetgroup ,armv8.5-a ,ARM64 ,armv8.4-a +instructionsetgroup ,armv8.6-a ,ARM64 ,armv8.5-a + +; Technically, apple-m1 is v8.5+ +instructionsetgroup ,apple-m1 ,ARM64 ,armv8.5-a diff --git a/src/coreclr/tools/Common/JitInterface/ThunkGenerator/InstructionSetGenerator.cs b/src/coreclr/tools/Common/JitInterface/ThunkGenerator/InstructionSetGenerator.cs index 5152a6ebde1103fa87467de27024e2bacbae2a4d..d8c6042fd0d96ad79cc66f08badc5087ce2a65a8 100644 --- a/src/coreclr/tools/Common/JitInterface/ThunkGenerator/InstructionSetGenerator.cs +++ b/src/coreclr/tools/Common/JitInterface/ThunkGenerator/InstructionSetGenerator.cs @@ -58,6 +58,8 @@ public string PublicName } } + record InstructionSetGroup(string Names, string Archs, string Sets); + class InstructionSetImplication { public string Architecture { get; } @@ -81,6 +83,7 @@ public InstructionSetImplication(string architecture, InstructionSetImplication List _instructionSets = new List(); List _implications = new List(); + List _instructionSetsGroups = new List(); Dictionary> _64bitVariants = new Dictionary>(); SortedDictionary _r2rNamesByName = new SortedDictionary(); SortedDictionary _r2rNamesByNumber = new SortedDictionary(); @@ -184,6 +187,11 @@ public bool ParseInput(TextReader tr) ValidateArchitectureEncountered(command[1]); _implications.Add(new InstructionSetImplication(command[1],command[2], command[3])); break; + case "instructionsetgroup": + if (command.Length != 4) + throw new Exception("Incorrect number of args for instructionsetgroup"); + _instructionSetsGroups.Add(new InstructionSetGroup(command[1], command[2], command[3])); + break; case "copyinstructionsets": if (command.Length != 3) throw new Exception("Incorrect number of args for instructionset"); @@ -605,6 +613,28 @@ private static InstructionSetFlags ExpandInstructionSetByReverseImplicationHelpe return resultflags; } + private static Dictionary<(string, TargetArchitecture), string> AllInstructionSetGroups { get; } = new() + { +"); + foreach (InstructionSetGroup group in _instructionSetsGroups) + { + foreach (string name in group.Names.Split(' ')) + { + foreach (string arch in group.Archs.Split(' ')) + { + string key = $"\"{name}\",".PadRight(13, ' ') + $" TargetArchitecture.{arch}),".PadRight(27, ' '); + tr.WriteLine($" {{ ({key} \"{group.Sets}\" }},"); + } + } + } + tr.Write(@" }; + + public static IEnumerable AllCpuNames => + AllInstructionSetGroups.Keys.Select(key => key.Item1).Distinct(); + + public static IEnumerable CpuNameToInstructionSets(string cpu, TargetArchitecture arch) => + AllInstructionSetGroups.TryGetValue((cpu, arch), out string value) ? value.Split(' ') : null; + public struct InstructionSetInfo { public readonly string Name; diff --git a/src/coreclr/tools/aot/ILCompiler/Program.cs b/src/coreclr/tools/aot/ILCompiler/Program.cs index eb3643851fd50af7b2726cdf9a073a0268c93941..115ca29863cd283d67e47211aa4a0e13aefc8778 100644 --- a/src/coreclr/tools/aot/ILCompiler/Program.cs +++ b/src/coreclr/tools/aot/ILCompiler/Program.cs @@ -305,6 +305,10 @@ private ArgumentSyntax ParseCommandLine(string[] args) extraHelp.Add(archString.ToString()); } + extraHelp.Add(""); + extraHelp.Add("The following CPU names are predefined groups of instruction sets and can be used in --instruction-set too:"); + extraHelp.Add(string.Join(", ", Internal.JitInterface.InstructionSetFlags.AllCpuNames)); + argSyntax.ExtraHelpParagraphs = extraHelp; } @@ -438,7 +442,15 @@ private int Run(string[] args) } else if (_targetArchitecture == TargetArchitecture.ARM64) { - instructionSetSupportBuilder.AddSupportedInstructionSet("neon"); // Lower baselines included by implication + if (_targetOS == TargetOS.OSX) + { + // For osx-arm64 we know that apple-m1 is a baseline + instructionSetSupportBuilder.AddSupportedInstructionSet("apple-m1"); + } + else + { + instructionSetSupportBuilder.AddSupportedInstructionSet("neon"); // Lower baselines included by implication + } } if (_instructionSet != null) diff --git a/src/coreclr/tools/aot/crossgen2/CommandLineOptions.cs b/src/coreclr/tools/aot/crossgen2/CommandLineOptions.cs index ceefe4d1705d6e6b5bb8569e9b7e0c8c0f3006a2..86a5340faa89f5df1a4aae8432b62ffd52018b36 100644 --- a/src/coreclr/tools/aot/crossgen2/CommandLineOptions.cs +++ b/src/coreclr/tools/aot/crossgen2/CommandLineOptions.cs @@ -241,6 +241,10 @@ public CommandLineOptions(string[] args) extraHelp.Add(archString.ToString()); } + extraHelp.Add(""); + extraHelp.Add(SR.CpuFamilies); + extraHelp.Add(string.Join(", ", Internal.JitInterface.InstructionSetFlags.AllCpuNames)); + argSyntax.ExtraHelpParagraphs = extraHelp; HelpText = argSyntax.GetHelpText(); diff --git a/src/coreclr/tools/aot/crossgen2/Program.cs b/src/coreclr/tools/aot/crossgen2/Program.cs index de6370cc5066e2a6f780e194633348828fc83a6c..81bdb61ae09ef4a4e291ce917c2dc90fb6ab5153 100644 --- a/src/coreclr/tools/aot/crossgen2/Program.cs +++ b/src/coreclr/tools/aot/crossgen2/Program.cs @@ -20,6 +20,7 @@ using ILCompiler.Reflection.ReadyToRun; using ILCompiler.DependencyAnalysis; using ILCompiler.IBC; +using System.Diagnostics; namespace ILCompiler { @@ -245,10 +246,17 @@ private InstructionSetSupport ConfigureInstructionSetSupport() } else if (_targetArchitecture == TargetArchitecture.ARM64) { - instructionSetSupportBuilder.AddSupportedInstructionSet("neon"); // Lower baselines included by implication + if (_targetOS == TargetOS.OSX) + { + // For osx-arm64 we know that apple-m1 is a baseline + instructionSetSupportBuilder.AddSupportedInstructionSet("apple-m1"); + } + else + { + instructionSetSupportBuilder.AddSupportedInstructionSet("neon"); // Lower baselines included by implication + } } - if (_commandLineOptions.InstructionSet != null) { List instructionSetParams = new List(); diff --git a/src/coreclr/tools/aot/crossgen2/Properties/Resources.resx b/src/coreclr/tools/aot/crossgen2/Properties/Resources.resx index 929181a75bebbb2f065aa0d84aeb8c66bfaaa06e..37720091236db06051c71eba551c07ff3f6613db 100644 --- a/src/coreclr/tools/aot/crossgen2/Properties/Resources.resx +++ b/src/coreclr/tools/aot/crossgen2/Properties/Resources.resx @@ -387,4 +387,7 @@ "{0}" was specified to the --non-local-generics-module switch, but was not in the set of modules associated with the compile + + The following CPU names are predefined groups of instruction sets and can be used in --instruction-set too: + \ No newline at end of file