https://gcc.gnu.org/bugzilla/show_bug.cgi?id=84503
Bug ID: 84503 Summary: [7/8 Regression] store-merging miscompilation on powerpc64 with -O3 since r241789 Product: gcc Version: 8.0 Status: UNCONFIRMED Severity: normal Priority: P3 Component: tree-optimization Assignee: unassigned at gcc dot gnu.org Reporter: jakub at gcc dot gnu.org Target Milestone: --- typedef __SIZE_TYPE__ size_t; typedef __UINTPTR_TYPE__ uintptr_t; struct S { int a; unsigned short b; int c, d, e; long f, g, h; int i, j; }; static struct S *k; static size_t l = 0; int m; static int bar (void) { unsigned i; int j; if (k[0].c == 0) { ++m; size_t n = l * 2; struct S *o; o = (struct S *) __builtin_realloc (k, sizeof (struct S) * n); if (!o) __builtin_exit (0); k = o; for (i = l; i < n; i++) { void *p = (void *) &k[i]; int q = 0; size_t r = sizeof (struct S); if ((((uintptr_t) p) % __alignof__ (long)) == 0 && r % sizeof (long) == 0) { long __attribute__ ((may_alias)) *s = (long *) p; long *t = (long *) ((char *) s + r); while (s < t) *s++ = 0; } else __builtin_memset (p, q, r); k[i].c = i + 1; k[i].a = -1; } k[n - 1].c = 0; k[0].c = l; l = n; } j = k[0].c; k[0].c = k[j].c; return j; } int main () { k = (struct S *) __builtin_malloc (sizeof (struct S)); if (!k) __builtin_exit (0); __builtin_memset (k, '\0', sizeof (struct S)); k->a = -1; l = 1; for (int i = 0; i < 15; ++i) bar (); if (m != 4) __builtin_abort (); return 0; } is miscompiled with -O3 starting with r241789. The bug can be seen when diffing store_merging dump with the previous one: --- rh1547495.c.192t.widening_mul 2018-02-21 17:25:00.049972838 +0100 +++ rh1547495.c.193t.store-merging 2018-02-21 17:25:00.049972838 +0100 @@ -1,6 +1,10 @@ ;; Function main (main, funcdef_no=1, decl_uid=2691, cgraph_uid=1, symbol_order=4) (executed once) +Coalescing successful! +Merged into 2 stores +New sequence of 2 stmts to replace old one of 3 stmts +Merging successful! main () { unsigned int i; @@ -120,8 +124,6 @@ main () goto <bb 11>; [57.11%] <bb 10> [local count: 510973054]: - MEM[(long int *)p_28] = 0; - MEM[(long int *)p_28 + 8B] = 0; MEM[(long int *)p_28 + 16B] = 0; MEM[(long int *)p_28 + 24B] = 0; MEM[(long int *)p_28 + 32B] = 0; @@ -130,7 +132,8 @@ main () _14 = i_31 + 1; _119 = (int) _14; MEM[(struct S *)p_28].c = _119; - MEM[(struct S *)p_28].a = -1; + MEM[(void *)p_28] = 18446744069414584320; + MEM[(long int *)p_28 + 8B] = 0; _111 = (long unsigned int) _14; if (n_21 > _111) goto <bb 8>; [89.00%] MEM[(void *)p_28] = 18446744069414584320; is fine, that stores 0xffffffff00000000 into the first 8 bytes, but MEM[(struct S *)p_28].c = _119; stores 4 bytes at offset 8 and MEM[(long int *)p_28 + 8B] = 0; overwrites it.