#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;
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));
/* 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);
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. */
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))
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. */
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:
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;
}
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
reg_known_value = 0;
reg_base_value = 0;
reg_base_value_size = 0;
+ if (alias_invariant)
+ {
+ free ((char *)alias_invariant);
+ alias_invariant = 0;
+ }
}
{
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
{
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
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;
{
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);
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);
{
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;
|| 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;
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,
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);
/* 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);