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