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

            Bug ID: 118350
           Summary: [12/13/14/15 Regression] Wrong number of loop
                    iterations starting with r7-3839-gde0a3fa38e2ad8
           Product: gcc
           Version: unknown
            Status: UNCONFIRMED
          Keywords: wrong-code
          Severity: normal
          Priority: P3
         Component: rtl-optimization
          Assignee: unassigned at gcc dot gnu.org
          Reporter: stefansf at gcc dot gnu.org
  Target Milestone: ---
            Target: s390*-*-*

static volatile unsigned long x = 0;
static unsigned int y = 0;
int main (void)
{
  {
  l:
    ++x;
    --y;
    if (y)
      goto l;
  }
  if (x != 0x100000000ul)
    __builtin_abort ();
}

On s390x compiling this e.g. via gcc -O2 -funroll-loops leads to wrong code. 
At the end of doloop2 we have:

(insn 6 2 75 2 (set (reg:SI 62 [ y_lsm.6 ])
        (mem/c:SI (symbol_ref:DI ("*.LANCHOR0") [flags 0x182]) [1 y+0 S4 A32]))
1507 {*movsi_zarch}
     (nil))
(note 75 6 72 9 [bb 9] NOTE_INSN_BASIC_BLOCK)
(insn 72 75 73 9 (parallel [
            (set (reg:SI 78)
                (plus:SI (reg:SI 62 [ y_lsm.6 ])
                    (const_int -1 [0xffffffffffffffff])))
            (clobber (reg:CC 33 %cc))
        ]) -1
     (nil))
(insn 73 72 74 9 (parallel [
            (set (reg:SI 79)
                (plus:SI (reg:SI 78)
                    (const_int 1 [0x1])))
            (clobber (reg:CC 33 %cc))
        ]) -1
     (nil))

That means reg 79 contains the initial value of y which is zero.  During
doloop2 we substitute the newly computed niter which is

(insn 281 184 196 37 (set (reg:SI 82)
        (lshiftrt:SI (reg:SI 79)
            (const_int 3 [0x3]))) -1
     (nil))

wich resulted from unroll2

desc->niter_expr =
  simplify_gen_binary (UDIV, desc->mode, old_niter,
                       gen_int_mode (max_unroll + 1, desc->mode));

Since old_niter is just y which is initially zero, dividing it by the number of
loop unrollings (in this case 8) leads to wrong code, i.e., the loop is
executed 8 times more which means the final value of x is not 0x100000000 but
0x800000000.

Although bisection stops at r7-3839-gde0a3fa38e2ad8 this doesn't seem to be the
culprit to me since it is not affecting the computation of niters.

Reply via email to