Skip to content

Commit 3e7e5ba

Browse files
alobakinYuryNorov
authored andcommitted
bitmap: don't assume compiler evaluates small mem*() builtins calls
Intel kernel bot triggered the build bug on ARC architecture that in fact is as follows: DECLARE_BITMAP(bitmap, BITS_PER_LONG); bitmap_clear(bitmap, 0, BITS_PER_LONG); BUILD_BUG_ON(!__builtin_constant_p(*bitmap)); which can be expanded to: unsigned long bitmap[1]; memset(bitmap, 0, sizeof(*bitmap)); BUILD_BUG_ON(!__builtin_constant_p(*bitmap)); In most cases, a compiler is able to expand small/simple mem*() calls to simple assignments or bitops, in this case that would mean: unsigned long bitmap[1] = { 0 }; BUILD_BUG_ON(!__builtin_constant_p(*bitmap)); and on most architectures this works, but not on ARC, despite having -O3 for every build. So, to make this work, in case when the last bit to modify is still within the first long (small_const_nbits()), just use plain assignments for the rest of bitmap_*() functions which still use mem*(), but didn't receive such compile-time optimizations yet. This doesn't have the same coverage as compilers provide, but at least something to start: text: add/remove: 3/7 grow/shrink: 43/78 up/down: 1848/-3370 (-1546) data: add/remove: 1/11 grow/shrink: 0/8 up/down: 4/-356 (-352) notably cpumask_*() family when NR_CPUS <= BITS_PER_LONG: netif_get_num_default_rss_queues 38 4 -34 cpumask_copy 90 - -90 cpumask_clear 146 - -146 and the abovementioned assertion started passing. Signed-off-by: Alexander Lobakin <alexandr.lobakin@intel.com> Signed-off-by: Yury Norov <yury.norov@gmail.com>
1 parent 2f7ee2a commit 3e7e5ba

File tree

1 file changed

+19
-3
lines changed

1 file changed

+19
-3
lines changed

include/linux/bitmap.h

Lines changed: 19 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -238,20 +238,32 @@ extern int bitmap_print_list_to_buf(char *buf, const unsigned long *maskp,
238238
static inline void bitmap_zero(unsigned long *dst, unsigned int nbits)
239239
{
240240
unsigned int len = BITS_TO_LONGS(nbits) * sizeof(unsigned long);
241-
memset(dst, 0, len);
241+
242+
if (small_const_nbits(nbits))
243+
*dst = 0;
244+
else
245+
memset(dst, 0, len);
242246
}
243247

244248
static inline void bitmap_fill(unsigned long *dst, unsigned int nbits)
245249
{
246250
unsigned int len = BITS_TO_LONGS(nbits) * sizeof(unsigned long);
247-
memset(dst, 0xff, len);
251+
252+
if (small_const_nbits(nbits))
253+
*dst = ~0UL;
254+
else
255+
memset(dst, 0xff, len);
248256
}
249257

250258
static inline void bitmap_copy(unsigned long *dst, const unsigned long *src,
251259
unsigned int nbits)
252260
{
253261
unsigned int len = BITS_TO_LONGS(nbits) * sizeof(unsigned long);
254-
memcpy(dst, src, len);
262+
263+
if (small_const_nbits(nbits))
264+
*dst = *src;
265+
else
266+
memcpy(dst, src, len);
255267
}
256268

257269
/*
@@ -431,6 +443,8 @@ static __always_inline void bitmap_set(unsigned long *map, unsigned int start,
431443
{
432444
if (__builtin_constant_p(nbits) && nbits == 1)
433445
__set_bit(start, map);
446+
else if (small_const_nbits(start + nbits))
447+
*map |= GENMASK(start + nbits - 1, start);
434448
else if (__builtin_constant_p(start & BITMAP_MEM_MASK) &&
435449
IS_ALIGNED(start, BITMAP_MEM_ALIGNMENT) &&
436450
__builtin_constant_p(nbits & BITMAP_MEM_MASK) &&
@@ -445,6 +459,8 @@ static __always_inline void bitmap_clear(unsigned long *map, unsigned int start,
445459
{
446460
if (__builtin_constant_p(nbits) && nbits == 1)
447461
__clear_bit(start, map);
462+
else if (small_const_nbits(start + nbits))
463+
*map &= ~GENMASK(start + nbits - 1, start);
448464
else if (__builtin_constant_p(start & BITMAP_MEM_MASK) &&
449465
IS_ALIGNED(start, BITMAP_MEM_ALIGNMENT) &&
450466
__builtin_constant_p(nbits & BITMAP_MEM_MASK) &&

0 commit comments

Comments
 (0)