-
Notifications
You must be signed in to change notification settings - Fork 4.7k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Intrinsify RuntimeInformation.IsOSPlatform #738
Comments
Presumably that could potentially enable the JIT to remove the code as dead. How common is it to check this though, and is it normally a perf concern? |
I think it belongs to the same category as branch elimination due to |
These APIs were specifically designed to be friendly to JIT optimizations
This API is not friendly to JIT optimizations. It can be optimized quite a bit by having a better implementation, without any help from the JIT. These optimizations should be done first. |
It can reduce code size in common scenarios. Platform specific code may be large when calling a sequence of P/Invoke. |
@jkotas, do you have a suggestion on how to do this? The implementation today is trivial and just compares the input struct with the static readonly instance member for the current platform: Lines 17 to 20 in c9789de
Which ultimately just compares the internal string member using I can't think of any existing JIT optimizations that would allow us to improve this so that it could be constant folded for the common case of |
Looks like Unix has a slightly different implementation, but I think the same question applies: Lines 18 to 22 in c9789de
|
Another case where this would help is in AOT situations. If I was compiling for if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
{
// bring in a whole new dependency that is Windows-specific
} It could eliminate a whole dependency completely in a Note that this is the pattern we recommend to developers to use for switching on Operating Systems. There currently isn't a built-in way to pivot your C# compilation based on target OS. |
There is an effort to do this in the linker: dotnet/linker#607 . Doing this in the linker will strip it from both IL and potential AOT image. Stripping it from both is better than stripping it from just AOT image. |
For example, we can normalize the string into This approach has trade-offs so it is not obvious that we should do it. I am just trying to demonstrate that there are options.
To avoid bringing in the whole new dependency, the code should better be moved into a separate method. Even if we intrinsify this in the JIT, the JIT would still bring in the inline dependency in in the common case before optimizing it out.
Do we have it written anywhere? This pattern is a non-starter in many cases given the current performance characteristics of this API. |
Yes: https://github.com/dotnet/platform-compat/blob/master/docs/DE0007.md
https://github.com/dotnet/platform-compat/blob/master/docs/DE0009.md
|
Also enable cross-building and publishing Windows ARM64-hosted objwriter.dll. Use Release build type with debug information enabled.
The new methods on the I'll close this issue and recommended to use the method on the |
NOTE: it's handled in .NET 8.0 now in JIT as well (it wasn't intrisified specially, but a set of unrelated general optimizations helped to make this happen) class Tests
{
public static bool IsWin() => RuntimeInformation.IsOSPlatform(OSPlatform.Windows);
public static bool IsLinux() => RuntimeInformation.IsOSPlatform(OSPlatform.Linux);
} Codegen (e.g. on Windows): ; Assembly listing for method Tests:IsWin():bool (Tier1)
mov eax, 1
ret
; Assembly listing for method Tests:IsLinux():bool (Tier1)
xor eax, eax
ret Only for JIT and only if promoted to Tier1 naturally so sharplab won't show it. NativeAOT is blocked by #83043 |
The result of
RuntimeInformation.IsOSPlatform
does not change during the application run lifecycle. It would be a nice optimization if JIT intrinsically generate a better code for this method.For example, for the following method:
JIT produces this asm (with VS2019 and .NET Core 3.1 in Release configuration):
Instead, it could just produce:
on Windows, and on Unix:
The text was updated successfully, but these errors were encountered: