Add predefined cpu names for --instruction-set (e.g. haswell) (#71911)
authorEgor Bogatov <egorbo@gmail.com>
Wed, 13 Jul 2022 00:52:03 +0000 (02:52 +0200)
committerGitHub <noreply@github.com>
Wed, 13 Jul 2022 00:52:03 +0000 (02:52 +0200)
src/coreclr/tools/Common/Compiler/InstructionSetSupport.cs
src/coreclr/tools/Common/JitInterface/CorInfoInstructionSet.cs
src/coreclr/tools/Common/JitInterface/ThunkGenerator/InstructionSetDesc.txt
src/coreclr/tools/Common/JitInterface/ThunkGenerator/InstructionSetGenerator.cs
src/coreclr/tools/aot/ILCompiler/Program.cs
src/coreclr/tools/aot/crossgen2/CommandLineOptions.cs
src/coreclr/tools/aot/crossgen2/Program.cs
src/coreclr/tools/aot/crossgen2/Properties/Resources.resx

index 2f35f08..cab9ca3 100644 (file)
@@ -191,6 +191,27 @@ namespace ILCompiler
         /// <returns>returns "false" if instruction set isn't valid on this architecture</returns>
         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;
 
index 8e82477..b3c266d 100644 (file)
@@ -752,6 +752,32 @@ namespace Internal.JitInterface
             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<string> AllCpuNames =>
+            AllInstructionSetGroups.Keys.Select(key => key.Item1).Distinct();
+
+        public static IEnumerable<string> CpuNameToInstructionSets(string cpu, TargetArchitecture arch) =>
+            AllInstructionSetGroups.TryGetValue((cpu, arch), out string value) ? value.Split(' ') : null;
+
         public struct InstructionSetInfo
         {
             public readonly string Name;
index bab454d..327d4b7 100644 (file)
@@ -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
index 5152a6e..d8c6042 100644 (file)
@@ -58,6 +58,8 @@ namespace Thunkerator
             }
         }
 
+        record InstructionSetGroup(string Names, string Archs, string Sets);
+
         class InstructionSetImplication
         {
             public string Architecture { get; }
@@ -81,6 +83,7 @@ namespace Thunkerator
 
         List<InstructionSetInfo> _instructionSets = new List<InstructionSetInfo>();
         List<InstructionSetImplication> _implications = new List<InstructionSetImplication>();
+        List<InstructionSetGroup> _instructionSetsGroups = new List<InstructionSetGroup>();
         Dictionary<string, HashSet<string>> _64bitVariants = new Dictionary<string, HashSet<string>>();
         SortedDictionary<string,int> _r2rNamesByName = new SortedDictionary<string,int>();
         SortedDictionary<int,string> _r2rNamesByNumber = new SortedDictionary<int,string>();
@@ -184,6 +187,11 @@ namespace Thunkerator
                             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 @@ namespace Internal.JitInterface
             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<string> AllCpuNames =>
+            AllInstructionSetGroups.Keys.Select(key => key.Item1).Distinct();
+
+        public static IEnumerable<string> CpuNameToInstructionSets(string cpu, TargetArchitecture arch) =>
+            AllInstructionSetGroups.TryGetValue((cpu, arch), out string value) ? value.Split(' ') : null;
+
         public struct InstructionSetInfo
         {
             public readonly string Name;
index eb36438..115ca29 100644 (file)
@@ -305,6 +305,10 @@ namespace ILCompiler
                     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 @@ namespace ILCompiler
             }
             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)
index ceefe4d..86a5340 100644 (file)
@@ -241,6 +241,10 @@ namespace ILCompiler
                     extraHelp.Add(archString.ToString());
                 }
 
+                extraHelp.Add("");
+                extraHelp.Add(SR.CpuFamilies);
+                extraHelp.Add(string.Join(", ", Internal.JitInterface.InstructionSetFlags.AllCpuNames));
+
                 argSyntax.ExtraHelpParagraphs = extraHelp;
 
                 HelpText = argSyntax.GetHelpText();
index de6370c..81bdb61 100644 (file)
@@ -20,6 +20,7 @@ using Internal.TypeSystem.Ecma;
 using ILCompiler.Reflection.ReadyToRun;
 using ILCompiler.DependencyAnalysis;
 using ILCompiler.IBC;
+using System.Diagnostics;
 
 namespace ILCompiler
 {
@@ -245,10 +246,17 @@ namespace ILCompiler
             }
             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<string> instructionSetParams = new List<string>();
index 929181a..3772009 100644 (file)
   <data name="ErrorNonLocalGenericsModule" xml:space="preserve">
     <value>"{0}" was specified to the --non-local-generics-module switch, but was not in the set of modules associated with the compile</value>
   </data>
+  <data name="CpuFamilies" xml:space="preserve">
+    <value>The following CPU names are predefined groups of instruction sets and can be used in --instruction-set too:</value>
+  </data>
 </root>
\ No newline at end of file