diff options
author | Zoltan Hidvegi <hzoli@hzoli.2y.net> | 2001-11-30 23:27:52 +0000 |
---|---|---|
committer | David Edelsohn <dje@gcc.gnu.org> | 2001-11-30 18:27:52 -0500 |
commit | d2384b42b71b44a33544ab87254ba7abea6c45f9 (patch) | |
tree | d95f24ee811f21b2743ece3e6720b2fd527d36e1 /gcc/unroll.c | |
parent | 38875aba474d312aa737aec754d70cf690e6ae25 (diff) | |
download | gcc-d2384b42b71b44a33544ab87254ba7abea6c45f9.zip gcc-d2384b42b71b44a33544ab87254ba7abea6c45f9.tar.gz gcc-d2384b42b71b44a33544ab87254ba7abea6c45f9.tar.bz2 |
* unroll.c (unroll_loop): Correct special exit cases.
From-SVN: r47499
Diffstat (limited to 'gcc/unroll.c')
-rw-r--r-- | gcc/unroll.c | 41 |
1 files changed, 32 insertions, 9 deletions
diff --git a/gcc/unroll.c b/gcc/unroll.c index 4b7dd97..b66916e 100644 --- a/gcc/unroll.c +++ b/gcc/unroll.c @@ -901,6 +901,9 @@ unroll_loop (loop, insn_count, strength_reduce_p) rtx diff; rtx *labels; int abs_inc, neg_inc; + enum rtx_code cc = loop_info->comparison_code; + int less_p = (cc == LE || cc == LEU || cc == LT || cc == LTU); + int unsigned_p = (cc == LEU || cc == GEU || cc == LTU || cc == GTU); map->reg_map = (rtx *) xmalloc (maxregnum * sizeof (rtx)); @@ -933,11 +936,25 @@ unroll_loop (loop, insn_count, strength_reduce_p) a constant. We must copy the final and initial values here to avoid - improperly shared rtl. */ - - diff = expand_simple_binop (mode, MINUS, copy_rtx (final_value), - copy_rtx (initial_value), NULL_RTX, 0, - OPTAB_LIB_WIDEN); + improperly shared rtl. + + We have to deal with for (i = 0; --i < 6;) type loops. + For such loops the real final value is the first time the + loop variable overflows, so the diff we calculate is the + distance from the overflow value. This is 0 or ~0 for + unsigned loops depending on the direction, or INT_MAX, + INT_MAX+1 for signed loops. We really do not need the + exact value, since we are only interested in the diff + modulo the increment, and the increment is a power of 2, + so we can pretend that the overflow value is 0/~0. */ + + if (cc == NE || less_p != neg_inc) + diff = expand_simple_binop (mode, MINUS, copy_rtx (final_value), + copy_rtx (initial_value), NULL_RTX, 0, + OPTAB_LIB_WIDEN); + else + diff = expand_simple_unop (mode, neg_inc ? NOT : NEG, + copy_rtx (initial_value), NULL_RTX, 0); /* Now calculate (diff % (unroll * abs (increment))) by using an and instruction. */ @@ -958,11 +975,17 @@ unroll_loop (loop, insn_count, strength_reduce_p) case. This check does not apply if the loop has a NE comparison at the end. */ - if (loop_info->comparison_code != NE) + if (cc != NE) { - emit_cmp_and_jump_insns (initial_value, final_value, - neg_inc ? LE : GE, - NULL_RTX, mode, 0, labels[1]); + rtx incremented_initval; + incremented_initval = expand_simple_binop (mode, PLUS, + initial_value, + increment, + NULL_RTX, 0, + OPTAB_LIB_WIDEN); + emit_cmp_and_jump_insns (incremented_initval, final_value, + less_p ? GE : LE, NULL_RTX, + mode, unsigned_p, labels[1]); predict_insn_def (get_last_insn (), PRED_LOOP_CONDITION, NOT_TAKEN); JUMP_LABEL (get_last_insn ()) = labels[1]; |