Minimal acceptable integer size - i32min, u8min, etc

Are you suggesting having the compiler deduce the minimum sized integer for an integral variable/field? I don't think it's possible because the compiler cannot generally prove that overflow won't happen in compile time.

What you can do is to make your numerical types generic by using crates like num-traits or alga. It's ugly and hard to work with, but doable.

Another reason why C's [u]int_fastN_t types never got any traction was that they got baked into ABIs, making it impossible to change them to account for changes in subsequent CPU generations.

Because of that, I would say that if Rust adds these at all, they should not be allowed to appear in pub types and function signatures (there's an argument for making this a deny-default warning rather than a no-recourse hard error, I suppose).

2 Likes

Thanks Zack...

I'm a bit confused. Doesn't C and C++ have several ABI's depending on the 32 vs 64 bit architecture vs Itanium architecture and Windows vs Unix, etc?

The idea behind this proposal is that the programmer explicitly gives the compiler the freedom to extend the size of an integer if it's faster for that target.

It would be great to think that there would be a way to implement it so it could grow to efficiently support 128, or even 256 bit data-path integers in future ABI's if/when that would be faster.

All of this said, it does seem like the potential gains are enough to justify the added complications.

Given the increasing criticality of cache locality, in what world will someone in the future specify a processor architecture that does not frequently have to deal with small units of data? Only in such a world would it be reasonable to fail to implement extraction of a smaller value from memory into a larger datapath without incurring extra delay for the data fetch.

It may well be the case that some currently-available legacy processor implementations do make such a tradeoff. If that is the case, it's almost certain that those implementations either will be superceded or will simply be consigned to the scrapheap of history.

If this proposal is really about wrapping vs. overflow issues for such small-unit-of-data values, then that is the problem which should be addressed. If it really about writing code that is optimized for specific legacy processor implementations of a given architecture, but not for other processor implementations of that architecture, then a general-purpose solution in the Rust language is neither needed or advisable.

I apologize... that was a typo...

All of this said, it does NOT seem like the potential gains are enough to justify the added complications.

The issue I was talking about is with a single architecture with many CPU generations. They all use the same ABI but the tradeoffs involved in choosing the sizes for the "fast" types change from generation to generation.

For a real-world example, the first generation of Alpha CPUs did not have 8-bit or 16-bit load or store instructions (maybe not 32-bit either? I'm not sure and I don't have that architecture manual anymore). To write an 8-bit quantity to RAM you had to do a read-modify-write on the surrounding 32-bit (possibly 64-bit) word. int_fast8_t tuned for that CPU would be 32 (possibly 64) bits wide. But the next generation added those instructions (the BWX extension), so when compiling for that generation it would be desirable to use an 8-bit int_fast8_t to save memory ... but the size of int_fast8_t could not be changed without breaking the ABI.

1 Like

It seems like the ABI would need to be implemented so it could efficiently mutate as required, however, that sounds like it would just add another layer of complexity with questionable benefits. The smaller 8 and 16 bit processors probably would likely benefit the most from this, but that by no way means it's worth implementing, especially at this point in time.

Would it be worth adding u8min, i8min, etc to the reserved word list at this time?

Now that editions exist, there is no reason to reserve keywords “preemptively” any more. This just means it’d take a long time to stabilise, if we ever get to the point of agreeing there’s anything worth adding to the stable language (although for this thread, it seems pretty clear that there isn’t).

1 Like

Given that even u8 isn't a keyword, definitely not.

https://github.com/rust-lang/rust/blob/master/src/test/ui/weird-exprs.rs#L86-L106

5 Likes

Using different-than-register-size values does hurt performance in some cases. In other words, using u8 or u16 can actually can have worse performance than doing an "identical" series of ops in u32. The compiler has to insert additional masking instructions in between the real ops to keep values in range for their type.

Also, for SIMD purposes, the instruction coverage on x86/x64 is an absolute madhouse and there is very simply no assurance at all that any given int width is better or worse at doing some series of ops. sse and friends are practically trying to make you suffer compared to the consistency of neon.

All that said, I don't even care about any of that. If someone needs that much attention to detail for a bit of code on their device, they'll custom adapt it to that particular device.

1 Like

This topic was automatically closed 90 days after the last reply. New replies are no longer allowed.