Skip to content

Constants as arguments don't really work #1011

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

Closed
raphaelcohn opened this issue Feb 19, 2021 · 7 comments
Closed

Constants as arguments don't really work #1011

raphaelcohn opened this issue Feb 19, 2021 · 7 comments

Comments

@raphaelcohn
Copy link

I'm adding some wrappers around some of the AVX512 intrinsics to make them a bit more useful. In doing so, I found that there's no real way to propagate that an intrinsic with an argument marked as constant by the [rustc_args_required_const] attribute is constant in any wrapper.

This seems to also have been an issue in implementing the Altivec intrinsics, eg rust-lang/rust#61180. It's also a pain when adding one's own implementation of an intrinsic that needs to take a constant argument, eg _kshiftli_mask8(). One can decorate the function, but it then needs nightly to work (but it needs it anyway to use additional target features like avx512bw to get access to the __mmask8 type).

Is there any possibility this working group could push a way of passing arguments as constants as part of const generics into wider Rust? At the moment, I can workaround this problem with the world's worst looking match statement...

@Lokathor
Copy link
Contributor

you'll have to use const generics.

in fact, it's hoped that we can move all of stdarch to const generics at some point (but it's a fair way off).

@Amanieu
Copy link
Member

Amanieu commented Feb 19, 2021

At the moment the only way is to use one of the constify_* macros which expand to huge match statements. I am working on converting all these functions to use const generics instead but this will likely take a while since it requires compiler changes as well.

@raphaelcohn
Copy link
Author

raphaelcohn commented Feb 20, 2021

@Amanieu Does the compiler change involve being able to do const math on a const generic?

For example, I've designed a wrapper function _mm512_extract_epi32<const index: i32>(a: __m512i) -> i32, and I'd like to use it from a function that works on epi16. Before making the call, it needs to do index / 2, eg _mm512_extract_epi32<index / 2>(a). I believe that's currently impossible in nightly rust (but am happy to be corrected).

To make things a bit clearer:-

#[inline(always)]
pub unsafe fn _mm512_extract_epi32<const index: i32>(a: __m512i) -> i32
{
	_mm512_cvtsi512_si32(_mm512_alignr_epi32(a, a, index))
}

#[inline(always)]
pub unsafe fn _mm512_extract_epi16<const index: i32>(a: __m512i) -> i32
{
	let shift = if (index % 2) == 0
	{
		0
	}
	else
	{
		16
	};
	
	(_mm512_extract_epi32::<index / 2>(a) >> shift) & 0xFFFF
}

@Amanieu
Copy link
Member

Amanieu commented Feb 20, 2021

Unfortunately that's not possible due to limitations on const generics. There are plans for const generics to allow that in the future though.

@Lokathor
Copy link
Contributor

In the mean time you can sometimes use macros to get a similar situation.

@raphaelcohn
Copy link
Author

@Lokathor Thank you. That's exactly what I did yesterday. I do wonder about how llvm will optimize what I've done, but I wont look at that until I'm happy with the design of what I'm trying to achieve (for interest: iterating over a bit set trying to find contiguous ranges of bits with different alignments). Depending how things end up I might end up writing everything using assembler, in any event*.

@Amanieu Thank you. That plans going to need us to push back on the compiler currently preventing the definition of const items in a method that depend on a generic parameter (viz const X: usize = Self::Y where Self might be impl<A> - this has wider scope and has been a bug bear of mine for a long time, not least because adding a generic parameter when changing an impl causes a cascade of issues.

I'm beginning to worry that const generics are lacking a proper high-level usage plan - they're coming in drips and drabs, which, from the point of view of gaining experience, is good for their designers but they do need to be driven by real-world use, too. That could be seen as unfair from those on the inside, but it's intended as expression of a worry, not an attack. Everytime I've tried to nudge a point into the conversation, it's been effectively ignored, and the responses here reinforce that view.

* this is because intrinsics struggle to express concepts like the result is in the x86_64 CF flag and do not allow (by Intel's definition) access to the unaligned memory load variants (eg of popcnt). LLVM is sometimes capable of optimising these situations, but given the point of these sorts of things is efficiency in the first place (and switching in and out of AVX512 is expensive), sometimes one needs to take charge.

@raphaelcohn
Copy link
Author

Closing as it seems there's not much more to say.

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

No branches or pull requests

3 participants