From f9bac238840155e1539aa68daf1507ea63c9ed80 Mon Sep 17 00:00:00 2001
From: Jakub Jelinek <jakub@redhat.com>
Date: Wed, 16 Oct 2024 10:22:44 +0200
Subject: [PATCH] c: Speed up compilation of large char array initializers when
 not using #embed

The following patch on attempts to speed up compilation of large char array
initializers when one doesn't use #embed in the source.

My testcase has been
unsigned char a[] = {
 #embed "cc1gm2" limit (100000000)
};
and corresponding variant which has the middle line replaced with
dd if=cc1gm bs=100000000 count=1 | xxd -i
With embed 95.3MiB is really fast:
time ./cc1 -quiet -O2 -o test4a.s test4a.c

real    0m0.700s
user    0m0.576s
sys     0m0.123s
Without embed and without this patch it needs around 11GB of RAM and
time ./cc1 -quiet -O2 -o test4b.s test4b.c

real    2m47.230s
user    2m41.548s
sys     0m4.328s
Without embed and with this patch it needs around 3.5GB of RAM and
time ./cc1 -quiet -O2 -o test4b.s2 test4b.c

real    0m25.004s
user    0m23.655s
sys     0m1.308s
Not perfect (but one needs to parse all the numbers, libcpp also creates
strings which are pointed by CPP_NUMBER tokens (that can take up to 4 bytes
per byte), but still almost 7x speed improvement and 3x compile time memory.

One drawback of the patch is that for the larger initializers the precise
locations for -Wconversion warnings are gone when initializing signed char
(or char when it is signed) arrays.

If that is important, perhaps c_maybe_optimize_large_byte_initializer could
tell the caller this is the case and c_parser_initval could emit the
warnings directly when it still knows the location_t and suppress warnings
on the RAW_DATA_CST.

2024-10-16  Jakub Jelinek  <jakub@redhat.com>

	* c-tree.h (c_maybe_optimize_large_byte_initializer): Declare.
	* c-parser.cc (c_parser_initval): Attempt to optimize large char array
	initializers into RAW_DATA_CST.
	* c-typeck.cc (c_maybe_optimize_large_byte_initializer): New function.

	* c-c++-common/init-1.c: New test.
	* c-c++-common/init-2.c: New test.
	* c-c++-common/init-3.c: New test.
---
 gcc/c/c-parser.cc                   | 118 +++++++++++++++
 gcc/c/c-tree.h                      |   1 +
 gcc/c/c-typeck.cc                   |  36 +++++
 gcc/testsuite/c-c++-common/init-1.c | 218 ++++++++++++++++++++++++++++
 gcc/testsuite/c-c++-common/init-2.c | 218 ++++++++++++++++++++++++++++
 gcc/testsuite/c-c++-common/init-3.c | 218 ++++++++++++++++++++++++++++
 6 files changed, 809 insertions(+)
 create mode 100644 gcc/testsuite/c-c++-common/init-1.c
 create mode 100644 gcc/testsuite/c-c++-common/init-2.c
 create mode 100644 gcc/testsuite/c-c++-common/init-3.c

diff --git a/gcc/c/c-parser.cc b/gcc/c/c-parser.cc
index 9eaa91413b6c..120f2b289c0b 100644
--- a/gcc/c/c-parser.cc
+++ b/gcc/c/c-parser.cc
@@ -6507,7 +6507,125 @@ c_parser_initval (c_parser *parser, struct c_expr *after,
 					    (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,
diff --git a/gcc/c/c-tree.h b/gcc/c/c-tree.h
index e23d8e59ac4b..bfdcb78bbcc1 100644
--- a/gcc/c/c-tree.h
+++ b/gcc/c/c-tree.h
@@ -832,6 +832,7 @@ extern struct c_expr pop_init_level (location_t, int, struct obstack *,
 				     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,
diff --git a/gcc/c/c-typeck.cc b/gcc/c/c-typeck.cc
index 36d0b23a3d72..108ea5ca3e8c 100644
--- a/gcc/c/c-typeck.cc
+++ b/gcc/c/c-typeck.cc
@@ -11347,6 +11347,42 @@ maybe_split_raw_data (tree value, tree *raw_data)
   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
diff --git a/gcc/testsuite/c-c++-common/init-1.c b/gcc/testsuite/c-c++-common/init-1.c
new file mode 100644
index 000000000000..47ddbf8eddfc
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/init-1.c
@@ -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 ();
+}
diff --git a/gcc/testsuite/c-c++-common/init-2.c b/gcc/testsuite/c-c++-common/init-2.c
new file mode 100644
index 000000000000..9e55aabe0c5f
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/init-2.c
@@ -0,0 +1,218 @@
+/* { dg-do run } */
+/* { dg-options "-O2" } */
+
+signed char a[] = {
+  1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 110, 15,
+  109, 16, 108, 17, 107, 18, 106, 19, 105, 20, 104, 21, 103, 22, 102, 23,
+  1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 110, 15,
+  109, 16, 108, 17, 107, 18, 106, 19, 105, 20, 104, 21, 103, 22, 102, 23 + 1 };
+signed char b[] = {
+  1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 110, 15,
+  109, 16, 108, 17, 107, 18, 106, 19, 105, 20, 104, 21, 103, 22, 102, 23,
+  1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 110, 15,
+  109, 16, 108, 17, 107, 18, 106, 19, 105, 20, 104, 21, 103, 22, 102, 23,
+  1 };
+signed char c[] = {
+  1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 110, 15,
+  109, 16, 108, 17, 107, 18, 106, 19, 105, 20, 104, 21, 103, 22, 102, 23,
+  1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 110, 15,
+  109, 16, 108, 17, 107, 18, 106, 19, 105, 20, 104, 21, 103, 22, 102, 23,
+  1, 2 };
+signed char d[] = {
+  1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 110, 15,
+  109, 16, 108, 17, 107, 18, 106, 19, 105, 20, 104, 21, 103, 22, 102, 23,
+  1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 110, 15,
+  109, 16, 108, 17, 107, 18, 106, 19, 105, 20, 104, 21, 103, 22, 102, 23,
+  1, 2, 3 };
+signed char e[] = {
+  1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 110, 15,
+  109, 16, 108, 17, 107, 18, 106, 19, 105, 20, 104, 21, 103, 22, 102, 23,
+  1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 110, 15,
+  109, 16, 108, 17, 107, 18, 106, 19, 105, 20, 104, 21, 103, 22, 102, 23,
+  1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 110, 15,
+  109, 16, 108, 17, 107, 18, 106, 19, 105, 20, 104, 21, 103, 22, 102, 23,
+  1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 110, 15,
+  109, 16, 108, 17, 107, 18, 106, 19, 105, 20, 104, 21, 103, 22, 102, 23,
+  1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 110, 15,
+  109, 16, 108, 17, 107, 18, 106, 19, 105, 20, 104, 21, 103, 22, 102, 23,
+  1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 110, 15,
+  109, 16, 108, 17, 107, 18, 106, 19, 105, 20, 104, 21, 103, 22, 102, 23,
+  1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 110, 15,
+  109, 16, 108, 17, 107, 18, 106, 19, 105, 20, 104, 21, 103, 22, 102, 23,
+  1, 2, 3 };
+struct A { signed char a[64]; int b; } f = {
+  1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 110, 15,
+  109, 16, 108, 17, 107, 18, 106, 19, 105, 20, 104, 21, 103, 22, 102, 23,
+  1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 110, 15,
+  109, 16, 108, 17, 107, 18, 106, 19, 105, 20, 104, 21, 103, 22, 102, 23 + 1,
+  101 };
+struct A g = {
+  1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 110, 15,
+  109, 16, 108, 17, 107, 18, 106, 19, 105, 20, 104, 21, 103, 22, 102, 23,
+  1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 110, 15,
+  109, 16, 108, 17, 107, 18, 106, 19, 105, 20, 104, 21, 103, 22, 102, 23,
+  101 };
+struct A h = {
+{ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 110, 15,
+  109, 16, 108, 17, 107, 18, 106, 19, 105, 20, 104, 21, 103, 22, 102, 23,
+  1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 110, 15,
+  109, 16, 108, 17, 107, 18, 106, 19, 105, 20, 104, 21, 103, 22, 102, 23 },
+  101 };
+struct B { signed char a[65]; int b; } k = {
+  1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 110, 15,
+  109, 16, 108, 17, 107, 18, 106, 19, 105, 20, 104, 21, 103, 22, 102, 23,
+  1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 110, 15,
+  109, 16, 108, 17, 107, 18, 106, 19, 105, 20, 104, 21, 103, 22, 102, 23,
+  1, 2 };
+struct C { signed char a[66]; int b; } l = {
+  1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 110, 15,
+  109, 16, 108, 17, 107, 18, 106, 19, 105, 20, 104, 21, 103, 22, 102, 23,
+  1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 110, 15,
+  109, 16, 108, 17, 107, 18, 106, 19, 105, 20, 104, 21, 103, 22, 102, 23,
+  1, 2, 3 };
+struct D { signed char a[67]; int b; } m = {
+  1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 110, 15,
+  109, 16, 108, 17, 107, 18, 106, 19, 105, 20, 104, 21, 103, 22, 102, 23,
+  1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 110, 15,
+  109, 16, 108, 17, 107, 18, 106, 19, 105, 20, 104, 21, 103, 22, 102, 23,
+  1, 2, 3, 4 };
+struct E { signed char a[227]; int b; } n = {
+  1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 110, 15,
+  109, 16, 108, 17, 107, 18, 106, 19, 105, 20, 104, 21, 103, 22, 102, 23,
+  1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 110, 15,
+  109, 16, 108, 17, 107, 18, 106, 19, 105, 20, 104, 21, 103, 22, 102, 23,
+  1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 110, 15,
+  109, 16, 108, 17, 107, 18, 106, 19, 105, 20, 104, 21, 103, 22, 102, 23,
+  1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 110, 15,
+  109, 16, 108, 17, 107, 18, 106, 19, 105, 20, 104, 21, 103, 22, 102, 23,
+  1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 110, 15,
+  109, 16, 108, 17, 107, 18, 106, 19, 105, 20, 104, 21, 103, 22, 102, 23,
+  1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 110, 15,
+  109, 16, 108, 17, 107, 18, 106, 19, 105, 20, 104, 21, 103, 22, 102, 23,
+  1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 110, 15,
+  109, 16, 108, 17, 107, 18, 106, 19, 105, 20, 104, 21, 103, 22, 102, 23,
+  1, 2, 3, 4 };
+signed char o[] = {
+  1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 110, 15,
+  109, 16, 108, 17, 107, 18, 106, 19, 105, 20, 104, 21, 103, 22, 102, 23,
+  1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 110, 15,
+  109, 16, 108, 17, 107, 18, 106, 19, 105, 20, 104, 21, 103, 22, 102, 23,
+  1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 110, 15,
+  109, 16, 108, 17, 107, 18, 106, 19, 105, 20, 104, 21, 103, 22, 102, 23,
+  1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 110, 15,
+  109, 16, 108, 17, 107, 18, 106, 19, 105, 20, 104, 21, 103, 22, 102, 23,
+  1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 110, 15,
+  109, 16, 108, 17, 107, 18, 106, 19, 105, 20, 104, 21, 103, 22, 102, 23,
+  1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 110, 15,
+  109, 16, 108, 17, 107, 18, 106, 19, 105, 20, 104, 21, 103, 22, 102, 23,
+  1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 110, 15,
+  109, 16, 108, 17, 107, 18, 106, 19, 105, 20, 104, 21, 103, 22, 102, 23,
+  1, 2, -3, 4 };
+signed char p[] = {
+  1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 110, 15,
+  109, 16, 108, 17, 107, 18, 106, 19, 105, 20, 104, 21, 103, 22, 102, 23,
+  1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 110, 15,
+  109, 16, 108, 17, 107, 18, 106, 19, 105, 20, 104, 21, 103, 22, 102, 23,
+  1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 110, 15,
+  109, 16, 108, 17, 107, 18, 106, 19, 105, 20, 104, 21, 103, 22, 102, 23,
+  1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 110, 15,
+  109, 16, 108, 17, 107, 18, 106, 19, 105, 20, 104, 21, 103, 22, 102, 23,
+  1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 110, 15,
+  109, 16, 108, 17, 107, 18, 106, 19, 105, 20, 104, 21, 103, 22, 102, 23,
+  1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 110, 15,
+  109, 16, 108, 17, 107, 18, 106, 19, 105, 20, 104, 21, 103, 22, 102, 23,
+  1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 110, 15,
+  109, 16, 108, 17, 107, 18, 106, 19, 105, 20, 104, 21, 103, 22, 102, 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 = 110 - (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 != 101
+      || g.b != 101
+      || h.b != 101
+      || 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] != -3
+      || o[227] != 4
+      || __builtin_memcmp (e, p, 226)
+      || p[226] != 4
+      || p[227] != 5)
+    __builtin_abort ();
+}
diff --git a/gcc/testsuite/c-c++-common/init-3.c b/gcc/testsuite/c-c++-common/init-3.c
new file mode 100644
index 000000000000..411616e8778a
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/init-3.c
@@ -0,0 +1,218 @@
+/* { dg-do run } */
+/* { dg-options "-O2" } */
+
+char a[] = {
+  1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 110, 15,
+  109, 16, 108, 17, 107, 18, 106, 19, 105, 20, 104, 21, 103, 22, 102, 23,
+  1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 110, 15,
+  109, 16, 108, 17, 107, 18, 106, 19, 105, 20, 104, 21, 103, 22, 102, 23 + 1 };
+char b[] = {
+  1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 110, 15,
+  109, 16, 108, 17, 107, 18, 106, 19, 105, 20, 104, 21, 103, 22, 102, 23,
+  1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 110, 15,
+  109, 16, 108, 17, 107, 18, 106, 19, 105, 20, 104, 21, 103, 22, 102, 23,
+  1 };
+char c[] = {
+  1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 110, 15,
+  109, 16, 108, 17, 107, 18, 106, 19, 105, 20, 104, 21, 103, 22, 102, 23,
+  1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 110, 15,
+  109, 16, 108, 17, 107, 18, 106, 19, 105, 20, 104, 21, 103, 22, 102, 23,
+  1, 2 };
+char d[] = {
+  1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 110, 15,
+  109, 16, 108, 17, 107, 18, 106, 19, 105, 20, 104, 21, 103, 22, 102, 23,
+  1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 110, 15,
+  109, 16, 108, 17, 107, 18, 106, 19, 105, 20, 104, 21, 103, 22, 102, 23,
+  1, 2, 3 };
+char e[] = {
+  1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 110, 15,
+  109, 16, 108, 17, 107, 18, 106, 19, 105, 20, 104, 21, 103, 22, 102, 23,
+  1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 110, 15,
+  109, 16, 108, 17, 107, 18, 106, 19, 105, 20, 104, 21, 103, 22, 102, 23,
+  1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 110, 15,
+  109, 16, 108, 17, 107, 18, 106, 19, 105, 20, 104, 21, 103, 22, 102, 23,
+  1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 110, 15,
+  109, 16, 108, 17, 107, 18, 106, 19, 105, 20, 104, 21, 103, 22, 102, 23,
+  1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 110, 15,
+  109, 16, 108, 17, 107, 18, 106, 19, 105, 20, 104, 21, 103, 22, 102, 23,
+  1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 110, 15,
+  109, 16, 108, 17, 107, 18, 106, 19, 105, 20, 104, 21, 103, 22, 102, 23,
+  1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 110, 15,
+  109, 16, 108, 17, 107, 18, 106, 19, 105, 20, 104, 21, 103, 22, 102, 23,
+  1, 2, 3 };
+struct A { char a[64]; int b; } f = {
+  1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 110, 15,
+  109, 16, 108, 17, 107, 18, 106, 19, 105, 20, 104, 21, 103, 22, 102, 23,
+  1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 110, 15,
+  109, 16, 108, 17, 107, 18, 106, 19, 105, 20, 104, 21, 103, 22, 102, 23 + 1,
+  101 };
+struct A g = {
+  1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 110, 15,
+  109, 16, 108, 17, 107, 18, 106, 19, 105, 20, 104, 21, 103, 22, 102, 23,
+  1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 110, 15,
+  109, 16, 108, 17, 107, 18, 106, 19, 105, 20, 104, 21, 103, 22, 102, 23,
+  101 };
+struct A h = {
+{ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 110, 15,
+  109, 16, 108, 17, 107, 18, 106, 19, 105, 20, 104, 21, 103, 22, 102, 23,
+  1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 110, 15,
+  109, 16, 108, 17, 107, 18, 106, 19, 105, 20, 104, 21, 103, 22, 102, 23 },
+  101 };
+struct B { char a[65]; int b; } k = {
+  1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 110, 15,
+  109, 16, 108, 17, 107, 18, 106, 19, 105, 20, 104, 21, 103, 22, 102, 23,
+  1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 110, 15,
+  109, 16, 108, 17, 107, 18, 106, 19, 105, 20, 104, 21, 103, 22, 102, 23,
+  1, 2 };
+struct C { char a[66]; int b; } l = {
+  1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 110, 15,
+  109, 16, 108, 17, 107, 18, 106, 19, 105, 20, 104, 21, 103, 22, 102, 23,
+  1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 110, 15,
+  109, 16, 108, 17, 107, 18, 106, 19, 105, 20, 104, 21, 103, 22, 102, 23,
+  1, 2, 3 };
+struct D { char a[67]; int b; } m = {
+  1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 110, 15,
+  109, 16, 108, 17, 107, 18, 106, 19, 105, 20, 104, 21, 103, 22, 102, 23,
+  1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 110, 15,
+  109, 16, 108, 17, 107, 18, 106, 19, 105, 20, 104, 21, 103, 22, 102, 23,
+  1, 2, 3, 4 };
+struct E { char a[227]; int b; } n = {
+  1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 110, 15,
+  109, 16, 108, 17, 107, 18, 106, 19, 105, 20, 104, 21, 103, 22, 102, 23,
+  1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 110, 15,
+  109, 16, 108, 17, 107, 18, 106, 19, 105, 20, 104, 21, 103, 22, 102, 23,
+  1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 110, 15,
+  109, 16, 108, 17, 107, 18, 106, 19, 105, 20, 104, 21, 103, 22, 102, 23,
+  1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 110, 15,
+  109, 16, 108, 17, 107, 18, 106, 19, 105, 20, 104, 21, 103, 22, 102, 23,
+  1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 110, 15,
+  109, 16, 108, 17, 107, 18, 106, 19, 105, 20, 104, 21, 103, 22, 102, 23,
+  1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 110, 15,
+  109, 16, 108, 17, 107, 18, 106, 19, 105, 20, 104, 21, 103, 22, 102, 23,
+  1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 110, 15,
+  109, 16, 108, 17, 107, 18, 106, 19, 105, 20, 104, 21, 103, 22, 102, 23,
+  1, 2, 3, 4 };
+char o[] = {
+  1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 110, 15,
+  109, 16, 108, 17, 107, 18, 106, 19, 105, 20, 104, 21, 103, 22, 102, 23,
+  1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 110, 15,
+  109, 16, 108, 17, 107, 18, 106, 19, 105, 20, 104, 21, 103, 22, 102, 23,
+  1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 110, 15,
+  109, 16, 108, 17, 107, 18, 106, 19, 105, 20, 104, 21, 103, 22, 102, 23,
+  1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 110, 15,
+  109, 16, 108, 17, 107, 18, 106, 19, 105, 20, 104, 21, 103, 22, 102, 23,
+  1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 110, 15,
+  109, 16, 108, 17, 107, 18, 106, 19, 105, 20, 104, 21, 103, 22, 102, 23,
+  1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 110, 15,
+  109, 16, 108, 17, 107, 18, 106, 19, 105, 20, 104, 21, 103, 22, 102, 23,
+  1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 110, 15,
+  109, 16, 108, 17, 107, 18, 106, 19, 105, 20, 104, 21, 103, 22, 102, 23,
+  1, 2, (char) -3, 4 };
+char p[] = {
+  1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 110, 15,
+  109, 16, 108, 17, 107, 18, 106, 19, 105, 20, 104, 21, 103, 22, 102, 23,
+  1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 110, 15,
+  109, 16, 108, 17, 107, 18, 106, 19, 105, 20, 104, 21, 103, 22, 102, 23,
+  1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 110, 15,
+  109, 16, 108, 17, 107, 18, 106, 19, 105, 20, 104, 21, 103, 22, 102, 23,
+  1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 110, 15,
+  109, 16, 108, 17, 107, 18, 106, 19, 105, 20, 104, 21, 103, 22, 102, 23,
+  1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 110, 15,
+  109, 16, 108, 17, 107, 18, 106, 19, 105, 20, 104, 21, 103, 22, 102, 23,
+  1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 110, 15,
+  109, 16, 108, 17, 107, 18, 106, 19, 105, 20, 104, 21, 103, 22, 102, 23,
+  1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 110, 15,
+  109, 16, 108, 17, 107, 18, 106, 19, 105, 20, 104, 21, 103, 22, 102, 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 = 110 - (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 != 101
+      || g.b != 101
+      || h.b != 101
+      || 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] != (char) -3
+      || o[227] != 4
+      || __builtin_memcmp (e, p, 226)
+      || p[226] != 4
+      || p[227] != 5)
+    __builtin_abort ();
+}
-- 
GitLab