-
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
Vector.As<TFrom, TTo> #47150
Vector.As<TFrom, TTo> #47150
Conversation
Note regarding the This serves as a reminder for when your PR is modifying a ref *.cs file and adding/modifying public APIs, to please make sure the API implementation in the src *.cs file is documented with triple slash comments, so the PR reviewers can sign off that change. |
Tagging subscribers to this area: @tannergooding, @pgovind Issue DetailsNot sure how to test it, because all the Questions:
|
IMHO yes, with |
I've tried JITDump but I remember I didn't get result for generic methods. (Or just generic for reference types) |
No, unfortunately not. Issues tend to crop up when you have things have their address taken in one way or another. This method will have to either be intrinsified (probably better in terms of Jit throughput and potentially CQ too) or use the existing
For such simple methods that will be inlined unless you're out of budget, I'd use Disasmo (optionally with the dump option set). I'd write two methods that use |
ThrowHelper.ThrowForUnsupportedVectorBaseType<TFrom>(); | ||
ThrowHelper.ThrowForUnsupportedVectorBaseType<TTo>(); | ||
|
||
Debug.Assert(Vector<TFrom>.Count * Unsafe.SizeOf<TFrom>() == Vector<TTo>.Count * Unsafe.SizeOf<TTo>()); |
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 don' think this assert is necessary. If the size, in bytes, of Vector<T>
vs Vector<U>
varies then we have much bigger problems in the JIT 😄
src/libraries/System.Private.CoreLib/src/System/Numerics/Vector.cs
Outdated
Show resolved
Hide resolved
Could you update the top post with a comment similar to: "This resolves #508"?
I'd recommend just adding a few tests that validate converting |
I think it was missed in API review, so I'll see if I can bring it up quickly today, but I think this should be an extension method like it is for |
Having this be an extension method was approved in API review. |
Changes look good to me. It would just be good to get some basic tests covering a successful case and an error with an invalid type for |
This still needs a test for the positive case, it should be mergeable after that is added. |
Does it need to evaluate the content of vector? Or just 0 is fine? |
Ideally it would test it with an actual value to assert there aren't any bugs or accidental conversions (now or in the future) and that it is actually a bit-cast. var x = new Vector<int>(new int[] { 1, 2, 3, 4, 5, 6, 7, 8 });
var y = x.As<int, float>();
var xBytes = new byte[Vector<T>.Count * 4];
x.CopyTo(xBytes);
var yBytes = new byte[Vector<T>.Count * 4];
y.CopyTo(yBytes);
AssertEqual(xBytes, yBytes); And repeat for a few cases. The ones that are likely most interesting to cover are |
@echesakovMSFT, could you give the HWIntrinsic changes a quick secondary review? |
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
src/libraries/System.Numerics.Vectors/tests/GenericVectorUnsupportedTests.cs
Show resolved
Hide resolved
@huoyaoyuan, I'm investigating the alpine failure. I'm also going to quickly close and reopen the PR so the CI jobs pick up latest master and therefore the System.Linq.Expressions test fix |
@@ -405,6 +405,22 @@ GenTree* Compiler::impSimdAsHWIntrinsicSpecial(NamedIntrinsic intrinsic, | |||
} | |||
#endif // TARGET_X86 | |||
|
|||
#if defined(TARGET_XARCH) |
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 issue is that this is actually under a #if defined(TARGET_XARCH)
already (defined on L385) and so this is never hit on arm64.
The simplest fix is to remove the #if defined(TARGET_XARCH)
here and then copy the following logic into the #elif defined(TARGET_ARM64)
on L446
switch (intrinsic)
{
case NI_VectorT128_As:
{
unsigned retSimdSize;
var_types retBaseType = getBaseTypeAndSizeOfSIMDType(sig->retTypeSigClass, &retSimdSize);
if (!varTypeIsArithmetic(retBaseType) || (retSimdSize == 0))
{
// We get here if the return type is an unsupported type
return nullptr;
}
break;
}
default:
{
// Most intrinsics have some path that works even if only AdvSimd is available
break;
}
}
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.
Got it. I'll look at the structure and find the opportunity to share code.
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 reordered the ifdef block into two. One for general instruction set availability, one for special logic for each instruction. Is this sure?
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 looks correct. I think this will be good to merge if CI passes
Thanks for the PR @huoyaoyuan! |
Closes #508
Not sure how to test it, because all the
AsVectorXXX
are not tested.Questions:
Can we tread
Unsafe.As
to be reliably optimized by JIT and reduce the requirement for[Intrinsic]
?What's the simplest way to see the JIT and inlining decision on methods in CoreLib? jitdump or disasmo?