aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gcc/ChangeLog14
-rw-r--r--gcc/alias.c89
-rw-r--r--gcc/loop.c2
-rw-r--r--gcc/rtl.h2
-rw-r--r--gcc/unroll.c25
5 files changed, 96 insertions, 36 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 118c16b..f981008 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,17 @@
+Sat Apr 25 17:55:54 1998 John Carr <jfc@mit.edu>
+
+ * 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 bc0b49c..a9024b8 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 bcc7d2c..6b66484 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 c01770a..76b1565 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 c21e69f..a6cd9bd 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);