Skip to content
Merged
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
18 changes: 9 additions & 9 deletions .github/workflows/cicd.yml
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ jobs:
- name: Setup dotnet
uses: actions/setup-dotnet@v3
with:
dotnet-version: '8.0.x'
dotnet-version: '10.0.x'
dotnet-quality: 'preview'
- name: Ask Github to please let us use the package registry
run: |
Expand Down Expand Up @@ -73,42 +73,42 @@ jobs:
tar -C layouts/linux-glibc-arm64/ -czvf layouts/linux-glibc-arm64.tar.gz .
tar -C layouts/obj/linux-glibc-arm64/ -czvf layouts/linux-glibc-arm64-symbols.tar.gz bflat.dwo
- name: Archive windows-x64 hosted compiler
uses: actions/upload-artifact@v2
uses: actions/upload-artifact@v4
with:
name: bflat-windows-x64.zip
path: layouts/windows-x64.zip
- name: Archive windows-x64 hosted compiler symbols
uses: actions/upload-artifact@v2
uses: actions/upload-artifact@v4
with:
name: debugsymbols-bflat-windows-x64.zip
path: layouts/windows-x64-symbols.zip
- name: Archive windows-arm64 hosted compiler
uses: actions/upload-artifact@v2
uses: actions/upload-artifact@v4
with:
name: bflat-windows-arm64.zip
path: layouts/windows-arm64.zip
- name: Archive windows-arm64 hosted compiler symbols
uses: actions/upload-artifact@v2
uses: actions/upload-artifact@v4
with:
name: debugsymbols-bflat-windows-arm64.zip
path: layouts/windows-arm64-symbols.zip
- name: Archive linux-glibc-x64 hosted compiler
uses: actions/upload-artifact@v2
uses: actions/upload-artifact@v4
with:
name: bflat-linux-glibc-x64.zip
path: layouts/linux-glibc-x64.tar.gz
- name: Archive linux-glibc-x64 hosted compiler symbols
uses: actions/upload-artifact@v2
uses: actions/upload-artifact@v4
with:
name: debugsymbols-bflat-linux-glibc-x64.zip
path: layouts/linux-glibc-x64-symbols.tar.gz
- name: Archive linux-glibc-arm64 hosted compiler
uses: actions/upload-artifact@v2
uses: actions/upload-artifact@v4
with:
name: bflat-linux-glibc-arm64.zip
path: layouts/linux-glibc-arm64.tar.gz
- name: Archive linux-glibc-arm64 hosted compiler symbols
uses: actions/upload-artifact@v2
uses: actions/upload-artifact@v4
with:
name: debugsymbols-bflat-linux-glibc-arm64.zip
path: layouts/linux-glibc-arm64-symbols.tar.gz
Expand Down
2 changes: 1 addition & 1 deletion src/bflat.Tests/bflat.Tests.csproj
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<TargetFramework>net6.0</TargetFramework>
<TargetFramework>net10.0</TargetFramework>
</PropertyGroup>

<ItemGroup>
Expand Down
106 changes: 74 additions & 32 deletions src/bflat/BuildCommand.cs

Large diffs are not rendered by default.

11 changes: 9 additions & 2 deletions src/bflat/ConfigurablePInvokePolicy.cs
Original file line number Diff line number Diff line change
Expand Up @@ -91,10 +91,17 @@ private IEnumerable<string> ModuleNameVariations(string name)
}
else
{
string suffix = _target.IsOSXLike ? ".dylib" : ".so";
string suffix = _target.IsApplePlatform ? ".dylib" : ".so";
bool hasSharedLibraryExtension = name.EndsWith(suffix, StringComparison.Ordinal);
const string LibPrefix = "lib";
bool hasLibPrefix = name.StartsWith(LibPrefix, StringComparison.Ordinal);

if (name.EndsWith(suffix, StringComparison.Ordinal))
if (hasSharedLibraryExtension)
yield return name.Substring(0, name.Length - suffix.Length);
if (hasLibPrefix)
yield return name.Substring(LibPrefix.Length);
if (hasLibPrefix && hasSharedLibraryExtension)
yield return name.Substring(LibPrefix.Length, name.Length - suffix.Length - LibPrefix.Length);
}
}

Expand Down
153 changes: 118 additions & 35 deletions src/bflat/InstructionSetHelpers.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
using System.Collections.Generic;
using System.Diagnostics;
using System.Runtime.InteropServices;
using System.Runtime.Intrinsics.X86;

using ILCompiler;

