Fix heap when size_t is not unsigned long long
When the width of size_t doesn't match the width of the unsigned long long type, the number of leading zeros doesn't match, making the heap_get_move() function return incorrect values. This is the case on ARMv7 with 32 bits, where size_t is 32 bits but unsigned long long is 64 bits. We check the size of size_t to select which builtin we need. The sizeof operator cannot be used at preprocessing, so we rely on the optimizations to only leave the proper assembly instruction. Fixes: https://pm.bsc.es/gitlab/rarias/ovni/-/issues/193
This commit is contained in:
parent
91e8367d35
commit
3d8c84e17c
@ -1,4 +1,4 @@
|
|||||||
/* Copyright (c) 2021-2023 Barcelona Supercomputing Center (BSC)
|
/* Copyright (c) 2021-2024 Barcelona Supercomputing Center (BSC)
|
||||||
* SPDX-License-Identifier: GPL-3.0-or-later */
|
* SPDX-License-Identifier: GPL-3.0-or-later */
|
||||||
|
|
||||||
/* Author: David Alvarez
|
/* Author: David Alvarez
|
||||||
@ -112,6 +112,20 @@ heap_max(heap_head_t *head)
|
|||||||
return head->root;
|
return head->root;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline int
|
||||||
|
leading_zeros(size_t x)
|
||||||
|
{
|
||||||
|
/* Call and if()'s optimized by the compiler with -O2 */
|
||||||
|
if (sizeof(size_t) == sizeof(unsigned int))
|
||||||
|
return __builtin_clz(x);
|
||||||
|
else if (sizeof(size_t) == sizeof(unsigned long))
|
||||||
|
return __builtin_clzl(x);
|
||||||
|
else if (sizeof(size_t) == sizeof(unsigned long long))
|
||||||
|
return __builtin_clzll(x);
|
||||||
|
else
|
||||||
|
die("cannot find suitable size for __builtin_clz*");
|
||||||
|
}
|
||||||
|
|
||||||
/* Get a move to reach a leaf */
|
/* Get a move to reach a leaf */
|
||||||
static inline int
|
static inline int
|
||||||
heap_get_move(size_t *node /*out*/)
|
heap_get_move(size_t *node /*out*/)
|
||||||
@ -119,8 +133,8 @@ heap_get_move(size_t *node /*out*/)
|
|||||||
size_t aux_node = *node;
|
size_t aux_node = *node;
|
||||||
|
|
||||||
// Round to previous po2
|
// Round to previous po2
|
||||||
size_t base = (1ULL) << (sizeof(size_t) * 8
|
int shift = sizeof(size_t) * 8 - leading_zeros(aux_node) - 1;
|
||||||
- __builtin_clzll(aux_node) - 1);
|
size_t base = 1ULL << shift;
|
||||||
|
|
||||||
aux_node -= base / 2;
|
aux_node -= base / 2;
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user