Skip to content
This repository has been archived by the owner on Jan 23, 2023. It is now read-only.

Fix SIMD intrinsics handling in crossgen2 #27853

Merged
merged 2 commits into from
Nov 13, 2019

Conversation

janvorli
Copy link
Member

Crossgen2 was compiling methods that call SIMD intrinsics
(System.Numerics.Vector). This is not correct, as the size of the
vector is a runtime specific detail - e.g. when running on devices
without SSE2 support, the size is 4 and when running on devices with
SSE2 support, the size is 8.
So methods that call SIMD intrinsics should not be crossgened.
This fixes runtime errors in 6 coreclr pri 0 tests.

Crossgen2 was compiling methods that call SIMD intrinsics
(System.Numerics.Vector<T>). This is not correct, as the size of the
vector is a runtime specific detail - e.g. when running on devices
without SSE2 support, the size is 4 and when running on devices with
SSE2 support, the size is 8.
This fixes runtime errors in 6 coreclr pri 0 tests.
@janvorli janvorli added this to the 5.0 milestone Nov 13, 2019
@janvorli janvorli requested a review from trylek November 13, 2019 12:26
@janvorli janvorli self-assigned this Nov 13, 2019
Copy link
Member

@trylek trylek left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM. At some point we should probably extract the check somewhere as we already have it in 3 different places in Crossgen2 but it can easily wait for a separate change.

@@ -697,6 +697,13 @@ private uint getMethodAttribsInternal(MethodDesc method)
result |= CorInfoFlag.CORINFO_FLG_FINAL;
}

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

#if READYTORUN ?

Create a IsVectorOfT method and use it at all places where we were
previously checking the namespace and type name of Vector<T>
@MichalStrehovsky
Copy link
Member

Is this a regression? GetLayoutAlgorithmForType should make sure that we never come up with a valid layout for these types (the size will never be 4 or 8, as the description alludes to). When jit asks for the layout, the type system says the size is indeterminate, and we end up throwing RequiresRuntimeJit.

@janvorli
Copy link
Member Author

I don't think it is a regression, the related tests (e.g JIT/SIMD/VectorDot_r) were failing for as long as I remember.

@janvorli
Copy link
Member Author

But let me check why the stuff you've mentioned doesn't kick in

@janvorli
Copy link
Member Author

@MichalStrehovsky where would you expect the exception to be thrown? I've set a breakpoint at the GetLayoutAlgorithmForType in the branch that returns the layout for the Vector and after hitting it, I've stepped out of that method until I've reached the JIT code. I haven't seen any exception throwing around the code path.

@MichalStrehovsky
Copy link
Member

Tomáš can probably point you to it better - I'm on the phone only these days. Look for IsIndeterminate checks. RyuJIT should not be able to do anything that requires the size or layout of these.

@janvorli
Copy link
Member Author

Actually, maybe the case the tests were hitting is special and different. The Main method contains the following lines:

        if (VectorDotTest<float>.VectorDot(3f, 2f, 6f * Vector<float>.Count) != Pass) returnVal = Fail;
        if (VectorDotTest<double>.VectorDot(3d, 2d, 6d * Vector<double>.Count) != Pass) returnVal = Fail;
        if (VectorDotTest<int>.VectorDot(3, 2, 6 * Vector<int>.Count) != Pass) returnVal = Fail;
        if (VectorDotTest<long>.VectorDot(3, 2, (long)(6 * Vector<long>.Count)) != Pass) returnVal = Fail;

So only the Count method is being called, which is a static method and also an intrinsic. So maybe computing 6f * Vector<float>.Count etc doesn't involve computing the layout in the Main function.

@janvorli
Copy link
Member Author

janvorli commented Nov 13, 2019

I can see that even before my change, we were not compiling e.g. the VectorDotTest method with the following message:
Info: Method [VectorDot_r]VectorTest+VectorDotTest'1<float32>.VectorDot(float32,float32,float32) was not compiled because [S.P.CoreLib]System.Numerics.Vector'1<float32> requires runtime JIT
So it seems that one is hitting the code path you've mentioned as it actually creates instance of the type.

@@ -106,5 +106,10 @@ public static bool IsVectorType(DefType type)
type.Name == "Vector128`1" ||
type.Name == "Vector256`1");
}

public static bool IsVectorOfTType(DefType type)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For #23899, I had added this as InteropTypes.IsSystemNumericsVectorT, as that appears to be where a fair number of the other IsType checks live

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am not sure which location is better. Your methods are also a bit different as they require the TypeSystemContext parameter. So maybe keeping both versions makes sense. There was already the IsVectorType here, so adding the IsVectorOfTypeT to the same place felt ok.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

InteropTypes only handles types interesting for interop (as the name implies). Up until Tanner's change it was exclusively used in generating/figuring out marshalling. Crossgen2 doesn't have a central MscorlibBinder equivalent (as it exists in CoreCLR).

We place these as close to the usage as possible. Centralized locations tend to end up with orphaned entries.

@janvorli janvorli merged commit 0f9814c into dotnet:master Nov 13, 2019
@janvorli janvorli deleted the fix-simd-crossgen2 branch November 13, 2019 19:41
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants