Skip to content

[ESIMD][NFC] Remove constexpr from simd class ctors #3944

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

Merged
merged 2 commits into from
Jun 19, 2021

Conversation

DenisBakhvalov
Copy link
Contributor

No description provided.

kbobrovs
kbobrovs previously approved these changes Jun 17, 2021
Copy link
Contributor

@kbobrovs kbobrovs left a comment

Choose a reason for hiding this comment

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

@rolandschulz, please take a look as well.

@vladimirlaz vladimirlaz requested a review from rolandschulz June 17, 2021 10:54
Comment on lines 51 to 56
template <typename SrcTy> simd(const simd<SrcTy, N> &other) {
if constexpr (std::is_same<SrcTy, Ty>::value)
set(other.data());
else
set(__builtin_convertvector(other.data(), detail::vector_type_t<Ty, N>));
}
Copy link
Contributor

Choose a reason for hiding this comment

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

Not something you changed as part of this PR, but something I hope can be fixed (maybe as part of a different PR).

This constructor uses bad practice of how to deal with a templated constructor which may or may not convert. The problem with this way is that it messes with traits like is_trivially_constructible. Rather the converting and non-converting should be different overloads. This should be done as:

Suggested change
template <typename SrcTy> simd(const simd<SrcTy, N> &other) {
if constexpr (std::is_same<SrcTy, Ty>::value)
set(other.data());
else
set(__builtin_convertvector(other.data(), detail::vector_type_t<Ty, N>));
}
simd(const simd&) = default;
template <typename SrcTy> simd(const simd<SrcTy, N> &other) {
set(__builtin_convertvector(other.data(), detail::vector_type_t<Ty, N>));
}

The non-templated is picked over the templated and will therefore be used in the non-converting case. And because it is defaulted, things like traits work correctly.

else
set(__builtin_convertvector(other.data(), detail::vector_type_t<Ty, N>));
simd() = default;
simd(const simd &other) { set(other.data()); }
Copy link
Contributor

Choose a reason for hiding this comment

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

@rolandschulz suggested to make it default too, which makes sense unless there are unforeseen complications like bad code gen. Are there any? If yes, please add a comment. Otherwise, =default should work.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yes, but set is calling __esimd_vstore for device compilation. Let me double-check.

Copy link
Contributor

Choose a reason for hiding this comment

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

@rolandschulz, @DenisBakhvalov - this patch luckily fixes a real problem. constexpr leads to creating a constant global of simd wrapper type, e.g:

@vc = private unnamed_addr addrspace(1) constant %"esimd::simd" \{ { <16 x i16> <i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1> }, align 32
...
call void @llvm.memcpy.p0i8.p0i8.i64(i8* %0, i8* bitcast (%class.simd* @vc to i8*), i64 32, i1 false)

which is not handled properly by the BE. W/o {{constexpr}}, the constant becomes an immediate of the primitive vector type, and memcpy is replaced with store. And this is handled by the BE correctly.

Copy link
Contributor

@kbobrovs kbobrovs Jun 19, 2021

Choose a reason for hiding this comment

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

I checked on a simplified sample - simd(const simd &other) = default will lead to a memcpy compared to __esimd_vstore (as Denis mentions above) done today, which may cause CG problems. Since keeping it non-default does not change compatibility, we can add =default later if we find a proper way. @rolandschulz, I'm approving and merging, if you still have concerns - we can discuss and fix as a separate PR as you suggest above.

Copy link
Contributor

Choose a reason for hiding this comment

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

It seems like a good temporary solution. Note that it isn't trivial if is isn't =default. And by not being trivial it can't be used for those things limited to trivial types (e.g. bit_cast). In general it is also an ABI break to change whether a type is trivial because some ABIs CC is different for trivial vs non-trivial types. Not sure whether any of this is a concern here.

@kbobrovs kbobrovs merged commit eb6d098 into intel:sycl Jun 19, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants