Skip to content

Commit 3044233

Browse files
committed
py/misc: Add a popcount(uint32_t) implementation.
This makes the existing popcount(uint32_t) implementation found in the RV32 emitter available to the rest of the codebase. This version of popcount will use intrinsic or builtin implementations if they are available, falling back to a generic implementation if that is not the case. Signed-off-by: Alessandro Gatti <a.gatti@frob.it>
1 parent a5270c8 commit 3044233

File tree

2 files changed

+19
-22
lines changed

2 files changed

+19
-22
lines changed

py/asmrv32.c

+2-22
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@
2929
#include <string.h>
3030

3131
#include "py/emit.h"
32+
#include "py/misc.h"
3233
#include "py/mpconfig.h"
3334

3435
// wrapper around everything in this file
@@ -43,27 +44,6 @@
4344
#define DEBUG_printf(...) (void)0
4445
#endif
4546

46-
#ifndef MP_POPCOUNT
47-
#ifdef _MSC_VER
48-
#include <intrin.h>
49-
#define MP_POPCOUNT __popcnt
50-
#else
51-
#if defined __has_builtin
52-
#if __has_builtin(__builtin_popcount)
53-
#define MP_POPCOUNT __builtin_popcount
54-
#endif
55-
#else
56-
static uint32_t fallback_popcount(uint32_t value) {
57-
value = value - ((value >> 1) & 0x55555555);
58-
value = (value & 0x33333333) + ((value >> 2) & 0x33333333);
59-
value = (value + (value >> 4)) & 0x0F0F0F0F;
60-
return value * 0x01010101;
61-
}
62-
#define MP_POPCOUNT fallback_popcount
63-
#endif
64-
#endif
65-
#endif
66-
6747
#define INTERNAL_TEMPORARY ASM_RV32_REG_S0
6848
#define AVAILABLE_REGISTERS_COUNT 32
6949

@@ -249,7 +229,7 @@ static void adjust_stack(asm_rv32_t *state, mp_int_t stack_size) {
249229
// stack to hold all the tainted registers and an arbitrary amount of space
250230
// for locals.
251231
static void emit_function_prologue(asm_rv32_t *state, mp_uint_t registers) {
252-
mp_uint_t registers_count = MP_POPCOUNT(registers);
232+
mp_uint_t registers_count = mp_popcount(registers);
253233
state->stack_size = (registers_count + state->locals_count) * sizeof(uint32_t);
254234
mp_uint_t old_saved_registers_mask = state->saved_registers_mask;
255235
// Move stack pointer up.

py/misc.h

+17
Original file line numberDiff line numberDiff line change
@@ -370,12 +370,29 @@ static inline uint32_t mp_ctz(uint32_t x) {
370370
static inline bool mp_check(bool value) {
371371
return value;
372372
}
373+
374+
static inline uint32_t mp_popcount(uint32_t x) {
375+
return __popcnt(x);
376+
}
373377
#else
374378
#define mp_clz(x) __builtin_clz(x)
375379
#define mp_clzl(x) __builtin_clzl(x)
376380
#define mp_clzll(x) __builtin_clzll(x)
377381
#define mp_ctz(x) __builtin_ctz(x)
378382
#define mp_check(x) (x)
383+
#if defined __has_builtin
384+
#if __has_builtin(__builtin_popcount)
385+
#define mp_popcount(x) __builtin_popcount(x)
386+
#endif
387+
#endif
388+
#if !defined(mp_popcount)
389+
static inline uint32_t mp_popcount(uint32_t x) {
390+
x = x - ((x >> 1) & 0x55555555);
391+
x = (x & 0x33333333) + ((x >> 2) & 0x33333333);
392+
x = (x + (x >> 4)) & 0x0F0F0F0F;
393+
return x * 0x01010101;
394+
}
395+
#endif
379396
#endif
380397

381398
// mp_int_t can be larger than long, i.e. Windows 64-bit, nan-box variants

0 commit comments

Comments
 (0)