diff mbox series

[testsuite] memchr-1.c wide char and AIX

Message ID CAGWvnym-Y8jhpZ8xpEsdbsRp9FKZMk+KfBVeYrGOcwVN7sNf_g@mail.gmail.com
State New
Headers show
Series [testsuite] memchr-1.c wide char and AIX | expand

Commit Message

David Edelsohn Oct. 5, 2018, 6:54 p.m. UTC
memchr-1.c tests for char (test_narrow) and wchar (test_wide).  The
wide character test assumes 32 bit wide character, while 32 bit AIX
uses 16 bit wide character.  This assumption causes the wide character
part of the test to fail in 32 bit mode on AIX (it succeeds on 64 bit
AIX).

The testcase already includes ifdefs for endianness.  The "narrow"
part of the test succeeds and is a useful test on AIX.  Me proposed
solution adds an AIX-specific ifdef in the testcase to avoid the
compile-time errors in 32 bit mode.

Because of the structure of the testcase, I need to #ifdef test_wide()
and its constants, and separately it's invocation in main(), as
opposed to making test_wide() a no-op that is called.

Another alternative is to split memchr-1.c into memchr-1.c for
test_narrow and memchr-2.c for test_wide, with the latter skipped on
AIX using a DejaGNU directive.

Is the #ifdef okay or would others prefer that I split the testcase?
No solution is particularly elegant.

Thanks, David

* gcc.c-torture/execute/memchr-1.c (test_wide): Skip on 32 bit AIX.

Comments

Martin Sebor Oct. 5, 2018, 8:10 p.m. UTC | #1
On 10/05/2018 12:54 PM, David Edelsohn wrote:
> memchr-1.c tests for char (test_narrow) and wchar (test_wide).  The
> wide character test assumes 32 bit wide character, while 32 bit AIX
> uses 16 bit wide character.  This assumption causes the wide character
> part of the test to fail in 32 bit mode on AIX (it succeeds on 64 bit
> AIX).
>
> The testcase already includes ifdefs for endianness.  The "narrow"
> part of the test succeeds and is a useful test on AIX.  Me proposed
> solution adds an AIX-specific ifdef in the testcase to avoid the
> compile-time errors in 32 bit mode.
>
> Because of the structure of the testcase, I need to #ifdef test_wide()
> and its constants, and separately it's invocation in main(), as
> opposed to making test_wide() a no-op that is called.
>
> Another alternative is to split memchr-1.c into memchr-1.c for
> test_narrow and memchr-2.c for test_wide, with the latter skipped on
> AIX using a DejaGNU directive.
>
> Is the #ifdef okay or would others prefer that I split the testcase?
> No solution is particularly elegant.

That's my bad for hardwiring 4 as the wchar_t size.  Sorry about
the breakage.  I can't think of any better solutions than what
you covered above.  It would be nice to exercise this optimization
with 16-bit wchar_t.  It looks like GCC has a -fshort-wchar option
to force wchar_t to be 2 bytes wide that I didn't know about.
That will make the problem easier to solve without necessarily
having to build all of GCC on AIX.  Let me take care of it.

Martin

>
> Thanks, David
>
> * gcc.c-torture/execute/memchr-1.c (test_wide): Skip on 32 bit AIX.
>
> Index: memchr-1.c
> ===================================================================
> --- memchr-1.c  (revision 264869)
> +++ memchr-1.c  (working copy)
> @@ -106,6 +106,7 @@
>    A (memchr (&s5_3[1][i0], 0, sizeof s5_3[1] - i0) == &s5_3[1][4]);
>  }
>
> +#if !defined(_AIX) || defined(__64BIT__)
>  static const wchar_t wc = L'1';
>  static const wchar_t ws1[] = L"1";
>  static const wchar_t ws4[] = L"\x00123456\x12005678\x12340078\x12345600";
> @@ -144,10 +145,13 @@
>    A (memchr (&ws4[3], 0, nb - 3 * nwb) == pws4 + 3 * nwb + 3);
>  #endif
>  }
> +#endif
>
>
>  int main ()
>  {
>    test_narrow ();
> +#if !defined(_AIX) || defined(__64BIT__)
>    test_wide ();
> +#endif
>  }
>
Martin Sebor Oct. 5, 2018, 9:47 p.m. UTC | #2
David,

