/* Try to unroll loops, and split induction variables.
Copyright (C) 1992, 1993, 1994, 1995, 1997, 1998, 1999, 2000, 2001,
- 2002, 2003
+ 2002, 2003, 2004
Free Software Foundation, Inc.
Contributed by James E. Wilson, Cygnus Support/UC Berkeley.
without initializing fields within the map structure.
To be safe, we use xcalloc to zero the memory. */
- map = (struct inline_remap *) xcalloc (1, sizeof (struct inline_remap));
+ map = xcalloc (1, sizeof (struct inline_remap));
/* Allocate the label map. */
if (max_labelno > 0)
{
- map->label_map = (rtx *) xcalloc (max_labelno, sizeof (rtx));
- local_label = (char *) xcalloc (max_labelno, sizeof (char));
+ map->label_map = xcalloc (max_labelno, sizeof (rtx));
+ local_label = xcalloc (max_labelno, sizeof (char));
}
/* Search the loop and mark all local labels, i.e. the ones which have to
/* Allocate space for the insn map. */
- map->insn_map = (rtx *) xmalloc (max_insnno * sizeof (rtx));
+ map->insn_map = xmalloc (max_insnno * sizeof (rtx));
/* Set this to zero, to indicate that we are doing loop unrolling,
not function inlining. */
preconditioning code and find_splittable_regs will never be used
to access the splittable_regs[] and addr_combined_regs[] arrays. */
- splittable_regs = (rtx *) xcalloc (maxregnum, sizeof (rtx));
- splittable_regs_updates = (int *) xcalloc (maxregnum, sizeof (int));
- addr_combined_regs
- = (struct induction **) xcalloc (maxregnum, sizeof (struct induction *));
- local_regno = (char *) xcalloc (maxregnum, sizeof (char));
+ splittable_regs = xcalloc (maxregnum, sizeof (rtx));
+ splittable_regs_updates = xcalloc (maxregnum, sizeof (int));
+ addr_combined_regs = xcalloc (maxregnum, sizeof (struct induction *));
+ local_regno = xcalloc (maxregnum, sizeof (char));
/* Mark all local registers, i.e. the ones which are referenced only
inside the loop. */
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));
+ map->reg_map = xmalloc (maxregnum * sizeof (rtx));
VARRAY_CONST_EQUIV_INIT (map->const_equiv_varray, maxregnum,
"unroll_loop_precondition");
/* Now emit a sequence of branches to jump to the proper precond
loop entry point. */
- labels = (rtx *) xmalloc (sizeof (rtx) * unroll_number);
+ labels = xmalloc (sizeof (rtx) * unroll_number);
for (i = 0; i < unroll_number; i++)
labels[i] = gen_label_rtx ();
emit_label_after (labels[unroll_number - i],
PREV_INSN (loop_start));
- memset ((char *) map->insn_map, 0, max_insnno * sizeof (rtx));
- memset ((char *) &VARRAY_CONST_EQUIV (map->const_equiv_varray, 0),
+ memset (map->insn_map, 0, max_insnno * sizeof (rtx));
+ memset (&VARRAY_CONST_EQUIV (map->const_equiv_varray, 0),
0, (VARRAY_SIZE (map->const_equiv_varray)
* sizeof (struct const_equiv_data)));
map->const_age = 0;
the constant maps also. */
maxregnum = max_reg_num ();
- map->reg_map = (rtx *) xmalloc (maxregnum * sizeof (rtx));
+ map->reg_map = xmalloc (maxregnum * sizeof (rtx));
init_reg_map (map, maxregnum);
for (i = 0; i < unroll_number; i++)
{
- memset ((char *) map->insn_map, 0, max_insnno * sizeof (rtx));
- memset ((char *) &VARRAY_CONST_EQUIV (map->const_equiv_varray, 0), 0,
+ memset (map->insn_map, 0, max_insnno * sizeof (rtx));
+ memset (&VARRAY_CONST_EQUIV (map->const_equiv_varray, 0), 0,
VARRAY_SIZE (map->const_equiv_varray) * sizeof (struct const_equiv_data));
map->const_age = 0;
{
rtx t, insn;
- t = simplify_relational_operation (code, mode, op0, op1);
+ t = simplify_const_relational_operation (code, mode, op0, op1);
if (!t)
{
enum rtx_code scode = signed_condition (code);
if (v->always_computable && v->mult_val == const1_rtx
&& ! v->maybe_multiple
&& SCALAR_INT_MODE_P (v->mode))
- result = fold_rtx_mult_add (result, const1_rtx, v->add_val, v->mode);
+ {
+ /* If we have already counted it, skip it. */
+ if (v->same)
+ continue;
+
+ result = fold_rtx_mult_add (result, const1_rtx, v->add_val, v->mode);
+ }
else
return 0;
}
{
rtx tem = gen_reg_rtx (v->mode);
record_base_value (REGNO (tem), v->add_val, 0);
- loop_iv_add_mult_hoist (loop, bl->initial_value, v->mult_val,
- v->add_val, tem);
+ loop_iv_add_mult_hoist (loop,
+ extend_value_for_giv (v, bl->initial_value),
+ v->mult_val, v->add_val, tem);
value = tem;
}
reg_dead_after_loop (const struct loop *loop, rtx reg)
{
rtx insn, label;
- enum rtx_code code;
int jump_count = 0;
int label_count = 0;
insn = NEXT_INSN (XEXP (label, 0));
while (insn)
{
- code = GET_CODE (insn);
- if (GET_RTX_CLASS (code) == 'i')
+ if (INSN_P (insn))
{
- rtx set;
+ rtx set, note;
if (reg_referenced_p (reg, PATTERN (insn)))
return 0;
+ note = find_reg_equal_equiv_note (insn);
+ if (note && reg_overlap_mentioned_p (reg, XEXP (note, 0)))
+ return 0;
+
set = single_set (insn);
if (set && rtx_equal_p (SET_DEST (set), reg))
break;
- }
- if (code == JUMP_INSN)
- {
- if (GET_CODE (PATTERN (insn)) == RETURN)
- break;
- else if (!any_uncondjump_p (insn)
- /* Prevent infinite loop following infinite loops. */
- || jump_count++ > 20)
- return 0;
- else
- insn = JUMP_LABEL (insn);
+ if (GET_CODE (insn) == JUMP_INSN)
+ {
+ if (GET_CODE (PATTERN (insn)) == RETURN)
+ break;
+ else if (!any_uncondjump_p (insn)
+ /* Prevent infinite loop following infinite loops. */
+ || jump_count++ > 20)
+ return 0;
+ else
+ insn = JUMP_LABEL (insn);
+ }
}
insn = NEXT_INSN (insn);
"Loop iterations: Iteration var not an integer.\n");
return 0;
}
- else if (REG_IV_TYPE (ivs, REGNO (iteration_var)) == BASIC_INDUCT)
+
+ /* Try swapping the comparison to identify a suitable iv. */
+ if (REG_IV_TYPE (ivs, REGNO (iteration_var)) != BASIC_INDUCT
+ && REG_IV_TYPE (ivs, REGNO (iteration_var)) != GENERAL_INDUCT
+ && GET_CODE (comparison_value) == REG
+ && REGNO (comparison_value) < ivs->n_regs)
+ {
+ rtx temp = comparison_value;
+ comparison_code = swap_condition (comparison_code);
+ comparison_value = iteration_var;
+ iteration_var = temp;
+ }
+
+ if (REG_IV_TYPE (ivs, REGNO (iteration_var)) == BASIC_INDUCT)
{
if (REGNO (iteration_var) >= ivs->n_regs)
abort ();
return 0;
}
+ /* If we have already counted it, skip it. */
+ if (biv_inc->same)
+ continue;
+
offset -= INTVAL (biv_inc->add_val);
}
}
unsigned_p = 1;
case GT:
compare_dir = -1;
+ break;
case NE:
compare_dir = 0;
break;
if (find_common_reg_term (temp, reg2))
initial_value = temp;
- else
+ else if (loop_invariant_p (loop, reg2))
{
/* Find what reg2 is equivalent to. Hopefully it will
either be reg1 or reg1 plus a constant. Let's ignore