Index: unroll.c =================================================================== RCS file: /cvs/gcc/gcc/gcc/unroll.c,v retrieving revision 1.146 diff -u -r1.146 unroll.c --- unroll.c 2001/11/16 17:08:12 1.146 +++ unroll.c 2001/11/26 16:44:55 @@ -3479,6 +3479,8 @@ int unsigned_p, compare_dir, final_larger; rtx last_loop_insn; rtx reg_term; + rtx insn; + rtx end_loop_scan; struct iv_class *bl; loop_info->n_iterations = 0; @@ -3704,6 +3706,62 @@ if (initial_value == 0) return 0; + + /* Some code transformations can result in code akin to + + LOOP_BEG + goto start; + top: + i++; + start: + ... + LOOP_CONT + if (i < n) goto top; + LOOP_END + + In this situation, we skip the increment the first time through + the loop, which results in an incorrect estimate of the number + of iterations. As we did for GIVs above, adjust the initial value + to compensate. */ + + off_by_one = 0; + if (loop->top) + end_loop_scan = loop->top; + else + end_loop_scan = loop->cont; + + for (insn = loop->start; insn != end_loop_scan; insn = NEXT_INSN (insn)) + if (GET_CODE (insn) == JUMP_INSN) + { + if (any_uncondjump_p (insn) + && JUMP_LABEL (insn) + && INSN_IN_RANGE_P (JUMP_LABEL (insn), insn, loop->end)) + { + if (reg_set_between_p (bl->biv->src_reg, insn, JUMP_LABEL (insn))) + off_by_one = 1; + break; + } + /* No idea what's going on. */ + if (loop_dump_stream) + fprintf (loop_dump_stream, + "Loop iterations: Confused by jump before loop top.\n"); + return 0; + } + + if (off_by_one) + { + if (loop_dump_stream) + fprintf (loop_dump_stream, + "Loop iterations: Basic induction var skips initial incr.\n"); + if (GET_CODE (increment) != CONST_INT) + { + if (loop_dump_stream) + fprintf (loop_dump_stream, + "Loop iterations: Can't adjust with non-constant incr.\n"); + return 0; + } + initial_value = plus_constant (initial_value, -INTVAL (increment)); + } unsigned_p = 0; off_by_one = 0;