Expand Down Expand Up @@ -52,7 +53,7 @@ public static InstructionSetSupport ConfigureInstructionSetSupport(string instru
// Ready to run images are built with certain instruction set baselines
if ((targetArchitecture == TargetArchitecture.X86) || (targetArchitecture == TargetArchitecture.X64))
{
instructionSetSupportBuilder.AddSupportedInstructionSet("sse2"); // Lower baselines included by implication
instructionSetSupportBuilder.AddSupportedInstructionSet("base");
}
else if (targetArchitecture == TargetArchitecture.ARM64)
{
Expand All @@ -63,7 +64,7 @@ public static InstructionSetSupport ConfigureInstructionSetSupport(string instru
}
else
{
instructionSetSupportBuilder.AddSupportedInstructionSet("neon"); // Lower baselines included by implication
instructionSetSupportBuilder.AddSupportedInstructionSet("neon");
}
}

Expand All @@ -72,6 +73,8 @@ public static InstructionSetSupport ConfigureInstructionSetSupport(string instru
// compile both branches of IsSupported checks.
bool allowOptimistic = !optimizingForSize;

bool throttleAvx512 = false;

if (instructionSet == "native")
{
// We're compiling for a specific chip
Expand All @@ -92,31 +95,78 @@ public static InstructionSetSupport ConfigureInstructionSetSupport(string instru
}
HardwareIntrinsicHelpers.AddRuntimeRequiredIsaFlagsToBuilder(instructionSetSupportBuilder, cpuFeatures);

if (targetArchitecture is TargetArchitecture.X64 or TargetArchitecture.X86)
{
// Some architectures can experience frequency throttling when executing
// 512-bit width instructions. To account for this we set the
// default preferred vector width to 256-bits in some scenarios.
(int Eax, int Ebx, int Ecx, int Edx) cpuidInfo = X86Base.CpuId(0, 0);
bool isGenuineIntel = (cpuidInfo.Ebx == 0x756E6547) && // Genu
(cpuidInfo.Edx == 0x49656E69) && // ineI
(cpuidInfo.Ecx == 0x6C65746E); // ntel
if (isGenuineIntel)
{
cpuidInfo = X86Base.CpuId(1, 0);
Debug.Assert((cpuidInfo.Edx & (1 << 15)) != 0); // CMOV
int model = (cpuidInfo.Eax >> 4) & 0xF;
int family = (cpuidInfo.Eax >> 8) & 0xF;
int extendedModel = (cpuidInfo.Eax >> 16) & 0xF;

if (family == 0x06)
{
if (extendedModel == 0x05)
{
if (model == 0x05)
{
// * Skylake (Server)
// * Cascade Lake
// * Cooper Lake

throttleAvx512 = true;
}
}
else if (extendedModel == 0x06)
{
if (model == 0x06)
{
// * Cannon Lake

throttleAvx512 = true;
}
}
}
}

if (throttleAvx512 && logger.IsVerbose)
logger.LogMessage("Vector512 is throttled");
}

if (logger.IsVerbose)
logger.LogMessage($"The 'native' instruction set expanded to {instructionSetSupportBuilder}");
}
else if (instructionSet != null)
{
List<string> instructionSetParams = new List<string>();
string[] instructionSetParamsInput = instructionSet.Split(',');

// Normalize instruction set format to include implied +.
string[] instructionSetParamsInput = instructionSet.Split(',');
for (int i = 0; i < instructionSetParamsInput.Length; i++)
{
instructionSet = instructionSetParamsInput[i];
instructionSet = instructionSetParamsInput[i].Trim();

if (string.IsNullOrEmpty(instructionSet))
throw new CommandLineException(string.Format(mustNotBeMessage, ""));

char firstChar = instructionSet[0];

if ((firstChar != '+') && (firstChar != '-'))
{
instructionSet = "+" + instructionSet;
instructionSet = "+" + instructionSet;
}

instructionSetParams.Add(instructionSet);
}

Dictionary<string, bool> instructionSetSpecification = new Dictionary<string, bool>();
foreach (string instructionSetSpecifier in instructionSetParams)
{
instructionSet = instructionSetSpecifier.Substring(1);
Expand Down Expand Up @@ -160,53 +210,56 @@ public static InstructionSetSupport ConfigureInstructionSetSupport(string instru
InstructionSetSupportBuilder optimisticInstructionSetSupportBuilder = new InstructionSetSupportBuilder(instructionSetSupportBuilder);

// Optimistically assume some instruction sets are present.
if (allowOptimistic && (targetArchitecture == TargetArchitecture.X86 || targetArchitecture == TargetArchitecture.X64))
if (allowOptimistic && targetArchitecture is TargetArchitecture.X86 or TargetArchitecture.X64)
{
// We set these hardware features as opportunistically enabled as most of hardware in the wild supports them.
// Note that we do not indicate support for AVX, or any other instruction set which uses the VEX encodings as
// the presence of those makes otherwise acceptable code be unusable on hardware which does not support VEX encodings.
//
optimisticInstructionSetSupportBuilder.AddSupportedInstructionSet("sse4.2"); // Lower SSE versions included by implication
optimisticInstructionSetSupportBuilder.AddSupportedInstructionSet("sse42");
optimisticInstructionSetSupportBuilder.AddSupportedInstructionSet("aes");
optimisticInstructionSetSupportBuilder.AddSupportedInstructionSet("pclmul");
optimisticInstructionSetSupportBuilder.AddSupportedInstructionSet("movbe");
optimisticInstructionSetSupportBuilder.AddSupportedInstructionSet("popcnt");
optimisticInstructionSetSupportBuilder.AddSupportedInstructionSet("lzcnt");
optimisticInstructionSetSupportBuilder.AddSupportedInstructionSet("serialize");
optimisticInstructionSetSupportBuilder.AddSupportedInstructionSet("gfni");
optimisticInstructionSetSupportBuilder.AddSupportedInstructionSet("sha");
optimisticInstructionSetSupportBuilder.AddSupportedInstructionSet("waitpkg");
optimisticInstructionSetSupportBuilder.AddSupportedInstructionSet("x86serialize");

// If AVX was enabled, we can opportunistically enable instruction sets which use the VEX encodings
Debug.Assert(InstructionSet.X64_AVX == InstructionSet.X86_AVX);
Debug.Assert(InstructionSet.X64_AVX2 == InstructionSet.X86_AVX2);

if (supportedInstructionSet.HasInstructionSet(InstructionSet.X64_AVX))
{
// TODO: Enable optimistic usage of AVX2 once we validate it doesn't break Vector<T> usage
// optimisticInstructionSetSupportBuilder.AddSupportedInstructionSet("avx2");
optimisticInstructionSetSupportBuilder.AddSupportedInstructionSet("avx2");
optimisticInstructionSetSupportBuilder.AddSupportedInstructionSet("avxifma");
optimisticInstructionSetSupportBuilder.AddSupportedInstructionSet("avxvnni");
optimisticInstructionSetSupportBuilder.AddSupportedInstructionSet("avxvnniint");
optimisticInstructionSetSupportBuilder.AddSupportedInstructionSet("aes_v256");
optimisticInstructionSetSupportBuilder.AddSupportedInstructionSet("gfni_v256");

// If AVX2 is not in the supported set, we need to restrict the optimistic Vector<T> size, because
// 256-bit Vector<T> cannot be fully accelerated based on AVX2 being in the optimistic set only.

if (supportedInstructionSet.HasInstructionSet(InstructionSet.X64_AVX2))
if (!supportedInstructionSet.HasInstructionSet(InstructionSet.X64_AVX2))
{
optimisticInstructionSetSupportBuilder.AddSupportedInstructionSet("avxvnni");
maxVectorTBitWidth = 128;
}

optimisticInstructionSetSupportBuilder.AddSupportedInstructionSet("fma");
optimisticInstructionSetSupportBuilder.AddSupportedInstructionSet("bmi");
optimisticInstructionSetSupportBuilder.AddSupportedInstructionSet("bmi2");
}

Debug.Assert(InstructionSet.X64_AVX512F == InstructionSet.X86_AVX512F);
if (supportedInstructionSet.HasInstructionSet(InstructionSet.X64_AVX512F))
Debug.Assert(InstructionSet.X64_AVX512 == InstructionSet.X86_AVX512);
if (supportedInstructionSet.HasInstructionSet(InstructionSet.X64_AVX512))
{
Debug.Assert(supportedInstructionSet.HasInstructionSet(InstructionSet.X64_AVX512F_VL));
Debug.Assert(supportedInstructionSet.HasInstructionSet(InstructionSet.X64_AVX512BW));
Debug.Assert(supportedInstructionSet.HasInstructionSet(InstructionSet.X64_AVX512BW_VL));
Debug.Assert(supportedInstructionSet.HasInstructionSet(InstructionSet.X64_AVX512CD));
Debug.Assert(supportedInstructionSet.HasInstructionSet(InstructionSet.X64_AVX512CD_VL));
Debug.Assert(supportedInstructionSet.HasInstructionSet(InstructionSet.X64_AVX512DQ));
Debug.Assert(supportedInstructionSet.HasInstructionSet(InstructionSet.X64_AVX512DQ_VL));

optimisticInstructionSetSupportBuilder.AddSupportedInstructionSet("avx512vbmi");
optimisticInstructionSetSupportBuilder.AddSupportedInstructionSet("avx512vbmi_vl");
optimisticInstructionSetSupportBuilder.AddSupportedInstructionSet("avx512v2");
optimisticInstructionSetSupportBuilder.AddSupportedInstructionSet("avx512v3");
optimisticInstructionSetSupportBuilder.AddSupportedInstructionSet("avx10v1");
optimisticInstructionSetSupportBuilder.AddSupportedInstructionSet("avx10v2");
optimisticInstructionSetSupportBuilder.AddSupportedInstructionSet("avxvnniint_v512");
optimisticInstructionSetSupportBuilder.AddSupportedInstructionSet("avx512vp2intersect");
optimisticInstructionSetSupportBuilder.AddSupportedInstructionSet("aes_v512");
optimisticInstructionSetSupportBuilder.AddSupportedInstructionSet("gfni_v512");

}
}
else if (targetArchitecture == TargetArchitecture.ARM64)
else if (allowOptimistic && targetArchitecture is TargetArchitecture.ARM64)
{
optimisticInstructionSetSupportBuilder.AddSupportedInstructionSet("aes");
optimisticInstructionSetSupportBuilder.AddSupportedInstructionSet("crc");
Expand All @@ -215,7 +268,6 @@ public static InstructionSetSupport ConfigureInstructionSetSupport(string instru
optimisticInstructionSetSupportBuilder.AddSupportedInstructionSet("lse");
optimisticInstructionSetSupportBuilder.AddSupportedInstructionSet("dotprod");
optimisticInstructionSetSupportBuilder.AddSupportedInstructionSet("rdma");
optimisticInstructionSetSupportBuilder.AddSupportedInstructionSet("rcpc");
}

// Vector<T> can always be part of the optimistic set, we only want to optionally exclude it from the supported set
Expand All @@ -224,6 +276,37 @@ public static InstructionSetSupport ConfigureInstructionSetSupport(string instru
optimisticInstructionSet.Remove(unsupportedInstructionSet);
optimisticInstructionSet.Add(supportedInstructionSet);

if (throttleAvx512)
{
Debug.Assert(InstructionSet.X86_AVX512 == InstructionSet.X64_AVX512);
if (supportedInstructionSet.HasInstructionSet(InstructionSet.X86_AVX512))
{
Debug.Assert(InstructionSet.X86_Vector256 == InstructionSet.X64_Vector256);
Debug.Assert(InstructionSet.X86_VectorT256 == InstructionSet.X64_VectorT256);
Debug.Assert(InstructionSet.X86_VectorT512 == InstructionSet.X64_VectorT512);

// AVX-512 is supported, but we are compiling specifically for hardware that has a performance penalty for
// using 512-bit ops. We want to tell JIT not to consider Vector512 to be hardware accelerated, which we do
// by passing a PreferredVectorBitWidth value, in the form of a virtual vector ISA of the appropriate size.
//
// If we are downgrading the max accelerated vector size, we also need to downgrade Vector<T> size.

supportedInstructionSet.AddInstructionSet(InstructionSet.X86_Vector256);

if (supportedInstructionSet.HasInstructionSet(InstructionSet.X86_VectorT512))
{
supportedInstructionSet.RemoveInstructionSet(InstructionSet.X86_VectorT512);
supportedInstructionSet.AddInstructionSet(InstructionSet.X86_VectorT256);
}

if (optimisticInstructionSet.HasInstructionSet(InstructionSet.X86_VectorT512))
{
optimisticInstructionSet.RemoveInstructionSet(InstructionSet.X86_VectorT512);
optimisticInstructionSet.AddInstructionSet(InstructionSet.X86_VectorT256);
}
}
}

return new InstructionSetSupport(supportedInstructionSet,
unsupportedInstructionSet,
optimisticInstructionSet,
Expand Down
4 changes: 2 additions & 2 deletions src/bflat/bflat.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,14 @@

<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net8.0</TargetFramework>
<TargetFramework>net10.0</TargetFramework>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<Version Condition="'$(Version)' == ''">42.42.42.42</Version>
<SatelliteResourceLanguages>en-US</SatelliteResourceLanguages>
</PropertyGroup>

<PropertyGroup>
<RuntimeVersion>8.0.2-rtm.24317.2</RuntimeVersion>
<RuntimeVersion>10.0.0-rc.1.25451.2</RuntimeVersion>
<RuntimeUri>https://github.com/bflattened/runtime/releases/download/</RuntimeUri>

<BlobsVersion>1.3</BlobsVersion>
Expand Down
2 changes: 1 addition & 1 deletion src/debloat/debloat.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net6.0</TargetFramework>
<TargetFramework>net10.0</TargetFramework>
</PropertyGroup>

</Project>
Loading