https://gcc.gnu.org/bugzilla/show_bug.cgi?id=93908

            Bug ID: 93908
           Summary: [8/9/10 Regression] git miscompilation on s390x-linux
                    with -O2 -march=zEC12 -mtune=z13 starting with r8-1288
           Product: gcc
           Version: 9.2.1
            Status: UNCONFIRMED
          Severity: normal
          Priority: P3
         Component: rtl-optimization
          Assignee: unassigned at gcc dot gnu.org
          Reporter: jakub at gcc dot gnu.org
  Target Milestone: ---

The following testcase manually reduced from git's diff.c is miscompiled on
s390x-linux with -O2 -march=zEC12 -mtune=z13 starting with
r8-1288-ge701e0b9e8c74e5e93764556a447ea334e4e9389 .  git itself started to be
miscompiled with r10-4651-gafeb887562af17ea235fbec650ff6d16c412682a (r10-4650
fails to build), but that was just (apparently quite significant) change in
inlining behavior (Martin L., was that intended?).

struct T
{
  int b;
  int c;
  unsigned short d;
  unsigned e:1, f:1, g:1, h:2, i:1, j:1;
  signed int k:2;
};

struct S
{
  struct T s;
  char c[64];
} buf[2];

__attribute__ ((noinline, noclone, noipa)) void *
baz (void)
{
  static int cnt;
  return (void *) &buf[cnt++];
}

static inline __attribute__ ((always_inline)) struct T *
bar (const char *a)
{
  struct T *s;
  s = baz ();
  s->b = 1;
  s->k = -1;
  return s;
}

__attribute__ ((noinline, noclone, noipa)) void
foo (const char *x, struct T **y)
{
  struct T *l = bar (x);
  struct T *m = bar (x);
  y[0] = l;
  y[1] = m;
}

int
main ()
{
  struct T *r[2];
  foo ("foo", r);
  if (r[0]->e || r[0]->f || r[0]->g || r[0]->h || r[0]->i || r[0]->j || r[0]->k
!= -1)
    __builtin_abort ();
  if (r[1]->e || r[1]->f || r[1]->g || r[1]->h || r[1]->i || r[1]->j || r[1]->k
!= -1)
    __builtin_abort ();
  return 0;
}

The first s->k = -1; bitfield store is always done through:
 (insn 14 13 15 2 (parallel [
             (set (mem/j:HI (plus:DI (reg/v/f:DI 61 [ s ])
                         (const_int 10 [0xa])) [0 +0 S2 A16])
                 (ior:HI (mem/j:HI (plus:DI (reg/v/f:DI 61 [ s ])
                             (const_int 10 [0xa])) [0 +0 S2 A16])
                     (const_int 384 [0x180])))
             (clobber (reg:CC 33 %cc))
         ]) "diff2.i":29 1733 {*iorhi3_zarch}
      (expr_list:REG_UNUSED (reg:CC 33 %cc)
         (nil)))
but the second one changed like:
 (insn 22 21 23 2 (parallel [
             (set (mem/j:HI (plus:DI (reg/v/f:DI 60 [ s ])
                         (const_int 10 [0xa])) [0 +0 S2 A16])
                 (ior:HI (mem/j:HI (plus:DI (reg/v/f:DI 60 [ s ])
                             (const_int 10 [0xa])) [0 +0 S2 A16])
-                    (const_int 384 [0x180])))
+                    (const_int -128 [0xffffffffffffff80])))
             (clobber (reg:CC 33 %cc))
         ]) "diff2.i":29 1733 {*iorhi3_zarch}
      (expr_list:REG_UNUSED (reg:CC 33 %cc)
         (nil)))
which means it sets to all ones various other bitfields.

Reply via email to