From de12be17436e7a02a24b9e99da71fb6bfa9a8075 Mon Sep 17 00:00:00 2001 From: John Carr Date: Sat, 25 Apr 1998 16:09:24 +0000 Subject: [PATCH] alias.c (alias_invariant): New variable. * alias.c (alias_invariant): New variable. (record_base_value): New argument INVARIANT. (memrefs_conflict_p): If a register has an entry in the alias_invariant array, try substituting that value for the register. * rtl.h: Declare record_base_value. * loop.c, unroll.c: Update callers of record_base_value. * alias.c (find_base_value, find_base_term): SIGN_EXTEND and ZERO_EXTEND do not affect base values. From-SVN: r19408 --- gcc/ChangeLog | 14 ++++++++ gcc/alias.c | 89 ++++++++++++++++++++++++++++++++++++--------------- gcc/loop.c | 2 +- gcc/rtl.h | 2 ++ gcc/unroll.c | 25 +++++++++------ 5 files changed, 96 insertions(+), 36 deletions(-) diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 118c16b0719..f98100817f8 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,17 @@ +Sat Apr 25 17:55:54 1998 John Carr + + * alias.c (alias_invariant): New variable. + (record_base_value): New argument INVARIANT. + (memrefs_conflict_p): If a register has an entry in the alias_invariant + array, try substituting that value for the register. + + * rtl.h: Declare record_base_value. + + * loop.c, unroll.c: Update callers of record_base_value. + + * alias.c (find_base_value, find_base_term): SIGN_EXTEND and + ZERO_EXTEND do not affect base values. + Fri Apr 24 15:57:02 1998 Jeffrey A Law (law@cygnus.com) * dbxout.c (dbxout_type): Fix typo. diff --git a/gcc/alias.c b/gcc/alias.c index bc0b49c2322..a9024b8c98f 100644 --- a/gcc/alias.c +++ b/gcc/alias.c @@ -68,6 +68,16 @@ unsigned int reg_base_value_size; /* size of reg_base_value array */ #define REG_BASE_VALUE(X) \ (REGNO (X) < reg_base_value_size ? reg_base_value[REGNO (X)] : 0) +/* Vector of known invariant relationships between registers. Set in + loop unrolling. Indexed by register number, if nonzero the value + is an expression describing this register in terms of another. + + The length of this array is REG_BASE_VALUE_SIZE. + + Because this array contains only pseudo registers it has no effect + after reload. */ +static rtx *alias_invariant; + /* Vector indexed by N giving the initial (unchanging) value known for pseudo-register N. */ rtx *reg_known_value; @@ -205,6 +215,8 @@ find_base_value (src) return find_base_value (XEXP (src, 0)); return 0; + case ZERO_EXTEND: + case SIGN_EXTEND: /* used for NT/Alpha pointers */ case HIGH: return find_base_value (XEXP (src, 0)); @@ -295,16 +307,26 @@ record_set (dest, set) /* Called from loop optimization when a new pseudo-register is created. */ void -record_base_value (regno, val) +record_base_value (regno, val, invariant) int regno; rtx val; + int invariant; { if (regno >= reg_base_value_size) return; + + /* If INVARIANT is true then this value also describes an invariant + relationship which can be used to deduce that two registers with + unknown values are different. */ + if (invariant && alias_invariant) + alias_invariant[regno] = val; + if (GET_CODE (val) == REG) { if (REGNO (val) < reg_base_value_size) - reg_base_value[regno] = reg_base_value[REGNO (val)]; + { + reg_base_value[regno] = reg_base_value[REGNO (val)]; + } return; } reg_base_value[regno] = find_base_value (val); @@ -397,6 +419,10 @@ rtx_equal_for_memref_p (x, y) return XEXP (x, 0) == XEXP (y, 0); if (code == SYMBOL_REF) return XSTR (x, 0) == XSTR (y, 0); + if (code == CONST_INT) + return INTVAL (x) == INTVAL (y); + if (code == ADDRESSOF) + return REGNO (XEXP (x, 0)) == REGNO (XEXP (y, 0)) && XINT (x, 1) == XINT (y, 1); /* For commutative operations, the RTX match if the operand match in any order. Also handle the simple binary and unary cases without a loop. */ @@ -412,25 +438,20 @@ rtx_equal_for_memref_p (x, y) return rtx_equal_for_memref_p (XEXP (x, 0), XEXP (y, 0)); /* Compare the elements. If any pair of corresponding elements - fail to match, return 0 for the whole things. */ + fail to match, return 0 for the whole things. + + Limit cases to types which actually appear in addresses. */ fmt = GET_RTX_FORMAT (code); for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--) { switch (fmt[i]) { - case 'w': - if (XWINT (x, i) != XWINT (y, i)) - return 0; - break; - - case 'n': case 'i': if (XINT (x, i) != XINT (y, i)) return 0; break; - case 'V': case 'E': /* Two vectors must have the same length. */ if (XVECLEN (x, i) != XVECLEN (y, i)) @@ -447,19 +468,6 @@ rtx_equal_for_memref_p (x, y) return 0; break; - case 'S': - case 's': - if (strcmp (XSTR (x, i), XSTR (y, i))) - return 0; - break; - - case 'u': - /* These are just backpointers, so they don't matter. */ - break; - - case '0': - break; - /* It is believed that rtx's at this level will never contain anything but integers and other rtx's, except for within LABEL_REFs and SYMBOL_REFs. */ @@ -513,9 +521,9 @@ find_base_term (x) case REG: return REG_BASE_VALUE (x); + case ZERO_EXTEND: + case SIGN_EXTEND: /* Used for Alpha/NT pointers */ case HIGH: - return find_base_term (XEXP (x, 0)); - case PRE_INC: case PRE_DEC: case POST_INC: @@ -747,6 +755,25 @@ memrefs_conflict_p (xsize, x, ysize, y, c) return memrefs_conflict_p (xsize, x0, ysize, y0, c); } + case REG: + /* Are these registers known not to be equal? */ + if (alias_invariant) + { + int r_x = REGNO (x), r_y = REGNO (y); + rtx i_x, i_y; /* invariant relationships of X and Y */ + + i_x = r_x >= reg_base_value_size ? 0 : alias_invariant[r_x]; + i_y = r_y >= reg_base_value_size ? 0 : alias_invariant[r_y]; + + if (i_x == 0 && i_y == 0) + break; + + if (! memrefs_conflict_p (xsize, i_x ? i_x : x, + ysize, i_y ? i_y : y, c)) + return 0; + } + break; + default: break; } @@ -1034,6 +1061,13 @@ init_alias_analysis () new_reg_base_value = (rtx *)alloca (reg_base_value_size * sizeof (rtx)); reg_seen = (char *)alloca (reg_base_value_size); bzero ((char *) reg_base_value, reg_base_value_size * sizeof (rtx)); + if (! reload_completed && flag_unroll_loops) + { + alias_invariant = (rtx *)xrealloc (alias_invariant, + reg_base_value_size * sizeof (rtx)); + bzero ((char *)alias_invariant, reg_base_value_size * sizeof (rtx)); + } + /* The basic idea is that each pass through this loop will use the "constant" information from the previous pass to propagate alias @@ -1203,4 +1237,9 @@ end_alias_analysis () reg_known_value = 0; reg_base_value = 0; reg_base_value_size = 0; + if (alias_invariant) + { + free ((char *)alias_invariant); + alias_invariant = 0; + } } diff --git a/gcc/loop.c b/gcc/loop.c index bcc7d2cc663..6b66484647b 100644 --- a/gcc/loop.c +++ b/gcc/loop.c @@ -5986,7 +5986,7 @@ emit_iv_add_mult (b, m, a, reg, insert_before) emit_insn_before (seq, insert_before); - record_base_value (REGNO (reg), b); + record_base_value (REGNO (reg), b, 0); } /* Test whether A * B can be computed without diff --git a/gcc/rtl.h b/gcc/rtl.h index c01770a90f3..76b15654c80 100644 --- a/gcc/rtl.h +++ b/gcc/rtl.h @@ -1402,4 +1402,6 @@ extern void init_alias_once PROTO ((void)); extern void init_alias_analysis PROTO ((void)); extern void end_alias_analysis PROTO ((void)); +extern void record_base_value PROTO ((int, rtx, int)); + #endif /* _RTL_H */ diff --git a/gcc/unroll.c b/gcc/unroll.c index c21e69f93f9..a6cd9bdd529 100644 --- a/gcc/unroll.c +++ b/gcc/unroll.c @@ -1054,7 +1054,7 @@ unroll_loop (loop_end, insn_count, loop_start, end_insert_before, { map->reg_map[j] = gen_reg_rtx (GET_MODE (regno_reg_rtx[j])); record_base_value (REGNO (map->reg_map[j]), - regno_reg_rtx[j]); + regno_reg_rtx[j], 0); } /* The last copy needs the compare/branch insns at the end, so reset copy_end here if the loop ends with a conditional @@ -1216,7 +1216,7 @@ unroll_loop (loop_end, insn_count, loop_start, end_insert_before, { map->reg_map[j] = gen_reg_rtx (GET_MODE (regno_reg_rtx[j])); record_base_value (REGNO (map->reg_map[j]), - regno_reg_rtx[j]); + regno_reg_rtx[j], 0); } /* If loop starts with a branch to the test, then fix it so that @@ -1861,7 +1861,12 @@ copy_loop_body (copy_start, copy_end, map, exit_label, last_iteration, tem = gen_reg_rtx (GET_MODE (giv_src_reg)); giv_dest_reg = tem; map->reg_map[regno] = tem; - record_base_value (REGNO (tem), giv_src_reg); + record_base_value (REGNO (tem), + giv_inc == const0_rtx + ? giv_src_reg + : gen_rtx_PLUS (GET_MODE (giv_src_reg), + giv_src_reg, giv_inc), + 1); } else map->reg_map[regno] = giv_src_reg; @@ -2560,7 +2565,7 @@ find_splittable_regs (unroll_type, loop_start, loop_end, end_insert_before, { rtx tem = gen_reg_rtx (bl->biv->mode); - record_base_value (REGNO (tem), bl->biv->add_val); + record_base_value (REGNO (tem), bl->biv->add_val, 0); emit_insn_before (gen_move_insn (tem, bl->biv->src_reg), loop_start); @@ -2617,7 +2622,7 @@ find_splittable_regs (unroll_type, loop_start, loop_end, end_insert_before, this insn will always be executed, no matter how the loop exits. */ rtx tem = gen_reg_rtx (bl->biv->mode); - record_base_value (REGNO (tem), bl->biv->add_val); + record_base_value (REGNO (tem), bl->biv->add_val, 0); emit_insn_before (gen_move_insn (tem, bl->biv->src_reg), loop_start); @@ -2799,7 +2804,7 @@ find_splittable_givs (bl, unroll_type, loop_start, loop_end, increment, { rtx tem = gen_reg_rtx (bl->biv->mode); - record_base_value (REGNO (tem), bl->biv->add_val); + record_base_value (REGNO (tem), bl->biv->add_val, 0); emit_insn_before (gen_move_insn (tem, bl->biv->src_reg), loop_start); biv_initial_value = tem; @@ -2841,7 +2846,7 @@ find_splittable_givs (bl, unroll_type, loop_start, loop_end, increment, || GET_CODE (XEXP (value, 1)) != CONST_INT)) { rtx tem = gen_reg_rtx (v->mode); - record_base_value (REGNO (tem), v->add_val); + record_base_value (REGNO (tem), v->add_val, 0); emit_iv_add_mult (bl->initial_value, v->mult_val, v->add_val, tem, loop_start); value = tem; @@ -2900,7 +2905,7 @@ 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); - record_base_value (REGNO (tem), v->add_val); + record_base_value (REGNO (tem), v->add_val, 0); v->unrolled = 1; /* If the address giv has a constant in its new_reg value, @@ -3216,7 +3221,7 @@ final_biv_value (bl, loop_start, loop_end) case it is needed later. */ tem = gen_reg_rtx (bl->biv->mode); - record_base_value (REGNO (tem), bl->biv->add_val); + record_base_value (REGNO (tem), bl->biv->add_val, 0); /* Make sure loop_end is not the last insn. */ if (NEXT_INSN (loop_end) == 0) emit_note_after (NOTE_INSN_DELETED, loop_end); @@ -3315,7 +3320,7 @@ final_giv_value (v, loop_start, loop_end) /* Put the final biv value in tem. */ tem = gen_reg_rtx (bl->biv->mode); - record_base_value (REGNO (tem), bl->biv->add_val); + record_base_value (REGNO (tem), bl->biv->add_val, 0); emit_iv_add_mult (increment, GEN_INT (loop_n_iterations), bl->initial_value, tem, insert_before); -- 2.30.2