Skip to content

Commit 7c67928

Browse files
hcahcaAlexander Gordeev
authored andcommitted
s390: Provide optimized __arch_hweight*() implementations
Make use of the popcnt instruction to provide optimized __arch_hweight*() implementations. The generated code is shorter and avoids rather expensive functions calls. Acked-by: Alexander Gordeev <[email protected]> Signed-off-by: Heiko Carstens <[email protected]> Signed-off-by: Alexander Gordeev <[email protected]>
1 parent 447360d commit 7c67928

File tree

3 files changed

+79
-2
lines changed

3 files changed

+79
-2
lines changed

arch/s390/Kconfig

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ config ARCH_PROC_KCORE_TEXT
2121
def_bool y
2222

2323
config GENERIC_HWEIGHT
24-
def_bool y
24+
def_bool !HAVE_MARCH_Z196_FEATURES
2525

2626
config GENERIC_BUG
2727
def_bool y if BUG

arch/s390/include/asm/arch_hweight.h

Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
/* SPDX-License-Identifier: GPL-2.0 */
2+
3+
#ifndef _ASM_S390_ARCH_HWEIGHT_H
4+
#define _ASM_S390_ARCH_HWEIGHT_H
5+
6+
#include <linux/types.h>
7+
8+
static __always_inline unsigned long popcnt_z196(unsigned long w)
9+
{
10+
unsigned long cnt;
11+
12+
asm volatile(".insn rrf,0xb9e10000,%[cnt],%[w],0,0"
13+
: [cnt] "=d" (cnt)
14+
: [w] "d" (w)
15+
: "cc");
16+
return cnt;
17+
}
18+
19+
static __always_inline unsigned long popcnt_z15(unsigned long w)
20+
{
21+
unsigned long cnt;
22+
23+
asm volatile(".insn rrf,0xb9e10000,%[cnt],%[w],8,0"
24+
: [cnt] "=d" (cnt)
25+
: [w] "d" (w)
26+
: "cc");
27+
return cnt;
28+
}
29+
30+
static __always_inline unsigned long __arch_hweight64(__u64 w)
31+
{
32+
if (IS_ENABLED(CONFIG_HAVE_MARCH_Z15_FEATURES))
33+
return popcnt_z15(w);
34+
if (IS_ENABLED(CONFIG_HAVE_MARCH_Z196_FEATURES)) {
35+
w = popcnt_z196(w);
36+
w += w >> 32;
37+
w += w >> 16;
38+
w += w >> 8;
39+
return w & 0xff;
40+
}
41+
return __sw_hweight64(w);
42+
}
43+
44+
static __always_inline unsigned int __arch_hweight32(unsigned int w)
45+
{
46+
if (IS_ENABLED(CONFIG_HAVE_MARCH_Z15_FEATURES))
47+
return popcnt_z15(w);
48+
if (IS_ENABLED(CONFIG_HAVE_MARCH_Z196_FEATURES)) {
49+
w = popcnt_z196(w);
50+
w += w >> 16;
51+
w += w >> 8;
52+
return w & 0xff;
53+
}
54+
return __sw_hweight32(w);
55+
}
56+
57+
static __always_inline unsigned int __arch_hweight16(unsigned int w)
58+
{
59+
if (IS_ENABLED(CONFIG_HAVE_MARCH_Z15_FEATURES))
60+
return popcnt_z15((unsigned short)w);
61+
if (IS_ENABLED(CONFIG_HAVE_MARCH_Z196_FEATURES)) {
62+
w = popcnt_z196(w);
63+
w += w >> 8;
64+
return w & 0xff;
65+
}
66+
return __sw_hweight16(w);
67+
}
68+
69+
static __always_inline unsigned int __arch_hweight8(unsigned int w)
70+
{
71+
if (IS_ENABLED(CONFIG_HAVE_MARCH_Z196_FEATURES))
72+
return popcnt_z196((unsigned char)w);
73+
return __sw_hweight8(w);
74+
}
75+
76+
#endif /* _ASM_S390_ARCH_HWEIGHT_H */

arch/s390/include/asm/bitops.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -379,8 +379,9 @@ static inline int fls(unsigned int word)
379379
return fls64(word);
380380
}
381381

382+
#include <asm/arch_hweight.h>
383+
#include <asm-generic/bitops/const_hweight.h>
382384
#include <asm-generic/bitops/ffz.h>
383-
#include <asm-generic/bitops/hweight.h>
384385
#include <asm-generic/bitops/sched.h>
385386
#include <asm-generic/bitops/le.h>
386387
#include <asm-generic/bitops/ext2-atomic-setbit.h>

0 commit comments

Comments
 (0)