Skip to content

Commit 200a90a

Browse files
authored
Remove mono specific SpanHelpers (#79215)
* Revert "[Mono] Restore old code to solve the recent SpanHelpers regressions (#75917)" This reverts commit 254844a. * [System.Span] Refactor hot loop code This would replace code like ``` load b.neq add ret load b.neq add ret load .... ``` with ``` load b.eq load b.eq load ... ``` This makes the code more compact in the hot loop, reduces overall code size and thus improves performance. This pattern is widely used and it was also used before with Span lookups. * [mono][interp] Replace compare + brfalse/brtrue with single conditional branch * [mono][interp] Dump in/out links for bblocks during verbose logging * [mono][interp] Improve detection of dead bblocks Before we were marking bblocks as dead if they had their in_count 0. This is not enough however, since it doesn't account for loops. We now do a full traversal of the bblock graph to detect unreachable bblocks. * [mono][interp] Reorder bblocks to facilitate propagation of values Consider for example the following pattern used commonly with conditional branches: ``` br.s [nil <- nil], BB0 ... ceq0.i4 [32 <- 40], br.s [nil <- nil], BB1 BB0: ldc.i4.0 [32 <- nil], BB1: brfalse.i4.s [nil <- 32], BB_EXIT BB2: ldstr [56 <- nil], 2 ``` This commit reorders this code to look like: ``` br.s [nil <- nil], BB0 ... ceq0.i4 [32 <- 40], brfalse.i4.s [nil <- 32], BB_EXIT br.s [nil <- nil], BB2 BB0 ldc.i4.0 [32 <- nil], BB1: brfalse.i4.s [nil <- 32], BB_EXIT BB2: ldstr [56 <- nil], 2 ``` This means we will have duplicated brfalse instructions, but every basic block reaching the conditional branch will have information about the condition. For example ceq0.i4 + brfalse is equivalent to brtrue, ldc.i4.0 + brfalse is equivalent to unconditional branch. After other future optimizations applied on the bblocks graph, like removal, merging and propagation of target, the resulting code in this example would look like: ``` br.s [nil <- nil], BB_EXIT ... brtrue.i4.s [nil <- 40], BB_EXIT BB2: ldstr [56 <- nil], 2 ``` Which is a great simplification over the original code. * [mono][interp] Don't optimize out bblocks that are tiering patchpoint targets Even though they can be become unreachable in the current method, they can still be called when the unoptimized method gets tiered at this point. Add assert to prevent such issues in the future. * [mono][interp] Make bblock reordering more conservative If we are unlikely to gain anything from propagating the condition (if we don't have information about any of the condition operand vars), simply avoid the optimization. * [mono][interp] Add basic removal of unused defines If we store in a var and this var is not used and redefined by the end of the basic block, then we can clear the original store. * [mono][interp] Clear unused defines of local only vars We detect if a var's value never escapes the definition of a bblock. We mark such vars and clear unused definitions of that var from other bblocks. * [mono][interp] Propagate target branches If a bblock contains only an unconditional br, then all bblocks branching into it can just call the target directly instead. * [mono][interp] Add super instruction for (var + ct1) * ct2 This pattern is used in low level unsafe code when using (var + ct1) as an index into an array, where ct2 is the sizeof of array element. Also fix diplay of two shorts when dumping instructions. * [mono][interp] Add new ldind super instruction These new instructions can apply addition and multiplication with constant to the offset var.
1 parent 4dd8a78 commit 200a90a

File tree

11 files changed

+681
-2842
lines changed

11 files changed

+681
-2842
lines changed

src/libraries/System.Private.CoreLib/src/System.Private.CoreLib.Shared.projitems

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2526,7 +2526,4 @@
25262526
<Compile Include="$(MSBuildThisFileDirectory)System\Numerics\IUnaryPlusOperators.cs" />
25272527
<Compile Include="$(MSBuildThisFileDirectory)System\Numerics\IUnsignedNumber.cs" />
25282528
</ItemGroup>
2529-
<ItemGroup Condition="'$(FeatureMono)' == 'true'">
2530-
<Compile Include="$(MSBuildThisFileDirectory)System\SpanHelpers.Mono.cs" />
2531-
</ItemGroup>
25322529
</Project>

src/libraries/System.Private.CoreLib/src/System/MemoryExtensions.cs

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1750,7 +1750,6 @@ public static unsafe int IndexOfAny<T>(this ReadOnlySpan<T> span, ReadOnlySpan<T
17501750
Unsafe.Add(ref valueRef, 2),
17511751
span.Length);
17521752

1753-
#if !MONO // We don't have a mono overload for 4 values
17541753
case 4:
17551754
return SpanHelpers.IndexOfAnyValueType(
17561755
ref spanRef,
@@ -1759,7 +1758,7 @@ public static unsafe int IndexOfAny<T>(this ReadOnlySpan<T> span, ReadOnlySpan<T
17591758
Unsafe.Add(ref valueRef, 2),
17601759
Unsafe.Add(ref valueRef, 3),
17611760
span.Length);
1762-
#endif
1761+
17631762
case 5:
17641763
return SpanHelpers.IndexOfAnyValueType(
17651764
ref spanRef,
@@ -2025,7 +2024,6 @@ public static unsafe int LastIndexOfAny<T>(this ReadOnlySpan<T> span, ReadOnlySp
20252024
Unsafe.Add(ref valueRef, 2),
20262025
span.Length);
20272026

2028-
#if !MONO // We don't have a mono overload for 4 values
20292027
case 4:
20302028
return SpanHelpers.LastIndexOfAnyValueType(
20312029
ref spanRef,
@@ -2034,7 +2032,6 @@ public static unsafe int LastIndexOfAny<T>(this ReadOnlySpan<T> span, ReadOnlySp
20342032
Unsafe.Add(ref valueRef, 2),
20352033
Unsafe.Add(ref valueRef, 3),
20362034
span.Length);
2037-
#endif
20382035

20392036
case 5:
20402037
return SpanHelpers.LastIndexOfAnyValueType(
@@ -2075,7 +2072,6 @@ public static unsafe int LastIndexOfAny<T>(this ReadOnlySpan<T> span, ReadOnlySp
20752072
Unsafe.Add(ref valueRef, 2),
20762073
span.Length);
20772074

2078-
#if !MONO // We don't have a mono overload for 4 values
20792075
case 4:
20802076
return SpanHelpers.LastIndexOfAnyValueType(
20812077
ref spanRef,
@@ -2084,7 +2080,6 @@ public static unsafe int LastIndexOfAny<T>(this ReadOnlySpan<T> span, ReadOnlySp
20842080
Unsafe.Add(ref valueRef, 2),
20852081
Unsafe.Add(ref valueRef, 3),
20862082
span.Length);
2087-
#endif
20882083

20892084
case 5:
20902085
return SpanHelpers.LastIndexOfAnyValueType(

src/libraries/System.Private.CoreLib/src/System/SpanHelpers.Byte.cs

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -986,13 +986,21 @@ public static nuint CommonPrefixLength(ref byte first, ref byte second, nuint le
986986

987987
for (; (nint)i <= (nint)length - 4; i += 4)
988988
{
989-
if (Unsafe.Add(ref first, i + 0) != Unsafe.Add(ref second, i + 0)) return i + 0;
990-
if (Unsafe.Add(ref first, i + 1) != Unsafe.Add(ref second, i + 1)) return i + 1;
991-
if (Unsafe.Add(ref first, i + 2) != Unsafe.Add(ref second, i + 2)) return i + 2;
992-
if (Unsafe.Add(ref first, i + 3) != Unsafe.Add(ref second, i + 3)) return i + 3;
989+
if (Unsafe.Add(ref first, i + 0) != Unsafe.Add(ref second, i + 0)) goto Found0;
990+
if (Unsafe.Add(ref first, i + 1) != Unsafe.Add(ref second, i + 1)) goto Found1;
991+
if (Unsafe.Add(ref first, i + 2) != Unsafe.Add(ref second, i + 2)) goto Found2;
992+
if (Unsafe.Add(ref first, i + 3) != Unsafe.Add(ref second, i + 3)) goto Found3;
993993
}
994994

995995
return length;
996+
Found0:
997+
return i;
998+
Found1:
999+
return i + 1;
1000+
Found2:
1001+
return i + 2;
1002+
Found3:
1003+
return i + 3;
9961004
}
9971005

9981006
Debug.Assert(length >= (uint)Vector128<byte>.Count);

0 commit comments

Comments
 (0)