return;
}
- if (iv->step == const0_rtx)
- {
- fprintf (file, "invariant ");
- print_rtl (file, iv->base);
- return;
- }
+ if (iv->step == const0_rtx
+ && !iv->first_special)
+ fprintf (file, "invariant ");
print_rtl (file, iv->base);
- fprintf (file, " + ");
- print_rtl (file, iv->step);
- fprintf (file, " * iteration");
+ if (iv->step != const0_rtx)
+ {
+ fprintf (file, " + ");
+ print_rtl (file, iv->step);
+ fprintf (file, " * iteration");
+ }
fprintf (file, " (in %s)", GET_MODE_NAME (iv->mode));
if (iv->mode != iv->extend_mode)
/* Generates a subreg to get the least significant part of EXPR (in mode
INNER_MODE) to OUTER_MODE. */
-static rtx
+rtx
lowpart_subreg (enum machine_mode outer_mode, rtx expr,
enum machine_mode inner_mode)
{
iv->base = cst;
iv->step = const0_rtx;
iv->first_special = false;
- iv->extend = NIL;
+ iv->extend = UNKNOWN;
iv->extend_mode = iv->mode;
iv->delta = const0_rtx;
iv->mult = const1_rtx;
static bool
iv_subreg (struct rtx_iv *iv, enum machine_mode mode)
{
+ /* If iv is invariant, just calculate the new value. */
+ if (iv->step == const0_rtx
+ && !iv->first_special)
+ {
+ rtx val = get_iv_value (iv, const0_rtx);
+ val = lowpart_subreg (mode, val, iv->extend_mode);
+
+ iv->base = val;
+ iv->extend = UNKNOWN;
+ iv->mode = iv->extend_mode = mode;
+ iv->delta = const0_rtx;
+ iv->mult = const1_rtx;
+ return true;
+ }
+
if (iv->extend_mode == mode)
return true;
if (GET_MODE_BITSIZE (mode) > GET_MODE_BITSIZE (iv->mode))
return false;
- iv->extend = NIL;
+ iv->extend = UNKNOWN;
iv->mode = mode;
iv->base = simplify_gen_binary (PLUS, iv->extend_mode, iv->delta,
static bool
iv_extend (struct rtx_iv *iv, enum rtx_code extend, enum machine_mode mode)
{
+ /* If iv is invariant, just calculate the new value. */
+ if (iv->step == const0_rtx
+ && !iv->first_special)
+ {
+ rtx val = get_iv_value (iv, const0_rtx);
+ val = simplify_gen_unary (extend, mode, val, iv->extend_mode);
+
+ iv->base = val;
+ iv->extend = UNKNOWN;
+ iv->mode = iv->extend_mode = mode;
+ iv->delta = const0_rtx;
+ iv->mult = const1_rtx;
+ return true;
+ }
+
if (mode != iv->extend_mode)
return false;
- if (iv->extend != NIL
+ if (iv->extend != UNKNOWN
&& iv->extend != extend)
return false;
static bool
iv_neg (struct rtx_iv *iv)
{
- if (iv->extend == NIL)
+ if (iv->extend == UNKNOWN)
{
iv->base = simplify_gen_unary (NEG, iv->extend_mode,
iv->base, iv->extend_mode);
rtx arg;
/* Extend the constant to extend_mode of the other operand if necessary. */
- if (iv0->extend == NIL
+ if (iv0->extend == UNKNOWN
&& iv0->mode == iv0->extend_mode
&& iv0->step == const0_rtx
&& GET_MODE_SIZE (iv0->extend_mode) < GET_MODE_SIZE (iv1->extend_mode))
iv0->base = simplify_gen_unary (ZERO_EXTEND, iv0->extend_mode,
iv0->base, iv0->mode);
}
- if (iv1->extend == NIL
+ if (iv1->extend == UNKNOWN
&& iv1->mode == iv1->extend_mode
&& iv1->step == const0_rtx
&& GET_MODE_SIZE (iv1->extend_mode) < GET_MODE_SIZE (iv0->extend_mode))
if (mode != iv1->extend_mode)
return false;
- if (iv0->extend == NIL && iv1->extend == NIL)
+ if (iv0->extend == UNKNOWN && iv1->extend == UNKNOWN)
{
if (iv0->mode != iv1->mode)
return false;
}
/* Handle addition of constant. */
- if (iv1->extend == NIL
+ if (iv1->extend == UNKNOWN
&& iv1->mode == mode
&& iv1->step == const0_rtx)
{
return true;
}
- if (iv0->extend == NIL
+ if (iv0->extend == UNKNOWN
&& iv0->mode == mode
&& iv0->step == const0_rtx)
{
&& GET_MODE (mby) != mode)
return false;
- if (iv->extend == NIL)
+ if (iv->extend == UNKNOWN)
{
iv->base = simplify_gen_binary (MULT, mode, iv->base, mby);
iv->step = simplify_gen_binary (MULT, mode, iv->step, mby);
&& GET_MODE (mby) != mode)
return false;
- if (iv->extend == NIL)
+ if (iv->extend == UNKNOWN)
{
iv->base = simplify_gen_binary (ASHIFT, mode, iv->base, mby);
iv->step = simplify_gen_binary (ASHIFT, mode, iv->step, mby);
return false;
*inner_step = const0_rtx;
- *extend = NIL;
+ *extend = UNKNOWN;
*inner_mode = outer_mode;
*outer_step = const0_rtx;
}
*inner_step = simplify_gen_binary (PLUS, outer_mode,
*inner_step, *outer_step);
*outer_step = const0_rtx;
- *extend = NIL;
+ *extend = UNKNOWN;
}
switch (code)
case SIGN_EXTEND:
case ZERO_EXTEND:
if (GET_MODE (op0) != *inner_mode
- || *extend != NIL
+ || *extend != UNKNOWN
|| *outer_step != const0_rtx)
abort ();
return false;
if (*inner_mode != *outer_mode
- && *extend == NIL)
+ && *extend == UNKNOWN)
abort ();
if (*inner_mode == *outer_mode
- && *extend != NIL)
+ && *extend != UNKNOWN)
abort ();
if (*inner_mode == *outer_mode
return iv->base != NULL_RTX;
}
+/* Checks whether definition of register REG in INSN a basic induction
+ variable. IV analysis must have been initialized (via a call to
+ iv_analysis_loop_init) for this function to produce a result. */
+
+bool
+biv_p (rtx insn, rtx reg)
+{
+ struct rtx_iv iv;
+
+ if (!REG_P (reg))
+ return false;
+
+ if (last_def[REGNO (reg)] != insn)
+ return false;
+
+ return iv_analyze_biv (reg, &iv);
+}
+
/* Calculates value of IV at ITERATION-th iteration. */
rtx
val = lowpart_subreg (iv->mode, val, iv->extend_mode);
- if (iv->extend == NIL)
+ if (iv->extend == UNKNOWN)
return val;
val = simplify_gen_unary (iv->extend, iv->extend_mode, val, iv->mode);
simplify_using_assignment (rtx insn, rtx *expr, regset altered)
{
rtx set = single_set (insn);
- rtx lhs, rhs;
+ rtx lhs = NULL_RTX, rhs;
bool ret = false;
if (set)
else
abort ();
- simplify_using_initial_values (loop, NIL, &head);
+ simplify_using_initial_values (loop, UNKNOWN, &head);
if (head == aggr)
{
XEXP (*expr, 0) = aggr;
return;
}
- if (op != NIL)
+ if (op != UNKNOWN)
abort ();
e = loop_preheader_edge (loop);
while (1)
{
+ basic_block tmp_bb;
+
insn = BB_END (e->src);
if (any_condjump_p (insn))
{
- /* FIXME -- slightly wrong -- what if compared register
- gets altered between start of the condition and insn? */
- rtx cond = get_condition (BB_END (e->src), NULL, false);
+ rtx cond = get_condition (BB_END (e->src), NULL, false, true);
if (cond && (e->flags & EDGE_FALLTHRU))
cond = reversed_condition (cond);
}
}
- e = e->src->pred;
- if (e->pred_next
+ /* This is a bit subtle. Store away e->src in tmp_bb, since we
+ modify `e' and this can invalidate the subsequent count of
+ e->src's predecessors by looking at the wrong block. */
+ tmp_bb = e->src;
+ e = EDGE_PRED (tmp_bb, 0);
+ if (EDGE_COUNT (tmp_bb->preds) > 1
|| e->src == ENTRY_BLOCK_PTR)
break;
}
break;
case NE:
- if (iv0->extend != NIL
- && iv1->extend != NIL
+ if (iv0->extend != UNKNOWN
+ && iv1->extend != UNKNOWN
&& iv0->extend != iv1->extend)
return false;
signed_p = false;
- if (iv0->extend != NIL)
+ if (iv0->extend != UNKNOWN)
signed_p = iv0->extend == SIGN_EXTEND;
- if (iv1->extend != NIL)
+ if (iv1->extend != UNKNOWN)
signed_p = iv1->extend == SIGN_EXTEND;
break;
goto fail;
simplify_using_initial_values (loop, IOR, &desc->noloop_assumptions);
simplify_using_initial_values (loop, IOR, &desc->infinite);
- simplify_using_initial_values (loop, NIL, &desc->niter_expr);
+ simplify_using_initial_values (loop, UNKNOWN, &desc->niter_expr);
/* Rerun the simplification. Consider code (created by copying loop headers)
goto fail;
simplify_using_initial_values (loop, IOR, &desc->noloop_assumptions);
simplify_using_initial_values (loop, IOR, &desc->infinite);
- simplify_using_initial_values (loop, NIL, &desc->niter_expr);
+ simplify_using_initial_values (loop, UNKNOWN, &desc->niter_expr);
if (desc->noloop_assumptions
&& XEXP (desc->noloop_assumptions, 0) == const_true_rtx)
{
basic_block exit_bb;
rtx condition, at;
- edge ei;
+ edge ein;
exit_bb = e->src;
desc->simple_p = false;
if (!any_condjump_p (BB_END (exit_bb)))
return;
- ei = exit_bb->succ;
- if (ei == e)
- ei = ei->succ_next;
+ ein = EDGE_SUCC (exit_bb, 0);
+ if (ein == e)
+ ein = EDGE_SUCC (exit_bb, 1);
desc->out_edge = e;
- desc->in_edge = ei;
+ desc->in_edge = ein;
/* Test whether the condition is suitable. */
- if (!(condition = get_condition (BB_END (ei->src), &at, false)))
+ if (!(condition = get_condition (BB_END (ein->src), &at, false, false)))
return;
- if (ei->flags & EDGE_FALLTHRU)
+ if (ein->flags & EDGE_FALLTHRU)
{
condition = reversed_condition (condition);
if (!condition)
edge e;
struct niter_desc act;
bool any = false;
+ edge_iterator ei;
desc->simple_p = false;
body = get_loop_body (loop);
for (i = 0; i < loop->num_nodes; i++)
{
- for (e = body[i]->succ; e; e = e->succ_next)
+ FOR_EACH_EDGE (e, ei, body[i]->succs)
{
if (flow_bb_inside_loop_p (loop, e->dest))
continue;