Skip to content

Commit 55ca8d7

Browse files
XiaoWang1772palmer-dabbelt
authored andcommitted
riscv: Optimize hweight API with Zbb extension
The Hamming Weight of a number is the total number of bits set in it, so the cpop/cpopw instruction from Zbb extension can be used to accelerate hweight() API. Signed-off-by: Xiao Wang <xiao.w.wang@intel.com> Reviewed-by: Charlie Jenkins <charlie@rivosinc.com> Link: https://lore.kernel.org/r/20231112095244.4015351-1-xiao.w.wang@intel.com Signed-off-by: Palmer Dabbelt <palmer@rivosinc.com>
1 parent c4db7ff commit 55ca8d7

File tree

2 files changed

+81
-1
lines changed

2 files changed

+81
-1
lines changed

arch/riscv/include/asm/arch_hweight.h

Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
/* SPDX-License-Identifier: GPL-2.0 */
2+
/*
3+
* Based on arch/x86/include/asm/arch_hweight.h
4+
*/
5+
6+
#ifndef _ASM_RISCV_HWEIGHT_H
7+
#define _ASM_RISCV_HWEIGHT_H
8+
9+
#include <asm/alternative-macros.h>
10+
#include <asm/hwcap.h>
11+
12+
#if (BITS_PER_LONG == 64)
13+
#define CPOPW "cpopw "
14+
#elif (BITS_PER_LONG == 32)
15+
#define CPOPW "cpop "
16+
#else
17+
#error "Unexpected BITS_PER_LONG"
18+
#endif
19+
20+
static __always_inline unsigned int __arch_hweight32(unsigned int w)
21+
{
22+
#ifdef CONFIG_RISCV_ISA_ZBB
23+
asm_volatile_goto(ALTERNATIVE("j %l[legacy]", "nop", 0,
24+
RISCV_ISA_EXT_ZBB, 1)
25+
: : : : legacy);
26+
27+
asm (".option push\n"
28+
".option arch,+zbb\n"
29+
CPOPW "%0, %0\n"
30+
".option pop\n"
31+
: "+r" (w) : :);
32+
33+
return w;
34+
35+
legacy:
36+
#endif
37+
return __sw_hweight32(w);
38+
}
39+
40+
static inline unsigned int __arch_hweight16(unsigned int w)
41+
{
42+
return __arch_hweight32(w & 0xffff);
43+
}
44+
45+
static inline unsigned int __arch_hweight8(unsigned int w)
46+
{
47+
return __arch_hweight32(w & 0xff);
48+
}
49+
50+
#if BITS_PER_LONG == 64
51+
static __always_inline unsigned long __arch_hweight64(__u64 w)
52+
{
53+
# ifdef CONFIG_RISCV_ISA_ZBB
54+
asm_volatile_goto(ALTERNATIVE("j %l[legacy]", "nop", 0,
55+
RISCV_ISA_EXT_ZBB, 1)
56+
: : : : legacy);
57+
58+
asm (".option push\n"
59+
".option arch,+zbb\n"
60+
"cpop %0, %0\n"
61+
".option pop\n"
62+
: "+r" (w) : :);
63+
64+
return w;
65+
66+
legacy:
67+
# endif
68+
return __sw_hweight64(w);
69+
}
70+
#else /* BITS_PER_LONG == 64 */
71+
static inline unsigned long __arch_hweight64(__u64 w)
72+
{
73+
return __arch_hweight32((u32)w) +
74+
__arch_hweight32((u32)(w >> 32));
75+
}
76+
#endif /* !(BITS_PER_LONG == 64) */
77+
78+
#endif /* _ASM_RISCV_HWEIGHT_H */

arch/riscv/include/asm/bitops.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -271,7 +271,9 @@ static __always_inline int variable_fls(unsigned int x)
271271
#include <asm-generic/bitops/fls64.h>
272272
#include <asm-generic/bitops/sched.h>
273273

274-
#include <asm-generic/bitops/hweight.h>
274+
#include <asm/arch_hweight.h>
275+
276+
#include <asm-generic/bitops/const_hweight.h>
275277

276278
#if (BITS_PER_LONG == 64)
277279
#define __AMO(op) "amo" #op ".d"

0 commit comments

Comments
 (0)