Message ID | c9067f6a-9e55-8483-4f4f-c162d4c7a170@gmail.com |
---|---|
State | New |
Headers | show |
Series | convert braced initializers to strings (PR 71625) | expand |
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
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
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
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.
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" } } */
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
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.
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" } } */
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
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
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" } } */
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.
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
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.
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.
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. >
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.
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
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
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
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
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
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
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"
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
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
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
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
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" } } */