Attached is a patch to conditionalize the memchr-1.c test
to pass even with 2-byte wchar_t's.  It also adds a compile
only test to verify memchr with -fnarrow-wchar.  I verified
the changes on LE x86_64-linux and BE powerpc64-linux but
if you could confirm they also work on AIX that would be
great.

Unless some concerns come up I will plan to commit these
changes sometime next week.

Thanks
Martin

On 10/05/2018 02:10 PM, Martin Sebor wrote:
> On 10/05/2018 12:54 PM, David Edelsohn wrote:
>> memchr-1.c tests for char (test_narrow) and wchar (test_wide).  The
>> wide character test assumes 32 bit wide character, while 32 bit AIX
>> uses 16 bit wide character.  This assumption causes the wide character
>> part of the test to fail in 32 bit mode on AIX (it succeeds on 64 bit
>> AIX).
>>
>> The testcase already includes ifdefs for endianness.  The "narrow"
>> part of the test succeeds and is a useful test on AIX.  Me proposed
>> solution adds an AIX-specific ifdef in the testcase to avoid the
>> compile-time errors in 32 bit mode.
>>
>> Because of the structure of the testcase, I need to #ifdef test_wide()
>> and its constants, and separately it's invocation in main(), as
>> opposed to making test_wide() a no-op that is called.
>>
>> Another alternative is to split memchr-1.c into memchr-1.c for
>> test_narrow and memchr-2.c for test_wide, with the latter skipped on
>> AIX using a DejaGNU directive.
>>
>> Is the #ifdef okay or would others prefer that I split the testcase?
>> No solution is particularly elegant.
>
> That's my bad for hardwiring 4 as the wchar_t size.  Sorry about
> the breakage.  I can't think of any better solutions than what
> you covered above.  It would be nice to exercise this optimization
> with 16-bit wchar_t.  It looks like GCC has a -fshort-wchar option
> to force wchar_t to be 2 bytes wide that I didn't know about.
> That will make the problem easier to solve without necessarily
> having to build all of GCC on AIX.  Let me take care of it.
>
> Martin
>
>>
>> Thanks, David
>>
>> * gcc.c-torture/execute/memchr-1.c (test_wide): Skip on 32 bit AIX.
>>
>> Index: memchr-1.c
>> ===================================================================
>> --- memchr-1.c  (revision 264869)
>> +++ memchr-1.c  (working copy)
>> @@ -106,6 +106,7 @@
>>    A (memchr (&s5_3[1][i0], 0, sizeof s5_3[1] - i0) == &s5_3[1][4]);
>>  }
>>
>> +#if !defined(_AIX) || defined(__64BIT__)
>>  static const wchar_t wc = L'1';
>>  static const wchar_t ws1[] = L"1";
>>  static const wchar_t ws4[] =
>> L"\x00123456\x12005678\x12340078\x12345600";
>> @@ -144,10 +145,13 @@
>>    A (memchr (&ws4[3], 0, nb - 3 * nwb) == pws4 + 3 * nwb + 3);
>>  #endif
>>  }
>> +#endif
>>
>>
>>  int main ()
>>  {
>>    test_narrow ();
>> +#if !defined(_AIX) || defined(__64BIT__)
>>    test_wide ();
>> +#endif
>>  }
>>
>
gcc/tewstsuite/ChangeLog:

	* gcc.c-torture/execute/memchr-1.c: Avoid assuming 4-byte wchar_t.
	Add a test for 2-byte wchar_t.
	* gcc.dg/builtin-memchr.c: New test.

Index: gcc/testsuite/gcc.c-torture/execute/memchr-1.c
===================================================================
--- gcc/testsuite/gcc.c-torture/execute/memchr-1.c	(revision 264875)
+++ gcc/testsuite/gcc.c-torture/execute/memchr-1.c	(working copy)
@@ -106,6 +106,8 @@ void test_narrow (void)
   A (memchr (&s5_3[1][i0], 0, sizeof s5_3[1] - i0) == &s5_3[1][4]);
 }
 
