Skip to content

Commit 945fc9d

Browse files
committed
xtensa: Add __attribute_const__ to ffs()-family implementations
While tracking down a problem where constant expressions used by BUILD_BUG_ON() suddenly stopped working[1], we found that an added static initializer was convincing the compiler that it couldn't track the state of the prior statically initialized value. Tracing this down found that ffs() was used in the initializer macro, but since it wasn't marked with __attribute__const__, the compiler had to assume the function might change variable states as a side-effect (which is not true for ffs(), which provides deterministic math results). Add missing __attribute_const__ annotations to Xtensa's implementations of ffs(), __ffs(), fls(), __fls(), ffz() functions. These are pure mathematical functions that always return the same result for the same input with no side effects, making them eligible for compiler optimization. Build tested ARCH=xtensa defconfig with GCC xtensa-linux 15.1.0. Link: KSPP#364 [1] Acked-by: Peter Zijlstra (Intel) <peterz@infradead.org> Link: https://lore.kernel.org/r/20250804164417.1612371-15-kees@kernel.org Signed-off-by: Kees Cook <kees@kernel.org>
1 parent b77fee8 commit 945fc9d

1 file changed

Lines changed: 5 additions & 5 deletions

File tree

arch/xtensa/include/asm/bitops.h

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ static inline unsigned long __cntlz (unsigned long x)
3737
* bit 0 is the LSB of addr; bit 32 is the LSB of (addr+1).
3838
*/
3939

40-
static inline int ffz(unsigned long x)
40+
static inline int __attribute_const__ ffz(unsigned long x)
4141
{
4242
return 31 - __cntlz(~x & -~x);
4343
}
@@ -46,7 +46,7 @@ static inline int ffz(unsigned long x)
4646
* __ffs: Find first bit set in word. Return 0 for bit 0
4747
*/
4848

49-
static inline unsigned long __ffs(unsigned long x)
49+
static inline __attribute_const__ unsigned long __ffs(unsigned long x)
5050
{
5151
return 31 - __cntlz(x & -x);
5252
}
@@ -57,7 +57,7 @@ static inline unsigned long __ffs(unsigned long x)
5757
* differs in spirit from the above ffz (man ffs).
5858
*/
5959

60-
static inline int ffs(unsigned long x)
60+
static inline __attribute_const__ int ffs(unsigned long x)
6161
{
6262
return 32 - __cntlz(x & -x);
6363
}
@@ -67,7 +67,7 @@ static inline int ffs(unsigned long x)
6767
* Note fls(0) = 0, fls(1) = 1, fls(0x80000000) = 32.
6868
*/
6969

70-
static inline int fls (unsigned int x)
70+
static inline __attribute_const__ int fls (unsigned int x)
7171
{
7272
return 32 - __cntlz(x);
7373
}
@@ -78,7 +78,7 @@ static inline int fls (unsigned int x)
7878
*
7979
* Undefined if no set bit exists, so code should check against 0 first.
8080
*/
81-
static inline unsigned long __fls(unsigned long word)
81+
static inline __attribute_const__ unsigned long __fls(unsigned long word)
8282
{
8383
return 31 - __cntlz(word);
8484
}

0 commit comments

Comments
 (0)