-
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
JIT: Loop cloning when the method has GDV skips necessary validity checks #95315
Comments
Tagging subscribers to this area: @JulieLeeMSFT, @jakobbotsch Issue DetailsThe following program either hits AV or prints memory from a random heap location. We get rid of the bounds check in the loop in using System;
using System.Runtime.CompilerServices;
using System.Threading;
public class Program
{
public static void Main()
{
for (int i = 0; i < 4; i++)
{
for (int j = 0; j < 200; j++)
{
try
{
Bar(new int[10], new C());
}
catch (IndexOutOfRangeException)
{
}
}
Thread.Sleep(500);
}
Bar(new int[1], new C());
}
[MethodImpl(MethodImplOptions.NoInlining)]
private static void Bar(int[] arr, I iface)
{
if (arr == null)
{
return;
}
iface.Foo();
int i = 10000000;
do
{
Console.WriteLine(arr[i]);
i++;
} while (i < arr.Length);
}
}
internal interface I
{
void Foo();
}
internal class C : I
{
public void Foo()
{
}
} The problem is that we skip the following check when we have GDVs in the method, but then still end up optimizing bounds checks. That's only legal when this check passes. runtime/src/coreclr/jit/loopcloning.cpp Line 1893 in 9ca9580
|
I'm not sure why we leave this particular validity check up to loop cloning instead of rejecting the induction analysis during loop finding. The results of the induction analysis do not seem useful unless we know the full loop body is protected by the loop test. |
Probably the case that when I added GDV driven cloning and generalized the cloning conditions I didn't look carefully enough at the hot loop optimizations, so for a pure GDV clone, they can turn on when they shouldn't. |
Move the validation of the base case of the IV analysis into `FlowGraphNaturalLoop::AnalyzeIteration`. Previously the validation for the base case was left up to the users: - Loop cloning tried to accomplish this by checking whether loop inversion had run, but this is not sufficient (dotnet#96623) as nothing guarantees the loop is dominated by the inverted test. Loop cloning also skipped the check entirely for GDV, leading to dotnet#95315. - Unrolling completely neglected to check the condition leading to dotnet#96591. Furthermore, unrolling made implicit assumptions that any `BBJ_COND` init block was an inverted test and downright removed the condition without any checks. This also led to another issue dotnet#97040 where unrolling could uncover new natural loops that had not been canonicalized. This change makes `FlowGraphNaturalLoop::AnalyzeIteration` try to prove that the loop invariant it returns is true in the base case as well as being maintained by the loop. If it cannot prove this then it fails. This fixes all the issues, but sadly uncovers that we were doing a lot of cloning in OSR methods without actually proving legality. We no longer clone in these cases, but we can look into what to do about them separately. Fix dotnet#95315 Fix dotnet#96591 Fix dotnet#96623 Fix dotnet#97040
…#97122) Move the validation of the base case of the IV analysis into `FlowGraphNaturalLoop::AnalyzeIteration`. Previously the validation for the base case was left up to the users: - Loop cloning tried to accomplish this by checking whether loop inversion had run, but this is not sufficient (dotnet#96623) as nothing guarantees the loop is dominated by the inverted test. Loop cloning also skipped the check entirely for GDV, leading to dotnet#95315. - Unrolling completely neglected to check the condition leading to dotnet#96591. Furthermore, unrolling made implicit assumptions that any `BBJ_COND` init block was an inverted test and downright removed the condition without any checks. This also led to another issue dotnet#97040 where unrolling could uncover new natural loops that had not been canonicalized. This change makes `FlowGraphNaturalLoop::AnalyzeIteration` try to prove that the loop invariant it returns is true in the base case as well as being maintained by the loop. If it cannot prove this then it fails. This fixes all the issues, but sadly uncovers that we were doing a lot of cloning in OSR methods without actually proving legality. We no longer clone in these cases, but we can look into what to do about them separately. Fix dotnet#95315 Fix dotnet#96591 Fix dotnet#96623 Fix dotnet#97040
The following program either hits AV or prints memory from a random heap location. We get rid of the bounds check in the loop in
Bar
.The problem is that we skip the following check when we have GDVs in the method, but then still end up optimizing bounds checks. That's only legal when this check passes.
runtime/src/coreclr/jit/loopcloning.cpp
Line 1893 in 9ca9580
The text was updated successfully, but these errors were encountered: