[PATCH 2/3] s390/bitops: Limit return value range of __flogr()

Heiko Carstens posted 3 patches 5 months ago
There is a newer version of this series
[PATCH 2/3] s390/bitops: Limit return value range of __flogr()
Posted by Heiko Carstens 5 months ago
With the recent ffs() and ffs64() optimization a logical and operation was
removed, which allows the compiler to tell that the return value range of
both functions. This may lead to compile warnings as reported by the kernel
test robot.

Instead of only adding the not needed mask again, also add an __assume()
statement to tell newer compilers that they can assume a specific value
range. This allows newer compilers to optimize the not-needed logical and
operation away.

Also change the return type of flogr() to unsigned long and add the const
attribute to the function.

With this the reported warning is away, and in addition the kernel image
size is reduced by ~4kb.

Reported-by: kernel test robot <lkp@intel.com>
Closes: https://lore.kernel.org/oe-kbuild-all/202508211859.UoYsJbLN-lkp@intel.com/
Fixes: de88e74889a3 ("s390/bitops: Slightly optimize ffs() and fls64()")
Suggested-by: Juergen Christ <jchrist@linux.ibm.com>
Signed-off-by: Heiko Carstens <hca@linux.ibm.com>
---
 arch/s390/include/asm/bitops.h | 11 +++++++----
 1 file changed, 7 insertions(+), 4 deletions(-)

