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.