This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: RFA: Add builtin bitcounting bitops for xstormy16


Hi Richard,

I'd rather keep this limited to the stormy16 port for now.

OK, attached is a revised patch to tidy up the bit counting functions in stormy16-lib.c. It turns out to be more extensive than I had originally planned and there are a couple of features of the patch that you may not like:


* I added libgcc2.h to the LIBGCC_DEPS variable in gcc/Makefile.in.

    Originally I was just trying to make sure that stormy16-lib.c
    would be rebuilt if libgcc2.h was updated, but when I investigated
    it turned out that almost none of the libgcc2.c functions had a
    dependency upon this header.

  * It adds the dimension of the __clz_tab[] and __popcount_tab[] arrays
    to their definitions and prototypes.  I do not know why this number
    - 256 - was omitted in the first place, perhaps there is a good
    reason ?  I put the dimension in because I think that it is a good
    idea to give the compiler as much information as possible.

In addition the patch adds a copyright notice to stormy16-lib.c, and updates the types that it is using to match those used in libgcc2.c. It also moves the prototypes for __clz_tab[] inside longlong.h so that this is only done if it has not been included from inside libgcc2.h.

What do you think of this version ? Is it OK to go in ? I have tested it again by building and running gcc.c-torture/execute/builtin-bitops.c.

Cheers
  Nick

gcc/ChangeLog
2005-09-08  Nick Clifton  <nickc@redhat.com>

	* Makefile.in (LIBGCC_DEPS): Add libgcc2.h.
	* libgcc2.c (__clz_tab[], __popcount_tab[]): Set the fixed
	dimension of these arrays.
	* libgcc2.h (__clz_tab[], __popcount_tab[]): Add exports of
	these arrays.
	* longlong.h: Only provide a prototype for the __clz_tab[] array
	if this header has not been included from libgcc2.h.
	* config/stormy16/stormy16-lib2.c: Include libgcc2.h rather than
	defining own types.
	Provide prototypes for exported functions.
	Use the __clz_tab[] and __popcount_tab[] arrays provided by
	libgcc2.c.
Index: gcc/Makefile.in
===================================================================
RCS file: /cvs/gcc/gcc/gcc/Makefile.in,v
retrieving revision 1.1537
diff -c -3 -p -r1.1537 Makefile.in
*** gcc/Makefile.in	29 Aug 2005 13:52:32 -0000	1.1537
--- gcc/Makefile.in	8 Sep 2005 11:31:22 -0000
*************** libgcc.mk: config.status Makefile mklibg
*** 1350,1356 ****
  # All the things that might cause us to want to recompile bits of libgcc.
  LIBGCC_DEPS = $(GCC_PASSES) $(LANGUAGES) stmp-int-hdrs $(STMP_FIXPROTO) \
  	libgcc.mk $(srcdir)/libgcc2.c $(srcdir)/libgcov.c $(TCONFIG_H) \
! 	$(MACHMODE_H) longlong.h gbl-ctors.h config.status \
  	tsystem.h $(FPBIT) $(DPBIT) $(TPBIT) $(LIB2ADD) \
  	$(LIB2ADD_ST) $(LIB2ADDEH) $(LIB2ADDEHDEP) $(EXTRA_PARTS) \
  	$(srcdir)/config/$(LIB1ASMSRC) \
--- 1350,1356 ----
  # All the things that might cause us to want to recompile bits of libgcc.
  LIBGCC_DEPS = $(GCC_PASSES) $(LANGUAGES) stmp-int-hdrs $(STMP_FIXPROTO) \
  	libgcc.mk $(srcdir)/libgcc2.c $(srcdir)/libgcov.c $(TCONFIG_H) \
! 	$(MACHMODE_H) longlong.h gbl-ctors.h config.status $(srcdir)/libgcc2.h \
  	tsystem.h $(FPBIT) $(DPBIT) $(TPBIT) $(LIB2ADD) \
  	$(LIB2ADD_ST) $(LIB2ADDEH) $(LIB2ADDEHDEP) $(EXTRA_PARTS) \
  	$(srcdir)/config/$(LIB1ASMSRC) \
Index: gcc/libgcc2.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/libgcc2.c,v
retrieving revision 1.193
diff -c -3 -p -r1.193 libgcc2.c
*** gcc/libgcc2.c	2 Jul 2005 08:51:56 -0000	1.193
--- gcc/libgcc2.c	8 Sep 2005 11:31:23 -0000
*************** __udiv_w_sdiv (UWtype *rp __attribute__ 
*** 648,654 ****
  #endif
  
  #ifdef L_clz
! const UQItype __clz_tab[] =
  {
    0,1,2,2,3,3,3,3,4,4,4,4,4,4,4,4,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,
    6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
--- 648,654 ----
  #endif
  
  #ifdef L_clz
! const UQItype __clz_tab[256] =
  {
    0,1,2,2,3,3,3,3,4,4,4,4,4,4,4,4,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,
    6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
*************** const UQItype __clz_tab[] =
*** 657,663 ****
    8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,
    8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,
    8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,
!   8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,
  };
  #endif
  
--- 657,663 ----
    8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,
    8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,
    8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,
!   8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8
  };
  #endif
  
*************** extern const UQItype __popcount_tab[] AT
*** 731,737 ****
  #endif
  
  #ifdef L_popcount_tab
! const UQItype __popcount_tab[] =
  {
      0,1,1,2,1,2,2,3,1,2,2,3,2,3,3,4,1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5,
      1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5,2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,
--- 731,737 ----
  #endif
  
  #ifdef L_popcount_tab
! const UQItype __popcount_tab[256] =
  {
      0,1,1,2,1,2,2,3,1,2,2,3,2,3,3,4,1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5,
      1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5,2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,
*************** const UQItype __popcount_tab[] =
*** 740,746 ****
      1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5,2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,
      2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,
      2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,
!     3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,
  };
  #endif
  
--- 740,746 ----
      1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5,2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,
      2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,
      2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,
!     3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8
  };
  #endif
  
Index: gcc/libgcc2.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/libgcc2.h,v
retrieving revision 1.43
diff -c -3 -p -r1.43 libgcc2.h
*** gcc/libgcc2.h	2 Jul 2005 08:51:55 -0000	1.43
--- gcc/libgcc2.h	8 Sep 2005 11:31:23 -0000
*************** typedef union
*** 373,378 ****
--- 373,388 ----
    DWtype ll;
  } DWunion;
  
+ /* Defined for L_popcount_tab.  Exported here because some targets may
+    want to use it for their own versions of the __popcount builtins.  */
+ extern const UQItype __popcount_tab[256];
+ 
+ /* Defined for L_clz.  Exported here because some targets may want to use
+    it for their own versions of the __clz builtins.  It contains the bit
+    position of the first set bit for the numbers 0 - 255.  This avoids the
+    need for a seperate table for the __ctz builtins.  */
+ extern const UQItype __clz_tab[256];
+ 
  #include "longlong.h"
  
  #undef int
Index: gcc/longlong.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/longlong.h,v
retrieving revision 1.46
diff -c -3 -p -r1.46 longlong.h
*** gcc/longlong.h	25 Jun 2005 02:00:34 -0000	1.46
--- gcc/longlong.h	8 Sep 2005 11:31:23 -0000
***************
*** 42,47 ****
--- 41,47 ----
  #define UWtype		USItype
  #define UHWtype		USItype
  #define UDWtype		UDItype
+ extern const UQItype __clz_tab[256] ATTRIBUTE_HIDDEN;
  #endif
  
  /* Define auxiliary asm macros.
*************** extern UDItype __udiv_qrnnd (UDItype *, 
*** 129,135 ****
  #define count_trailing_zeros(COUNT,X)	((COUNT) = __builtin_ctzl (X))
  #define COUNT_LEADING_ZEROS_0 64
  #else
- extern const UQItype __clz_tab[] ATTRIBUTE_HIDDEN;
  #define count_leading_zeros(COUNT,X) \
    do {									\
      UDItype __xr = (X), __t, __a;					\
--- 129,134 ----
*************** UDItype __umulsidi3 (USItype, USItype);
*** 1312,1318 ****
  #endif
  
  #if !defined (count_leading_zeros)
- extern const UQItype __clz_tab[] ATTRIBUTE_HIDDEN;
  #define count_leading_zeros(count, x) \
    do {									\
      UWtype __xr = (x);							\
--- 1311,1316 ----
Index: gcc/config/stormy16/stormy16-lib2.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/stormy16/stormy16-lib2.c,v
retrieving revision 1.2
diff -c -3 -p -r1.2 stormy16-lib2.c
*** gcc/config/stormy16/stormy16-lib2.c	2 Sep 2005 14:17:36 -0000	1.2
--- gcc/config/stormy16/stormy16-lib2.c	8 Sep 2005 11:31:25 -0000
***************
*** 1,19 ****
! typedef		 int HItype		__attribute__ ((mode (HI)));
! typedef		 int SItype		__attribute__ ((mode (SI)));
! typedef unsigned int USItype		__attribute__ ((mode (SI)));
  
- typedef int word_type			__attribute__ ((mode (__word__)));
  
  USItype
! udivmodsi4(USItype num, USItype den, word_type modwanted)
  {
    USItype bit = 1;
    USItype res = 0;
  
!   while (den < num && bit && !(den & (1L<<31)))
      {
!       den <<=1;
!       bit <<=1;
      }
    while (bit)
      {
--- 1,79 ----
! /* This file contains 16-bit versions of some of the functions found in
!    libgcc2.c.  Really libgcc ought to be moved out of the gcc directory
!    and into its own top level directory, and then split up into multiple
!    files.  On this glorious day maybe this code can be integrated into
!    it too.  */
! 
! /* Copyright (C) 2005  Free Software Foundation, Inc.
! 
!    This file is part of GCC.
! 
!    GCC is free software; you can redistribute it and/or modify it under
!    the terms of the GNU General Public License as published by the Free
!    Software Foundation; either version 2, or (at your option) any later
!    version.
! 
!    In addition to the permissions in the GNU General Public License, the
!    Free Software Foundation gives you unlimited permission to link the
!    compiled version of this file into combinations with other programs,
!    and to distribute those combinations without any restriction coming
!    from the use of this file.  (The General Public License restrictions
!    do apply in other respects; for example, they cover modification of
!    the file, and distribution when not linked into a combine
!    executable.)
! 
!    GCC is distributed in the hope that it will be useful, but WITHOUT ANY
!    WARRANTY; without even the implied warranty of MERCHANTABILITY or
!    FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
!    for more details.
! 
!    You should have received a copy of the GNU General Public License
!    along with GCC; see the file COPYING.  If not, write to the Free
!    Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
!    02110-1301, USA.  */
! 
! #include "tconfig.h"
! #include "tsystem.h"
! #include "coretypes.h"
! #include "tm.h"
! 
! #ifdef HAVE_GAS_HIDDEN
! #define ATTRIBUTE_HIDDEN  __attribute__ ((__visibility__ ("hidden")))
! #else
! #define ATTRIBUTE_HIDDEN
! #endif
! 
! #include "libgcc2.h"
! #undef int
! 
! /* These prototypes would normally live in libgcc2.h, but this can
!    only happen once the code below is integrated into libgcc2.c.  */
! 
! extern USItype udivmodsi4 (USItype, USItype, word_type);
! extern SItype __divsi3 (SItype, SItype);
! extern SItype __modsi3 (SItype, SItype);
! extern SItype __udivsi3 (SItype, SItype);
! extern SItype __umodsi3 (SItype, SItype);
! extern SItype __ashlsi3 (SItype, SItype);
! extern SItype __ashrsi3 (SItype, SItype);
! extern USItype __lshrsi3 (USItype, USItype);
! extern int __popcounthi2 (UHWtype);
! extern int __parityhi2 (UHWtype);
! extern int __clzhi2 (UHWtype);
! extern int __ctzhi2 (UHWtype);
! 
  
  
  USItype
! udivmodsi4 (USItype num, USItype den, word_type modwanted)
  {
    USItype bit = 1;
    USItype res = 0;
  
!   while (den < num && bit && !(den & (1L << 31)))
      {
!       den <<= 1;
!       bit <<= 1;
      }
    while (bit)
      {
*************** udivmodsi4(USItype num, USItype den, wor
*** 22,36 ****
  	  num -= den;
  	  res |= bit;
  	}
!       bit >>=1;
!       den >>=1;
      }
!   if (modwanted) return num;
    return res;
  }
  
- 
- 
  SItype
  __divsi3 (SItype a, SItype b)
  {
--- 82,96 ----
  	  num -= den;
  	  res |= bit;
  	}
!       bit >>= 1;
!       den >>= 1;
      }
! 
!   if (modwanted)
!     return num;
    return res;
  }
  
  SItype
  __divsi3 (SItype a, SItype b)
  {
*************** __divsi3 (SItype a, SItype b)
*** 57,64 ****
    return res;
  }
  
- 
- 
  SItype
  __modsi3 (SItype a, SItype b)
  {
--- 117,122 ----
*************** __modsi3 (SItype a, SItype b)
*** 82,98 ****
    return res;
  }
  
- 
- 
- 
  SItype
  __udivsi3 (SItype a, SItype b)
  {
    return udivmodsi4 (a, b, 0);
  }
  
- 
- 
  SItype
  __umodsi3 (SItype a, SItype b)
  {
--- 140,151 ----
*************** __lshrsi3 (USItype a, USItype b)
*** 141,162 ****
    return a;
  }
  
! static const unsigned char __popcount_tab[] =
! {
!   0,1,1,2,1,2,2,3,1,2,2,3,2,3,3,4,1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5,
!   1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5,2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,
!   1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5,2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,
!   2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,
!   1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5,2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,
!   2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,
!   2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,
!   3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,
! };
! 
  int
! __popcounthi2 (unsigned int x)
  {
!   unsigned int ret;
  
    ret = __popcount_tab [x & 0xff];
    ret += __popcount_tab [(x >> 8) & 0xff];
--- 194,206 ----
    return a;
  }
  
! /* Returns the number of set bits in X.
!    FIXME:  The return type really should be unsigned,
!    but this is not how the builtin is prototyped.  */
  int
! __popcounthi2 (UHWtype x)
  {
!   int ret;
  
    ret = __popcount_tab [x & 0xff];
    ret += __popcount_tab [(x >> 8) & 0xff];
*************** __popcounthi2 (unsigned int x)
*** 164,171 ****
    return ret;
  }
  
  int
! __parityhi2 (unsigned int x)
  {
    x ^= x >> 8;
    x ^= x >> 4;
--- 208,219 ----
    return ret;
  }
  
+ /* Returns the number of set bits in X, modulo 2.
+    FIXME:  The return type really should be unsigned,
+    but this is not how the builtin is prototyped.  */
+ 
  int
! __parityhi2 (UHWtype x)
  {
    x ^= x >> 8;
    x ^= x >> 4;
*************** __parityhi2 (unsigned int x)
*** 173,191 ****
    return (0x6996 >> x) & 1;
  }
  
  int
! __ctzhi2 (unsigned int x)
  {
!   extern int __ctzsi2 (unsigned long);
!   unsigned long y = x;
! 
!   return __ctzsi2 (y << 16) - 16;
  }
  
  int
! __clzhi2 (unsigned int x)
  {
!   extern int __clzsi2 (unsigned long);
! 
!   return __clzsi2 (x) - 16;
  }
--- 221,251 ----
    return (0x6996 >> x) & 1;
  }
  
+ /* Returns the number of leading zero bits in X.
+    FIXME:  The return type really should be unsigned,
+    but this is not how the builtin is prototyped.  */
+ 
  int
! __clzhi2 (UHWtype x)
  {
!   if (x > 0xff)
!     return 8 - __clz_tab[x >> 8];
!   return 16 - __clz_tab[x];
  }
  
+ /* Returns the number of trailing zero bits in X.
+    FIXME:  The return type really should be unsigned,
+    but this is not how the builtin is prototyped.  */
+ 
  int
! __ctzhi2 (UHWtype x)
  {
!   /* This is cunning.  It converts X into a number with only the one bit
!      set, the bit was the least significant bit in X.  From this we can
!      use the __clz_tab[] array to compute the number of trailing bits.  */
!   x &= - x;
! 
!   if (x > 0xff)
!     return __clz_tab[x >> 8] + 7;
!   return __clz_tab[x] - 1;
  }

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]