diff --git a/arch/s390/include/asm/bitops.h b/arch/s390/include/asm/bitops.h
index 9dfb687ba620..46b90b545986 100644
--- a/arch/s390/include/asm/bitops.h
+++ b/arch/s390/include/asm/bitops.h
@@ -130,11 +130,12 @@ static inline bool test_bit_inv(unsigned long nr,
  * where the most significant bit has bit number 0.
  * If no bit is set this function returns 64.
  */
-static __always_inline unsigned char __flogr(unsigned long word)
+static __always_inline __attribute_const__ unsigned long __flogr(unsigned long word)
 {
-	if (__builtin_constant_p(word)) {
-		unsigned long bit = 0;
+	unsigned long bit;
 
+	if (__builtin_constant_p(word)) {
+		bit = 0;
 		if (!word)
 			return 64;
 		if (!(word & 0xffffffff00000000UL)) {
@@ -169,7 +170,9 @@ static __always_inline unsigned char __flogr(unsigned long word)
 		asm volatile(
 			"       flogr   %[rp],%[rp]\n"
 			: [rp] "+d" (rp.pair) : : "cc");
-		return rp.even;
+		bit = rp.even;
+		__assume(bit <= 64);
+		return bit & 127;
 	}
 }
 
-- 
2.48.1
Re: [PATCH 2/3] s390/bitops: Limit return value range of __flogr()
Posted by kernel test robot 4 months, 4 weeks ago
Hi Heiko,

kernel test robot noticed the following build errors:

[auto build test ERROR on s390/features]
[also build test ERROR on next-20250911]
[cannot apply to linus/master v6.17-rc5]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch#_base_tree_information]

url:    https://github.com/intel-lab-lkp/linux/commits/Heiko-Carstens/Compiler-Attributes-Add-__assume-macro/20250910-231949
base:   https://git.kernel.org/pub/scm/linux/kernel/git/s390/linux.git features
patch link:    https://lore.kernel.org/r/20250910151216.646600-3-hca%40linux.ibm.com
patch subject: [PATCH 2/3] s390/bitops: Limit return value range of __flogr()
config: s390-randconfig-002-20250911 (https://download.01.org/0day-ci/archive/20250911/202509112018.eZI47cSy-lkp@intel.com/config)
compiler: clang version 16.0.6 (https://github.com/llvm/llvm-project 7cbf1a2591520c2491aa35339f227775f4d3adf6)
reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20250911/202509112018.eZI47cSy-lkp@intel.com/reproduce)

If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <lkp@intel.com>
| Closes: https://lore.kernel.org/oe-kbuild-all/202509112018.eZI47cSy-lkp@intel.com/

All errors (new ones prefixed by >>):

   In file included from kernel/bounds.c:13:
   In file included from include/linux/log2.h:12:
   In file included from include/linux/bitops.h:67:
>> arch/s390/include/asm/bitops.h:174:3: error: '__assume__' attribute cannot be applied to a statement
                   __assume(bit <= 64);
                   ^                  ~
   include/linux/compiler_attributes.h:68:56: note: expanded from macro '__assume'
   # define __assume(expr)                 __attribute__((__assume__(expr)))
                                                          ^
   1 error generated.
   make[3]: *** [scripts/Makefile.build:182: kernel/bounds.s] Error 1 shuffle=1723937077
   make[3]: Target 'prepare' not remade because of errors.
   make[2]: *** [Makefile:1282: prepare0] Error 2 shuffle=1723937077
   make[2]: Target 'prepare' not remade because of errors.
   make[1]: *** [Makefile:248: __sub-make] Error 2 shuffle=1723937077
   make[1]: Target 'prepare' not remade because of errors.
   make: *** [Makefile:248: __sub-make] Error 2 shuffle=1723937077
   make: Target 'prepare' not remade because of errors.


vim +/__assume__ +174 arch/s390/include/asm/bitops.h

   124	
   125	/**
   126	 * __flogr - find leftmost one
   127	 * @word - The word to search
   128	 *
   129	 * Returns the bit number of the most significant bit set,
   130	 * where the most significant bit has bit number 0.
   131	 * If no bit is set this function returns 64.
   132	 */
   133	static __always_inline __attribute_const__ unsigned long __flogr(unsigned long word)
   134	{
   135		unsigned long bit;
   136	
   137		if (__builtin_constant_p(word)) {
   138			bit = 0;
   139			if (!word)
   140				return 64;
   141			if (!(word & 0xffffffff00000000UL)) {
   142				word <<= 32;
   143				bit += 32;
   144			}
   145			if (!(word & 0xffff000000000000UL)) {
   146				word <<= 16;
   147				bit += 16;
   148			}
   149			if (!(word & 0xff00000000000000UL)) {
   150				word <<= 8;
   151				bit += 8;
   152			}
   153			if (!(word & 0xf000000000000000UL)) {
   154				word <<= 4;
   155				bit += 4;
   156			}
   157			if (!(word & 0xc000000000000000UL)) {
   158				word <<= 2;
   159				bit += 2;
   160			}
   161			if (!(word & 0x8000000000000000UL)) {
   162				word <<= 1;
   163				bit += 1;
   164			}
   165			return bit;
   166		} else {
   167			union register_pair rp __uninitialized;
   168	
   169			rp.even = word;
   170			asm volatile(
   171				"       flogr   %[rp],%[rp]\n"
   172				: [rp] "+d" (rp.pair) : : "cc");
   173			bit = rp.even;
 > 174			__assume(bit <= 64);
   175			return bit & 127;
   176		}
   177	}
   178	

-- 
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki
Re: [PATCH 2/3] s390/bitops: Limit return value range of __flogr()
Posted by Juergen Christ 4 months, 4 weeks ago
> With the recent ffs() and ffs64() optimization a logical and operation was
> removed, which allows the compiler to tell that the return value range of
> both functions. This may lead to compile warnings as reported by the kernel
> test robot.
> 
> Instead of only adding the not needed mask again, also add an __assume()
> statement to tell newer compilers that they can assume a specific value
> range. This allows newer compilers to optimize the not-needed logical and
> operation away.
> 
> Also change the return type of flogr() to unsigned long and add the const
> attribute to the function.
> 
> With this the reported warning is away, and in addition the kernel image
> size is reduced by ~4kb.
> 
> Reported-by: kernel test robot <lkp@intel.com>
> Closes: https://lore.kernel.org/oe-kbuild-all/202508211859.UoYsJbLN-lkp@intel.com/
> Fixes: de88e74889a3 ("s390/bitops: Slightly optimize ffs() and fls64()")
> Suggested-by: Juergen Christ <jchrist@linux.ibm.com>
> Signed-off-by: Heiko Carstens <hca@linux.ibm.com>

Reviewed-by: Juergen Christ <jchrist@linux.ibm.com>