Re: xstrtol: fix test failure on mingw

2008-04-23 Thread Bruno Haible
Hi Jim,

> > ! LC_ALL=C tr -d '\r' < t-xstrtoimax.tmp > t-xstrtoimax.xo
> I hear that there really do exist systems in actual use
> on which tr still does not honor backslash-escapes like \r and \n.

Which platforms, please? (I use the similar idiom in more than 200 files in
gettext. So I need to know the reasons.)

> So you might want to change that \r to \015, in spite of the
> ASCII dependency.

A few programs, like groff and IBM's ICU, are ported to platforms not based on
ASCII. On the other hand, files compiled by gperf have a compile-time check
for ASCII, and I've received no reports from systems where that failed.

Bruno





Re: xstrtol: fix test failure on mingw

2008-04-23 Thread Ralf Wildenhues
Hi Bruno,

* Bruno Haible wrote on Wed, Apr 23, 2008 at 10:55:49PM CEST:
> > > ! LC_ALL=C tr -d '\r' < t-xstrtoimax.tmp > t-xstrtoimax.xo
> > I hear that there really do exist systems in actual use
> > on which tr still does not honor backslash-escapes like \r and \n.
> 
> Which platforms, please? (I use the similar idiom in more than 200 files in
> gettext. So I need to know the reasons.)

Solaris 10 /usr/ucb/tr.  Not likely to be early in PATH, but hey, people
do all kinds of weird things to their path.  ;-)

Cheers,
Ralf




Re: memchr2 speed, gcc

2008-04-23 Thread Eric Blake
Bruno Haible  clisp.org> writes:

> > +   New module 'memchr2'.
> 
> Wondering why you used 'uintmax_t' as basic word type, rather than the
> 'unsigned long' that memchr.c uses, I benchmarked this and a few other
> variations of the memchr2.c implementation.
> 
> Summary of results:
>   - With gcc 3.2.2 and 4.2.2, the word type 'unsigned long' is more efficient.
>   - With gcc 4.3-20080215, it is the opposite. But this version of gcc also
> exhibits mysterious performance characteristics.

I've got an even more efficient implementation, inspired by 
http://www.cl.cam.ac.uk/~am21/progtricks.html, and here are my measurements of 
10 iterations of your test program using gcc 3.4.4 at -O2 on cygwin (32-bit 
machine):

original original modified modified
uintmax_tuint32_t uintmax_tuint32_t
1.2500.8281.3750.765 

As you observed in your measurements, the 32-bit operations were more efficient 
with this older gcc.  But what is more interesting is that the modified version 
was roughly 10% worse than the original with 64-bit math, while it was roughly 
8% better with 32-bit math.  I'm not sure what is causing that effect (maybe 
it's due to more register pressure for the number of live values during the 
computation; maybe it's due to the fact that the original version can be proven 
to not trigger a carry bit to cross the 32-bit boundary, but the subtraction in 
the modified version can cause a carry, and carries slow down 64-bit math when 
done in 32-bit chunks).  But with the right data type, the modified version is 
inherently faster, since it requires fewer operations and never has false hits.

Therefore, I'm checking this in, although it would be interesting to see your 
timings by swapping the typedef to try 64-bit math with newer gcc again.  For 
that matter, is it worth putting a preprocessor conditional to change the 
typedef according to whether the compiler appears to be a new enough version of 
gcc to intelligently optimize the 64-bit math?

Also, is anyone interested in making gnulib's memchr and strchrnul more 
efficient by copying the optimizations learned in memchr2?  Also, should we 
provide a replacement for glibc's rawmemchr (surprisingly useful:
rawmemchr(s,0) is more efficient than a naive strchr(s,0) or s+strlen(s))?

>From 092621651ba401797a2e671eb24207c49e5e9b64 Mon Sep 17 00:00:00 2001
From: Eric Blake <[EMAIL PROTECTED]>
Date: Wed, 23 Apr 2008 15:03:40 -0600
Subject: [PATCH] Improve memchr2 performance.

* lib/memchr2.c (memchr2): Further optimize parallel detection of
NUL bytes.
* modules/memchr2 (Depends-on): Use intprops.h.

Signed-off-by: Eric Blake <[EMAIL PROTECTED]>
---
 ChangeLog   |7 +++
 lib/memchr2.c   |  140 ++
 modules/memchr2 |1 +
 3 files changed, 45 insertions(+), 103 deletions(-)

diff --git a/ChangeLog b/ChangeLog
index 4b87fda..769f0f3 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,10 @@
+2008-04-23  Eric Blake  <[EMAIL PROTECTED]>
+
+   Improve memchr2 performance.
+   * lib/memchr2.c (memchr2): Further optimize parallel detection of
+   NUL bytes.
+   * modules/memchr2 (Depends-on): Use intprops.h.
+
 2008-04-23  Simon Josefsson  <[EMAIL PROTECTED]>
 
* lib/sys_socket.in.h (setsockopt): Be more type safe by declaring
diff --git a/lib/memchr2.c b/lib/memchr2.c
index 3853343..81de613 100644
--- a/lib/memchr2.c
+++ b/lib/memchr2.c
@@ -29,19 +29,28 @@ along with this program.  If not, see 
.  */
 #include 
 #include 
 
+#include "intprops.h"
+
 /* Return the first address of either C1 or C2 (treated as unsigned
char) that occurs within N bytes of the memory region S.  If
neither byte appears, return NULL.  */
 void *
 memchr2 (void const *s, int c1_in, int c2_in, size_t n)
 {
+  /* On 32-bit hardware, choosing longword to be a 32-bit unsigned
+ long instead of a 64-bit uintmax_t tends to give better
+ performance.  On 64-bit hardware, unsigned long is generally 64
+ bits already.  Change this typedef to experiment with
+ performance.  */
+  typedef unsigned long longword;
+
   const unsigned char *char_ptr;
-  const uintmax_t *longword_ptr;
-  uintmax_t longword1;
-  uintmax_t longword2;
-  uintmax_t magic_bits;
-  uintmax_t charmask1;
-  uintmax_t charmask2;
+  const longword *longword_ptr;
+  longword longword1;
+  longword longword2;
+  longword magic_bits;
+  longword charmask1;
+  longword charmask2;
   unsigned char c1;
   unsigned char c2;
   int i;
@@ -63,31 +72,17 @@ memchr2 (void const *s, int c1_in, int c2_in, size_t n)
   /* All these elucidatory comments refer to 4-byte longwords,
  but the theory applies equally well to any size longwords.  */
 
-  longword_ptr = (const uintmax_t *) char_ptr;
-
-  /* Bits 31, 24, 16, and 8 of this number are zero.  Call these bits
- the "holes."  Note that there is a hole just to the left of
- each byte, with an ex