-
Notifications
You must be signed in to change notification settings - Fork 4.8k
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
JIT: cloning invariant analysis seems oddly limited #70100
Comments
Tagging subscribers to this area: @JulieLeeMSFT Issue DetailsConsider the three similar methods using System;
using System.Runtime.CompilerServices;
class X
{
[MethodImpl(MethodImplOptions.NoInlining)]
public static void S() { }
[MethodImpl(MethodImplOptions.NoInlining)]
public static void F(int[] a, int low, int high, ref int z)
{
for (int i = low; i < high; i++)
{
z += a[i];
S();
}
}
[MethodImpl(MethodImplOptions.NoInlining)]
public static void G(int[] a, int low, int high, ref int z)
{
for (int i = low; i < high; i++)
{
z += a[i];
}
}
[MethodImpl(MethodImplOptions.NoInlining)]
public static void H(int[] a, int low, int high, ref int z)
{
int r = 0;
for (int i = low; i < high; i++)
{
r += a[i];
S();
}
z = r;
}
public static int Main()
{
int[] a = new int[] { 1, 2, 3, 4 };
int z = 0;
F(a, 2, 3, ref z);
G(a, 2, 3, ref z);
H(a, 2, 3, ref z);
return z + 70;
}
} The JIT will clone the loops in I think the check done in the latter part of runtime/src/coreclr/jit/optimizer.cpp Lines 5758 to 5870 in 41c1c10
This impacts GDV-driven cloning of loops (#65206), since such loops inevitably involve calls; if the loop is the expansion of a Fixing this leads to a fairly large total diff given the relatively small number of impacted methods. Presumably this combination of calls and indir stores only appears in larger loops. We could perhaps be even more aggressive with the fix and consider actually setting the indir mask if the local we're interested in proving invariant is address exposed. Haven't tried this. Longer term we really should find a way to leverage parts of the invariant logic we use for hoisting here. The fact that a local is assigned in a loop is an indication it might not be a loop invariant, but is by no means a proof.
cc @dotnet/jit-contrib
|
Also wanted to fix the loop invariant analysis to use wider bit vectors, but we're upstream of
Ultimately all this loop stuff should happen with SSA built, in which case the above is moot, we won't need bit vectors. |
Looks like |
Streamline call effects checks. Use wider bit vectors. Closes dotnet#70100.
Streamline call effects checks. Use wider bit vectors. Closes #70100.
Consider the three similar methods
F
,G
, andH
:The JIT will clone the loops in
G
andH
but not inF
. This happens becauseoptIsSetAssgLoop
will always report locals as modified in any loop that contains both a user call and an indir store, even if the local in question (i
in this case) is not address exposed.I think the check done in the latter part of
optIsSetAssgLoop
is wrong, and it should be checking whetherinds
has the various possibilities, notloop->lpAsgInds
(which we've already checked earlier in the method). And the loop invariant tests done by the cloner always pass an emptyinds
so that these latter checks become irrelevant.runtime/src/coreclr/jit/optimizer.cpp
Lines 5758 to 5870 in 41c1c10
This impacts GDV-driven cloning of loops (#65206), since such loops inevitably involve calls; if the loop is the expansion of a
foreach
we often also see indir stores updating the iterator fields.Fixing this leads to a fairly large total diff given the relatively small number of impacted methods. Presumably this combination of calls and indir stores only appears in larger loops.
We could perhaps be even more aggressive with the fix and consider actually setting the indir mask if the local we're interested in proving invariant is address exposed. Haven't tried this.
Longer term we really should find a way to leverage parts of the invariant logic we use for hoisting here. The fact that a local is assigned in a loop is an indication it might not be a loop invariant, but is by no means a proof.
cc @dotnet/jit-contrib
The text was updated successfully, but these errors were encountered: