more potential janitor work: simplifying test for power of 2

Robert P. J. Day
2026-03-31T11:48:11Z

As another example of a cleanup script I wrote lo those many years
ago, this one checked if someone was manually testing if a value was a
power of two (do not make fun of my coding):

#!/bin/sh

DIR=${1-*}

echo "PATTERN: x & (x - 1):\n"
grep -Ern "([^\(\)]+) ?\& ?\(\1 ?- ?1\)" ${DIR}
echo "PATTERN: x & ((x) - 1):\n"
grep -Ern "([^\(\)]+) ?\& ?\(\(\1\) ?- ?1\)" ${DIR}
echo "PATTERN: (x) & (x - 1):\n"
grep -Ern "\(([^\(\)]+)\) ?\& ?\(\1 ?- ?1\)" ${DIR}
echo "PATTERN: (x) & ((x) - 1):\n"
grep -Ern "\(([^\(\)]+)\) ?\& ?\(\(\1\) ?- ?1\)" ${DIR}

As you can see, the typical hacky check was to test the value of
some variant of "n & (n - 1)" to see if n was in fact a power of 2.
Note that, when run from the top of the kernel source tree, you can
focus the search on any subdirectory. There is a ton of this sort of
thing scattered throughout the kernel source; for example:

$ test_for_power_of_2.sh drivers/net/ethernet
PATTERN: x & (x - 1):

drivers/net/ethernet/huawei/hinic/hinic_hw_eqs.c:756: if (eq->num_elem_in_pg & (eq->num_elem_in_pg - 1)) {
drivers/net/ethernet/huawei/hinic/hinic_hw_wq.c:456: if (num_q_pages & (num_q_pages - 1)) {
drivers/net/ethernet/huawei/hinic/hinic_hw_wq.c:523: if (q_depth & (q_depth - 1)) {
drivers/net/ethernet/huawei/hinic/hinic_hw_wq.c:620: if (q_depth & (q_depth - 1)) {
drivers/net/ethernet/huawei/hinic/hinic_hw_api_cmd.c:872: if (attr->num_cells & (attr->num_cells - 1)) {
drivers/net/ethernet/mellanox/mlx5/core/steering/hws/definer.c:691: if (flags & (flags - 1))
drivers/net/ethernet/mellanox/mlx5/core/steering/hws/definer.c:697: if (flags & (flags - 1))
drivers/net/ethernet/mellanox/mlx5/core/steering/hws/definer.c:702: if (flags & (flags - 1))
drivers/net/ethernet/mellanox/mlx5/core/steering/hws/definer.c:709: if (flags & (flags - 1))
drivers/net/ethernet/mellanox/mlx5/core/steering/sws/dr_rule.c:680: byte_mask = byte_mask & (byte_mask - 1);
drivers/net/ethernet/mellanox/mlx5/core/lib/dm.c:163: if (!length || (length & (length - 1)) ||
drivers/net/ethernet/sfc/siena/siena_sriov.c:505: return ((buf_count & (buf_count - 1)) || buf_count > max_buf_count);
drivers/net/ethernet/sfc/siena/siena_sriov.c:956: BUG_ON(vf->evq0_count & (vf->evq0_count - 1));
drivers/net/ethernet/broadcom/bnxt/bnxt.c:4736: while (pages & (pages - 1))
drivers/net/ethernet/broadcom/bnx2x/bnx2x_dcb.c:1230:#define POWER_OF_2(x) ((0 != x) && (0 == (x & (x-1))))
drivers/net/ethernet/synopsys/dwc-xlgmac-common.c:110: if (pdata->tx_desc_count & (pdata->tx_desc_count - 1)) {
drivers/net/ethernet/synopsys/dwc-xlgmac-common.c:118: if (pdata->rx_desc_count & (pdata->rx_desc_count - 1)) {
drivers/net/ethernet/freescale/fman/fman_keygen.c:700: if (hash_size == 0 || (hash_size & (hash_size - 1)) != 0) {
drivers/net/ethernet/chelsio/cxgb4/sge.c:5094: (fl_large_pg & (fl_large_pg-1)) != 0) {
drivers/net/ethernet/chelsio/cxgb4vf/sge.c:2649: (fl_large_pg & (fl_large_pg - 1)) != 0) {
drivers/net/ethernet/chelsio/cxgb/cxgb2.c:657: if (advertising & (advertising - 1))
drivers/net/ethernet/emulex/benet/be.h:136: BUG_ON(limit & (limit - 1));
drivers/net/ethernet/intel/igc/igc_leds.c:156: if (flags & (flags - 1))
drivers/net/ethernet/intel/igc/igc_ethtool.c:1286: (rule->filter.match_flags & (rule->filter.match_flags - 1)))
drivers/net/ethernet/intel/fm10k/fm10k_tlv.c:203: if (!msg || !len || len > 8 || (len & (len - 1)))
drivers/net/ethernet/marvell/octeontx2/af/rvu_npc_hash.c:1917: if ((table->mem_table.depth & (table->mem_table.depth - 1)) != 0) {
PATTERN: x & ((x) - 1):

PATTERN: (x) & (x - 1):

PATTERN: (x) & ((x) - 1):

This can be simplified using the kernel header file
include/linux/log2.h, which defines the test using an exclusive-OR
operation:

/**
* is_power_of_2() - check if a value is a power of two
* @n: the value to check
*
* Determine whether some value is a power of two, where zero is
* *not* considered a power of two.
* Return: true if @n is a power of 2, otherwise false.
*/
static __always_inline __attribute__((const))
bool is_power_of_2(unsigned long n)
{
return n - 1 < (n ^ (n - 1));
}

Lots of simplification there if one wants some janitor work; I don't
see a coccinelle test for this.

rday