+#if 4 == __WCHAR_WIDTH__
+
 static const wchar_t wc = L'1';
 static const wchar_t ws1[] = L"1";
 static const wchar_t ws4[] = L"\x00123456\x12005678\x12340078\x12345600";
@@ -145,7 +147,59 @@ void test_wide (void)
 #endif
 }
 
+#elif 2 == __WCHAR_WIDTH__
 
+static const wchar_t wc = L'1';
+static const wchar_t ws1[] = L"1";
+static const wchar_t ws2[2] = L"\x1234\x5678";   /* no terminating nul */
+static const wchar_t ws4[] = L"\x0012\x1200\x1234";
+
+void test_wide (void)
+{
+  int i0 = 0;
+  int i1 = i0 + 1;
+  int i2 = i1 + 1;
+
+  A (sizeof (wchar_t) == 2);
+
+  A (memchr (L"" + 1, 0, 0) == 0);
+  A (memchr (&wc + 1, 0, 0) == 0);
+  A (memchr (L"\x1234", 0, sizeof (wchar_t)) == 0);
+
+  A (memchr (L"" + i1, i0, i0) == 0);
+  A (memchr (&wc + i1, i0, i0) == 0);
+  A (memchr (L"\x1234", i0, sizeof (wchar_t)) == 0);
+
+  A (memchr (ws2, 0, sizeof ws2) == 0);
+  A (memchr (ws2, i0, sizeof ws2) == 0);
+
+  const size_t nb = sizeof ws4;
+  const size_t nwb = sizeof (wchar_t);
+
+  const char *pws1 = (const char*)ws1;
+  const char *pws4 = (const char*)ws4;
+
+#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
+  A (memchr (ws1, i0, sizeof ws1) == pws1 + 1);
+
+  A (memchr (&ws4[0], i0, nb) == pws4 + i1);
+  A (memchr (&ws4[1], i0, nb - i1 * nwb) == pws4 + i1 * nwb);
+  A (memchr (&ws4[2], i0, nb - i2 * nwb) == pws4 + i2 * nwb + i2);
+#else
+  A (memchr (ws1, i0, sizeof ws1) == pws1 + 0);
+
+  A (memchr (&ws4[0], i0, nb) == pws4 + 0);
+  A (memchr (&ws4[1], i0, nb - i1 * nwb) == pws4 + i1 * nwb + i1);
+  A (memchr (&ws4[2], i0, nb - i2 * nwb) == pws4 + i2 * nwb + i2);
+#endif
+}
+
+#else
+
+void test_wide (void) { }
+
+#endif
+
 int main ()
 {
   test_narrow ();
Index: gcc/testsuite/gcc.dg/builtin-memchr.c
===================================================================
--- gcc/testsuite/gcc.dg/builtin-memchr.c	(nonexistent)
+++ gcc/testsuite/gcc.dg/builtin-memchr.c	(working copy)
@@ -0,0 +1,68 @@
+/* PR tree-optimization/86711 - wrong folding of memchr
+
+   Verify that memchr() of arrays initialized with 16-bit wide string
+   literals finds the nul only when it is present in the wide string.
+
+   { dg-do compile }
+   { dg-options "-O1 -Wall -fshort-wchar -fdump-tree-optimized" } */
+
+typedef __SIZE_TYPE__  size_t;
+typedef __WCHAR_TYPE__ wchar_t;
+
+extern void* memchr (const void*, int, size_t);
+extern int printf (const char*, ...);
+extern void abort (void);
+
+#define A(expr)							\
+  ((expr)							\
+   ? (void)0							\
+   : (printf ("assertion failed on line %i: %s\n",		\
+			__LINE__, #expr),			\
+      abort ()))
+
+static const wchar_t wc = L'1';
+static const wchar_t ws1[] = L"1";
+static const wchar_t ws2[2] = L"\x1234\x5678";   /* no terminating nul */
+static const wchar_t ws4[] = L"\x0012\x1200\x1234";
+
+void test_wide (void)
+{
+  int i0 = 0;
+  int i1 = i0 + 1;
+  int i2 = i1 + 1;
+
+  A (sizeof (wchar_t) == 2);
+
+  A (memchr (L"" + 1, 0, 0) == 0);
+  A (memchr (&wc + 1, 0, 0) == 0);
+  A (memchr (L"\x1234", 0, sizeof (wchar_t)) == 0);
+
+  A (memchr (L"" + i1, i0, i0) == 0);
+  A (memchr (&wc + i1, i0, i0) == 0);
+  A (memchr (L"\x1234", i0, sizeof (wchar_t)) == 0);
+
+  A (memchr (ws2, 0, sizeof ws2) == 0);
+  A (memchr (ws2, i0, sizeof ws2) == 0);
+
+  const size_t nb = sizeof ws4;
+  const size_t nwb = sizeof (wchar_t);
+
+  const char *pws1 = (const char*)ws1;
+  const char *pws4 = (const char*)ws4;
+
+#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
+  A (memchr (ws1, i0, sizeof ws1) == pws1 + 1);
+
+  A (memchr (&ws4[0], i0, nb) == pws4 + i1);
+  A (memchr (&ws4[1], i0, nb - i1 * nwb) == pws4 + i1 * nwb);
+  A (memchr (&ws4[2], i0, nb - i2 * nwb) == pws4 + i2 * nwb + i2);
+#else
+  A (memchr (ws1, i0, sizeof ws1) == pws1 + 0);
+
+  A (memchr (&ws4[0], i0, nb) == pws4 + 0);
+  A (memchr (&ws4[1], i0, nb - i1 * nwb) == pws4 + i1 * nwb + i1);
+  A (memchr (&ws4[2], i0, nb - i2 * nwb) == pws4 + i2 * nwb + i2);
+#endif
+}
+
+/* { dg-final { scan-tree-dump-not "abort" "optimized" } } */
David Edelsohn Oct. 6, 2018, 10:13 p.m. UTC | #3
On Fri, Oct 5, 2018 at 5:47 PM Martin Sebor <msebor@gmail.com> wrote:
>
> David,
>
> Attached is a patch to conditionalize the memchr-1.c test
> to pass even with 2-byte wchar_t's.  It also adds a compile
> only test to verify memchr with -fnarrow-wchar.  I verified
> the changes on LE x86_64-linux and BE powerpc64-linux but
> if you could confirm they also work on AIX that would be
> great.

With the patch, the memchr failures on AIX are fixed.

Thanks, David
Martin Sebor Oct. 10, 2018, 3:34 p.m. UTC | #4
On 10/06/2018 04:13 PM, David Edelsohn wrote:
> On Fri, Oct 5, 2018 at 5:47 PM Martin Sebor <msebor@gmail.com> wrote:
>>
>> David,
>>
>> Attached is a patch to conditionalize the memchr-1.c test
>> to pass even with 2-byte wchar_t's.  It also adds a compile
>> only test to verify memchr with -fnarrow-wchar.  I verified
>> the changes on LE x86_64-linux and BE powerpc64-linux but
>> if you could confirm they also work on AIX that would be
>> great.
>
> With the patch, the memchr failures on AIX are fixed.


Thanks!  I've checked it in as r265020.

Martin
diff mbox series

Patch

Index: memchr-1.c
===================================================================
--- memchr-1.c  (revision 264869)
+++ memchr-1.c  (working copy)
@@ -106,6 +106,7 @@ 
   A (memchr (&s5_3[1][i0], 0, sizeof s5_3[1] - i0) == &s5_3[1][4]);
 }

+#if !defined(_AIX) || defined(__64BIT__)
 static const wchar_t wc = L'1';
 static const wchar_t ws1[] = L"1";
 static const wchar_t ws4[] = L"\x00123456\x12005678\x12340078\x12345600";
@@ -144,10 +145,13 @@ 
   A (memchr (&ws4[3], 0, nb - 3 * nwb) == pws4 + 3 * nwb + 3);
 #endif
 }
+#endif


 int main ()
 {
   test_narrow ();
+#if !defined(_AIX) || defined(__64BIT__)
   test_wide ();
+#endif
 }