-
Notifications
You must be signed in to change notification settings - Fork 4.9k
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
Fix failure in net472 debug AdvSimd Utf16Utility #39652
Conversation
Tagging subscribers to this area: @tannergooding |
src/libraries/System.Private.CoreLib/src/System/Text/Unicode/Utf16Utility.Validation.cs
Show resolved
Hide resolved
d0f19b2
to
a19c88b
Compare
Vector128<byte> bitMask128 = BitConverter.IsLittleEndian ? | ||
Vector128.Create(0x80402010_08040201).AsByte() : | ||
Vector128.Create(0x01020408_10204080).AsByte(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Does the JIT know that Vector128.Create
is side-effect free so it can eliminate this code when the bitMask128
variable is unused? If not, this is adding unnecessary overhead to the x86 path.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not sure. @echesakovMSFT @tannergooding @kunalspathak do you know the answer to this?
Regardless of the answer, since the code was moved from being a static field (which was initialized for all architectures) to a local variable (which is also available for all architectures), I assume the behavior would not be worse than before.
If we think this needs to be addressed to avoid the unnecessary overhead in x86, I can create an issue so it gets fixed later.
I would like to get this merged as soon as possible to unblock net472 (prevent the PNS exception on runtime), so the backport to Prev8 gets approved.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The static would only have been initialized once. The local is created for every invocation.
The simple workaround, if indeed the JIT isn't eliminating it as dead, would just be to re-use the zero vector above so this one becomes an unused alias. i.e.:
Vector128<byte> bitMask128 = !AdvSimd.IsSupported ? vectorZero :
BitConverter.IsLittleEndian ?
Vector128.Create(0x80402010_08040201).AsByte() :
Vector128.Create(0x01020408_10204080).AsByte();
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah, thanks for the clarification, @saucecontrol . I'll add it to the list of TODOs to address in the next PR.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We do eliminate dead stores. Here is a sample test on x64:
Vector128<byte> bitMask128 = BitConverter.IsLittleEndian ?
Vector128.Create(0x80402010_08040201).AsByte() :
Vector128.Create(0x01020408_10204080).AsByte();
if (AdvSimd.IsSupported)
{
Console.WriteLine(bitMask128);
}
else
{
Console.WriteLine(1);
}
Produces:
G_M58174_IG01:
4883EC28 sub rsp, 40
;; bbWeight=1 PerfScore 0.25
G_M58174_IG02:
B901000000 mov ecx, 1
E832FDFFFF call System.Console:WriteLine(int)
B864000000 mov eax, 100
;; bbWeight=1 PerfScore 1.50
G_M58174_IG03:
4883C428 add rsp, 40
C3 ret
;; bbWeight=1 PerfScore 1.25
…#39738) * AdvSimd support for System.Text.Unicode.Utf16Utility.GetPointerToFirstInvalidChar (#39050) * AdvSimd support for System.Text.Unicode.Utf16Utility.GetPointerToFirstInvalidChar * Move using directive outside #if. Improve Arm64MoveMask. * Change overloads * UIn64 in Arm64MoveMask * Build error implicit conversion fix * Rename method and use simpler version * Use ShiftRightArithmetic instead of CompareEqual + And. * Remove unnecessary comment * Add missing shims causing Linux build to fail * AdvSimd support for System.Text.Unicode.Utf8Utility.TranscodeToUtf8 (#39041) * AdvSimd support for System.Text.Unicode.Utf8Utility.TranscodeToUtf8 * Readd using to prevent build failure. Add AdvSimd equivalent operation to TestZ. * Inverted condition * Address IsSupported order, improve use ExtractNarrowingSaturated usage * Rename source to result, second argument utf16Data * Improve CompareTest * Add shims causing failures in Linux * Use unsigned version of ExtractNarrowingSaturate, avoid using MinAcross and use MaxPairwise instead * Missing support check for Sse2.X64 * Add missing case for AdvSimd * Use MinPairwise for short * AdvSimd support for System.Text.Unicode.Utf8Utility.GetPointerToFirstInvalidByte (#38653) * AdvSimd support for System.Text.Unicode.Utf8Utility.GetPointerToFirstInvalidByte * Move comment to the top, add shims. * Little endian checks * Use custom MoveMask method for AdvSimd * Address suggestions to improve the AdvSimdMoveMask method * Define initialMask outside MoveMask method * UInt64 in Arm64MoveMask * Add unit test case to verify intrinsics improvement * Avoid casting to smaller integer type * Typo and comment * Use ShiftRightArithmetic instead of CompareEqual + And. Remove test case causing other unit tests to fail. * Use AddPairwise version of GetNotAsciiBytes * Add missing shims causing Linux build to fail * Simplify GetNonAsciiBytes to only one AddPairwise call, shorter bitmask * Respect data type returned by masking method * Address suggestions - assert trailingzerocount and bring back uint mask * Trailing zeroes in AdvSimd need to be divided by 4, and total number should not be larger than 16 * Avoid declaring static field which causes PNSE in Utf8String.Experimental (S.P.Corelib code is used for being NetStandard) * Prefer using nuint for BitConverter.TrailingZeroCount * Fix build failure in net472 debug AdvSimd Utf16Utility (#39652) Co-authored-by: Carlos Sanchez Lopez <[email protected]>
The
Utf16Utility
is a static class, and it's consumed inSystem.Utf8String.Experimental
, which is a .NET Standard project, meaning it can be used in .NET Framework too.Intrinsics code is not available in .NET Framework, so it shouldn't be added to a static field in that class, otherwise it causes net472 to fail on runtime when the static class gets called for the first time (it gets initialized, then tries to initialize the static fields).
The breaking change was introduced in #39050
The fix is to pass the value of the
bitMask
as a parameter, like we have been doing in other recent intrinsics changes.cc @ViktorHofer @safern @kunalspathak @tannergooding