mailing list of musl libc
 help / color / mirror / code / Atom feed
* Further limits/stdint issues
@ 2014-12-03  1:02 Rich Felker
  2014-12-03  4:10 ` Glenn Weinberg
  2014-12-03 10:38 ` Jens Gustedt
  0 siblings, 2 replies; 7+ messages in thread
From: Rich Felker @ 2014-12-03  1:02 UTC (permalink / raw)
  To: musl

Based on Jens' proposed patches, I took another look at things in
limits.h and stdint.h and here are some things I noticed that should
perhaps be changed:

LLONG_MAX is needlessly in bits/limits.h despite widespread
assumptions that long long is 64-bit.

LONG_BIT and LONG_MAX in bits/limits.h are redundant; either can be
derived from the other.

In general I try to avoid #ifdefs for feature tests in bits headers,
so perhaps we could make bits/limits.h just define __PAGE_SIZE and
__LONG_BIT and leave it to the top-level limits.h to expose these as
PAGE_SIZE and LONG_BIT according to feature tests and to derive
LONG_MAX from __LONG_BIT.

UINT32_MAX and UINT64_MAX lack the U suffix. This probably does not
matter for UINT64_MAX since the value does not fit in intmax_t, but
for UINT32_MAX, it will be treated as a signed value at the
preprocessor level without the U suffix.

The fast16/fast32 types and limits are still in bits/stdint.h despite
not varying between archs. Removing those would make bits/stdint.h
tiny/trivial. Aside from PAGE_SIZE, both bits/limits.h and
bits/stdint.h would essentially have no information except
"long/pointer size" and maybe we could even eventually eliminate them
by having a global idea of "wordsize".

As noted in the other thread, wint_t should be a shared type, not
arch-specific, and WINT_MIN needs to be unsigned.

WCHAR_MIN could be defined slightly simpler (just L'\0') in the
unsigned case.

It may be possible to eliminate the #if UINTPTR_MAX == UINT64_MAX
check for defining INT64_C() etc. using an expression that yields the
right type naturally (e.g. (c)+0*0x7fffffffffffffff etc.) but I'm not
sure if that's an improvement.

Rich


^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: Further limits/stdint issues
  2014-12-03  1:02 Further limits/stdint issues Rich Felker
@ 2014-12-03  4:10 ` Glenn Weinberg
  2014-12-03  5:03   ` Rich Felker
  2014-12-03 10:38 ` Jens Gustedt
  1 sibling, 1 reply; 7+ messages in thread
From: Glenn Weinberg @ 2014-12-03  4:10 UTC (permalink / raw)
  To: musl


> On Dec 2, 2014, at 8:02 PM, Rich Felker <dalias@libc.org> wrote:
> 
> The fast16/fast32 types and limits are still in bits/stdint.h despite
> not varying between archs. Removing those would make bits/stdint.h
> tiny/trivial. Aside from PAGE_SIZE, both bits/limits.h and
> bits/stdint.h would essentially have no information except
> "long/pointer size" and maybe we could even eventually eliminate them
> by having a global idea of "wordsize".

I don't think it's safe to make such assumptions.  Our architecture is native 64-bit, so we define all the fast types as 64-bit.

	Regards,

	Glenn
--
Glenn Weinberg
Vice President, Product
Cognitive Electronics, Inc.
www.cognitive-electronics.com
glenn@cognitive-electronics.com





^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: Further limits/stdint issues
  2014-12-03  4:10 ` Glenn Weinberg
@ 2014-12-03  5:03   ` Rich Felker
  2014-12-03 16:34     ` Glenn Weinberg
  0 siblings, 1 reply; 7+ messages in thread
From: Rich Felker @ 2014-12-03  5:03 UTC (permalink / raw)
  To: Glenn Weinberg; +Cc: musl

On Tue, Dec 02, 2014 at 11:10:58PM -0500, Glenn Weinberg wrote:
> 
> > On Dec 2, 2014, at 8:02 PM, Rich Felker <dalias@libc.org> wrote:
> > 
> > The fast16/fast32 types and limits are still in bits/stdint.h despite
> > not varying between archs. Removing those would make bits/stdint.h
> > tiny/trivial. Aside from PAGE_SIZE, both bits/limits.h and
> > bits/stdint.h would essentially have no information except
> > "long/pointer size" and maybe we could even eventually eliminate them
> > by having a global idea of "wordsize".
> 
> I don't think it's safe to make such assumptions. Our architecture
> is native 64-bit, so we define all the fast types as 64-bit.

