diff mbox series

convert braced initializers to strings (PR 71625)

Message ID c9067f6a-9e55-8483-4f4f-c162d4c7a170@gmail.com
State New
Headers show
Series convert braced initializers to strings (PR 71625) | expand

Commit Message

Martin Sebor July 30, 2018, 11:51 p.m. UTC
The middle-end contains code to determine the lengths of constant
character arrays initialized by string literals.  The code is used
in a number of optimizations and warnings.

However, the code is unable to deal with constant arrays initialized
using the braced initializer syntax, as in

   const char a[] = { '1', '2', '\0' };

The attached patch extends the C and C++ front-ends to convert such
initializers into a STRING_CST form.

The goal of this work is to both enable existing optimizations for
such arrays, and to help detect bugs due to using non-nul terminated
arrays where nul-terminated strings are expected.  The latter is
an extension of the GCC 8 _Wstringop-overflow and
-Wstringop-truncation warnings that help detect or prevent reading
past the end of dynamically created character arrays.  Future work
includes detecting potential past-the-end reads from uninitialized
local character arrays.

Tested on x86_64-linux.

Martin

Comments

Jason Merrill July 31, 2018, 1:38 p.m. UTC | #1
On Tue, Jul 31, 2018 at 9:51 AM, Martin Sebor <msebor@gmail.com> wrote:
> The middle-end contains code to determine the lengths of constant
> character arrays initialized by string literals.  The code is used
> in a number of optimizations and warnings.
>
> However, the code is unable to deal with constant arrays initialized
> using the braced initializer syntax, as in
>
>   const char a[] = { '1', '2', '\0' };
>
> The attached patch extends the C and C++ front-ends to convert such
> initializers into a STRING_CST form.
>
> The goal of this work is to both enable existing optimizations for
> such arrays, and to help detect bugs due to using non-nul terminated
> arrays where nul-terminated strings are expected.  The latter is
> an extension of the GCC 8 _Wstringop-overflow and
> -Wstringop-truncation warnings that help detect or prevent reading
> past the end of dynamically created character arrays.  Future work
> includes detecting potential past-the-end reads from uninitialized
> local character arrays.

>   && TYPE_MAIN_VARIANT (TREE_TYPE (valtype)) == char_type_node)

Why? Don't we want this for other character types as well?

Jason
Martin Sebor July 31, 2018, 2:49 p.m. UTC | #2
On 07/31/2018 07:38 AM, Jason Merrill wrote:
> On Tue, Jul 31, 2018 at 9:51 AM, Martin Sebor <msebor@gmail.com> wrote:
>> The middle-end contains code to determine the lengths of constant
>> character arrays initialized by string literals.  The code is used
>> in a number of optimizations and warnings.
>>
>> However, the code is unable to deal with constant arrays initialized
>> using the braced initializer syntax, as in
>>
>>   const char a[] = { '1', '2', '\0' };
>>
>> The attached patch extends the C and C++ front-ends to convert such
>> initializers into a STRING_CST form.
>>
>> The goal of this work is to both enable existing optimizations for
>> such arrays, and to help detect bugs due to using non-nul terminated
>> arrays where nul-terminated strings are expected.  The latter is
>> an extension of the GCC 8 _Wstringop-overflow and
>> -Wstringop-truncation warnings that help detect or prevent reading
>> past the end of dynamically created character arrays.  Future work
>> includes detecting potential past-the-end reads from uninitialized
>> local character arrays.
>
>>   && TYPE_MAIN_VARIANT (TREE_TYPE (valtype)) == char_type_node)
>
> Why? Don't we want this for other character types as well?

It suppresses narrowing warnings for things like

   signed char a[] = { 0xff };

(there are a couple of tests that exercise this).

At the same time, STRING_CST is supposed to be able to represent
strings of any integer type so there should be a way to make it
work.  On the flip side, recent discussions of changes in this
area suggest there may be bugs in the wide character handling of
STRING_CST so those would need to be fixed before relying on it
for robust support.

In any case, if you have a suggestion for how to make it work for
at least the narrow character types I'll adjust the patch.

Martin
Martin Sebor Aug. 6, 2018, 4:41 p.m. UTC | #3
Ping: https://gcc.gnu.org/ml/gcc-patches/2018-07/msg01884.html

On 07/30/2018 05:51 PM, Martin Sebor wrote:
> The middle-end contains code to determine the lengths of constant
> character arrays initialized by string literals.  The code is used
> in a number of optimizations and warnings.
>
> However, the code is unable to deal with constant arrays initialized
> using the braced initializer syntax, as in
>
>   const char a[] = { '1', '2', '\0' };
>
> The attached patch extends the C and C++ front-ends to convert such
> initializers into a STRING_CST form.
>
> The goal of this work is to both enable existing optimizations for
> such arrays, and to help detect bugs due to using non-nul terminated
> arrays where nul-terminated strings are expected.  The latter is
> an extension of the GCC 8 _Wstringop-overflow and
> -Wstringop-truncation warnings that help detect or prevent reading
> past the end of dynamically created character arrays.  Future work
> includes detecting potential past-the-end reads from uninitialized
> local character arrays.
>
> Tested on x86_64-linux.
>
> Martin
Joseph Myers Aug. 6, 2018, 5:04 p.m. UTC | #4
On Mon, 6 Aug 2018, Martin Sebor wrote:

> Ping: https://gcc.gnu.org/ml/gcc-patches/2018-07/msg01884.html

I'd expect testcases with signed char and unsigned char as well, if those 
work for C, including tests for signed char where some of the initializers 
are negative.  (Tests that actual array contents are still correct after 
this conversion, as well as that the optimizations occur, would also be a 
good idea.)

The c-parser.c patch adds a comment that ends in the middle of a word.
Martin Sebor Aug. 7, 2018, 2:02 a.m. UTC | #5
On 08/06/2018 11:04 AM, Joseph Myers wrote:
> On Mon, 6 Aug 2018, Martin Sebor wrote:
>
>> Ping: https://gcc.gnu.org/ml/gcc-patches/2018-07/msg01884.html
>
> I'd expect testcases with signed char and unsigned char as well, if those
> work for C, including tests for signed char where some of the initializers
> are negative.  (Tests that actual array contents are still correct after
> this conversion, as well as that the optimizations occur, would also be a
> good idea.)
>
> The c-parser.c patch adds a comment that ends in the middle of a word.

Thanks.  Adding more tests revealed a couple of oversights:
1) using tree_fits_uhwi_p excluded initializers with negative
values,
2) skipping embedded nuls made it possible to create a string
with fewer elements than the initializer array, which caused
arrays with unspecified bound to be smaller than they would
have been otherwise

The attached update fixes both of these and makes the C/C++
front-end code simpler and more alike.

Martin
PR tree-optimization/71625 - missing strlen optimization on different array initialization style

gcc/c/ChangeLog:

	PR tree-optimization/71625
	* c-parser.c (c_parser_declaration_or_fndef): Call
	braced_list_to_string.

gcc/c-family/ChangeLog:

	PR tree-optimization/71625
	* c-common.c (braced_list_to_string): New function.
	* c-common.h (braced_list_to_string): Declare it.

gcc/cp/ChangeLog:

	PR tree-optimization/71625
	* parser.c (cp_parser_init_declarator):  Call braced_list_to_string.

gcc/testsuite/ChangeLog:

	PR tree-optimization/71625
	* g++.dg/init/string2.C: New test.
	* g++.dg/init/string3.C: New test.
	* gcc.dg/strlenopt-55.c: New test.

diff --git a/gcc/c-family/c-common.c b/gcc/c-family/c-common.c
Index: gcc/c/c-parser.c
===================================================================
--- gcc/c/c-parser.c	(revision 263341)
+++ gcc/c/c-parser.c	(working copy)
@@ -2126,6 +2126,24 @@ c_parser_declaration_or_fndef (c_parser *parser, b
 	      if (d != error_mark_node)
 		{
 		  maybe_warn_string_init (init_loc, TREE_TYPE (d), init);
+
+		  /* Convert a string CONSTRUCTOR into a STRING_CST.  */
+		  tree valtype = TREE_TYPE (init.value);
+		  if (TREE_CODE (init.value) == CONSTRUCTOR
+		      && TREE_CODE (valtype) == ARRAY_TYPE)
+		    {
+		      if (TYPE_STRING_FLAG (TREE_TYPE (valtype)))
+			{
+			  if (tree str = braced_list_to_string (valtype,
+								init.value))
+			    {
+			      /* Replace the initializer with the string
+				 constant.  */
+			      init.value = str;
+			    }
+			}
+		    }
+
 		  finish_decl (d, init_loc, init.value,
 			       init.original_type, asm_name);
 		}
Index: gcc/c-family/c-common.c
===================================================================
--- gcc/c-family/c-common.c	(revision 263341)
+++ gcc/c-family/c-common.c	(working copy)
@@ -8509,4 +8509,83 @@ maybe_add_include_fixit (rich_location *richloc, c
   free (text);
 }
 
+/* Attempt to convert a braced array initializer list CTOR for array
+   TYPE into a STRING_CST for convenience and efficiency.  When non-null,
+   use EVAL to attempt to evalue constants (used by C++).  Return
+   the converted string on success or null on failure.  */
+
+tree
+braced_list_to_string (tree type, tree ctor, tree (*eval)(tree))
+{
+  /* If the array has an explicit bound, use it to constrain the size
+     of the string.  If it doesn't, be sure to create a string that's
+     as long as implied by the index of the last zero specified via
+     a designator, as in:
+       const char a[] = { [7] = 0 };  */
+  unsigned HOST_WIDE_INT maxelts = HOST_WIDE_INT_M1U;
+  if (tree nelts = TYPE_SIZE_UNIT (type))
+    if (tree_fits_uhwi_p (nelts))
+      {
+	maxelts = tree_to_uhwi (nelts);
+	maxelts /= tree_to_uhwi (TYPE_SIZE_UNIT (TREE_TYPE (type)));
+      }
+
+  unsigned HOST_WIDE_INT nelts = CONSTRUCTOR_NELTS (ctor);
+
+  auto_vec<char> str;
+  str.reserve (nelts + 1);
+
+  unsigned HOST_WIDE_INT i;
+  tree index, value;
+
+  FOR_EACH_CONSTRUCTOR_ELT (CONSTRUCTOR_ELTS (ctor), i, index, value)
+    {
+      unsigned HOST_WIDE_INT idx = index ? tree_to_uhwi (index) : i;
+
+      /* auto_vec is limited to UINT_MAX elements.  */
+      if (idx > UINT_MAX)
+	return NULL_TREE;
+
+      /* Attempt to evaluate constants.  */
+      if (eval)
+	value = eval (value);
+
+      /* Avoid non-constant initializers.  */
+     if (!tree_fits_shwi_p (value))
+	return NULL_TREE;
+
+      /* Skip over embedded nuls.  */
+      unsigned val = tree_to_shwi (value);
+      if (!val && i + 1 < nelts)
+	continue;
+
+      /* Bail if the CTOR has a block of more than 256 embedded nuls
+	 due to implicitly initialized elements.  */
+      unsigned nelts = (idx - str.length ()) + 1;
+      if (nelts > 256)
+	return NULL_TREE;
+
+      if (nelts > 1)
+	{
+	  str.reserve (idx);
+	  str.quick_grow_cleared (idx);
+	}
+
+      if (idx > maxelts)
+	return NULL_TREE;
+
+      str.safe_insert (idx, val);
+    }
+
+  if (!nelts || str.length () < i)
+    /* Append a nul for the empty initializer { } and for the last
+       explicit initializer in the loop above that is a nul.  */
+    str.safe_push (0);
+
+  /* Build a string literal but return the embedded STRING_CST.  */
+  tree res = build_string_literal (str.length (), str.begin ());
+  res = TREE_OPERAND (TREE_OPERAND (res, 0), 0);
+  return res;
+}
+
 #include "gt-c-family-c-common.h"
Index: gcc/c-family/c-common.h
===================================================================
--- gcc/c-family/c-common.h	(revision 263341)
+++ gcc/c-family/c-common.h	(working copy)
@@ -1331,6 +1331,7 @@ extern void maybe_add_include_fixit (rich_location
 extern void maybe_suggest_missing_token_insertion (rich_location *richloc,
 						   enum cpp_ttype token_type,
 						   location_t prev_token_loc);
+extern tree braced_list_to_string (tree, tree, tree (*)(tree) = NULL);
 
 #if CHECKING_P
 namespace selftest {
Index: gcc/cp/parser.c
===================================================================
--- gcc/cp/parser.c	(revision 263341)
+++ gcc/cp/parser.c	(working copy)
@@ -19825,6 +19825,24 @@ cp_parser_init_declarator (cp_parser* parser,
 	    finish_lambda_scope ();
 	  if (initializer == error_mark_node)
 	    cp_parser_skip_to_end_of_statement (parser);
+	  else if (decl)
+	    {
+	      tree valtype = TREE_TYPE (decl);
+	      if (TREE_CODE (valtype) == ARRAY_TYPE
+		  && TYPE_STRING_FLAG (TREE_TYPE (valtype))
+		  && TYPE_MAIN_VARIANT (TREE_TYPE (valtype)) == char_type_node)
+		{
+		  /* Convert a string CONSTRUCTOR into a STRING_CST.  */
+		  if (TREE_CODE (initializer) == CONSTRUCTOR
+		      && TREE_TYPE (initializer) == init_list_type_node)
+		    {
+		      if (tree str
+			  = braced_list_to_string (valtype, initializer,
+						   scalar_constant_value))
+			initializer = str;
+		    }
+		}
+	    }
 	}
     }
 
Index: gcc/testsuite/g++.dg/init/string2.C
===================================================================
--- gcc/testsuite/g++.dg/init/string2.C	(nonexistent)
+++ gcc/testsuite/g++.dg/init/string2.C	(working copy)
@@ -0,0 +1,48 @@
+// PR tree-optimization/71625 - missing strlen optimization on different
+// array initialization style
+//
+// Verify that strlen() calls with constant character array arguments
+// initialized with string constants are folded.  (This is a small
+// subset of pr63989).
+// { dg-do compile }
+// { dg-options "-O0 -fdump-tree-gimple" }
+
+const char a0[] = { 'a', 'b', 'c', '\0' };
+
+int len0 ()
+{
+  return __builtin_strlen (a0);
+}
+
+const char c = 0;
+const char a1[] = { 'a', 'b', 'c', c };
+
+int len1 ()
+{
+  return __builtin_strlen (a1);
+}
+
+#if 0
+
+// The following aren't handled.
+
+const char &cref = c;
+const char a2[] = { 'a', 'b', 'c', cref };
+
+int len2 ()
+{
+  return __builtin_strlen (a2);
+}
+
+
+const char* const cptr = &cref;
+const char a3[] = { 'a', 'b', 'c', *cptr };
+
+int len3 ()
+{
+  return __builtin_strlen (a3);
+}
+
+#endif
+
+// { dg-final { scan-tree-dump-times "strlen" 0 "gimple" } }
Index: gcc/testsuite/g++.dg/init/string3.C
===================================================================
--- gcc/testsuite/g++.dg/init/string3.C	(nonexistent)
+++ gcc/testsuite/g++.dg/init/string3.C	(working copy)
@@ -0,0 +1,36 @@
+// PR tree-optimization/71625 - missing strlen optimization on different
+// array initialization style
+//
+// Verify that strlen() call with a constant character array argument
+// initialized with non-constant elements isn't folded.  (This is a small
+// subset of pr63989).
+//
+// { dg-do compile }
+// { dg-options "-O2 -fdump-tree-optimized" }
+
+
+extern const char c;
+const char a0[] = { 'a', 'b', 'c', c };
+
+int len0 ()
+{
+  return __builtin_strlen (a0);
+}
+
+const char &ref = c;
+const char a1[] = { 'a', 'b', 'c', ref };
+
+int len1 ()
+{
+  return __builtin_strlen (a1);
+}
+
+const char* const ptr = &c;
+const char a2[] = { 'a', 'b', 'c', *ptr };
+
+int len2 ()
+{
+  return __builtin_strlen (a2);
+}
+
+// { dg-final { scan-tree-dump-times "strlen" 3 "optimized" } }
Index: gcc/testsuite/gcc.dg/strlenopt-55.c
===================================================================
--- gcc/testsuite/gcc.dg/strlenopt-55.c	(nonexistent)
+++ gcc/testsuite/gcc.dg/strlenopt-55.c	(working copy)
@@ -0,0 +1,227 @@
+/* PR tree-optimization/71625 - missing strlen optimization on different
+   array initialization style
+
+   Verify that strlen() of braced initialized array is folded
+   { dg-do compile }
+   { dg-options "-O1 -Wall -fdump-tree-gimple -fdump-tree-optimized" } */
+
+#include "strlenopt.h"
+
+#define S								\
+  "\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f"	\
+  "\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f"	\
+  "\x20\x21\x22\x23\x24\x25\x26\x27\x28\x29\x2a\x2b\x2c\x2d\x2e\x2f"	\
+  "\x30\x31\x32\x33\x34\x35\x36\x37\x38\x39\x3a\x3b\x3c\x3d\x3e\x3f"	\
+  "\x40\x41\x42\x43\x44\x45\x46\x47\x48\x49\x4a\x4b\x4c\x4d\x4e\x4f"	\
+  "\x50\x51\x52\x53\x54\x55\x56\x57\x58\x59\x5a\x5b\x5c\x5d\x5e\x5f"	\
+  "\x60\x61\x62\x63\x64\x65\x66\x67\x68\x69\x6a\x6b\x6c\x6d\x6e\x6f"	\
+  "\x70\x71\x72\x73\x74\x75\x76\x77\x78\x79\x7a\x7b\x7c\x7d\x7e\x7f"	\
+  "\x80\x81\x82\x83\x84\x85\x86\x87\x88\x89\x8a\x8b\x8c\x8d\x8e\x8f"	\
+  "\x90\x91\x92\x93\x94\x95\x96\x97\x98\x99\x9a\x9b\x9c\x9d\x9e\x9f"	\
+  "\xa0\xa1\xa2\xa3\xa4\xa5\xa6\xa7\xa8\xa9\xaa\xab\xac\xad\xae\xaf"	\
+  "\xb0\xb1\xb2\xb3\xb4\xb5\xb6\xb7\xb8\xb9\xba\xbb\xbc\xbd\xbe\xbf"	\
+  "\xc0\xc1\xc2\xc3\xc4\xc5\xc6\xc7\xc8\xc9\xca\xcb\xcc\xcd\xce\xcf"	\
+  "\xd0\xd1\xd2\xd3\xd4\xd5\xd6\xd7\xd8\xd9\xda\xdb\xdc\xdd\xde\xdf"	\
+  "\xe0\xe1\xe2\xe3\xe4\xe5\xe6\xe7\xe8\xe9\xea\xeb\xec\xed\xee\xef"	\
+  "\xf0\xf1\xf2\xf3\xf4\xf5\xf6\xf7\xf8\xf9\xfa\xfb\xfc\xfd\xfe\xff"
+
+/* Arrays of char, signed char, and unsigned char to verify that
+   the length and contents of all are the same as that of the string
+   literal above.  */
+
+const char c256[] = {
+  S[0], S[1], S[2], S[3], S[4], S[5], S[6], S[7], S[8], S[9], S[10],
+  S[11], S[12], S[13], S[14], S[15], S[16], S[17], S[18], S[19], S[20],
+  S[21], S[22], S[23], S[24], S[25], S[26], S[27], S[28], S[29], S[30],
+  S[31], S[32], S[33], S[34], S[35], S[36], S[37], S[38], S[39], S[40],
+  S[41], S[42], S[43], S[44], S[45], S[46], S[47], S[48], S[49], S[50],
+  S[51], S[52], S[53], S[54], S[55], S[56], S[57], S[58], S[59], S[60],
+  S[61], S[62], S[63], S[64], S[65], S[66], S[67], S[68], S[69], S[70],
+  S[71], S[72], S[73], S[74], S[75], S[76], S[77], S[78], S[79], S[80],
+  S[81], S[82], S[83], S[84], S[85], S[86], S[87], S[88], S[89], S[90],
+  S[91], S[92], S[93], S[94], S[95], S[96], S[97], S[98], S[99], S[100],
+  S[101], S[102], S[103], S[104], S[105], S[106], S[107], S[108], S[109],
+  S[110], S[111], S[112], S[113], S[114], S[115], S[116], S[117], S[118],
+  S[119], S[120], S[121], S[122], S[123], S[124], S[125], S[126], S[127],
+  S[128], S[129], S[130], S[131], S[132], S[133], S[134], S[135], S[136],
+  S[137], S[138], S[139], S[140], S[141], S[142], S[143], S[144], S[145],
+  S[146], S[147], S[148], S[149], S[150], S[151], S[152], S[153], S[154],
+  S[155], S[156], S[157], S[158], S[159], S[160], S[161], S[162], S[163],
+  S[164], S[165], S[166], S[167], S[168], S[169], S[170], S[171], S[172],
+  S[173], S[174], S[175], S[176], S[177], S[178], S[179], S[180], S[181],
+  S[182], S[183], S[184], S[185], S[186], S[187], S[188], S[189], S[190],
+  S[191], S[192], S[193], S[194], S[195], S[196], S[197], S[198], S[199],
+  S[200], S[201], S[202], S[203], S[204], S[205], S[206], S[207], S[208],
+  S[209], S[210], S[211], S[212], S[213], S[214], S[215], S[216], S[217],
+  S[218], S[219], S[220], S[221], S[222], S[223], S[224], S[225], S[226],
+  S[227], S[228], S[229], S[230], S[231], S[232], S[233], S[234], S[235],
+  S[236], S[237], S[238], S[239], S[240], S[241], S[242], S[243], S[244],
+  S[245], S[246], S[247], S[248], S[249], S[250], S[251], S[252], S[253],
+  S[254], S[255] /* = NUL */
+};
+
+const signed char sc256[] = {
+  S[0], S[1], S[2], S[3], S[4], S[5], S[6], S[7], S[8], S[9], S[10],
+  S[11], S[12], S[13], S[14], S[15], S[16], S[17], S[18], S[19], S[20],
+  S[21], S[22], S[23], S[24], S[25], S[26], S[27], S[28], S[29], S[30],
+  S[31], S[32], S[33], S[34], S[35], S[36], S[37], S[38], S[39], S[40],
+  S[41], S[42], S[43], S[44], S[45], S[46], S[47], S[48], S[49], S[50],
+  S[51], S[52], S[53], S[54], S[55], S[56], S[57], S[58], S[59], S[60],
+  S[61], S[62], S[63], S[64], S[65], S[66], S[67], S[68], S[69], S[70],
+  S[71], S[72], S[73], S[74], S[75], S[76], S[77], S[78], S[79], S[80],
+  S[81], S[82], S[83], S[84], S[85], S[86], S[87], S[88], S[89], S[90],
+  S[91], S[92], S[93], S[94], S[95], S[96], S[97], S[98], S[99], S[100],
+  S[101], S[102], S[103], S[104], S[105], S[106], S[107], S[108], S[109],
+  S[110], S[111], S[112], S[113], S[114], S[115], S[116], S[117], S[118],
+  S[119], S[120], S[121], S[122], S[123], S[124], S[125], S[126], S[127],
+  S[128], S[129], S[130], S[131], S[132], S[133], S[134], S[135], S[136],
+  S[137], S[138], S[139], S[140], S[141], S[142], S[143], S[144], S[145],
+  S[146], S[147], S[148], S[149], S[150], S[151], S[152], S[153], S[154],
+  S[155], S[156], S[157], S[158], S[159], S[160], S[161], S[162], S[163],
+  S[164], S[165], S[166], S[167], S[168], S[169], S[170], S[171], S[172],
+  S[173], S[174], S[175], S[176], S[177], S[178], S[179], S[180], S[181],
+  S[182], S[183], S[184], S[185], S[186], S[187], S[188], S[189], S[190],
+  S[191], S[192], S[193], S[194], S[195], S[196], S[197], S[198], S[199],
+  S[200], S[201], S[202], S[203], S[204], S[205], S[206], S[207], S[208],
+  S[209], S[210], S[211], S[212], S[213], S[214], S[215], S[216], S[217],
+  S[218], S[219], S[220], S[221], S[222], S[223], S[224], S[225], S[226],
+  S[227], S[228], S[229], S[230], S[231], S[232], S[233], S[234], S[235],
+  S[236], S[237], S[238], S[239], S[240], S[241], S[242], S[243], S[244],
+  S[245], S[246], S[247], S[248], S[249], S[250], S[251], S[252], S[253],
+  S[254], S[255] /* = NUL */
+};
+
+const unsigned char uc256[] = {
+  S[0], S[1], S[2], S[3], S[4], S[5], S[6], S[7], S[8], S[9], S[10],
+  S[11], S[12], S[13], S[14], S[15], S[16], S[17], S[18], S[19], S[20],
+  S[21], S[22], S[23], S[24], S[25], S[26], S[27], S[28], S[29], S[30],
+  S[31], S[32], S[33], S[34], S[35], S[36], S[37], S[38], S[39], S[40],
+  S[41], S[42], S[43], S[44], S[45], S[46], S[47], S[48], S[49], S[50],
+  S[51], S[52], S[53], S[54], S[55], S[56], S[57], S[58], S[59], S[60],
+  S[61], S[62], S[63], S[64], S[65], S[66], S[67], S[68], S[69], S[70],
+  S[71], S[72], S[73], S[74], S[75], S[76], S[77], S[78], S[79], S[80],
+  S[81], S[82], S[83], S[84], S[85], S[86], S[87], S[88], S[89], S[90],
+  S[91], S[92], S[93], S[94], S[95], S[96], S[97], S[98], S[99], S[100],
+  S[101], S[102], S[103], S[104], S[105], S[106], S[107], S[108], S[109],
+  S[110], S[111], S[112], S[113], S[114], S[115], S[116], S[117], S[118],
+  S[119], S[120], S[121], S[122], S[123], S[124], S[125], S[126], S[127],
+  S[128], S[129], S[130], S[131], S[132], S[133], S[134], S[135], S[136],
+  S[137], S[138], S[139], S[140], S[141], S[142], S[143], S[144], S[145],
+  S[146], S[147], S[148], S[149], S[150], S[151], S[152], S[153], S[154],
+  S[155], S[156], S[157], S[158], S[159], S[160], S[161], S[162], S[163],
+  S[164], S[165], S[166], S[167], S[168], S[169], S[170], S[171], S[172],
+  S[173], S[174], S[175], S[176], S[177], S[178], S[179], S[180], S[181],
+  S[182], S[183], S[184], S[185], S[186], S[187], S[188], S[189], S[190],
+  S[191], S[192], S[193], S[194], S[195], S[196], S[197], S[198], S[199],
+  S[200], S[201], S[202], S[203], S[204], S[205], S[206], S[207], S[208],
+  S[209], S[210], S[211], S[212], S[213], S[214], S[215], S[216], S[217],
+  S[218], S[219], S[220], S[221], S[222], S[223], S[224], S[225], S[226],
+  S[227], S[228], S[229], S[230], S[231], S[232], S[233], S[234], S[235],
+  S[236], S[237], S[238], S[239], S[240], S[241], S[242], S[243], S[244],
+  S[245], S[246], S[247], S[248], S[249], S[250], S[251], S[252], S[253],
+  S[254], S[255] /* = NUL */
+};
+
+const __CHAR16_TYPE__ c16_4[] = {
+  1, 0x7fff, 0x8000, 0xffff,
+  0x10000   /* { dg-warning "\\\[-Woverflow]" } */
+};
+
+const char a2_implicit[2] = { };
+const char a3_implicit[3] = { };
+
+const char a3_nul[3] = { 0 };
+const char a5_nul1[3] = { [1] = 0 };
+const char a7_nul2[3] = { [2] = 0 };
+
+const char ax_2_nul[] = { '1', '2', '\0' };
+const char ax_3_nul[] = { '1', '2', '3', '\0' };
+
+const char ax_3_des_nul[] = { [3] = 0, [2] = '3', [1] = '2', [0] = '1' };
+
+const char ax_3[] = { '1', '2', '3' };
+const char a3_3[3] = { '1', '2', '3' };
+
+const char a100_3[] = { '1', '2', '3', [100] = '\0' };
+
+#define CONCAT(x, y) x ## y
+#define CAT(x, y) CONCAT (x, y)
+#define FAILNAME(name) CAT (call_ ## name ##_on_line_, __LINE__)
+
+#define FAIL(name) do {				\
+    extern void FAILNAME (name) (void);		\
+    FAILNAME (name)();				\
+  } while (0)
+
+/* Macro to emit a call to funcation named
+   call_in_true_branch_not_eliminated_on_line_NNN()
+   for each call that's expected to be eliminated.  The dg-final
+   scan-tree-dump-time directive at the bottom of the test verifies
+   that no such call appears in output.  */
+#define ELIM(expr)							\
+  if (!(expr)) FAIL (in_true_branch_not_eliminated); else (void)0
+
+#define T(s, n) ELIM (strlen (s) == n)
+
+void test_nulstring (void)
+{
+  T (a2_implicit, 0);
+  T (a3_implicit, 0);
+
+  T (a3_nul, 0);
+  T (a5_nul1, 0);
+  T (a7_nul2, 0);
+
+  T (ax_2_nul, 2);
+  T (ax_3_nul, 3);
+  T (ax_3_des_nul, 3);
+
+  T (a100_3, 3);
+
+  /* Verify that all three character arrays have the same length
+     as the string literal they are initialized with.  */
+  T (S, 255);
+  T (c256, 255);
+  T ((const char*)sc256, 255);
+  T ((const char*)uc256, 255);
+
+  /* Verify that all three character arrays have the same contents
+     as the string literal they are initialized with.  */
+  ELIM (0 == memcmp (c256, S, sizeof c256));
+  ELIM (0 == memcmp (c256, (const char*)sc256, sizeof c256));
+  ELIM (0 == memcmp (c256, (const char*)uc256, sizeof c256));
+
+  ELIM (0 == strcmp (c256, (const char*)sc256));
+  ELIM (0 == strcmp (c256, (const char*)uc256));
+
+  /* Verify that the char16_t array has the expected contents.  */
+  ELIM (c16_4[0] == 1 && c16_4[1] == 0x7fff
+	&& c16_4[2] == 0x8000 && c16_4[3] == 0xffff
+	&& c16_4[4] == 0);
+}
+
+/* Verify that excessively large initializers don't run out of
+   memory.  Also verify that the they have the expected size and
+   contents.  */
+
+#define MAX (__PTRDIFF_MAX__ - 1)
+
+const char large_string[] = { 'a', [1234] = 'b', [MAX] = '\0' };
+
+const void test_large_string_size (void)
+{
+  ELIM (sizeof large_string == MAX + 1);
+
+  /* The following expressions are not folded without optimization.  */
+  ELIM ('a'  == large_string[0]);
+  ELIM ('\0' == large_string[1233]);
+  ELIM ('b'  == large_string[1234]);
+  ELIM ('\0' == large_string[1235]);
+  ELIM ('\0' == large_string[MAX - 1]);
+}
+
+
+/* { dg-final { scan-tree-dump-times "strlen" 0 "gimple" } }
+   { dg-final { scan-tree-dump-times "memcmp" 0 "gimple" } }
+   { dg-final { scan-tree-dump-times "strcmp" 0 "gimple" } }
+   { dg-final { scan-tree-dump-times "call_in_true_branch_not_eliminated" 0 "optimized" } } */
Jason Merrill Aug. 7, 2018, 8:57 a.m. UTC | #6
On Wed, Aug 1, 2018 at 12:49 AM, Martin Sebor <msebor@gmail.com> wrote:
> On 07/31/2018 07:38 AM, Jason Merrill wrote:
>>
>> On Tue, Jul 31, 2018 at 9:51 AM, Martin Sebor <msebor@gmail.com> wrote:
>>>
>>> The middle-end contains code to determine the lengths of constant
>>> character arrays initialized by string literals.  The code is used
>>> in a number of optimizations and warnings.
>>>
>>> However, the code is unable to deal with constant arrays initialized
>>> using the braced initializer syntax, as in
>>>
>>>   const char a[] = { '1', '2', '\0' };
>>>
>>> The attached patch extends the C and C++ front-ends to convert such
>>> initializers into a STRING_CST form.
>>>
>>> The goal of this work is to both enable existing optimizations for
>>> such arrays, and to help detect bugs due to using non-nul terminated
>>> arrays where nul-terminated strings are expected.  The latter is
>>> an extension of the GCC 8 _Wstringop-overflow and
>>> -Wstringop-truncation warnings that help detect or prevent reading
>>> past the end of dynamically created character arrays.  Future work
>>> includes detecting potential past-the-end reads from uninitialized
>>> local character arrays.
>>
>>
>>>   && TYPE_MAIN_VARIANT (TREE_TYPE (valtype)) == char_type_node)
>>
>>
>> Why? Don't we want this for other character types as well?
>
> It suppresses narrowing warnings for things like
>
>   signed char a[] = { 0xff };
>
> (there are a couple of tests that exercise this).

Why is plain char different in this respect?  Presumably one of

char a[] = { -1 };
char b[] = { 0xff };

should give the same narrowing warning, depending on whether char is signed.

> At the same time, STRING_CST is supposed to be able to represent
> strings of any integer type so there should be a way to make it
> work.  On the flip side, recent discussions of changes in this
> area suggest there may be bugs in the wide character handling of
> STRING_CST so those would need to be fixed before relying on it
> for robust support.
>
> In any case, if you have a suggestion for how to make it work for
> at least the narrow character types I'll adjust the patch.

I suppose braced_list_to_string should call check_narrowing for C++.

Currently it uses tree_fits_shwi_p (signed host_wide_int) and then
stores the extracted value in a host unsigned int, which is then
converted to host char.  Does the right thing happen for -fsigned-char
or targets with a different character set?

Jason
Joseph Myers Aug. 7, 2018, 11:31 a.m. UTC | #7
On Tue, 7 Aug 2018, Martin Sebor wrote:

> 2) skipping embedded nuls made it possible to create a string
> with fewer elements than the initializer array, which caused
> arrays with unspecified bound to be smaller than they would
> have been otherwise

I think there should be explicit tests of sizeof for arrays with 
unspecified bound - to make sure both that it isn't any smaller than it 
should be, but also that any NULs implicitly added for a STRING_CST don't 
make the arrays any larger than their size should be for the originally 
given initializer that doesn't have a 0 as the last element.
Martin Sebor Aug. 7, 2018, 11:04 p.m. UTC | #8
On 08/07/2018 02:57 AM, Jason Merrill wrote:
> On Wed, Aug 1, 2018 at 12:49 AM, Martin Sebor <msebor@gmail.com> wrote:
>> On 07/31/2018 07:38 AM, Jason Merrill wrote:
>>>
>>> On Tue, Jul 31, 2018 at 9:51 AM, Martin Sebor <msebor@gmail.com> wrote:
>>>>
>>>> The middle-end contains code to determine the lengths of constant
>>>> character arrays initialized by string literals.  The code is used
>>>> in a number of optimizations and warnings.
>>>>
>>>> However, the code is unable to deal with constant arrays initialized
>>>> using the braced initializer syntax, as in
>>>>
>>>>   const char a[] = { '1', '2', '\0' };
>>>>
>>>> The attached patch extends the C and C++ front-ends to convert such
>>>> initializers into a STRING_CST form.
>>>>
>>>> The goal of this work is to both enable existing optimizations for
>>>> such arrays, and to help detect bugs due to using non-nul terminated
>>>> arrays where nul-terminated strings are expected.  The latter is
>>>> an extension of the GCC 8 _Wstringop-overflow and
>>>> -Wstringop-truncation warnings that help detect or prevent reading
>>>> past the end of dynamically created character arrays.  Future work
>>>> includes detecting potential past-the-end reads from uninitialized
>>>> local character arrays.
>>>
>>>
>>>>   && TYPE_MAIN_VARIANT (TREE_TYPE (valtype)) == char_type_node)
>>>
>>>
>>> Why? Don't we want this for other character types as well?
>>
>> It suppresses narrowing warnings for things like
>>
>>   signed char a[] = { 0xff };
>>
>> (there are a couple of tests that exercise this).
>
> Why is plain char different in this respect?  Presumably one of
>
> char a[] = { -1 };
> char b[] = { 0xff };
>
> should give the same narrowing warning, depending on whether char is signed.

Right.  I've added more tests to verify that it does.

>> At the same time, STRING_CST is supposed to be able to represent
>> strings of any integer type so there should be a way to make it
>> work.  On the flip side, recent discussions of changes in this
>> area suggest there may be bugs in the wide character handling of
>> STRING_CST so those would need to be fixed before relying on it
>> for robust support.
>>
>> In any case, if you have a suggestion for how to make it work for
>> at least the narrow character types I'll adjust the patch.
>
> I suppose braced_list_to_string should call check_narrowing for C++.

I see.  I've made that change.  That has made it possible to
convert arrays of all character types.  Thanks!

> Currently it uses tree_fits_shwi_p (signed host_wide_int) and then
> stores the extracted value in a host unsigned int, which is then
> converted to host char.  Does the right thing happen for -fsigned-char
> or targets with a different character set?

I believe so.  I've added tests for these too (ASCII and EBCDIC)
and also changed the type of the extracted value to HWI to match
(it doesn't change the results of the tests).

Attached is an updated patch with these changes plus more tests
as suggested by Joseph.

Martin
PR tree-optimization/71625 - missing strlen optimization on different array initialization style

gcc/c/ChangeLog:

	PR tree-optimization/71625
	* c-parser.c (c_parser_declaration_or_fndef): Call
	braced_list_to_string.

gcc/c-family/ChangeLog:

	PR tree-optimization/71625
	* c-common.c (braced_list_to_string): New function.
	* c-common.h (braced_list_to_string): Declare it.

gcc/cp/ChangeLog:

	PR tree-optimization/71625
	* parser.c (cp_parser_init_declarator):  Call braced_list_to_string.
	(eval_check_narrowing): New function.

gcc/testsuite/ChangeLog:

	PR tree-optimization/71625
	* g++.dg/init/string2.C: New test.
	* g++.dg/init/string3.C: New test.
	* gcc.dg/strlenopt-55.c: New test.
	* gcc.dg/strlenopt-56.c: New test.

Index: gcc/c/c-parser.c
===================================================================
--- gcc/c/c-parser.c	(revision 263372)
+++ gcc/c/c-parser.c	(working copy)
@@ -2126,6 +2126,15 @@ c_parser_declaration_or_fndef (c_parser *parser, b
 	      if (d != error_mark_node)
 		{
 		  maybe_warn_string_init (init_loc, TREE_TYPE (d), init);
+
+		  /* Try to convert a string CONSTRUCTOR into a STRING_CST.  */
+		  tree valtype = TREE_TYPE (init.value);
+		  if (TREE_CODE (init.value) == CONSTRUCTOR
+		      && TREE_CODE (valtype) == ARRAY_TYPE
+		      && TYPE_STRING_FLAG (TREE_TYPE (valtype)))
+		    if (tree str = braced_list_to_string (valtype, init.value))
+		      init.value = str;
+
 		  finish_decl (d, init_loc, init.value,
 			       init.original_type, asm_name);
 		}
Index: gcc/c-family/c-common.c
===================================================================
--- gcc/c-family/c-common.c	(revision 263372)
+++ gcc/c-family/c-common.c	(working copy)
@@ -8509,4 +8509,84 @@ maybe_add_include_fixit (rich_location *richloc, c
   free (text);
 }
 
+/* Attempt to convert a braced array initializer list CTOR for array
+   TYPE into a STRING_CST for convenience and efficiency.  When non-null,
+   use EVAL to attempt to evalue constants (used by C++).  Return
+   the converted string on success or null on failure.  */
+
+tree
+braced_list_to_string (tree type, tree ctor, tree (*eval)(tree, tree))
+{
+  /* If the array has an explicit bound, use it to constrain the size
+     of the string.  If it doesn't, be sure to create a string that's
+     as long as implied by the index of the last zero specified via
+     a designator, as in:
+       const char a[] = { [7] = 0 };  */
+  unsigned HOST_WIDE_INT maxelts = HOST_WIDE_INT_M1U;
+  if (tree nelts = TYPE_SIZE_UNIT (type))
+    if (tree_fits_uhwi_p (nelts))
+      {
+	maxelts = tree_to_uhwi (nelts);
+	maxelts /= tree_to_uhwi (TYPE_SIZE_UNIT (TREE_TYPE (type)));
+      }
+
+  unsigned HOST_WIDE_INT nelts = CONSTRUCTOR_NELTS (ctor);
+  tree eltype = TREE_TYPE (type);
+
+  auto_vec<char> str;
+  str.reserve (nelts + 1);
+
+  unsigned HOST_WIDE_INT i;
+  tree index, value;
+
+  FOR_EACH_CONSTRUCTOR_ELT (CONSTRUCTOR_ELTS (ctor), i, index, value)
+    {
+      unsigned HOST_WIDE_INT idx = index ? tree_to_uhwi (index) : i;
+
+      /* auto_vec is limited to UINT_MAX elements.  */
+      if (idx > UINT_MAX)
+	return NULL_TREE;
+
+      /* Attempt to evaluate constants.  */
+      if (eval)
+	value = eval (eltype, value);
+
+      /* Avoid non-constant initializers.  */
+     if (!tree_fits_shwi_p (value))
+	return NULL_TREE;
+
+      /* Skip over embedded nuls.  */
+      HOST_WIDE_INT val = tree_to_shwi (value);
+      if (!val && i + 1 < nelts)
+	continue;
+
+      /* Bail if the CTOR has a block of more than 256 embedded nuls
+	 due to implicitly initialized elements.  */
+      unsigned nelts = (idx - str.length ()) + 1;
+      if (nelts > 256)
+	return NULL_TREE;
+
+      if (nelts > 1)
+	{
+	  str.reserve (idx);
+	  str.quick_grow_cleared (idx);
+	}
+
+      if (idx > maxelts)
+	return NULL_TREE;
+
+      str.safe_insert (idx, val);
+    }
+
+  if (!nelts || str.length () < i)
+    /* Append a nul for the empty initializer { } and for the last
+       explicit initializer in the loop above that is a nul.  */
+    str.safe_push (0);
+
+  /* Build a string literal but return the embedded STRING_CST.  */
+  tree res = build_string_literal (str.length (), str.begin ());
+  res = TREE_OPERAND (TREE_OPERAND (res, 0), 0);
+  return res;
+}
+
 #include "gt-c-family-c-common.h"
Index: gcc/c-family/c-common.h
===================================================================
--- gcc/c-family/c-common.h	(revision 263372)
+++ gcc/c-family/c-common.h	(working copy)
@@ -1331,6 +1331,7 @@ extern void maybe_add_include_fixit (rich_location
 extern void maybe_suggest_missing_token_insertion (rich_location *richloc,
 						   enum cpp_ttype token_type,
 						   location_t prev_token_loc);
+extern tree braced_list_to_string (tree, tree, tree (*)(tree, tree) = NULL);
 
 #if CHECKING_P
 namespace selftest {
Index: gcc/cp/parser.c
===================================================================
--- gcc/cp/parser.c	(revision 263372)
+++ gcc/cp/parser.c	(working copy)
@@ -19419,6 +19419,30 @@ strip_declarator_types (tree type, cp_declarator *
   return type;
 }
 
+/* Attempt to determine the constant VALUE of integral type and convert
+   it to TYPE, issuing narrowing warnings/errors as necessary.  Return
+   the constant result or null on failure.  Callback for
+   braced_list_to_string.  */
+
+static tree
+eval_check_narrowing (tree type, tree value)
+{
+  if (tree valtype = TREE_TYPE (value))
+    {
+      if (TREE_CODE (valtype) != INTEGER_TYPE)
+	return NULL_TREE;
+    }
+  else
+    return NULL_TREE;
+
+  value = scalar_constant_value (value);
+  if (!value)
+    return NULL_TREE;
+
+  check_narrowing (type, value, tf_warning_or_error);
+  return value;
+}
+
 /* Declarators [gram.dcl.decl] */
 
 /* Parse an init-declarator.
@@ -19825,6 +19849,18 @@ cp_parser_init_declarator (cp_parser* parser,
 	    finish_lambda_scope ();
 	  if (initializer == error_mark_node)
 	    cp_parser_skip_to_end_of_statement (parser);
+	  else if (decl)
+	    {
+	      /* Try to convert a string CONSTRUCTOR into a STRING_CST.  */
+	      tree valtype = TREE_TYPE (decl);
+	      if (TREE_CODE (valtype) == ARRAY_TYPE
+		  && TYPE_STRING_FLAG (TREE_TYPE (valtype))
+		  && TREE_CODE (initializer) == CONSTRUCTOR
+		  && TREE_TYPE (initializer) == init_list_type_node)
+		if (tree str = braced_list_to_string (valtype, initializer,
+						      eval_check_narrowing))
+		  initializer = str;
+	    }
 	}
     }
 
Index: gcc/testsuite/g++.dg/init/string2.C
===================================================================
--- gcc/testsuite/g++.dg/init/string2.C	(nonexistent)
+++ gcc/testsuite/g++.dg/init/string2.C	(working copy)
@@ -0,0 +1,85 @@
+// PR tree-optimization/71625 - missing strlen optimization on different
+// array initialization style
+//
+// Verify that strlen() calls with constant character array arguments
+// initialized with string constants are folded.  (This is a small
+// subset of pr63989).
+// { dg-do compile }
+// { dg-options "-O0 -Wno-error=narrowing -fdump-tree-gimple" }
+
+#define A(expr) do { typedef char A[-1 + 2 * !!(expr)]; } while (0)
+
+const char a0[] = { 'a', 'b', 'c', '\0' };
+
+int len0 ()
+{
+  return __builtin_strlen (a0);
+}
+
+// Verify that narrowing warnings are preserved.
+const signed char
+sa0[] = { 'a', 'b', 255, '\0' };   // { dg-warning "\\\[\(-Wnarrowing|-Woverflow\)" "" { target { ! c++98_only } } }
+
+int lens0 ()
+{
+  return __builtin_strlen ((const char*)sa0);
+}
+
+const unsigned char
+ua0[] = { 'a', 'b', -1, '\0' };   // { dg-warning "\\\[\(-Wnarrowing|-Woverflow\)" "" { target { ! c++98_only } } }
+
+int lenu0 ()
+{
+  return __builtin_strlen ((const char*)ua0);
+}
+
+const char c = 0;
+const char a1[] = { 'a', 'b', 'c', c };
+
+int len1 ()
+{
+  return __builtin_strlen (a1);
+}
+
+const wchar_t ws4[] = { 1, 2, 3, 4 };
+const wchar_t ws7[] = { 1, 2, 3, 4, 0, 0, 0 };
+const wchar_t ws9[9] = { 1, 2, 3, 4, 0 };
+
+void wsize ()
+{
+  A (sizeof ws4 == 4 * sizeof *ws4);
+  A (ws4[0] == 1 && ws4[1] == 2 && ws4[2] == 3 && ws4[3] == 4);
+
+  A (sizeof ws7 == 7 * sizeof *ws7);
+  A (ws7[0] == 1 && ws7[1] == 2 && ws7[2] == 3 && ws7[4] == 4
+     && !ws7[5] && !ws7[6]);
+
+  A (sizeof ws9 == 9 * sizeof *ws9);
+  A (ws9[0] == 1 && ws9[1] == 2 && ws9[2] == 3 && ws9[4] == 4
+     && !ws9[5] && !ws9[6] && !ws9[7] && !ws9[8]);
+}
+
+#if 0
+
+// The following aren't handled.
+
+const char &cref = c;
+const char a2[] = { 'a', 'b', 'c', cref };
+
+int len2 ()
+{
+  return __builtin_strlen (a2);
+}
+
+
+const char* const cptr = &cref;
+const char a3[] = { 'a', 'b', 'c', *cptr };
+
+int len3 ()
+{
+  return __builtin_strlen (a3);
+}
+
+#endif
+
+// { dg-final { scan-tree-dump-times "strlen" 0 "gimple" } }
Index: gcc/testsuite/g++.dg/init/string3.C
===================================================================
--- gcc/testsuite/g++.dg/init/string3.C	(nonexistent)
+++ gcc/testsuite/g++.dg/init/string3.C	(working copy)
@@ -0,0 +1,36 @@
+// PR tree-optimization/71625 - missing strlen optimization on different
+// array initialization style
+//
+// Verify that strlen() call with a constant character array argument
+// initialized with non-constant elements isn't folded.  (This is a small
+// subset of pr63989).
+//
+// { dg-do compile }
+// { dg-options "-O2 -fdump-tree-optimized" }
+
+
+extern const char c;
+const char a0[] = { 'a', 'b', 'c', c };
+
+int len0 ()
+{
+  return __builtin_strlen (a0);
+}
+
+const char &ref = c;
+const char a1[] = { 'a', 'b', 'c', ref };
+
+int len1 ()
+{
+  return __builtin_strlen (a1);
+}
+
+const char* const ptr = &c;
+const char a2[] = { 'a', 'b', 'c', *ptr };
+
+int len2 ()
+{
+  return __builtin_strlen (a2);
+}
+
+// { dg-final { scan-tree-dump-times "strlen" 3 "optimized" } }
Index: gcc/testsuite/gcc.dg/strlenopt-55.c
===================================================================
--- gcc/testsuite/gcc.dg/strlenopt-55.c	(nonexistent)
+++ gcc/testsuite/gcc.dg/strlenopt-55.c	(working copy)
@@ -0,0 +1,230 @@
+/* PR tree-optimization/71625 - missing strlen optimization on different
+   array initialization style
+
+   Verify that strlen() of braced initialized array is folded
+   { dg-do compile }
+   { dg-options "-O1 -Wall -fdump-tree-gimple -fdump-tree-optimized" } */
+
+#include "strlenopt.h"
+
+#define S								\
+  "\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f"	\
+  "\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f"	\
+  "\x20\x21\x22\x23\x24\x25\x26\x27\x28\x29\x2a\x2b\x2c\x2d\x2e\x2f"	\
+  "\x30\x31\x32\x33\x34\x35\x36\x37\x38\x39\x3a\x3b\x3c\x3d\x3e\x3f"	\
+  "\x40\x41\x42\x43\x44\x45\x46\x47\x48\x49\x4a\x4b\x4c\x4d\x4e\x4f"	\
+  "\x50\x51\x52\x53\x54\x55\x56\x57\x58\x59\x5a\x5b\x5c\x5d\x5e\x5f"	\
+  "\x60\x61\x62\x63\x64\x65\x66\x67\x68\x69\x6a\x6b\x6c\x6d\x6e\x6f"	\
+  "\x70\x71\x72\x73\x74\x75\x76\x77\x78\x79\x7a\x7b\x7c\x7d\x7e\x7f"	\
+  "\x80\x81\x82\x83\x84\x85\x86\x87\x88\x89\x8a\x8b\x8c\x8d\x8e\x8f"	\
+  "\x90\x91\x92\x93\x94\x95\x96\x97\x98\x99\x9a\x9b\x9c\x9d\x9e\x9f"	\
+  "\xa0\xa1\xa2\xa3\xa4\xa5\xa6\xa7\xa8\xa9\xaa\xab\xac\xad\xae\xaf"	\
+  "\xb0\xb1\xb2\xb3\xb4\xb5\xb6\xb7\xb8\xb9\xba\xbb\xbc\xbd\xbe\xbf"	\
+  "\xc0\xc1\xc2\xc3\xc4\xc5\xc6\xc7\xc8\xc9\xca\xcb\xcc\xcd\xce\xcf"	\
+  "\xd0\xd1\xd2\xd3\xd4\xd5\xd6\xd7\xd8\xd9\xda\xdb\xdc\xdd\xde\xdf"	\
+  "\xe0\xe1\xe2\xe3\xe4\xe5\xe6\xe7\xe8\xe9\xea\xeb\xec\xed\xee\xef"	\
+  "\xf0\xf1\xf2\xf3\xf4\xf5\xf6\xf7\xf8\xf9\xfa\xfb\xfc\xfd\xfe\xff"
+
+/* Arrays of char, signed char, and unsigned char to verify that
+   the length and contents of all are the same as that of the string
+   literal above.  */
+
+const char c256[] = {
+  S[0], S[1], S[2], S[3], S[4], S[5], S[6], S[7], S[8], S[9], S[10],
+  S[11], S[12], S[13], S[14], S[15], S[16], S[17], S[18], S[19], S[20],
+  S[21], S[22], S[23], S[24], S[25], S[26], S[27], S[28], S[29], S[30],
+  S[31], S[32], S[33], S[34], S[35], S[36], S[37], S[38], S[39], S[40],
+  S[41], S[42], S[43], S[44], S[45], S[46], S[47], S[48], S[49], S[50],
+  S[51], S[52], S[53], S[54], S[55], S[56], S[57], S[58], S[59], S[60],
+  S[61], S[62], S[63], S[64], S[65], S[66], S[67], S[68], S[69], S[70],
+  S[71], S[72], S[73], S[74], S[75], S[76], S[77], S[78], S[79], S[80],
+  S[81], S[82], S[83], S[84], S[85], S[86], S[87], S[88], S[89], S[90],
+  S[91], S[92], S[93], S[94], S[95], S[96], S[97], S[98], S[99], S[100],
+  S[101], S[102], S[103], S[104], S[105], S[106], S[107], S[108], S[109],
+  S[110], S[111], S[112], S[113], S[114], S[115], S[116], S[117], S[118],
+  S[119], S[120], S[121], S[122], S[123], S[124], S[125], S[126], S[127],
+  S[128], S[129], S[130], S[131], S[132], S[133], S[134], S[135], S[136],
+  S[137], S[138], S[139], S[140], S[141], S[142], S[143], S[144], S[145],
+  S[146], S[147], S[148], S[149], S[150], S[151], S[152], S[153], S[154],
+  S[155], S[156], S[157], S[158], S[159], S[160], S[161], S[162], S[163],
+  S[164], S[165], S[166], S[167], S[168], S[169], S[170], S[171], S[172],
+  S[173], S[174], S[175], S[176], S[177], S[178], S[179], S[180], S[181],
+  S[182], S[183], S[184], S[185], S[186], S[187], S[188], S[189], S[190],
+  S[191], S[192], S[193], S[194], S[195], S[196], S[197], S[198], S[199],
+  S[200], S[201], S[202], S[203], S[204], S[205], S[206], S[207], S[208],
+  S[209], S[210], S[211], S[212], S[213], S[214], S[215], S[216], S[217],
+  S[218], S[219], S[220], S[221], S[222], S[223], S[224], S[225], S[226],
+  S[227], S[228], S[229], S[230], S[231], S[232], S[233], S[234], S[235],
+  S[236], S[237], S[238], S[239], S[240], S[241], S[242], S[243], S[244],
+  S[245], S[246], S[247], S[248], S[249], S[250], S[251], S[252], S[253],
+  S[254], S[255] /* = NUL */
+};
+
+const signed char sc256[] = {
+  S[0], S[1], S[2], S[3], S[4], S[5], S[6], S[7], S[8], S[9], S[10],
+  S[11], S[12], S[13], S[14], S[15], S[16], S[17], S[18], S[19], S[20],
+  S[21], S[22], S[23], S[24], S[25], S[26], S[27], S[28], S[29], S[30],
+  S[31], S[32], S[33], S[34], S[35], S[36], S[37], S[38], S[39], S[40],
+  S[41], S[42], S[43], S[44], S[45], S[46], S[47], S[48], S[49], S[50],
+  S[51], S[52], S[53], S[54], S[55], S[56], S[57], S[58], S[59], S[60],
+  S[61], S[62], S[63], S[64], S[65], S[66], S[67], S[68], S[69], S[70],
+  S[71], S[72], S[73], S[74], S[75], S[76], S[77], S[78], S[79], S[80],
+  S[81], S[82], S[83], S[84], S[85], S[86], S[87], S[88], S[89], S[90],
+  S[91], S[92], S[93], S[94], S[95], S[96], S[97], S[98], S[99], S[100],
+  S[101], S[102], S[103], S[104], S[105], S[106], S[107], S[108], S[109],
+  S[110], S[111], S[112], S[113], S[114], S[115], S[116], S[117], S[118],
+  S[119], S[120], S[121], S[122], S[123], S[124], S[125], S[126], S[127],
+  S[128], S[129], S[130], S[131], S[132], S[133], S[134], S[135], S[136],
+  S[137], S[138], S[139], S[140], S[141], S[142], S[143], S[144], S[145],
+  S[146], S[147], S[148], S[149], S[150], S[151], S[152], S[153], S[154],
+  S[155], S[156], S[157], S[158], S[159], S[160], S[161], S[162], S[163],
+  S[164], S[165], S[166], S[167], S[168], S[169], S[170], S[171], S[172],
+  S[173], S[174], S[175], S[176], S[177], S[178], S[179], S[180], S[181],
+  S[182], S[183], S[184], S[185], S[186], S[187], S[188], S[189], S[190],
+  S[191], S[192], S[193], S[194], S[195], S[196], S[197], S[198], S[199],
+  S[200], S[201], S[202], S[203], S[204], S[205], S[206], S[207], S[208],
+  S[209], S[210], S[211], S[212], S[213], S[214], S[215], S[216], S[217],
+  S[218], S[219], S[220], S[221], S[222], S[223], S[224], S[225], S[226],
+  S[227], S[228], S[229], S[230], S[231], S[232], S[233], S[234], S[235],
+  S[236], S[237], S[238], S[239], S[240], S[241], S[242], S[243], S[244],
+  S[245], S[246], S[247], S[248], S[249], S[250], S[251], S[252], S[253],
+  S[254], S[255] /* = NUL */
+};
+
+const unsigned char uc256[] = {
+  S[0], S[1], S[2], S[3], S[4], S[5], S[6], S[7], S[8], S[9], S[10],
+  S[11], S[12], S[13], S[14], S[15], S[16], S[17], S[18], S[19], S[20],
+  S[21], S[22], S[23], S[24], S[25], S[26], S[27], S[28], S[29], S[30],
+  S[31], S[32], S[33], S[34], S[35], S[36], S[37], S[38], S[39], S[40],
+  S[41], S[42], S[43], S[44], S[45], S[46], S[47], S[48], S[49], S[50],
+  S[51], S[52], S[53], S[54], S[55], S[56], S[57], S[58], S[59], S[60],
+  S[61], S[62], S[63], S[64], S[65], S[66], S[67], S[68], S[69], S[70],
+  S[71], S[72], S[73], S[74], S[75], S[76], S[77], S[78], S[79], S[80],
+  S[81], S[82], S[83], S[84], S[85], S[86], S[87], S[88], S[89], S[90],
+  S[91], S[92], S[93], S[94], S[95], S[96], S[97], S[98], S[99], S[100],
+  S[101], S[102], S[103], S[104], S[105], S[106], S[107], S[108], S[109],
+  S[110], S[111], S[112], S[113], S[114], S[115], S[116], S[117], S[118],
+  S[119], S[120], S[121], S[122], S[123], S[124], S[125], S[126], S[127],
+  S[128], S[129], S[130], S[131], S[132], S[133], S[134], S[135], S[136],
+  S[137], S[138], S[139], S[140], S[141], S[142], S[143], S[144], S[145],
+  S[146], S[147], S[148], S[149], S[150], S[151], S[152], S[153], S[154],
+  S[155], S[156], S[157], S[158], S[159], S[160], S[161], S[162], S[163],
+  S[164], S[165], S[166], S[167], S[168], S[169], S[170], S[171], S[172],
+  S[173], S[174], S[175], S[176], S[177], S[178], S[179], S[180], S[181],
+  S[182], S[183], S[184], S[185], S[186], S[187], S[188], S[189], S[190],
+  S[191], S[192], S[193], S[194], S[195], S[196], S[197], S[198], S[199],
+  S[200], S[201], S[202], S[203], S[204], S[205], S[206], S[207], S[208],
+  S[209], S[210], S[211], S[212], S[213], S[214], S[215], S[216], S[217],
+  S[218], S[219], S[220], S[221], S[222], S[223], S[224], S[225], S[226],
+  S[227], S[228], S[229], S[230], S[231], S[232], S[233], S[234], S[235],
+  S[236], S[237], S[238], S[239], S[240], S[241], S[242], S[243], S[244],
+  S[245], S[246], S[247], S[248], S[249], S[250], S[251], S[252], S[253],
+  S[254], S[255] /* = NUL */
+};
+
+const __CHAR16_TYPE__ c16_4[] = {
+  1, 0x7fff, 0x8000, 0xffff,
+  0x10000   /* { dg-warning "\\\[-Woverflow]" } */
+};
+
+const char a2_implicit[2] = { };
+const char a3_implicit[3] = { };
+
+const char a3_nul[3] = { 0 };
+const char a5_nul1[3] = { [1] = 0 };
+const char a7_nul2[3] = { [2] = 0 };
+
+const char ax_2_nul[] = { '1', '2', '\0' };
+const char ax_3_nul[] = { '1', '2', '3', '\0' };
+
+const char ax_3_des_nul[] = { [3] = 0, [2] = '3', [1] = '2', [0] = '1' };
+
+const char ax_3[] = { '1', '2', '3' };
+const char a3_3[3] = { '1', '2', '3' };
+
+const char ax_100_3[] = { '1', '2', '3', [100] = '\0' };
+
+#define CONCAT(x, y) x ## y
+#define CAT(x, y) CONCAT (x, y)
+#define FAILNAME(name) CAT (call_ ## name ##_on_line_, __LINE__)
+
+#define FAIL(name) do {				\
+    extern void FAILNAME (name) (void);		\
+    FAILNAME (name)();				\
+  } while (0)
+
+/* Macro to emit a call to funcation named
+   call_in_true_branch_not_eliminated_on_line_NNN()
+   for each call that's expected to be eliminated.  The dg-final
+   scan-tree-dump-time directive at the bottom of the test verifies
+   that no such call appears in output.  */
+#define ELIM(expr)							\
+  if (!(expr)) FAIL (in_true_branch_not_eliminated); else (void)0
+
+#define T(s, n) ELIM (strlen (s) == n)
+
+void test_nulstring (void)
+{
+  T (a2_implicit, 0);
+  T (a3_implicit, 0);
+
+  T (a3_nul, 0);
+  T (a5_nul1, 0);
+  T (a7_nul2, 0);
+
+  T (ax_2_nul, 2);
+  T (ax_3_nul, 3);
+  T (ax_3_des_nul, 3);
+
+  T (ax_100_3, 3);
+  T (ax_100_3 + 4, 0);
+  ELIM (101 == sizeof ax_100_3);
+  ELIM ('\0' == ax_100_3[100]);
+
+  /* Verify that all three character arrays have the same length
+     as the string literal they are initialized with.  */
+  T (S, 255);
+  T (c256, 255);
+  T ((const char*)sc256, 255);
+  T ((const char*)uc256, 255);
+
+  /* Verify that all three character arrays have the same contents
+     as the string literal they are initialized with.  */
+  ELIM (0 == memcmp (c256, S, sizeof c256));
+  ELIM (0 == memcmp (c256, (const char*)sc256, sizeof c256));
+  ELIM (0 == memcmp (c256, (const char*)uc256, sizeof c256));
+
+  ELIM (0 == strcmp (c256, (const char*)sc256));
+  ELIM (0 == strcmp (c256, (const char*)uc256));
+
+  /* Verify that the char16_t array has the expected contents.  */
+  ELIM (c16_4[0] == 1 && c16_4[1] == 0x7fff
+	&& c16_4[2] == 0x8000 && c16_4[3] == 0xffff
+	&& c16_4[4] == 0);
+}
+
+/* Verify that excessively large initializers don't run out of
+   memory.  Also verify that the they have the expected size and
+   contents.  */
+
+#define MAX (__PTRDIFF_MAX__ - 1)
+
+const char large_string[] = { 'a', [1234] = 'b', [MAX] = '\0' };
+
+const void test_large_string_size (void)
+{
+  ELIM (sizeof large_string == MAX + 1);
+
+  /* The following expressions are not folded without optimization.  */
+  ELIM ('a'  == large_string[0]);
+  ELIM ('\0' == large_string[1233]);
+  ELIM ('b'  == large_string[1234]);
+  ELIM ('\0' == large_string[1235]);
+  ELIM ('\0' == large_string[MAX - 1]);
+}
+
+
+/* { dg-final { scan-tree-dump-times "strlen" 0 "gimple" } }
+   { dg-final { scan-tree-dump-times "memcmp" 0 "gimple" } }
+   { dg-final { scan-tree-dump-times "strcmp" 0 "gimple" } }
+   { dg-final { scan-tree-dump-times "call_in_true_branch_not_eliminated" 0 "optimized" } } */
Index: gcc/testsuite/gcc.dg/strlenopt-56.c
===================================================================
--- gcc/testsuite/gcc.dg/strlenopt-56.c	(nonexistent)
+++ gcc/testsuite/gcc.dg/strlenopt-56.c	(working copy)
@@ -0,0 +1,50 @@
+/* PR tree-optimization/71625 - conversion of braced initializers to strings
+   Verify that array elements have the expected values regardless of sign
+   and non-ASCII execution character set.
+   { dg-do compile }
+   { dg-require-iconv "IBM1047" }
+   { dg-options "-O -Wall -fexec-charset=IBM1047 -fdump-tree-gimple -fdump-tree-optimized" } */
+
+#include "strlenopt.h"
+
+const char a[] = { 'a', 129, 0 };
+const signed char b[] = { 'b', 130, 0 };
+const unsigned char c[] = { 'c', 131, 0 };
+
+const char s[] = "a\201";
+const signed char ss[] = "b\202";
+const unsigned char us[] = "c\203";
+
+
+#define A(expr)   ((expr) ? (void)0 : __builtin_abort ())
+
+void test_values (void)
+{
+  A (a[0] == a[1]);
+  A (a[1] == 'a');
+
+  A (b[0] == b[1]);
+  A (b[1] == (signed char)'b');
+
+  A (c[0] == c[1]);
+  A (c[1] == (unsigned char)'c');
+}
+
+void test_lengths (void)
+{
+  A (2 == strlen (a));
+  A (2 == strlen ((const char*)b));
+  A (2 == strlen ((const char*)c));
+}
+
+void test_contents (void)
+{
+  A (0 == strcmp (a, s));
+  A (0 == strcmp ((const char*)b, (const char*)ss));
+  A (0 == strcmp ((const char*)c, (const char*)us));
+}
+
+
+/* { dg-final { scan-tree-dump-times "strlen" 0 "gimple" } }
+   { dg-final { scan-tree-dump-times "strcmp" 0 "gimple" } }
+   { dg-final { scan-tree-dump-times "abort" 0 "optimized" } } */
Martin Sebor Aug. 7, 2018, 11:05 p.m. UTC | #9
On 08/07/2018 05:31 AM, Joseph Myers wrote:
> On Tue, 7 Aug 2018, Martin Sebor wrote:
>
>> 2) skipping embedded nuls made it possible to create a string
>> with fewer elements than the initializer array, which caused
>> arrays with unspecified bound to be smaller than they would
>> have been otherwise
>
> I think there should be explicit tests of sizeof for arrays with
> unspecified bound - to make sure both that it isn't any smaller than it
> should be, but also that any NULs implicitly added for a STRING_CST don't
> make the arrays any larger than their size should be for the originally
> given initializer that doesn't have a 0 as the last element.

I added some more tests to the latest revision of the patch.
Please see it in my other response.

Thanks
Martin
Jason Merrill Aug. 8, 2018, 11:08 a.m. UTC | #10
On Wed, Aug 8, 2018 at 9:04 AM, Martin Sebor <msebor@gmail.com> wrote:
> On 08/07/2018 02:57 AM, Jason Merrill wrote:
>>
>> On Wed, Aug 1, 2018 at 12:49 AM, Martin Sebor <msebor@gmail.com> wrote:
>>>
>>> On 07/31/2018 07:38 AM, Jason Merrill wrote:
>>>>
>>>>
>>>> On Tue, Jul 31, 2018 at 9:51 AM, Martin Sebor <msebor@gmail.com> wrote:
>>>>>
>>>>>
>>>>> The middle-end contains code to determine the lengths of constant
>>>>> character arrays initialized by string literals.  The code is used
>>>>> in a number of optimizations and warnings.
>>>>>
>>>>> However, the code is unable to deal with constant arrays initialized
>>>>> using the braced initializer syntax, as in
>>>>>
>>>>>   const char a[] = { '1', '2', '\0' };
>>>>>
>>>>> The attached patch extends the C and C++ front-ends to convert such
>>>>> initializers into a STRING_CST form.
>>>>>
>>>>> The goal of this work is to both enable existing optimizations for
>>>>> such arrays, and to help detect bugs due to using non-nul terminated
>>>>> arrays where nul-terminated strings are expected.  The latter is
>>>>> an extension of the GCC 8 _Wstringop-overflow and
>>>>> -Wstringop-truncation warnings that help detect or prevent reading
>>>>> past the end of dynamically created character arrays.  Future work
>>>>> includes detecting potential past-the-end reads from uninitialized
>>>>> local character arrays.
>>>>
>>>>
>>>>
>>>>>   && TYPE_MAIN_VARIANT (TREE_TYPE (valtype)) == char_type_node)
>>>>
>>>>
>>>>
>>>> Why? Don't we want this for other character types as well?
>>>
>>>
>>> It suppresses narrowing warnings for things like
>>>
>>>   signed char a[] = { 0xff };
>>>
>>> (there are a couple of tests that exercise this).
>>
>>
>> Why is plain char different in this respect?  Presumably one of
>>
>> char a[] = { -1 };
>> char b[] = { 0xff };
>>
>> should give the same narrowing warning, depending on whether char is
>> signed.
>
>
> Right.  I've added more tests to verify that it does.
>
>>> At the same time, STRING_CST is supposed to be able to represent
>>> strings of any integer type so there should be a way to make it
>>> work.  On the flip side, recent discussions of changes in this
>>> area suggest there may be bugs in the wide character handling of
>>> STRING_CST so those would need to be fixed before relying on it
>>> for robust support.
>>>
>>> In any case, if you have a suggestion for how to make it work for
>>> at least the narrow character types I'll adjust the patch.
>>
>>
>> I suppose braced_list_to_string should call check_narrowing for C++.
>
>
> I see.  I've made that change.  That has made it possible to
> convert arrays of all character types.  Thanks!
>
>> Currently it uses tree_fits_shwi_p (signed host_wide_int) and then
>> stores the extracted value in a host unsigned int, which is then
>> converted to host char.  Does the right thing happen for -fsigned-char
>> or targets with a different character set?
>
> I believe so.  I've added tests for these too (ASCII and EBCDIC)
> and also changed the type of the extracted value to HWI to match
> (it doesn't change the results of the tests).
>
> Attached is an updated patch with these changes plus more tests
> as suggested by Joseph.

Great.  Can we also move the call to braced_list_to_string into
check_initializer, so it works for templates as well?  As a case just
before the block that calls reshape_init seems appropriate.

Jason
Martin Sebor Aug. 9, 2018, 12:17 a.m. UTC | #11
On 08/08/2018 05:08 AM, Jason Merrill wrote:
> On Wed, Aug 8, 2018 at 9:04 AM, Martin Sebor <msebor@gmail.com> wrote:
>> On 08/07/2018 02:57 AM, Jason Merrill wrote:
>>>
>>> On Wed, Aug 1, 2018 at 12:49 AM, Martin Sebor <msebor@gmail.com> wrote:
>>>>
>>>> On 07/31/2018 07:38 AM, Jason Merrill wrote:
>>>>>
>>>>>
>>>>> On Tue, Jul 31, 2018 at 9:51 AM, Martin Sebor <msebor@gmail.com> wrote:
>>>>>>
>>>>>>
>>>>>> The middle-end contains code to determine the lengths of constant
>>>>>> character arrays initialized by string literals.  The code is used
>>>>>> in a number of optimizations and warnings.
>>>>>>
>>>>>> However, the code is unable to deal with constant arrays initialized
>>>>>> using the braced initializer syntax, as in
>>>>>>
>>>>>>   const char a[] = { '1', '2', '\0' };
>>>>>>
>>>>>> The attached patch extends the C and C++ front-ends to convert such
>>>>>> initializers into a STRING_CST form.
>>>>>>
>>>>>> The goal of this work is to both enable existing optimizations for
>>>>>> such arrays, and to help detect bugs due to using non-nul terminated
>>>>>> arrays where nul-terminated strings are expected.  The latter is
>>>>>> an extension of the GCC 8 _Wstringop-overflow and
>>>>>> -Wstringop-truncation warnings that help detect or prevent reading
>>>>>> past the end of dynamically created character arrays.  Future work
>>>>>> includes detecting potential past-the-end reads from uninitialized
>>>>>> local character arrays.
>>>>>
>>>>>
>>>>>
>>>>>>   && TYPE_MAIN_VARIANT (TREE_TYPE (valtype)) == char_type_node)
>>>>>
>>>>>
>>>>>
>>>>> Why? Don't we want this for other character types as well?
>>>>
>>>>
>>>> It suppresses narrowing warnings for things like
>>>>
>>>>   signed char a[] = { 0xff };
>>>>
>>>> (there are a couple of tests that exercise this).
>>>
>>>
>>> Why is plain char different in this respect?  Presumably one of
>>>
>>> char a[] = { -1 };
>>> char b[] = { 0xff };
>>>
>>> should give the same narrowing warning, depending on whether char is
>>> signed.
>>
>>
>> Right.  I've added more tests to verify that it does.
>>
>>>> At the same time, STRING_CST is supposed to be able to represent
>>>> strings of any integer type so there should be a way to make it
>>>> work.  On the flip side, recent discussions of changes in this
>>>> area suggest there may be bugs in the wide character handling of
>>>> STRING_CST so those would need to be fixed before relying on it
>>>> for robust support.
>>>>
>>>> In any case, if you have a suggestion for how to make it work for
>>>> at least the narrow character types I'll adjust the patch.
>>>
>>>
>>> I suppose braced_list_to_string should call check_narrowing for C++.
>>
>>
>> I see.  I've made that change.  That has made it possible to
>> convert arrays of all character types.  Thanks!
>>
>>> Currently it uses tree_fits_shwi_p (signed host_wide_int) and then
>>> stores the extracted value in a host unsigned int, which is then
>>> converted to host char.  Does the right thing happen for -fsigned-char
>>> or targets with a different character set?
>>
>> I believe so.  I've added tests for these too (ASCII and EBCDIC)
>> and also changed the type of the extracted value to HWI to match
>> (it doesn't change the results of the tests).
>>
>> Attached is an updated patch with these changes plus more tests
>> as suggested by Joseph.
>
> Great.  Can we also move the call to braced_list_to_string into
> check_initializer, so it works for templates as well?  As a case just
> before the block that calls reshape_init seems appropriate.

Done in the attached patch.  I've also avoided dealing with
zero-length arrays and added tests to make sure their size
stays is regardless of the form of their initializer and
the appropriate warnings are issued.

Using build_string() rather than build_string_literal() needed
a tweak in digest_init_r().  It didn't break anything but since
the array type may not have a domain yet, neither will the
string.  It looks like that may get adjusted later on but I've
temporarily guarded the code with #if 1.  If the change is
fine I'll remove the #if before committing.

This initial patch only handles narrow character initializers
(i.e., those with TYPE_STRING_FLAG set).  Once this gets some
exposure I'd like to extend it to other character types,
including wchar_t.

Martin
PR tree-optimization/71625 - missing strlen optimization on different array initialization style

gcc/c/ChangeLog:

	PR tree-optimization/71625
	* c-parser.c (c_parser_declaration_or_fndef): Call
	braced_list_to_string.

gcc/c-family/ChangeLog:

	PR tree-optimization/71625
	* c-common.c (braced_list_to_string): New function.
	* c-common.h (braced_list_to_string): Declare it.

gcc/cp/ChangeLog:

	PR tree-optimization/71625
	* decl.c (check_initializer):  Call braced_list_to_string.
	(eval_check_narrowing): New function.
	* gcc/cp/typeck2.c (digest_init_r): Accept strings literals
	as initilizers for all narrow character types.

gcc/testsuite/ChangeLog:

	PR tree-optimization/71625
	* g++.dg/init/string2.C: New test.
	* g++.dg/init/string3.C: New test.
	* g++.dg/init/string4.C: New test.
	* gcc.dg/init-string-3.c: New test.
	* gcc.dg/strlenopt-55.c: New test.
	* gcc.dg/strlenopt-56.c: New test.
diff --git a/gcc/c-family/c-common.c b/gcc/c-family/c-common.c
index d919605..b10d9c9 100644
--- a/gcc/c-family/c-common.c
+++ b/gcc/c-family/c-common.c
@@ -8509,4 +8509,102 @@ maybe_add_include_fixit (rich_location *richloc, const char *header)
   free (text);
 }
 
+/* Attempt to convert a braced array initializer list CTOR for array
+   TYPE into a STRING_CST for convenience and efficiency.  When non-null,
+   use EVAL to attempt to evalue constants (used by C++).  Return
+   the converted string on success or null on failure.  */
+
+tree
+braced_list_to_string (tree type, tree ctor, tree (*eval)(tree, tree))
+{
+  unsigned HOST_WIDE_INT nelts = CONSTRUCTOR_NELTS (ctor);
+
+  /* If the array has an explicit bound, use it to constrain the size
+     of the string.  If it doesn't, be sure to create a string that's
+     as long as implied by the index of the last zero specified via
+     a designator, as in:
+       const char a[] = { [7] = 0 };  */
+  unsigned HOST_WIDE_INT maxelts = HOST_WIDE_INT_M1U;
+  if (tree size = TYPE_SIZE_UNIT (type))
+    {
+      if (tree_fits_uhwi_p (size))
+	{
+	  maxelts = tree_to_uhwi (size);
+	  maxelts /= tree_to_uhwi (TYPE_SIZE_UNIT (TREE_TYPE (type)));
+
+	  /* Avoid converting initializers for zero-length arrays.  */
+	  if (!maxelts)
+	    return NULL_TREE;
+	}
+    }
+  else if (!nelts)
+    /* Avoid handling the undefined/erroneous case of an empty
+       initializer for an arrays with unspecified bound.  */
+    return NULL_TREE;
+
+  tree eltype = TREE_TYPE (type);
+
+  auto_vec<char> str;
+  str.reserve (nelts + 1);
+
+  unsigned HOST_WIDE_INT i;
+  tree index, value;
+
+  FOR_EACH_CONSTRUCTOR_ELT (CONSTRUCTOR_ELTS (ctor), i, index, value)
+    {
+      unsigned HOST_WIDE_INT idx = index ? tree_to_uhwi (index) : i;
+
+      /* auto_vec is limited to UINT_MAX elements.  */
+      if (idx > UINT_MAX)
+	return NULL_TREE;
+
+      /* Attempt to evaluate constants.  */
+      if (eval)
+	value = eval (eltype, value);
+
+      /* Avoid non-constant initializers.  */
+     if (!tree_fits_shwi_p (value))
+	return NULL_TREE;
+
+      /* Skip over embedded nuls except the last one (initializer
+	 elements are in ascending order of indices).  */
+      HOST_WIDE_INT val = tree_to_shwi (value);
+      if (!val && i + 1 < nelts)
+	continue;
+
+      /* Bail if the CTOR has a block of more than 256 embedded nuls
+	 due to implicitly initialized elements.  */
+      unsigned nchars = (idx - str.length ()) + 1;
+      if (nchars > 256)
+	return NULL_TREE;
+
+      if (nchars > 1)
+	{
+	  str.reserve (idx);
+	  str.quick_grow_cleared (idx);
+	}
+
+      if (idx > maxelts)
+	return NULL_TREE;
+
+      str.safe_insert (idx, val);
+    }
+
+  if (!nelts)
+    /* Append a nul for the empty initializer { }.  */
+    str.safe_push (0);
+
+#if 1
+  /* Build a STRING_CST with the same type as the array, which
+     may be an array of unknown bound.  */
+  tree res = build_string (str.length (), str.begin ());
+  TREE_TYPE (res) = type;
+#else
+  /* Build a string literal but return the embedded STRING_CST.  */
+  tree res = build_string_literal (str.length (), str.begin (), eltype);
+  res = TREE_OPERAND (TREE_OPERAND (res, 0), 0);
+#endif
+  return res;
+}
+
 #include "gt-c-family-c-common.h"
diff --git a/gcc/c-family/c-common.h b/gcc/c-family/c-common.h
index fcec95b..8a802bb 100644
--- a/gcc/c-family/c-common.h
+++ b/gcc/c-family/c-common.h
@@ -1331,6 +1331,7 @@ extern void maybe_add_include_fixit (rich_location *, const char *);
 extern void maybe_suggest_missing_token_insertion (rich_location *richloc,
 						   enum cpp_ttype token_type,
 						   location_t prev_token_loc);
+extern tree braced_list_to_string (tree, tree, tree (*)(tree, tree) = NULL);
 
 #if CHECKING_P
 namespace selftest {
diff --git a/gcc/c/c-parser.c b/gcc/c/c-parser.c
index 7a92628..5ad4f57 100644
--- a/gcc/c/c-parser.c
+++ b/gcc/c/c-parser.c
@@ -2126,6 +2126,15 @@ c_parser_declaration_or_fndef (c_parser *parser, bool fndef_ok,
 	      if (d != error_mark_node)
 		{
 		  maybe_warn_string_init (init_loc, TREE_TYPE (d), init);
+
+		  /* Try to convert a string CONSTRUCTOR into a STRING_CST.  */
+		  tree valtype = TREE_TYPE (init.value);
+		  if (TREE_CODE (init.value) == CONSTRUCTOR
+		      && TREE_CODE (valtype) == ARRAY_TYPE
+		      && TYPE_STRING_FLAG (TREE_TYPE (valtype)))
+		    if (tree str = braced_list_to_string (valtype, init.value))
+		      init.value = str;
+
 		  finish_decl (d, init_loc, init.value,
 			       init.original_type, asm_name);
 		}
diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c
index 78ebbde..d2c5b5d 100644
--- a/gcc/cp/decl.c
+++ b/gcc/cp/decl.c
@@ -6282,6 +6282,30 @@ build_aggr_init_full_exprs (tree decl, tree init, int flags)
   return build_aggr_init (decl, init, flags, tf_warning_or_error);
 }
 
+/* Attempt to determine the constant VALUE of integral type and convert
+   it to TYPE, issuing narrowing warnings/errors as necessary.  Return
+   the constant result or null on failure.  Callback for
+   braced_list_to_string.  */
+
+static tree
+eval_check_narrowing (tree type, tree value)
+{
+  if (tree valtype = TREE_TYPE (value))
+    {
+      if (TREE_CODE (valtype) != INTEGER_TYPE)
+	return NULL_TREE;
+    }
+  else
+    return NULL_TREE;
+
+  value = scalar_constant_value (value);
+  if (!value)
+    return NULL_TREE;
+
+  check_narrowing (type, value, tf_warning_or_error);
+  return value;
+}
+
 /* Verify INIT (the initializer for DECL), and record the
    initialization in DECL_INITIAL, if appropriate.  CLEANUP is as for
    grok_reference_init.
@@ -6397,7 +6421,18 @@ check_initializer (tree decl, tree init, int flags, vec<tree, va_gc> **cleanups)
 	    }
 	  else
 	    {
-	      init = reshape_init (type, init, tf_warning_or_error);
+	      /* Try to convert a string CONSTRUCTOR into a STRING_CST.  */
+	      tree valtype = TREE_TYPE (decl);
+	      if (TREE_CODE (valtype) == ARRAY_TYPE
+		  && TYPE_STRING_FLAG (TREE_TYPE (valtype))
+		  && TREE_CODE (init) == CONSTRUCTOR
+		  && TREE_TYPE (init) == init_list_type_node)
+		if (tree str = braced_list_to_string (valtype, init,
+						      eval_check_narrowing))
+		  init = str;
+
+	      if (TREE_CODE (init) != STRING_CST)
+		init = reshape_init (type, init, tf_warning_or_error);
 	      flags |= LOOKUP_NO_NARROWING;
 	    }
 	}
diff --git a/gcc/cp/typeck2.c b/gcc/cp/typeck2.c
index 7763d53..72515d9 100644
--- a/gcc/cp/typeck2.c
+++ b/gcc/cp/typeck2.c
@@ -1056,7 +1056,9 @@ digest_init_r (tree type, tree init, int nested, int flags,
 
 	  if (TYPE_PRECISION (typ1) == BITS_PER_UNIT)
 	    {
-	      if (char_type != char_type_node)
+	      if (char_type != char_type_node
+		  && char_type != signed_char_type_node
+		  && char_type != unsigned_char_type_node)
 		{
 		  if (complain & tf_error)
 		    error_at (loc, "char-array initialized from wide string");
diff --git a/gcc/testsuite/g++.dg/init/string2.C b/gcc/testsuite/g++.dg/init/string2.C
new file mode 100644
index 0000000..5da13bd
--- /dev/null
+++ b/gcc/testsuite/g++.dg/init/string2.C
@@ -0,0 +1,104 @@
+// PR tree-optimization/71625 - missing strlen optimization on different
+// array initialization style
+//
+// Verify that strlen() calls with constant character array arguments
+// initialized with string constants are folded.  (This is a small
+// subset of pr71625).
+// { dg-do compile }
+// { dg-options "-O0 -Wno-error=narrowing -fdump-tree-gimple" }
+
+#define A(expr) do { typedef char A[-1 + 2 * !!(expr)]; } while (0)
+
+/* This is undefined but accepted without -Wpedantic.  Verify that
+   the size is zero.  */
+const char ax[] = { };
+
+void size0 ()
+{
+  A (sizeof ax == 0);
+}
+
+const char a0[] = { 'a', 'b', 'c', '\0' };
+
+int len0 ()
+{
+  return __builtin_strlen (a0);
+}
+
+// Verify that narrowing warnings are preserved.
+const signed char
+sa0[] = { 'a', 'b', 255, '\0' };    // { dg-warning "\\\[\(-Wnarrowing|-Woverflow\)" "" { target { ! c++98_only } } }
+
+int lens0 ()
+{
+  return __builtin_strlen ((const char*)sa0);
+}
+
+const unsigned char
+ua0[] = { 'a', 'b', -1, '\0' };     // { dg-warning "\\\[\(-Wnarrowing|-Woverflow\)" "" { target { ! c++98_only } } }
+
+int lenu0 ()
+{
+  return __builtin_strlen ((const char*)ua0);
+}
+
+const char c = 0;
+const char a1[] = { 'a', 'b', 'c', c };
+
+int len1 ()
+{
+  return __builtin_strlen (a1);
+}
+
+template <class T>
+int tmplen ()
+{
+  static const T
+    a[] = { 1, 2, 333, 0 };         // { dg-warning "\\\[\(-Wnarrowing|-Woverflow\)" "" { target { ! c++98_only } } }
+  return __builtin_strlen (a);
+}
+
+template int tmplen<char>();
+
+const wchar_t ws4[] = { 1, 2, 3, 4 };
+const wchar_t ws7[] = { 1, 2, 3, 4, 0, 0, 0 };
+const wchar_t ws9[9] = { 1, 2, 3, 4, 0 };
+
+void wsize ()
+{
+  A (sizeof ws4 == 4 * sizeof *ws4);
+  A (ws4[0] == 1 && ws4[1] == 2 && ws4[2] == 3 && ws4[3] == 4);
+
+  A (sizeof ws7 == 7 * sizeof *ws7);
+  A (ws7[0] == 1 && ws7[1] == 2 && ws7[2] == 3 && ws7[4] == 4
+     && !ws7[5] && !ws7[6]);
+
+  A (sizeof ws9 == 9 * sizeof *ws9);
+  A (ws9[0] == 1 && ws9[1] == 2 && ws9[2] == 3 && ws9[4] == 4
+     && !ws9[5] && !ws9[6] && !ws9[7] && !ws9[8]);
+}
+
+#if 0
+
+// The following aren't handled.
+
+const char &cref = c;
+const char a2[] = { 'a', 'b', 'c', cref };
+
+int len2 ()
+{
+  return __builtin_strlen (a2);
+}
+
+
+const char* const cptr = &cref;
+const char a3[] = { 'a', 'b', 'c', *cptr };
+
+int len3 ()
+{
+  return __builtin_strlen (a3);
+}
+
+#endif
+
+// { dg-final { scan-tree-dump-times "strlen" 0 "gimple" } }
diff --git a/gcc/testsuite/g++.dg/init/string3.C b/gcc/testsuite/g++.dg/init/string3.C
new file mode 100644
index 0000000..8212e81
--- /dev/null
+++ b/gcc/testsuite/g++.dg/init/string3.C
@@ -0,0 +1,35 @@
+// PR tree-optimization/71625 - missing strlen optimization on different
+// array initialization style
+//
+// Verify that strlen() call with a constant character array argument
+// initialized with non-constant elements isn't folded.
+//
+// { dg-do compile }
+// { dg-options "-O2 -fdump-tree-optimized" }
+
+
+extern const char c;
+const char a0[] = { 'a', 'b', 'c', c };
+
+int len0 ()
+{
+  return __builtin_strlen (a0);
+}
+
+const char &ref = c;
+const char a1[] = { 'a', 'b', 'c', ref };
+
+int len1 ()
+{
+  return __builtin_strlen (a1);
+}
+
+const char* const ptr = &c;
+const char a2[] = { 'a', 'b', 'c', *ptr };
+
+int len2 ()
+{
+  return __builtin_strlen (a2);
+}
+
+// { dg-final { scan-tree-dump-times "strlen" 3 "optimized" } }
diff --git a/gcc/testsuite/g++.dg/init/string4.C b/gcc/testsuite/g++.dg/init/string4.C
new file mode 100644
index 0000000..5df4176
--- /dev/null
+++ b/gcc/testsuite/g++.dg/init/string4.C
@@ -0,0 +1,60 @@
+// PR tree-optimization/71625 - missing strlen optimization on different
+// array initialization style
+
+// Verify that zero-length array initialization results in the expected
+// array sizes and in the expected diagnostics.  See init-string-3.c
+// for the corresponding C test.
+
+// { dg-do compile }
+// { dg-options "-Wall -Wno-unused-local-typedefs -fpermissive" }
+
+#define A(expr) typedef char A[-1 + 2 * !!(expr)];
+
+const char a[] = { };
+
+A (sizeof a == 0);
+
+
+const char b[0] = { };
+
+A (sizeof b == 0);
+
+// Also verify that the error is "too many initializers for
+// 'const char [0]'" and not "initializer-string is too long."
+const char c[0] = { 1 };      // { dg-error "too many initializers for .const char \\\[0]" }
+
+A (sizeof c == 0);
+
+
+void test_auto_empty (void)
+{
+  const char a[] = { };
+
+  A (sizeof a == 0);
+}
+
+void test_auto_zero_length (void)
+{
+  const char a[0] = { };
+
+  A (sizeof a == 0);
+
+  const char b[0] = { 0 };    // { dg-error "too many initializers" }
+
+  A (sizeof b == 0);
+
+  const char c[0] = "";       // { dg-warning "too long" }
+
+  A (sizeof c == 0);
+}
+
+
+void test_compound_zero_length (void)
+{
+  A (sizeof (const char[]){ } == 0);
+  A (sizeof (const char[0]){ } == 0);
+  A (sizeof (const char[0]){ 0 } == 0);    // { dg-error "too many" }
+  A (sizeof (const char[0]){ 1 } == 0);    // { dg-error "too many" }
+  A (sizeof (const char[0]){ "" } == 0);   // { dg-warning "too long" }
+  A (sizeof (const char[0]){ "1" } == 0);  // { dg-warning "too long" }
+}
diff --git a/gcc/testsuite/gcc.dg/init-string-3.c b/gcc/testsuite/gcc.dg/init-string-3.c
new file mode 100644
index 0000000..e955f2e
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/init-string-3.c
@@ -0,0 +1,58 @@
+/* PR tree-optimization/71625 - missing strlen optimization on different
+   array initialization style
+
+   Verify that zero-length array initialization results in the expected
+   array sizes.
+
+   { dg-do compile }
+   { dg-options "-Wall -Wno-unused-local-typedefs" }  */
+
+#define A(expr) typedef char A[-1 + 2 * !!(expr)];
+
+const char a[] = { };
+
+A (sizeof a == 0);
+
+
+const char b[0] = { };
+
+A (sizeof b == 0);
+
+
+const char c[0] = { 1 };    /* { dg-warning "excess elements" } */
+
+A (sizeof c == 0);
+
+
+void test_auto_empty (void)
+{
+  const char a[] = { };
+
+  A (sizeof a == 0);
+}
+
+void test_auto_zero_length (void)
+{
+  const char a[0] = { };
+
+  A (sizeof a == 0);
+
+  const char b[0] = { 0 };    /* { dg-warning "excess elements" } */
+
+  A (sizeof b == 0);
+
+  const char c[0] = "";
+
+  A (sizeof c == 0);
+}
+
+
+void test_compound_zero_length (void)
+{
+  A (sizeof (const char[]){ } == 0);
+  A (sizeof (const char[0]){ } == 0);
+  A (sizeof (const char[0]){ 0 } == 0);   /* { dg-warning "excess elements" } */
+  A (sizeof (const char[0]){ 1 } == 0);   /* { dg-warning "excess elements" } */
+  A (sizeof (const char[0]){ "" } == 0);
+  A (sizeof (const char[0]){ "1" } == 0);  /* { dg-warning "too long" } */
+}
diff --git a/gcc/testsuite/gcc.dg/strlenopt-55.c b/gcc/testsuite/gcc.dg/strlenopt-55.c
new file mode 100644
index 0000000..d5a0295
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/strlenopt-55.c
@@ -0,0 +1,230 @@
+/* PR tree-optimization/71625 - missing strlen optimization on different
+   array initialization style
+
+   Verify that strlen() of braced initialized array is folded
+   { dg-do compile }
+   { dg-options "-O1 -Wall -fdump-tree-gimple -fdump-tree-optimized" } */
+
+#include "strlenopt.h"
+
+#define S								\
+  "\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f"	\
+  "\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f"	\
+  "\x20\x21\x22\x23\x24\x25\x26\x27\x28\x29\x2a\x2b\x2c\x2d\x2e\x2f"	\
+  "\x30\x31\x32\x33\x34\x35\x36\x37\x38\x39\x3a\x3b\x3c\x3d\x3e\x3f"	\
+  "\x40\x41\x42\x43\x44\x45\x46\x47\x48\x49\x4a\x4b\x4c\x4d\x4e\x4f"	\
+  "\x50\x51\x52\x53\x54\x55\x56\x57\x58\x59\x5a\x5b\x5c\x5d\x5e\x5f"	\
+  "\x60\x61\x62\x63\x64\x65\x66\x67\x68\x69\x6a\x6b\x6c\x6d\x6e\x6f"	\
+  "\x70\x71\x72\x73\x74\x75\x76\x77\x78\x79\x7a\x7b\x7c\x7d\x7e\x7f"	\
+  "\x80\x81\x82\x83\x84\x85\x86\x87\x88\x89\x8a\x8b\x8c\x8d\x8e\x8f"	\
+  "\x90\x91\x92\x93\x94\x95\x96\x97\x98\x99\x9a\x9b\x9c\x9d\x9e\x9f"	\
+  "\xa0\xa1\xa2\xa3\xa4\xa5\xa6\xa7\xa8\xa9\xaa\xab\xac\xad\xae\xaf"	\
+  "\xb0\xb1\xb2\xb3\xb4\xb5\xb6\xb7\xb8\xb9\xba\xbb\xbc\xbd\xbe\xbf"	\
+  "\xc0\xc1\xc2\xc3\xc4\xc5\xc6\xc7\xc8\xc9\xca\xcb\xcc\xcd\xce\xcf"	\
+  "\xd0\xd1\xd2\xd3\xd4\xd5\xd6\xd7\xd8\xd9\xda\xdb\xdc\xdd\xde\xdf"	\
+  "\xe0\xe1\xe2\xe3\xe4\xe5\xe6\xe7\xe8\xe9\xea\xeb\xec\xed\xee\xef"	\
+  "\xf0\xf1\xf2\xf3\xf4\xf5\xf6\xf7\xf8\xf9\xfa\xfb\xfc\xfd\xfe\xff"
+
+/* Arrays of char, signed char, and unsigned char to verify that
+   the length and contents of all are the same as that of the string
+   literal above.  */
+
+const char c256[] = {
+  S[0], S[1], S[2], S[3], S[4], S[5], S[6], S[7], S[8], S[9], S[10],
+  S[11], S[12], S[13], S[14], S[15], S[16], S[17], S[18], S[19], S[20],
+  S[21], S[22], S[23], S[24], S[25], S[26], S[27], S[28], S[29], S[30],
+  S[31], S[32], S[33], S[34], S[35], S[36], S[37], S[38], S[39], S[40],
+  S[41], S[42], S[43], S[44], S[45], S[46], S[47], S[48], S[49], S[50],
+  S[51], S[52], S[53], S[54], S[55], S[56], S[57], S[58], S[59], S[60],
+  S[61], S[62], S[63], S[64], S[65], S[66], S[67], S[68], S[69], S[70],
+  S[71], S[72], S[73], S[74], S[75], S[76], S[77], S[78], S[79], S[80],
+  S[81], S[82], S[83], S[84], S[85], S[86], S[87], S[88], S[89], S[90],
+  S[91], S[92], S[93], S[94], S[95], S[96], S[97], S[98], S[99], S[100],
+  S[101], S[102], S[103], S[104], S[105], S[106], S[107], S[108], S[109],
+  S[110], S[111], S[112], S[113], S[114], S[115], S[116], S[117], S[118],
+  S[119], S[120], S[121], S[122], S[123], S[124], S[125], S[126], S[127],
+  S[128], S[129], S[130], S[131], S[132], S[133], S[134], S[135], S[136],
+  S[137], S[138], S[139], S[140], S[141], S[142], S[143], S[144], S[145],
+  S[146], S[147], S[148], S[149], S[150], S[151], S[152], S[153], S[154],
+  S[155], S[156], S[157], S[158], S[159], S[160], S[161], S[162], S[163],
+  S[164], S[165], S[166], S[167], S[168], S[169], S[170], S[171], S[172],
+  S[173], S[174], S[175], S[176], S[177], S[178], S[179], S[180], S[181],
+  S[182], S[183], S[184], S[185], S[186], S[187], S[188], S[189], S[190],
+  S[191], S[192], S[193], S[194], S[195], S[196], S[197], S[198], S[199],
+  S[200], S[201], S[202], S[203], S[204], S[205], S[206], S[207], S[208],
+  S[209], S[210], S[211], S[212], S[213], S[214], S[215], S[216], S[217],
+  S[218], S[219], S[220], S[221], S[222], S[223], S[224], S[225], S[226],
+  S[227], S[228], S[229], S[230], S[231], S[232], S[233], S[234], S[235],
+  S[236], S[237], S[238], S[239], S[240], S[241], S[242], S[243], S[244],
+  S[245], S[246], S[247], S[248], S[249], S[250], S[251], S[252], S[253],
+  S[254], S[255] /* = NUL */
+};
+
+const signed char sc256[] = {
+  S[0], S[1], S[2], S[3], S[4], S[5], S[6], S[7], S[8], S[9], S[10],
+  S[11], S[12], S[13], S[14], S[15], S[16], S[17], S[18], S[19], S[20],
+  S[21], S[22], S[23], S[24], S[25], S[26], S[27], S[28], S[29], S[30],
+  S[31], S[32], S[33], S[34], S[35], S[36], S[37], S[38], S[39], S[40],
+  S[41], S[42], S[43], S[44], S[45], S[46], S[47], S[48], S[49], S[50],
+  S[51], S[52], S[53], S[54], S[55], S[56], S[57], S[58], S[59], S[60],
+  S[61], S[62], S[63], S[64], S[65], S[66], S[67], S[68], S[69], S[70],
+  S[71], S[72], S[73], S[74], S[75], S[76], S[77], S[78], S[79], S[80],
+  S[81], S[82], S[83], S[84], S[85], S[86], S[87], S[88], S[89], S[90],
+  S[91], S[92], S[93], S[94], S[95], S[96], S[97], S[98], S[99], S[100],
+  S[101], S[102], S[103], S[104], S[105], S[106], S[107], S[108], S[109],
+  S[110], S[111], S[112], S[113], S[114], S[115], S[116], S[117], S[118],
+  S[119], S[120], S[121], S[122], S[123], S[124], S[125], S[126], S[127],
+  S[128], S[129], S[130], S[131], S[132], S[133], S[134], S[135], S[136],
+  S[137], S[138], S[139], S[140], S[141], S[142], S[143], S[144], S[145],
+  S[146], S[147], S[148], S[149], S[150], S[151], S[152], S[153], S[154],
+  S[155], S[156], S[157], S[158], S[159], S[160], S[161], S[162], S[163],
+  S[164], S[165], S[166], S[167], S[168], S[169], S[170], S[171], S[172],
+  S[173], S[174], S[175], S[176], S[177], S[178], S[179], S[180], S[181],
+  S[182], S[183], S[184], S[185], S[186], S[187], S[188], S[189], S[190],
+  S[191], S[192], S[193], S[194], S[195], S[196], S[197], S[198], S[199],
+  S[200], S[201], S[202], S[203], S[204], S[205], S[206], S[207], S[208],
+  S[209], S[210], S[211], S[212], S[213], S[214], S[215], S[216], S[217],
+  S[218], S[219], S[220], S[221], S[222], S[223], S[224], S[225], S[226],
+  S[227], S[228], S[229], S[230], S[231], S[232], S[233], S[234], S[235],
+  S[236], S[237], S[238], S[239], S[240], S[241], S[242], S[243], S[244],
+  S[245], S[246], S[247], S[248], S[249], S[250], S[251], S[252], S[253],
+  S[254], S[255] /* = NUL */
+};
+
+const unsigned char uc256[] = {
+  S[0], S[1], S[2], S[3], S[4], S[5], S[6], S[7], S[8], S[9], S[10],
+  S[11], S[12], S[13], S[14], S[15], S[16], S[17], S[18], S[19], S[20],
+  S[21], S[22], S[23], S[24], S[25], S[26], S[27], S[28], S[29], S[30],
+  S[31], S[32], S[33], S[34], S[35], S[36], S[37], S[38], S[39], S[40],
+  S[41], S[42], S[43], S[44], S[45], S[46], S[47], S[48], S[49], S[50],
+  S[51], S[52], S[53], S[54], S[55], S[56], S[57], S[58], S[59], S[60],
+  S[61], S[62], S[63], S[64], S[65], S[66], S[67], S[68], S[69], S[70],
+  S[71], S[72], S[73], S[74], S[75], S[76], S[77], S[78], S[79], S[80],
+  S[81], S[82], S[83], S[84], S[85], S[86], S[87], S[88], S[89], S[90],
+  S[91], S[92], S[93], S[94], S[95], S[96], S[97], S[98], S[99], S[100],
+  S[101], S[102], S[103], S[104], S[105], S[106], S[107], S[108], S[109],
+  S[110], S[111], S[112], S[113], S[114], S[115], S[116], S[117], S[118],
+  S[119], S[120], S[121], S[122], S[123], S[124], S[125], S[126], S[127],
+  S[128], S[129], S[130], S[131], S[132], S[133], S[134], S[135], S[136],
+  S[137], S[138], S[139], S[140], S[141], S[142], S[143], S[144], S[145],
+  S[146], S[147], S[148], S[149], S[150], S[151], S[152], S[153], S[154],
+  S[155], S[156], S[157], S[158], S[159], S[160], S[161], S[162], S[163],
+  S[164], S[165], S[166], S[167], S[168], S[169], S[170], S[171], S[172],
+  S[173], S[174], S[175], S[176], S[177], S[178], S[179], S[180], S[181],
+  S[182], S[183], S[184], S[185], S[186], S[187], S[188], S[189], S[190],
+  S[191], S[192], S[193], S[194], S[195], S[196], S[197], S[198], S[199],
+  S[200], S[201], S[202], S[203], S[204], S[205], S[206], S[207], S[208],
+  S[209], S[210], S[211], S[212], S[213], S[214], S[215], S[216], S[217],
+  S[218], S[219], S[220], S[221], S[222], S[223], S[224], S[225], S[226],
+  S[227], S[228], S[229], S[230], S[231], S[232], S[233], S[234], S[235],
+  S[236], S[237], S[238], S[239], S[240], S[241], S[242], S[243], S[244],
+  S[245], S[246], S[247], S[248], S[249], S[250], S[251], S[252], S[253],
+  S[254], S[255] /* = NUL */
+};
+
+const __CHAR16_TYPE__ c16_4[] = {
+  1, 0x7fff, 0x8000, 0xffff,
+  0x10000   /* { dg-warning "\\\[-Woverflow]" } */
+};
+
+const char a2_implicit[2] = { };
+const char a3_implicit[3] = { };
+
+const char a3_nul[3] = { 0 };
+const char a5_nul1[3] = { [1] = 0 };
+const char a7_nul2[3] = { [2] = 0 };
+
+const char ax_2_nul[] = { '1', '2', '\0' };
+const char ax_3_nul[] = { '1', '2', '3', '\0' };
+
+const char ax_3_des_nul[] = { [3] = 0, [2] = '3', [1] = '2', [0] = '1' };
+
+const char ax_3[] = { '1', '2', '3' };
+const char a3_3[3] = { '1', '2', '3' };
+
+const char ax_100_3[] = { '1', '2', '3', [100] = '\0' };
+
+#define CONCAT(x, y) x ## y
+#define CAT(x, y) CONCAT (x, y)
+#define FAILNAME(name) CAT (call_ ## name ##_on_line_, __LINE__)
+
+#define FAIL(name) do {				\
+    extern void FAILNAME (name) (void);		\
+    FAILNAME (name)();				\
+  } while (0)
+
+/* Macro to emit a call to funcation named
+   call_in_true_branch_not_eliminated_on_line_NNN()
+   for each call that's expected to be eliminated.  The dg-final
+   scan-tree-dump-time directive at the bottom of the test verifies
+   that no such call appears in output.  */
+#define ELIM(expr)							\
+  if (!(expr)) FAIL (in_true_branch_not_eliminated); else (void)0
+
+#define T(s, n) ELIM (strlen (s) == n)
+
+void test_nulstring (void)
+{
+  T (a2_implicit, 0);
+  T (a3_implicit, 0);
+
+  T (a3_nul, 0);
+  T (a5_nul1, 0);
+  T (a7_nul2, 0);
+
+  T (ax_2_nul, 2);
+  T (ax_3_nul, 3);
+  T (ax_3_des_nul, 3);
+
+  T (ax_100_3, 3);
+  T (ax_100_3 + 4, 0);
+  ELIM (101 == sizeof ax_100_3);
+  ELIM ('\0' == ax_100_3[100]);
+
+  /* Verify that all three character arrays have the same length
+     as the string literal they are initialized with.  */
+  T (S, 255);
+  T (c256, 255);
+  T ((const char*)sc256, 255);
+  T ((const char*)uc256, 255);
+
+  /* Verify that all three character arrays have the same contents
+     as the string literal they are initialized with.  */
+  ELIM (0 == memcmp (c256, S, sizeof c256));
+  ELIM (0 == memcmp (c256, (const char*)sc256, sizeof c256));
+  ELIM (0 == memcmp (c256, (const char*)uc256, sizeof c256));
+
+  ELIM (0 == strcmp (c256, (const char*)sc256));
+  ELIM (0 == strcmp (c256, (const char*)uc256));
+
+  /* Verify that the char16_t array has the expected contents.  */
+  ELIM (c16_4[0] == 1 && c16_4[1] == 0x7fff
+	&& c16_4[2] == 0x8000 && c16_4[3] == 0xffff
+	&& c16_4[4] == 0);
+}
+
+/* Verify that excessively large initializers don't run out of
+   memory.  Also verify that the they have the expected size and
+   contents.  */
+
+#define MAX (__PTRDIFF_MAX__ - 1)
+
+const char large_string[] = { 'a', [1234] = 'b', [MAX] = '\0' };
+
+const void test_large_string_size (void)
+{
+  ELIM (sizeof large_string == MAX + 1);
+
+  /* The following expressions are not folded without optimization.  */
+  ELIM ('a'  == large_string[0]);
+  ELIM ('\0' == large_string[1233]);
+  ELIM ('b'  == large_string[1234]);
+  ELIM ('\0' == large_string[1235]);
+  ELIM ('\0' == large_string[MAX - 1]);
+}
+
+
+/* { dg-final { scan-tree-dump-times "strlen" 0 "gimple" } }
+   { dg-final { scan-tree-dump-times "memcmp" 0 "gimple" } }
+   { dg-final { scan-tree-dump-times "strcmp" 0 "gimple" } }
+   { dg-final { scan-tree-dump-times "call_in_true_branch_not_eliminated" 0 "optimized" } } */
diff --git a/gcc/testsuite/gcc.dg/strlenopt-56.c b/gcc/testsuite/gcc.dg/strlenopt-56.c
new file mode 100644
index 0000000..39a532b
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/strlenopt-56.c
@@ -0,0 +1,50 @@
+/* PR tree-optimization/71625 - conversion of braced initializers to strings
+   Verify that array elements have the expected values regardless of sign
+   and non-ASCII execution character set.
+   { dg-do compile }
+   { dg-require-iconv "IBM1047" }
+   { dg-options "-O -Wall -fexec-charset=IBM1047 -fdump-tree-gimple -fdump-tree-optimized" } */
+
+#include "strlenopt.h"
+
+const char a[] = { 'a', 129, 0 };
+const signed char b[] = { 'b', 130, 0 };
+const unsigned char c[] = { 'c', 131, 0 };
+
+const char s[] = "a\201";
+const signed char ss[] = "b\202";
+const unsigned char us[] = "c\203";
+
+
+#define A(expr)   ((expr) ? (void)0 : __builtin_abort ())
+
+void test_values (void)
+{
+  A (a[0] == a[1]);
+  A (a[1] == 'a');
+
+  A (b[0] == b[1]);
+  A (b[1] == (signed char)'b');
+
+  A (c[0] == c[1]);
+  A (c[1] == (unsigned char)'c');
+}
+
+void test_lengths (void)
+{
+  A (2 == strlen (a));
+  A (2 == strlen ((const char*)b));
+  A (2 == strlen ((const char*)c));
+}
+
+void test_contents (void)
+{
+  A (0 == strcmp (a, s));
+  A (0 == strcmp ((const char*)b, (const char*)ss));
+  A (0 == strcmp ((const char*)c, (const char*)us));
+}
+
+
+/* { dg-final { scan-tree-dump-times "strlen" 0 "gimple" } }
+   { dg-final { scan-tree-dump-times "strcmp" 0 "gimple" } }
+   { dg-final { scan-tree-dump-times "abort" 0 "optimized" } } */
Joseph Myers Aug. 9, 2018, 10:06 p.m. UTC | #12
On Wed, 8 Aug 2018, Martin Sebor wrote:

> Done in the attached patch.  I've also avoided dealing with
> zero-length arrays and added tests to make sure their size
> stays is regardless of the form of their initializer and
> the appropriate warnings are issued.

The C front-end changes in this patch version are OK.
Jason Merrill Aug. 13, 2018, 10:36 a.m. UTC | #13
On 08/09/2018 12:17 PM, Martin Sebor wrote:
> Using build_string() rather than build_string_literal() needed
> a tweak in digest_init_r().  It didn't break anything but since
> the array type may not have a domain yet, neither will the
> string.  It looks like that may get adjusted later on but I've
> temporarily guarded the code with #if 1.  If the change is
> fine I'll remove the #if before committing. 

The digest_init_r change seems to follow from allowing STRING_CST of 
signed char, so yes, it's fine.

> +		  && TREE_CODE (init) == CONSTRUCTOR
> +		  && TREE_TYPE (init) == init_list_type_node)

This is BRACE_ENCLOSED_INITIALIZER_P.

OK with that change.

Jason
James Greenhalgh Aug. 14, 2018, 1:27 p.m. UTC | #14
On Wed, Aug 08, 2018 at 07:17:07PM -0500, Martin Sebor wrote:
> On 08/08/2018 05:08 AM, Jason Merrill wrote:
> > On Wed, Aug 8, 2018 at 9:04 AM, Martin Sebor <msebor@gmail.com> wrote:
> >> On 08/07/2018 02:57 AM, Jason Merrill wrote:
> >>>
> >>> On Wed, Aug 1, 2018 at 12:49 AM, Martin Sebor <msebor@gmail.com> wrote:
> >>>>
> >>>> On 07/31/2018 07:38 AM, Jason Merrill wrote:

<snip>

> Done in the attached patch.  I've also avoided dealing with
> zero-length arrays and added tests to make sure their size
> stays is regardless of the form of their initializer and
> the appropriate warnings are issued.
> 
> Using build_string() rather than build_string_literal() needed
> a tweak in digest_init_r().  It didn't break anything but since
> the array type may not have a domain yet, neither will the
> string.  It looks like that may get adjusted later on but I've
> temporarily guarded the code with #if 1.  If the change is
> fine I'll remove the #if before committing.
> 
> This initial patch only handles narrow character initializers
> (i.e., those with TYPE_STRING_FLAG set).  Once this gets some
> exposure I'd like to extend it to other character types,
> including wchar_t.

Hi Martin,

This causes issues for the AArch64 tests (full list below).

I see an error message on the following construct:

  void foo (void)
  {
    __Poly8_t x[4] = { 1, 2, 3, 4 };
  }

  init.c:3:20: error: array of inappropriate type initialized from string constant
  3 |   __Poly8_t x[4] = { 1, 2, 3, 4 };
    |

__Poly8_t is a type we define in our backend, through a convoluted set of
functions, which operates a lot like an unsigned, QI mode type.

A second set of tests fail due to changed inlining behaviour for functions
with char array initialization:

  gcc.target/aarch64/vset_lane_1.c
  gcc.target/aarch64/vneg_s.c
  gcc.target/aarch64/vclz.c

Thanks,
James

-----

New failures in: 


gcc.target/aarch64/advsimd-intrinsics/vmax.c
gcc.target/aarch64/simd/vzipqp8_1.c
gcc.target/aarch64/vldN_dup_1.c
gcc.target/aarch64/advsimd-intrinsics/vcle.c
gcc.target/aarch64/advsimd-intrinsics/vadd.c
gcc.target/aarch64/advsimd-intrinsics/vhadd.c
gcc.target/aarch64/advsimd-intrinsics/vmull_n.c
gcc.target/aarch64/advsimd-intrinsics/vrndn.c
gcc.target/aarch64/simd/vtrnqp8_1.c
gcc.target/aarch64/advsimd-intrinsics/vpadal.c
gcc.target/aarch64/advsimd-intrinsics/vtrn_half.c
gcc.target/aarch64/advsimd-intrinsics/vqdmlal_n.c
gcc.target/aarch64/advsimd-intrinsics/vqdmulh.c
gcc.target/aarch64/advsimd-intrinsics/vqsub.c
gcc.target/aarch64/advsimd-intrinsics/vqdmlal_lane.c
gcc.target/aarch64/advsimd-intrinsics/vqdmlsl_n.c
gcc.target/aarch64/advsimd-intrinsics/vuzp_half.c
gcc.target/aarch64/advsimd-intrinsics/vst1_lane.c
gcc.target/aarch64/advsimd-intrinsics/vmla_lane.c
gcc.target/aarch64/advsimd-intrinsics/vqdmulh_lane.c
gcc.target/aarch64/advsimd-intrinsics/vrsqrte.c
gcc.target/aarch64/advsimd-intrinsics/vneg.c
gcc.target/aarch64/simd/vuzpqp8_1.c
gcc.target/aarch64/advsimd-intrinsics/vcale.c
gcc.target/aarch64/advsimd-intrinsics/vmla_n.c
gcc.target/aarch64/advsimd-intrinsics/vsub.c
gcc.target/aarch64/advsimd-intrinsics/vrev.c
gcc.target/aarch64/advsimd-intrinsics/vmul.c
gcc.target/aarch64/advsimd-intrinsics/vldX.c
gcc.target/aarch64/advsimd-intrinsics/vsubl.c
gcc.target/aarch64/advsimd-intrinsics/vfms.c
gcc.target/aarch64/advsimd-intrinsics/vmlsl.c
gcc.target/aarch64/advsimd-intrinsics/vsli_n.c
gcc.target/aarch64/advsimd-intrinsics/vcombine.c
gcc.target/aarch64/advsimd-intrinsics/vmul_n.c
gcc.target/aarch64/advsimd-intrinsics/vldX_dup.c
gcc.target/aarch64/advsimd-intrinsics/vpaddl.c
gcc.target/aarch64/advsimd-intrinsics/vqshrn_n.c
gcc.target/aarch64/advsimd-intrinsics/vstX_lane.c
gcc.target/aarch64/advsimd-intrinsics/vqtbX.c
gcc.target/aarch64/advsimd-intrinsics/vext.c
gcc.target/aarch64/advsimd-intrinsics/vtrn.c
gcc.target/aarch64/advsimd-intrinsics/vtst.c
gcc.target/aarch64/advsimd-intrinsics/vbic.c
gcc.target/aarch64/advsimd-intrinsics/vqdmlsl.c
gcc.target/aarch64/advsimd-intrinsics/vqshl.c
gcc.target/aarch64/advsimd-intrinsics/vrsqrts.c
gcc.target/aarch64/advsimd-intrinsics/vqdmull_n.c
gcc.target/aarch64/advsimd-intrinsics/vqdmlsl_lane.c
gcc.target/aarch64/advsimd-intrinsics/vqdmulh_n.c
gcc.target/aarch64/advsimd-intrinsics/vsubw.c
gcc.target/aarch64/advsimd-intrinsics/vdup_lane.c
gcc.target/aarch64/advsimd-intrinsics/vget_high.c
gcc.target/aarch64/advsimd-intrinsics/vuzp.c
gcc.target/aarch64/advsimd-intrinsics/vqshl_n.c
gcc.target/aarch64/advsimd-intrinsics/vrsra_n.c
gcc.target/aarch64/advsimd-intrinsics/vcgt.c
gcc.target/aarch64/advsimd-intrinsics/vld1_dup.c
gcc.target/aarch64/advsimd-intrinsics/vaddhn.c
gcc.target/aarch64/advsimd-intrinsics/vqshlu_n.c
gcc.target/aarch64/advsimd-intrinsics/vabs.c
gcc.target/aarch64/advsimd-intrinsics/vshll_n.c
gcc.target/aarch64/advsimd-intrinsics/vsubhn.c
gcc.target/aarch64/advsimd-intrinsics/vmlal.c
gcc.target/aarch64/advsimd-intrinsics/vqdmlal.c
gcc.target/aarch64/advsimd-intrinsics/vrecpe.c
gcc.target/aarch64/advsimd-intrinsics/vqneg.c
gcc.target/aarch64/advsimd-intrinsics/veor.c
gcc.target/aarch64/simd/extq_p8_1.c
gcc.target/aarch64/advsimd-intrinsics/vclz.c
gcc.target/aarch64/simd/ext_p8_1.c
gcc.target/aarch64/advsimd-intrinsics/vqrdmulh_lane.c
gcc.target/aarch64/advsimd-intrinsics/vqrshl.c
gcc.target/aarch64/advsimd-intrinsics/vqrshrun_n.c
gcc.target/aarch64/advsimd-intrinsics/vqrshrn_n.c
gcc.target/aarch64/advsimd-intrinsics/vceq.c
gcc.target/aarch64/advsimd-intrinsics/vrndm.c
gcc.target/aarch64/advsimd-intrinsics/vmlsl_n.c
gcc.target/aarch64/advsimd-intrinsics/vmlal_n.c
gcc.target/aarch64/advsimd-intrinsics/vqmovun.c
gcc.target/aarch64/advsimd-intrinsics/vrshr_n.c
gcc.target/aarch64/advsimd-intrinsics/vmls_n.c
gcc.target/aarch64/advsimd-intrinsics/vmlsl_lane.c
gcc.target/aarch64/advsimd-intrinsics/vqdmull_lane.c
gcc.target/aarch64/advsimd-intrinsics/vfms_vfma_n.c
gcc.target/aarch64/advsimd-intrinsics/vorr.c
gcc.target/aarch64/advsimd-intrinsics/vaddl.c
gcc.target/aarch64/advsimd-intrinsics/vmovl.c
gcc.target/aarch64/advsimd-intrinsics/vbsl.c
gcc.target/aarch64/advsimd-intrinsics/vld1_lane.c
gcc.target/aarch64/advsimd-intrinsics/vqmovn.c
gcc.target/aarch64/advsimd-intrinsics/vcalt.c
gcc.target/aarch64/advsimd-intrinsics/vmul_lane.c
gcc.target/aarch64/advsimd-intrinsics/vqshrun_n.c
gcc.target/aarch64/advsimd-intrinsics/vset_lane.c
gcc.target/aarch64/advsimd-intrinsics/vrsubhn.c
gcc.target/aarch64/advsimd-intrinsics/vshl_n.c
gcc.target/aarch64/advsimd-intrinsics/vmovn.c
gcc.target/aarch64/advsimd-intrinsics/vcls.c
gcc.target/aarch64/advsimd-intrinsics/vcage.c
gcc.target/aarch64/advsimd-intrinsics/vcnt.c
gcc.target/aarch64/advsimd-intrinsics/vmull.c
gcc.target/aarch64/simd/vuzpp8_1.c
gcc.target/aarch64/advsimd-intrinsics/vreinterpret_p64.c
gcc.target/aarch64/advsimd-intrinsics/vfma.c
gcc.target/aarch64/advsimd-intrinsics/vld1.c
gcc.target/aarch64/advsimd-intrinsics/vhsub.c
gcc.target/aarch64/advsimd-intrinsics/vget_low.c
gcc.target/aarch64/advsimd-intrinsics/p64_p128.c
gcc.target/aarch64/advsimd-intrinsics/vcvt.c
gcc.target/aarch64/advsimd-intrinsics/vqdmull.c
gcc.target/aarch64/advsimd-intrinsics/vmvn.c
gcc.target/aarch64/advsimd-intrinsics/vmin.c
gcc.target/aarch64/advsimd-intrinsics/vaba.c
gcc.target/aarch64/advsimd-intrinsics/vqrdmulh_n.c
gcc.target/aarch64/simd/vtrnp8_1.c
gcc.target/aarch64/advsimd-intrinsics/vcagt.c
gcc.target/aarch64/advsimd-intrinsics/vdup-vmov.c
gcc.target/aarch64/advsimd-intrinsics/vrhadd.c
gcc.target/aarch64/advsimd-intrinsics/vabal.c
gcc.target/aarch64/advsimd-intrinsics/vrshrn_n.c
gcc.target/aarch64/advsimd-intrinsics/vpmax.c
gcc.target/aarch64/advsimd-intrinsics/vmls.c
gcc.target/aarch64/advsimd-intrinsics/vshrn_n.c
gcc.target/aarch64/advsimd-intrinsics/vrnd.c
gcc.target/aarch64/advsimd-intrinsics/vabd.c
gcc.target/aarch64/simd/vzipp8_1.c
gcc.target/aarch64/advsimd-intrinsics/vduph_lane.c
gcc.target/aarch64/advsimd-intrinsics/vreinterpret_p128.c
gcc.target/aarch64/advsimd-intrinsics/vrshl.c
gcc.target/aarch64/advsimd-intrinsics/vcreate.c
gcc.target/aarch64/advsimd-intrinsics/vqabs.c
gcc.target/aarch64/advsimd-intrinsics/vmull_lane.c
gcc.target/aarch64/advsimd-intrinsics/vreinterpret.c
gcc.target/aarch64/advsimd-intrinsics/vmlal_lane.c
gcc.target/aarch64/advsimd-intrinsics/vshr_n.c
gcc.target/aarch64/advsimd-intrinsics/vzip.c
gcc.target/aarch64/vldN_lane_1.c
gcc.target/aarch64/advsimd-intrinsics/vabdl.c
gcc.target/aarch64/advsimd-intrinsics/vpmin.c
gcc.target/aarch64/advsimd-intrinsics/vqadd.c
gcc.target/aarch64/advsimd-intrinsics/vzip_half.c
gcc.target/aarch64/advsimd-intrinsics/vand.c
gcc.target/aarch64/advsimd-intrinsics/vpadd.c
gcc.target/aarch64/advsimd-intrinsics/vrndx.c
gcc.target/aarch64/advsimd-intrinsics/vmla.c
gcc.target/aarch64/advsimd-intrinsics/vsra_n.c
gcc.target/aarch64/advsimd-intrinsics/vget_lane.c
gcc.target/aarch64/advsimd-intrinsics/vqrdmulh.c
gcc.target/aarch64/advsimd-intrinsics/vrndp.c
gcc.target/aarch64/advsimd-intrinsics/vmls_lane.c
gcc.target/aarch64/advsimd-intrinsics/vclt.c
gcc.target/aarch64/advsimd-intrinsics/vfma_n.c
gcc.target/aarch64/advsimd-intrinsics/vaddw.c
gcc.target/aarch64/advsimd-intrinsics/vsri_n.c
gcc.target/aarch64/advsimd-intrinsics/vorn.c
gcc.target/aarch64/advsimd-intrinsics/vcvt_f16.c
gcc.target/aarch64/advsimd-intrinsics/vldX_lane.c
gcc.target/aarch64/advsimd-intrinsics/vcge.c
gcc.target/aarch64/advsimd-intrinsics/vshl.c
gcc.target/aarch64/advsimd-intrinsics/vtbX.c
gcc.target/aarch64/advsimd-intrinsics/vraddhn.c
gcc.target/aarch64/advsimd-intrinsics/vrnda.c
gcc.target/aarch64/advsimd-intrinsics/vrecps.c





> 
> Martin

> PR tree-optimization/71625 - missing strlen optimization on different array initialization style
> 
> gcc/c/ChangeLog:
> 
> 	PR tree-optimization/71625
> 	* c-parser.c (c_parser_declaration_or_fndef): Call
> 	braced_list_to_string.
> 
> gcc/c-family/ChangeLog:
> 
> 	PR tree-optimization/71625
> 	* c-common.c (braced_list_to_string): New function.
> 	* c-common.h (braced_list_to_string): Declare it.
> 
> gcc/cp/ChangeLog:
> 
> 	PR tree-optimization/71625
> 	* decl.c (check_initializer):  Call braced_list_to_string.
> 	(eval_check_narrowing): New function.
> 	* gcc/cp/typeck2.c (digest_init_r): Accept strings literals
> 	as initilizers for all narrow character types.
> 
> gcc/testsuite/ChangeLog:
> 
> 	PR tree-optimization/71625
> 	* g++.dg/init/string2.C: New test.
> 	* g++.dg/init/string3.C: New test.
> 	* g++.dg/init/string4.C: New test.
> 	* gcc.dg/init-string-3.c: New test.
> 	* gcc.dg/strlenopt-55.c: New test.
> 	* gcc.dg/strlenopt-56.c: New test.
Martin Sebor Aug. 14, 2018, 3:08 p.m. UTC | #15
On 08/14/2018 07:27 AM, James Greenhalgh wrote:
> On Wed, Aug 08, 2018 at 07:17:07PM -0500, Martin Sebor wrote:
>> On 08/08/2018 05:08 AM, Jason Merrill wrote:
>>> On Wed, Aug 8, 2018 at 9:04 AM, Martin Sebor <msebor@gmail.com> wrote:
>>>> On 08/07/2018 02:57 AM, Jason Merrill wrote:
>>>>>
>>>>> On Wed, Aug 1, 2018 at 12:49 AM, Martin Sebor <msebor@gmail.com> wrote:
>>>>>>
>>>>>> On 07/31/2018 07:38 AM, Jason Merrill wrote:
>
> <snip>
>
>> Done in the attached patch.  I've also avoided dealing with
>> zero-length arrays and added tests to make sure their size
>> stays is regardless of the form of their initializer and
>> the appropriate warnings are issued.
>>
>> Using build_string() rather than build_string_literal() needed
>> a tweak in digest_init_r().  It didn't break anything but since
>> the array type may not have a domain yet, neither will the
>> string.  It looks like that may get adjusted later on but I've
>> temporarily guarded the code with #if 1.  If the change is
>> fine I'll remove the #if before committing.
>>
>> This initial patch only handles narrow character initializers
>> (i.e., those with TYPE_STRING_FLAG set).  Once this gets some
>> exposure I'd like to extend it to other character types,
>> including wchar_t.
>
> Hi Martin,
>
> This causes issues for the AArch64 tests (full list below).
>
> I see an error message on the following construct:
>
>   void foo (void)
>   {
>     __Poly8_t x[4] = { 1, 2, 3, 4 };
>   }
>
>   init.c:3:20: error: array of inappropriate type initialized from string constant
>   3 |   __Poly8_t x[4] = { 1, 2, 3, 4 };
>     |
>
> __Poly8_t is a type we define in our backend, through a convoluted set of
> functions, which operates a lot like an unsigned, QI mode type.

I see the error with my aarch64 cross-compiler .  The new code
that does the conversion of array initializers to STRING_CSTs
looks for the TYPE_STRING_FLAG() to be set on the type of
the array elements.  Perhaps __Poly8_t should not have the flag
set?  (If it needs it then I think we'd have to only consider
named character types.)

> A second set of tests fail due to changed inlining behaviour for functions
> with char array initialization:
>
>   gcc.target/aarch64/vset_lane_1.c
>   gcc.target/aarch64/vneg_s.c
>   gcc.target/aarch64/vclz.c

I'm not sure what's going on here.  The tests are very big and
take forever to compile with an aarch64 cross-compiler, and I'm
not sure what to look for.  Can you provide a smaller test case
that shows the issue?

Martin

>
> Thanks,
> James
>
> -----
>
> New failures in:
>
>
> gcc.target/aarch64/advsimd-intrinsics/vmax.c
> gcc.target/aarch64/simd/vzipqp8_1.c
> gcc.target/aarch64/vldN_dup_1.c
> gcc.target/aarch64/advsimd-intrinsics/vcle.c
> gcc.target/aarch64/advsimd-intrinsics/vadd.c
> gcc.target/aarch64/advsimd-intrinsics/vhadd.c
> gcc.target/aarch64/advsimd-intrinsics/vmull_n.c
> gcc.target/aarch64/advsimd-intrinsics/vrndn.c
> gcc.target/aarch64/simd/vtrnqp8_1.c
> gcc.target/aarch64/advsimd-intrinsics/vpadal.c
> gcc.target/aarch64/advsimd-intrinsics/vtrn_half.c
> gcc.target/aarch64/advsimd-intrinsics/vqdmlal_n.c
> gcc.target/aarch64/advsimd-intrinsics/vqdmulh.c
> gcc.target/aarch64/advsimd-intrinsics/vqsub.c
> gcc.target/aarch64/advsimd-intrinsics/vqdmlal_lane.c
> gcc.target/aarch64/advsimd-intrinsics/vqdmlsl_n.c
> gcc.target/aarch64/advsimd-intrinsics/vuzp_half.c
> gcc.target/aarch64/advsimd-intrinsics/vst1_lane.c
> gcc.target/aarch64/advsimd-intrinsics/vmla_lane.c
> gcc.target/aarch64/advsimd-intrinsics/vqdmulh_lane.c
> gcc.target/aarch64/advsimd-intrinsics/vrsqrte.c
> gcc.target/aarch64/advsimd-intrinsics/vneg.c
> gcc.target/aarch64/simd/vuzpqp8_1.c
> gcc.target/aarch64/advsimd-intrinsics/vcale.c
> gcc.target/aarch64/advsimd-intrinsics/vmla_n.c
> gcc.target/aarch64/advsimd-intrinsics/vsub.c
> gcc.target/aarch64/advsimd-intrinsics/vrev.c
> gcc.target/aarch64/advsimd-intrinsics/vmul.c
> gcc.target/aarch64/advsimd-intrinsics/vldX.c
> gcc.target/aarch64/advsimd-intrinsics/vsubl.c
> gcc.target/aarch64/advsimd-intrinsics/vfms.c
> gcc.target/aarch64/advsimd-intrinsics/vmlsl.c
> gcc.target/aarch64/advsimd-intrinsics/vsli_n.c
> gcc.target/aarch64/advsimd-intrinsics/vcombine.c
> gcc.target/aarch64/advsimd-intrinsics/vmul_n.c
> gcc.target/aarch64/advsimd-intrinsics/vldX_dup.c
> gcc.target/aarch64/advsimd-intrinsics/vpaddl.c
> gcc.target/aarch64/advsimd-intrinsics/vqshrn_n.c
> gcc.target/aarch64/advsimd-intrinsics/vstX_lane.c
> gcc.target/aarch64/advsimd-intrinsics/vqtbX.c
> gcc.target/aarch64/advsimd-intrinsics/vext.c
> gcc.target/aarch64/advsimd-intrinsics/vtrn.c
> gcc.target/aarch64/advsimd-intrinsics/vtst.c
> gcc.target/aarch64/advsimd-intrinsics/vbic.c
> gcc.target/aarch64/advsimd-intrinsics/vqdmlsl.c
> gcc.target/aarch64/advsimd-intrinsics/vqshl.c
> gcc.target/aarch64/advsimd-intrinsics/vrsqrts.c
> gcc.target/aarch64/advsimd-intrinsics/vqdmull_n.c
> gcc.target/aarch64/advsimd-intrinsics/vqdmlsl_lane.c
> gcc.target/aarch64/advsimd-intrinsics/vqdmulh_n.c
> gcc.target/aarch64/advsimd-intrinsics/vsubw.c
> gcc.target/aarch64/advsimd-intrinsics/vdup_lane.c
> gcc.target/aarch64/advsimd-intrinsics/vget_high.c
> gcc.target/aarch64/advsimd-intrinsics/vuzp.c
> gcc.target/aarch64/advsimd-intrinsics/vqshl_n.c
> gcc.target/aarch64/advsimd-intrinsics/vrsra_n.c
> gcc.target/aarch64/advsimd-intrinsics/vcgt.c
> gcc.target/aarch64/advsimd-intrinsics/vld1_dup.c
> gcc.target/aarch64/advsimd-intrinsics/vaddhn.c
> gcc.target/aarch64/advsimd-intrinsics/vqshlu_n.c
> gcc.target/aarch64/advsimd-intrinsics/vabs.c
> gcc.target/aarch64/advsimd-intrinsics/vshll_n.c
> gcc.target/aarch64/advsimd-intrinsics/vsubhn.c
> gcc.target/aarch64/advsimd-intrinsics/vmlal.c
> gcc.target/aarch64/advsimd-intrinsics/vqdmlal.c
> gcc.target/aarch64/advsimd-intrinsics/vrecpe.c
> gcc.target/aarch64/advsimd-intrinsics/vqneg.c
> gcc.target/aarch64/advsimd-intrinsics/veor.c
> gcc.target/aarch64/simd/extq_p8_1.c
> gcc.target/aarch64/advsimd-intrinsics/vclz.c
> gcc.target/aarch64/simd/ext_p8_1.c
> gcc.target/aarch64/advsimd-intrinsics/vqrdmulh_lane.c
> gcc.target/aarch64/advsimd-intrinsics/vqrshl.c
> gcc.target/aarch64/advsimd-intrinsics/vqrshrun_n.c
> gcc.target/aarch64/advsimd-intrinsics/vqrshrn_n.c
> gcc.target/aarch64/advsimd-intrinsics/vceq.c
> gcc.target/aarch64/advsimd-intrinsics/vrndm.c
> gcc.target/aarch64/advsimd-intrinsics/vmlsl_n.c
> gcc.target/aarch64/advsimd-intrinsics/vmlal_n.c
> gcc.target/aarch64/advsimd-intrinsics/vqmovun.c
> gcc.target/aarch64/advsimd-intrinsics/vrshr_n.c
> gcc.target/aarch64/advsimd-intrinsics/vmls_n.c
> gcc.target/aarch64/advsimd-intrinsics/vmlsl_lane.c
> gcc.target/aarch64/advsimd-intrinsics/vqdmull_lane.c
> gcc.target/aarch64/advsimd-intrinsics/vfms_vfma_n.c
> gcc.target/aarch64/advsimd-intrinsics/vorr.c
> gcc.target/aarch64/advsimd-intrinsics/vaddl.c
> gcc.target/aarch64/advsimd-intrinsics/vmovl.c
> gcc.target/aarch64/advsimd-intrinsics/vbsl.c
> gcc.target/aarch64/advsimd-intrinsics/vld1_lane.c
> gcc.target/aarch64/advsimd-intrinsics/vqmovn.c
> gcc.target/aarch64/advsimd-intrinsics/vcalt.c
> gcc.target/aarch64/advsimd-intrinsics/vmul_lane.c
> gcc.target/aarch64/advsimd-intrinsics/vqshrun_n.c
> gcc.target/aarch64/advsimd-intrinsics/vset_lane.c
> gcc.target/aarch64/advsimd-intrinsics/vrsubhn.c
> gcc.target/aarch64/advsimd-intrinsics/vshl_n.c
> gcc.target/aarch64/advsimd-intrinsics/vmovn.c
> gcc.target/aarch64/advsimd-intrinsics/vcls.c
> gcc.target/aarch64/advsimd-intrinsics/vcage.c
> gcc.target/aarch64/advsimd-intrinsics/vcnt.c
> gcc.target/aarch64/advsimd-intrinsics/vmull.c
> gcc.target/aarch64/simd/vuzpp8_1.c
> gcc.target/aarch64/advsimd-intrinsics/vreinterpret_p64.c
> gcc.target/aarch64/advsimd-intrinsics/vfma.c
> gcc.target/aarch64/advsimd-intrinsics/vld1.c
> gcc.target/aarch64/advsimd-intrinsics/vhsub.c
> gcc.target/aarch64/advsimd-intrinsics/vget_low.c
> gcc.target/aarch64/advsimd-intrinsics/p64_p128.c
> gcc.target/aarch64/advsimd-intrinsics/vcvt.c
> gcc.target/aarch64/advsimd-intrinsics/vqdmull.c
> gcc.target/aarch64/advsimd-intrinsics/vmvn.c
> gcc.target/aarch64/advsimd-intrinsics/vmin.c
> gcc.target/aarch64/advsimd-intrinsics/vaba.c
> gcc.target/aarch64/advsimd-intrinsics/vqrdmulh_n.c
> gcc.target/aarch64/simd/vtrnp8_1.c
> gcc.target/aarch64/advsimd-intrinsics/vcagt.c
> gcc.target/aarch64/advsimd-intrinsics/vdup-vmov.c
> gcc.target/aarch64/advsimd-intrinsics/vrhadd.c
> gcc.target/aarch64/advsimd-intrinsics/vabal.c
> gcc.target/aarch64/advsimd-intrinsics/vrshrn_n.c
> gcc.target/aarch64/advsimd-intrinsics/vpmax.c
> gcc.target/aarch64/advsimd-intrinsics/vmls.c
> gcc.target/aarch64/advsimd-intrinsics/vshrn_n.c
> gcc.target/aarch64/advsimd-intrinsics/vrnd.c
> gcc.target/aarch64/advsimd-intrinsics/vabd.c
> gcc.target/aarch64/simd/vzipp8_1.c
> gcc.target/aarch64/advsimd-intrinsics/vduph_lane.c
> gcc.target/aarch64/advsimd-intrinsics/vreinterpret_p128.c
> gcc.target/aarch64/advsimd-intrinsics/vrshl.c
> gcc.target/aarch64/advsimd-intrinsics/vcreate.c
> gcc.target/aarch64/advsimd-intrinsics/vqabs.c
> gcc.target/aarch64/advsimd-intrinsics/vmull_lane.c
> gcc.target/aarch64/advsimd-intrinsics/vreinterpret.c
> gcc.target/aarch64/advsimd-intrinsics/vmlal_lane.c
> gcc.target/aarch64/advsimd-intrinsics/vshr_n.c
> gcc.target/aarch64/advsimd-intrinsics/vzip.c
> gcc.target/aarch64/vldN_lane_1.c
> gcc.target/aarch64/advsimd-intrinsics/vabdl.c
> gcc.target/aarch64/advsimd-intrinsics/vpmin.c
> gcc.target/aarch64/advsimd-intrinsics/vqadd.c
> gcc.target/aarch64/advsimd-intrinsics/vzip_half.c
> gcc.target/aarch64/advsimd-intrinsics/vand.c
> gcc.target/aarch64/advsimd-intrinsics/vpadd.c
> gcc.target/aarch64/advsimd-intrinsics/vrndx.c
> gcc.target/aarch64/advsimd-intrinsics/vmla.c
> gcc.target/aarch64/advsimd-intrinsics/vsra_n.c
> gcc.target/aarch64/advsimd-intrinsics/vget_lane.c
> gcc.target/aarch64/advsimd-intrinsics/vqrdmulh.c
> gcc.target/aarch64/advsimd-intrinsics/vrndp.c
> gcc.target/aarch64/advsimd-intrinsics/vmls_lane.c
> gcc.target/aarch64/advsimd-intrinsics/vclt.c
> gcc.target/aarch64/advsimd-intrinsics/vfma_n.c
> gcc.target/aarch64/advsimd-intrinsics/vaddw.c
> gcc.target/aarch64/advsimd-intrinsics/vsri_n.c
> gcc.target/aarch64/advsimd-intrinsics/vorn.c
> gcc.target/aarch64/advsimd-intrinsics/vcvt_f16.c
> gcc.target/aarch64/advsimd-intrinsics/vldX_lane.c
> gcc.target/aarch64/advsimd-intrinsics/vcge.c
> gcc.target/aarch64/advsimd-intrinsics/vshl.c
> gcc.target/aarch64/advsimd-intrinsics/vtbX.c
> gcc.target/aarch64/advsimd-intrinsics/vraddhn.c
> gcc.target/aarch64/advsimd-intrinsics/vrnda.c
> gcc.target/aarch64/advsimd-intrinsics/vrecps.c
>
>
>
>
>
>>
>> Martin
>
>> PR tree-optimization/71625 - missing strlen optimization on different array initialization style
>>
>> gcc/c/ChangeLog:
>>
>> 	PR tree-optimization/71625
>> 	* c-parser.c (c_parser_declaration_or_fndef): Call
>> 	braced_list_to_string.
>>
>> gcc/c-family/ChangeLog:
>>
>> 	PR tree-optimization/71625
>> 	* c-common.c (braced_list_to_string): New function.
>> 	* c-common.h (braced_list_to_string): Declare it.
>>
>> gcc/cp/ChangeLog:
>>
>> 	PR tree-optimization/71625
>> 	* decl.c (check_initializer):  Call braced_list_to_string.
>> 	(eval_check_narrowing): New function.
>> 	* gcc/cp/typeck2.c (digest_init_r): Accept strings literals
>> 	as initilizers for all narrow character types.
>>
>> gcc/testsuite/ChangeLog:
>>
>> 	PR tree-optimization/71625
>> 	* g++.dg/init/string2.C: New test.
>> 	* g++.dg/init/string3.C: New test.
>> 	* g++.dg/init/string4.C: New test.
>> 	* gcc.dg/init-string-3.c: New test.
>> 	* gcc.dg/strlenopt-55.c: New test.
>> 	* gcc.dg/strlenopt-56.c: New test.
Martin Sebor Aug. 14, 2018, 3:24 p.m. UTC | #16
On 08/14/2018 09:08 AM, Martin Sebor wrote:
> On 08/14/2018 07:27 AM, James Greenhalgh wrote:
>> On Wed, Aug 08, 2018 at 07:17:07PM -0500, Martin Sebor wrote:
>>> On 08/08/2018 05:08 AM, Jason Merrill wrote:
>>>> On Wed, Aug 8, 2018 at 9:04 AM, Martin Sebor <msebor@gmail.com> wrote:
>>>>> On 08/07/2018 02:57 AM, Jason Merrill wrote:
>>>>>>
>>>>>> On Wed, Aug 1, 2018 at 12:49 AM, Martin Sebor <msebor@gmail.com>
>>>>>> wrote:
>>>>>>>
>>>>>>> On 07/31/2018 07:38 AM, Jason Merrill wrote:
>>
>> <snip>
>>
>>> Done in the attached patch.  I've also avoided dealing with
>>> zero-length arrays and added tests to make sure their size
>>> stays is regardless of the form of their initializer and
>>> the appropriate warnings are issued.
>>>
>>> Using build_string() rather than build_string_literal() needed
>>> a tweak in digest_init_r().  It didn't break anything but since
>>> the array type may not have a domain yet, neither will the
>>> string.  It looks like that may get adjusted later on but I've
>>> temporarily guarded the code with #if 1.  If the change is
>>> fine I'll remove the #if before committing.
>>>
>>> This initial patch only handles narrow character initializers
>>> (i.e., those with TYPE_STRING_FLAG set).  Once this gets some
>>> exposure I'd like to extend it to other character types,
>>> including wchar_t.
>>
>> Hi Martin,
>>
>> This causes issues for the AArch64 tests (full list below).
>>
>> I see an error message on the following construct:
>>
>>   void foo (void)
>>   {
>>     __Poly8_t x[4] = { 1, 2, 3, 4 };
>>   }
>>
>>   init.c:3:20: error: array of inappropriate type initialized from
>> string constant
>>   3 |   __Poly8_t x[4] = { 1, 2, 3, 4 };
>>     |
>>
>> __Poly8_t is a type we define in our backend, through a convoluted set of
>> functions, which operates a lot like an unsigned, QI mode type.
>
> I see the error with my aarch64 cross-compiler .  The new code
> that does the conversion of array initializers to STRING_CSTs
> looks for the TYPE_STRING_FLAG() to be set on the type of
> the array elements.  Perhaps __Poly8_t should not have the flag
> set?  (If it needs it then I think we'd have to only consider
> named character types.)

The change below gets rid of the compilation error.  I don't
know if it's appropriate for the aarch64 back end:

Index: gcc/config/aarch64/aarch64-builtins.c
===================================================================
--- gcc/config/aarch64/aarch64-builtins.c	(revision 263537)
+++ gcc/config/aarch64/aarch64-builtins.c	(working copy)
@@ -643,6 +643,7 @@ aarch64_init_simd_builtin_types (void)
    /* Poly types are a world of their own.  */
    aarch64_simd_types[Poly8_t].eltype = aarch64_simd_types[Poly8_t].itype =
      build_distinct_type_copy (unsigned_intQI_type_node);
+  TYPE_STRING_FLAG (aarch64_simd_types[Poly8_t].eltype) = false;
    aarch64_simd_types[Poly16_t].eltype = 
aarch64_simd_types[Poly16_t].itype =
      build_distinct_type_copy (unsigned_intHI_type_node);
    aarch64_simd_types[Poly64_t].eltype = 
aarch64_simd_types[Poly64_t].itype =


>> A second set of tests fail due to changed inlining behaviour for
>> functions
>> with char array initialization:
>>
>>   gcc.target/aarch64/vset_lane_1.c
>>   gcc.target/aarch64/vneg_s.c
>>   gcc.target/aarch64/vclz.c
>
> I'm not sure what's going on here.  The tests are very big and
> take forever to compile with an aarch64 cross-compiler, and I'm
> not sure what to look for.  Can you provide a smaller test case
> that shows the issue?
>
> Martin
>
>>
>> Thanks,
>> James
>>
>> -----
>>
>> New failures in:
>>
>>
>> gcc.target/aarch64/advsimd-intrinsics/vmax.c
>> gcc.target/aarch64/simd/vzipqp8_1.c
>> gcc.target/aarch64/vldN_dup_1.c
>> gcc.target/aarch64/advsimd-intrinsics/vcle.c
>> gcc.target/aarch64/advsimd-intrinsics/vadd.c
>> gcc.target/aarch64/advsimd-intrinsics/vhadd.c
>> gcc.target/aarch64/advsimd-intrinsics/vmull_n.c
>> gcc.target/aarch64/advsimd-intrinsics/vrndn.c
>> gcc.target/aarch64/simd/vtrnqp8_1.c
>> gcc.target/aarch64/advsimd-intrinsics/vpadal.c
>> gcc.target/aarch64/advsimd-intrinsics/vtrn_half.c
>> gcc.target/aarch64/advsimd-intrinsics/vqdmlal_n.c
>> gcc.target/aarch64/advsimd-intrinsics/vqdmulh.c
>> gcc.target/aarch64/advsimd-intrinsics/vqsub.c
>> gcc.target/aarch64/advsimd-intrinsics/vqdmlal_lane.c
>> gcc.target/aarch64/advsimd-intrinsics/vqdmlsl_n.c
>> gcc.target/aarch64/advsimd-intrinsics/vuzp_half.c
>> gcc.target/aarch64/advsimd-intrinsics/vst1_lane.c
>> gcc.target/aarch64/advsimd-intrinsics/vmla_lane.c
>> gcc.target/aarch64/advsimd-intrinsics/vqdmulh_lane.c
>> gcc.target/aarch64/advsimd-intrinsics/vrsqrte.c
>> gcc.target/aarch64/advsimd-intrinsics/vneg.c
>> gcc.target/aarch64/simd/vuzpqp8_1.c
>> gcc.target/aarch64/advsimd-intrinsics/vcale.c
>> gcc.target/aarch64/advsimd-intrinsics/vmla_n.c
>> gcc.target/aarch64/advsimd-intrinsics/vsub.c
>> gcc.target/aarch64/advsimd-intrinsics/vrev.c
>> gcc.target/aarch64/advsimd-intrinsics/vmul.c
>> gcc.target/aarch64/advsimd-intrinsics/vldX.c
>> gcc.target/aarch64/advsimd-intrinsics/vsubl.c
>> gcc.target/aarch64/advsimd-intrinsics/vfms.c
>> gcc.target/aarch64/advsimd-intrinsics/vmlsl.c
>> gcc.target/aarch64/advsimd-intrinsics/vsli_n.c
>> gcc.target/aarch64/advsimd-intrinsics/vcombine.c
>> gcc.target/aarch64/advsimd-intrinsics/vmul_n.c
>> gcc.target/aarch64/advsimd-intrinsics/vldX_dup.c
>> gcc.target/aarch64/advsimd-intrinsics/vpaddl.c
>> gcc.target/aarch64/advsimd-intrinsics/vqshrn_n.c
>> gcc.target/aarch64/advsimd-intrinsics/vstX_lane.c
>> gcc.target/aarch64/advsimd-intrinsics/vqtbX.c
>> gcc.target/aarch64/advsimd-intrinsics/vext.c
>> gcc.target/aarch64/advsimd-intrinsics/vtrn.c
>> gcc.target/aarch64/advsimd-intrinsics/vtst.c
>> gcc.target/aarch64/advsimd-intrinsics/vbic.c
>> gcc.target/aarch64/advsimd-intrinsics/vqdmlsl.c
>> gcc.target/aarch64/advsimd-intrinsics/vqshl.c
>> gcc.target/aarch64/advsimd-intrinsics/vrsqrts.c
>> gcc.target/aarch64/advsimd-intrinsics/vqdmull_n.c
>> gcc.target/aarch64/advsimd-intrinsics/vqdmlsl_lane.c
>> gcc.target/aarch64/advsimd-intrinsics/vqdmulh_n.c
>> gcc.target/aarch64/advsimd-intrinsics/vsubw.c
>> gcc.target/aarch64/advsimd-intrinsics/vdup_lane.c
>> gcc.target/aarch64/advsimd-intrinsics/vget_high.c
>> gcc.target/aarch64/advsimd-intrinsics/vuzp.c
>> gcc.target/aarch64/advsimd-intrinsics/vqshl_n.c
>> gcc.target/aarch64/advsimd-intrinsics/vrsra_n.c
>> gcc.target/aarch64/advsimd-intrinsics/vcgt.c
>> gcc.target/aarch64/advsimd-intrinsics/vld1_dup.c
>> gcc.target/aarch64/advsimd-intrinsics/vaddhn.c
>> gcc.target/aarch64/advsimd-intrinsics/vqshlu_n.c
>> gcc.target/aarch64/advsimd-intrinsics/vabs.c
>> gcc.target/aarch64/advsimd-intrinsics/vshll_n.c
>> gcc.target/aarch64/advsimd-intrinsics/vsubhn.c
>> gcc.target/aarch64/advsimd-intrinsics/vmlal.c
>> gcc.target/aarch64/advsimd-intrinsics/vqdmlal.c
>> gcc.target/aarch64/advsimd-intrinsics/vrecpe.c
>> gcc.target/aarch64/advsimd-intrinsics/vqneg.c
>> gcc.target/aarch64/advsimd-intrinsics/veor.c
>> gcc.target/aarch64/simd/extq_p8_1.c
>> gcc.target/aarch64/advsimd-intrinsics/vclz.c
>> gcc.target/aarch64/simd/ext_p8_1.c
>> gcc.target/aarch64/advsimd-intrinsics/vqrdmulh_lane.c
>> gcc.target/aarch64/advsimd-intrinsics/vqrshl.c
>> gcc.target/aarch64/advsimd-intrinsics/vqrshrun_n.c
>> gcc.target/aarch64/advsimd-intrinsics/vqrshrn_n.c
>> gcc.target/aarch64/advsimd-intrinsics/vceq.c
>> gcc.target/aarch64/advsimd-intrinsics/vrndm.c
>> gcc.target/aarch64/advsimd-intrinsics/vmlsl_n.c
>> gcc.target/aarch64/advsimd-intrinsics/vmlal_n.c
>> gcc.target/aarch64/advsimd-intrinsics/vqmovun.c
>> gcc.target/aarch64/advsimd-intrinsics/vrshr_n.c
>> gcc.target/aarch64/advsimd-intrinsics/vmls_n.c
>> gcc.target/aarch64/advsimd-intrinsics/vmlsl_lane.c
>> gcc.target/aarch64/advsimd-intrinsics/vqdmull_lane.c
>> gcc.target/aarch64/advsimd-intrinsics/vfms_vfma_n.c
>> gcc.target/aarch64/advsimd-intrinsics/vorr.c
>> gcc.target/aarch64/advsimd-intrinsics/vaddl.c
>> gcc.target/aarch64/advsimd-intrinsics/vmovl.c
>> gcc.target/aarch64/advsimd-intrinsics/vbsl.c
>> gcc.target/aarch64/advsimd-intrinsics/vld1_lane.c
>> gcc.target/aarch64/advsimd-intrinsics/vqmovn.c
>> gcc.target/aarch64/advsimd-intrinsics/vcalt.c
>> gcc.target/aarch64/advsimd-intrinsics/vmul_lane.c
>> gcc.target/aarch64/advsimd-intrinsics/vqshrun_n.c
>> gcc.target/aarch64/advsimd-intrinsics/vset_lane.c
>> gcc.target/aarch64/advsimd-intrinsics/vrsubhn.c
>> gcc.target/aarch64/advsimd-intrinsics/vshl_n.c
>> gcc.target/aarch64/advsimd-intrinsics/vmovn.c
>> gcc.target/aarch64/advsimd-intrinsics/vcls.c
>> gcc.target/aarch64/advsimd-intrinsics/vcage.c
>> gcc.target/aarch64/advsimd-intrinsics/vcnt.c
>> gcc.target/aarch64/advsimd-intrinsics/vmull.c
>> gcc.target/aarch64/simd/vuzpp8_1.c
>> gcc.target/aarch64/advsimd-intrinsics/vreinterpret_p64.c
>> gcc.target/aarch64/advsimd-intrinsics/vfma.c
>> gcc.target/aarch64/advsimd-intrinsics/vld1.c
>> gcc.target/aarch64/advsimd-intrinsics/vhsub.c
>> gcc.target/aarch64/advsimd-intrinsics/vget_low.c
>> gcc.target/aarch64/advsimd-intrinsics/p64_p128.c
>> gcc.target/aarch64/advsimd-intrinsics/vcvt.c
>> gcc.target/aarch64/advsimd-intrinsics/vqdmull.c
>> gcc.target/aarch64/advsimd-intrinsics/vmvn.c
>> gcc.target/aarch64/advsimd-intrinsics/vmin.c
>> gcc.target/aarch64/advsimd-intrinsics/vaba.c
>> gcc.target/aarch64/advsimd-intrinsics/vqrdmulh_n.c
>> gcc.target/aarch64/simd/vtrnp8_1.c
>> gcc.target/aarch64/advsimd-intrinsics/vcagt.c
>> gcc.target/aarch64/advsimd-intrinsics/vdup-vmov.c
>> gcc.target/aarch64/advsimd-intrinsics/vrhadd.c
>> gcc.target/aarch64/advsimd-intrinsics/vabal.c
>> gcc.target/aarch64/advsimd-intrinsics/vrshrn_n.c
>> gcc.target/aarch64/advsimd-intrinsics/vpmax.c
>> gcc.target/aarch64/advsimd-intrinsics/vmls.c
>> gcc.target/aarch64/advsimd-intrinsics/vshrn_n.c
>> gcc.target/aarch64/advsimd-intrinsics/vrnd.c
>> gcc.target/aarch64/advsimd-intrinsics/vabd.c
>> gcc.target/aarch64/simd/vzipp8_1.c
>> gcc.target/aarch64/advsimd-intrinsics/vduph_lane.c
>> gcc.target/aarch64/advsimd-intrinsics/vreinterpret_p128.c
>> gcc.target/aarch64/advsimd-intrinsics/vrshl.c
>> gcc.target/aarch64/advsimd-intrinsics/vcreate.c
>> gcc.target/aarch64/advsimd-intrinsics/vqabs.c
>> gcc.target/aarch64/advsimd-intrinsics/vmull_lane.c
>> gcc.target/aarch64/advsimd-intrinsics/vreinterpret.c
>> gcc.target/aarch64/advsimd-intrinsics/vmlal_lane.c
>> gcc.target/aarch64/advsimd-intrinsics/vshr_n.c
>> gcc.target/aarch64/advsimd-intrinsics/vzip.c
>> gcc.target/aarch64/vldN_lane_1.c
>> gcc.target/aarch64/advsimd-intrinsics/vabdl.c
>> gcc.target/aarch64/advsimd-intrinsics/vpmin.c
>> gcc.target/aarch64/advsimd-intrinsics/vqadd.c
>> gcc.target/aarch64/advsimd-intrinsics/vzip_half.c
>> gcc.target/aarch64/advsimd-intrinsics/vand.c
>> gcc.target/aarch64/advsimd-intrinsics/vpadd.c
>> gcc.target/aarch64/advsimd-intrinsics/vrndx.c
>> gcc.target/aarch64/advsimd-intrinsics/vmla.c
>> gcc.target/aarch64/advsimd-intrinsics/vsra_n.c
>> gcc.target/aarch64/advsimd-intrinsics/vget_lane.c
>> gcc.target/aarch64/advsimd-intrinsics/vqrdmulh.c
>> gcc.target/aarch64/advsimd-intrinsics/vrndp.c
>> gcc.target/aarch64/advsimd-intrinsics/vmls_lane.c
>> gcc.target/aarch64/advsimd-intrinsics/vclt.c
>> gcc.target/aarch64/advsimd-intrinsics/vfma_n.c
>> gcc.target/aarch64/advsimd-intrinsics/vaddw.c
>> gcc.target/aarch64/advsimd-intrinsics/vsri_n.c
>> gcc.target/aarch64/advsimd-intrinsics/vorn.c
>> gcc.target/aarch64/advsimd-intrinsics/vcvt_f16.c
>> gcc.target/aarch64/advsimd-intrinsics/vldX_lane.c
>> gcc.target/aarch64/advsimd-intrinsics/vcge.c
>> gcc.target/aarch64/advsimd-intrinsics/vshl.c
>> gcc.target/aarch64/advsimd-intrinsics/vtbX.c
>> gcc.target/aarch64/advsimd-intrinsics/vraddhn.c
>> gcc.target/aarch64/advsimd-intrinsics/vrnda.c
>> gcc.target/aarch64/advsimd-intrinsics/vrecps.c
>>
>>
>>
>>
>>
>>>
>>> Martin
>>
>>> PR tree-optimization/71625 - missing strlen optimization on different
>>> array initialization style
>>>
>>> gcc/c/ChangeLog:
>>>
>>>     PR tree-optimization/71625
>>>     * c-parser.c (c_parser_declaration_or_fndef): Call
>>>     braced_list_to_string.
>>>
>>> gcc/c-family/ChangeLog:
>>>
>>>     PR tree-optimization/71625
>>>     * c-common.c (braced_list_to_string): New function.
>>>     * c-common.h (braced_list_to_string): Declare it.
>>>
>>> gcc/cp/ChangeLog:
>>>
>>>     PR tree-optimization/71625
>>>     * decl.c (check_initializer):  Call braced_list_to_string.
>>>     (eval_check_narrowing): New function.
>>>     * gcc/cp/typeck2.c (digest_init_r): Accept strings literals
>>>     as initilizers for all narrow character types.
>>>
>>> gcc/testsuite/ChangeLog:
>>>
>>>     PR tree-optimization/71625
>>>     * g++.dg/init/string2.C: New test.
>>>     * g++.dg/init/string3.C: New test.
>>>     * g++.dg/init/string4.C: New test.
>>>     * gcc.dg/init-string-3.c: New test.
>>>     * gcc.dg/strlenopt-55.c: New test.
>>>     * gcc.dg/strlenopt-56.c: New test.
>
Joseph Myers Aug. 14, 2018, 9:14 p.m. UTC | #17
On Tue, 14 Aug 2018, James Greenhalgh wrote:

> Hi Martin,
> 
> This causes issues for the AArch64 tests (full list below).

This change (r263511) also breaks the glibc build for alpha-linux-gnu with 
build-many-glibcs.py (using mainline GCC and binutils).  The error I see 
is:

/scratch/jmyers/glibc-bot/install/compilers/alpha-linux-gnu/lib/gcc/alpha-glibc-linux-gnu/9.0.0/../../../../alpha-glibc-linux-gnu/bin/ld: 
/scratch/jmyers/glibc-bot/build/compilers/alpha-linux-gnu/glibc/alpha-linux-gnu/libc.a(plural.o): 
in function `__gettextparse':
/scratch/jmyers/glibc-bot/build/compilers/alpha-linux-gnu/glibc/alpha-linux-gnu/intl/plural.c:1108:(.text+0x218): 
relocation truncated to fit: GPRELHIGH against `.sdata'
/scratch/jmyers/glibc-bot/install/compilers/alpha-linux-gnu/lib/gcc/alpha-glibc-linux-gnu/9.0.0/../../../../alpha-glibc-linux-gnu/bin/ld: 
/scratch/jmyers/glibc-bot/build/compilers/alpha-linux-gnu/glibc/alpha-linux-gnu/intl/plural.c:1348:(.text+0x300): 
relocation truncated to fit: GPRELHIGH against `.sdata'
collect2: error: ld returned 1 exit status
../Rules:224: recipe for target 
'/scratch/jmyers/glibc-bot/build/compilers/alpha-linux-gnu/glibc/alpha-linux-gnu/elf/sln' 
failed
make[3]: *** 
[/scratch/jmyers/glibc-bot/build/compilers/alpha-linux-gnu/glibc/alpha-linux-gnu/elf/sln] 
Error 1

This is with Bison 3.0.4, should the version used to produce intl/plural.c 
prove relevant.
Martin Sebor Aug. 14, 2018, 10:18 p.m. UTC | #18
On 08/14/2018 03:14 PM, Joseph Myers wrote:
> On Tue, 14 Aug 2018, James Greenhalgh wrote:
>
>> Hi Martin,
>>
>> This causes issues for the AArch64 tests (full list below).
>
> This change (r263511) also breaks the glibc build for alpha-linux-gnu with
> build-many-glibcs.py (using mainline GCC and binutils).  The error I see
> is:
>
> /scratch/jmyers/glibc-bot/install/compilers/alpha-linux-gnu/lib/gcc/alpha-glibc-linux-gnu/9.0.0/../../../../alpha-glibc-linux-gnu/bin/ld:
> /scratch/jmyers/glibc-bot/build/compilers/alpha-linux-gnu/glibc/alpha-linux-gnu/libc.a(plural.o):
> in function `__gettextparse':
> /scratch/jmyers/glibc-bot/build/compilers/alpha-linux-gnu/glibc/alpha-linux-gnu/intl/plural.c:1108:(.text+0x218):
> relocation truncated to fit: GPRELHIGH against `.sdata'
> /scratch/jmyers/glibc-bot/install/compilers/alpha-linux-gnu/lib/gcc/alpha-glibc-linux-gnu/9.0.0/../../../../alpha-glibc-linux-gnu/bin/ld:
> /scratch/jmyers/glibc-bot/build/compilers/alpha-linux-gnu/glibc/alpha-linux-gnu/intl/plural.c:1348:(.text+0x300):
> relocation truncated to fit: GPRELHIGH against `.sdata'
> collect2: error: ld returned 1 exit status
> ../Rules:224: recipe for target
> '/scratch/jmyers/glibc-bot/build/compilers/alpha-linux-gnu/glibc/alpha-linux-gnu/elf/sln'
> failed
> make[3]: ***
> [/scratch/jmyers/glibc-bot/build/compilers/alpha-linux-gnu/glibc/alpha-linux-gnu/elf/sln]
> Error 1
>
> This is with Bison 3.0.4, should the version used to produce intl/plural.c
> prove relevant.

Can you send me the translation unit and the options it was compiled
with that triggered the errors?

Thanks
Martin
Martin Sebor Aug. 15, 2018, 2:34 a.m. UTC | #19
On 08/14/2018 09:24 AM, Martin Sebor wrote:
> On 08/14/2018 09:08 AM, Martin Sebor wrote:
>> On 08/14/2018 07:27 AM, James Greenhalgh wrote:
>>> On Wed, Aug 08, 2018 at 07:17:07PM -0500, Martin Sebor wrote:
>>>> On 08/08/2018 05:08 AM, Jason Merrill wrote:
>>>>> On Wed, Aug 8, 2018 at 9:04 AM, Martin Sebor <msebor@gmail.com> wrote:
>>>>>> On 08/07/2018 02:57 AM, Jason Merrill wrote:
>>>>>>>
>>>>>>> On Wed, Aug 1, 2018 at 12:49 AM, Martin Sebor <msebor@gmail.com>
>>>>>>> wrote:
>>>>>>>>
>>>>>>>> On 07/31/2018 07:38 AM, Jason Merrill wrote:
>>>
>>> <snip>
>>>
>>>> Done in the attached patch.  I've also avoided dealing with
>>>> zero-length arrays and added tests to make sure their size
>>>> stays is regardless of the form of their initializer and
>>>> the appropriate warnings are issued.
>>>>
>>>> Using build_string() rather than build_string_literal() needed
>>>> a tweak in digest_init_r().  It didn't break anything but since
>>>> the array type may not have a domain yet, neither will the
>>>> string.  It looks like that may get adjusted later on but I've
>>>> temporarily guarded the code with #if 1.  If the change is
>>>> fine I'll remove the #if before committing.
>>>>
>>>> This initial patch only handles narrow character initializers
>>>> (i.e., those with TYPE_STRING_FLAG set).  Once this gets some
>>>> exposure I'd like to extend it to other character types,
>>>> including wchar_t.
>>>
>>> Hi Martin,
>>>
>>> This causes issues for the AArch64 tests (full list below).
>>>
>>> I see an error message on the following construct:
>>>
>>>   void foo (void)
>>>   {
>>>     __Poly8_t x[4] = { 1, 2, 3, 4 };
>>>   }
>>>
>>>   init.c:3:20: error: array of inappropriate type initialized from
>>> string constant
>>>   3 |   __Poly8_t x[4] = { 1, 2, 3, 4 };
>>>     |
>>>
>>> __Poly8_t is a type we define in our backend, through a convoluted
>>> set of
>>> functions, which operates a lot like an unsigned, QI mode type.
>>
>> I see the error with my aarch64 cross-compiler .  The new code
>> that does the conversion of array initializers to STRING_CSTs
>> looks for the TYPE_STRING_FLAG() to be set on the type of
>> the array elements.  Perhaps __Poly8_t should not have the flag
>> set?  (If it needs it then I think we'd have to only consider
>> named character types.)
>
> The change below gets rid of the compilation error.  I don't
> know if it's appropriate for the aarch64 back end:
>
> Index: gcc/config/aarch64/aarch64-builtins.c
> ===================================================================
> --- gcc/config/aarch64/aarch64-builtins.c    (revision 263537)
> +++ gcc/config/aarch64/aarch64-builtins.c    (working copy)
> @@ -643,6 +643,7 @@ aarch64_init_simd_builtin_types (void)
>    /* Poly types are a world of their own.  */
>    aarch64_simd_types[Poly8_t].eltype = aarch64_simd_types[Poly8_t].itype =
>      build_distinct_type_copy (unsigned_intQI_type_node);
> +  TYPE_STRING_FLAG (aarch64_simd_types[Poly8_t].eltype) = false;
>    aarch64_simd_types[Poly16_t].eltype =
> aarch64_simd_types[Poly16_t].itype =
>      build_distinct_type_copy (unsigned_intHI_type_node);
>    aarch64_simd_types[Poly64_t].eltype =
> aarch64_simd_types[Poly64_t].itype =
>
>
>>> A second set of tests fail due to changed inlining behaviour for
>>> functions
>>> with char array initialization:
>>>
>>>   gcc.target/aarch64/vset_lane_1.c
>>>   gcc.target/aarch64/vneg_s.c
>>>   gcc.target/aarch64/vclz.c
>>
>> I'm not sure what's going on here.  The tests are very big and
>> take forever to compile with an aarch64 cross-compiler, and I'm
>> not sure what to look for.  Can you provide a smaller test case
>> that shows the issue?

I wonder if these changes might be due to the same problem:
the tests define and initialize arrays of the Int8x16_t type
which is initialized to intQI_type_node, i.e., the signed
form of Poly8_t.  Does the conversion to STRING_CST cause
a performance degradation or is it just that the tests end
up with equivalent but slightly different assembly?

The tests also use int8_t and uint8_t for the expected results.
Those are typedefs for signed and unsigned char, respectively.
Is the conversion to strings for those fine?

Martin
James Greenhalgh Aug. 15, 2018, 10:28 a.m. UTC | #20
On Tue, Aug 14, 2018 at 09:34:08PM -0500, Martin Sebor wrote:
> On 08/14/2018 09:24 AM, Martin Sebor wrote:
> > On 08/14/2018 09:08 AM, Martin Sebor wrote:
> >> On 08/14/2018 07:27 AM, James Greenhalgh wrote:
> >>> On Wed, Aug 08, 2018 at 07:17:07PM -0500, Martin Sebor wrote:
> >>>> On 08/08/2018 05:08 AM, Jason Merrill wrote:
> >>>>> On Wed, Aug 8, 2018 at 9:04 AM, Martin Sebor <msebor@gmail.com> wrote:
> >>>>>> On 08/07/2018 02:57 AM, Jason Merrill wrote:
> >>>>>>>
> >>>>>>> On Wed, Aug 1, 2018 at 12:49 AM, Martin Sebor <msebor@gmail.com>
> >>>>>>> wrote:
> >>>>>>>>
> >>>>>>>> On 07/31/2018 07:38 AM, Jason Merrill wrote:
> >>>
> >>> <snip>
> >>>
> >>>> Done in the attached patch.  I've also avoided dealing with
> >>>> zero-length arrays and added tests to make sure their size
> >>>> stays is regardless of the form of their initializer and
> >>>> the appropriate warnings are issued.
> >>>>
> >>>> Using build_string() rather than build_string_literal() needed
> >>>> a tweak in digest_init_r().  It didn't break anything but since
> >>>> the array type may not have a domain yet, neither will the
> >>>> string.  It looks like that may get adjusted later on but I've
> >>>> temporarily guarded the code with #if 1.  If the change is
> >>>> fine I'll remove the #if before committing.
> >>>>
> >>>> This initial patch only handles narrow character initializers
> >>>> (i.e., those with TYPE_STRING_FLAG set).  Once this gets some
> >>>> exposure I'd like to extend it to other character types,
> >>>> including wchar_t.
> >>>
> >>> Hi Martin,
> >>>
> >>> This causes issues for the AArch64 tests (full list below).
> >>>
> >>> I see an error message on the following construct:
> >>>
> >>>   void foo (void)
> >>>   {
> >>>     __Poly8_t x[4] = { 1, 2, 3, 4 };
> >>>   }
> >>>
> >>>   init.c:3:20: error: array of inappropriate type initialized from
> >>> string constant
> >>>   3 |   __Poly8_t x[4] = { 1, 2, 3, 4 };
> >>>     |
> >>>
> >>> __Poly8_t is a type we define in our backend, through a convoluted
> >>> set of
> >>> functions, which operates a lot like an unsigned, QI mode type.
> >>
> >> I see the error with my aarch64 cross-compiler .  The new code
> >> that does the conversion of array initializers to STRING_CSTs
> >> looks for the TYPE_STRING_FLAG() to be set on the type of
> >> the array elements.  Perhaps __Poly8_t should not have the flag
> >> set?  (If it needs it then I think we'd have to only consider
> >> named character types.)
> >
> > The change below gets rid of the compilation error.  I don't
> > know if it's appropriate for the aarch64 back end:
> >
> > Index: gcc/config/aarch64/aarch64-builtins.c
> > ===================================================================
> > --- gcc/config/aarch64/aarch64-builtins.c    (revision 263537)
> > +++ gcc/config/aarch64/aarch64-builtins.c    (working copy)
> > @@ -643,6 +643,7 @@ aarch64_init_simd_builtin_types (void)
> >    /* Poly types are a world of their own.  */
> >    aarch64_simd_types[Poly8_t].eltype = aarch64_simd_types[Poly8_t].itype =
> >      build_distinct_type_copy (unsigned_intQI_type_node);
> > +  TYPE_STRING_FLAG (aarch64_simd_types[Poly8_t].eltype) = false;
> >    aarch64_simd_types[Poly16_t].eltype =
> > aarch64_simd_types[Poly16_t].itype =
> >      build_distinct_type_copy (unsigned_intHI_type_node);
> >    aarch64_simd_types[Poly64_t].eltype =
> > aarch64_simd_types[Poly64_t].itype =

This fix seems correct to me, the poly types are not strings. Looking at
other uses of TYPE_STRING_FLAG this change doesn't seem like it would have
impact on parsing or code generation.

OK for trunk.

> >>> A second set of tests fail due to changed inlining behaviour for
> >>> functions
> >>> with char array initialization:
> >>>
> >>>   gcc.target/aarch64/vset_lane_1.c
> >>>   gcc.target/aarch64/vneg_s.c
> >>>   gcc.target/aarch64/vclz.c
> >>
> >> I'm not sure what's going on here.  The tests are very big and
> >> take forever to compile with an aarch64 cross-compiler, and I'm
> >> not sure what to look for.  Can you provide a smaller test case
> >> that shows the issue?
> 
> I wonder if these changes might be due to the same problem:
> the tests define and initialize arrays of the Int8x16_t type
> which is initialized to intQI_type_node, i.e., the signed
> form of Poly8_t.  Does the conversion to STRING_CST cause
> a performance degradation or is it just that the tests end
> up with equivalent but slightly different assembly?

These tests aren't looking at performance, just expecting to see certain
instructions emitted. The only change is that now the int8x16_t forms are
inlined (so the scan-assembler-times fails with two matches, one expected,
one in the inlined function body copy).

The difference seems to be in the initialization cost of the input data set.

Before your patch:

  int8_tD.3359 test_set0D.21541[8];
  int8_tD.3359 answ_set0D.21542[8];

      test_set0D.21541[0] = 0;
      test_set0D.21541[1] = 1;
      test_set0D.21541[2] = -1;
      test_set0D.21541[3] = 10;
      test_set0D.21541[4] = -10;
      test_set0D.21541[5] = 0;
      test_set0D.21541[6] = 127;
      test_set0D.21541[7] = -128;
      answ_set0D.21542[0] = 0;
      answ_set0D.21542[1] = -1;
      answ_set0D.21542[2] = 1;
      answ_set0D.21542[3] = -10;
      answ_set0D.21542[4] = 10;
      answ_set0D.21542[5] = 0;
      answ_set0D.21542[6] = -127;
      answ_set0D.21542[7] = -128;

After your patch:

  int8_tD.3357 test_set0D.21539[8];
  int8_tD.3357 answ_set0D.21540[8];

      test_set0D.21539 = "";
      answ_set0D.21540 = "";

I think that is probably what you expected to happen; but the impact on
inlining might not have been. Probably, we want to just change these tests
to explicitly disable inlining. The tests appear to execute correctly.

The print in the dump file is a bit unusual; presumably the impact of having
non-printing characters in my initializer list - but less helpful output for
it.

Off topic; these tests are quick to copmpile on my cross and native
compilers. Do you have additional checking enabled?

Thanks,
James

> 
> The tests also use int8_t and uint8_t for the expected results.
> Those are typedefs for signed and unsigned char, respectively.
> Is the conversion to strings for those fine?
> 
> Martin
Joseph Myers Aug. 15, 2018, 12:07 p.m. UTC | #21
On Tue, 14 Aug 2018, Martin Sebor wrote:

> > This is with Bison 3.0.4, should the version used to produce intl/plural.c
> > prove relevant.
> 
> Can you send me the translation unit and the options it was compiled
> with that triggered the errors?

I've attached plural.i.  The error is a static link error linking sln, but 
maybe comparing results of compiling plural.i before and after the changes 
may be enlightening (unless it's actually a difference in code elsewhere 
in glibc causing a link error reported in plural.o).

Compiled with:

alpha-glibc-linux-gnu-gcc 
/scratch/jmyers/glibc/many9/build/compilers/alpha-linux-gnu/glibc/alpha-linux-gnu/intl/plural.c 
-c -std=gnu11 -fgnu89-inline  -O2 -Wall -Werror -Wundef -Wwrite-strings 
-fmerge-all-constants -fno-stack-protector -frounding-math -g 
-Wstrict-prototypes -Wold-style-definition -fno-math-errno 
-mlong-double-128 -mieee -mfp-rounding-mode=d     -ftls-model=initial-exec      
-I../include 
-I/scratch/jmyers/glibc/many9/build/compilers/alpha-linux-gnu/glibc/alpha-linux-gnu/intl  
-I/scratch/jmyers/glibc/many9/build/compilers/alpha-linux-gnu/glibc/alpha-linux-gnu  
-I../sysdeps/unix/sysv/linux/alpha/alpha  
-I../sysdeps/unix/sysv/linux/alpha/fpu  -I../sysdeps/alpha/fpu  
-I../sysdeps/unix/sysv/linux/alpha  -I../sysdeps/alpha/nptl  
-I../sysdeps/unix/sysv/linux/wordsize-64  -I../sysdeps/ieee754/ldbl-64-128  
-I../sysdeps/ieee754/ldbl-opt  -I../sysdeps/unix/sysv/linux/include 
-I../sysdeps/unix/sysv/linux  -I../sysdeps/nptl  -I../sysdeps/pthread  
-I../sysdeps/gnu  -I../sysdeps/unix/inet  -I../sysdeps/unix/sysv  
-I../sysdeps/unix/alpha  -I../sysdeps/unix  -I../sysdeps/posix  
-I../sysdeps/alpha  -I../sysdeps/wordsize-64  
-I../sysdeps/ieee754/ldbl-128  -I../sysdeps/ieee754/dbl-64/wordsize-64  
-I../sysdeps/ieee754/dbl-64  -I../sysdeps/ieee754/flt-32  
-I../sysdeps/ieee754  -I../sysdeps/generic  -I.. -I../libio -I.   
-D_LIBC_REENTRANT -include 
/scratch/jmyers/glibc/many9/build/compilers/alpha-linux-gnu/glibc/alpha-linux-gnu/libc-modules.h 
-DMODULE_NAME=libc -include ../include/libc-symbols.h       
-DTOP_NAMESPACE=glibc -D'LOCALEDIR="/usr/share/locale"' 
-D'LOCALE_ALIAS_PATH="/usr/share/locale"' -o 
/scratch/jmyers/glibc/many9/build/compilers/alpha-linux-gnu/glibc/alpha-linux-gnu/intl/plural.o 
-MD -MP -MF 
/scratch/jmyers/glibc/many9/build/compilers/alpha-linux-gnu/glibc/alpha-linux-gnu/intl/plural.o.dt 
-MT 
/scratch/jmyers/glibc/many9/build/compilers/alpha-linux-gnu/glibc/alpha-linux-gnu/intl/plural.o
Richard Biener Aug. 15, 2018, 3:03 p.m. UTC | #22
On August 15, 2018 12:28:55 PM GMT+02:00, James Greenhalgh <James.Greenhalgh@arm.com> wrote:
>On Tue, Aug 14, 2018 at 09:34:08PM -0500, Martin Sebor wrote:
>> On 08/14/2018 09:24 AM, Martin Sebor wrote:
>> > On 08/14/2018 09:08 AM, Martin Sebor wrote:
>> >> On 08/14/2018 07:27 AM, James Greenhalgh wrote:
>> >>> On Wed, Aug 08, 2018 at 07:17:07PM -0500, Martin Sebor wrote:
>> >>>> On 08/08/2018 05:08 AM, Jason Merrill wrote:
>> >>>>> On Wed, Aug 8, 2018 at 9:04 AM, Martin Sebor <msebor@gmail.com>
>wrote:
>> >>>>>> On 08/07/2018 02:57 AM, Jason Merrill wrote:
>> >>>>>>>
>> >>>>>>> On Wed, Aug 1, 2018 at 12:49 AM, Martin Sebor
><msebor@gmail.com>
>> >>>>>>> wrote:
>> >>>>>>>>
>> >>>>>>>> On 07/31/2018 07:38 AM, Jason Merrill wrote:
>> >>>
>> >>> <snip>
>> >>>
>> >>>> Done in the attached patch.  I've also avoided dealing with
>> >>>> zero-length arrays and added tests to make sure their size
>> >>>> stays is regardless of the form of their initializer and
>> >>>> the appropriate warnings are issued.
>> >>>>
>> >>>> Using build_string() rather than build_string_literal() needed
>> >>>> a tweak in digest_init_r().  It didn't break anything but since
>> >>>> the array type may not have a domain yet, neither will the
>> >>>> string.  It looks like that may get adjusted later on but I've
>> >>>> temporarily guarded the code with #if 1.  If the change is
>> >>>> fine I'll remove the #if before committing.
>> >>>>
>> >>>> This initial patch only handles narrow character initializers
>> >>>> (i.e., those with TYPE_STRING_FLAG set).  Once this gets some
>> >>>> exposure I'd like to extend it to other character types,
>> >>>> including wchar_t.
>> >>>
>> >>> Hi Martin,
>> >>>
>> >>> This causes issues for the AArch64 tests (full list below).
>> >>>
>> >>> I see an error message on the following construct:
>> >>>
>> >>>   void foo (void)
>> >>>   {
>> >>>     __Poly8_t x[4] = { 1, 2, 3, 4 };
>> >>>   }
>> >>>
>> >>>   init.c:3:20: error: array of inappropriate type initialized
>from
>> >>> string constant
>> >>>   3 |   __Poly8_t x[4] = { 1, 2, 3, 4 };
>> >>>     |
>> >>>
>> >>> __Poly8_t is a type we define in our backend, through a
>convoluted
>> >>> set of
>> >>> functions, which operates a lot like an unsigned, QI mode type.
>> >>
>> >> I see the error with my aarch64 cross-compiler .  The new code
>> >> that does the conversion of array initializers to STRING_CSTs
>> >> looks for the TYPE_STRING_FLAG() to be set on the type of
>> >> the array elements.  Perhaps __Poly8_t should not have the flag
>> >> set?  (If it needs it then I think we'd have to only consider
>> >> named character types.)
>> >
>> > The change below gets rid of the compilation error.  I don't
>> > know if it's appropriate for the aarch64 back end:
>> >
>> > Index: gcc/config/aarch64/aarch64-builtins.c
>> > ===================================================================
>> > --- gcc/config/aarch64/aarch64-builtins.c    (revision 263537)
>> > +++ gcc/config/aarch64/aarch64-builtins.c    (working copy)
>> > @@ -643,6 +643,7 @@ aarch64_init_simd_builtin_types (void)
>> >    /* Poly types are a world of their own.  */
>> >    aarch64_simd_types[Poly8_t].eltype =
>aarch64_simd_types[Poly8_t].itype =
>> >      build_distinct_type_copy (unsigned_intQI_type_node);
>> > +  TYPE_STRING_FLAG (aarch64_simd_types[Poly8_t].eltype) = false;
>> >    aarch64_simd_types[Poly16_t].eltype =
>> > aarch64_simd_types[Poly16_t].itype =
>> >      build_distinct_type_copy (unsigned_intHI_type_node);
>> >    aarch64_simd_types[Poly64_t].eltype =
>> > aarch64_simd_types[Poly64_t].itype =
>
>This fix seems correct to me, the poly types are not strings. Looking
>at
>other uses of TYPE_STRING_FLAG this change doesn't seem like it would
>have
>impact on parsing or code generation.
>
>OK for trunk.
>
>> >>> A second set of tests fail due to changed inlining behaviour for
>> >>> functions
>> >>> with char array initialization:
>> >>>
>> >>>   gcc.target/aarch64/vset_lane_1.c
>> >>>   gcc.target/aarch64/vneg_s.c
>> >>>   gcc.target/aarch64/vclz.c
>> >>
>> >> I'm not sure what's going on here.  The tests are very big and
>> >> take forever to compile with an aarch64 cross-compiler, and I'm
>> >> not sure what to look for.  Can you provide a smaller test case
>> >> that shows the issue?
>> 
>> I wonder if these changes might be due to the same problem:
>> the tests define and initialize arrays of the Int8x16_t type
>> which is initialized to intQI_type_node, i.e., the signed
>> form of Poly8_t.  Does the conversion to STRING_CST cause
>> a performance degradation or is it just that the tests end
>> up with equivalent but slightly different assembly?
>
>These tests aren't looking at performance, just expecting to see
>certain
>instructions emitted. The only change is that now the int8x16_t forms
>are
>inlined (so the scan-assembler-times fails with two matches, one
>expected,
>one in the inlined function body copy).
>
>The difference seems to be in the initialization cost of the input data
>set.
>
>Before your patch:
>
>  int8_tD.3359 test_set0D.21541[8];
>  int8_tD.3359 answ_set0D.21542[8];
>
>      test_set0D.21541[0] = 0;
>      test_set0D.21541[1] = 1;
>      test_set0D.21541[2] = -1;
>      test_set0D.21541[3] = 10;
>      test_set0D.21541[4] = -10;
>      test_set0D.21541[5] = 0;
>      test_set0D.21541[6] = 127;
>      test_set0D.21541[7] = -128;
>      answ_set0D.21542[0] = 0;
>      answ_set0D.21542[1] = -1;
>      answ_set0D.21542[2] = 1;
>      answ_set0D.21542[3] = -10;
>      answ_set0D.21542[4] = 10;
>      answ_set0D.21542[5] = 0;
>      answ_set0D.21542[6] = -127;
>      answ_set0D.21542[7] = -128;
>
>After your patch:
>
>  int8_tD.3357 test_set0D.21539[8];
>  int8_tD.3357 answ_set0D.21540[8];
>
>      test_set0D.21539 = "";
>      answ_set0D.21540 = "";

Can we fix printing of string literals to include non-printable chars please? The above looks like wrong-code though it probably isn't. When Martin L. proposed a similar patch I was suggesting to restrict conversion to initializes with only printable characters. 

>I think that is probably what you expected to happen; but the impact on
>inlining might not have been.

It's more the effect of changed gimplification that shows, the inlining is a 2nd order effect. 

Richard. 

 Probably, we want to just change these
>tests
>to explicitly disable inlining. The tests appear to execute correctly.
>
>The print in the dump file is a bit unusual; presumably the impact of
>having
>non-printing characters in my initializer list - but less helpful
>output for
>it.
>
>Off topic; these tests are quick to copmpile on my cross and native
>compilers. Do you have additional checking enabled?
>
>Thanks,
>James
>
>> 
>> The tests also use int8_t and uint8_t for the expected results.
>> Those are typedefs for signed and unsigned char, respectively.
>> Is the conversion to strings for those fine?
>> 
>> Martin
Martin Sebor Aug. 15, 2018, 3:51 p.m. UTC | #23
On 08/15/2018 04:28 AM, James Greenhalgh wrote:
> On Tue, Aug 14, 2018 at 09:34:08PM -0500, Martin Sebor wrote:
>> On 08/14/2018 09:24 AM, Martin Sebor wrote:
>>> On 08/14/2018 09:08 AM, Martin Sebor wrote:
>>>> On 08/14/2018 07:27 AM, James Greenhalgh wrote:
>>>>> On Wed, Aug 08, 2018 at 07:17:07PM -0500, Martin Sebor wrote:
>>>>>> On 08/08/2018 05:08 AM, Jason Merrill wrote:
>>>>>>> On Wed, Aug 8, 2018 at 9:04 AM, Martin Sebor <msebor@gmail.com> wrote:
>>>>>>>> On 08/07/2018 02:57 AM, Jason Merrill wrote:
>>>>>>>>>
>>>>>>>>> On Wed, Aug 1, 2018 at 12:49 AM, Martin Sebor <msebor@gmail.com>
>>>>>>>>> wrote:
>>>>>>>>>>
>>>>>>>>>> On 07/31/2018 07:38 AM, Jason Merrill wrote:
>>>>>
>>>>> <snip>
>>>>>
>>>>>> Done in the attached patch.  I've also avoided dealing with
>>>>>> zero-length arrays and added tests to make sure their size
>>>>>> stays is regardless of the form of their initializer and
>>>>>> the appropriate warnings are issued.
>>>>>>
>>>>>> Using build_string() rather than build_string_literal() needed
>>>>>> a tweak in digest_init_r().  It didn't break anything but since
>>>>>> the array type may not have a domain yet, neither will the
>>>>>> string.  It looks like that may get adjusted later on but I've
>>>>>> temporarily guarded the code with #if 1.  If the change is
>>>>>> fine I'll remove the #if before committing.
>>>>>>
>>>>>> This initial patch only handles narrow character initializers
>>>>>> (i.e., those with TYPE_STRING_FLAG set).  Once this gets some
>>>>>> exposure I'd like to extend it to other character types,
>>>>>> including wchar_t.
>>>>>
>>>>> Hi Martin,
>>>>>
>>>>> This causes issues for the AArch64 tests (full list below).
>>>>>
>>>>> I see an error message on the following construct:
>>>>>
>>>>>   void foo (void)
>>>>>   {
>>>>>     __Poly8_t x[4] = { 1, 2, 3, 4 };
>>>>>   }
>>>>>
>>>>>   init.c:3:20: error: array of inappropriate type initialized from
>>>>> string constant
>>>>>   3 |   __Poly8_t x[4] = { 1, 2, 3, 4 };
>>>>>     |
>>>>>
>>>>> __Poly8_t is a type we define in our backend, through a convoluted
>>>>> set of
>>>>> functions, which operates a lot like an unsigned, QI mode type.
>>>>
>>>> I see the error with my aarch64 cross-compiler .  The new code
>>>> that does the conversion of array initializers to STRING_CSTs
>>>> looks for the TYPE_STRING_FLAG() to be set on the type of
>>>> the array elements.  Perhaps __Poly8_t should not have the flag
>>>> set?  (If it needs it then I think we'd have to only consider
>>>> named character types.)
>>>
>>> The change below gets rid of the compilation error.  I don't
>>> know if it's appropriate for the aarch64 back end:
>>>
>>> Index: gcc/config/aarch64/aarch64-builtins.c
>>> ===================================================================
>>> --- gcc/config/aarch64/aarch64-builtins.c    (revision 263537)
>>> +++ gcc/config/aarch64/aarch64-builtins.c    (working copy)
>>> @@ -643,6 +643,7 @@ aarch64_init_simd_builtin_types (void)
>>>    /* Poly types are a world of their own.  */
>>>    aarch64_simd_types[Poly8_t].eltype = aarch64_simd_types[Poly8_t].itype =
>>>      build_distinct_type_copy (unsigned_intQI_type_node);
>>> +  TYPE_STRING_FLAG (aarch64_simd_types[Poly8_t].eltype) = false;
>>>    aarch64_simd_types[Poly16_t].eltype =
>>> aarch64_simd_types[Poly16_t].itype =
>>>      build_distinct_type_copy (unsigned_intHI_type_node);
>>>    aarch64_simd_types[Poly64_t].eltype =
>>> aarch64_simd_types[Poly64_t].itype =
>
> This fix seems correct to me, the poly types are not strings. Looking at
> other uses of TYPE_STRING_FLAG this change doesn't seem like it would have
> impact on parsing or code generation.
>
> OK for trunk.

I committed this in r263561.

>>>>> A second set of tests fail due to changed inlining behaviour for
>>>>> functions
>>>>> with char array initialization:
>>>>>
>>>>>   gcc.target/aarch64/vset_lane_1.c
>>>>>   gcc.target/aarch64/vneg_s.c
>>>>>   gcc.target/aarch64/vclz.c
>>>>
>>>> I'm not sure what's going on here.  The tests are very big and
>>>> take forever to compile with an aarch64 cross-compiler, and I'm
>>>> not sure what to look for.  Can you provide a smaller test case
>>>> that shows the issue?
>>
>> I wonder if these changes might be due to the same problem:
>> the tests define and initialize arrays of the Int8x16_t type
>> which is initialized to intQI_type_node, i.e., the signed
>> form of Poly8_t.  Does the conversion to STRING_CST cause
>> a performance degradation or is it just that the tests end
>> up with equivalent but slightly different assembly?
>
> These tests aren't looking at performance, just expecting to see certain
> instructions emitted. The only change is that now the int8x16_t forms are
> inlined (so the scan-assembler-times fails with two matches, one expected,
> one in the inlined function body copy).
>
> The difference seems to be in the initialization cost of the input data set.
>
> Before your patch:
>
>   int8_tD.3359 test_set0D.21541[8];
>   int8_tD.3359 answ_set0D.21542[8];
>
>       test_set0D.21541[0] = 0;
>       test_set0D.21541[1] = 1;
>       test_set0D.21541[2] = -1;
>       test_set0D.21541[3] = 10;
>       test_set0D.21541[4] = -10;
>       test_set0D.21541[5] = 0;
>       test_set0D.21541[6] = 127;
>       test_set0D.21541[7] = -128;
>       answ_set0D.21542[0] = 0;
>       answ_set0D.21542[1] = -1;
>       answ_set0D.21542[2] = 1;
>       answ_set0D.21542[3] = -10;
>       answ_set0D.21542[4] = 10;
>       answ_set0D.21542[5] = 0;
>       answ_set0D.21542[6] = -127;
>       answ_set0D.21542[7] = -128;
>
> After your patch:
>
>   int8_tD.3357 test_set0D.21539[8];
>   int8_tD.3357 answ_set0D.21540[8];
>
>       test_set0D.21539 = "";
>       answ_set0D.21540 = "";
>
> I think that is probably what you expected to happen; but the impact on
> inlining might not have been. Probably, we want to just change these tests
> to explicitly disable inlining. The tests appear to execute correctly.
>
> The print in the dump file is a bit unusual; presumably the impact of having
> non-printing characters in my initializer list - but less helpful output for
> it.

I agree it's less than helpful.  It's not the result of this
change.  The output is the same for string literals.  E.g., for
this:

   void f (void*, ...);

   void g (void)
   {
     char a[] = { 0, 1, 2, 3 };
     char b[] = "\000\001\002\003";
     f (a, b);
   }

we get the following on trunk:

   <bb 2> [local count: 1073741825]:
   a = "";
   b = "";
   f (&a, &b);

and the following with GCC 8:

   MEM[(char[4] *)&a] = 50462976;
   b = "";
   f (&a, &b);

I'll see if I can quickly tweak things to include all characters
in the output.

> Off topic; these tests are quick to copmpile on my cross and native
> compilers. Do you have additional checking enabled?

Yes, I did have --enable-checking=all set that I forgot about.
With it, gcc.target/aarch64/advsimd-intrinsics/vmax.c takes
2m 21sec to compile without optimization.  The
gcc.target/aarch64/vclz.c test takes 1m 45sec at -O3.

Removing --enable-checking=all reduced the compile times for
the two tests to just over a second.

Martin
Martin Sebor Aug. 15, 2018, 9:02 p.m. UTC | #24
On 08/15/2018 06:07 AM, Joseph Myers wrote:
> On Tue, 14 Aug 2018, Martin Sebor wrote:
>
>>> This is with Bison 3.0.4, should the version used to produce intl/plural.c
>>> prove relevant.
>>
>> Can you send me the translation unit and the options it was compiled
>> with that triggered the errors?
>
> I've attached plural.i.  The error is a static link error linking sln, but
> maybe comparing results of compiling plural.i before and after the changes
> may be enlightening (unless it's actually a difference in code elsewhere
> in glibc causing a link error reported in plural.o).
>
> Compiled with:
>
> alpha-glibc-linux-gnu-gcc
> /scratch/jmyers/glibc/many9/build/compilers/alpha-linux-gnu/glibc/alpha-linux-gnu/intl/plural.c
> -c -std=gnu11 -fgnu89-inline  -O2 -Wall -Werror -Wundef -Wwrite-strings
> -fmerge-all-constants -fno-stack-protector -frounding-math -g
> -Wstrict-prototypes -Wold-style-definition -fno-math-errno
> -mlong-double-128 -mieee -mfp-rounding-mode=d     -ftls-model=initial-exec
> -I../include
> -I/scratch/jmyers/glibc/many9/build/compilers/alpha-linux-gnu/glibc/alpha-linux-gnu/intl
> -I/scratch/jmyers/glibc/many9/build/compilers/alpha-linux-gnu/glibc/alpha-linux-gnu
> -I../sysdeps/unix/sysv/linux/alpha/alpha
> -I../sysdeps/unix/sysv/linux/alpha/fpu  -I../sysdeps/alpha/fpu
> -I../sysdeps/unix/sysv/linux/alpha  -I../sysdeps/alpha/nptl
> -I../sysdeps/unix/sysv/linux/wordsize-64  -I../sysdeps/ieee754/ldbl-64-128
> -I../sysdeps/ieee754/ldbl-opt  -I../sysdeps/unix/sysv/linux/include
> -I../sysdeps/unix/sysv/linux  -I../sysdeps/nptl  -I../sysdeps/pthread
> -I../sysdeps/gnu  -I../sysdeps/unix/inet  -I../sysdeps/unix/sysv
> -I../sysdeps/unix/alpha  -I../sysdeps/unix  -I../sysdeps/posix
> -I../sysdeps/alpha  -I../sysdeps/wordsize-64
> -I../sysdeps/ieee754/ldbl-128  -I../sysdeps/ieee754/dbl-64/wordsize-64
> -I../sysdeps/ieee754/dbl-64  -I../sysdeps/ieee754/flt-32
> -I../sysdeps/ieee754  -I../sysdeps/generic  -I.. -I../libio -I.
> -D_LIBC_REENTRANT -include
> /scratch/jmyers/glibc/many9/build/compilers/alpha-linux-gnu/glibc/alpha-linux-gnu/libc-modules.h
> -DMODULE_NAME=libc -include ../include/libc-symbols.h
> -DTOP_NAMESPACE=glibc -D'LOCALEDIR="/usr/share/locale"'
> -D'LOCALE_ALIAS_PATH="/usr/share/locale"' -o
> /scratch/jmyers/glibc/many9/build/compilers/alpha-linux-gnu/glibc/alpha-linux-gnu/intl/plural.o
> -MD -MP -MF
> /scratch/jmyers/glibc/many9/build/compilers/alpha-linux-gnu/glibc/alpha-linux-gnu/intl/plural.o.dt
> -MT
> /scratch/jmyers/glibc/many9/build/compilers/alpha-linux-gnu/glibc/alpha-linux-gnu/intl/plural.o
>

Thanks.  I don't see anything obviously wrong but I don't know
much about Alpha assembly.  Attached are the two .s files, with
(plural-new.s) and without (plural-old.s) the array-to-string
transformation.

There are also only a handful of transformed arrays in the file
and they all look reasonable to me (see the attachment named
plural-array-to-string.txt).  The only arrays in the .sdata
section are yydefgoto and yypgoto, both before and after.
They are each just 3 bytes in size.

There is one unusual difference in the loads of one of them in
the assembly emitted by GCC for __gettextparse.

Before:

	ldah $22,yypgoto($29)				!gprelhigh
	...
	lda $2,yypgoto($22)				!gprellow

After:

	ldah $2,yypgoto+2305843009213693936($29)	!gprelhigh
	...
	lda $2,yypgoto+2305843009213693936($2)		!gprellow

I don't know if it's significant -- the lda instruction uses
just the least significant 16 bits of the constant displacement,
shifted left by 16.  I don't see any obviously bogus constants
in the disassembly produced by objdump.

I'll need some help from someone who knows more about Alpha
to understand what's going on.

Martin
plural-old.o:     file format elf64-alpha


Disassembly of section .text:

0000000000000000 <__gettext_free_exp>:
   0:	00 00 bb 27 	ldah	gp,0(t12)
   4:	00 00 bd 23 	lda	gp,0(gp)
   8:	f0 ff de 23 	lda	sp,-16(sp)
   c:	08 00 3e b5 	stq	s0,8(sp)
  10:	09 04 f0 47 	mov	a0,s0
  14:	00 00 5e b7 	stq	ra,0(sp)
  18:	11 00 00 e6 	beq	a0,60 <__gettext_free_exp+0x60>
  1c:	00 00 30 a0 	ldl	t0,0(a0)
  20:	a2 5d 20 40 	cmple	t0,0x2,t1
  24:	12 00 40 e4 	beq	t1,70 <__gettext_free_exp+0x70>
  28:	a2 55 20 40 	cmpeq	t0,0x2,t1
  2c:	17 00 40 f4 	bne	t1,8c <__gettext_free_exp+0x8c>
  30:	a1 35 20 40 	cmpeq	t0,0x1,t0
  34:	05 00 20 e4 	beq	t0,4c <__gettext_free_exp+0x4c>
  38:	08 00 09 a6 	ldq	a0,8(s0)
  3c:	00 00 7d a7 	ldq	t12,0(gp)
  40:	00 40 5b 6b 	jsr	ra,(t12),44 <__gettext_free_exp+0x44>
  44:	00 00 ba 27 	ldah	gp,0(ra)
  48:	00 00 bd 23 	lda	gp,0(gp)
  4c:	10 04 e9 47 	mov	s0,a0
  50:	00 00 7d a7 	ldq	t12,0(gp)
  54:	00 40 5b 6b 	jsr	ra,(t12),58 <__gettext_free_exp+0x58>
  58:	00 00 ba 27 	ldah	gp,0(ra)
  5c:	00 00 bd 23 	lda	gp,0(gp)
  60:	00 00 5e a7 	ldq	ra,0(sp)
  64:	08 00 3e a5 	ldq	s0,8(sp)
  68:	10 00 de 23 	lda	sp,16(sp)
  6c:	01 80 fa 6b 	ret
  70:	a1 75 20 40 	cmpeq	t0,0x3,t0
  74:	f5 ff 3f e4 	beq	t0,4c <__gettext_free_exp+0x4c>
  78:	18 00 10 a6 	ldq	a0,24(a0)
  7c:	00 00 7d a7 	ldq	t12,0(gp)
  80:	00 40 5b 6b 	jsr	ra,(t12),84 <__gettext_free_exp+0x84>
  84:	00 00 ba 27 	ldah	gp,0(ra)
  88:	00 00 bd 23 	lda	gp,0(gp)
  8c:	10 00 09 a6 	ldq	a0,16(s0)
  90:	00 00 7d a7 	ldq	t12,0(gp)
  94:	00 40 5b 6b 	jsr	ra,(t12),98 <__gettext_free_exp+0x98>
  98:	00 00 ba 27 	ldah	gp,0(ra)
  9c:	00 00 bd 23 	lda	gp,0(gp)
  a0:	e5 ff ff c3 	br	38 <__gettext_free_exp+0x38>
  a4:	00 00 fe 2f 	unop	
  a8:	1f 04 ff 47 	nop	
  ac:	00 00 fe 2f 	unop	

00000000000000b0 <new_exp>:
  b0:	00 00 bb 27 	ldah	gp,0(t12)
  b4:	00 00 bd 23 	lda	gp,0(gp)
  b8:	d0 ff de 23 	lda	sp,-48(sp)
  bc:	08 00 3e b5 	stq	s0,8(sp)
  c0:	29 31 00 42 	subl	a0,0x1,s0
  c4:	10 00 5e b5 	stq	s1,16(sp)
  c8:	01 00 29 20 	lda	t0,1(s0)
  cc:	18 00 7e b5 	stq	s2,24(sp)
  d0:	0a 04 f2 47 	mov	a2,s1
  d4:	20 00 9e b5 	stq	s3,32(sp)
  d8:	0b 04 f0 47 	mov	a0,s2
  dc:	00 00 5e b7 	stq	ra,0(sp)
  e0:	0c 04 f1 47 	mov	a1,s3
  e4:	35 00 20 e4 	beq	t0,1bc <new_exp+0x10c>
  e8:	01 04 e9 47 	mov	s0,t0
  ec:	01 00 e0 c3 	br	f4 <new_exp+0x44>
  f0:	1b 00 40 e4 	beq	t1,160 <new_exp+0xb0>
  f4:	43 06 2a 40 	s8addq	t0,s1,t2
  f8:	ff ff 21 20 	lda	t0,-1(t0)
  fc:	02 00 e1 43 	sextl	t0,t1
 100:	00 00 63 a4 	ldq	t2,0(t2)
 104:	01 00 42 20 	lda	t1,1(t1)
 108:	f9 ff 7f f4 	bne	t2,f0 <new_exp+0x40>
 10c:	00 00 fe 2f 	unop	
 110:	41 06 2a 41 	s8addq	s0,s1,t0
 114:	ff ff 29 21 	lda	s0,-1(s0)
 118:	00 00 01 a6 	ldq	a0,0(t0)
 11c:	00 00 7d a7 	ldq	t12,0(gp)
 120:	00 40 5b 6b 	jsr	ra,(t12),124 <new_exp+0x74>
 124:	00 00 ba 27 	ldah	gp,0(ra)
 128:	00 00 bd 23 	lda	gp,0(gp)
 12c:	01 00 e9 43 	sextl	s0,t0
 130:	01 00 21 20 	lda	t0,1(t0)
 134:	f6 ff 3f f4 	bne	t0,110 <new_exp+0x60>
 138:	00 00 5e a7 	ldq	ra,0(sp)
 13c:	08 00 3e a5 	ldq	s0,8(sp)
 140:	10 00 5e a5 	ldq	s1,16(sp)
 144:	18 00 7e a5 	ldq	s2,24(sp)
 148:	00 04 ff 47 	clr	v0
 14c:	20 00 9e a5 	ldq	s3,32(sp)
 150:	30 00 de 23 	lda	sp,48(sp)
 154:	01 80 fa 6b 	ret
 158:	1f 04 ff 47 	nop	
 15c:	00 00 fe 2f 	unop	
 160:	20 00 1f 22 	lda	a0,32
 164:	00 00 7d a7 	ldq	t12,0(gp)
 168:	00 40 5b 6b 	jsr	ra,(t12),16c <new_exp+0xbc>
 16c:	00 00 ba 27 	ldah	gp,0(ra)
 170:	00 00 bd 23 	lda	gp,0(gp)
 174:	e6 ff 1f e4 	beq	v0,110 <new_exp+0x60>
 178:	00 00 60 b1 	stl	s2,0(v0)
 17c:	04 00 80 b1 	stl	s3,4(v0)
 180:	41 06 2a 41 	s8addq	s0,s1,t0
 184:	42 06 20 41 	s8addq	s0,v0,t1
 188:	ff ff 29 21 	lda	s0,-1(s0)
 18c:	00 00 61 a4 	ldq	t2,0(t0)
 190:	01 00 e9 43 	sextl	s0,t0
 194:	01 00 21 20 	lda	t0,1(t0)
 198:	08 00 62 b4 	stq	t2,8(t1)
 19c:	f8 ff 3f f4 	bne	t0,180 <new_exp+0xd0>
 1a0:	00 00 5e a7 	ldq	ra,0(sp)
 1a4:	08 00 3e a5 	ldq	s0,8(sp)
 1a8:	10 00 5e a5 	ldq	s1,16(sp)
 1ac:	18 00 7e a5 	ldq	s2,24(sp)
 1b0:	20 00 9e a5 	ldq	s3,32(sp)
 1b4:	30 00 de 23 	lda	sp,48(sp)
 1b8:	01 80 fa 6b 	ret
 1bc:	20 00 1f 22 	lda	a0,32
 1c0:	00 00 7d a7 	ldq	t12,0(gp)
 1c4:	00 40 5b 6b 	jsr	ra,(t12),1c8 <new_exp+0x118>
 1c8:	00 00 ba 27 	ldah	gp,0(ra)
 1cc:	00 00 bd 23 	lda	gp,0(gp)
 1d0:	d9 ff 1f e4 	beq	v0,138 <new_exp+0x88>
 1d4:	04 00 80 b1 	stl	s3,4(v0)
 1d8:	00 00 5e a7 	ldq	ra,0(sp)
 1dc:	08 00 3e a5 	ldq	s0,8(sp)
 1e0:	10 00 5e a5 	ldq	s1,16(sp)
 1e4:	18 00 7e a5 	ldq	s2,24(sp)
 1e8:	20 00 9e a5 	ldq	s3,32(sp)
 1ec:	00 00 e0 b3 	stl	zero,0(v0)
 1f0:	30 00 de 23 	lda	sp,48(sp)
 1f4:	01 80 fa 6b 	ret
 1f8:	1f 04 ff 47 	nop	
 1fc:	00 00 fe 2f 	unop	

0000000000000200 <__gettextparse>:
 200:	00 00 bb 27 	ldah	gp,0(t12)
 204:	00 00 bd 23 	lda	gp,0(gp)
 208:	90 f7 de 23 	lda	sp,-2160(sp)
 20c:	00 00 9d 24 	ldah	t3,0(gp)
 210:	80 06 3e a0 	ldl	t0,1664(sp)
 214:	08 00 3e b5 	stq	s0,8(sp)
 218:	80 06 3e 21 	lda	s0,1664(sp)
 21c:	10 00 5e b5 	stq	s1,16(sp)
 220:	40 00 5e 21 	lda	s1,64(sp)
 224:	21 96 3f 48 	zapnot	t0,0xfc,t0
 228:	20 00 9e b5 	stq	s3,32(sp)
 22c:	00 00 9d 25 	ldah	s3,0(gp)
 230:	18 00 7e b5 	stq	s2,24(sp)
 234:	28 00 be b5 	stq	s4,40(sp)
 238:	fe ff bf 20 	lda	t4,-2
 23c:	38 00 fe b5 	stq	fp,56(sp)
 240:	c8 00 7f 21 	lda	s2,200
 244:	80 06 3e b0 	stl	t0,1664(sp)
 248:	0f 04 ea 47 	mov	s1,fp
 24c:	01 04 ff 47 	clr	t0
 250:	00 00 5e b7 	stq	ra,0(sp)
 254:	0d 04 e9 47 	mov	s0,s4
 258:	30 00 de b5 	stq	s5,48(sp)
 25c:	00 00 84 20 	lda	t3,0(t3)
 260:	40 08 1e b6 	stq	a0,2112(sp)
 264:	00 00 8c 21 	lda	s3,0(s3)
 268:	38 08 fe b7 	stq	zero,2104(sp)
 26c:	30 08 3e b5 	stq	s0,2096(sp)
 270:	02 04 81 40 	addq	t3,t0,t1
 274:	01 00 c2 20 	lda	t5,1(t1)
 278:	00 00 e2 2c 	ldq_u	t6,0(t1)
 27c:	47 0f e6 48 	extqh	t6,t5,t6
 280:	87 17 e7 48 	sra	t6,0x38,t6
 284:	0a 00 47 20 	lda	t1,10(t6)
 288:	1d 00 40 e4 	beq	t1,300 <__gettextparse+0x100>
 28c:	02 00 45 20 	lda	t1,2(t4)
 290:	17 01 40 e4 	beq	t1,6f0 <__gettextparse+0x4f0>
 294:	86 00 a0 ec 	ble	t4,4b0 <__gettextparse+0x2b0>
 298:	00 00 5d 24 	ldah	t1,0(gp)
 29c:	00 00 42 20 	lda	t1,0(t1)
 2a0:	02 04 a2 40 	addq	t4,t1,t1
 2a4:	00 00 02 2d 	ldq_u	t7,0(t1)
 2a8:	c8 00 02 49 	extbl	t7,t1,t7
 2ac:	07 00 e8 40 	addl	t6,t7,t6
 2b0:	26 f6 e1 48 	zapnot	t6,0xf,t5
 2b4:	a6 d7 c6 40 	cmpule	t5,0x36,t5
 2b8:	11 00 c0 e4 	beq	t5,300 <__gettextparse+0x100>
 2bc:	06 04 ec 40 	addq	t6,s3,t5
 2c0:	01 00 c6 22 	lda	t8,1(t5)
 2c4:	00 00 46 2c 	ldq_u	t1,0(t5)
 2c8:	42 0f 56 48 	extqh	t1,t8,t1
 2cc:	82 17 47 48 	sra	t1,0x38,t1
 2d0:	a2 05 48 40 	cmpeq	t1,t7,t1
 2d4:	0a 00 40 e4 	beq	t1,300 <__gettextparse+0x100>
 2d8:	00 00 3d 24 	ldah	t0,0(gp)
 2dc:	00 00 21 20 	lda	t0,0(t0)
 2e0:	07 04 e1 40 	addq	t6,t0,t6
 2e4:	00 00 27 2c 	ldq_u	t0,0(t6)
 2e8:	c1 00 27 48 	extbl	t0,t6,t0
 2ec:	20 01 20 f4 	bne	t0,770 <__gettextparse+0x570>
 2f0:	08 04 ea 47 	mov	s1,t7
 2f4:	08 00 0a a4 	ldq	v0,8(s1)
 2f8:	f0 ff ff 20 	lda	t6,-16
 2fc:	8d 00 e0 c3 	br	534 <__gettextparse+0x334>
 300:	00 00 5d 24 	ldah	t1,0(gp)
 304:	00 00 42 20 	lda	t1,0(t1)
 308:	02 04 22 40 	addq	t0,t1,t1
 30c:	00 00 c2 2c 	ldq_u	t5,0(t1)
 310:	c2 00 c2 48 	extbl	t5,t1,t1
 314:	08 00 e2 43 	sextl	t1,t7
 318:	45 00 40 f4 	bne	t1,430 <__gettextparse+0x230>
 31c:	38 08 5e a4 	ldq	t1,2104(sp)
 320:	ae 75 40 40 	cmpeq	t1,0x3,s5
 324:	16 00 c0 e5 	beq	s5,380 <__gettextparse+0x180>
 328:	1d 01 a0 fc 	bgt	t4,7a0 <__gettextparse+0x5a0>
 32c:	14 00 a0 f4 	bne	t4,380 <__gettextparse+0x180>
 330:	09 04 ed 47 	mov	s4,s0
 334:	01 00 5f 21 	lda	s1,1
 338:	27 00 e0 c3 	br	3d8 <__gettextparse+0x1d8>
 33c:	00 00 fe 2f 	unop	
 340:	00 00 5d 24 	ldah	t1,0(gp)
 344:	00 00 42 20 	lda	t1,0(t1)
 348:	01 04 22 40 	addq	t0,t1,t0
 34c:	00 00 41 2c 	ldq_u	t1,0(t0)
 350:	c1 00 41 48 	extbl	t1,t0,t0
 354:	9d 01 20 f4 	bne	t0,9cc <__gettextparse+0x7cc>
 358:	1f 04 ff 47 	nop	
 35c:	00 00 fe 2f 	unop	
 360:	a1 05 2d 41 	cmpeq	s0,s4,t0
 364:	1b 00 20 f4 	bne	t0,3d4 <__gettextparse+0x1d4>
 368:	fe ff 29 21 	lda	s0,-2(s0)
 36c:	02 00 49 20 	lda	t1,2(s0)
 370:	f8 ff 4a 21 	lda	s1,-8(s1)
 374:	00 00 29 2c 	ldq_u	t0,0(s0)
 378:	41 0f 22 48 	extqh	t0,t1,t0
 37c:	81 17 26 48 	sra	t0,0x30,t0
 380:	01 04 81 40 	addq	t3,t0,t0
 384:	01 00 41 20 	lda	t1,1(t0)
 388:	00 00 21 2c 	ldq_u	t0,0(t0)
 38c:	41 0f 22 48 	extqh	t0,t1,t0
 390:	81 17 27 48 	sra	t0,0x38,t0
 394:	0a 00 41 20 	lda	t1,10(t0)
 398:	f1 ff 5f e4 	beq	t1,360 <__gettextparse+0x160>
 39c:	01 30 20 40 	addl	t0,0x1,t0
 3a0:	22 f6 21 48 	zapnot	t0,0xf,t1
 3a4:	01 00 e1 43 	sextl	t0,t0
 3a8:	a2 d7 46 40 	cmpule	t1,0x36,t1
 3ac:	ec ff 5f e4 	beq	t1,360 <__gettextparse+0x160>
 3b0:	06 04 2c 40 	addq	t0,s3,t5
 3b4:	01 00 e6 20 	lda	t6,1(t5)
 3b8:	00 00 46 2c 	ldq_u	t1,0(t5)
 3bc:	42 0f 47 48 	extqh	t1,t6,t1
 3c0:	82 17 47 48 	sra	t1,0x38,t1
 3c4:	a2 35 40 40 	cmpeq	t1,0x1,t1
 3c8:	dd ff 5f f4 	bne	t1,340 <__gettextparse+0x140>
 3cc:	a1 05 2d 41 	cmpeq	s0,s4,t0
 3d0:	e5 ff 3f e4 	beq	t0,368 <__gettextparse+0x168>
 3d4:	01 00 5f 21 	lda	s1,1
 3d8:	30 08 7e a4 	ldq	t2,2096(sp)
 3dc:	a1 05 23 41 	cmpeq	s0,t2,t0
 3e0:	05 00 20 f4 	bne	t0,3f8 <__gettextparse+0x1f8>
 3e4:	10 04 e9 47 	mov	s0,a0
 3e8:	00 00 7d a7 	ldq	t12,0(gp)
 3ec:	00 40 5b 6b 	jsr	ra,(t12),3f0 <__gettextparse+0x1f0>
 3f0:	00 00 ba 27 	ldah	gp,0(ra)
 3f4:	00 00 bd 23 	lda	gp,0(gp)
 3f8:	00 04 ea 47 	mov	s1,v0
 3fc:	00 00 5e a7 	ldq	ra,0(sp)
 400:	08 00 3e a5 	ldq	s0,8(sp)
 404:	10 00 5e a5 	ldq	s1,16(sp)
 408:	18 00 7e a5 	ldq	s2,24(sp)
 40c:	20 00 9e a5 	ldq	s3,32(sp)
 410:	28 00 be a5 	ldq	s4,40(sp)
 414:	30 00 de a5 	ldq	s5,48(sp)
 418:	38 00 fe a5 	ldq	fp,56(sp)
 41c:	70 08 de 23 	lda	sp,2160(sp)
 420:	01 80 fa 6b 	ret
 424:	00 00 fe 2f 	unop	
 428:	1f 04 ff 47 	nop	
 42c:	00 00 fe 2f 	unop	
 430:	00 00 3d 24 	ldah	t0,0(gp)
 434:	00 00 21 20 	lda	t0,0(t0)
 438:	01 04 01 41 	addq	t7,t0,t0
 43c:	a7 b7 41 40 	cmpule	t1,0xd,t6
 440:	00 00 c1 2c 	ldq_u	t5,0(t0)
 444:	c1 00 c1 48 	extbl	t5,t0,t0
 448:	01 00 df 20 	lda	t5,1
 44c:	26 01 c1 40 	subl	t5,t0,t5
 450:	46 06 ca 40 	s8addq	t5,s1,t5
 454:	00 00 06 a4 	ldq	v0,0(t5)
 458:	19 00 e0 f4 	bne	t6,4c0 <__gettextparse+0x2c0>
 45c:	00 00 5d 24 	ldah	t1,0(gp)
 460:	00 00 42 20 	lda	t1,0(t1)
 464:	02 04 02 41 	addq	t7,t1,t1
 468:	00 00 dd 26 	ldah	t8,0(gp)
 46c:	48 16 20 40 	s8addq	t0,0,t7
 470:	00 00 e2 2c 	ldq_u	t6,0(t1)
 474:	01 04 21 40 	addq	t0,t0,t0
 478:	29 05 21 41 	subq	s0,t0,s0
 47c:	c2 00 e2 48 	extbl	t6,t1,t1
 480:	28 05 48 41 	subq	s1,t7,t7
 484:	27 11 42 40 	subl	t1,0x10,t6
 488:	00 00 56 20 	lda	t1,0(t8)
 48c:	02 04 e2 40 	addq	t6,t1,t1
 490:	01 00 c2 20 	lda	t5,1(t1)
 494:	00 00 22 2c 	ldq_u	t0,0(t1)
 498:	41 0f 26 48 	extqh	t0,t5,t0
 49c:	81 17 27 48 	sra	t0,0x38,t0
 4a0:	24 00 e0 c3 	br	534 <__gettextparse+0x334>
 4a4:	00 00 fe 2f 	unop	
 4a8:	1f 04 ff 47 	nop	
 4ac:	00 00 fe 2f 	unop	
 4b0:	08 04 ff 47 	clr	t7
 4b4:	05 04 ff 47 	clr	t4
 4b8:	7d ff ff c3 	br	2b0 <__gettextparse+0xb0>
 4bc:	00 00 fe 2f 	unop	
 4c0:	00 00 dd 24 	ldah	t5,0(gp)
 4c4:	00 00 c6 20 	lda	t5,0(t5)
 4c8:	42 04 46 40 	s4addq	t1,t5,t1
 4cc:	00 00 42 a0 	ldl	t1,0(t1)
 4d0:	02 04 a2 43 	addq	gp,t1,t1
 4d4:	00 00 e2 6b 	jmp	(t1)
 4d8:	1f 04 ff 47 	nop	
 4dc:	00 00 fe 2f 	unop	
 4e0:	10 08 5e 22 	lda	a2,2064(sp)
 4e4:	f8 ff 2a a2 	ldl	a1,-8(s1)
 4e8:	00 00 4a a4 	ldq	t1,0(s1)
 4ec:	f0 ff 2a a4 	ldq	t0,-16(s1)
 4f0:	10 08 3e b4 	stq	t0,2064(sp)
 4f4:	02 00 1f 22 	lda	a0,2
 4f8:	ff ff 3f 20 	lda	t0,-1
 4fc:	68 08 9e b4 	stq	t3,2152(sp)
 500:	58 08 3e b4 	stq	t0,2136(sp)
 504:	fa ff 29 21 	lda	s0,-6(s0)
 508:	60 08 be b4 	stq	t4,2144(sp)
 50c:	18 08 5e b4 	stq	t1,2072(sp)
 510:	00 00 7d a7 	ldq	t12,0(gp)
 514:	00 40 5b 6b 	jsr	ra,(t12),518 <__gettextparse+0x318>
 518:	00 00 ba 27 	ldah	gp,0(ra)
 51c:	00 00 bd 23 	lda	gp,0(gp)
 520:	e8 ff 0a 21 	lda	t7,-24(s1)
 524:	58 08 3e a4 	ldq	t0,2136(sp)
 528:	02 00 ff 20 	lda	t6,2
 52c:	68 08 9e a4 	ldq	t3,2152(sp)
 530:	60 08 be a4 	ldq	t4,2144(sp)
 534:	08 00 08 b4 	stq	v0,8(t7)
 538:	02 00 49 20 	lda	t1,2(s0)
 53c:	08 00 48 21 	lda	s1,8(t7)
 540:	00 00 c9 2c 	ldq_u	t5,0(s0)
 544:	46 0f c2 48 	extqh	t5,t1,t5
 548:	86 17 c6 48 	sra	t5,0x30,t5
 54c:	01 00 c1 40 	addl	t5,t0,t0
 550:	28 f6 21 48 	zapnot	t0,0xf,t7
 554:	01 00 e1 43 	sextl	t0,t0
 558:	a8 d7 06 41 	cmpule	t7,0x36,t7
 55c:	07 00 00 e5 	beq	t7,57c <__gettextparse+0x37c>
 560:	16 04 2c 40 	addq	t0,s3,t8
 564:	01 00 f6 22 	lda	t9,1(t8)
 568:	00 00 16 2d 	ldq_u	t7,0(t8)
 56c:	48 0f 17 49 	extqh	t7,t9,t7
 570:	88 17 07 49 	sra	t7,0x38,t7
 574:	a6 05 06 41 	cmpeq	t7,t5,t5
 578:	8d 00 c0 f4 	bne	t5,7b0 <__gettextparse+0x5b0>
 57c:	00 00 dd 24 	ldah	t5,0(gp)
 580:	00 00 c6 20 	lda	t5,0(t5)
 584:	06 04 e6 40 	addq	t6,t5,t5
 588:	01 00 e6 20 	lda	t6,1(t5)
 58c:	00 00 26 2c 	ldq_u	t0,0(t5)
 590:	41 0f 27 48 	extqh	t0,t6,t0
 594:	81 17 27 48 	sra	t0,0x38,t0
 598:	16 04 6b 41 	addq	s2,s2,t8
 59c:	02 00 09 2d 	ldq_u	t7,2(s0)
 5a0:	67 03 22 48 	inswl	t0,t1,t6
 5a4:	fe ff d6 20 	lda	t5,-2(t8)
 5a8:	48 02 02 49 	mskwl	t7,t1,t7
 5ac:	06 04 a6 41 	addq	s4,t5,t5
 5b0:	07 04 e8 44 	or	t6,t7,t6
 5b4:	02 00 e9 3c 	stq_u	t6,2(s0)
 5b8:	a6 03 46 40 	cmpult	t1,t5,t5
 5bc:	09 04 e2 47 	mov	t1,s0
 5c0:	44 00 c0 f4 	bne	t5,6d4 <__gettextparse+0x4d4>
 5c4:	2a 05 4d 40 	subq	t1,s4,s1
 5c8:	8a 37 40 49 	sra	s1,0x1,s1
 5cc:	0f 27 df 20 	lda	t5,9999
 5d0:	ab 07 66 41 	cmpule	s2,t5,s2
 5d4:	01 00 4a 21 	lda	s1,1(s1)
 5d8:	b2 01 60 e5 	beq	s2,ca4 <__gettextparse+0xaa4>
 5dc:	10 27 5f 20 	lda	t1,10000
 5e0:	00 00 7d a7 	ldq	t12,0(gp)
 5e4:	ab 03 c2 42 	cmpult	t8,t1,s2
 5e8:	58 08 3e b4 	stq	t0,2136(sp)
 5ec:	68 08 9e b4 	stq	t3,2152(sp)
 5f0:	c2 04 76 45 	cmovne	s2,t8,t1
 5f4:	60 08 be b4 	stq	t4,2144(sp)
 5f8:	50 04 42 40 	s4addq	t1,t1,a0
 5fc:	10 04 10 42 	addq	a0,a0,a0
 600:	07 00 10 22 	lda	a0,7(a0)
 604:	0b 04 e2 47 	mov	t1,s2
 608:	00 40 5b 6b 	jsr	ra,(t12),60c <__gettextparse+0x40c>
 60c:	00 00 ba 27 	ldah	gp,0(ra)
 610:	00 00 bd 23 	lda	gp,0(gp)
 614:	0e 04 e0 47 	mov	v0,s5
 618:	a2 01 00 e4 	beq	v0,ca4 <__gettextparse+0xaa4>
 61c:	09 04 4a 41 	addq	s1,s1,s0
 620:	00 00 7d a7 	ldq	t12,0(gp)
 624:	12 04 e9 47 	mov	s0,a2
 628:	11 04 ed 47 	mov	s4,a1
 62c:	10 04 e0 47 	mov	v0,a0
 630:	00 40 5b 6b 	jsr	ra,(t12),634 <__gettextparse+0x434>
 634:	00 00 ba 27 	ldah	gp,0(ra)
 638:	4a 16 40 41 	s8addq	s1,0,s1
 63c:	06 04 6b 41 	addq	s2,s2,t5
 640:	00 00 bd 23 	lda	gp,0(gp)
 644:	06 04 c6 41 	addq	s5,t5,t5
 648:	11 04 ef 47 	mov	fp,a1
 64c:	00 00 7d a7 	ldq	t12,0(gp)
 650:	10 04 e6 47 	mov	t5,a0
 654:	12 04 ea 47 	mov	s1,a2
 658:	00 40 5b 6b 	jsr	ra,(t12),65c <__gettextparse+0x45c>
 65c:	00 00 ba 27 	ldah	gp,0(ra)
 660:	0f 04 6b 41 	addq	s2,s2,fp
 664:	30 08 5e a4 	ldq	t1,2096(sp)
 668:	00 00 bd 23 	lda	gp,0(gp)
 66c:	58 08 3e a4 	ldq	t0,2136(sp)
 670:	06 04 e0 47 	mov	v0,t5
 674:	68 08 9e a4 	ldq	t3,2152(sp)
 678:	a7 05 a2 41 	cmpeq	s4,t1,t6
 67c:	60 08 be a4 	ldq	t4,2144(sp)
 680:	0a 00 e0 f4 	bne	t6,6ac <__gettextparse+0x4ac>
 684:	10 04 ed 47 	mov	s4,a0
 688:	00 00 7d a7 	ldq	t12,0(gp)
 68c:	50 08 1e b4 	stq	v0,2128(sp)
 690:	00 40 5b 6b 	jsr	ra,(t12),694 <__gettextparse+0x494>
 694:	00 00 ba 27 	ldah	gp,0(ra)
 698:	50 08 de a4 	ldq	t5,2128(sp)
 69c:	00 00 bd 23 	lda	gp,0(gp)
 6a0:	60 08 be a4 	ldq	t4,2144(sp)
 6a4:	68 08 9e a4 	ldq	t3,2152(sp)
 6a8:	58 08 3e a4 	ldq	t0,2136(sp)
 6ac:	fe ff 29 21 	lda	s0,-2(s0)
 6b0:	fe ff ef 21 	lda	fp,-2(fp)
 6b4:	09 04 c9 41 	addq	s5,s0,s0
 6b8:	0f 04 cf 41 	addq	s5,fp,fp
 6bc:	f8 ff 4a 21 	lda	s1,-8(s1)
 6c0:	af 03 2f 41 	cmpult	s0,fp,fp
 6c4:	0a 04 ca 40 	addq	t5,s1,s1
 6c8:	79 01 e0 e5 	beq	fp,cb0 <__gettextparse+0xab0>
 6cc:	0f 04 e6 47 	mov	t5,fp
 6d0:	0d 04 ee 47 	mov	s5,s4
 6d4:	a2 35 21 40 	cmpeq	t0,0x9,t1
 6d8:	e5 fe 5f e4 	beq	t1,270 <__gettextparse+0x70>
 6dc:	09 04 ed 47 	mov	s4,s0
 6e0:	0a 04 ff 47 	clr	s1
 6e4:	3c ff ff c3 	br	3d8 <__gettextparse+0x1d8>
 6e8:	1f 04 ff 47 	nop	
 6ec:	00 00 fe 2f 	unop	
 6f0:	40 08 7e a4 	ldq	t2,2112(sp)
 6f4:	00 00 c3 a6 	ldq	t8,0(t2)
 6f8:	01 00 16 21 	lda	t7,1(t8)
 6fc:	00 00 56 2c 	ldq_u	t1,0(t8)
 700:	42 0f 48 48 	extqh	t1,t7,t1
 704:	82 17 47 48 	sra	t1,0x38,t1
 708:	08 00 40 f4 	bne	t1,72c <__gettextparse+0x52c>
 70c:	2e 00 e0 c3 	br	7c8 <__gettextparse+0x5c8>
 710:	02 00 b6 20 	lda	t4,2(t8)
 714:	00 00 48 2c 	ldq_u	t1,0(t7)
 718:	16 04 e8 47 	mov	t7,t8
 71c:	42 0f 45 48 	extqh	t1,t4,t1
 720:	82 17 47 48 	sra	t1,0x38,t1
 724:	2a 00 40 e4 	beq	t1,7d0 <__gettextparse+0x5d0>
 728:	01 00 08 21 	lda	t7,1(t7)
 72c:	a6 15 44 40 	cmpeq	t1,0x20,t5
 730:	a5 35 41 40 	cmpeq	t1,0x9,t4
 734:	a6 15 c0 40 	cmpeq	t5,0,t5
 738:	a5 15 a0 40 	cmpeq	t4,0,t4
 73c:	17 04 e8 47 	mov	t7,t9
 740:	05 00 c5 44 	and	t5,t4,t4
 744:	f2 ff bf e4 	beq	t4,710 <__gettextparse+0x510>
 748:	06 f0 5f 44 	and	t1,0xff,t5
 74c:	a6 97 cf 40 	cmpule	t5,0x7c,t5
 750:	05 00 e2 43 	sextl	t1,t4
 754:	97 00 c0 f4 	bne	t5,9b4 <__gettextparse+0x7b4>
 758:	40 08 be a4 	ldq	t4,2112(sp)
 75c:	00 00 05 b5 	stq	t7,0(t4)
 760:	01 00 1f 21 	lda	t7,1
 764:	00 01 bf 20 	lda	t4,256
 768:	d0 fe ff c3 	br	2ac <__gettextparse+0xac>
 76c:	00 00 fe 2f 	unop	
 770:	38 08 7e a4 	ldq	t2,2104(sp)
 774:	08 00 4a 21 	lda	s1,8(s1)
 778:	48 08 be a4 	ldq	t4,2120(sp)
 77c:	22 31 60 40 	subl	t2,0x1,t1
 780:	00 00 aa b4 	stq	t4,0(s1)
 784:	c3 04 62 44 	cmovne	t2,t1,t2
 788:	fe ff bf 20 	lda	t4,-2
 78c:	38 08 7e b4 	stq	t2,2104(sp)
 790:	02 00 49 20 	lda	t1,2(s0)
 794:	80 ff ff c3 	br	598 <__gettextparse+0x398>
 798:	1f 04 ff 47 	nop	
 79c:	00 00 fe 2f 	unop	
 7a0:	fe ff bf 20 	lda	t4,-2
 7a4:	f6 fe ff c3 	br	380 <__gettextparse+0x180>
 7a8:	1f 04 ff 47 	nop	
 7ac:	00 00 fe 2f 	unop	
 7b0:	00 00 7d 24 	ldah	t2,0(gp)
 7b4:	00 00 63 20 	lda	t2,0(t2)
 7b8:	01 04 23 40 	addq	t0,t2,t0
 7bc:	00 00 c1 2c 	ldq_u	t5,0(t0)
 7c0:	c1 00 c1 48 	extbl	t5,t0,t0
 7c4:	74 ff ff c3 	br	598 <__gettextparse+0x398>
 7c8:	17 04 f6 47 	mov	t8,t9
 7cc:	00 00 fe 2f 	unop	
 7d0:	08 04 ff 47 	clr	t7
 7d4:	40 08 be a4 	ldq	t4,2112(sp)
 7d8:	00 00 e5 b6 	stq	t9,0(t4)
 7dc:	05 04 ff 47 	clr	t4
 7e0:	b3 fe ff c3 	br	2b0 <__gettextparse+0xb0>
 7e4:	00 00 fe 2f 	unop	
 7e8:	1f 04 ff 47 	nop	
 7ec:	00 00 fe 2f 	unop	
 7f0:	10 08 5e 22 	lda	a2,2064(sp)
 7f4:	00 00 2a a4 	ldq	t0,0(s1)
 7f8:	02 00 3f 22 	lda	a1,2
 7fc:	68 08 9e b4 	stq	t3,2152(sp)
 800:	01 00 1f 22 	lda	a0,1
 804:	60 08 be b4 	stq	t4,2144(sp)
 808:	10 08 3e b4 	stq	t0,2064(sp)
 80c:	ff ff 3f 20 	lda	t0,-1
 810:	58 08 3e b4 	stq	t0,2136(sp)
 814:	fc ff 29 21 	lda	s0,-4(s0)
 818:	00 00 7d a7 	ldq	t12,0(gp)
 81c:	00 40 5b 6b 	jsr	ra,(t12),820 <__gettextparse+0x620>
 820:	00 00 ba 27 	ldah	gp,0(ra)
 824:	00 00 bd 23 	lda	gp,0(gp)
 828:	f0 ff 0a 21 	lda	t7,-16(s1)
 82c:	58 08 3e a4 	ldq	t0,2136(sp)
 830:	02 00 ff 20 	lda	t6,2
 834:	68 08 9e a4 	ldq	t3,2152(sp)
 838:	60 08 be a4 	ldq	t4,2144(sp)
 83c:	3d ff ff c3 	br	534 <__gettextparse+0x334>
 840:	12 04 ff 47 	clr	a2
 844:	68 08 9e b4 	stq	t3,2152(sp)
 848:	11 04 ff 47 	clr	a1
 84c:	60 08 be b4 	stq	t4,2144(sp)
 850:	10 04 ff 47 	clr	a0
 854:	00 00 7d a7 	ldq	t12,0(gp)
 858:	00 40 5b 6b 	jsr	ra,(t12),85c <__gettextparse+0x65c>
 85c:	00 00 ba 27 	ldah	gp,0(ra)
 860:	00 00 bd 23 	lda	gp,0(gp)
 864:	fe ff 29 21 	lda	s0,-2(s0)
 868:	f8 ff 0a 21 	lda	t7,-8(s1)
 86c:	68 08 9e a4 	ldq	t3,2152(sp)
 870:	ff ff 3f 20 	lda	t0,-1
 874:	60 08 be a4 	ldq	t4,2144(sp)
 878:	02 00 ff 20 	lda	t6,2
 87c:	2d ff ff c3 	br	534 <__gettextparse+0x334>
 880:	12 04 ff 47 	clr	a2
 884:	68 08 9e b4 	stq	t3,2152(sp)
 888:	01 00 3f 22 	lda	a1,1
 88c:	60 08 be b4 	stq	t4,2144(sp)
 890:	10 04 ff 47 	clr	a0
 894:	00 00 7d a7 	ldq	t12,0(gp)
 898:	00 40 5b 6b 	jsr	ra,(t12),89c <__gettextparse+0x69c>
 89c:	00 00 ba 27 	ldah	gp,0(ra)
 8a0:	00 00 bd 23 	lda	gp,0(gp)
 8a4:	fe ff 29 21 	lda	s0,-2(s0)
 8a8:	f8 ff 0a 21 	lda	t7,-8(s1)
 8ac:	68 08 9e a4 	ldq	t3,2152(sp)
 8b0:	ff ff 3f 20 	lda	t0,-1
 8b4:	60 08 be a4 	ldq	t4,2144(sp)
 8b8:	02 00 ff 20 	lda	t6,2
 8bc:	1d ff 1f e4 	beq	v0,534 <__gettextparse+0x334>
 8c0:	00 00 4a a4 	ldq	t1,0(s1)
 8c4:	08 00 40 b4 	stq	t1,8(v0)
 8c8:	1a ff ff c3 	br	534 <__gettextparse+0x334>
 8cc:	00 00 fe 2f 	unop	
 8d0:	e8 ff 0a 21 	lda	t7,-24(s1)
 8d4:	f8 ff 0a a4 	ldq	v0,-8(s1)
 8d8:	fa ff 29 21 	lda	s0,-6(s0)
 8dc:	ff ff 3f 20 	lda	t0,-1
 8e0:	02 00 ff 20 	lda	t6,2
 8e4:	13 ff ff c3 	br	534 <__gettextparse+0x334>
 8e8:	1f 04 ff 47 	nop	
 8ec:	00 00 fe 2f 	unop	
 8f0:	10 08 5e 22 	lda	a2,2064(sp)
 8f4:	00 00 4a a4 	ldq	t1,0(s1)
 8f8:	0e 00 3f 22 	lda	a1,14
 8fc:	f0 ff 2a a4 	ldq	t0,-16(s1)
 900:	fb fe ff c3 	br	4f0 <__gettextparse+0x2f0>
 904:	00 00 fe 2f 	unop	
 908:	1f 04 ff 47 	nop	
 90c:	00 00 fe 2f 	unop	
 910:	10 08 5e 22 	lda	a2,2064(sp)
 914:	00 00 4a a4 	ldq	t1,0(s1)
 918:	0f 00 3f 22 	lda	a1,15
 91c:	f0 ff 2a a4 	ldq	t0,-16(s1)
 920:	f3 fe ff c3 	br	4f0 <__gettextparse+0x2f0>
 924:	00 00 fe 2f 	unop	
 928:	1f 04 ff 47 	nop	
 92c:	00 00 fe 2f 	unop	
 930:	e0 ff 2a a4 	ldq	t0,-32(s1)
 934:	f0 ff ca a4 	ldq	t5,-16(s1)
 938:	10 08 5e 22 	lda	a2,2064(sp)
 93c:	00 00 4a a4 	ldq	t1,0(s1)
 940:	10 08 3e b4 	stq	t0,2064(sp)
 944:	10 00 3f 22 	lda	a1,16
 948:	ff ff 3f 20 	lda	t0,-1
 94c:	68 08 9e b4 	stq	t3,2152(sp)
 950:	03 00 1f 22 	lda	a0,3
 954:	58 08 3e b4 	stq	t0,2136(sp)
 958:	60 08 be b4 	stq	t4,2144(sp)
 95c:	f6 ff 29 21 	lda	s0,-10(s0)
 960:	18 08 de b4 	stq	t5,2072(sp)
 964:	20 08 5e b4 	stq	t1,2080(sp)
 968:	00 00 7d a7 	ldq	t12,0(gp)
 96c:	00 40 5b 6b 	jsr	ra,(t12),970 <__gettextparse+0x770>
 970:	00 00 ba 27 	ldah	gp,0(ra)
 974:	00 00 bd 23 	lda	gp,0(gp)
 978:	d8 ff 0a 21 	lda	t7,-40(s1)
 97c:	58 08 3e a4 	ldq	t0,2136(sp)
 980:	02 00 ff 20 	lda	t6,2
 984:	68 08 9e a4 	ldq	t3,2152(sp)
 988:	60 08 be a4 	ldq	t4,2144(sp)
 98c:	e9 fe ff c3 	br	534 <__gettextparse+0x334>
 990:	00 00 2a a4 	ldq	t0,0(s1)
 994:	66 fe 3f e4 	beq	t0,330 <__gettextparse+0x130>
 998:	f8 ff 0a 21 	lda	t7,-8(s1)
 99c:	40 08 7e a4 	ldq	t2,2112(sp)
 9a0:	fe ff 29 21 	lda	s0,-2(s0)
 9a4:	01 00 ff 20 	lda	t6,1
 9a8:	08 00 23 b4 	stq	t0,8(t2)
 9ac:	f6 ff 3f 20 	lda	t0,-10
 9b0:	e0 fe ff c3 	br	534 <__gettextparse+0x334>
 9b4:	00 00 dd 24 	ldah	t5,0(gp)
 9b8:	00 00 c6 20 	lda	t5,0(t5)
 9bc:	46 04 46 40 	s4addq	t1,t5,t5
 9c0:	00 00 c6 a0 	ldl	t5,0(t5)
 9c4:	06 04 a6 43 	addq	gp,t5,t5
 9c8:	00 00 e6 6b 	jmp	(t5)
 9cc:	03 00 5f 20 	lda	t1,3
 9d0:	48 08 7e a4 	ldq	t2,2120(sp)
 9d4:	38 08 5e b4 	stq	t1,2104(sp)
 9d8:	08 00 4a 21 	lda	s1,8(s1)
 9dc:	02 00 49 20 	lda	t1,2(s0)
 9e0:	00 00 6a b4 	stq	t2,0(s1)
 9e4:	ec fe ff c3 	br	598 <__gettextparse+0x398>
 9e8:	1f 04 ff 47 	nop	
 9ec:	00 00 fe 2f 	unop	
 9f0:	40 08 7e a4 	ldq	t2,2112(sp)
 9f4:	00 00 e3 b6 	stq	t9,0(t2)
 9f8:	26 fe ff c3 	br	294 <__gettextparse+0x94>
 9fc:	00 00 fe 2f 	unop	
 a00:	02 00 b6 20 	lda	t4,2(t8)
 a04:	01 00 56 2c 	ldq_u	t1,1(t8)
 a08:	42 0f 45 48 	extqh	t1,t4,t1
 a0c:	82 17 47 48 	sra	t1,0x38,t1
 a10:	a2 b5 47 40 	cmpeq	t1,0x3d,t1
 a14:	b2 00 40 f4 	bne	t1,ce0 <__gettextparse+0xae0>
 a18:	48 08 be a4 	ldq	t4,2120(sp)
 a1c:	40 08 7e a4 	ldq	t2,2112(sp)
 a20:	22 16 be 48 	zapnot	t4,0xf0,t1
 a24:	00 00 03 b5 	stq	t7,0(t2)
 a28:	03 01 bf 20 	lda	t4,259
 a2c:	02 34 41 44 	or	t1,0x9,t1
 a30:	48 08 5e b4 	stq	t1,2120(sp)
 a34:	07 00 1f 21 	lda	t7,7
 a38:	1c fe ff c3 	br	2ac <__gettextparse+0xac>
 a3c:	00 00 fe 2f 	unop	
 a40:	48 08 be a4 	ldq	t4,2120(sp)
 a44:	40 08 7e a4 	ldq	t2,2112(sp)
 a48:	22 16 be 48 	zapnot	t4,0xf0,t1
 a4c:	00 00 03 b5 	stq	t7,0(t2)
 a50:	05 01 bf 20 	lda	t4,261
 a54:	02 74 40 44 	or	t1,0x3,t1
 a58:	48 08 5e b4 	stq	t1,2120(sp)
 a5c:	09 00 1f 21 	lda	t7,9
 a60:	12 fe ff c3 	br	2ac <__gettextparse+0xac>
 a64:	00 00 fe 2f 	unop	
 a68:	1f 04 ff 47 	nop	
 a6c:	00 00 fe 2f 	unop	
 a70:	48 08 be a4 	ldq	t4,2120(sp)
 a74:	40 08 7e a4 	ldq	t2,2112(sp)
 a78:	22 16 be 48 	zapnot	t4,0xf0,t1
 a7c:	00 00 03 b5 	stq	t7,0(t2)
 a80:	04 01 bf 20 	lda	t4,260
 a84:	02 f4 40 44 	or	t1,0x7,t1
 a88:	48 08 5e b4 	stq	t1,2120(sp)
 a8c:	08 00 1f 21 	lda	t7,8
 a90:	06 fe ff c3 	br	2ac <__gettextparse+0xac>
 a94:	00 00 fe 2f 	unop	
 a98:	1f 04 ff 47 	nop	
 a9c:	00 00 fe 2f 	unop	
 aa0:	48 08 be a4 	ldq	t4,2120(sp)
 aa4:	40 08 7e a4 	ldq	t2,2112(sp)
 aa8:	22 16 be 48 	zapnot	t4,0xf0,t1
 aac:	00 00 03 b5 	stq	t7,0(t2)
 ab0:	04 01 bf 20 	lda	t4,260
 ab4:	02 d4 40 44 	or	t1,0x6,t1
 ab8:	48 08 5e b4 	stq	t1,2120(sp)
 abc:	08 00 1f 21 	lda	t7,8
 ac0:	fa fd ff c3 	br	2ac <__gettextparse+0xac>
 ac4:	00 00 fe 2f 	unop	
 ac8:	1f 04 ff 47 	nop	
 acc:	00 00 fe 2f 	unop	
 ad0:	02 00 f6 22 	lda	t9,2(t8)
 ad4:	01 00 d6 2c 	ldq_u	t5,1(t8)
 ad8:	46 0f d7 48 	extqh	t5,t9,t5
 adc:	86 17 c7 48 	sra	t5,0x38,t5
 ae0:	a2 05 c2 40 	cmpeq	t5,t1,t1
 ae4:	c2 ff 5f f4 	bne	t1,9f0 <__gettextparse+0x7f0>
 ae8:	00 01 bf 20 	lda	t4,256
 aec:	40 08 7e a4 	ldq	t2,2112(sp)
 af0:	00 00 03 b5 	stq	t7,0(t2)
 af4:	01 00 1f 21 	lda	t7,1
 af8:	ec fd ff c3 	br	2ac <__gettextparse+0xac>
 afc:	00 00 fe 2f 	unop	
 b00:	48 08 be a4 	ldq	t4,2120(sp)
 b04:	40 08 7e a4 	ldq	t2,2112(sp)
 b08:	22 16 be 48 	zapnot	t4,0xf0,t1
 b0c:	00 00 03 b5 	stq	t7,0(t2)
 b10:	05 01 bf 20 	lda	t4,261
 b14:	02 b4 40 44 	or	t1,0x5,t1
 b18:	48 08 5e b4 	stq	t1,2120(sp)
 b1c:	09 00 1f 21 	lda	t7,9
 b20:	e2 fd ff c3 	br	2ac <__gettextparse+0xac>
 b24:	00 00 fe 2f 	unop	
 b28:	1f 04 ff 47 	nop	
 b2c:	00 00 fe 2f 	unop	
 b30:	02 00 b6 20 	lda	t4,2(t8)
 b34:	01 00 56 2c 	ldq_u	t1,1(t8)
 b38:	42 0f 45 48 	extqh	t1,t4,t1
 b3c:	82 17 47 48 	sra	t1,0x38,t1
 b40:	a2 b5 47 40 	cmpeq	t1,0x3d,t1
 b44:	6f 00 40 f4 	bne	t1,d04 <__gettextparse+0xb04>
 b48:	21 00 bf 20 	lda	t4,33
 b4c:	40 08 5e a4 	ldq	t1,2112(sp)
 b50:	00 00 02 b5 	stq	t7,0(t1)
 b54:	0a 00 1f 21 	lda	t7,10
 b58:	d4 fd ff c3 	br	2ac <__gettextparse+0xac>
 b5c:	00 00 fe 2f 	unop	
 b60:	08 04 ff 47 	clr	t7
 b64:	40 08 5e a4 	ldq	t1,2112(sp)
 b68:	05 04 ff 47 	clr	t4
 b6c:	00 00 c2 b6 	stq	t8,0(t1)
 b70:	cf fd ff c3 	br	2b0 <__gettextparse+0xb0>
 b74:	00 00 fe 2f 	unop	
 b78:	1f 04 ff 47 	nop	
 b7c:	00 00 fe 2f 	unop	
 b80:	02 00 b6 20 	lda	t4,2(t8)
 b84:	01 00 56 2c 	ldq_u	t1,1(t8)
 b88:	42 0f 45 48 	extqh	t1,t4,t1
 b8c:	82 17 47 48 	sra	t1,0x38,t1
 b90:	a2 b5 47 40 	cmpeq	t1,0x3d,t1
 b94:	f0 fe 5f e4 	beq	t1,758 <__gettextparse+0x558>
 b98:	06 00 1f 21 	lda	t7,6
 b9c:	48 08 7e a4 	ldq	t2,2120(sp)
 ba0:	22 16 7e 48 	zapnot	t2,0xf0,t1
 ba4:	40 08 7e a4 	ldq	t2,2112(sp)
 ba8:	02 94 41 44 	or	t1,0xc,t1
 bac:	48 08 5e b4 	stq	t1,2120(sp)
 bb0:	00 00 a3 b4 	stq	t4,0(t2)
 bb4:	02 01 bf 20 	lda	t4,258
 bb8:	bc fd ff c3 	br	2ac <__gettextparse+0xac>
 bbc:	00 00 fe 2f 	unop	
 bc0:	02 00 b6 20 	lda	t4,2(t8)
 bc4:	01 00 56 2c 	ldq_u	t1,1(t8)
 bc8:	42 0f 45 48 	extqh	t1,t4,t1
 bcc:	82 17 47 48 	sra	t1,0x38,t1
 bd0:	a2 b5 47 40 	cmpeq	t1,0x3d,t1
 bd4:	39 00 40 f4 	bne	t1,cbc <__gettextparse+0xabc>
 bd8:	48 08 be a4 	ldq	t4,2120(sp)
 bdc:	40 08 7e a4 	ldq	t2,2112(sp)
 be0:	22 16 be 48 	zapnot	t4,0xf0,t1
 be4:	00 00 03 b5 	stq	t7,0(t2)
 be8:	03 01 bf 20 	lda	t4,259
 bec:	02 14 41 44 	or	t1,0x8,t1
 bf0:	48 08 5e b4 	stq	t1,2120(sp)
 bf4:	07 00 1f 21 	lda	t7,7
 bf8:	ac fd ff c3 	br	2ac <__gettextparse+0xac>
 bfc:	00 00 fe 2f 	unop	
 c00:	02 00 d6 20 	lda	t5,2(t8)
 c04:	01 00 56 2c 	ldq_u	t1,1(t8)
 c08:	25 11 a6 40 	subl	t4,0x30,t4
 c0c:	42 0f 46 48 	extqh	t1,t5,t1
 c10:	82 17 47 48 	sra	t1,0x38,t1
 c14:	22 11 46 40 	subl	t1,0x30,t1
 c18:	06 f0 5f 44 	and	t1,0xff,t5
 c1c:	a6 37 c1 40 	cmpule	t5,0x9,t5
 c20:	0e 00 c0 e4 	beq	t5,c5c <__gettextparse+0xa5c>
 c24:	01 00 08 21 	lda	t7,1(t7)
 c28:	17 04 e8 47 	mov	t7,t9
 c2c:	01 00 08 21 	lda	t7,1(t7)
 c30:	45 04 a5 40 	s4addq	t4,t4,t4
 c34:	00 00 d7 2c 	ldq_u	t5,0(t9)
 c38:	02 00 e2 43 	sextl	t1,t1
 c3c:	05 04 a5 40 	addq	t4,t4,t4
 c40:	46 0f c8 48 	extqh	t5,t7,t5
 c44:	05 04 45 40 	addq	t1,t4,t4
 c48:	82 17 c7 48 	sra	t5,0x38,t1
 c4c:	22 11 46 40 	subl	t1,0x30,t1
 c50:	06 f0 5f 44 	and	t1,0xff,t5
 c54:	a6 37 c1 40 	cmpule	t5,0x9,t5
 c58:	f3 ff df f4 	bne	t5,c28 <__gettextparse+0xa28>
 c5c:	40 08 5e a4 	ldq	t1,2112(sp)
 c60:	48 08 be b4 	stq	t4,2120(sp)
 c64:	0b 00 1f 21 	lda	t7,11
 c68:	06 01 bf 20 	lda	t4,262
 c6c:	00 00 e2 b6 	stq	t9,0(t1)
 c70:	8e fd ff c3 	br	2ac <__gettextparse+0xac>
 c74:	00 00 fe 2f 	unop	
 c78:	1f 04 ff 47 	nop	
 c7c:	00 00 fe 2f 	unop	
 c80:	48 08 be a4 	ldq	t4,2120(sp)
 c84:	40 08 7e a4 	ldq	t2,2112(sp)
 c88:	22 16 be 48 	zapnot	t4,0xf0,t1
 c8c:	00 00 03 b5 	stq	t7,0(t2)
 c90:	05 01 bf 20 	lda	t4,261
 c94:	02 94 40 44 	or	t1,0x4,t1
 c98:	48 08 5e b4 	stq	t1,2120(sp)
 c9c:	09 00 1f 21 	lda	t7,9
 ca0:	82 fd ff c3 	br	2ac <__gettextparse+0xac>
 ca4:	09 04 ed 47 	mov	s4,s0
 ca8:	02 00 5f 21 	lda	s1,2
 cac:	ca fd ff c3 	br	3d8 <__gettextparse+0x1d8>
 cb0:	09 04 ee 47 	mov	s5,s0
 cb4:	01 00 5f 21 	lda	s1,1
 cb8:	ca fd ff c3 	br	3e4 <__gettextparse+0x1e4>
 cbc:	07 00 1f 21 	lda	t7,7
 cc0:	48 08 7e a4 	ldq	t2,2120(sp)
 cc4:	22 16 7e 48 	zapnot	t2,0xf0,t1
 cc8:	40 08 7e a4 	ldq	t2,2112(sp)
 ccc:	02 54 41 44 	or	t1,0xa,t1
 cd0:	48 08 5e b4 	stq	t1,2120(sp)
 cd4:	00 00 a3 b4 	stq	t4,0(t2)
 cd8:	03 01 bf 20 	lda	t4,259
 cdc:	73 fd ff c3 	br	2ac <__gettextparse+0xac>
 ce0:	07 00 1f 21 	lda	t7,7
 ce4:	48 08 7e a4 	ldq	t2,2120(sp)
 ce8:	22 16 7e 48 	zapnot	t2,0xf0,t1
 cec:	40 08 7e a4 	ldq	t2,2112(sp)
 cf0:	02 74 41 44 	or	t1,0xb,t1
 cf4:	48 08 5e b4 	stq	t1,2120(sp)
 cf8:	00 00 a3 b4 	stq	t4,0(t2)
 cfc:	03 01 bf 20 	lda	t4,259
 d00:	6a fd ff c3 	br	2ac <__gettextparse+0xac>
 d04:	06 00 1f 21 	lda	t7,6
 d08:	48 08 7e a4 	ldq	t2,2120(sp)
 d0c:	22 16 7e 48 	zapnot	t2,0xf0,t1
 d10:	40 08 7e a4 	ldq	t2,2112(sp)
 d14:	02 b4 41 44 	or	t1,0xd,t1
 d18:	48 08 5e b4 	stq	t1,2120(sp)
 d1c:	00 00 a3 b4 	stq	t4,0(t2)
 d20:	02 01 bf 20 	lda	t4,258
 d24:	61 fd ff c3 	br	2ac <__gettextparse+0xac>
 d28:	1f 04 ff 47 	nop	
 d2c:	00 00 fe 2f 	unop
plural-new.o:     file format elf64-alpha


Disassembly of section .text:

0000000000000000 <__gettext_free_exp>:
   0:	00 00 bb 27 	ldah	gp,0(t12)
   4:	00 00 bd 23 	lda	gp,0(gp)
   8:	f0 ff de 23 	lda	sp,-16(sp)
   c:	08 00 3e b5 	stq	s0,8(sp)
  10:	09 04 f0 47 	mov	a0,s0
  14:	00 00 5e b7 	stq	ra,0(sp)
  18:	11 00 00 e6 	beq	a0,60 <__gettext_free_exp+0x60>
  1c:	00 00 30 a0 	ldl	t0,0(a0)
  20:	a2 5d 20 40 	cmple	t0,0x2,t1
  24:	12 00 40 e4 	beq	t1,70 <__gettext_free_exp+0x70>
  28:	a2 55 20 40 	cmpeq	t0,0x2,t1
  2c:	17 00 40 f4 	bne	t1,8c <__gettext_free_exp+0x8c>
  30:	a1 35 20 40 	cmpeq	t0,0x1,t0
  34:	05 00 20 e4 	beq	t0,4c <__gettext_free_exp+0x4c>
  38:	08 00 09 a6 	ldq	a0,8(s0)
  3c:	00 00 7d a7 	ldq	t12,0(gp)
  40:	00 40 5b 6b 	jsr	ra,(t12),44 <__gettext_free_exp+0x44>
  44:	00 00 ba 27 	ldah	gp,0(ra)
  48:	00 00 bd 23 	lda	gp,0(gp)
  4c:	10 04 e9 47 	mov	s0,a0
  50:	00 00 7d a7 	ldq	t12,0(gp)
  54:	00 40 5b 6b 	jsr	ra,(t12),58 <__gettext_free_exp+0x58>
  58:	00 00 ba 27 	ldah	gp,0(ra)
  5c:	00 00 bd 23 	lda	gp,0(gp)
  60:	00 00 5e a7 	ldq	ra,0(sp)
  64:	08 00 3e a5 	ldq	s0,8(sp)
  68:	10 00 de 23 	lda	sp,16(sp)
  6c:	01 80 fa 6b 	ret
  70:	a1 75 20 40 	cmpeq	t0,0x3,t0
  74:	f5 ff 3f e4 	beq	t0,4c <__gettext_free_exp+0x4c>
  78:	18 00 10 a6 	ldq	a0,24(a0)
  7c:	00 00 7d a7 	ldq	t12,0(gp)
  80:	00 40 5b 6b 	jsr	ra,(t12),84 <__gettext_free_exp+0x84>
  84:	00 00 ba 27 	ldah	gp,0(ra)
  88:	00 00 bd 23 	lda	gp,0(gp)
  8c:	10 00 09 a6 	ldq	a0,16(s0)
  90:	00 00 7d a7 	ldq	t12,0(gp)
  94:	00 40 5b 6b 	jsr	ra,(t12),98 <__gettext_free_exp+0x98>
  98:	00 00 ba 27 	ldah	gp,0(ra)
  9c:	00 00 bd 23 	lda	gp,0(gp)
  a0:	e5 ff ff c3 	br	38 <__gettext_free_exp+0x38>
  a4:	00 00 fe 2f 	unop	
  a8:	1f 04 ff 47 	nop	
  ac:	00 00 fe 2f 	unop	

00000000000000b0 <new_exp>:
  b0:	00 00 bb 27 	ldah	gp,0(t12)
  b4:	00 00 bd 23 	lda	gp,0(gp)
  b8:	d0 ff de 23 	lda	sp,-48(sp)
  bc:	08 00 3e b5 	stq	s0,8(sp)
  c0:	29 31 00 42 	subl	a0,0x1,s0
  c4:	10 00 5e b5 	stq	s1,16(sp)
  c8:	01 00 29 20 	lda	t0,1(s0)
  cc:	18 00 7e b5 	stq	s2,24(sp)
  d0:	0a 04 f2 47 	mov	a2,s1
  d4:	20 00 9e b5 	stq	s3,32(sp)
  d8:	0b 04 f0 47 	mov	a0,s2
  dc:	00 00 5e b7 	stq	ra,0(sp)
  e0:	0c 04 f1 47 	mov	a1,s3
  e4:	35 00 20 e4 	beq	t0,1bc <new_exp+0x10c>
  e8:	01 04 e9 47 	mov	s0,t0
  ec:	01 00 e0 c3 	br	f4 <new_exp+0x44>
  f0:	1b 00 40 e4 	beq	t1,160 <new_exp+0xb0>
  f4:	43 06 2a 40 	s8addq	t0,s1,t2
  f8:	ff ff 21 20 	lda	t0,-1(t0)
  fc:	02 00 e1 43 	sextl	t0,t1
 100:	00 00 63 a4 	ldq	t2,0(t2)
 104:	01 00 42 20 	lda	t1,1(t1)
 108:	f9 ff 7f f4 	bne	t2,f0 <new_exp+0x40>
 10c:	00 00 fe 2f 	unop	
 110:	41 06 2a 41 	s8addq	s0,s1,t0
 114:	ff ff 29 21 	lda	s0,-1(s0)
 118:	00 00 01 a6 	ldq	a0,0(t0)
 11c:	00 00 7d a7 	ldq	t12,0(gp)
 120:	00 40 5b 6b 	jsr	ra,(t12),124 <new_exp+0x74>
 124:	00 00 ba 27 	ldah	gp,0(ra)
 128:	00 00 bd 23 	lda	gp,0(gp)
 12c:	01 00 e9 43 	sextl	s0,t0
 130:	01 00 21 20 	lda	t0,1(t0)
 134:	f6 ff 3f f4 	bne	t0,110 <new_exp+0x60>
 138:	00 00 5e a7 	ldq	ra,0(sp)
 13c:	08 00 3e a5 	ldq	s0,8(sp)
 140:	10 00 5e a5 	ldq	s1,16(sp)
 144:	18 00 7e a5 	ldq	s2,24(sp)
 148:	00 04 ff 47 	clr	v0
 14c:	20 00 9e a5 	ldq	s3,32(sp)
 150:	30 00 de 23 	lda	sp,48(sp)
 154:	01 80 fa 6b 	ret
 158:	1f 04 ff 47 	nop	
 15c:	00 00 fe 2f 	unop	
 160:	20 00 1f 22 	lda	a0,32
 164:	00 00 7d a7 	ldq	t12,0(gp)
 168:	00 40 5b 6b 	jsr	ra,(t12),16c <new_exp+0xbc>
 16c:	00 00 ba 27 	ldah	gp,0(ra)
 170:	00 00 bd 23 	lda	gp,0(gp)
 174:	e6 ff 1f e4 	beq	v0,110 <new_exp+0x60>
 178:	00 00 60 b1 	stl	s2,0(v0)
 17c:	04 00 80 b1 	stl	s3,4(v0)
 180:	41 06 2a 41 	s8addq	s0,s1,t0
 184:	42 06 20 41 	s8addq	s0,v0,t1
 188:	ff ff 29 21 	lda	s0,-1(s0)
 18c:	00 00 61 a4 	ldq	t2,0(t0)
 190:	01 00 e9 43 	sextl	s0,t0
 194:	01 00 21 20 	lda	t0,1(t0)
 198:	08 00 62 b4 	stq	t2,8(t1)
 19c:	f8 ff 3f f4 	bne	t0,180 <new_exp+0xd0>
 1a0:	00 00 5e a7 	ldq	ra,0(sp)
 1a4:	08 00 3e a5 	ldq	s0,8(sp)
 1a8:	10 00 5e a5 	ldq	s1,16(sp)
 1ac:	18 00 7e a5 	ldq	s2,24(sp)
 1b0:	20 00 9e a5 	ldq	s3,32(sp)
 1b4:	30 00 de 23 	lda	sp,48(sp)
 1b8:	01 80 fa 6b 	ret
 1bc:	20 00 1f 22 	lda	a0,32
 1c0:	00 00 7d a7 	ldq	t12,0(gp)
 1c4:	00 40 5b 6b 	jsr	ra,(t12),1c8 <new_exp+0x118>
 1c8:	00 00 ba 27 	ldah	gp,0(ra)
 1cc:	00 00 bd 23 	lda	gp,0(gp)
 1d0:	d9 ff 1f e4 	beq	v0,138 <new_exp+0x88>
 1d4:	04 00 80 b1 	stl	s3,4(v0)
 1d8:	00 00 5e a7 	ldq	ra,0(sp)
 1dc:	08 00 3e a5 	ldq	s0,8(sp)
 1e0:	10 00 5e a5 	ldq	s1,16(sp)
 1e4:	18 00 7e a5 	ldq	s2,24(sp)
 1e8:	20 00 9e a5 	ldq	s3,32(sp)
 1ec:	00 00 e0 b3 	stl	zero,0(v0)
 1f0:	30 00 de 23 	lda	sp,48(sp)
 1f4:	01 80 fa 6b 	ret
 1f8:	1f 04 ff 47 	nop	
 1fc:	00 00 fe 2f 	unop	

0000000000000200 <__gettextparse>:
 200:	00 00 bb 27 	ldah	gp,0(t12)
 204:	00 00 bd 23 	lda	gp,0(gp)
 208:	90 f7 de 23 	lda	sp,-2160(sp)
 20c:	00 00 9d 24 	ldah	t3,0(gp)
 210:	80 06 3e a0 	ldl	t0,1664(sp)
 214:	08 00 3e b5 	stq	s0,8(sp)
 218:	00 00 5d 24 	ldah	t1,0(gp)
 21c:	80 06 3e 21 	lda	s0,1664(sp)
 220:	10 00 5e b5 	stq	s1,16(sp)
 224:	21 96 3f 48 	zapnot	t0,0xfc,t0
 228:	18 00 7e b5 	stq	s2,24(sp)
 22c:	40 00 5e 21 	lda	s1,64(sp)
 230:	20 00 9e b5 	stq	s3,32(sp)
 234:	28 00 be b5 	stq	s4,40(sp)
 238:	00 00 42 20 	lda	t1,0(t1)
 23c:	30 00 de b5 	stq	s5,48(sp)
 240:	fe ff bf 20 	lda	t4,-2
 244:	80 06 3e b0 	stl	t0,1664(sp)
 248:	c8 00 7f 21 	lda	s2,200
 24c:	01 04 ff 47 	clr	t0
 250:	00 00 5e b7 	stq	ra,0(sp)
 254:	0e 04 ea 47 	mov	s1,s5
 258:	38 00 fe b5 	stq	fp,56(sp)
 25c:	0d 04 e9 47 	mov	s0,s4
 260:	40 08 1e b6 	stq	a0,2112(sp)
 264:	00 00 84 21 	lda	s3,0(t3)
 268:	38 08 fe b7 	stq	zero,2104(sp)
 26c:	01 00 42 20 	lda	t1,1(t1)
 270:	30 08 3e b5 	stq	s0,2096(sp)
 274:	48 08 5e b4 	stq	t1,2120(sp)
 278:	02 04 81 41 	addq	s3,t0,t1
 27c:	01 00 c2 20 	lda	t5,1(t1)
 280:	00 00 e2 2c 	ldq_u	t6,0(t1)
 284:	47 0f e6 48 	extqh	t6,t5,t6
 288:	87 17 e7 48 	sra	t6,0x38,t6
 28c:	0a 00 47 20 	lda	t1,10(t6)
 290:	27 00 40 e4 	beq	t1,330 <__gettextparse+0x130>
 294:	02 00 45 20 	lda	t1,2(t4)
 298:	21 01 40 e4 	beq	t1,720 <__gettextparse+0x520>
 29c:	94 00 a0 ec 	ble	t4,4f0 <__gettextparse+0x2f0>
 2a0:	00 00 5d 24 	ldah	t1,0(gp)
 2a4:	00 00 42 20 	lda	t1,0(t1)
 2a8:	02 04 a2 40 	addq	t4,t1,t1
 2ac:	00 00 02 2d 	ldq_u	t7,0(t1)
 2b0:	c8 00 02 49 	extbl	t7,t1,t7
 2b4:	07 00 e8 40 	addl	t6,t7,t6
 2b8:	26 f6 e1 48 	zapnot	t6,0xf,t5
 2bc:	a6 d7 c6 40 	cmpule	t5,0x36,t5
 2c0:	1b 00 c0 e4 	beq	t5,330 <__gettextparse+0x130>
 2c4:	00 00 dd 24 	ldah	t5,0(gp)
 2c8:	00 00 c6 20 	lda	t5,0(t5)
 2cc:	06 04 e6 40 	addq	t6,t5,t5
 2d0:	01 00 c6 22 	lda	t8,1(t5)
 2d4:	00 00 46 2c 	ldq_u	t1,0(t5)
 2d8:	42 0f 56 48 	extqh	t1,t8,t1
 2dc:	82 17 47 48 	sra	t1,0x38,t1
 2e0:	a2 05 48 40 	cmpeq	t1,t7,t1
 2e4:	12 00 40 e4 	beq	t1,330 <__gettextparse+0x130>
 2e8:	00 00 3d 24 	ldah	t0,0(gp)
 2ec:	00 00 21 20 	lda	t0,0(t0)
 2f0:	07 04 e1 40 	addq	t6,t0,t6
 2f4:	00 00 27 2c 	ldq_u	t0,0(t6)
 2f8:	c1 00 27 48 	extbl	t0,t6,t0
 2fc:	28 01 20 f4 	bne	t0,7a0 <__gettextparse+0x5a0>
 300:	00 00 5d 24 	ldah	t1,0(gp)
 304:	48 08 7e a4 	ldq	t2,2120(sp)
 308:	00 00 42 20 	lda	t1,0(t1)
 30c:	08 00 0a a4 	ldq	v0,8(s1)
 310:	08 04 ea 47 	mov	s1,t7
 314:	f0 ff ff 20 	lda	t6,-16
 318:	00 00 22 2c 	ldq_u	t0,0(t1)
 31c:	41 0f 23 48 	extqh	t0,t2,t0
 320:	81 17 27 48 	sra	t0,0x38,t0
 324:	8f 00 e0 c3 	br	564 <__gettextparse+0x364>
 328:	1f 04 ff 47 	nop	
 32c:	00 00 fe 2f 	unop	
 330:	00 00 5d 24 	ldah	t1,0(gp)
 334:	00 00 42 20 	lda	t1,0(t1)
 338:	02 04 22 40 	addq	t0,t1,t1
 33c:	00 00 c2 2c 	ldq_u	t5,0(t1)
 340:	c2 00 c2 48 	extbl	t5,t1,t1
 344:	08 00 e2 43 	sextl	t1,t7
 348:	35 00 40 f4 	bne	t1,420 <__gettextparse+0x220>
 34c:	38 08 9e a4 	ldq	t3,2104(sp)
 350:	a2 75 80 40 	cmpeq	t3,0x3,t1
 354:	02 00 40 e4 	beq	t1,360 <__gettextparse+0x160>
 358:	1d 01 a0 fc 	bgt	t4,7d0 <__gettextparse+0x5d0>
 35c:	4d 02 a0 e4 	beq	t4,c94 <__gettextparse+0xa94>
 360:	00 00 dd 24 	ldah	t5,0(gp)
 364:	00 00 fd 24 	ldah	t6,0(gp)
 368:	00 00 c6 20 	lda	t5,0(t5)
 36c:	00 00 e7 20 	lda	t6,0(t6)
 370:	0b 00 e0 c3 	br	3a0 <__gettextparse+0x1a0>
 374:	00 00 fe 2f 	unop	
 378:	1f 04 ff 47 	nop	
 37c:	00 00 fe 2f 	unop	
 380:	a1 05 2d 41 	cmpeq	s0,s4,t0
 384:	46 00 20 f4 	bne	t0,4a0 <__gettextparse+0x2a0>
 388:	fe ff 29 21 	lda	s0,-2(s0)
 38c:	02 00 49 20 	lda	t1,2(s0)
 390:	f8 ff 4a 21 	lda	s1,-8(s1)
 394:	00 00 29 2c 	ldq_u	t0,0(s0)
 398:	41 0f 22 48 	extqh	t0,t1,t0
 39c:	81 17 26 48 	sra	t0,0x30,t0
 3a0:	01 04 81 41 	addq	s3,t0,t0
 3a4:	01 00 41 20 	lda	t1,1(t0)
 3a8:	00 00 21 2c 	ldq_u	t0,0(t0)
 3ac:	41 0f 22 48 	extqh	t0,t1,t0
 3b0:	81 17 27 48 	sra	t0,0x38,t0
 3b4:	0a 00 41 20 	lda	t1,10(t0)
 3b8:	f1 ff 5f e4 	beq	t1,380 <__gettextparse+0x180>
 3bc:	01 30 20 40 	addl	t0,0x1,t0
 3c0:	22 f6 21 48 	zapnot	t0,0xf,t1
 3c4:	01 00 e1 43 	sextl	t0,t0
 3c8:	a2 d7 46 40 	cmpule	t1,0x36,t1
 3cc:	ec ff 5f e4 	beq	t1,380 <__gettextparse+0x180>
 3d0:	08 04 26 40 	addq	t0,t5,t7
 3d4:	01 00 c8 22 	lda	t8,1(t7)
 3d8:	00 00 48 2c 	ldq_u	t1,0(t7)
 3dc:	42 0f 56 48 	extqh	t1,t8,t1
 3e0:	82 17 47 48 	sra	t1,0x38,t1
 3e4:	a2 35 40 40 	cmpeq	t1,0x1,t1
 3e8:	e5 ff 5f e4 	beq	t1,380 <__gettextparse+0x180>
 3ec:	01 04 27 40 	addq	t0,t6,t0
 3f0:	00 00 41 2c 	ldq_u	t1,0(t0)
 3f4:	c1 00 41 48 	extbl	t1,t0,t0
 3f8:	e1 ff 3f e4 	beq	t0,380 <__gettextparse+0x180>
 3fc:	03 00 9f 20 	lda	t3,3
 400:	50 08 7e a4 	ldq	t2,2128(sp)
 404:	38 08 9e b4 	stq	t3,2104(sp)
 408:	08 00 4a 21 	lda	s1,8(s1)
 40c:	02 00 49 20 	lda	t1,2(s0)
 410:	00 00 6a b4 	stq	t2,0(s1)
 414:	6e 00 e0 c3 	br	5d0 <__gettextparse+0x3d0>
 418:	1f 04 ff 47 	nop	
 41c:	00 00 fe 2f 	unop	
 420:	00 00 3d 24 	ldah	t0,0(gp)
 424:	00 00 21 20 	lda	t0,0(t0)
 428:	01 04 01 41 	addq	t7,t0,t0
 42c:	a7 b7 41 40 	cmpule	t1,0xd,t6
 430:	00 00 c1 2c 	ldq_u	t5,0(t0)
 434:	c1 00 c1 48 	extbl	t5,t0,t0
 438:	01 00 df 20 	lda	t5,1
 43c:	26 01 c1 40 	subl	t5,t0,t5
 440:	46 06 ca 40 	s8addq	t5,s1,t5
 444:	00 00 06 a4 	ldq	v0,0(t5)
 448:	2d 00 e0 f4 	bne	t6,500 <__gettextparse+0x300>
 44c:	00 00 5d 24 	ldah	t1,0(gp)
 450:	00 00 42 20 	lda	t1,0(t1)
 454:	02 04 02 41 	addq	t7,t1,t1
 458:	00 00 9d 24 	ldah	t3,0(gp)
 45c:	48 16 20 40 	s8addq	t0,0,t7
 460:	00 00 e2 2c 	ldq_u	t6,0(t1)
 464:	01 04 21 40 	addq	t0,t0,t0
 468:	00 00 84 20 	lda	t3,0(t3)
 46c:	c2 00 e2 48 	extbl	t6,t1,t1
 470:	29 05 21 41 	subq	s0,t0,s0
 474:	27 11 42 40 	subl	t1,0x10,t6
 478:	01 04 e4 40 	addq	t6,t3,t0
 47c:	01 00 41 20 	lda	t1,1(t0)
 480:	28 05 48 41 	subq	s1,t7,t7
 484:	00 00 21 2c 	ldq_u	t0,0(t0)
 488:	41 0f 22 48 	extqh	t0,t1,t0
 48c:	81 17 27 48 	sra	t0,0x38,t0
 490:	34 00 e0 c3 	br	564 <__gettextparse+0x364>
 494:	00 00 fe 2f 	unop	
 498:	1f 04 ff 47 	nop	
 49c:	00 00 fe 2f 	unop	
 4a0:	01 00 5f 21 	lda	s1,1
 4a4:	30 08 3e a4 	ldq	t0,2096(sp)
 4a8:	ad 05 21 41 	cmpeq	s0,t0,s4
 4ac:	05 00 a0 f5 	bne	s4,4c4 <__gettextparse+0x2c4>
 4b0:	10 04 e9 47 	mov	s0,a0
 4b4:	00 00 7d a7 	ldq	t12,0(gp)
 4b8:	00 40 5b 6b 	jsr	ra,(t12),4bc <__gettextparse+0x2bc>
 4bc:	00 00 ba 27 	ldah	gp,0(ra)
 4c0:	00 00 bd 23 	lda	gp,0(gp)
 4c4:	00 04 ea 47 	mov	s1,v0
 4c8:	00 00 5e a7 	ldq	ra,0(sp)
 4cc:	08 00 3e a5 	ldq	s0,8(sp)
 4d0:	10 00 5e a5 	ldq	s1,16(sp)
 4d4:	18 00 7e a5 	ldq	s2,24(sp)
 4d8:	20 00 9e a5 	ldq	s3,32(sp)
 4dc:	28 00 be a5 	ldq	s4,40(sp)
 4e0:	30 00 de a5 	ldq	s5,48(sp)
 4e4:	38 00 fe a5 	ldq	fp,56(sp)
 4e8:	70 08 de 23 	lda	sp,2160(sp)
 4ec:	01 80 fa 6b 	ret
 4f0:	08 04 ff 47 	clr	t7
 4f4:	05 04 ff 47 	clr	t4
 4f8:	6f ff ff c3 	br	2b8 <__gettextparse+0xb8>
 4fc:	00 00 fe 2f 	unop	
 500:	00 00 dd 24 	ldah	t5,0(gp)
 504:	00 00 c6 20 	lda	t5,0(t5)
 508:	42 04 46 40 	s4addq	t1,t5,t1
 50c:	00 00 42 a0 	ldl	t1,0(t1)
 510:	02 04 a2 43 	addq	gp,t1,t1
 514:	00 00 e2 6b 	jmp	(t1)
 518:	1f 04 ff 47 	nop	
 51c:	00 00 fe 2f 	unop	
 520:	10 08 5e 22 	lda	a2,2064(sp)
 524:	f8 ff 2a a2 	ldl	a1,-8(s1)
 528:	00 00 4a a4 	ldq	t1,0(s1)
 52c:	f0 ff 2a a4 	ldq	t0,-16(s1)
 530:	02 00 1f 22 	lda	a0,2
 534:	10 08 3e b4 	stq	t0,2064(sp)
 538:	68 08 be b4 	stq	t4,2152(sp)
 53c:	fa ff 29 21 	lda	s0,-6(s0)
 540:	18 08 5e b4 	stq	t1,2072(sp)
 544:	00 00 7d a7 	ldq	t12,0(gp)
 548:	00 40 5b 6b 	jsr	ra,(t12),54c <__gettextparse+0x34c>
 54c:	00 00 ba 27 	ldah	gp,0(ra)
 550:	00 00 bd 23 	lda	gp,0(gp)
 554:	e8 ff 0a 21 	lda	t7,-24(s1)
 558:	68 08 be a4 	ldq	t4,2152(sp)
 55c:	ff ff 3f 20 	lda	t0,-1
 560:	02 00 ff 20 	lda	t6,2
 564:	08 00 08 b4 	stq	v0,8(t7)
 568:	02 00 49 20 	lda	t1,2(s0)
 56c:	08 00 48 21 	lda	s1,8(t7)
 570:	00 00 c9 2c 	ldq_u	t5,0(s0)
 574:	46 0f c2 48 	extqh	t5,t1,t5
 578:	86 17 c6 48 	sra	t5,0x30,t5
 57c:	01 00 c1 40 	addl	t5,t0,t0
 580:	28 f6 21 48 	zapnot	t0,0xf,t7
 584:	01 00 e1 43 	sextl	t0,t0
 588:	a8 d7 06 41 	cmpule	t7,0x36,t7
 58c:	09 00 00 e5 	beq	t7,5b4 <__gettextparse+0x3b4>
 590:	00 00 dd 26 	ldah	t8,0(gp)
 594:	00 00 d6 22 	lda	t8,0(t8)
 598:	16 04 36 40 	addq	t0,t8,t8
 59c:	01 00 f6 22 	lda	t9,1(t8)
 5a0:	00 00 16 2d 	ldq_u	t7,0(t8)
 5a4:	48 0f 17 49 	extqh	t7,t9,t7
 5a8:	88 17 07 49 	sra	t7,0x38,t7
 5ac:	a6 05 06 41 	cmpeq	t7,t5,t5
 5b0:	8b 00 c0 f4 	bne	t5,7e0 <__gettextparse+0x5e0>
 5b4:	00 00 dd 24 	ldah	t5,0(gp)
 5b8:	00 00 c6 20 	lda	t5,0(t5)
 5bc:	06 04 e6 40 	addq	t6,t5,t5
 5c0:	01 00 e6 20 	lda	t6,1(t5)
 5c4:	00 00 26 2c 	ldq_u	t0,0(t5)
 5c8:	41 0f 27 48 	extqh	t0,t6,t0
 5cc:	81 17 27 48 	sra	t0,0x38,t0
 5d0:	16 04 6b 41 	addq	s2,s2,t8
 5d4:	02 00 09 2d 	ldq_u	t7,2(s0)
 5d8:	67 03 22 48 	inswl	t0,t1,t6
 5dc:	fe ff d6 20 	lda	t5,-2(t8)
 5e0:	48 02 02 49 	mskwl	t7,t1,t7
 5e4:	06 04 a6 41 	addq	s4,t5,t5
 5e8:	07 04 e8 44 	or	t6,t7,t6
 5ec:	02 00 e9 3c 	stq_u	t6,2(s0)
 5f0:	a6 03 46 40 	cmpult	t1,t5,t5
 5f4:	09 04 e2 47 	mov	t1,s0
 5f8:	41 00 c0 f4 	bne	t5,700 <__gettextparse+0x500>
 5fc:	2a 05 4d 40 	subq	t1,s4,s1
 600:	8a 37 40 49 	sra	s1,0x1,s1
 604:	0f 27 df 20 	lda	t5,9999
 608:	ab 07 66 41 	cmpule	s2,t5,s2
 60c:	01 00 4a 21 	lda	s1,1(s1)
 610:	a3 01 60 e5 	beq	s2,ca0 <__gettextparse+0xaa0>
 614:	10 27 5f 20 	lda	t1,10000
 618:	00 00 7d a7 	ldq	t12,0(gp)
 61c:	ab 03 c2 42 	cmpult	t8,t1,s2
 620:	60 08 3e b4 	stq	t0,2144(sp)
 624:	68 08 be b4 	stq	t4,2152(sp)
 628:	c2 04 76 45 	cmovne	s2,t8,t1
 62c:	50 04 42 40 	s4addq	t1,t1,a0
 630:	10 04 10 42 	addq	a0,a0,a0
 634:	07 00 10 22 	lda	a0,7(a0)
 638:	0b 04 e2 47 	mov	t1,s2
 63c:	00 40 5b 6b 	jsr	ra,(t12),640 <__gettextparse+0x440>
 640:	00 00 ba 27 	ldah	gp,0(ra)
 644:	00 00 bd 23 	lda	gp,0(gp)
 648:	0f 04 e0 47 	mov	v0,fp
 64c:	94 01 00 e4 	beq	v0,ca0 <__gettextparse+0xaa0>
 650:	09 04 4a 41 	addq	s1,s1,s0
 654:	00 00 7d a7 	ldq	t12,0(gp)
 658:	12 04 e9 47 	mov	s0,a2
 65c:	11 04 ed 47 	mov	s4,a1
 660:	10 04 e0 47 	mov	v0,a0
 664:	00 40 5b 6b 	jsr	ra,(t12),668 <__gettextparse+0x468>
 668:	00 00 ba 27 	ldah	gp,0(ra)
 66c:	4a 16 40 41 	s8addq	s1,0,s1
 670:	06 04 6b 41 	addq	s2,s2,t5
 674:	00 00 bd 23 	lda	gp,0(gp)
 678:	06 04 e6 41 	addq	fp,t5,t5
 67c:	11 04 ee 47 	mov	s5,a1
 680:	00 00 7d a7 	ldq	t12,0(gp)
 684:	10 04 e6 47 	mov	t5,a0
 688:	12 04 ea 47 	mov	s1,a2
 68c:	00 40 5b 6b 	jsr	ra,(t12),690 <__gettextparse+0x490>
 690:	00 00 ba 27 	ldah	gp,0(ra)
 694:	0e 04 6b 41 	addq	s2,s2,s5
 698:	30 08 7e a4 	ldq	t2,2096(sp)
 69c:	00 00 bd 23 	lda	gp,0(gp)
 6a0:	60 08 3e a4 	ldq	t0,2144(sp)
 6a4:	06 04 e0 47 	mov	v0,t5
 6a8:	68 08 be a4 	ldq	t4,2152(sp)
 6ac:	a7 05 a3 41 	cmpeq	s4,t2,t6
 6b0:	09 00 e0 f4 	bne	t6,6d8 <__gettextparse+0x4d8>
 6b4:	10 04 ed 47 	mov	s4,a0
 6b8:	00 00 7d a7 	ldq	t12,0(gp)
 6bc:	58 08 1e b4 	stq	v0,2136(sp)
 6c0:	00 40 5b 6b 	jsr	ra,(t12),6c4 <__gettextparse+0x4c4>
 6c4:	00 00 ba 27 	ldah	gp,0(ra)
 6c8:	58 08 de a4 	ldq	t5,2136(sp)
 6cc:	00 00 bd 23 	lda	gp,0(gp)
 6d0:	68 08 be a4 	ldq	t4,2152(sp)
 6d4:	60 08 3e a4 	ldq	t0,2144(sp)
 6d8:	fe ff 29 21 	lda	s0,-2(s0)
 6dc:	fe ff ce 21 	lda	s5,-2(s5)
 6e0:	09 04 e9 41 	addq	fp,s0,s0
 6e4:	0e 04 ee 41 	addq	fp,s5,s5
 6e8:	f8 ff 4a 21 	lda	s1,-8(s1)
 6ec:	ae 03 2e 41 	cmpult	s0,s5,s5
 6f0:	0a 04 ca 40 	addq	t5,s1,s1
 6f4:	6d 01 c0 e5 	beq	s5,cac <__gettextparse+0xaac>
 6f8:	0e 04 e6 47 	mov	t5,s5
 6fc:	0d 04 ef 47 	mov	fp,s4
 700:	a2 35 21 40 	cmpeq	t0,0x9,t1
 704:	dc fe 5f e4 	beq	t1,278 <__gettextparse+0x78>
 708:	09 04 ed 47 	mov	s4,s0
 70c:	0a 04 ff 47 	clr	s1
 710:	64 ff ff c3 	br	4a4 <__gettextparse+0x2a4>
 714:	00 00 fe 2f 	unop	
 718:	1f 04 ff 47 	nop	
 71c:	00 00 fe 2f 	unop	
 720:	40 08 9e a4 	ldq	t3,2112(sp)
 724:	00 00 c4 a6 	ldq	t8,0(t3)
 728:	01 00 16 21 	lda	t7,1(t8)
 72c:	00 00 56 2c 	ldq_u	t1,0(t8)
 730:	42 0f 48 48 	extqh	t1,t7,t1
 734:	82 17 47 48 	sra	t1,0x38,t1
 738:	08 00 40 f4 	bne	t1,75c <__gettextparse+0x55c>
 73c:	2e 00 e0 c3 	br	7f8 <__gettextparse+0x5f8>
 740:	02 00 b6 20 	lda	t4,2(t8)
 744:	00 00 48 2c 	ldq_u	t1,0(t7)
 748:	16 04 e8 47 	mov	t7,t8
 74c:	42 0f 45 48 	extqh	t1,t4,t1
 750:	82 17 47 48 	sra	t1,0x38,t1
 754:	2a 00 40 e4 	beq	t1,800 <__gettextparse+0x600>
 758:	01 00 08 21 	lda	t7,1(t7)
 75c:	a6 15 44 40 	cmpeq	t1,0x20,t5
 760:	a5 35 41 40 	cmpeq	t1,0x9,t4
 764:	a6 15 c0 40 	cmpeq	t5,0,t5
 768:	a5 15 a0 40 	cmpeq	t4,0,t4
 76c:	17 04 e8 47 	mov	t7,t9
 770:	05 00 c5 44 	and	t5,t4,t4
 774:	f2 ff bf e4 	beq	t4,740 <__gettextparse+0x540>
 778:	06 f0 5f 44 	and	t1,0xff,t5
 77c:	a6 97 cf 40 	cmpule	t5,0x7c,t5
 780:	05 00 e2 43 	sextl	t1,t4
 784:	8f 00 c0 f4 	bne	t5,9c4 <__gettextparse+0x7c4>
 788:	00 01 bf 20 	lda	t4,256
 78c:	40 08 9e a4 	ldq	t3,2112(sp)
 790:	00 00 04 b5 	stq	t7,0(t3)
 794:	01 00 1f 21 	lda	t7,1
 798:	c6 fe ff c3 	br	2b4 <__gettextparse+0xb4>
 79c:	00 00 fe 2f 	unop	
 7a0:	38 08 9e a4 	ldq	t3,2104(sp)
 7a4:	08 00 4a 21 	lda	s1,8(s1)
 7a8:	50 08 7e a4 	ldq	t2,2128(sp)
 7ac:	fe ff bf 20 	lda	t4,-2
 7b0:	22 31 80 40 	subl	t3,0x1,t1
 7b4:	c4 04 82 44 	cmovne	t3,t1,t3
 7b8:	00 00 6a b4 	stq	t2,0(s1)
 7bc:	38 08 9e b4 	stq	t3,2104(sp)
 7c0:	02 00 49 20 	lda	t1,2(s0)
 7c4:	82 ff ff c3 	br	5d0 <__gettextparse+0x3d0>
 7c8:	1f 04 ff 47 	nop	
 7cc:	00 00 fe 2f 	unop	
 7d0:	fe ff bf 20 	lda	t4,-2
 7d4:	e2 fe ff c3 	br	360 <__gettextparse+0x160>
 7d8:	1f 04 ff 47 	nop	
 7dc:	00 00 fe 2f 	unop	
 7e0:	00 00 dd 24 	ldah	t5,0(gp)
 7e4:	00 00 c6 20 	lda	t5,0(t5)
 7e8:	01 04 26 40 	addq	t0,t5,t0
 7ec:	00 00 c1 2c 	ldq_u	t5,0(t0)
 7f0:	c1 00 c1 48 	extbl	t5,t0,t0
 7f4:	76 ff ff c3 	br	5d0 <__gettextparse+0x3d0>
 7f8:	17 04 f6 47 	mov	t8,t9
 7fc:	00 00 fe 2f 	unop	
 800:	08 04 ff 47 	clr	t7
 804:	40 08 5e a4 	ldq	t1,2112(sp)
 808:	05 04 ff 47 	clr	t4
 80c:	00 00 e2 b6 	stq	t9,0(t1)
 810:	a9 fe ff c3 	br	2b8 <__gettextparse+0xb8>
 814:	00 00 fe 2f 	unop	
 818:	1f 04 ff 47 	nop	
 81c:	00 00 fe 2f 	unop	
 820:	10 08 5e 22 	lda	a2,2064(sp)
 824:	00 00 2a a4 	ldq	t0,0(s1)
 828:	02 00 3f 22 	lda	a1,2
 82c:	68 08 be b4 	stq	t4,2152(sp)
 830:	01 00 1f 22 	lda	a0,1
 834:	10 08 3e b4 	stq	t0,2064(sp)
 838:	fc ff 29 21 	lda	s0,-4(s0)
 83c:	00 00 7d a7 	ldq	t12,0(gp)
 840:	00 40 5b 6b 	jsr	ra,(t12),844 <__gettextparse+0x644>
 844:	00 00 ba 27 	ldah	gp,0(ra)
 848:	00 00 bd 23 	lda	gp,0(gp)
 84c:	f0 ff 0a 21 	lda	t7,-16(s1)
 850:	68 08 be a4 	ldq	t4,2152(sp)
 854:	ff ff 3f 20 	lda	t0,-1
 858:	02 00 ff 20 	lda	t6,2
 85c:	41 ff ff c3 	br	564 <__gettextparse+0x364>
 860:	12 04 ff 47 	clr	a2
 864:	68 08 be b4 	stq	t4,2152(sp)
 868:	11 04 ff 47 	clr	a1
 86c:	10 04 ff 47 	clr	a0
 870:	00 00 7d a7 	ldq	t12,0(gp)
 874:	00 40 5b 6b 	jsr	ra,(t12),878 <__gettextparse+0x678>
 878:	00 00 ba 27 	ldah	gp,0(ra)
 87c:	00 00 bd 23 	lda	gp,0(gp)
 880:	fe ff 29 21 	lda	s0,-2(s0)
 884:	f8 ff 0a 21 	lda	t7,-8(s1)
 888:	68 08 be a4 	ldq	t4,2152(sp)
 88c:	ff ff 3f 20 	lda	t0,-1
 890:	02 00 ff 20 	lda	t6,2
 894:	33 ff ff c3 	br	564 <__gettextparse+0x364>
 898:	1f 04 ff 47 	nop	
 89c:	00 00 fe 2f 	unop	
 8a0:	12 04 ff 47 	clr	a2
 8a4:	68 08 be b4 	stq	t4,2152(sp)
 8a8:	01 00 3f 22 	lda	a1,1
 8ac:	10 04 ff 47 	clr	a0
 8b0:	00 00 7d a7 	ldq	t12,0(gp)
 8b4:	00 40 5b 6b 	jsr	ra,(t12),8b8 <__gettextparse+0x6b8>
 8b8:	00 00 ba 27 	ldah	gp,0(ra)
 8bc:	00 00 bd 23 	lda	gp,0(gp)
 8c0:	fe ff 29 21 	lda	s0,-2(s0)
 8c4:	f8 ff 0a 21 	lda	t7,-8(s1)
 8c8:	68 08 be a4 	ldq	t4,2152(sp)
 8cc:	ff ff 3f 20 	lda	t0,-1
 8d0:	02 00 ff 20 	lda	t6,2
 8d4:	23 ff 1f e4 	beq	v0,564 <__gettextparse+0x364>
 8d8:	00 00 4a a4 	ldq	t1,0(s1)
 8dc:	08 00 40 b4 	stq	t1,8(v0)
 8e0:	20 ff ff c3 	br	564 <__gettextparse+0x364>
 8e4:	00 00 fe 2f 	unop	
 8e8:	1f 04 ff 47 	nop	
 8ec:	00 00 fe 2f 	unop	
 8f0:	e8 ff 0a 21 	lda	t7,-24(s1)
 8f4:	f8 ff 0a a4 	ldq	v0,-8(s1)
 8f8:	fa ff 29 21 	lda	s0,-6(s0)
 8fc:	ff ff 3f 20 	lda	t0,-1
 900:	02 00 ff 20 	lda	t6,2
 904:	17 ff ff c3 	br	564 <__gettextparse+0x364>
 908:	1f 04 ff 47 	nop	
 90c:	00 00 fe 2f 	unop	
 910:	10 08 5e 22 	lda	a2,2064(sp)
 914:	00 00 4a a4 	ldq	t1,0(s1)
 918:	0e 00 3f 22 	lda	a1,14
 91c:	f0 ff 2a a4 	ldq	t0,-16(s1)
 920:	03 ff ff c3 	br	530 <__gettextparse+0x330>
 924:	00 00 fe 2f 	unop	
 928:	1f 04 ff 47 	nop	
 92c:	00 00 fe 2f 	unop	
 930:	10 08 5e 22 	lda	a2,2064(sp)
 934:	00 00 4a a4 	ldq	t1,0(s1)
 938:	0f 00 3f 22 	lda	a1,15
 93c:	f0 ff 2a a4 	ldq	t0,-16(s1)
 940:	fb fe ff c3 	br	530 <__gettextparse+0x330>
 944:	00 00 fe 2f 	unop	
 948:	1f 04 ff 47 	nop	
 94c:	00 00 fe 2f 	unop	
 950:	e0 ff 2a a4 	ldq	t0,-32(s1)
 954:	f0 ff ca a4 	ldq	t5,-16(s1)
 958:	10 08 5e 22 	lda	a2,2064(sp)
 95c:	00 00 4a a4 	ldq	t1,0(s1)
 960:	10 00 3f 22 	lda	a1,16
 964:	10 08 3e b4 	stq	t0,2064(sp)
 968:	03 00 1f 22 	lda	a0,3
 96c:	68 08 be b4 	stq	t4,2152(sp)
 970:	18 08 de b4 	stq	t5,2072(sp)
 974:	f6 ff 29 21 	lda	s0,-10(s0)
 978:	20 08 5e b4 	stq	t1,2080(sp)
 97c:	00 00 7d a7 	ldq	t12,0(gp)
 980:	00 40 5b 6b 	jsr	ra,(t12),984 <__gettextparse+0x784>
 984:	00 00 ba 27 	ldah	gp,0(ra)
 988:	00 00 bd 23 	lda	gp,0(gp)
 98c:	d8 ff 0a 21 	lda	t7,-40(s1)
 990:	68 08 be a4 	ldq	t4,2152(sp)
 994:	ff ff 3f 20 	lda	t0,-1
 998:	02 00 ff 20 	lda	t6,2
 99c:	f1 fe ff c3 	br	564 <__gettextparse+0x364>
 9a0:	00 00 2a a4 	ldq	t0,0(s1)
 9a4:	bb 00 20 e4 	beq	t0,c94 <__gettextparse+0xa94>
 9a8:	f8 ff 0a 21 	lda	t7,-8(s1)
 9ac:	40 08 5e a4 	ldq	t1,2112(sp)
 9b0:	fe ff 29 21 	lda	s0,-2(s0)
 9b4:	01 00 ff 20 	lda	t6,1
 9b8:	08 00 22 b4 	stq	t0,8(t1)
 9bc:	f6 ff 3f 20 	lda	t0,-10
 9c0:	e8 fe ff c3 	br	564 <__gettextparse+0x364>
 9c4:	00 00 dd 24 	ldah	t5,0(gp)
 9c8:	00 00 c6 20 	lda	t5,0(t5)
 9cc:	46 04 46 40 	s4addq	t1,t5,t5
 9d0:	00 00 c6 a0 	ldl	t5,0(t5)
 9d4:	06 04 a6 43 	addq	gp,t5,t5
 9d8:	00 00 e6 6b 	jmp	(t5)
 9dc:	00 00 fe 2f 	unop	
 9e0:	40 08 7e a4 	ldq	t2,2112(sp)
 9e4:	00 00 e3 b6 	stq	t9,0(t2)
 9e8:	2c fe ff c3 	br	29c <__gettextparse+0x9c>
 9ec:	00 00 fe 2f 	unop	
 9f0:	02 00 b6 20 	lda	t4,2(t8)
 9f4:	01 00 56 2c 	ldq_u	t1,1(t8)
 9f8:	50 08 9e a4 	ldq	t3,2128(sp)
 9fc:	42 0f 45 48 	extqh	t1,t4,t1
 a00:	82 17 47 48 	sra	t1,0x38,t1
 a04:	a2 b5 47 40 	cmpeq	t1,0x3d,t1
 a08:	b3 00 40 f4 	bne	t1,cd8 <__gettextparse+0xad8>
 a0c:	22 16 9e 48 	zapnot	t3,0xf0,t1
 a10:	40 08 7e a4 	ldq	t2,2112(sp)
 a14:	03 01 bf 20 	lda	t4,259
 a18:	02 34 41 44 	or	t1,0x9,t1
 a1c:	50 08 5e b4 	stq	t1,2128(sp)
 a20:	00 00 03 b5 	stq	t7,0(t2)
 a24:	07 00 1f 21 	lda	t7,7
 a28:	22 fe ff c3 	br	2b4 <__gettextparse+0xb4>
 a2c:	00 00 fe 2f 	unop	
 a30:	50 08 9e a4 	ldq	t3,2128(sp)
 a34:	05 01 bf 20 	lda	t4,261
 a38:	40 08 7e a4 	ldq	t2,2112(sp)
 a3c:	22 16 9e 48 	zapnot	t3,0xf0,t1
 a40:	00 00 03 b5 	stq	t7,0(t2)
 a44:	09 00 1f 21 	lda	t7,9
 a48:	02 74 40 44 	or	t1,0x3,t1
 a4c:	50 08 5e b4 	stq	t1,2128(sp)
 a50:	18 fe ff c3 	br	2b4 <__gettextparse+0xb4>
 a54:	00 00 fe 2f 	unop	
 a58:	1f 04 ff 47 	nop	
 a5c:	00 00 fe 2f 	unop	
 a60:	50 08 9e a4 	ldq	t3,2128(sp)
 a64:	04 01 bf 20 	lda	t4,260
 a68:	40 08 7e a4 	ldq	t2,2112(sp)
 a6c:	22 16 9e 48 	zapnot	t3,0xf0,t1
 a70:	00 00 03 b5 	stq	t7,0(t2)
 a74:	08 00 1f 21 	lda	t7,8
 a78:	02 f4 40 44 	or	t1,0x7,t1
 a7c:	50 08 5e b4 	stq	t1,2128(sp)
 a80:	0c fe ff c3 	br	2b4 <__gettextparse+0xb4>
 a84:	00 00 fe 2f 	unop	
 a88:	1f 04 ff 47 	nop	
 a8c:	00 00 fe 2f 	unop	
 a90:	50 08 9e a4 	ldq	t3,2128(sp)
 a94:	04 01 bf 20 	lda	t4,260
 a98:	40 08 7e a4 	ldq	t2,2112(sp)
 a9c:	22 16 9e 48 	zapnot	t3,0xf0,t1
 aa0:	00 00 03 b5 	stq	t7,0(t2)
 aa4:	08 00 1f 21 	lda	t7,8
 aa8:	02 d4 40 44 	or	t1,0x6,t1
 aac:	50 08 5e b4 	stq	t1,2128(sp)
 ab0:	00 fe ff c3 	br	2b4 <__gettextparse+0xb4>
 ab4:	00 00 fe 2f 	unop	
 ab8:	1f 04 ff 47 	nop	
 abc:	00 00 fe 2f 	unop	
 ac0:	02 00 f6 22 	lda	t9,2(t8)
 ac4:	01 00 d6 2c 	ldq_u	t5,1(t8)
 ac8:	46 0f d7 48 	extqh	t5,t9,t5
 acc:	86 17 c7 48 	sra	t5,0x38,t5
 ad0:	a2 05 c2 40 	cmpeq	t5,t1,t1
 ad4:	c2 ff 5f f4 	bne	t1,9e0 <__gettextparse+0x7e0>
 ad8:	00 01 bf 20 	lda	t4,256
 adc:	40 08 7e a4 	ldq	t2,2112(sp)
 ae0:	00 00 03 b5 	stq	t7,0(t2)
 ae4:	01 00 1f 21 	lda	t7,1
 ae8:	f2 fd ff c3 	br	2b4 <__gettextparse+0xb4>
 aec:	00 00 fe 2f 	unop	
 af0:	50 08 9e a4 	ldq	t3,2128(sp)
 af4:	05 01 bf 20 	lda	t4,261
 af8:	40 08 7e a4 	ldq	t2,2112(sp)
 afc:	22 16 9e 48 	zapnot	t3,0xf0,t1
 b00:	00 00 03 b5 	stq	t7,0(t2)
 b04:	09 00 1f 21 	lda	t7,9
 b08:	02 b4 40 44 	or	t1,0x5,t1
 b0c:	50 08 5e b4 	stq	t1,2128(sp)
 b10:	e8 fd ff c3 	br	2b4 <__gettextparse+0xb4>
 b14:	00 00 fe 2f 	unop	
 b18:	1f 04 ff 47 	nop	
 b1c:	00 00 fe 2f 	unop	
 b20:	02 00 b6 20 	lda	t4,2(t8)
 b24:	01 00 56 2c 	ldq_u	t1,1(t8)
 b28:	42 0f 45 48 	extqh	t1,t4,t1
 b2c:	82 17 47 48 	sra	t1,0x38,t1
 b30:	a2 b5 47 40 	cmpeq	t1,0x3d,t1
 b34:	70 00 40 f4 	bne	t1,cf8 <__gettextparse+0xaf8>
 b38:	21 00 bf 20 	lda	t4,33
 b3c:	40 08 5e a4 	ldq	t1,2112(sp)
 b40:	00 00 02 b5 	stq	t7,0(t1)
 b44:	0a 00 1f 21 	lda	t7,10
 b48:	da fd ff c3 	br	2b4 <__gettextparse+0xb4>
 b4c:	00 00 fe 2f 	unop	
 b50:	08 04 ff 47 	clr	t7
 b54:	40 08 5e a4 	ldq	t1,2112(sp)
 b58:	05 04 ff 47 	clr	t4
 b5c:	00 00 c2 b6 	stq	t8,0(t1)
 b60:	d5 fd ff c3 	br	2b8 <__gettextparse+0xb8>
 b64:	00 00 fe 2f 	unop	
 b68:	1f 04 ff 47 	nop	
 b6c:	00 00 fe 2f 	unop	
 b70:	02 00 b6 20 	lda	t4,2(t8)
 b74:	01 00 56 2c 	ldq_u	t1,1(t8)
 b78:	42 0f 45 48 	extqh	t1,t4,t1
 b7c:	82 17 47 48 	sra	t1,0x38,t1
 b80:	a2 b5 47 40 	cmpeq	t1,0x3d,t1
 b84:	00 ff 5f e4 	beq	t1,788 <__gettextparse+0x588>
 b88:	50 08 9e a4 	ldq	t3,2128(sp)
 b8c:	06 00 1f 21 	lda	t7,6
 b90:	40 08 7e a4 	ldq	t2,2112(sp)
 b94:	22 16 9e 48 	zapnot	t3,0xf0,t1
 b98:	00 00 a3 b4 	stq	t4,0(t2)
 b9c:	02 01 bf 20 	lda	t4,258
 ba0:	02 94 41 44 	or	t1,0xc,t1
 ba4:	50 08 5e b4 	stq	t1,2128(sp)
 ba8:	c2 fd ff c3 	br	2b4 <__gettextparse+0xb4>
 bac:	00 00 fe 2f 	unop	
 bb0:	02 00 b6 20 	lda	t4,2(t8)
 bb4:	01 00 56 2c 	ldq_u	t1,1(t8)
 bb8:	50 08 9e a4 	ldq	t3,2128(sp)
 bbc:	42 0f 45 48 	extqh	t1,t4,t1
 bc0:	82 17 47 48 	sra	t1,0x38,t1
 bc4:	a2 b5 47 40 	cmpeq	t1,0x3d,t1
 bc8:	3b 00 40 f4 	bne	t1,cb8 <__gettextparse+0xab8>
 bcc:	22 16 9e 48 	zapnot	t3,0xf0,t1
 bd0:	40 08 7e a4 	ldq	t2,2112(sp)
 bd4:	03 01 bf 20 	lda	t4,259
 bd8:	02 14 41 44 	or	t1,0x8,t1
 bdc:	50 08 5e b4 	stq	t1,2128(sp)
 be0:	00 00 03 b5 	stq	t7,0(t2)
 be4:	07 00 1f 21 	lda	t7,7
 be8:	b2 fd ff c3 	br	2b4 <__gettextparse+0xb4>
 bec:	00 00 fe 2f 	unop	
 bf0:	02 00 d6 20 	lda	t5,2(t8)
 bf4:	01 00 56 2c 	ldq_u	t1,1(t8)
 bf8:	25 11 a6 40 	subl	t4,0x30,t4
 bfc:	42 0f 46 48 	extqh	t1,t5,t1
 c00:	82 17 47 48 	sra	t1,0x38,t1
 c04:	22 11 46 40 	subl	t1,0x30,t1
 c08:	06 f0 5f 44 	and	t1,0xff,t5
 c0c:	a6 37 c1 40 	cmpule	t5,0x9,t5
 c10:	0e 00 c0 e4 	beq	t5,c4c <__gettextparse+0xa4c>
 c14:	01 00 08 21 	lda	t7,1(t7)
 c18:	17 04 e8 47 	mov	t7,t9
 c1c:	01 00 08 21 	lda	t7,1(t7)
 c20:	45 04 a5 40 	s4addq	t4,t4,t4
 c24:	00 00 d7 2c 	ldq_u	t5,0(t9)
 c28:	02 00 e2 43 	sextl	t1,t1
 c2c:	05 04 a5 40 	addq	t4,t4,t4
 c30:	46 0f c8 48 	extqh	t5,t7,t5
 c34:	05 04 45 40 	addq	t1,t4,t4
 c38:	82 17 c7 48 	sra	t5,0x38,t1
 c3c:	22 11 46 40 	subl	t1,0x30,t1
 c40:	06 f0 5f 44 	and	t1,0xff,t5
 c44:	a6 37 c1 40 	cmpule	t5,0x9,t5
 c48:	f3 ff df f4 	bne	t5,c18 <__gettextparse+0xa18>
 c4c:	40 08 7e a4 	ldq	t2,2112(sp)
 c50:	50 08 be b4 	stq	t4,2128(sp)
 c54:	0b 00 1f 21 	lda	t7,11
 c58:	06 01 bf 20 	lda	t4,262
 c5c:	00 00 e3 b6 	stq	t9,0(t2)
 c60:	94 fd ff c3 	br	2b4 <__gettextparse+0xb4>
 c64:	00 00 fe 2f 	unop	
 c68:	1f 04 ff 47 	nop	
 c6c:	00 00 fe 2f 	unop	
 c70:	50 08 9e a4 	ldq	t3,2128(sp)
 c74:	05 01 bf 20 	lda	t4,261
 c78:	40 08 7e a4 	ldq	t2,2112(sp)
 c7c:	22 16 9e 48 	zapnot	t3,0xf0,t1
 c80:	00 00 03 b5 	stq	t7,0(t2)
 c84:	09 00 1f 21 	lda	t7,9
 c88:	02 94 40 44 	or	t1,0x4,t1
 c8c:	50 08 5e b4 	stq	t1,2128(sp)
 c90:	88 fd ff c3 	br	2b4 <__gettextparse+0xb4>
 c94:	09 04 ed 47 	mov	s4,s0
 c98:	01 00 5f 21 	lda	s1,1
 c9c:	01 fe ff c3 	br	4a4 <__gettextparse+0x2a4>
 ca0:	09 04 ed 47 	mov	s4,s0
 ca4:	02 00 5f 21 	lda	s1,2
 ca8:	fe fd ff c3 	br	4a4 <__gettextparse+0x2a4>
 cac:	09 04 ef 47 	mov	fp,s0
 cb0:	01 00 5f 21 	lda	s1,1
 cb4:	fe fd ff c3 	br	4b0 <__gettextparse+0x2b0>
 cb8:	22 16 9e 48 	zapnot	t3,0xf0,t1
 cbc:	40 08 7e a4 	ldq	t2,2112(sp)
 cc0:	07 00 1f 21 	lda	t7,7
 cc4:	02 54 41 44 	or	t1,0xa,t1
 cc8:	50 08 5e b4 	stq	t1,2128(sp)
 ccc:	00 00 a3 b4 	stq	t4,0(t2)
 cd0:	03 01 bf 20 	lda	t4,259
 cd4:	77 fd ff c3 	br	2b4 <__gettextparse+0xb4>
 cd8:	22 16 9e 48 	zapnot	t3,0xf0,t1
 cdc:	40 08 7e a4 	ldq	t2,2112(sp)
 ce0:	07 00 1f 21 	lda	t7,7
 ce4:	02 74 41 44 	or	t1,0xb,t1
 ce8:	50 08 5e b4 	stq	t1,2128(sp)
 cec:	00 00 a3 b4 	stq	t4,0(t2)
 cf0:	03 01 bf 20 	lda	t4,259
 cf4:	6f fd ff c3 	br	2b4 <__gettextparse+0xb4>
 cf8:	50 08 9e a4 	ldq	t3,2128(sp)
 cfc:	06 00 1f 21 	lda	t7,6
 d00:	40 08 7e a4 	ldq	t2,2112(sp)
 d04:	22 16 9e 48 	zapnot	t3,0xf0,t1
 d08:	00 00 a3 b4 	stq	t4,0(t2)
 d0c:	02 01 bf 20 	lda	t4,258
 d10:	02 b4 41 44 	or	t1,0xd,t1
 d14:	50 08 5e b4 	stq	t1,2128(sp)
 d18:	66 fd ff c3 	br	2b4 <__gettextparse+0xb4>
 d1c:	00 00 fe 2f 	unop
/scratch/jmyers/glibc/many9/build/compilers/alpha-linux-gnu/glibc/alpha-linux-gnu/intl/plural.c:527:1: note: yytranslate = "\000\002\002\002\002\002\002\002\002\002\002\002\002\002\002\002\002\002\002\002\002\002\002\002\002\002\002\002\002\002\002\002\002\012\002\002\002\002\005\002\016\017\002\002\002\002\002\002\002\002\002\002\002\002\002\002\002\002\014\002\002\002\002\003\002\002\002\002\002\002\002\002\002\002\002\002\002\002\002\002\002\002\002\002\002\002\002\002\002\002\002\002\002\002\002\002\002\002\002\002\002\002\002\002\002\002\002\002\002\002\015\002\002\002\002\002\002\002\002\002\002\002\002\002\004\002\002\002\002\002\002\002\002\002\002\002\002\002\002\002\002\002\002\002\002\002\002\002\002\002\002\002\002\002\002\002\002\002\002\002\002\002\002\002\002\002\002\002\002\002\002\002\002\002\002\002\002\002\002\002\002\002\002\002\002\002\002\002\002\002\002\002\002\002\002\002\002\002\002\002\002\002\002\002\002\002\002\002\002\002\002\002\002\002\002\002\002\002\002\002\002\002\002\002\002\002\002\002\002\002\002\002\002\002\002\002\002\002\002\002\002\002\002\002\002\002\002\002\002\002\002\002\002\002\002\002\001\002\006\007\010\011"
/scratch/jmyers/glibc/many9/build/compilers/alpha-linux-gnu/glibc/alpha-linux-gnu/intl/plural.c:600:1: note: yypact = "\37777777767\37777777767\37777777766\37777777766\37777777767\010$\37777777766\015\37777777766\37777777767\37777777767\37777777767\37777777767\37777777767\37777777767\37777777767\37777777766\032)-\022\37777777776\016\37777777766\37777777767"
/scratch/jmyers/glibc/many9/build/compilers/alpha-linux-gnu/glibc/alpha-linux-gnu/intl/plural.c:610:1: note: yydefact = "\000\000\014\013\000\000\002\012\000\001\000\000\000\000\000\000\000\015\000\004\005\006\007\010\011\000"
/scratch/jmyers/glibc/many9/build/compilers/alpha-linux-gnu/glibc/alpha-linux-gnu/intl/plural.c:618:1: note: yypgoto = "\37777777766\37777777766"
/scratch/jmyers/glibc/many9/build/compilers/alpha-linux-gnu/glibc/alpha-linux-gnu/intl/plural.c:624:1: note: yydefgoto = "\37777777777\005"
/scratch/jmyers/glibc/many9/build/compilers/alpha-linux-gnu/glibc/alpha-linux-gnu/intl/plural.c:632:1: note: yytable = "\007\001\002\010\003\004\017\020\011\022\023\024\025\026\027\030\012\013\014\015\016\017\020\020\032\016\017\020\021\012\013\014\015\016\017\020\000\000\031\012\013\014\015\016\017\020\014\015\016\017\020\015\016\017"
/scratch/jmyers/glibc/many9/build/compilers/alpha-linux-gnu/glibc/alpha-linux-gnu/intl/plural.c:642:1: note: yycheck = "\001\012\013\004\015\016\010\011\000\012\013\014\015\016\017\020\003\004\005\006\007\010\011\011\031\007\010\011\017\003\004\005\006\007\010\011\37777777777\37777777777\014\003\004\005\006\007\010\011\005\006\007\010\011\006\007\010"
/scratch/jmyers/glibc/many9/build/compilers/alpha-linux-gnu/glibc/alpha-linux-gnu/intl/plural.c:654:1: note: yystos = "\000\012\013\015\016\021\022\022\022\000\003\004\005\006\007\010\011\017\022\022\022\022\022\022\022\014"
/scratch/jmyers/glibc/many9/build/compilers/alpha-linux-gnu/glibc/alpha-linux-gnu/intl/plural.c:662:1: note: yyr1 = "\000\020\021\022\022\022\022\022\022\022\022\022\022"
/scratch/jmyers/glibc/many9/build/compilers/alpha-linux-gnu/glibc/alpha-linux-gnu/intl/plural.c:669:1: note: yyr2 = "\000\002\001\005\003\003\003\003\003\003\002\001\001"
Jeff Law Aug. 15, 2018, 9:14 p.m. UTC | #25
On 08/15/2018 03:02 PM, Martin Sebor wrote:
> On 08/15/2018 06:07 AM, Joseph Myers wrote:
>> On Tue, 14 Aug 2018, Martin Sebor wrote:
>>
>>>> This is with Bison 3.0.4, should the version used to produce
>>>> intl/plural.c
>>>> prove relevant.
>>>
>>> Can you send me the translation unit and the options it was compiled
>>> with that triggered the errors?
>>
>> I've attached plural.i.  The error is a static link error linking sln,
>> but
>> maybe comparing results of compiling plural.i before and after the
>> changes
>> may be enlightening (unless it's actually a difference in code elsewhere
>> in glibc causing a link error reported in plural.o).
>>
>> Compiled with:
>>
>> alpha-glibc-linux-gnu-gcc
>> /scratch/jmyers/glibc/many9/build/compilers/alpha-linux-gnu/glibc/alpha-linux-gnu/intl/plural.c
>>
>> -c -std=gnu11 -fgnu89-inline  -O2 -Wall -Werror -Wundef -Wwrite-strings
>> -fmerge-all-constants -fno-stack-protector -frounding-math -g
>> -Wstrict-prototypes -Wold-style-definition -fno-math-errno
>> -mlong-double-128 -mieee -mfp-rounding-mode=d    
>> -ftls-model=initial-exec
>> -I../include
>> -I/scratch/jmyers/glibc/many9/build/compilers/alpha-linux-gnu/glibc/alpha-linux-gnu/intl
>>
>> -I/scratch/jmyers/glibc/many9/build/compilers/alpha-linux-gnu/glibc/alpha-linux-gnu
>>
>> -I../sysdeps/unix/sysv/linux/alpha/alpha
>> -I../sysdeps/unix/sysv/linux/alpha/fpu  -I../sysdeps/alpha/fpu
>> -I../sysdeps/unix/sysv/linux/alpha  -I../sysdeps/alpha/nptl
>> -I../sysdeps/unix/sysv/linux/wordsize-64 
>> -I../sysdeps/ieee754/ldbl-64-128
>> -I../sysdeps/ieee754/ldbl-opt  -I../sysdeps/unix/sysv/linux/include
>> -I../sysdeps/unix/sysv/linux  -I../sysdeps/nptl  -I../sysdeps/pthread
>> -I../sysdeps/gnu  -I../sysdeps/unix/inet  -I../sysdeps/unix/sysv
>> -I../sysdeps/unix/alpha  -I../sysdeps/unix  -I../sysdeps/posix
>> -I../sysdeps/alpha  -I../sysdeps/wordsize-64
>> -I../sysdeps/ieee754/ldbl-128  -I../sysdeps/ieee754/dbl-64/wordsize-64
>> -I../sysdeps/ieee754/dbl-64  -I../sysdeps/ieee754/flt-32
>> -I../sysdeps/ieee754  -I../sysdeps/generic  -I.. -I../libio -I.
>> -D_LIBC_REENTRANT -include
>> /scratch/jmyers/glibc/many9/build/compilers/alpha-linux-gnu/glibc/alpha-linux-gnu/libc-modules.h
>>
>> -DMODULE_NAME=libc -include ../include/libc-symbols.h
>> -DTOP_NAMESPACE=glibc -D'LOCALEDIR="/usr/share/locale"'
>> -D'LOCALE_ALIAS_PATH="/usr/share/locale"' -o
>> /scratch/jmyers/glibc/many9/build/compilers/alpha-linux-gnu/glibc/alpha-linux-gnu/intl/plural.o
>>
>> -MD -MP -MF
>> /scratch/jmyers/glibc/many9/build/compilers/alpha-linux-gnu/glibc/alpha-linux-gnu/intl/plural.o.dt
>>
>> -MT
>> /scratch/jmyers/glibc/many9/build/compilers/alpha-linux-gnu/glibc/alpha-linux-gnu/intl/plural.o
>>
>>
> 
> Thanks.  I don't see anything obviously wrong but I don't know
> much about Alpha assembly.  Attached are the two .s files, with
> (plural-new.s) and without (plural-old.s) the array-to-string
> transformation.
> 
> There are also only a handful of transformed arrays in the file
> and they all look reasonable to me (see the attachment named
> plural-array-to-string.txt).  The only arrays in the .sdata
> section are yydefgoto and yypgoto, both before and after.
> They are each just 3 bytes in size.
> 
> There is one unusual difference in the loads of one of them in
> the assembly emitted by GCC for __gettextparse.
> 
> Before:
> 
>     ldah $22,yypgoto($29)                !gprelhigh
>     ...
>     lda $2,yypgoto($22)                !gprellow
> 
> After:
> 
>     ldah $2,yypgoto+2305843009213693936($29)    !gprelhigh
>     ...
>     lda $2,yypgoto+2305843009213693936($2)        !gprellow
> 
> I don't know if it's significant -- the lda instruction uses
> just the least significant 16 bits of the constant displacement,
> shifted left by 16.  I don't see any obviously bogus constants
> in the disassembly produced by objdump.
> 
> I'll need some help from someone who knows more about Alpha
> to understand what's going on.
I wonder if the change to how we set up the initializers is ultimately
changing the section those go into and ultimately causing an overflow of
the .sdata section.

Jeff
> 
> Martin
Jeff Law Aug. 15, 2018, 9:34 p.m. UTC | #26
On 08/15/2018 03:02 PM, Martin Sebor wrote:
> On 08/15/2018 06:07 AM, Joseph Myers wrote:
>> On Tue, 14 Aug 2018, Martin Sebor wrote:
>>
>>>> This is with Bison 3.0.4, should the version used to produce
>>>> intl/plural.c
>>>> prove relevant.
>>>
>>> Can you send me the translation unit and the options it was compiled
>>> with that triggered the errors?
>>
>> I've attached plural.i.  The error is a static link error linking sln,
>> but
>> maybe comparing results of compiling plural.i before and after the
>> changes
>> may be enlightening (unless it's actually a difference in code elsewhere
>> in glibc causing a link error reported in plural.o).
>>
>> Compiled with:
>>
>> alpha-glibc-linux-gnu-gcc
>> /scratch/jmyers/glibc/many9/build/compilers/alpha-linux-gnu/glibc/alpha-linux-gnu/intl/plural.c
>>
>> -c -std=gnu11 -fgnu89-inline  -O2 -Wall -Werror -Wundef -Wwrite-strings
>> -fmerge-all-constants -fno-stack-protector -frounding-math -g
>> -Wstrict-prototypes -Wold-style-definition -fno-math-errno
>> -mlong-double-128 -mieee -mfp-rounding-mode=d    
>> -ftls-model=initial-exec
>> -I../include
>> -I/scratch/jmyers/glibc/many9/build/compilers/alpha-linux-gnu/glibc/alpha-linux-gnu/intl
>>
>> -I/scratch/jmyers/glibc/many9/build/compilers/alpha-linux-gnu/glibc/alpha-linux-gnu
>>
>> -I../sysdeps/unix/sysv/linux/alpha/alpha
>> -I../sysdeps/unix/sysv/linux/alpha/fpu  -I../sysdeps/alpha/fpu
>> -I../sysdeps/unix/sysv/linux/alpha  -I../sysdeps/alpha/nptl
>> -I../sysdeps/unix/sysv/linux/wordsize-64 
>> -I../sysdeps/ieee754/ldbl-64-128
>> -I../sysdeps/ieee754/ldbl-opt  -I../sysdeps/unix/sysv/linux/include
>> -I../sysdeps/unix/sysv/linux  -I../sysdeps/nptl  -I../sysdeps/pthread
>> -I../sysdeps/gnu  -I../sysdeps/unix/inet  -I../sysdeps/unix/sysv
>> -I../sysdeps/unix/alpha  -I../sysdeps/unix  -I../sysdeps/posix
>> -I../sysdeps/alpha  -I../sysdeps/wordsize-64
>> -I../sysdeps/ieee754/ldbl-128  -I../sysdeps/ieee754/dbl-64/wordsize-64
>> -I../sysdeps/ieee754/dbl-64  -I../sysdeps/ieee754/flt-32
>> -I../sysdeps/ieee754  -I../sysdeps/generic  -I.. -I../libio -I.
>> -D_LIBC_REENTRANT -include
>> /scratch/jmyers/glibc/many9/build/compilers/alpha-linux-gnu/glibc/alpha-linux-gnu/libc-modules.h
>>
>> -DMODULE_NAME=libc -include ../include/libc-symbols.h
>> -DTOP_NAMESPACE=glibc -D'LOCALEDIR="/usr/share/locale"'
>> -D'LOCALE_ALIAS_PATH="/usr/share/locale"' -o
>> /scratch/jmyers/glibc/many9/build/compilers/alpha-linux-gnu/glibc/alpha-linux-gnu/intl/plural.o
>>
>> -MD -MP -MF
>> /scratch/jmyers/glibc/many9/build/compilers/alpha-linux-gnu/glibc/alpha-linux-gnu/intl/plural.o.dt
>>
>> -MT
>> /scratch/jmyers/glibc/many9/build/compilers/alpha-linux-gnu/glibc/alpha-linux-gnu/intl/plural.o
>>
>>
> 
> Thanks.  I don't see anything obviously wrong but I don't know
> much about Alpha assembly.  Attached are the two .s files, with
> (plural-new.s) and without (plural-old.s) the array-to-string
> transformation.
I'd focus on these  insns which correspond to the error from the linker:

They're in plural.o within the fucntion gettextparse


        ldah $2,yypgoto+2305843009213693936($29)                !gprelhigh

Something certainly doesn't look right...

At the .o level this turns into:
218:   00 00 5d 24     ldah    t1,0(gp)
                        218: GPRELHIGH  .sdata+0x1ffffffffffffff3


300:   00 00 5d 24     ldah    t1,0(gp)
                        300: GPRELHIGH  .sdata+0x1ffffffffffffff3

It's not really a matter of what the instruction does, but a matter of
the relocation.  You'd have to look at the definition of GPRELHIGH which
you can find in BFD.


Jeff
Martin Sebor Aug. 16, 2018, 3:23 p.m. UTC | #27
On 08/15/2018 03:34 PM, Jeff Law wrote:
> On 08/15/2018 03:02 PM, Martin Sebor wrote:
>> On 08/15/2018 06:07 AM, Joseph Myers wrote:
>>> On Tue, 14 Aug 2018, Martin Sebor wrote:
>>>
>>>>> This is with Bison 3.0.4, should the version used to produce
>>>>> intl/plural.c
>>>>> prove relevant.
>>>>
>>>> Can you send me the translation unit and the options it was compiled
>>>> with that triggered the errors?
>>>
>>> I've attached plural.i.  The error is a static link error linking sln,
>>> but
>>> maybe comparing results of compiling plural.i before and after the
>>> changes
>>> may be enlightening (unless it's actually a difference in code elsewhere
>>> in glibc causing a link error reported in plural.o).
>>>
>>> Compiled with:
>>>
>>> alpha-glibc-linux-gnu-gcc
>>> /scratch/jmyers/glibc/many9/build/compilers/alpha-linux-gnu/glibc/alpha-linux-gnu/intl/plural.c
>>>
>>> -c -std=gnu11 -fgnu89-inline  -O2 -Wall -Werror -Wundef -Wwrite-strings
>>> -fmerge-all-constants -fno-stack-protector -frounding-math -g
>>> -Wstrict-prototypes -Wold-style-definition -fno-math-errno
>>> -mlong-double-128 -mieee -mfp-rounding-mode=d
>>> -ftls-model=initial-exec
>>> -I../include
>>> -I/scratch/jmyers/glibc/many9/build/compilers/alpha-linux-gnu/glibc/alpha-linux-gnu/intl
>>>
>>> -I/scratch/jmyers/glibc/many9/build/compilers/alpha-linux-gnu/glibc/alpha-linux-gnu
>>>
>>> -I../sysdeps/unix/sysv/linux/alpha/alpha
>>> -I../sysdeps/unix/sysv/linux/alpha/fpu  -I../sysdeps/alpha/fpu
>>> -I../sysdeps/unix/sysv/linux/alpha  -I../sysdeps/alpha/nptl
>>> -I../sysdeps/unix/sysv/linux/wordsize-64
>>> -I../sysdeps/ieee754/ldbl-64-128
>>> -I../sysdeps/ieee754/ldbl-opt  -I../sysdeps/unix/sysv/linux/include
>>> -I../sysdeps/unix/sysv/linux  -I../sysdeps/nptl  -I../sysdeps/pthread
>>> -I../sysdeps/gnu  -I../sysdeps/unix/inet  -I../sysdeps/unix/sysv
>>> -I../sysdeps/unix/alpha  -I../sysdeps/unix  -I../sysdeps/posix
>>> -I../sysdeps/alpha  -I../sysdeps/wordsize-64
>>> -I../sysdeps/ieee754/ldbl-128  -I../sysdeps/ieee754/dbl-64/wordsize-64
>>> -I../sysdeps/ieee754/dbl-64  -I../sysdeps/ieee754/flt-32
>>> -I../sysdeps/ieee754  -I../sysdeps/generic  -I.. -I../libio -I.
>>> -D_LIBC_REENTRANT -include
>>> /scratch/jmyers/glibc/many9/build/compilers/alpha-linux-gnu/glibc/alpha-linux-gnu/libc-modules.h
>>>
>>> -DMODULE_NAME=libc -include ../include/libc-symbols.h
>>> -DTOP_NAMESPACE=glibc -D'LOCALEDIR="/usr/share/locale"'
>>> -D'LOCALE_ALIAS_PATH="/usr/share/locale"' -o
>>> /scratch/jmyers/glibc/many9/build/compilers/alpha-linux-gnu/glibc/alpha-linux-gnu/intl/plural.o
>>>
>>> -MD -MP -MF
>>> /scratch/jmyers/glibc/many9/build/compilers/alpha-linux-gnu/glibc/alpha-linux-gnu/intl/plural.o.dt
>>>
>>> -MT
>>> /scratch/jmyers/glibc/many9/build/compilers/alpha-linux-gnu/glibc/alpha-linux-gnu/intl/plural.o
>>>
>>>
>>
>> Thanks.  I don't see anything obviously wrong but I don't know
>> much about Alpha assembly.  Attached are the two .s files, with
>> (plural-new.s) and without (plural-old.s) the array-to-string
>> transformation.
> I'd focus on these  insns which correspond to the error from the linker:
>
> They're in plural.o within the fucntion gettextparse
>
>
>         ldah $2,yypgoto+2305843009213693936($29)                !gprelhigh
>
> Something certainly doesn't look right...

Thanks.  I also get the same exact same assembly with both
forms of initializers for the two constant arrays, i.e.,

   static const yytype_int8 yypgoto[3] = "\366\366\377";
   static const yytype_int8 yydefgoto[3] = "\377\005\006";

and

   static const yytype_int8 yypgoto[] = { -10, -10, -1 };
   static const yytype_int8 yydefgoto[] = { -1, 5, 6 };

They end up in the .sdata section either way (the former
both with and without the GCC change as might be expected):

         .section        .sdata,"aws"
         .type   yydefgoto, @object
         .size   yydefgoto, 3
   yydefgoto:
         .ascii  "\377\005\006"
         .type   yypgoto, @object
         .size   yypgoto, 3
   yypgoto:
         .ascii  "\366\366\377"
         .section        .rodata

and also before the GCC change:

         .section        .sdata,"aws"
         .type   yydefgoto, @object
         .size   yydefgoto, 3
   yydefgoto:
         .byte   -1
         .byte   5
         .byte   6
         .type   yypgoto, @object
         .size   yypgoto, 3
   yypgoto:
         .byte   -10
         .byte   -10
         .byte   -1

> At the .o level this turns into:
> 218:   00 00 5d 24     ldah    t1,0(gp)
>                         218: GPRELHIGH  .sdata+0x1ffffffffffffff3
>
>
> 300:   00 00 5d 24     ldah    t1,0(gp)
>                         300: GPRELHIGH  .sdata+0x1ffffffffffffff3
>
> It's not really a matter of what the instruction does, but a matter of
> the relocation.  You'd have to look at the definition of GPRELHIGH which
> you can find in BFD.

The definitions match the assembly with both kinds of
initializers, and with the string literal also with GCC before
the change:

   0000000000000218 GPRELHIGH         .sdata+0x1ffffffffffffff3
   0000000000000238 GPRELLOW          .sdata+0x1ffffffffffffff3
   0000000000000300 GPRELHIGH         .sdata+0x1ffffffffffffff3
   0000000000000308 GPRELLOW          .sdata+0x1ffffffffffffff3
   0000000000000458 GPRELHIGH         .sdata+0x0000000000000003
   0000000000000468 GPRELLOW          .sdata+0x0000000000000003

vs the array form before the GCC change:

   0000000000000468 GPRELHIGH         .sdata+0x0000000000000003
   0000000000000488 GPRELLOW          .sdata+0x0000000000000003
   000000000000057c GPRELHIGH         .sdata
   0000000000000580 GPRELLOW          .sdata

So it seems as though using the string literal as an initializer
tickles a latent bug in GCC and the question is where.

Martin
Jeff Law Aug. 16, 2018, 3:32 p.m. UTC | #28
On 08/16/2018 09:23 AM, Martin Sebor wrote:
> On 08/15/2018 03:34 PM, Jeff Law wrote:
>> On 08/15/2018 03:02 PM, Martin Sebor wrote:
>>> On 08/15/2018 06:07 AM, Joseph Myers wrote:
>>>> On Tue, 14 Aug 2018, Martin Sebor wrote:
>>>>
>>>>>> This is with Bison 3.0.4, should the version used to produce
>>>>>> intl/plural.c
>>>>>> prove relevant.
>>>>>
>>>>> Can you send me the translation unit and the options it was compiled
>>>>> with that triggered the errors?
>>>>
>>>> I've attached plural.i.  The error is a static link error linking sln,
>>>> but
>>>> maybe comparing results of compiling plural.i before and after the
>>>> changes
>>>> may be enlightening (unless it's actually a difference in code
>>>> elsewhere
>>>> in glibc causing a link error reported in plural.o).
>>>>
>>>> Compiled with:
>>>>
>>>> alpha-glibc-linux-gnu-gcc
>>>> /scratch/jmyers/glibc/many9/build/compilers/alpha-linux-gnu/glibc/alpha-linux-gnu/intl/plural.c
>>>>
>>>>
>>>> -c -std=gnu11 -fgnu89-inline  -O2 -Wall -Werror -Wundef -Wwrite-strings
>>>> -fmerge-all-constants -fno-stack-protector -frounding-math -g
>>>> -Wstrict-prototypes -Wold-style-definition -fno-math-errno
>>>> -mlong-double-128 -mieee -mfp-rounding-mode=d
>>>> -ftls-model=initial-exec
>>>> -I../include
>>>> -I/scratch/jmyers/glibc/many9/build/compilers/alpha-linux-gnu/glibc/alpha-linux-gnu/intl
>>>>
>>>>
>>>> -I/scratch/jmyers/glibc/many9/build/compilers/alpha-linux-gnu/glibc/alpha-linux-gnu
>>>>
>>>>
>>>> -I../sysdeps/unix/sysv/linux/alpha/alpha
>>>> -I../sysdeps/unix/sysv/linux/alpha/fpu  -I../sysdeps/alpha/fpu
>>>> -I../sysdeps/unix/sysv/linux/alpha  -I../sysdeps/alpha/nptl
>>>> -I../sysdeps/unix/sysv/linux/wordsize-64
>>>> -I../sysdeps/ieee754/ldbl-64-128
>>>> -I../sysdeps/ieee754/ldbl-opt  -I../sysdeps/unix/sysv/linux/include
>>>> -I../sysdeps/unix/sysv/linux  -I../sysdeps/nptl  -I../sysdeps/pthread
>>>> -I../sysdeps/gnu  -I../sysdeps/unix/inet  -I../sysdeps/unix/sysv
>>>> -I../sysdeps/unix/alpha  -I../sysdeps/unix  -I../sysdeps/posix
>>>> -I../sysdeps/alpha  -I../sysdeps/wordsize-64
>>>> -I../sysdeps/ieee754/ldbl-128  -I../sysdeps/ieee754/dbl-64/wordsize-64
>>>> -I../sysdeps/ieee754/dbl-64  -I../sysdeps/ieee754/flt-32
>>>> -I../sysdeps/ieee754  -I../sysdeps/generic  -I.. -I../libio -I.
>>>> -D_LIBC_REENTRANT -include
>>>> /scratch/jmyers/glibc/many9/build/compilers/alpha-linux-gnu/glibc/alpha-linux-gnu/libc-modules.h
>>>>
>>>>
>>>> -DMODULE_NAME=libc -include ../include/libc-symbols.h
>>>> -DTOP_NAMESPACE=glibc -D'LOCALEDIR="/usr/share/locale"'
>>>> -D'LOCALE_ALIAS_PATH="/usr/share/locale"' -o
>>>> /scratch/jmyers/glibc/many9/build/compilers/alpha-linux-gnu/glibc/alpha-linux-gnu/intl/plural.o
>>>>
>>>>
>>>> -MD -MP -MF
>>>> /scratch/jmyers/glibc/many9/build/compilers/alpha-linux-gnu/glibc/alpha-linux-gnu/intl/plural.o.dt
>>>>
>>>>
>>>> -MT
>>>> /scratch/jmyers/glibc/many9/build/compilers/alpha-linux-gnu/glibc/alpha-linux-gnu/intl/plural.o
>>>>
>>>>
>>>>
>>>
>>> Thanks.  I don't see anything obviously wrong but I don't know
>>> much about Alpha assembly.  Attached are the two .s files, with
>>> (plural-new.s) and without (plural-old.s) the array-to-string
>>> transformation.
>> I'd focus on these  insns which correspond to the error from the linker:
>>
>> They're in plural.o within the fucntion gettextparse
>>
>>
>>         ldah $2,yypgoto+2305843009213693936($29)               
>> !gprelhigh
>>
>> Something certainly doesn't look right...
> 
> Thanks.  I also get the same exact same assembly with both
> forms of initializers for the two constant arrays, i.e.,
> 
>   static const yytype_int8 yypgoto[3] = "\366\366\377";
>   static const yytype_int8 yydefgoto[3] = "\377\005\006";
> 
> and
> 
>   static const yytype_int8 yypgoto[] = { -10, -10, -1 };
>   static const yytype_int8 yydefgoto[] = { -1, 5, 6 };
> 
> They end up in the .sdata section either way (the former
> both with and without the GCC change as might be expected):
> 
>         .section        .sdata,"aws"
>         .type   yydefgoto, @object
>         .size   yydefgoto, 3
>   yydefgoto:
>         .ascii  "\377\005\006"
>         .type   yypgoto, @object
>         .size   yypgoto, 3
>   yypgoto:
>         .ascii  "\366\366\377"
>         .section        .rodata
> 
> and also before the GCC change:
> 
>         .section        .sdata,"aws"
>         .type   yydefgoto, @object
>         .size   yydefgoto, 3
>   yydefgoto:
>         .byte   -1
>         .byte   5
>         .byte   6
>         .type   yypgoto, @object
>         .size   yypgoto, 3
>   yypgoto:
>         .byte   -10
>         .byte   -10
>         .byte   -1
> 
>> At the .o level this turns into:
>> 218:   00 00 5d 24     ldah    t1,0(gp)
>>                         218: GPRELHIGH  .sdata+0x1ffffffffffffff3
>>
>>
>> 300:   00 00 5d 24     ldah    t1,0(gp)
>>                         300: GPRELHIGH  .sdata+0x1ffffffffffffff3
>>
>> It's not really a matter of what the instruction does, but a matter of
>> the relocation.  You'd have to look at the definition of GPRELHIGH which
>> you can find in BFD.
> 
> The definitions match the assembly with both kinds of
> initializers, and with the string literal also with GCC before
> the change:
> 
>   0000000000000218 GPRELHIGH         .sdata+0x1ffffffffffffff3
>   0000000000000238 GPRELLOW          .sdata+0x1ffffffffffffff3
>   0000000000000300 GPRELHIGH         .sdata+0x1ffffffffffffff3
>   0000000000000308 GPRELLOW          .sdata+0x1ffffffffffffff3
>   0000000000000458 GPRELHIGH         .sdata+0x0000000000000003
>   0000000000000468 GPRELLOW          .sdata+0x0000000000000003
> 
> vs the array form before the GCC change:
> 
>   0000000000000468 GPRELHIGH         .sdata+0x0000000000000003
>   0000000000000488 GPRELLOW          .sdata+0x0000000000000003
>   000000000000057c GPRELHIGH         .sdata
>   0000000000000580 GPRELLOW          .sdata
> 
> So it seems as though using the string literal as an initializer
> tickles a latent bug in GCC and the question is where.
I'd start working backwards from alpha_print_operand_address using a
cross compiler.  I'd also get a -dap dump and look at the actual address
in the insn that's emitting the offending ldah instructions.

Jeff
diff mbox series

Patch

PR tree-optimization/71625 - missing strlen optimization on different array initialization style

gcc/c/ChangeLog:

	PR tree-optimization/71625
	* c-parser.c (c_parser_declaration_or_fndef): Call
	convert_braced_list_to_string.

gcc/c-family/ChangeLog:

	PR tree-optimization/71625
	* c-common.c (convert_braced_list_to_string): New function.
	* c-common.h (convert_braced_list_to_string): Declare it.

gcc/cp/ChangeLog:

	PR tree-optimization/71625
	* parser.c (cp_parser_init_declarator):  Call
	convert_braced_list_to_string.

gcc/testsuite/ChangeLog:

	PR tree-optimization/71625
	* g++.dg/init/string2.C: New test.
	* g++.dg/init/string3.C: New test.
	* gcc.dg/strlenopt-55.c: New test.

diff --git a/gcc/c-family/c-common.c b/gcc/c-family/c-common.c
index 422d668..9a93175 100644
--- a/gcc/c-family/c-common.c
+++ b/gcc/c-family/c-common.c
@@ -8345,4 +8345,72 @@  maybe_add_include_fixit (rich_location *richloc, const char *header)
   free (text);
 }
 
+/* Attempt to convert a braced array initializer list CTOR into
+   a STRING_CST for convenience and efficiency.  When non-null,
+   use EVAL to attempt to evalue constants (used by C++).
+   MAXELTS gives the maximum number of elements to accept.
+   Return the converted string on success or null on failure.  */
+
+tree
+convert_braced_list_to_string (tree ctor, tree (*eval)(tree),
+			       unsigned HOST_WIDE_INT maxelts)
+{
+  unsigned HOST_WIDE_INT nelts = CONSTRUCTOR_NELTS (ctor);
+
+  auto_vec<char> str;
+  str.reserve (nelts + 1);
+
+  unsigned HOST_WIDE_INT i;
+  tree index, value;
+
+  FOR_EACH_CONSTRUCTOR_ELT (CONSTRUCTOR_ELTS (ctor), i, index, value)
+    {
+      unsigned HOST_WIDE_INT idx = index ? tree_to_uhwi (index) : i;
+
+      /* auto_vec is limited to UINT_MAX elements.  */
+      if (idx > UINT_MAX)
+	return NULL_TREE;
+
+      /* Attempt to evaluate constants.  */
+      if (eval)
+	value = eval (value);
+
+      /* Avoid non-constant initializers.  */
+     if (!tree_fits_uhwi_p (value))
+	return NULL_TREE;
+
+      /* Skip over embedded nuls.  */
+      unsigned val = tree_to_uhwi (value);
+      if (!val)
+	continue;
+
+      /* Bail if the CTOR has a block of more than 256 embedded nuls
+	 due to implicitly initialized elements.  */
+      unsigned nelts = (idx - str.length ()) + 1;
+      if (nelts > 256)
+	return NULL_TREE;
+
+      if (nelts > 1)
+	{
+	  str.reserve (idx);
+	  str.quick_grow_cleared (idx);
+	}
+
+      if (idx > maxelts)
+	return NULL_TREE;
+
+      str.safe_insert (idx, val);
+    }
+
+  /* Append a nul for the empty initializer { } and for the last
+     explicit initializer in the loop above that is a nul.  */
+  if (!nelts || str.length () < i)
+    str.safe_push (0);
+
+  /* Build a string literal but return the embedded STRING_CST.  */
+  tree res = build_string_literal (str.length (), str.begin ());
+  res = TREE_OPERAND (TREE_OPERAND (res, 0), 0);
+  return res;
+}
+
 #include "gt-c-family-c-common.h"
diff --git a/gcc/c-family/c-common.h b/gcc/c-family/c-common.h
index fcec95b..343a1ae 100644
--- a/gcc/c-family/c-common.h
+++ b/gcc/c-family/c-common.h
@@ -1331,6 +1331,8 @@  extern void maybe_add_include_fixit (rich_location *, const char *);
 extern void maybe_suggest_missing_token_insertion (rich_location *richloc,
 						   enum cpp_ttype token_type,
 						   location_t prev_token_loc);
+extern tree convert_braced_list_to_string (tree, tree (*)(tree) = NULL,
+					   unsigned HOST_WIDE_INT = -1);
 
 #if CHECKING_P
 namespace selftest {
diff --git a/gcc/c/c-parser.c b/gcc/c/c-parser.c
index 7a92628..e12d270 100644
--- a/gcc/c/c-parser.c
+++ b/gcc/c/c-parser.c
@@ -2126,6 +2126,23 @@  c_parser_declaration_or_fndef (c_parser *parser, bool fndef_ok,
 	      if (d != error_mark_node)
 		{
 		  maybe_warn_string_init (init_loc, TREE_TYPE (d), init);
+
+		  /* Convert a string CONSTRUCTOR into a STRING_CST.  */
+		  tree valtype = TREE_TYPE (init.value);
+		  if (TREE_CODE (init.value) == CONSTRUCTOR
+		      && TREE_CODE (valtype) == ARRAY_TYPE)
+		    {
+		      valtype = TREE_TYPE (valtype);
+		      if (TYPE_STRING_FLAG (valtype))
+			if (tree str
+			    = convert_braced_list_to_string (init.value))
+			  {
+			    /* Replace the initializer with the string
+			       constant.  The resu*/
+			    init.value = str;
+			  }
+		    }
+
 		  finish_decl (d, init_loc, init.value,
 			       init.original_type, asm_name);
 		}
diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c
index d44a6b8..c35c2f1 100644
--- a/gcc/cp/parser.c
+++ b/gcc/cp/parser.c
@@ -19825,6 +19825,32 @@  cp_parser_init_declarator (cp_parser* parser,
 	    finish_lambda_scope ();
 	  if (initializer == error_mark_node)
 	    cp_parser_skip_to_end_of_statement (parser);
+	  else if (decl)
+	    {
+	      tree valtype = TREE_TYPE (decl);
+	      if (TREE_CODE (valtype) == ARRAY_TYPE
+		  && TYPE_STRING_FLAG (TREE_TYPE (valtype))
+		  && TYPE_MAIN_VARIANT (TREE_TYPE (valtype)) == char_type_node)
+		{
+		  /* If the array has an explicit bound, use it to
+		     constrain the size of the string.  */
+		  unsigned HOST_WIDE_INT maxelts = HOST_WIDE_INT_M1U;
+		  if (tree nelts = DECL_SIZE_UNIT (decl))
+		    if (tree_fits_uhwi_p (nelts))
+		      maxelts = tree_to_uhwi (nelts);
+
+		  /* Convert a string CONSTRUCTOR into a STRING_CST.  */
+		  if (TREE_CODE (initializer) == CONSTRUCTOR
+		      && TREE_TYPE (initializer) == init_list_type_node)
+		    {
+		      if (tree str
+			  = convert_braced_list_to_string (initializer,
+						   scalar_constant_value,
+						   maxelts))
+			initializer = str;
+		    }
+		}
+	    }
 	}
     }
 
diff --git a/gcc/testsuite/g++.dg/init/string2.C b/gcc/testsuite/g++.dg/init/string2.C
new file mode 100644
index 0000000..acb2f5b
--- /dev/null
+++ b/gcc/testsuite/g++.dg/init/string2.C
@@ -0,0 +1,49 @@ 
+// PR tree-optimization/71625 - missing strlen optimization on different
+// array initialization style
+//
+// Verify that strlen() calls with constant character array arguments
+// initialized with string constants are folded.  (This is a small
+// subset of pr63989).
+// { dg-do compile }
+// { dg-options "-O0 -fdump-tree-gimple" }
+
+const char a0[] = { 'a', 'b', 'c', '\0' };
+
+int len0 ()
+{
+  return __builtin_strlen (a0);
+}
+
+const char c = 0;
+const char a1[] = { 'a', 'b', 'c', c };
+
+int len1 ()
+{
+  return __builtin_strlen (a1);
+}
+
+#if 0
+
+// The following aren't handled.
+
+const char &cref = c;
+const char a2[] = { 'a', 'b', 'c', cref };
+
+int len2 ()
+{
+  return __builtin_strlen (a2);
+}
+
+
+const char* const cptr = &cref;
+const char a3[] = { 'a', 'b', 'c', *cptr };
+
+int len3 ()
+{
+  return __builtin_strlen (a3);
+}
+
+#endif
+
+// { dg-final { scan-tree-dump-times "strlen" 0 "gimple" } }
diff --git a/gcc/testsuite/g++.dg/init/string3.C b/gcc/testsuite/g++.dg/init/string3.C
new file mode 100644
index 0000000..f7c7f2f
--- /dev/null
+++ b/gcc/testsuite/g++.dg/init/string3.C
@@ -0,0 +1,37 @@ 
+// PR tree-optimization/71625 - missing strlen optimization on different
+// array initialization style
+//
+// Verify that strlen() call with a constant character array argument
+// initialized with non-constant elements isn't folded.  (This is a small
+// subset of pr63989).
+//
+// { dg-do compile }
+// { dg-options "-O2 -fdump-tree-optimized" }
+
+
+extern const char c;
+const char a0[] = { 'a', 'b', 'c', c };
+
+int len0 ()
+{
+  return __builtin_strlen (a0);
+}
+
+const char &ref = c;
+const char a1[] = { 'a', 'b', 'c', ref };
+
+int len1 ()
+{
+  return __builtin_strlen (a1);
+}
+
+const char* const ptr = &c;
+const char a2[] = { 'a', 'b', 'c', *ptr };
+
+int len2 ()
+{
+  return __builtin_strlen (a2);
+}
+
+// { dg-final { scan-tree-dump-times "strlen" 3 "optimized" } }
diff --git a/gcc/testsuite/gcc.dg/strlenopt-55.c b/gcc/testsuite/gcc.dg/strlenopt-55.c
new file mode 100644
index 0000000..68c7f1d
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/strlenopt-55.c
@@ -0,0 +1,83 @@ 
+/* PR tree-optimization/71625 - missing strlen optimization on different
+   array initialization style
+
+   Verify that strlen() of braced initialized array is folded
+   { dg-do compile }
+   { dg-options "-O0 -Wall -fdump-tree-gimple -fdump-tree-optimized" } */
+
+#include "strlenopt.h"
+
+const char a2_implicit[2] = { };
+const char a3_implicit[3] = { };
+
+const char a3_nul[3] = { 0 };
+const char a5_nul1[3] = { [1] = 0 };
+const char a7_nul2[3] = { [2] = 0 };
+
+const char ax_2_nul[] = { '1', '2', '\0' };
+const char ax_3_nul[] = { '1', '2', '3', '\0' };
+
+const char ax_3_des_nul[] = { [3] = 0, [2] = '3', [1] = '2', [0] = '1' };
+
+const char ax_3[] = { '1', '2', '3' };
+const char a3_3[3] = { '1', '2', '3' };
+
+const char a100_3[] = { '1', '2', '3', [100] = '\0' };
+
+#define CONCAT(x, y) x ## y
+#define CAT(x, y) CONCAT (x, y)
+#define FAILNAME(name) CAT (call_ ## name ##_on_line_, __LINE__)
+
+#define FAIL(name) do {				\
+    extern void FAILNAME (name) (void);		\
+    FAILNAME (name)();				\
+  } while (0)
+
+/* Macro to emit a call to funcation named
+   call_in_true_branch_not_eliminated_on_line_NNN()
+   for each call that's expected to be eliminated.  The dg-final
+   scan-tree-dump-time directive at the bottom of the test verifies
+   that no such call appears in output.  */
+#define ELIM(expr)							\
+  if (!(expr)) FAIL (in_true_branch_not_eliminated); else (void)0
+
+#define T(s, n) ELIM (strlen (s) == n)
+
+void test_nulstring (void)
+{
+  T (a2_implicit, 0);
+  T (a3_implicit, 0);
+
+  T (a3_nul, 0);
+  T (a5_nul1, 0);
+  T (a7_nul2, 0);
+
+  T (ax_2_nul, 2);
+  T (ax_3_nul, 3);
+  T (ax_3_des_nul, 3);
+
+  T (a100_3, 3);
+}
+
+/* Verify that excessively large initializers don't run out of
+   memory.  */
+
+const char large_string[] = { 'a', [__INT_MAX__] = '\0' };
+
+const int test_large_string (void)
+{
+  return large_string[0] + large_string[__INT_MAX__ - 1];
+}
+
+
+const char very_large_string[] = { 'a', [__LONG_MAX__ / 2] = '\0' };
+
+const int test_very_large_string (void)
+{
+  return very_large_string[0] + very_large_string[__LONG_MAX__ / 2 - 1];
+}
+
+
+/* { dg-final { scan-tree-dump-times "strlen" 0 "gimple" } }
+   { dg-final { scan-tree-dump-times "call_in_true_branch_not_eliminated" 0 "optimized" } } */