Define const_*() variants of the non-atomic bitops to be used when the input arguments are compile-time constants, so that the compiler will be always able to resolve those to compile-time constants as well. Those are mostly direct aliases for generic_*() with one exception for const_test_bit(): the original one is declared atomic-safe and thus doesn't discard the `volatile` qualifier, so in order to let optimize code, define it separately disregarding the qualifier. Add them to the compile-time type checks as well just in case.
Unified · Split
| @@ -127,4 +127,35 @@ generic_test_bit(unsigned long nr, const volatile unsigned long *addr) · 126 unmodified lines | ||
| 127 | 127 | return 1UL & (addr[BIT_WORD(nr)] >> (nr & (BITS_PER_LONG-1))); |
| 128 | 128 | } |
| 129 | 129 | |
| 130 | +/* | |
| 131 | + * const_*() definitions provide good compile-time optimizations when | |
| 132 | + * the passed arguments can be resolved at compile time. | |
| 133 | + */ | |
| 134 | +#define const___set_bit generic___set_bit | |
| 135 | +#define const___clear_bit generic___clear_bit | |
| 136 | +#define const___change_bit generic___change_bit | |
| 137 | +#define const___test_and_set_bit generic___test_and_set_bit | |
| 138 | +#define const___test_and_clear_bit generic___test_and_clear_bit | |
| 139 | +#define const___test_and_change_bit generic___test_and_change_bit | |
| 140 | + | |
| 141 | +/** | |
| 142 | + * const_test_bit - Determine whether a bit is set | |
| 143 | + * @nr: bit number to test | |
| 144 | + * @addr: Address to start counting from | |
| 145 | + * | |
| 146 | + * A version of generic_test_bit() which discards the `volatile` qualifier to | |
| 147 | + * allow a compiler to optimize code harder. Non-atomic and to be called only | |
| 148 | + * for testing compile-time constants, e.g. by the corresponding macros, not | |
| 149 | + * directly from "regular" code. | |
| 150 | + */ | |
| 151 | +static __always_inline bool | |
| 152 | +const_test_bit(unsigned long nr, const volatile unsigned long *addr) | |
| 153 | +{ | |
| 154 | + const unsigned long *p = (const unsigned long *)addr + BIT_WORD(nr); | |
| 155 | + unsigned long mask = BIT_MASK(nr); | |
| 156 | + unsigned long val = *p; | |
| 157 | + | |
| 158 | + return !!(val & mask); | |
| 159 | +} | |
| 160 | + | |
| 130 | 161 | #endif /* __ASM_GENERIC_BITOPS_GENERIC_NON_ATOMIC_H */ |
| @@ -37,6 +37,7 @@ extern unsigned long __sw_hweight64(__u64 w); · 36 unmodified lines | ||
| 37 | 37 | /* Check that the bitops prototypes are sane */ |
| 38 | 38 | #define __check_bitop_pr(name) \ |
| 39 | 39 | static_assert(__same_type(arch_##name, generic_##name) && \ |
| 40 | + __same_type(const_##name, generic_##name) && \ | |
| 40 | 41 | __same_type(name, generic_##name)) |
| 41 | 42 | |
| 42 | 43 | __check_bitop_pr(__set_bit); |