[patch cygwin]: Replace inline-assembler in string.h by C implementation

Kai Tietz ktietz70@googlemail.com
Wed Oct 24 16:02:00 GMT 2012


2012/10/24 Christopher Faylor wrote:
> On Wed, Oct 24, 2012 at 11:07:47AM -0400, Ryan Johnson wrote:
>>On 24/10/2012 5:16 AM, Kai Tietz wrote:
>>> Hello,
>>>
>>> this patch replaces the inline-assember used in string.h by C implementation.
>>> There are three reasons why I want to suggest this.  First, the C-code might
>>> be optimized further by fixed (constant) arguments.  Secondly, it is
>>> architecture
>>> independent and so we just need to maintain on code-path.  And as
>>> third point, by
>>> inspecting generated assembly code produced by compiler out of C code
>>> vs. inline-assembler
>>> it shows that compiler produces better code.  It handles
>>> jump-threading better, and also
>>> improves average executed instructions.
>>Devil's advocate: better-looking code isn't always faster code.
>>
>>However, I'm surprised that code was inline asm in the first place -- no
>>special instructions or unusual control flow -- and would not be at all
>>surprised if the compiler does a better job.
>>
>>Also, the portability issue is relevant now that cygwin is starting the
>>move toward 64-bit support.
>
> Yes, that's exactly why Kai is proposing this.
>
> I haven't looked at the code but I almost always have one response to
> a "I want to rewrite a standard function" patches:
>
> Have you looked at other implementations?  The current one was based
> on a linux implementation.  A C version of these functions has likely
> been written before, possibly even in newlib.  Were those considered?
>
> cgf

Sure, I have looked up standard-implementation of
stricmp/strnicmp/strchr as code-base.  We could of course simply use
C-runtime-funktions here, but well, those wouldn't be inlined.  The
latter seems to me the only cause why string.h implements them at all.
They are defined there as 'static inline', which makes them pure
inlines.
The strechr function isn't a classical C-runtime function (it is close
to strchr) as it doesn't has NULL return on none-match.

A classical strchr implementation would look in C like this:

char * __cdecl
ic_strchr (const char *s, int ch)
{
  while (*s != (char) ch && *s != 0)
    s++;

  if (*s == 0)
    return NULL;

  return (char *) s;
}

The ascii_strcasematch and ascii_strncasematch functions are close to
the strcasecmp/strncasecmp C-runtime functions, but the result of
those functions on failure/success are different.
strcasecmp/strncasecmp would return zero on identity, and != 0 on
none-match.  The strcasematch/strncasematch routines are returning 1
on match and zero on none match.

Classical implementation (for ASCII only) for str(n)casecmp functions
would be something like this:

int __cdecl
__ic_stricmp_a (const char *s1, const char *s2)
{
  int c1, c2;

  do
    {
      c1 = (int) *s1;
      c2 = (int) *s2;
      if (c1 >= 'A' && c1 <= 'Z')
        c1 -= 'A' - 'a';
      if (c2 >= 'A' && c2 <= 'Z')
        c2 -= 'A' - 'a';
      ++s1;
      ++s2;
    }
  while (c1 && c1 == c2);

  return (c1 - c2);
}

and

int __cdecl
__ic_strnicmp_a (const char *s1, const char *s2, size_t n)
{
  int c1, c2;

  if (!n)
    return 0;

  do
    {
      c1 = (unsigned char) *s1;
      c2 = (unsigned char) *s2;
      if (c1 >= 'A' && c1 <= 'Z')
        c1 -= 'A' - 'a';
      if (c2 >= 'A' && c2 <= 'Z')
        c2 -= 'A' - 'a';
      ++s1;
      ++s2;
      --n;
    }
  while (n != 0 && c1 != 0 && c1 == c2);

  return (c1 - c2);
}

Regards,
Kai



More information about the Cygwin-patches mailing list