* Use PackedIndexOfIsSupported checks in more places
This should avoids the size regression on WebAssembly and possibly other
platforms without Sse2.
The regression is side effect of https://github.com/dotnet/runtime/pull/78861
which uses `PackedSpanHelpers.CanUsePackedIndexOf (!!T)` and TShouldUsePacked.Value
to guard the usage of PackedSpanHelpers.
Because these involve generics, illinker is unable to link
the PackedSpanHelpers type away and that pulls other parts in, like
System.Runtime.Intrinsics.X86.* types. See https://gist.github.com/radekdoulik/
c0b52247d472f69bcf983ade78a924ea
for more complete list.
This change gets us back 9,216 bytes in the case of app used to repro
the regression.
...
- Type System.PackedSpanHelpers
- Type System.Runtime.Intrinsics.X86.X86Base
- Type System.Runtime.Intrinsics.X86.Sse
- Type System.Runtime.Intrinsics.X86.Sse2
Summary:
- 9,216 File size -0.76% (of 1,215,488)
- 2,744 Metadata size -0.43% (of 636,264)
- 4 Types count
* Update src/libraries/System.Private.CoreLib/src/System/IndexOfAnyValues/IndexOfAnyValues.cs
Co-authored-by: Miha Zupan <mihazupan.zupan1@gmail.com>
* Update src/libraries/System.Private.CoreLib/src/System/IndexOfAnyValues/IndexOfAnyValues.cs
Co-authored-by: Miha Zupan <mihazupan.zupan1@gmail.com>
* Feedback
Co-authored-by: Miha Zupan <mihazupan.zupan1@gmail.com>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
internal override int IndexOfAny(ReadOnlySpan<char> span) =>
- TShouldUsePacked.Value
+ (PackedSpanHelpers.PackedIndexOfIsSupported && TShouldUsePacked.Value)
? PackedSpanHelpers.IndexOf(ref MemoryMarshal.GetReference(span), _e0, span.Length)
: SpanHelpers.NonPackedIndexOfValueType<short, SpanHelpers.DontNegate<short>>(
ref Unsafe.As<char, short>(ref MemoryMarshal.GetReference(span)),
[MethodImpl(MethodImplOptions.AggressiveInlining)]
internal override int IndexOfAnyExcept(ReadOnlySpan<char> span) =>
- TShouldUsePacked.Value
+ (PackedSpanHelpers.PackedIndexOfIsSupported && TShouldUsePacked.Value)
? PackedSpanHelpers.IndexOfAnyExcept(ref MemoryMarshal.GetReference(span), _e0, span.Length)
: SpanHelpers.NonPackedIndexOfValueType<short, SpanHelpers.Negate<short>>(
ref Unsafe.As<char, short>(ref MemoryMarshal.GetReference(span)),
[MethodImpl(MethodImplOptions.AggressiveInlining)]
internal override int IndexOfAny(ReadOnlySpan<char> span) =>
- TShouldUsePacked.Value
+ (PackedSpanHelpers.PackedIndexOfIsSupported && TShouldUsePacked.Value)
? PackedSpanHelpers.IndexOfAny(ref MemoryMarshal.GetReference(span), _e0, _e1, span.Length)
: SpanHelpers.NonPackedIndexOfAnyValueType<short, SpanHelpers.DontNegate<short>>(
ref Unsafe.As<char, short>(ref MemoryMarshal.GetReference(span)),
[MethodImpl(MethodImplOptions.AggressiveInlining)]
internal override int IndexOfAnyExcept(ReadOnlySpan<char> span) =>
- TShouldUsePacked.Value
+ (PackedSpanHelpers.PackedIndexOfIsSupported && TShouldUsePacked.Value)
? PackedSpanHelpers.IndexOfAnyExcept(ref MemoryMarshal.GetReference(span), _e0, _e1, span.Length)
: SpanHelpers.NonPackedIndexOfAnyValueType<short, SpanHelpers.Negate<short>>(
ref Unsafe.As<char, short>(ref MemoryMarshal.GetReference(span)),
[MethodImpl(MethodImplOptions.AggressiveInlining)]
internal override int IndexOfAny(ReadOnlySpan<char> span) =>
- TShouldUsePacked.Value
+ (PackedSpanHelpers.PackedIndexOfIsSupported && TShouldUsePacked.Value)
? PackedSpanHelpers.IndexOfAny(ref MemoryMarshal.GetReference(span), _e0, _e1, _e2, span.Length)
: SpanHelpers.NonPackedIndexOfAnyValueType<short, SpanHelpers.DontNegate<short>>(
ref Unsafe.As<char, short>(ref MemoryMarshal.GetReference(span)),
[MethodImpl(MethodImplOptions.AggressiveInlining)]
internal override int IndexOfAnyExcept(ReadOnlySpan<char> span) =>
- TShouldUsePacked.Value
+ (PackedSpanHelpers.PackedIndexOfIsSupported && TShouldUsePacked.Value)
? PackedSpanHelpers.IndexOfAnyExcept(ref MemoryMarshal.GetReference(span), _e0, _e1, _e2, span.Length)
: SpanHelpers.NonPackedIndexOfAnyValueType<short, SpanHelpers.Negate<short>>(
ref Unsafe.As<char, short>(ref MemoryMarshal.GetReference(span)),
[MethodImpl(MethodImplOptions.AggressiveInlining)]
internal override int IndexOfAny(ReadOnlySpan<char> span) =>
- TShouldUsePacked.Value
+ (PackedSpanHelpers.PackedIndexOfIsSupported && TShouldUsePacked.Value)
? PackedSpanHelpers.IndexOfAnyInRange(ref MemoryMarshal.GetReference(span), _lowInclusive, _rangeInclusive, span.Length)
: SpanHelpers.NonPackedIndexOfAnyInRangeUnsignedNumber<ushort, SpanHelpers.DontNegate<ushort>>(
ref Unsafe.As<char, ushort>(ref MemoryMarshal.GetReference(span)),
[MethodImpl(MethodImplOptions.AggressiveInlining)]
internal override int IndexOfAnyExcept(ReadOnlySpan<char> span) =>
- TShouldUsePacked.Value
+ (PackedSpanHelpers.PackedIndexOfIsSupported && TShouldUsePacked.Value)
? PackedSpanHelpers.IndexOfAnyExceptInRange(ref MemoryMarshal.GetReference(span), _lowInclusive, _rangeInclusive, span.Length)
: SpanHelpers.NonPackedIndexOfAnyInRangeUnsignedNumber<ushort, SpanHelpers.Negate<ushort>>(
ref Unsafe.As<char, ushort>(ref MemoryMarshal.GetReference(span)),
if (values.Length == 1)
{
char value = values[0];
- return PackedSpanHelpers.CanUsePackedIndexOf(value)
+ return PackedSpanHelpers.PackedIndexOfIsSupported && PackedSpanHelpers.CanUsePackedIndexOf(value)
? new IndexOfAny1CharValue<TrueConst>(value)
: new IndexOfAny1CharValue<FalseConst>(value);
}
{
char value0 = values[0];
char value1 = values[1];
- return PackedSpanHelpers.CanUsePackedIndexOf(value0) && PackedSpanHelpers.CanUsePackedIndexOf(value1)
+ return PackedSpanHelpers.PackedIndexOfIsSupported && PackedSpanHelpers.CanUsePackedIndexOf(value0) && PackedSpanHelpers.CanUsePackedIndexOf(value1)
? new IndexOfAny2CharValue<TrueConst>(value0, value1)
: new IndexOfAny2CharValue<FalseConst>(value0, value1);
}
char value0 = values[0];
char value1 = values[1];
char value2 = values[2];
- return PackedSpanHelpers.CanUsePackedIndexOf(value0) && PackedSpanHelpers.CanUsePackedIndexOf(value1) && PackedSpanHelpers.CanUsePackedIndexOf(value2)
+ return PackedSpanHelpers.PackedIndexOfIsSupported && PackedSpanHelpers.CanUsePackedIndexOf(value0) && PackedSpanHelpers.CanUsePackedIndexOf(value1) && PackedSpanHelpers.CanUsePackedIndexOf(value2)
? new IndexOfAny3CharValue<TrueConst>(value0, value1, value2)
: new IndexOfAny3CharValue<FalseConst>(value0, value1, value2);
}
}
Debug.Assert(typeof(T) == typeof(char));
- return (IndexOfAnyValues<T>)(object)(PackedSpanHelpers.CanUsePackedIndexOf(min) && PackedSpanHelpers.CanUsePackedIndexOf(max)
+ return (IndexOfAnyValues<T>)(object)(PackedSpanHelpers.PackedIndexOfIsSupported && PackedSpanHelpers.CanUsePackedIndexOf(min) && PackedSpanHelpers.CanUsePackedIndexOf(max)
? new IndexOfAnyCharValuesInRange<TrueConst>(*(char*)&min, *(char*)&max)
: new IndexOfAnyCharValuesInRange<FalseConst>(*(char*)&min, *(char*)&max));
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
internal static unsafe bool ContainsValueType<T>(ref T searchSpace, T value, int length) where T : struct, INumber<T>
{
- if (PackedSpanHelpers.CanUsePackedIndexOf(value))
+ if (PackedSpanHelpers.PackedIndexOfIsSupported && PackedSpanHelpers.CanUsePackedIndexOf(value))
{
return PackedSpanHelpers.Contains(ref Unsafe.As<T, short>(ref searchSpace), *(short*)&value, length);
}
where TValue : struct, INumber<TValue>
where TNegator : struct, INegator<TValue>
{
- if (PackedSpanHelpers.CanUsePackedIndexOf(value))
+ if (PackedSpanHelpers.PackedIndexOfIsSupported && PackedSpanHelpers.CanUsePackedIndexOf(value))
{
return typeof(TNegator) == typeof(DontNegate<short>)
? PackedSpanHelpers.IndexOf(ref Unsafe.As<TValue, char>(ref searchSpace), *(char*)&value, length)
where TValue : struct, INumber<TValue>
where TNegator : struct, INegator<TValue>
{
- if (PackedSpanHelpers.CanUsePackedIndexOf(value0) && PackedSpanHelpers.CanUsePackedIndexOf(value1))
+ if (PackedSpanHelpers.PackedIndexOfIsSupported && PackedSpanHelpers.CanUsePackedIndexOf(value0) && PackedSpanHelpers.CanUsePackedIndexOf(value1))
{
return typeof(TNegator) == typeof(DontNegate<short>)
? PackedSpanHelpers.IndexOfAny(ref Unsafe.As<TValue, char>(ref searchSpace), *(char*)&value0, *(char*)&value1, length)
where TValue : struct, INumber<TValue>
where TNegator : struct, INegator<TValue>
{
- if (PackedSpanHelpers.CanUsePackedIndexOf(value0) && PackedSpanHelpers.CanUsePackedIndexOf(value1) && PackedSpanHelpers.CanUsePackedIndexOf(value2))
+ if (PackedSpanHelpers.PackedIndexOfIsSupported && PackedSpanHelpers.CanUsePackedIndexOf(value0) && PackedSpanHelpers.CanUsePackedIndexOf(value1) && PackedSpanHelpers.CanUsePackedIndexOf(value2))
{
return typeof(TNegator) == typeof(DontNegate<short>)
? PackedSpanHelpers.IndexOfAny(ref Unsafe.As<TValue, char>(ref searchSpace), *(char*)&value0, *(char*)&value1, *(char*)&value2, length)
where T : struct, IUnsignedNumber<T>, IComparisonOperators<T, T, bool>
where TNegator : struct, INegator<T>
{
- if (PackedSpanHelpers.CanUsePackedIndexOf(lowInclusive) && PackedSpanHelpers.CanUsePackedIndexOf(highInclusive) && highInclusive >= lowInclusive)
+ if (PackedSpanHelpers.PackedIndexOfIsSupported && PackedSpanHelpers.CanUsePackedIndexOf(lowInclusive) && PackedSpanHelpers.CanUsePackedIndexOf(highInclusive) && highInclusive >= lowInclusive)
{
ref char charSearchSpace = ref Unsafe.As<T, char>(ref searchSpace);
char charLowInclusive = *(char*)&lowInclusive;