Could you elaborate on your motivations? There's no inherent reason
that the fast types should be defined as 64-bit just because the
native word size is 64-bit, and there are lots of reasons against it.

Lots of people misinterpret the "fast" types as "fast unit for moving
data", i.e. in the sense of "given N bytes of data to move, what's the
fastest type to move it as?" This is not the meaning the C language
assigns to them; in fact this sense is rather meaningless since C does
not permit the aliasing that would be needed to move data as any type
other than its actual type or a character type.

Rather, "fast" is a matter of "given N values, possibly with just N=1,
what type should be used to optimize operations on the value(s)?" In
this sense, it's almost always best for the fast type to be the same
as the least type, unless the least type incurs some heavy penalty
(e.g. a machine that can't do 16-bit loads and stores and has to
emulate them with byte loads/stores or atomic cas on larger words).

As an example, take x86_64, where glibc made their [u]int_fast32_t
types 64-bit. Addition and subtraction are the same speed for 32- or
64-bit operations, and perhaps multiplication is too (?), but division
is significantly slower for 64-bit, and perhaps more importantly,
using 64-bit storage doubles the number of cache lines you use and
effectively halves the size of your cache.

If you have a good reason that the fast types should be 64-bit on some
archs, I'd like to hear it. I'm open to listening to alternative views
on this.

Rich


^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: Further limits/stdint issues
  2014-12-03  1:02 Further limits/stdint issues Rich Felker
  2014-12-03  4:10 ` Glenn Weinberg
@ 2014-12-03 10:38 ` Jens Gustedt
  1 sibling, 0 replies; 7+ messages in thread
From: Jens Gustedt @ 2014-12-03 10:38 UTC (permalink / raw)
  To: musl

