Acked-by: Jarno Rajahalme <jrajaha...@nicira.com>

On Nov 18, 2013, at 1:19 PM, Ben Pfaff <b...@nicira.com> wrote:

> Having a single function that can do ctz() on any integer type is easier
> for callers to get right, and there is no real downside in the
> implementation.
> 
> Signed-off-by: Ben Pfaff <b...@nicira.com>
> ---
> lib/flow.c  |   16 ++++++++--------
> lib/match.c |    2 +-
> lib/util.c  |   11 +++++------
> lib/util.h  |   31 +++++++++++--------------------
> 4 files changed, 25 insertions(+), 35 deletions(-)
> 
> diff --git a/lib/flow.c b/lib/flow.c
> index 137ce69..1e31982 100644
> --- a/lib/flow.c
> +++ b/lib/flow.c
> @@ -666,7 +666,7 @@ flow_union_with_miniflow(struct flow *dst, const struct 
> miniflow *src)
>     uint64_t map;
> 
>     for (map = src->map; map; map = zero_rightmost_1bit(map)) {
> -        dst_u32[raw_ctz64(map)] |= src->values[ofs++];
> +        dst_u32[raw_ctz(map)] |= src->values[ofs++];
>     }
> }
> 
> @@ -1133,7 +1133,7 @@ miniflow_init__(struct miniflow *dst, const struct flow 
> *src, int n)
>     dst->values = miniflow_alloc_values(dst, n);
>     ofs = 0;
>     for (map = dst->map; map; map = zero_rightmost_1bit(map)) {
> -        dst->values[ofs++] = src_u32[raw_ctz64(map)];
> +        dst->values[ofs++] = src_u32[raw_ctz(map)];
>     }
> }
> 
> @@ -1295,7 +1295,7 @@ miniflow_equal_in_minimask(const struct miniflow *a, 
> const struct miniflow *b,
>     p = mask->masks.values;
> 
>     for (map = mask->masks.map; map; map = zero_rightmost_1bit(map)) {
> -        int ofs = raw_ctz64(map);
> +        int ofs = raw_ctz(map);
> 
>         if ((miniflow_get(a, ofs) ^ miniflow_get(b, ofs)) & *p) {
>             return false;
> @@ -1319,7 +1319,7 @@ miniflow_equal_flow_in_minimask(const struct miniflow 
> *a, const struct flow *b,
>     p = mask->masks.values;
> 
>     for (map = mask->masks.map; map; map = zero_rightmost_1bit(map)) {
> -        int ofs = raw_ctz64(map);
> +        int ofs = raw_ctz(map);
> 
>         if ((miniflow_get(a, ofs) ^ b_u32[ofs]) & *p) {
>             return false;
> @@ -1369,7 +1369,7 @@ miniflow_hash_in_minimask(const struct miniflow *flow,
> 
>     for (map = mask->masks.map; map; map = zero_rightmost_1bit(map)) {
>         if (*p) {
> -            int ofs = raw_ctz64(map);
> +            int ofs = raw_ctz(map);
>             hash = mhash_add(hash, miniflow_get(flow, ofs) & *p);
>         }
>         p++;
> @@ -1395,7 +1395,7 @@ flow_hash_in_minimask(const struct flow *flow, const 
> struct minimask *mask,
>     hash = basis;
>     for (map = mask->masks.map; map; map = zero_rightmost_1bit(map)) {
>         if (*p) {
> -            hash = mhash_add(hash, flow_u32[raw_ctz64(map)] & *p);
> +            hash = mhash_add(hash, flow_u32[raw_ctz(map)] & *p);
>         }
>         p++;
>     }
> @@ -1446,7 +1446,7 @@ minimask_combine(struct minimask *dst_,
> 
>     dst->map = 0;
>     for (map = a->map & b->map; map; map = zero_rightmost_1bit(map)) {
> -        int ofs = raw_ctz64(map);
> +        int ofs = raw_ctz(map);
>         uint32_t mask = miniflow_get(a, ofs) & miniflow_get(b, ofs);
> 
>         if (mask) {
> @@ -1511,7 +1511,7 @@ minimask_has_extra(const struct minimask *a_, const 
> struct minimask *b_)
>     uint64_t map;
> 
>     for (map = a->map | b->map; map; map = zero_rightmost_1bit(map)) {
> -        int ofs = raw_ctz64(map);
> +        int ofs = raw_ctz(map);
>         uint32_t a_u32 = miniflow_get(a, ofs);
>         uint32_t b_u32 = miniflow_get(b, ofs);
> 
> diff --git a/lib/match.c b/lib/match.c
> index 35356c1..f2229bb 100644
> --- a/lib/match.c
> +++ b/lib/match.c
> @@ -1176,7 +1176,7 @@ minimatch_matches_flow(const struct minimatch *match,
>     uint64_t map;
> 
>     for (map = match->flow.map; map; map = zero_rightmost_1bit(map)) {
> -        if ((*flowp++ ^ target_u32[raw_ctz64(map)]) & *maskp++) {
> +        if ((*flowp++ ^ target_u32[raw_ctz(map)]) & *maskp++) {
>             return false;
>         }
>     }
> diff --git a/lib/util.c b/lib/util.c
> index 9b79c25..19abada 100644
> --- a/lib/util.c
> +++ b/lib/util.c
> @@ -889,16 +889,14 @@ log_2_ceil(uint32_t n)
> }
> 
> /* Returns the number of trailing 0-bits in 'n'.  Undefined if 'n' == 0. */
> -#if !defined(UINT_MAX) || !defined(UINT32_MAX)
> -#error "Someone screwed up the #includes."
> -#elif __GNUC__ >= 4 && UINT_MAX == UINT32_MAX
> +#if __GNUC__ >= 4
> /* Defined inline in util.h. */
> #else
> int
> -raw_ctz(uint32_t n)
> +raw_ctz(uint64_t n)
> {
> -    unsigned int k;
> -    int count = 31;
> +    uint64_t k;
> +    int count = 63;
> 
> #define CTZ_STEP(X)                             \
>     k = n << (X);                               \
> @@ -906,6 +904,7 @@ raw_ctz(uint32_t n)
>         count -= X;                             \
>         n = k;                                  \
>     }
> +    CTZ_STEP(32);
>     CTZ_STEP(16);
>     CTZ_STEP(8);
>     CTZ_STEP(4);
> diff --git a/lib/util.h b/lib/util.h
> index 374c094..91dc0a5 100644
> --- a/lib/util.h
> +++ b/lib/util.h
> @@ -289,29 +289,25 @@ int log_2_floor(uint32_t);
> int log_2_ceil(uint32_t);
> unsigned int popcount(uint32_t);
> 
> -/* Returns the number of trailing 0-bits in 'n'.  Undefined if 'n' == 0.
> - *
> - * This compiles to a single machine instruction ("bsf") with GCC on x86. */
> -#if !defined(UINT_MAX) || !defined(UINT32_MAX)
> -#error "Someone screwed up the #includes."
> -#elif __GNUC__ >= 4 && UINT_MAX == UINT32_MAX
> +/* Returns the number of trailing 0-bits in 'n'.  Undefined if 'n' == 0. */
> +#if __GNUC__ >= 4
> static inline int
> -raw_ctz(uint32_t n)
> +raw_ctz(uint64_t n)
> {
> -    return __builtin_ctz(n);
> +    /* With GCC 4.7 on 32-bit x86, if a 32-bit integer is passed as 'n', 
> using
> +     * a plain __builtin_ctzll() here always generates an out-of-line 
> function
> +     * call.  The test below helps it to emit a single 'bsf' instruction. */
> +    return (__builtin_constant_p(n <= UINT32_MAX) && n <= UINT32_MAX
> +            ? __builtin_ctz(n)
> +            : __builtin_ctzll(n));
> }
> #else
> /* Defined in util.c. */
> -int raw_ctz(uint32_t n);
> +int raw_ctz(uint64_t n);
> #endif
> 
> #if __GNUC__ >= 4
> static inline int
> -raw_ctz64(uint64_t n)
> -{
> -    return __builtin_ctzll(n);
> -}
> -static inline int
> popcount64(uint64_t n)
> {
>     return __builtin_popcountll(n);
> @@ -319,11 +315,6 @@ popcount64(uint64_t n)
> #else
> /* Defined using the 32-bit counterparts. */
> static inline int
> -raw_ctz64(uint64_t n)
> -{
> -    return (uint32_t)n ? raw_ctz(n) : 32 + raw_ctz(n >> 32);
> -}
> -static inline int
> popcount64(uint64_t n)
> {
>     return popcount(n) + popcount(n >> 32);
> @@ -341,7 +332,7 @@ ctz(uint32_t n)
> static inline int
> ctz64(uint64_t n)
> {
> -    return n ? raw_ctz64(n) : 64;
> +    return n ? raw_ctz(n) : 64;
> }
> 
> /* Returns the rightmost 1-bit in 'x' (e.g. 01011000 => 00001000), or 0 if 'x'
> -- 
> 1.7.10.4
> 
> _______________________________________________
> dev mailing list
> dev@openvswitch.org
> http://openvswitch.org/mailman/listinfo/dev

_______________________________________________
dev mailing list
dev@openvswitch.org
http://openvswitch.org/mailman/listinfo/dev

Reply via email to