[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
ffsl: optimization for non-GCC
From: |
Bruno Haible |
Subject: |
ffsl: optimization for non-GCC |
Date: |
Fri, 14 Oct 2011 02:19:59 +0200 |
User-agent: |
KMail/1.13.6 (Linux/2.6.37.6-0.5-desktop; KDE/4.6.0; x86_64; ; ) |
Before I added the previous optimization, I got this warning and code
on mingw:
$ gcc-3 -mno-cygwin -DHAVE_CONFIG_H -I. -I.. -DGNULIB_STRICT_CHECKING=1
-I/usr/local/mingw/include -Wall -S -O2 ffsl.c
In file included from ffsl.c:3:
ffsl.h: In function `ffsl':
ffsl.h:44: warning: right shift count >= width of type
$ cat ffsl.s
.file "ffsl.c"
.text
.p2align 4,,15
.globl _ffsl
.def _ffsl; .scl 2; .type 32; .endef
_ffsl:
pushl %ebp
xorl %eax, %eax
movl %esp, %ebp
movl 8(%ebp), %edx
testl %edx, %edx
je L1
xorl %ecx, %ecx
bsfl %edx, %eax
sete %cl
negl %ecx
orl %ecx, %eax
incl %eax
L1:
popl %ebp
ret
This is considerably longer than necessary. With the patch below, the
code boils down to
$ cat ffsl.s
.file "ffsl.c"
.text
.p2align 4,,15
.globl _ffsl
.def _ffsl; .scl 2; .type 32; .endef
_ffsl:
pushl %ebp
xorl %edx, %edx
movl %esp, %ebp
bsfl 8(%ebp), %eax
sete %dl
negl %edx
popl %ebp
orl %edx, %eax
incl %eax
ret
Also, the warning goes away by use of a valid shift count, even in dead code.
And let me add a comment about a tempting code change that would provoke a
test failure on Solaris 10/x86 with "cc -O" (only when -O is present - a
clear indication for a compiler bug).
2011-10-13 Bruno Haible <address@hidden>
ffsl: Optimize on 32-bit platforms.
* lib/ffsl.h (FUNC): If TYPE has the same representation as 'int', just
use ffs() without a loop.
*** lib/ffsl.h.orig Fri Oct 14 02:10:41 2011
--- lib/ffsl.h Fri Oct 14 02:09:43 2011
***************
*** 34,51 ****
#if (__GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 4)) && defined
GCC_BUILTIN
return GCC_BUILTIN (i);
#else
! int result = 0;
! unsigned TYPE j = i;
!
! /* GCC has __builtin_ffs, but it is limited to int. */
! if (!i)
! return 0;
! while (1)
{
! if ((unsigned int) j)
! return result + ffs ((unsigned int) j);
! j >>= CHAR_BIT * sizeof (unsigned int);
! result += CHAR_BIT * sizeof (unsigned int);
}
#endif
}
--- 34,67 ----
#if (__GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 4)) && defined
GCC_BUILTIN
return GCC_BUILTIN (i);
#else
! if (sizeof (TYPE) == sizeof (int))
! return ffs (i);
! else
{
! unsigned TYPE j = i;
! /* Split j into chunks, and look at one chunk after the other. */
! /* Define chunk_bits so as to avoid a GCC warning
! "right shift count >= width of type"
! if sizeof (TYPE) == sizeof (int). */
! enum
! {
! chunk_bits = (sizeof (TYPE) != sizeof (int)
! ? CHAR_BIT * sizeof (unsigned int)
! : 0)
! };
! int result = 0;
!
! /* It is tempting to write if (!j) here, but if we do this,
! Solaris 10/x86 "cc -O" miscompiles the code. */
! if (!i)
! return 0;
! while (1)
! {
! if ((unsigned int) j)
! return result + ffs ((unsigned int) j);
! j >>= chunk_bits;
! result += chunk_bits;
! }
}
#endif
}
--
In memoriam Bekir Çoban-zade <http://en.wikipedia.org/wiki/Bekir_Çoban-zade>
- ffsl: optimization for non-GCC,
Bruno Haible <=