[-- Attachment #1: Type: text/plain, Size: 1082 bytes --]

Am Dienstag, den 02.12.2014, 20:02 -0500 schrieb Rich Felker:
> UINT32_MAX and UINT64_MAX lack the U suffix. This probably does not
> matter for UINT64_MAX since the value does not fit in intmax_t, but
> for UINT32_MAX, it will be treated as a signed value at the
> preprocessor level without the U suffix.

right, so I should add such a signed/unsigned preprocessor test to my
test program. (makes it even more ugly)

> It may be possible to eliminate the #if UINTPTR_MAX == UINT64_MAX
> check for defining INT64_C() etc. using an expression that yields the
> right type naturally (e.g. (c)+0*0x7fffffffffffffff etc.) but I'm not
> sure if that's an improvement.

With the patch I proposed, there is no conditional compilation of that
kind anymore.

Jens


-- 
:: INRIA Nancy Grand Est ::: AlGorille ::: ICube/ICPS :::
:: ::::::::::::::: office Strasbourg : +33 368854536   ::
:: :::::::::::::::::::::: gsm France : +33 651400183   ::
:: ::::::::::::::: gsm international : +49 15737185122 ::
:: http://icube-icps.unistra.fr/index.php/Jens_Gustedt ::



[-- Attachment #2: This is a digitally signed message part --]
[-- Type: application/pgp-signature, Size: 198 bytes --]

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: Further limits/stdint issues
  2014-12-03  5:03   ` Rich Felker
@ 2014-12-03 16:34     ` Glenn Weinberg
  2014-12-03 17:01       ` Rich Felker
  0 siblings, 1 reply; 7+ messages in thread
From: Glenn Weinberg @ 2014-12-03 16:34 UTC (permalink / raw)
  To: Rich Felker; +Cc: musl


> On Dec 3, 2014, at 12:03 AM, Rich Felker <dalias@libc.org> wrote:
> 
> On Tue, Dec 02, 2014 at 11:10:58PM -0500, Glenn Weinberg wrote:
>> 
>>> On Dec 2, 2014, at 8:02 PM, Rich Felker <dalias@libc.org> wrote:
>>> 
>>> The fast16/fast32 types and limits are still in bits/stdint.h despite
>>> not varying between archs. Removing those would make bits/stdint.h
>>> tiny/trivial. Aside from PAGE_SIZE, both bits/limits.h and
>>> bits/stdint.h would essentially have no information except
>>> "long/pointer size" and maybe we could even eventually eliminate them
>>> by having a global idea of "wordsize".
>> 
>> I don't think it's safe to make such assumptions. Our architecture
>> is native 64-bit, so we define all the fast types as 64-bit.
> 
> Could you elaborate on your motivations? There's no inherent reason
> that the fast types should be defined as 64-bit just because the
> native word size is 64-bit, and there are lots of reasons against it.

I can, although I need to be a bit circumspect because our product won't be in the market for another year or so and thus we're not exposing all the details yet.

The fundamental answer is that our architecture does not define any 8, 16 or 32-bit integer arithmetic operations.  Integer add, subtract, divide and remainder take 64-bit operands and produce a 64-bit result; integer multiply, multiply-add and multiply-subtract take 64-bit operands and produce a 128-bit result.

> Lots of people misinterpret the "fast" types as "fast unit for moving
> data", i.e. in the sense of "given N bytes of data to move, what's the
> fastest type to move it as?" This is not the meaning the C language
> assigns to them; in fact this sense is rather meaningless since C does
> not permit the aliasing that would be needed to move data as any type
> other than its actual type or a character type.

Don't think I'm one of those people, but I've been wrong before :-)

> Rather, "fast" is a matter of "given N values, possibly with just N=1,
> what type should be used to optimize operations on the value(s)?" In
> this sense, it's almost always best for the fast type to be the same
> as the least type, unless the least type incurs some heavy penalty
> (e.g. a machine that can't do 16-bit loads and stores and has to
> emulate them with byte loads/stores or atomic cas on larger words).

> As an example, take x86_64, where glibc made their [u]int_fast32_t
> types 64-bit. Addition and subtraction are the same speed for 32- or
> 64-bit operations, and perhaps multiplication is too (?), but division
> is significantly slower for 64-bit, and perhaps more importantly,
> using 64-bit storage doubles the number of cache lines you use and
> effectively halves the size of your cache.

While we have 8, 16 and 32-bit loads and stores that promote into/demote from a 64-bit register, there is a penalty for stores of less than 64 bits.

> If you have a good reason that the fast types should be 64-bit on some
> archs, I'd like to hear it. I'm open to listening to alternative views
> on this.

I hope this explains our reasoning sufficiently.  If not, I'd be happy to discuss this further privately.

	Regards,

	Glenn
--
Glenn Weinberg
Vice President, Product
Cognitive Electronics, Inc.
www.cognitive-electronics.com
glenn@cognitive-electronics.com





^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: Further limits/stdint issues
  2014-12-03 16:34     ` Glenn Weinberg
@ 2014-12-03 17:01       ` Rich Felker
  2014-12-03 21:08         ` Glenn Weinberg
  0 siblings, 1 reply; 7+ messages in thread
From: Rich Felker @ 2014-12-03 17:01 UTC (permalink / raw)
  To: Glenn Weinberg; +Cc: musl

On Wed, Dec 03, 2014 at 11:34:02AM -0500, Glenn Weinberg wrote:
> 
> > On Dec 3, 2014, at 12:03 AM, Rich Felker <dalias@libc.org> wrote:
> > 
> > On Tue, Dec 02, 2014 at 11:10:58PM -0500, Glenn Weinberg wrote:
> >> 
> >>> On Dec 2, 2014, at 8:02 PM, Rich Felker <dalias@libc.org> wrote:
> >>> 
> >>> The fast16/fast32 types and limits are still in bits/stdint.h despite
> >>> not varying between archs. Removing those would make bits/stdint.h
> >>> tiny/trivial. Aside from PAGE_SIZE, both bits/limits.h and
> >>> bits/stdint.h would essentially have no information except
> >>> "long/pointer size" and maybe we could even eventually eliminate them
> >>> by having a global idea of "wordsize".
> >> 
> >> I don't think it's safe to make such assumptions. Our architecture
> >> is native 64-bit, so we define all the fast types as 64-bit.
> > 
> > Could you elaborate on your motivations? There's no inherent reason
> > that the fast types should be defined as 64-bit just because the
> > native word size is 64-bit, and there are lots of reasons against it.
> 
> I can, although I need to be a bit circumspect because our product
> won't be in the market for another year or so and thus we're not
> exposing all the details yet.
> 
> The fundamental answer is that our architecture does not define any
> 8, 16 or 32-bit integer arithmetic operations. Integer add,
> subtract, divide and remainder take 64-bit operands and produce a
> 64-bit result; integer multiply, multiply-add and multiply-subtract
> take 64-bit operands and produce a 128-bit result.

Thanks for the explanation. I don't see how this makes smaller
operations "slow" though. The compiler will just generate the 64-bit
operations and ignore the junk in the upper bits of the register,
which will eventually get discarded when storing back to memory. Is it
just the cost of that store you're worried about? Being that there
will be lots of 32-bit stores even if the fast32 type is 64-bit (e.g.
everything that's plain "int" and things which are explicitly
[u]int32_t), I would think you'd want/need 32-bit store to be fast
anyway.

Rich


^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: Further limits/stdint issues
  2014-12-03 17:01       ` Rich Felker
@ 2014-12-03 21:08         ` Glenn Weinberg
  0 siblings, 0 replies; 7+ messages in thread
From: Glenn Weinberg @ 2014-12-03 21:08 UTC (permalink / raw)
  To: Rich Felker; +Cc: musl


> On Dec 3, 2014, at 12:01 PM, Rich Felker <dalias@libc.org> wrote:
> 
> On Wed, Dec 03, 2014 at 11:34:02AM -0500, Glenn Weinberg wrote:
>> 
>> The fundamental answer is that our architecture does not define any
>> 8, 16 or 32-bit integer arithmetic operations. Integer add,
>> subtract, divide and remainder take 64-bit operands and produce a
>> 64-bit result; integer multiply, multiply-add and multiply-subtract
>> take 64-bit operands and produce a 128-bit result.
> 
> Thanks for the explanation. I don't see how this makes smaller
> operations "slow" though. The compiler will just generate the 64-bit
> operations and ignore the junk in the upper bits of the register,
> which will eventually get discarded when storing back to memory.

If the compiler doesn't limit intermediate results to 32 bits it's not preserving unsigned wraparound overflow semantics as required by the C standard.  Consider the following 32-bit pseudo assembly language implementing (0xffffffff + 2) / 2:

	r1 = 0xffffffff	// 0xffffffff
	r2 = 2		// 0x00000002
	r3 = r1 + r2	// 0x00000001 (Wraparound overflow)
	r4 = r3 / r2	// 0x00000000
	Store r4	// 0x00000000

Now consider it in 64-bit (without adding additional code to limit the value in r3):

	r1 = 0xffffffff	// 0x00000000ffffffff
	r2 = 2		// 0x0000000000000002
	r3 = r1 + r2	// 0x0000000100000001 (No overflow, 64-bit)
	r4 = r3 / r2	// 0x0000000080000000
	Store low32(r4)	// 0x80000000

> Is it
> just the cost of that store you're worried about? Being that there
> will be lots of 32-bit stores even if the fast32 type is 64-bit (e.g.
> everything that's plain "int" and things which are explicitly
> [u]int32_t), I would think you'd want/need 32-bit store to be fast
> anyway.


If it were free would we add 8, 16 and 32-bit arithmetic operations and fast 8, 16 and 32-bit stores to the hardware architecture?  Sure.  But it's not free, the architecture is what it is, and that is precisely the reason why the "fast" types should remain architecture-specific. 

	Regards,

	Glenn
--
Glenn Weinberg
Vice President, Product
Cognitive Electronics, Inc.
www.cognitive-electronics.com
glenn@cognitive-electronics.com





^ permalink raw reply	[flat|nested] 7+ messages in thread

end of thread, other threads:[~2014-12-03 21:08 UTC | newest]

Thread overview: 7+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2014-12-03  1:02 Further limits/stdint issues Rich Felker
2014-12-03  4:10 ` Glenn Weinberg
2014-12-03  5:03   ` Rich Felker
2014-12-03 16:34     ` Glenn Weinberg
2014-12-03 17:01       ` Rich Felker
2014-12-03 21:08         ` Glenn Weinberg
2014-12-03 10:38 ` Jens Gustedt

Code repositories for project(s) associated with this public inbox

	https://git.vuxu.org/mirror/musl/

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).