diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 556f5db6a98..95de3cb4c9c 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,15 @@ +Wed Feb 3 20:44:59 1999 J"orn Rennecke + + * loop.h (express_from): Declare. + (struct induction): Replace derived flag with derived_from pointer. + * loop.c (strength_reduce, record_giv, recombine_givs): Likewise. + (express_from): No longer static. + * unroll.c (find_splittable_givs): Replace derived with derived_from. + When processing an address giv with which another giv has been + combined that has also been derived from a third giv, handle like + having combined with the third giv. + Set splittable_regs_updates appropriately for derived givs. + Wed Feb 3 15:26:58 1999 Gavin Romig-Koch * config/mips/mips.md (div_trap_mips16): Remove nop's after branches. diff --git a/gcc/loop.c b/gcc/loop.c index 2f054fb5d78..c0e78928ef7 100644 --- a/gcc/loop.c +++ b/gcc/loop.c @@ -320,7 +320,6 @@ static int general_induction_var PROTO((rtx, rtx *, rtx *, rtx *, int, int *)); static int consec_sets_giv PROTO((int, rtx, rtx, rtx, rtx *, rtx *, rtx *)); static int check_dbra_loop PROTO((rtx, int, rtx, struct loop_info *)); static rtx express_from_1 PROTO((rtx, rtx, rtx)); -static rtx express_from PROTO((struct induction *, struct induction *)); static rtx combine_givs_p PROTO((struct induction *, struct induction *)); static void combine_givs PROTO((struct iv_class *)); struct recombine_givs_stats; @@ -4180,7 +4179,7 @@ strength_reduce (scan_start, end, loop_top, insn_count, v->auto_inc_opt = 0; v->unrolled = 0; v->shared = 0; - v->derived = 0; + v->derived_from = 0; v->always_computable = 1; v->always_executed = 1; v->replaceable = 1; @@ -4622,7 +4621,7 @@ strength_reduce (scan_start, end, loop_top, insn_count, v->new_reg = gen_reg_rtx (v->mode); - if (v->derived) + if (v->derived_from) { PATTERN (v->insn) = replace_rtx (PATTERN (v->insn), v->dest_reg, v->new_reg); @@ -5273,7 +5272,7 @@ record_giv (v, insn, src_reg, dest_reg, mult_val, add_val, benefit, v->auto_inc_opt = 0; v->unrolled = 0; v->shared = 0; - v->derived = 0; + v->derived_from = 0; v->last_use = 0; /* The v->always_computable field is used in update_giv_derive, to @@ -6632,7 +6631,7 @@ express_from_1 (a, b, mult) return NULL_RTX; } -static rtx +rtx express_from (g1, g2) struct induction *g1, *g2; { @@ -7290,7 +7289,7 @@ recombine_givs (bl, loop_start, loop_end, unroll_p) rtx sum; v = giv_array[stats[i].giv_number]; - if (v->giv_type != DEST_REG || v->derived || v->same) + if (v->giv_type != DEST_REG || v->derived_from || v->same) continue; if (! last_giv) { @@ -7347,7 +7346,7 @@ recombine_givs (bl, loop_start, loop_end, unroll_p) gen_rtx_SET (GET_MODE (v->dest_reg), v->dest_reg, sum), 0)) { - v->derived = 1; + v->derived_from = last_giv; v->new_reg = v->dest_reg; life_end = stats[i].end_luid; diff --git a/gcc/loop.h b/gcc/loop.h index f183b9e8fe5..50279bb09ec 100644 --- a/gcc/loop.h +++ b/gcc/loop.h @@ -101,8 +101,6 @@ struct induction initialized in unrolled loop. */ unsigned shared : 1; unsigned no_const_addval : 1; /* 1 if add_val does not contain a const. */ - unsigned derived : 1; /* For a giv, 1 if we decided to derive this - giv from another one. */ int lifetime; /* Length of life of this giv */ rtx derive_adjustment; /* If nonzero, is an adjustment to be subtracted from add_val when this giv @@ -115,6 +113,8 @@ struct induction struct induction *same; /* If this giv has been combined with another giv, this points to the base giv. The base giv will have COMBINED_WITH non-zero. */ + struct induction *derived_from;/* For a giv, if we decided to derive this + giv from another one. */ HOST_WIDE_INT const_adjust; /* Used by loop unrolling, when an address giv is split, and a constant is eliminated from the address, the -constant is stored here @@ -226,6 +226,7 @@ extern int first_increment_giv, last_increment_giv; int invariant_p PROTO((rtx)); rtx get_condition_for_loop PROTO((rtx)); void emit_iv_add_mult PROTO((rtx, rtx, rtx, rtx, rtx)); +rtx express_from PROTO((struct induction *, struct induction *)); /* Forward declarations for non-static functions declared in stmt.c. */ void find_loop_tree_blocks PROTO((void)); diff --git a/gcc/unroll.c b/gcc/unroll.c index 0d1787c0e52..341b8059882 100644 --- a/gcc/unroll.c +++ b/gcc/unroll.c @@ -1794,6 +1794,10 @@ copy_loop_body (copy_start, copy_end, map, exit_label, last_iteration, giv_dest_reg = SET_DEST (set); if (derived_regs[regno]) { + /* ??? This relies on SET_SRC (SET) to be of + the form (plus (reg) (const_int)), and thus + forces recombine_givs to restrict the kind + of giv derivations it does before unrolling. */ giv_src_reg = XEXP (SET_SRC (set), 0); giv_inc = XEXP (SET_SRC (set), 1); } @@ -2830,7 +2834,7 @@ find_splittable_givs (bl, unroll_type, loop_start, loop_end, increment, } splittable_regs[REGNO (v->new_reg)] = value; - derived_regs[REGNO (v->new_reg)] = v->derived; + derived_regs[REGNO (v->new_reg)] = v->derived_from != 0; } else { @@ -2886,17 +2890,36 @@ find_splittable_givs (bl, unroll_type, loop_start, loop_end, increment, Emit insn to initialize its value before loop start. */ rtx tem = gen_reg_rtx (v->mode); + struct induction *same = v->same; + rtx new_reg = v->new_reg; record_base_value (REGNO (tem), v->add_val, 0); + if (same && same->derived_from) + { + /* calculate_giv_inc doesn't work for derived givs. + copy_loop_body works around the problem for the + DEST_REG givs themselves, but it can't handle + DEST_ADDR givs that have been combined with + derived a derived DEST_REG giv. + So Handle V as if the giv from which V->SAME has + been derived has been combined with V. + recombine_givs only derives givs from givs that + are reduced the ordinary, so we need not worry + about same->derived_from being in turn derived. */ + + same = same->derived_from; + new_reg = express_from (same, v); + } + /* If the address giv has a constant in its new_reg value, then this constant can be pulled out and put in value, instead of being part of the initialization code. */ - if (GET_CODE (v->new_reg) == PLUS - && GET_CODE (XEXP (v->new_reg, 1)) == CONST_INT) + if (GET_CODE (new_reg) == PLUS + && GET_CODE (XEXP (new_reg, 1)) == CONST_INT) { v->dest_reg - = plus_constant (tem, INTVAL (XEXP (v->new_reg,1))); + = plus_constant (tem, INTVAL (XEXP (new_reg, 1))); /* Only succeed if this will give valid addresses. Try to validate both the first and the last @@ -2907,9 +2930,9 @@ find_splittable_givs (bl, unroll_type, loop_start, loop_end, increment, /* Save the negative of the eliminated const, so that we can calculate the dest_reg's increment value later. */ - v->const_adjust = - INTVAL (XEXP (v->new_reg, 1)); + v->const_adjust = - INTVAL (XEXP (new_reg, 1)); - v->new_reg = XEXP (v->new_reg, 0); + new_reg = XEXP (new_reg, 0); if (loop_dump_stream) fprintf (loop_dump_stream, "Eliminating constant from giv %d\n", @@ -2938,6 +2961,9 @@ find_splittable_givs (bl, unroll_type, loop_start, loop_end, increment, INSN_UID (v->insn)); continue; } + + v->new_reg = new_reg; + v->same = same; /* We set this after the address check, to guarantee that the register will be initialized. */ @@ -2992,6 +3018,15 @@ find_splittable_givs (bl, unroll_type, loop_start, loop_end, increment, INSN_UID (v->insn)); continue; } + if (v->same && v->same->derived_from) + { + /* Handle V as if the giv from which V->SAME has + been derived has been combined with V. */ + + v->same = v->same->derived_from; + v->new_reg = express_from (v->same, v); + } + } /* Store the value of dest_reg into the insn. This sharing @@ -3014,7 +3049,7 @@ find_splittable_givs (bl, unroll_type, loop_start, loop_end, increment, Make sure that it's giv is marked as splittable here. */ splittable_regs[REGNO (v->new_reg)] = value; - derived_regs[REGNO (v->new_reg)] = v->derived; + derived_regs[REGNO (v->new_reg)] = v->derived_from != 0; /* Make it appear to depend upon itself, so that the giv will be properly split in the main loop above. */ @@ -3058,6 +3093,11 @@ find_splittable_givs (bl, unroll_type, loop_start, loop_end, increment, if (! v->ignore) count = reg_biv_class[REGNO (v->src_reg)]->biv_count; + if (count > 1 && v->derived_from) + /* In this case, there is one set where the giv insn was and one + set each after each biv increment. (Most are likely dead.) */ + count++; + splittable_regs_updates[REGNO (v->new_reg)] = count; }