Skip to content
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

Add basic support for TYP_MASK constants #99743

Merged

Conversation

BruceForstall
Copy link
Member

This is to support fixing JitOptRepeat (#94250). I was seeing failures in a Tensor test where TYP_MASK generating instructions were getting CSE'd. When OptRepeat kicks in and runs VN over the new IR, it wants to create a "zero" value for the new CSE locals.

This change creates a TYP_MASK constant type, simdmask_t, like the pre-existing simd64_t, simd32_t, etc. simdmask_t is basically a simd8_t type, but with its own type. I expanded basically every place that generally handles simd64_t with simdmask_t support. This might be more than we currently need, but it seems to be a reasonable step towards making TYP_MASK more first-class. However, I didn't go so far as to support load/store of these constants, for example.

This is to support fixing JitOptRepeat (dotnet#94250).
I was seeing failures in a Tensor test where `TYP_MASK`
generating instructions were getting CSE'd. When OptRepeat kicks in
and runs VN over the new IR, it wants to create a "zero" value
for the new CSE locals.

This change creates a `TYP_MASK` constant type, `simdmask_t`, like the
pre-existing `simd64_t`, `simd32_t`, etc. `simdmask_t` is basically a
`simd8_t` type, but with its own type. I expanded basically every place
that generally handles `simd64_t` with `simdmask_t` support. This might be
more than we currently need, but it seems to be a reasonable step towards
making `TYP_MASK` more first-class. However, I didn't go so far as to
support load/store of these constants, for example.
@dotnet-issue-labeler dotnet-issue-labeler bot added the area-CodeGen-coreclr CLR JIT compiler in src/coreclr/src/jit and related components such as SuperPMI label Mar 14, 2024
Copy link
Contributor

Tagging subscribers to this area: @JulieLeeMSFT, @jakobbotsch
See info in area-owners.md if you want to be subscribed.

@BruceForstall
Copy link
Member Author

@jakobbotsch @tannergooding PTAL
cc @dotnet/jit-contrib

BruceForstall added a commit to BruceForstall/runtime that referenced this pull request Mar 14, 2024
This includes various fixes that are being separately PR'ed:
1. dotnet#99744:
Introduce HandleKindDataIsInvariant helper
2. dotnet#99743:
Add basic support for TYP_MASK constants
3. dotnet#99742:
Fix problem with scaling general loop blocks; add dumpers
4. dotnet#99740:
Add edge likelihood dumping; fix one edge likelihood update case

Also:
1. Add support for running JitOptRepeat under JitStress. This is still
over-written by JitOptRepeat being forced on at 4 iterations.

bool operator==(const simdmask_t& other) const
{
return (u64[0] == other.u64[0]);
Copy link
Member

Choose a reason for hiding this comment

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

This is UB in C++ if u64 is not the active union members, but I guess simd64_t has the same behavior...

Copy link
Member

Choose a reason for hiding this comment

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

It's UB per the spec. On the other hand, it's behavior that Clang, GCC, and MSVC all use themselves and which Windows, Linux, and MacOS all have various system level defines where similar is done. So it's something that's pretty heavily relied upon for all our targets

We could always switch to defining many different structs and using std::bit_cast or reinterpet_cast, but it doesn't buy us much in practice and the current definitions roughly match the official definitions used for __m128 and the related types used by Arm64

Copy link
Member

Choose a reason for hiding this comment

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

I would rather be safe about stuff like this. It won't be the first time we have had bugs caused by similar cases of UB (e.g. #67669), and tracking these down is very painful. Getters/setters that use memcpy can be introduced to support the other typed accesses in a well-defined way.

Copy link
Member

@jakobbotsch jakobbotsch left a comment

Choose a reason for hiding this comment

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

LGTM, but we ought to clean up the UB around these types.

@BruceForstall BruceForstall merged commit ca905a2 into dotnet:main Mar 14, 2024
124 of 129 checks passed
@BruceForstall BruceForstall deleted the AddBasicSimdMaskConstantSupport branch March 14, 2024 17:14
{
simdmask_t value = vnStore->ConstantValue<simdmask_t>(vnCns);

GenTreeVecCon* vecCon = gtNewVconNode(tree->TypeGet());
Copy link
Member

Choose a reason for hiding this comment

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

Is VecCon really the right type to use here? This isn't a vector constant and I worry about other places potentially getting this wrong as they expect the type to only be TYP_SIMD*.

I'd have expected that we instead represent this is a new type, since its a completely separate kind of constant.

Copy link
Member Author

Choose a reason for hiding this comment

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

Seems reasonable. I currently don't think we ever get here...

Comment on lines +12248 to +12249
printf("<0x%08x, 0x%08x>", vecCon->gtSimdVal.u32[0], vecCon->gtSimdVal.u32[1]);
break;
Copy link
Member

Choose a reason for hiding this comment

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

nit: I think this one would be better to display as a single 64-bit value. If we have a trivial way to format it as binary, that's all the better, as it is effectively a bitmask representing which elements are included or not.

Copy link
Member Author

Choose a reason for hiding this comment

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

Makes sense. I wasn't sure why simd8 displayed as 2x32 either.

Copy link
Member

Choose a reason for hiding this comment

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

For simd8, it's mostly for convenience. The most common data size used with vectors is 4-byte elements (float, int, and uint) so it makes the display more relevant for typical inputs while still being overall short.

Copy link
Member

@tannergooding tannergooding left a comment

Choose a reason for hiding this comment

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

LGTM overall

@github-actions github-actions bot locked and limited conversation to collaborators Apr 14, 2024
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
area-CodeGen-coreclr CLR JIT compiler in src/coreclr/src/jit and related components such as SuperPMI
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants