-
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
Optimize typeof(T1).IsAssignableFrom(typeof(T2)) #1195
Conversation
Didn't expect this (current behavior): typeof(SimpleEnum_int).IsAssignableFrom(typeof(SimpleEnum_uint)); // False
typeof(SimpleEnum_int[]).IsAssignableFrom(typeof(SimpleEnum_uint[])); // True |
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.
Would also be interesting to run diffs, and perhaps see what percentage of IsAssignableFrom
get optimized.
|
||
if (typeTo->IsCall() && typeFrom->IsCall()) | ||
{ | ||
// make sure both arguments are `typeof()` |
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.
Do we know what typical uses of IsAssignableFrom
look like? Are they usually via typeof
or does GetType
show up with any frequency?
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.
Good point, I started with typeof()+typeof() but it seems it makes sense to handle more cases (e.g. a.GetType().IsAssignableFrom(b.GetType())
) will analyze usages in popular projects.
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.
This is the scenario I was thinking about
https://github.com/dotnet/coreclr/issues/2591#issuecomment-170209816
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.
Currently this code handles two cases:
bool a = typeof(T1).IsAssignableFrom(typeof(T2));
bool a = variable.GetType().IsAssignableFrom(typeof(T2)); // for ValueType variables
It handles COMObjects by giving up. It can do better than that.
It may be a good idea to add an extra argument to |
@EgorBo any update on this? |
…edfrom # Conflicts: # src/coreclr/tests/src/JIT/Intrinsics/TypeIntrinsics.cs # src/libraries/System.Private.CoreLib/src/System/Type.Helpers.cs
@AndyAyersMS well, it already works. It just doesn't optimize |
We can always come back and add that part later. Can you run diffs? |
@AndyAyersMS jit-diff: (-f --pmi)
The diff comes from: EnumerableRowCollection.GetLinqDataView ArraySortHelper.CreateArraySortHelper I think I saw some usages in aspnetcore and ef but not sure. |
Those look like valid diffs, but I would guess PMI is asking for some unusual instantiations and we may not see this optimization fire much in our normal testing. Can you add in test cases for the primitive typed array assignments? Something like: IsTrue(typeof(byte[]).IsAssignableFrom(typeof(sbyte[])));
IsTrue(typeof(sbyte[]).IsAssignableFrom(typeof(byte[])));
IsTrue(typeof(short[]).IsAssignableFrom(typeof(ushort[])));
IsTrue(typeof(ushort[]).IsAssignableFrom(typeof(short[])));
IsTrue(typeof(int[]).IsAssignableFrom(typeof(uint[])));
IsTrue(typeof(uint[]).IsAssignableFrom(typeof(int[])));
IsTrue(typeof(long[]).IsAssignableFrom(typeof(ulong[])));
IsTrue(typeof(ulong[]).IsAssignableFrom(typeof(long[])));
IsFalse(typeof(int[]).IsAssignableFrom(typeof(byte[])));
IsFalse(typeof(int[]).IsAssignableFrom(typeof(sbyte[])));
IsFalse(typeof(int[]).IsAssignableFrom(typeof(short[])));
IsFalse(typeof(int[]).IsAssignableFrom(typeof(ushort[])));
IsFalse(typeof(int[]).IsAssignableFrom(typeof(float[])));
IsFalse(typeof(int[]).IsAssignableFrom(typeof(double[])));
IsFalse(typeof(long[]).IsAssignableFrom(typeof(double[]))); |
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.
This looks good.
Thanks!
This was merged with test failures that were most likely introduced by this change. Reverting in #31643 |
Sorry about that. For some reason I thought those were pre-existing failures. |
Failing case is asking about assigning runtime/src/coreclr/src/vm/jitinterface.cpp Lines 4502 to 4510 in 6000488
Existing callers avoid drawing the wrong conclusions from this; they either have more constrained inputs or are more cautious with Fix is either to refine the clause or just drop it all together. Will investigate. |
We weren't careful enough with `__Canon` in some cases, which lead to unsafely returning `MustNot` when the cast outcome was not determined at jit time. Add an extra check, update comments, and add some test cases. Addresses the failures seen in dotnet#1195 (which was reverted).
We weren't careful enough with `__Canon` in some cases, which lead to unsafely returning `MustNot` when the cast outcome was not determined at jit time. Add an extra check, update comments, and add some test cases. Addresses the failures seen in #1195 (which was reverted).
@EgorBo can you resubmit this PR? |
Ah, looks like Jan already did this in #31705. |
Optimize
typeof(T1).IsAssignableFrom(typeof(T2))
totrue/false
. E.g.compareTypesForCast seems does everything I need for
IsAssignableFrom
: handlesCOMObject
s,__Canon
, covariance/contravariance, etc. The only thing - it gives up onNullable<>
.Contributes to https://github.com/dotnet/coreclr/issues/2591