@@ -807,6 +807,7 @@ extern struct c_expr pop_init_level (loc
location_t);
extern void set_init_index (location_t, tree, tree, struct obstack *);
extern void set_init_label (location_t, tree, location_t, struct obstack *);
+unsigned c_maybe_optimize_large_byte_initializer (void);
extern void process_init_element (location_t, struct c_expr, bool,
struct obstack *);
extern tree build_compound_literal (location_t, tree, tree, bool,
@@ -6505,7 +6505,125 @@ c_parser_initval (c_parser *parser, stru
(init.value))))
init = convert_lvalue_to_rvalue (loc, init, true, true, true);
}
+ tree val = init.value;
process_init_element (loc, init, false, braced_init_obstack);
+
+ /* Attempt to optimize large char array initializers into RAW_DATA_CST
+ to save compile time and memory even when not using #embed. */
+ static unsigned vals_to_ignore;
+ if (vals_to_ignore)
+ /* If earlier call determined there is certain number of CPP_COMMA
+ CPP_NUMBER tokens with 0-255 int values, but not enough for
+ RAW_DATA_CST to be beneficial, don't try to check it again until
+ they are all parsed. */
+ --vals_to_ignore;
+ else if (val
+ && TREE_CODE (val) == INTEGER_CST
+ && TREE_TYPE (val) == integer_type_node
+ && c_parser_next_token_is (parser, CPP_COMMA))
+ if (unsigned int len = c_maybe_optimize_large_byte_initializer ())
+ {
+ char buf1[64];
+ unsigned int i;
+ gcc_checking_assert (len >= 64);
+ location_t last_loc = UNKNOWN_LOCATION;
+ for (i = 0; i < 64; ++i)
+ {
+ c_token *tok = c_parser_peek_nth_token_raw (parser, 1 + 2 * i);
+ if (tok->type != CPP_COMMA)
+ break;
+ tok = c_parser_peek_nth_token_raw (parser, 2 + 2 * i);
+ if (tok->type != CPP_NUMBER
+ || TREE_CODE (tok->value) != INTEGER_CST
+ || TREE_TYPE (tok->value) != integer_type_node
+ || wi::neg_p (wi::to_wide (tok->value))
+ || wi::to_widest (tok->value) > UCHAR_MAX)
+ break;
+ buf1[i] = (char) tree_to_uhwi (tok->value);
+ if (i == 0)
+ loc = tok->location;
+ last_loc = tok->location;
+ }
+ if (i < 64)
+ {
+ vals_to_ignore = i;
+ return;
+ }
+ c_token *tok = c_parser_peek_nth_token_raw (parser, 1 + 2 * i);
+ /* If 64 CPP_COMMA CPP_NUMBER pairs are followed by CPP_CLOSE_BRACE,
+ punt if len is INT_MAX as that can mean this is a flexible array
+ member and in that case we need one CPP_NUMBER afterwards
+ (as guaranteed for CPP_EMBED). */
+ if (tok->type == CPP_CLOSE_BRACE && len != INT_MAX)
+ len = i;
+ else if (tok->type != CPP_COMMA)
+ {
+ vals_to_ignore = i;
+ return;
+ }
+ /* Ensure the STRING_CST fits into 128K. */
+ unsigned int max_len = 131072 - offsetof (struct tree_string, str) - 1;
+ unsigned int orig_len = len;
+ unsigned int off = 0, last = 0;
+ if (!wi::neg_p (wi::to_wide (val)) && wi::to_widest (val) <= UCHAR_MAX)
+ off = 1;
+ len = MIN (len, max_len - off);
+ char *buf2 = XNEWVEC (char, len + off);
+ if (off)
+ buf2[0] = (char) tree_to_uhwi (val);
+ memcpy (buf2 + off, buf1, i);
+ for (unsigned int j = 0; j < i; ++j)
+ {
+ c_parser_peek_token (parser);
+ c_parser_consume_token (parser);
+ c_parser_peek_token (parser);
+ c_parser_consume_token (parser);
+ }
+ for (; i < len; ++i)
+ {
+ if (!c_parser_next_token_is (parser, CPP_COMMA))
+ break;
+ tok = c_parser_peek_2nd_token (parser);
+ if (tok->type != CPP_NUMBER
+ || TREE_CODE (tok->value) != INTEGER_CST
+ || TREE_TYPE (tok->value) != integer_type_node
+ || wi::neg_p (wi::to_wide (tok->value))
+ || wi::to_widest (tok->value) > UCHAR_MAX)
+ break;
+ c_token *tok2 = c_parser_peek_nth_token (parser, 3);
+ if (tok2->type != CPP_COMMA && tok2->type != CPP_CLOSE_BRACE)
+ break;
+ buf2[i + off] = (char) tree_to_uhwi (tok->value);
+ /* If orig_len is INT_MAX, this can be flexible array member and
+ in that case we need to ensure another element which
+ for CPP_EMBED is normally guaranteed after it. Include
+ that byte in the RAW_DATA_OWNER though, so it can be optimized
+ later. */
+ if (tok2->type == CPP_CLOSE_BRACE && orig_len == INT_MAX)
+ {
+ last = 1;
+ break;
+ }
+ last_loc = tok->location;
+ c_parser_consume_token (parser);
+ c_parser_consume_token (parser);
+ }
+ val = make_node (RAW_DATA_CST);
+ TREE_TYPE (val) = integer_type_node;
+ RAW_DATA_LENGTH (val) = i;
+ tree owner = build_string (i + off + last, buf2);
+ XDELETEVEC (buf2);
+ TREE_TYPE (owner) = build_array_type_nelts (unsigned_char_type_node,
+ i + off + last);
+ RAW_DATA_OWNER (val) = owner;
+ RAW_DATA_POINTER (val) = TREE_STRING_POINTER (owner) + off;
+ init.value = val;
+ set_c_expr_source_range (&init, loc, last_loc);
+ init.original_code = RAW_DATA_CST;
+ init.original_type = integer_type_node;
+ init.m_decimal = 0;
+ process_init_element (loc, init, false, braced_init_obstack);
+ }
}
/* Parse a compound statement (possibly a function body) (C90 6.6.2,
@@ -11329,6 +11329,42 @@ maybe_split_raw_data (tree value, tree *
return value;
}
+/* Return non-zero if c_parser_initval should attempt to optimize
+ large initializers into RAW_DATA_CST. In that case return how
+ many elements to optimize at most. */
+
+unsigned
+c_maybe_optimize_large_byte_initializer (void)
+{
+ if (!constructor_type
+ || TREE_CODE (constructor_type) != ARRAY_TYPE
+ || constructor_stack->implicit)
+ return 0;
+ tree elttype = TYPE_MAIN_VARIANT (TREE_TYPE (constructor_type));
+ if (TREE_CODE (elttype) != INTEGER_TYPE
+ && TREE_CODE (elttype) != BITINT_TYPE)
+ return 0;
+ if (TYPE_PRECISION (elttype) != CHAR_BIT
+ || constructor_stack->replacement_value.value
+ || (COMPLETE_TYPE_P (constructor_type)
+ && !poly_int_tree_p (TYPE_SIZE (constructor_type)))
+ || constructor_range_stack)
+ return 0;
+ if (constructor_max_index == NULL_TREE)
+ return INT_MAX;
+ if (tree_int_cst_le (constructor_max_index, constructor_index)
+ || integer_all_onesp (constructor_max_index))
+ return 0;
+ widest_int w = wi::to_widest (constructor_max_index);
+ w -= wi::to_widest (constructor_index);
+ w += 1;
+ if (w < 64)
+ return 0;
+ if (w > INT_MAX)
+ return INT_MAX;
+ return w.to_uhwi ();
+}
+
/* Add one non-braced element to the current constructor level.
This adjusts the current position within the constructor's type.
This may also start or terminate implicit levels
@@ -0,0 +1,218 @@
+/* { dg-do run } */
+/* { dg-options "-O2" } */
+
+unsigned char a[] = {
+ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 230, 15,
+ 229, 16, 228, 17, 227, 18, 226, 19, 225, 20, 224, 21, 223, 22, 222, 23,
+ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 230, 15,
+ 229, 16, 228, 17, 227, 18, 226, 19, 225, 20, 224, 21, 223, 22, 222, 23 + 1 };
+unsigned char b[] = {
+ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 230, 15,
+ 229, 16, 228, 17, 227, 18, 226, 19, 225, 20, 224, 21, 223, 22, 222, 23,
+ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 230, 15,
+ 229, 16, 228, 17, 227, 18, 226, 19, 225, 20, 224, 21, 223, 22, 222, 23,
+ 1 };
+unsigned char c[] = {
+ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 230, 15,
+ 229, 16, 228, 17, 227, 18, 226, 19, 225, 20, 224, 21, 223, 22, 222, 23,
+ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 230, 15,
+ 229, 16, 228, 17, 227, 18, 226, 19, 225, 20, 224, 21, 223, 22, 222, 23,
+ 1, 2 };
+unsigned char d[] = {
+ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 230, 15,
+ 229, 16, 228, 17, 227, 18, 226, 19, 225, 20, 224, 21, 223, 22, 222, 23,
+ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 230, 15,
+ 229, 16, 228, 17, 227, 18, 226, 19, 225, 20, 224, 21, 223, 22, 222, 23,
+ 1, 2, 3 };
+unsigned char e[] = {
+ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 230, 15,
+ 229, 16, 228, 17, 227, 18, 226, 19, 225, 20, 224, 21, 223, 22, 222, 23,
+ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 230, 15,
+ 229, 16, 228, 17, 227, 18, 226, 19, 225, 20, 224, 21, 223, 22, 222, 23,
+ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 230, 15,
+ 229, 16, 228, 17, 227, 18, 226, 19, 225, 20, 224, 21, 223, 22, 222, 23,
+ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 230, 15,
+ 229, 16, 228, 17, 227, 18, 226, 19, 225, 20, 224, 21, 223, 22, 222, 23,
+ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 230, 15,
+ 229, 16, 228, 17, 227, 18, 226, 19, 225, 20, 224, 21, 223, 22, 222, 23,
+ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 230, 15,
+ 229, 16, 228, 17, 227, 18, 226, 19, 225, 20, 224, 21, 223, 22, 222, 23,
+ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 230, 15,
+ 229, 16, 228, 17, 227, 18, 226, 19, 225, 20, 224, 21, 223, 22, 222, 23,
+ 1, 2, 3 };
+struct A { unsigned char a[64]; int b; } f = {
+ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 230, 15,
+ 229, 16, 228, 17, 227, 18, 226, 19, 225, 20, 224, 21, 223, 22, 222, 23,
+ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 230, 15,
+ 229, 16, 228, 17, 227, 18, 226, 19, 225, 20, 224, 21, 223, 22, 222, 23 + 1,
+ 221 };
+struct A g = {
+ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 230, 15,
+ 229, 16, 228, 17, 227, 18, 226, 19, 225, 20, 224, 21, 223, 22, 222, 23,
+ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 230, 15,
+ 229, 16, 228, 17, 227, 18, 226, 19, 225, 20, 224, 21, 223, 22, 222, 23,
+ 221 };
+struct A h = {
+{ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 230, 15,
+ 229, 16, 228, 17, 227, 18, 226, 19, 225, 20, 224, 21, 223, 22, 222, 23,
+ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 230, 15,
+ 229, 16, 228, 17, 227, 18, 226, 19, 225, 20, 224, 21, 223, 22, 222, 23 },
+ 221 };
+struct B { unsigned char a[65]; int b; } k = {
+ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 230, 15,
+ 229, 16, 228, 17, 227, 18, 226, 19, 225, 20, 224, 21, 223, 22, 222, 23,
+ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 230, 15,
+ 229, 16, 228, 17, 227, 18, 226, 19, 225, 20, 224, 21, 223, 22, 222, 23,
+ 1, 2 };
+struct C { unsigned char a[66]; int b; } l = {
+ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 230, 15,
+ 229, 16, 228, 17, 227, 18, 226, 19, 225, 20, 224, 21, 223, 22, 222, 23,
+ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 230, 15,
+ 229, 16, 228, 17, 227, 18, 226, 19, 225, 20, 224, 21, 223, 22, 222, 23,
+ 1, 2, 3 };
+struct D { unsigned char a[67]; int b; } m = {
+ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 230, 15,
+ 229, 16, 228, 17, 227, 18, 226, 19, 225, 20, 224, 21, 223, 22, 222, 23,
+ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 230, 15,
+ 229, 16, 228, 17, 227, 18, 226, 19, 225, 20, 224, 21, 223, 22, 222, 23,
+ 1, 2, 3, 4 };
+struct E { unsigned char a[227]; int b; } n = {
+ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 230, 15,
+ 229, 16, 228, 17, 227, 18, 226, 19, 225, 20, 224, 21, 223, 22, 222, 23,
+ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 230, 15,
+ 229, 16, 228, 17, 227, 18, 226, 19, 225, 20, 224, 21, 223, 22, 222, 23,
+ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 230, 15,
+ 229, 16, 228, 17, 227, 18, 226, 19, 225, 20, 224, 21, 223, 22, 222, 23,
+ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 230, 15,
+ 229, 16, 228, 17, 227, 18, 226, 19, 225, 20, 224, 21, 223, 22, 222, 23,
+ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 230, 15,
+ 229, 16, 228, 17, 227, 18, 226, 19, 225, 20, 224, 21, 223, 22, 222, 23,
+ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 230, 15,
+ 229, 16, 228, 17, 227, 18, 226, 19, 225, 20, 224, 21, 223, 22, 222, 23,
+ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 230, 15,
+ 229, 16, 228, 17, 227, 18, 226, 19, 225, 20, 224, 21, 223, 22, 222, 23,
+ 1, 2, 3, 4 };
+unsigned char o[] = {
+ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 230, 15,
+ 229, 16, 228, 17, 227, 18, 226, 19, 225, 20, 224, 21, 223, 22, 222, 23,
+ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 230, 15,
+ 229, 16, 228, 17, 227, 18, 226, 19, 225, 20, 224, 21, 223, 22, 222, 23,
+ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 230, 15,
+ 229, 16, 228, 17, 227, 18, 226, 19, 225, 20, 224, 21, 223, 22, 222, 23,
+ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 230, 15,
+ 229, 16, 228, 17, 227, 18, 226, 19, 225, 20, 224, 21, 223, 22, 222, 23,
+ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 230, 15,
+ 229, 16, 228, 17, 227, 18, 226, 19, 225, 20, 224, 21, 223, 22, 222, 23,
+ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 230, 15,
+ 229, 16, 228, 17, 227, 18, 226, 19, 225, 20, 224, 21, 223, 22, 222, 23,
+ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 230, 15,
+ 229, 16, 228, 17, 227, 18, 226, 19, 225, 20, 224, 21, 223, 22, 222, 23,
+ 1, 2, (unsigned char) -3, 4 };
+unsigned char p[] = {
+ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 230, 15,
+ 229, 16, 228, 17, 227, 18, 226, 19, 225, 20, 224, 21, 223, 22, 222, 23,
+ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 230, 15,
+ 229, 16, 228, 17, 227, 18, 226, 19, 225, 20, 224, 21, 223, 22, 222, 23,
+ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 230, 15,
+ 229, 16, 228, 17, 227, 18, 226, 19, 225, 20, 224, 21, 223, 22, 222, 23,
+ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 230, 15,
+ 229, 16, 228, 17, 227, 18, 226, 19, 225, 20, 224, 21, 223, 22, 222, 23,
+ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 230, 15,
+ 229, 16, 228, 17, 227, 18, 226, 19, 225, 20, 224, 21, 223, 22, 222, 23,
+ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 230, 15,
+ 229, 16, 228, 17, 227, 18, 226, 19, 225, 20, 224, 21, 223, 22, 222, 23,
+ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 230, 15,
+ 229, 16, 228, 17, 227, 18, 226, 19, 225, 20, 224, 21, 223, 22, 222, 23,
+ 1, 2, 3 + 1, 5 };
+
+int
+main ()
+{
+ if (sizeof (a) != 64
+ || sizeof (b) != 65
+ || sizeof (c) != 66
+ || sizeof (d) != 67
+ || sizeof (e) != 227
+ || sizeof (o) != 228
+ || sizeof (p) != 228)
+ __builtin_abort ();
+ for (int i = 0; i < 32; ++i)
+ {
+ int j;
+ if (i < 14)
+ j = i + 1;
+ else if (i & 1)
+ j = 15 + (i - 15) / 2;
+ else
+ j = 230 - (i - 14) / 2;
+ if (a[i] != j
+ || (i != 31 && a[i + 32] != j)
+ || b[i] != j
+ || b[i + 32] != j
+ || c[i] != j
+ || c[i + 32] != j
+ || d[i] != j
+ || d[i + 32] != j
+ || e[i] != j
+ || e[i + 32] != j
+ || e[i + 64] != j
+ || e[i + 96] != j
+ || e[i + 128] != j
+ || e[i + 160] != j
+ || e[i + 192] != j
+ || f.a[i] != j
+ || (i != 31 && f.a[i + 32] != j)
+ || g.a[i] != j
+ || g.a[i + 32] != j
+ || h.a[i] != j
+ || h.a[i + 32] != j
+ || k.a[i] != j
+ || k.a[i + 32] != j
+ || l.a[i] != j
+ || l.a[i + 32] != j
+ || m.a[i] != j
+ || m.a[i + 32] != j
+ || n.a[i] != j
+ || n.a[i + 32] != j
+ || n.a[i + 64] != j
+ || n.a[i + 96] != j
+ || n.a[i + 128] != j
+ || n.a[i + 160] != j
+ || n.a[i + 192] != j)
+ __builtin_abort ();
+ }
+ if (a[63] != 24
+ || b[64] != 1
+ || c[64] != 1
+ || c[65] != 2
+ || d[64] != 1
+ || d[65] != 2
+ || d[66] != 3
+ || e[224] != 1
+ || e[225] != 2
+ || e[226] != 3
+ || f.a[63] != 24
+ || f.b != 221
+ || g.b != 221
+ || h.b != 221
+ || k.a[64] != 1
+ || k.b != 2
+ || l.a[64] != 1
+ || l.a[65] != 2
+ || l.b != 3
+ || m.a[64] != 1
+ || m.a[65] != 2
+ || m.a[66] != 3
+ || m.b != 4
+ || n.a[224] != 1
+ || n.a[225] != 2
+ || n.a[226] != 3
+ || n.b != 4
+ || __builtin_memcmp (e, o, 226)
+ || o[226] != (unsigned char) -3
+ || o[227] != 4
+ || __builtin_memcmp (e, p, 226)
+ || p[226] != 4
+ || p[227] != 5)
+ __builtin_abort ();
+}