Commit 5d0f3df7 by Richard Henderson Committed by Richard Henderson

unroll.c (simplify_cmp_and_jump_insns): New.

	* unroll.c (simplify_cmp_and_jump_insns): New.
	(unroll_loop): Use it.  Use simplify_gen_foo+force_operand
	instead of expand_simple_foo.

From-SVN: r57596
parent d3d09886
2002-09-27 Richard Henderson <rth@redhat.com> 2002-09-27 Richard Henderson <rth@redhat.com>
* unroll.c (simplify_cmp_and_jump_insns): New.
(unroll_loop): Use it. Use simplify_gen_foo+force_operand
instead of expand_simple_foo.
2002-09-27 Richard Henderson <rth@redhat.com>
PR optimization/7520 PR optimization/7520
* cfganal.c (flow_active_insn_p): New. * cfganal.c (flow_active_insn_p): New.
(forwarder_block_p): Use it. (forwarder_block_p): Use it.
......
...@@ -193,6 +193,9 @@ static int *splittable_regs_updates; ...@@ -193,6 +193,9 @@ static int *splittable_regs_updates;
/* Forward declarations. */ /* Forward declarations. */
static rtx simplify_cmp_and_jump_insns PARAMS ((enum rtx_code,
enum machine_mode,
rtx, rtx, rtx));
static void init_reg_map PARAMS ((struct inline_remap *, int)); static void init_reg_map PARAMS ((struct inline_remap *, int));
static rtx calculate_giv_inc PARAMS ((rtx, rtx, unsigned int)); static rtx calculate_giv_inc PARAMS ((rtx, rtx, unsigned int));
static rtx initial_reg_note_copy PARAMS ((rtx, struct inline_remap *)); static rtx initial_reg_note_copy PARAMS ((rtx, struct inline_remap *));
...@@ -843,7 +846,7 @@ unroll_loop (loop, insn_count, strength_reduce_p) ...@@ -843,7 +846,7 @@ unroll_loop (loop, insn_count, strength_reduce_p)
&initial_value, &final_value, &increment, &initial_value, &final_value, &increment,
&mode)) &mode))
{ {
rtx diff; rtx diff, insn;
rtx *labels; rtx *labels;
int abs_inc, neg_inc; int abs_inc, neg_inc;
enum rtx_code cc = loop_info->comparison_code; enum rtx_code cc = loop_info->comparison_code;
...@@ -875,26 +878,20 @@ unroll_loop (loop, insn_count, strength_reduce_p) ...@@ -875,26 +878,20 @@ unroll_loop (loop, insn_count, strength_reduce_p)
start_sequence (); start_sequence ();
/* We must copy the final and initial values here to avoid
improperly shared rtl. */
final_value = copy_rtx (final_value);
initial_value = copy_rtx (initial_value);
/* Final value may have form of (PLUS val1 const1_rtx). We need /* Final value may have form of (PLUS val1 const1_rtx). We need
to convert it into general operand, so compute the real value. */ to convert it into general operand, so compute the real value. */
if (GET_CODE (final_value) == PLUS) final_value = force_operand (final_value, NULL_RTX);
{
final_value = expand_simple_binop (mode, PLUS,
copy_rtx (XEXP (final_value, 0)),
copy_rtx (XEXP (final_value, 1)),
NULL_RTX, 0, OPTAB_LIB_WIDEN);
}
if (!nonmemory_operand (final_value, VOIDmode)) if (!nonmemory_operand (final_value, VOIDmode))
final_value = force_reg (mode, copy_rtx (final_value)); final_value = force_reg (mode, final_value);
/* Calculate the difference between the final and initial values. /* Calculate the difference between the final and initial values.
Final value may be a (plus (reg x) (const_int 1)) rtx. Final value may be a (plus (reg x) (const_int 1)) rtx.
Let the following cse pass simplify this if initial value is
a constant.
We must copy the final and initial values here to avoid
improperly shared rtl.
We have to deal with for (i = 0; --i < 6;) type loops. We have to deal with for (i = 0; --i < 6;) type loops.
For such loops the real final value is the first time the For such loops the real final value is the first time the
...@@ -907,18 +904,18 @@ unroll_loop (loop, insn_count, strength_reduce_p) ...@@ -907,18 +904,18 @@ unroll_loop (loop, insn_count, strength_reduce_p)
so we can pretend that the overflow value is 0/~0. */ so we can pretend that the overflow value is 0/~0. */
if (cc == NE || less_p != neg_inc) if (cc == NE || less_p != neg_inc)
diff = expand_simple_binop (mode, MINUS, final_value, diff = simplify_gen_binary (MINUS, mode, final_value,
copy_rtx (initial_value), NULL_RTX, 0, initial_value);
OPTAB_LIB_WIDEN);
else else
diff = expand_simple_unop (mode, neg_inc ? NOT : NEG, diff = simplify_gen_unary (neg_inc ? NOT : NEG, mode,
copy_rtx (initial_value), NULL_RTX, 0); initial_value, mode);
diff = force_operand (diff, NULL_RTX);
/* Now calculate (diff % (unroll * abs (increment))) by using an /* Now calculate (diff % (unroll * abs (increment))) by using an
and instruction. */ and instruction. */
diff = expand_simple_binop (GET_MODE (diff), AND, diff, diff = simplify_gen_binary (AND, mode, diff,
GEN_INT (unroll_number * abs_inc - 1), GEN_INT (unroll_number*abs_inc - 1));
NULL_RTX, 0, OPTAB_LIB_WIDEN); diff = force_operand (diff, NULL_RTX);
/* Now emit a sequence of branches to jump to the proper precond /* Now emit a sequence of branches to jump to the proper precond
loop entry point. */ loop entry point. */
...@@ -936,18 +933,22 @@ unroll_loop (loop, insn_count, strength_reduce_p) ...@@ -936,18 +933,22 @@ unroll_loop (loop, insn_count, strength_reduce_p)
if (cc != NE) if (cc != NE)
{ {
rtx incremented_initval; rtx incremented_initval;
incremented_initval = expand_simple_binop (mode, PLUS, enum rtx_code cmp_code;
initial_value,
increment, incremented_initval
NULL_RTX, 0, = simplify_gen_binary (PLUS, mode, initial_value, increment);
OPTAB_LIB_WIDEN); incremented_initval
emit_cmp_and_jump_insns (incremented_initval, final_value, = force_operand (incremented_initval, NULL_RTX);
less_p ? GE : LE, NULL_RTX,
mode, unsigned_p, labels[1]); cmp_code = (less_p
predict_insn_def (get_last_insn (), PRED_LOOP_CONDITION, ? (unsigned_p ? GEU : GE)
TAKEN); : (unsigned_p ? LEU : LE));
JUMP_LABEL (get_last_insn ()) = labels[1];
LABEL_NUSES (labels[1])++; insn = simplify_cmp_and_jump_insns (cmp_code, mode,
incremented_initval,
final_value, labels[1]);
if (insn)
predict_insn_def (insn, PRED_LOOP_CONDITION, TAKEN);
} }
/* Assuming the unroll_number is 4, and the increment is 2, then /* Assuming the unroll_number is 4, and the increment is 2, then
...@@ -986,12 +987,12 @@ unroll_loop (loop, insn_count, strength_reduce_p) ...@@ -986,12 +987,12 @@ unroll_loop (loop, insn_count, strength_reduce_p)
cmp_code = LE; cmp_code = LE;
} }
emit_cmp_and_jump_insns (diff, GEN_INT (abs_inc * cmp_const), insn = simplify_cmp_and_jump_insns (cmp_code, mode, diff,
cmp_code, NULL_RTX, mode, 0, labels[i]); GEN_INT (abs_inc*cmp_const),
JUMP_LABEL (get_last_insn ()) = labels[i]; labels[i]);
LABEL_NUSES (labels[i])++; if (insn)
predict_insn (get_last_insn (), PRED_LOOP_PRECONDITIONING, predict_insn (insn, PRED_LOOP_PRECONDITIONING,
REG_BR_PROB_BASE / (unroll_number - i)); REG_BR_PROB_BASE / (unroll_number - i));
} }
/* If the increment is greater than one, then we need another branch, /* If the increment is greater than one, then we need another branch,
...@@ -1019,10 +1020,8 @@ unroll_loop (loop, insn_count, strength_reduce_p) ...@@ -1019,10 +1020,8 @@ unroll_loop (loop, insn_count, strength_reduce_p)
cmp_code = GE; cmp_code = GE;
} }
emit_cmp_and_jump_insns (diff, GEN_INT (cmp_const), cmp_code, simplify_cmp_and_jump_insns (cmp_code, mode, diff,
NULL_RTX, mode, 0, labels[0]); GEN_INT (cmp_const), labels[0]);
JUMP_LABEL (get_last_insn ()) = labels[0];
LABEL_NUSES (labels[0])++;
} }
sequence = get_insns (); sequence = get_insns ();
...@@ -1324,6 +1323,43 @@ unroll_loop (loop, insn_count, strength_reduce_p) ...@@ -1324,6 +1323,43 @@ unroll_loop (loop, insn_count, strength_reduce_p)
free (map->reg_map); free (map->reg_map);
free (map); free (map);
} }
/* A helper function for unroll_loop. Emit a compare and branch to
satisfy (CMP OP1 OP2), but pass this through the simplifier first.
If the branch turned out to be conditional, return it, otherwise
return NULL. */
static rtx
simplify_cmp_and_jump_insns (code, mode, op0, op1, label)
enum rtx_code code;
enum machine_mode mode;
rtx op0, op1, label;
{
rtx t, insn;
t = simplify_relational_operation (code, mode, op0, op1);
if (!t)
{
enum rtx_code scode = signed_condition (code);
emit_cmp_and_jump_insns (op0, op1, scode, NULL_RTX, mode,
code != scode, label);
insn = get_last_insn ();
JUMP_LABEL (insn) = label;
LABEL_NUSES (label) += 1;
return insn;
}
else if (t == const_true_rtx)
{
insn = emit_jump_insn (gen_jump (label));
emit_barrier ();
JUMP_LABEL (insn) = label;
LABEL_NUSES (label) += 1;
}
return NULL_RTX;
}
/* Return true if the loop can be safely, and profitably, preconditioned /* Return true if the loop can be safely, and profitably, preconditioned
so that the unrolled copies of the loop body don't need exit tests. so that the unrolled copies of the loop body don't need exit tests.
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment