then VAL represents the constant and all the other fields are zero, or
a memory load, then VAL represents the reference, BASE_ADDR is non-NULL
and the other fields also reflect the memory load, or an SSA name, then
- VAL represents the SSA name and all the other fields are zero, */
+ VAL represents the SSA name and all the other fields are zero. */
class store_operand_info
{
if (buf_size <= MOVE_MAX)
string_concatenation = false;
+ /* String concatenation only works for byte aligned start and end. */
+ if (start % BITS_PER_UNIT != 0 || width % BITS_PER_UNIT != 0)
+ string_concatenation = false;
+
/* Create a power-of-2-sized buffer for native_encode_expr. */
if (!string_concatenation)
buf_size = 1 << ceil_log2 (buf_size);
/* For bswap framework using sets of stores, all the checking has been done
earlier in try_coalesce_bswap and the result always needs to be emitted
- as a single store. Likewise for string concatenation, */
+ as a single store. Likewise for string concatenation. */
if (group->stores[0]->rhs_code == LROTATE_EXPR
|| group->stores[0]->rhs_code == NOP_EXPR
|| group->string_concatenation)
--- /dev/null
+/* PR tree-optimization/108498 */
+
+struct A
+{
+ signed char a1;
+ int a2;
+};
+
+struct B
+{
+ struct A b1;
+ unsigned char b2:1, b3:1, b4:2, b5:1, b6:1, b7[4];
+};
+
+struct C
+{
+ unsigned char c1;
+ char c2;
+ signed char c3;
+ unsigned char c4, c5[4], c6:1, c7:1, c8:1, c9:3, c10:1;
+ struct A c11;
+ struct B c12[3];
+};
+
+static inline struct C
+foo (unsigned char a, unsigned b, int c, struct A d,
+ unsigned e, struct B f, struct B g, struct B h)
+{
+ struct C x
+ = { .c1 = b, .c2 = 0, .c3 = c, .c6 = a, .c4 = e, .c7 = 0,
+ .c8 = 0, .c9 = 7, .c10 = 0, .c5 = {0, 1, 2, 3}, .c11 = d,
+ .c12 = {f, g, h} };
+ return x;
+}
+
+static inline struct A
+bar (int a, int b)
+{
+ struct A x = { .a1 = a, .a2 = b };
+ return x;
+}
+
+static inline struct B
+baz (struct A b1)
+{
+ struct B x = { .b1 = b1, .b6 = 0, .b5 = 0, .b7 = {0, 1, 2, 3}, .b2 = 0 };
+ return x;
+}
+
+struct C
+qux (void)
+{
+ const struct B a = baz (bar (0, 0));
+ struct C b;
+ struct B c[2];
+ struct A d = { 0, 1 };
+ c[0].b1.a1 = 0;
+ c[0].b1.a2 = 2;
+ c[1].b1.a1 = 4;
+ c[1].b1.a2 = 8;
+ return foo (0, 2, -1, d, 3, c[0], c[1], a);
+}
+
+__attribute__((noipa)) void
+corge (struct C *x)
+{
+ char buf[1024];
+ __builtin_memset (buf, 0xaa, sizeof (buf));
+ asm volatile ("" : : "r" (buf));
+ __builtin_memset (x, 0x55, sizeof (struct C));
+ asm volatile ("" : : "r" (x));
+}
+
+int
+main ()
+{
+ struct C x;
+ corge (&x);
+ x = qux ();
+ if (x.c6 || x.c9 != 7)
+ __builtin_abort ();
+}
--- /dev/null
+/* PR tree-optimization/108498 */
+
+struct U { char c[16]; };
+struct V { char c[16]; };
+struct S { unsigned int a : 3, b : 8, c : 21; struct U d; unsigned int e; struct V f; unsigned int g : 5, h : 27; };
+struct T { unsigned int a : 16, b : 8, c : 8; struct U d; unsigned int e; struct V f; unsigned int g : 5, h : 27; };
+
+__attribute__((noipa)) void
+foo (struct S *p)
+{
+ p->b = 231;
+ p->c = 42;
+ p->d = (struct U) { "abcdefghijklmno" };
+ p->e = 0xdeadbeef;
+ p->f = (struct V) { "ABCDEFGHIJKLMNO" };
+}
+
+__attribute__((noipa)) void
+bar (struct S *p)
+{
+ p->b = 231;
+ p->c = 42;
+ p->d = (struct U) { "abcdefghijklmno" };
+ p->e = 0xdeadbeef;
+ p->f = (struct V) { "ABCDEFGHIJKLMNO" };
+ p->g = 12;
+}
+
+__attribute__((noipa)) void
+baz (struct T *p)
+{
+ p->c = 42;
+ p->d = (struct U) { "abcdefghijklmno" };
+ p->e = 0xdeadbeef;
+ p->f = (struct V) { "ABCDEFGHIJKLMNO" };
+ p->g = 12;
+}
+
+int
+main ()
+{
+ if (__CHAR_BIT__ != 8 || __SIZEOF_INT__ != 4)
+ return 0;
+ struct S s = {};
+ struct T t = {};
+ foo (&s);
+ if (s.a != 0 || s.b != 231 || s.c != 42
+ || __builtin_memcmp (&s.d.c, "abcdefghijklmno", 16) || s.e != 0xdeadbeef
+ || __builtin_memcmp (&s.f.c, "ABCDEFGHIJKLMNO", 16) || s.g != 0 || s.h != 0)
+ __builtin_abort ();
+ __builtin_memset (&s, 0, sizeof (s));
+ s.a = 7;
+ s.g = 31;
+ s.h = (1U << 27) - 1;
+ foo (&s);
+ if (s.a != 7 || s.b != 231 || s.c != 42
+ || __builtin_memcmp (&s.d.c, "abcdefghijklmno", 16) || s.e != 0xdeadbeef
+ || __builtin_memcmp (&s.f.c, "ABCDEFGHIJKLMNO", 16) || s.g != 31 || s.h != (1U << 27) - 1)
+ __builtin_abort ();
+ __builtin_memset (&s, 0, sizeof (s));
+ bar (&s);
+ if (s.a != 0 || s.b != 231 || s.c != 42
+ || __builtin_memcmp (&s.d.c, "abcdefghijklmno", 16) || s.e != 0xdeadbeef
+ || __builtin_memcmp (&s.f.c, "ABCDEFGHIJKLMNO", 16) || s.g != 12 || s.h != 0)
+ __builtin_abort ();
+ __builtin_memset (&s, 0, sizeof (s));
+ s.a = 7;
+ s.g = 31;
+ s.h = (1U << 27) - 1;
+ bar (&s);
+ if (s.a != 7 || s.b != 231 || s.c != 42
+ || __builtin_memcmp (&s.d.c, "abcdefghijklmno", 16) || s.e != 0xdeadbeef
+ || __builtin_memcmp (&s.f.c, "ABCDEFGHIJKLMNO", 16) || s.g != 12 || s.h != (1U << 27) - 1)
+ __builtin_abort ();
+ baz (&t);
+ if (t.a != 0 || t.b != 0 || t.c != 42
+ || __builtin_memcmp (&t.d.c, "abcdefghijklmno", 16) || t.e != 0xdeadbeef
+ || __builtin_memcmp (&t.f.c, "ABCDEFGHIJKLMNO", 16) || t.g != 12 || t.h != 0)
+ __builtin_abort ();
+ __builtin_memset (&s, 0, sizeof (s));
+ t.a = 7;
+ t.b = 255;
+ t.g = 31;
+ t.h = (1U << 27) - 1;
+ baz (&t);
+ if (t.a != 7 || t.b != 255 || t.c != 42
+ || __builtin_memcmp (&t.d.c, "abcdefghijklmno", 16) || t.e != 0xdeadbeef
+ || __builtin_memcmp (&t.f.c, "ABCDEFGHIJKLMNO", 16) || t.g != 12 || t.h != (1U << 27) - 1)
+ __builtin_abort ();
+ return 0;
+}