* [Qemu-devel] [PATCH v2] utils: Add pow2ceil() @ 2015-02-23 12:23 Alexey Kardashevskiy 2015-02-23 13:59 ` Markus Armbruster 0 siblings, 1 reply; 14+ messages in thread From: Alexey Kardashevskiy @ 2015-02-23 12:23 UTC (permalink / raw) To: qemu-devel; +Cc: Alexey Kardashevskiy, Peter Maydell This adds a helper to get closest bigger power-of-two value. Signed-off-by: Alexey Kardashevskiy <aik@ozlabs.ru> --- Changes: v2: * s/up_pow_of_two/pow2ceil/ --- include/qemu-common.h | 2 ++ util/cutils.c | 9 +++++++++ 2 files changed, 11 insertions(+) diff --git a/include/qemu-common.h b/include/qemu-common.h index 644b46d..ae29748 100644 --- a/include/qemu-common.h +++ b/include/qemu-common.h @@ -417,6 +417,8 @@ static inline bool is_power_of_2(uint64_t value) /* round down to the nearest power of 2*/ int64_t pow2floor(int64_t value); +/* round up to the nearest power of 2*/ +int64_t pow2ceil(int64_t value); #include "qemu/module.h" diff --git a/util/cutils.c b/util/cutils.c index dbe7412..ecaa440 100644 --- a/util/cutils.c +++ b/util/cutils.c @@ -483,6 +483,15 @@ int64_t pow2floor(int64_t value) return value; } +/* round up to the nearest power of 2*/ +int64_t pow2ceil(int64_t value) +{ + if (!is_power_of_2(value)) { + value = 0x8000000000000000ULL >> (clz64(value) - 1); + } + return value; +} + /* * Implementation of ULEB128 (http://en.wikipedia.org/wiki/LEB128) * Input is limited to 14-bit numbers -- 2.0.0 ^ permalink raw reply related [flat|nested] 14+ messages in thread
* Re: [Qemu-devel] [PATCH v2] utils: Add pow2ceil() 2015-02-23 12:23 [Qemu-devel] [PATCH v2] utils: Add pow2ceil() Alexey Kardashevskiy @ 2015-02-23 13:59 ` Markus Armbruster 2015-02-23 16:17 ` Eric Blake 2015-02-25 0:40 ` Alexey Kardashevskiy 0 siblings, 2 replies; 14+ messages in thread From: Markus Armbruster @ 2015-02-23 13:59 UTC (permalink / raw) To: Alexey Kardashevskiy; +Cc: Peter Maydell, qemu-devel Alexey Kardashevskiy <aik@ozlabs.ru> writes: > This adds a helper to get closest bigger power-of-two value. > > Signed-off-by: Alexey Kardashevskiy <aik@ozlabs.ru> > --- > Changes: > v2: > * s/up_pow_of_two/pow2ceil/ > --- > include/qemu-common.h | 2 ++ > util/cutils.c | 9 +++++++++ > 2 files changed, 11 insertions(+) > > diff --git a/include/qemu-common.h b/include/qemu-common.h > index 644b46d..ae29748 100644 > --- a/include/qemu-common.h > +++ b/include/qemu-common.h > @@ -417,6 +417,8 @@ static inline bool is_power_of_2(uint64_t value) > > /* round down to the nearest power of 2*/ > int64_t pow2floor(int64_t value); > +/* round up to the nearest power of 2*/ > +int64_t pow2ceil(int64_t value); > > #include "qemu/module.h" > > diff --git a/util/cutils.c b/util/cutils.c > index dbe7412..ecaa440 100644 > --- a/util/cutils.c > +++ b/util/cutils.c > @@ -483,6 +483,15 @@ int64_t pow2floor(int64_t value) > return value; > } > > +/* round up to the nearest power of 2*/ > +int64_t pow2ceil(int64_t value) > +{ > + if (!is_power_of_2(value)) { > + value = 0x8000000000000000ULL >> (clz64(value) - 1); > + } > + return value; > +} > + > /* > * Implementation of ULEB128 (http://en.wikipedia.org/wiki/LEB128) > * Input is limited to 14-bit numbers pow2ceil(INT64_MIN) = INT64_MIN. Should be 1. pow2ceil(INT64_MAX) = INT64_MIN. Garbage. Related: "round down to the nearest power of 2" is defined only for x > 0, but our pow2floor(x) happily returns garbage then. In particular we return 0x8000000000000000ULL >> 64 when value is 0,. Undefined behavior. Here's how I'd do these functions: int64_t pow2floor(int64_t value) { assert(value > 0); return 0x8000000000000000u >> clz64(value); } int64_t pow2ceil(int64_t value) { assert(value <= 0x4000000000000000) if (value <= 1) return 1; return 0x8000000000000000u >> (clz64(value - 1) - 1); } ^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [Qemu-devel] [PATCH v2] utils: Add pow2ceil() 2015-02-23 13:59 ` Markus Armbruster @ 2015-02-23 16:17 ` Eric Blake 2015-02-23 17:40 ` Markus Armbruster 2015-02-25 0:40 ` Alexey Kardashevskiy 1 sibling, 1 reply; 14+ messages in thread From: Eric Blake @ 2015-02-23 16:17 UTC (permalink / raw) To: Markus Armbruster, Alexey Kardashevskiy; +Cc: Peter Maydell, qemu-devel [-- Attachment #1: Type: text/plain, Size: 989 bytes --] On 02/23/2015 06:59 AM, Markus Armbruster wrote: > Alexey Kardashevskiy <aik@ozlabs.ru> writes: > >> This adds a helper to get closest bigger power-of-two value. >> > > Here's how I'd do these functions: > > int64_t pow2floor(int64_t value) > { > assert(value > 0); > return 0x8000000000000000u >> clz64(value); > } Needs to be 0x8000000000000000ull for 32-bit machines to compile correctly. Why is the parameter int64_t? Wouldn't it be more useful to have: uint64_t pow2floor(uint64_t value) > > int64_t pow2ceil(int64_t value) > { Again, why allow signed inputs? > assert(value <= 0x4000000000000000) > if (value <= 1) > return 1; In particular, this slams all negative values to a result of 1, which doesn't necessarily make sense. > return 0x8000000000000000u >> (clz64(value - 1) - 1); > } > > > -- Eric Blake eblake redhat com +1-919-301-3266 Libvirt virtualization library http://libvirt.org [-- Attachment #2: OpenPGP digital signature --] [-- Type: application/pgp-signature, Size: 604 bytes --] ^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [Qemu-devel] [PATCH v2] utils: Add pow2ceil() 2015-02-23 16:17 ` Eric Blake @ 2015-02-23 17:40 ` Markus Armbruster 2015-02-23 21:20 ` Eric Blake 0 siblings, 1 reply; 14+ messages in thread From: Markus Armbruster @ 2015-02-23 17:40 UTC (permalink / raw) To: Eric Blake; +Cc: Alexey Kardashevskiy, Peter Maydell, qemu-devel Eric Blake <eblake@redhat.com> writes: > On 02/23/2015 06:59 AM, Markus Armbruster wrote: >> Alexey Kardashevskiy <aik@ozlabs.ru> writes: >> >>> This adds a helper to get closest bigger power-of-two value. >>> > >> >> Here's how I'd do these functions: >> >> int64_t pow2floor(int64_t value) >> { >> assert(value > 0); >> return 0x8000000000000000u >> clz64(value); >> } > > Needs to be 0x8000000000000000ull for 32-bit machines to compile correctly. Why? > Why is the parameter int64_t? Wouldn't it be more useful to have: > > uint64_t pow2floor(uint64_t value) Crossed my mind, too. However, the existing callers pass *signed* arguments. >> int64_t pow2ceil(int64_t value) >> { > > Again, why allow signed inputs? > >> assert(value <= 0x4000000000000000) >> if (value <= 1) >> return 1; > > In particular, this slams all negative values to a result of 1, which > doesn't necessarily make sense. It implements a straightforward contract: return the smallest power of two greater or equal to the argument. The function's domain is the set of int64_t arguments where this value can be represented in int64_t, i.e. [-2^63..2^62]. Feel free to suggest a more sensible contract. >> return 0x8000000000000000u >> (clz64(value - 1) - 1); >> } >> >> >> ^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [Qemu-devel] [PATCH v2] utils: Add pow2ceil() 2015-02-23 17:40 ` Markus Armbruster @ 2015-02-23 21:20 ` Eric Blake 2015-02-24 9:39 ` Markus Armbruster 0 siblings, 1 reply; 14+ messages in thread From: Eric Blake @ 2015-02-23 21:20 UTC (permalink / raw) To: Markus Armbruster; +Cc: Alexey Kardashevskiy, Peter Maydell, qemu-devel [-- Attachment #1: Type: text/plain, Size: 1942 bytes --] On 02/23/2015 10:40 AM, Markus Armbruster wrote: >>> int64_t pow2floor(int64_t value) >>> { >>> assert(value > 0); >>> return 0x8000000000000000u >> clz64(value); >>> } >> >> Needs to be 0x8000000000000000ull for 32-bit machines to compile correctly. > > Why? Because 0x8000000000000000u is only required to be a 'long', and on 32-bit machines, your constant would overflow long. See, for example, commit 5cb6be2ca. You NEED the 'll' suffix to ensure that the compiler doesn't reject the constant as an overflow. > >> Why is the parameter int64_t? Wouldn't it be more useful to have: >> >> uint64_t pow2floor(uint64_t value) > > Crossed my mind, too. However, the existing callers pass *signed* > arguments. I guess it means auditing callers either way. > >>> int64_t pow2ceil(int64_t value) >>> { >> >> Again, why allow signed inputs? >> >>> assert(value <= 0x4000000000000000) >>> if (value <= 1) >>> return 1; >> >> In particular, this slams all negative values to a result of 1, which >> doesn't necessarily make sense. > > It implements a straightforward contract: return the smallest power of > two greater or equal to the argument. The function's domain is the set > of int64_t arguments where this value can be represented in int64_t, > i.e. [-2^63..2^62]. > > Feel free to suggest a more sensible contract. But why should I claim that the nearest power of 2 greater than -3 is positive 1, when I could argue that it should instead be -2 (nearest positive or negative power of 2 rounding towards +inf) or -4 (nearest positive or negative power of 2 rounding away from 0)? Since there are multiple potential contracts once negative values are involved, I find it easier to just make the contract require a positive input to begin with. -- Eric Blake eblake redhat com +1-919-301-3266 Libvirt virtualization library http://libvirt.org [-- Attachment #2: OpenPGP digital signature --] [-- Type: application/pgp-signature, Size: 604 bytes --] ^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [Qemu-devel] [PATCH v2] utils: Add pow2ceil() 2015-02-23 21:20 ` Eric Blake @ 2015-02-24 9:39 ` Markus Armbruster 2015-02-24 11:39 ` Peter Maydell 0 siblings, 1 reply; 14+ messages in thread From: Markus Armbruster @ 2015-02-24 9:39 UTC (permalink / raw) To: Eric Blake; +Cc: Alexey Kardashevskiy, Peter Maydell, qemu-devel Eric Blake <eblake@redhat.com> writes: > On 02/23/2015 10:40 AM, Markus Armbruster wrote: > >>>> int64_t pow2floor(int64_t value) >>>> { >>>> assert(value > 0); >>>> return 0x8000000000000000u >> clz64(value); >>>> } >>> >>> Needs to be 0x8000000000000000ull for 32-bit machines to compile correctly. >> >> Why? > > Because 0x8000000000000000u is only required to be a 'long', and on > 32-bit machines, your constant would overflow long. See, for example, > commit 5cb6be2ca. You NEED the 'll' suffix to ensure that the compiler > doesn't reject the constant as an overflow. Not true. If you're not interested in whether it is true or not, only what suffix we should use, skip to "Commit 5cb6be2ca". If you trust me as a language lawyer, you can skip over my experiment to "Why is this so". ---<lit.c>--- #include <stdio.h> #define HAS_LIT_TYPE(lit, type) \ __builtin_types_compatible_p(type, typeof(lit)) #define LIT_TYPE_NAME1(lit, type) \ (HAS_LIT_TYPE(lit, type) ? #type : NULL) #define LIT_INT_TYPE_NAME(lit) \ (LIT_TYPE_NAME1(lit, int) \ ?: LIT_TYPE_NAME1(lit, unsigned) \ ?: LIT_TYPE_NAME1(lit, long) \ ?: LIT_TYPE_NAME1(lit, unsigned long) \ ?: LIT_TYPE_NAME1(lit, long long) \ ?: LIT_TYPE_NAME1(lit, unsigned long long) \ ?: "unknown") #define PR_LIT_INT_TYPE(lit) \ printf("%-24s %s\n", #lit, LIT_INT_TYPE_NAME(lit)); int main(void) { PR_LIT_INT_TYPE(0x8000000000000000); PR_LIT_INT_TYPE(0x8000000000000000u); PR_LIT_INT_TYPE(0x8000000000000000ull); return 0; } ---<End of lit.c>--- $ gcc -o lit64 -g -O -Wall lit.c $ gcc -m32 -o lit32 -g -O -Wall lit.c $ ./lit32 0x8000000000000000 unsigned long long 0x8000000000000000u unsigned long long 0x8000000000000000ull unsigned long long $ ./lit64 0x8000000000000000 unsigned long 0x8000000000000000u unsigned long 0x8000000000000000ull unsigned long long Why is this so? The type of an integer constant depends on its value, its suffix, and whether it's decimal or not. ISO/IEC 9899:1999 §6.4.4.1: [#5] The type of an integer constant is the first of the corresponding list in which its value can be represented. | | Octal or Hexadecimal Suffix | Decimal Constant | Constant -------------+-----------------------+----------------------- none |int |int |long int |unsigned int |long long int |long int | |unsigned long int | |long long int | |unsigned long long int -------------+-----------------------+----------------------- u or U |unsigned int |unsigned int |unsigned long int |unsigned long int |unsigned long long int |unsigned long long int -------------+-----------------------+----------------------- l or L |long int |long int |long long int |unsigned long int | |long long int | |unsigned long long int -------------+-----------------------+----------------------- Both u or U |unsigned long int |unsigned long int and l or L |unsigned long long int |unsigned long long int -------------+-----------------------+----------------------- ll or LL |long long int |long long int | |unsigned long long int -------------+-----------------------+----------------------- Both u or U |unsigned long long int |unsigned long long int and ll or LL | | A hexadecimal constant without a suffix can have a signed type, which can surprise the unwary programmer. But if the suffix contains u, the constant has an unsigned type. 0x8000000000000000u needs 64 bits to be representable. Its type is the narrowest of unsigned, unsigned long, unsigned long long that can represent it. Real-world examples: data model | int long long long | type of 0x8000000000000000u LLP64 | 32 32 64 | unsigned long long LP64 | 32 64 64 | unsigned long IILP64 | 64 64 64 | unsigned Commit 5cb6be2ca fixes up hexadecimal literals without a suffix. For what it's worth, I can't reproduce the warning with gcc -m32. Whether and where u-suffixed literals trigger the warning I can't say. If they do, we'll want whatever suffix it takes. If they don't, you could argue for suffix ull to avoid ambiguity. Matter of taste. I don't particularly care, but the reason is style, not "won't compile". >>> Why is the parameter int64_t? Wouldn't it be more useful to have: >>> >>> uint64_t pow2floor(uint64_t value) >> >> Crossed my mind, too. However, the existing callers pass *signed* >> arguments. > > I guess it means auditing callers either way. > >>>> int64_t pow2ceil(int64_t value) >>>> { >>> >>> Again, why allow signed inputs? >>> >>>> assert(value <= 0x4000000000000000) >>>> if (value <= 1) >>>> return 1; >>> >>> In particular, this slams all negative values to a result of 1, which >>> doesn't necessarily make sense. >> >> It implements a straightforward contract: return the smallest power of >> two greater or equal to the argument. The function's domain is the set >> of int64_t arguments where this value can be represented in int64_t, >> i.e. [-2^63..2^62]. >> >> Feel free to suggest a more sensible contract. > > But why should I claim that the nearest power of 2 greater than -3 is > positive 1, when I could argue that it should instead be -2 (nearest > positive or negative power of 2 rounding towards +inf) or -4 (nearest > positive or negative power of 2 rounding away from 0)? Since there are > multiple potential contracts once negative values are involved, I find > it easier to just make the contract require a positive input to begin with. -2 is not a power of two! Ask any mathematician :) "Round down to the nearest power of 2" is a pefectly obvious function contract. The function's domain is the representable numbers >= 1. Same for "round up", domain is representable numbers <= largest representable power of two. My implementations assert the actual argument is in the domain. If you want to change the two functions' contracts to return the nearest positive or negative power of two rounding towards whatever, I don't mind as long as you explicitly write it into their contract, because it sure isn't obvious from the function names. If you want to change the functions' parameter and return type to uint64_t, I don't mind, either. However, you'll have to handle domain errors in both functions all the same. An audit of the callers may be advisable regardless of what we do. ^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [Qemu-devel] [PATCH v2] utils: Add pow2ceil() 2015-02-24 9:39 ` Markus Armbruster @ 2015-02-24 11:39 ` Peter Maydell 2015-02-24 13:09 ` Markus Armbruster 0 siblings, 1 reply; 14+ messages in thread From: Peter Maydell @ 2015-02-24 11:39 UTC (permalink / raw) To: Markus Armbruster; +Cc: Alexey Kardashevskiy, QEMU Developers On 24 February 2015 at 18:39, Markus Armbruster <armbru@redhat.com> wrote: > Eric Blake <eblake@redhat.com> writes: >> Because 0x8000000000000000u is only required to be a 'long', and on >> 32-bit machines, your constant would overflow long. See, for example, >> commit 5cb6be2ca. You NEED the 'll' suffix to ensure that the compiler >> doesn't reject the constant as an overflow. > > Not true. You need ULL because certain versions of gcc will warn if you do not. (I have a feeling this includes the elderly gcc I currently use for mingw builds.) You could argue that this is a gcc bug, and somebody probably did given that newer gcc don't warn about this. However we should always use ULL (or LL) for 64-bit constants, to avoid confusing those versions of gcc. thanks -- PMM ^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [Qemu-devel] [PATCH v2] utils: Add pow2ceil() 2015-02-24 11:39 ` Peter Maydell @ 2015-02-24 13:09 ` Markus Armbruster 0 siblings, 0 replies; 14+ messages in thread From: Markus Armbruster @ 2015-02-24 13:09 UTC (permalink / raw) To: Peter Maydell; +Cc: Alexey Kardashevskiy, QEMU Developers Peter Maydell <peter.maydell@linaro.org> writes: > On 24 February 2015 at 18:39, Markus Armbruster <armbru@redhat.com> wrote: >> Eric Blake <eblake@redhat.com> writes: >>> Because 0x8000000000000000u is only required to be a 'long', and on >>> 32-bit machines, your constant would overflow long. See, for example, >>> commit 5cb6be2ca. You NEED the 'll' suffix to ensure that the compiler >>> doesn't reject the constant as an overflow. >> >> Not true. > > You need ULL because certain versions of gcc will warn if you do > not. (I have a feeling this includes the elderly gcc I currently > use for mingw builds.) You could argue that this is a gcc bug, and > somebody probably did given that newer gcc don't warn about this. > However we should always use ULL (or LL) for 64-bit constants, > to avoid confusing those versions of gcc. Working around compiler bugs is a perfectly good reason to ull big constants. ^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [Qemu-devel] [PATCH v2] utils: Add pow2ceil() 2015-02-23 13:59 ` Markus Armbruster 2015-02-23 16:17 ` Eric Blake @ 2015-02-25 0:40 ` Alexey Kardashevskiy 2015-02-25 10:45 ` Markus Armbruster 1 sibling, 1 reply; 14+ messages in thread From: Alexey Kardashevskiy @ 2015-02-25 0:40 UTC (permalink / raw) To: Markus Armbruster; +Cc: Peter Maydell, qemu-devel On 02/24/2015 12:59 AM, Markus Armbruster wrote: > Alexey Kardashevskiy <aik@ozlabs.ru> writes: > >> This adds a helper to get closest bigger power-of-two value. >> >> Signed-off-by: Alexey Kardashevskiy <aik@ozlabs.ru> >> --- >> Changes: >> v2: >> * s/up_pow_of_two/pow2ceil/ >> --- >> include/qemu-common.h | 2 ++ >> util/cutils.c | 9 +++++++++ >> 2 files changed, 11 insertions(+) >> >> diff --git a/include/qemu-common.h b/include/qemu-common.h >> index 644b46d..ae29748 100644 >> --- a/include/qemu-common.h >> +++ b/include/qemu-common.h >> @@ -417,6 +417,8 @@ static inline bool is_power_of_2(uint64_t value) >> >> /* round down to the nearest power of 2*/ >> int64_t pow2floor(int64_t value); >> +/* round up to the nearest power of 2*/ >> +int64_t pow2ceil(int64_t value); >> >> #include "qemu/module.h" >> >> diff --git a/util/cutils.c b/util/cutils.c >> index dbe7412..ecaa440 100644 >> --- a/util/cutils.c >> +++ b/util/cutils.c >> @@ -483,6 +483,15 @@ int64_t pow2floor(int64_t value) >> return value; >> } >> >> +/* round up to the nearest power of 2*/ >> +int64_t pow2ceil(int64_t value) >> +{ >> + if (!is_power_of_2(value)) { >> + value = 0x8000000000000000ULL >> (clz64(value) - 1); >> + } >> + return value; >> +} >> + >> /* >> * Implementation of ULEB128 (http://en.wikipedia.org/wiki/LEB128) >> * Input is limited to 14-bit numbers > > pow2ceil(INT64_MIN) = INT64_MIN. Should be 1. > > pow2ceil(INT64_MAX) = INT64_MIN. Garbage. > > Related: "round down to the nearest power of 2" is defined only for x > > 0, but our pow2floor(x) happily returns garbage then. > > In particular we return 0x8000000000000000ULL >> 64 when value is 0,. > Undefined behavior. > > Here's how I'd do these functions: > > int64_t pow2floor(int64_t value) > { > assert(value > 0); > return 0x8000000000000000u >> clz64(value); > } > > int64_t pow2ceil(int64_t value) > { > assert(value <= 0x4000000000000000) > if (value <= 1) > return 1; > return 0x8000000000000000u >> (clz64(value - 1) - 1); > } > I've read the whole thread, that was cool :) Do you want me to repost your versions as a patch? I do not feel I should since it is totally yours but I can :) -- Alexey ^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [Qemu-devel] [PATCH v2] utils: Add pow2ceil() 2015-02-25 0:40 ` Alexey Kardashevskiy @ 2015-02-25 10:45 ` Markus Armbruster 2015-03-12 15:29 ` Richard Henderson 0 siblings, 1 reply; 14+ messages in thread From: Markus Armbruster @ 2015-02-25 10:45 UTC (permalink / raw) To: Alexey Kardashevskiy; +Cc: Peter Maydell, qemu-devel Alexey Kardashevskiy <aik@ozlabs.ru> writes: > On 02/24/2015 12:59 AM, Markus Armbruster wrote: >> Alexey Kardashevskiy <aik@ozlabs.ru> writes: >> >>> This adds a helper to get closest bigger power-of-two value. >>> >>> Signed-off-by: Alexey Kardashevskiy <aik@ozlabs.ru> >>> --- >>> Changes: >>> v2: >>> * s/up_pow_of_two/pow2ceil/ >>> --- >>> include/qemu-common.h | 2 ++ >>> util/cutils.c | 9 +++++++++ >>> 2 files changed, 11 insertions(+) >>> >>> diff --git a/include/qemu-common.h b/include/qemu-common.h >>> index 644b46d..ae29748 100644 >>> --- a/include/qemu-common.h >>> +++ b/include/qemu-common.h >>> @@ -417,6 +417,8 @@ static inline bool is_power_of_2(uint64_t value) >>> >>> /* round down to the nearest power of 2*/ >>> int64_t pow2floor(int64_t value); >>> +/* round up to the nearest power of 2*/ >>> +int64_t pow2ceil(int64_t value); >>> >>> #include "qemu/module.h" >>> >>> diff --git a/util/cutils.c b/util/cutils.c >>> index dbe7412..ecaa440 100644 >>> --- a/util/cutils.c >>> +++ b/util/cutils.c >>> @@ -483,6 +483,15 @@ int64_t pow2floor(int64_t value) >>> return value; >>> } >>> >>> +/* round up to the nearest power of 2*/ >>> +int64_t pow2ceil(int64_t value) >>> +{ >>> + if (!is_power_of_2(value)) { >>> + value = 0x8000000000000000ULL >> (clz64(value) - 1); >>> + } >>> + return value; >>> +} >>> + >>> /* >>> * Implementation of ULEB128 (http://en.wikipedia.org/wiki/LEB128) >>> * Input is limited to 14-bit numbers >> >> pow2ceil(INT64_MIN) = INT64_MIN. Should be 1. >> >> pow2ceil(INT64_MAX) = INT64_MIN. Garbage. >> >> Related: "round down to the nearest power of 2" is defined only for x > >> 0, but our pow2floor(x) happily returns garbage then. >> >> In particular we return 0x8000000000000000ULL >> 64 when value is 0,. >> Undefined behavior. >> >> Here's how I'd do these functions: >> >> int64_t pow2floor(int64_t value) >> { >> assert(value > 0); >> return 0x8000000000000000u >> clz64(value); >> } >> >> int64_t pow2ceil(int64_t value) >> { >> assert(value <= 0x4000000000000000) >> if (value <= 1) >> return 1; >> return 0x8000000000000000u >> (clz64(value - 1) - 1); >> } >> > > > I've read the whole thread, that was cool :) I indulged in a bit of language lawyering, glad you liked it. > Do you want me to repost your versions as a patch? I do not feel I > should since it is totally yours but I can :) I'll post a patch fixing the existing pow2floor(). I prefer not to add pow2ceil() without a user. If you have one, I suggest you do your patches on top of mine. ^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [Qemu-devel] [PATCH v2] utils: Add pow2ceil() 2015-02-25 10:45 ` Markus Armbruster @ 2015-03-12 15:29 ` Richard Henderson 2015-03-12 16:45 ` Eric Blake 2015-03-13 7:33 ` Markus Armbruster 0 siblings, 2 replies; 14+ messages in thread From: Richard Henderson @ 2015-03-12 15:29 UTC (permalink / raw) To: Markus Armbruster, Alexey Kardashevskiy; +Cc: Peter Maydell, qemu-devel On 02/25/2015 02:45 AM, Markus Armbruster wrote: > return 0x8000000000000000u >> (clz64(value - 1) - 1); I realize this was weeks ago, but it would certainly be preferable to shift a small constant left than a large constant right. Most RISC machines can't form 0x8000000000000000ull without loading 1 and then left shifting to start with. So end the end you're better off with return 1ull << (63 - clz64(value)); r~ ^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [Qemu-devel] [PATCH v2] utils: Add pow2ceil() 2015-03-12 15:29 ` Richard Henderson @ 2015-03-12 16:45 ` Eric Blake 2015-03-13 19:04 ` Richard Henderson 2015-03-13 7:33 ` Markus Armbruster 1 sibling, 1 reply; 14+ messages in thread From: Eric Blake @ 2015-03-12 16:45 UTC (permalink / raw) To: Richard Henderson, Markus Armbruster, Alexey Kardashevskiy Cc: Peter Maydell, qemu-devel [-- Attachment #1: Type: text/plain, Size: 823 bytes --] On 03/12/2015 09:29 AM, Richard Henderson wrote: > On 02/25/2015 02:45 AM, Markus Armbruster wrote: >> return 0x8000000000000000u >> (clz64(value - 1) - 1); > > I realize this was weeks ago, but it would certainly be preferable to shift a > small constant left than a large constant right. > > Most RISC machines can't form 0x8000000000000000ull without loading 1 and then > left shifting to start with. So end the end you're better off with > > return 1ull << (63 - clz64(value)); Since the value being shifted is a constant either way, can't gcc figure out the equivalence and generate the optimal code to begin with? If not, should it be opened as a gcc bug for potential optimization? -- Eric Blake eblake redhat com +1-919-301-3266 Libvirt virtualization library http://libvirt.org [-- Attachment #2: OpenPGP digital signature --] [-- Type: application/pgp-signature, Size: 604 bytes --] ^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [Qemu-devel] [PATCH v2] utils: Add pow2ceil() 2015-03-12 16:45 ` Eric Blake @ 2015-03-13 19:04 ` Richard Henderson 0 siblings, 0 replies; 14+ messages in thread From: Richard Henderson @ 2015-03-13 19:04 UTC (permalink / raw) To: Eric Blake, Markus Armbruster, Alexey Kardashevskiy Cc: Peter Maydell, qemu-devel On 03/12/2015 09:45 AM, Eric Blake wrote: > On 03/12/2015 09:29 AM, Richard Henderson wrote: >> On 02/25/2015 02:45 AM, Markus Armbruster wrote: >>> return 0x8000000000000000u >> (clz64(value - 1) - 1); >> >> I realize this was weeks ago, but it would certainly be preferable to shift a >> small constant left than a large constant right. >> >> Most RISC machines can't form 0x8000000000000000ull without loading 1 and then >> left shifting to start with. So end the end you're better off with >> >> return 1ull << (63 - clz64(value)); > > Since the value being shifted is a constant either way, can't gcc figure > out the equivalence and generate the optimal code to begin with? If > not, should it be opened as a gcc bug for potential optimization? With the simplest of tests, unsigned long f(unsigned long x) { return 1UL << (63 - x); } unsigned long g(unsigned long x) { return 0x8000000000000000ul >> x; } the code is of similar size: 3 operations each. But if you throw in the whole operation 1ul << (63 - (__builtin_clzl(x - 1) - 1)) vs 0x8...0ul >> (__builtin_clzl(x - 1) - 1) then gcc is able to fold away one of the instructions and the 1UL alternative is shorter. r~ ^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [Qemu-devel] [PATCH v2] utils: Add pow2ceil() 2015-03-12 15:29 ` Richard Henderson 2015-03-12 16:45 ` Eric Blake @ 2015-03-13 7:33 ` Markus Armbruster 1 sibling, 0 replies; 14+ messages in thread From: Markus Armbruster @ 2015-03-13 7:33 UTC (permalink / raw) To: Richard Henderson; +Cc: Alexey Kardashevskiy, Peter Maydell, qemu-devel Richard Henderson <rth@twiddle.net> writes: > On 02/25/2015 02:45 AM, Markus Armbruster wrote: >> return 0x8000000000000000u >> (clz64(value - 1) - 1); > > I realize this was weeks ago, but it would certainly be preferable to shift a > small constant left than a large constant right. > > Most RISC machines can't form 0x8000000000000000ull without loading 1 and then > left shifting to start with. So end the end you're better off with > > return 1ull << (63 - clz64(value)); I intend to respin my own "[PATCH 0/2] Proactive pow2floor() fix, and dead code removal", and I'll keep your advice in mind for that. ^ permalink raw reply [flat|nested] 14+ messages in thread
end of thread, other threads:[~2015-03-13 19:04 UTC | newest] Thread overview: 14+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2015-02-23 12:23 [Qemu-devel] [PATCH v2] utils: Add pow2ceil() Alexey Kardashevskiy 2015-02-23 13:59 ` Markus Armbruster 2015-02-23 16:17 ` Eric Blake 2015-02-23 17:40 ` Markus Armbruster 2015-02-23 21:20 ` Eric Blake 2015-02-24 9:39 ` Markus Armbruster 2015-02-24 11:39 ` Peter Maydell 2015-02-24 13:09 ` Markus Armbruster 2015-02-25 0:40 ` Alexey Kardashevskiy 2015-02-25 10:45 ` Markus Armbruster 2015-03-12 15:29 ` Richard Henderson 2015-03-12 16:45 ` Eric Blake 2015-03-13 19:04 ` Richard Henderson 2015-03-13 7:33 ` Markus Armbruster
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).