-
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
Fold always false type checks #99761
Conversation
If we have a program like: ```csharp class Never { } class Program { static void Main() { Test(null); } [MethodImpl(MethodImplOptions.NoInlining)] static void Test(object o) { if (o is Never) Console.WriteLine("Hello!"); if (o.GetType() == typeof(Never)) Console.WriteLine("Hello!"); } } ``` We know these checks are never going to be true thanks to the whole program view. Fold these to `false`.
Closes #97601 I presume? |
/azp run runtime-nativeaot-outerloop |
Azure Pipelines successfully started running 1 pipeline(s). |
Does this optimization kick in for interfaces? If so, can we add a test around IDynamicInterfaceCastable to ensure that we don't fold casts to types that have the DynamicCastableImplementationAttribute or interfaces they implement (as its possible for no types to statically implement these interfaces but casts to them to still succeed)? |
@EgorBo @jakobbotsch either of your could psychically debug the reason for hitting a |
No good guess from my side without the jitdump, I'm afraid. |
It does kick in for interfaces. I cannot come up with a targeted test for this in regards to this optimization. I tried writing one, and ended up with exactly the same thing we already test for IDynamicInterfaceCastable. |
hm.. I tried to repro it locally on win-x64 using the CI steps and it succesfully completed on your branch, let's see what your new commit will show |
Yeah, the same happened to me. I hope we don't have nondeterminism :( |
/azp run runtime-nativeaot-outerloop |
Azure Pipelines successfully started running 1 pipeline(s). |
@MichalStrehovsky I suspect you need to change return value in |
Good point. I'll let the nativeaot outerloop finish and change it tomorrow together with the JitInterface guid. |
It's not nondeterministic - the assert is hitting in main. It very likely broke sometime after 136b100 because that's where my branch was when neither me nor Egor could repro the assert locally. I'll grab a jitdump and file is as a bug, it's unrelated to this PR. |
This is ready for review. @dotnet/ilc-contrib could someone have a look at the ILC part? @EgorBo could you have a look at the JIT part? |
/azp run runtime-nativeaot-outerloop |
Azure Pipelines successfully started running 1 pipeline(s). |
Sigh, I think I have a fix for the SPMI failures but want to wait until nativeaot outerloop finishes. |
src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/ILScanner.cs
Outdated
Show resolved
Hide resolved
|
||
#if !READYTORUN | ||
if (result == TypeCompareState.May | ||
&& (canNeverHaveInstanceOfSubclassOf(type1) || canNeverHaveInstanceOfSubclassOf(type2))) |
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.
Can compareTypesForEquality
operate on types that are not allocated, but otherwise exist in the system? This change seems to make hidden assumptions about how this API is used by the JIT.
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'll think about this some more. Worst case I'll just pull this part out. I already used up my JitInterface update quota for the month.
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.
It would not be a problem today but it adds a hidden assumption. Removed it. I'll measure how much it impacts things and whether we want to track that as a separate bug.
I know the typeof optimization would help CsWinRT but dont' have numbers.
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 can fix that by adding a bool
flag that says the query is specifically for System.Type
operator==/!=
and only execute this logic for that.
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.
It would not be a problem today but it adds a hidden assumption. Removed it. I'll measure how much it impacts things and whether we want to track that as a separate bug.
I removed the wrong part. Fixed it in the latest iteration.
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 JIT part specifically LGTM. There is also one use of getExactClasses
in the helperexpansion phase, but that one doesn't need any treatment.
Co-authored-by: Jan Kotas <jkotas@microsoft.com>
@@ -2248,14 +2248,42 @@ private void getFieldInfo(ref CORINFO_RESOLVED_TOKEN pResolvedToken, CORINFO_MET | |||
// and STS::AccessCheck::CanAccess. | |||
} | |||
|
|||
private bool canNeverHaveInstanceOfSubclassOf(TypeDesc type) |
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.
private bool canNeverHaveInstanceOfSubclassOf(TypeDesc type) | |
private bool CanNeverHaveInstanceOfSubclassOf(TypeDesc type) |
Nit: We seem to use regular naming convention in this file for methods that are not directly exposed on JIT/EE interface
public override bool CanReferenceConstructedMethodTable(TypeDesc type) | ||
=> _constructedMethodTables.Contains(type); | ||
|
||
public override bool CanTypeOrCanonicalFormOfTypeBeAllocated(TypeDesc type) |
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.
These two methods do very similar things, but they have very different names. Should these two methods have similar names, e.g. CanReferenceConstructedMethodTable
+ CanReferenceConstructedTypeOrCanonicalFormOfType
; CanTypeBeAllocated
+ CanTypeOrCanonicalFormOfTypeBeAllocated
?
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.
LGTM otherwise. Thanks!
/azp run runtime-nativeaot-outerloop |
Azure Pipelines successfully started running 1 pipeline(s). |
Fixes #97601
If we have a program like:
We know these checks are never going to be true thanks to the whole program view. Fold these to
false
.