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 | return 1UL & (addr[BIT_WORD(nr)] >> (nr & (BITS_PER_LONG-1))); | 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 | #endif /* __ASM_GENERIC_BITOPS_GENERIC_NON_ATOMIC_H */ | 161 | #endif /* __ASM_GENERIC_BITOPS_GENERIC_NON_ATOMIC_H */ |
| @@ -37,6 +37,7 @@ extern unsigned long __sw_hweight64(__u64 w); · 36 unmodified lines | |||
| 37 | /* Check that the bitops prototypes are sane */ | 37 | /* Check that the bitops prototypes are sane */ |
| 38 | #define __check_bitop_pr(name) \ | 38 | #define __check_bitop_pr(name) \ |
| 39 | static_assert(__same_type(arch_##name, generic_##name) && \ | 39 | static_assert(__same_type(arch_##name, generic_##name) && \ |
| 40 | __same_type(const_##name, generic_##name) && \ | ||
| 40 | __same_type(name, generic_##name)) | 41 | __same_type(name, generic_##name)) |
| 41 | 42 | ||
| 42 | __check_bitop_pr(__set_bit); | 43 | __check_bitop_pr(__set_bit); |