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
This commit is contained in:
parent
d3d09886b3
commit
5d0f3df7fd
2 changed files with 86 additions and 44 deletions
|
@ -1,3 +1,9 @@
|
|||
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
|
||||
|
|
124
gcc/unroll.c
124
gcc/unroll.c
|
@ -193,6 +193,9 @@ static int *splittable_regs_updates;
|
|||
|
||||
/* 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 rtx calculate_giv_inc PARAMS ((rtx, rtx, unsigned int));
|
||||
static rtx initial_reg_note_copy PARAMS ((rtx, struct inline_remap *));
|
||||
|
@ -843,7 +846,7 @@ unroll_loop (loop, insn_count, strength_reduce_p)
|
|||
&initial_value, &final_value, &increment,
|
||||
&mode))
|
||||
{
|
||||
rtx diff;
|
||||
rtx diff, insn;
|
||||
rtx *labels;
|
||||
int abs_inc, neg_inc;
|
||||
enum rtx_code cc = loop_info->comparison_code;
|
||||
|
@ -875,26 +878,20 @@ unroll_loop (loop, insn_count, strength_reduce_p)
|
|||
|
||||
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
|
||||
to convert it into general operand, so compute the real value. */
|
||||
|
||||
if (GET_CODE (final_value) == PLUS)
|
||||
{
|
||||
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);
|
||||
}
|
||||
final_value = force_operand (final_value, NULL_RTX);
|
||||
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.
|
||||
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.
|
||||
For such loops the real final value is the first time the
|
||||
|
@ -907,18 +904,18 @@ unroll_loop (loop, insn_count, strength_reduce_p)
|
|||
so we can pretend that the overflow value is 0/~0. */
|
||||
|
||||
if (cc == NE || less_p != neg_inc)
|
||||
diff = expand_simple_binop (mode, MINUS, final_value,
|
||||
copy_rtx (initial_value), NULL_RTX, 0,
|
||||
OPTAB_LIB_WIDEN);
|
||||
diff = simplify_gen_binary (MINUS, mode, final_value,
|
||||
initial_value);
|
||||
else
|
||||
diff = expand_simple_unop (mode, neg_inc ? NOT : NEG,
|
||||
copy_rtx (initial_value), NULL_RTX, 0);
|
||||
diff = simplify_gen_unary (neg_inc ? NOT : NEG, mode,
|
||||
initial_value, mode);
|
||||
diff = force_operand (diff, NULL_RTX);
|
||||
|
||||
/* Now calculate (diff % (unroll * abs (increment))) by using an
|
||||
and instruction. */
|
||||
diff = expand_simple_binop (GET_MODE (diff), AND, diff,
|
||||
GEN_INT (unroll_number * abs_inc - 1),
|
||||
NULL_RTX, 0, OPTAB_LIB_WIDEN);
|
||||
diff = simplify_gen_binary (AND, mode, diff,
|
||||
GEN_INT (unroll_number*abs_inc - 1));
|
||||
diff = force_operand (diff, NULL_RTX);
|
||||
|
||||
/* Now emit a sequence of branches to jump to the proper precond
|
||||
loop entry point. */
|
||||
|
@ -936,18 +933,22 @@ unroll_loop (loop, insn_count, strength_reduce_p)
|
|||
if (cc != NE)
|
||||
{
|
||||
rtx incremented_initval;
|
||||
incremented_initval = expand_simple_binop (mode, PLUS,
|
||||
initial_value,
|
||||
increment,
|
||||
NULL_RTX, 0,
|
||||
OPTAB_LIB_WIDEN);
|
||||
emit_cmp_and_jump_insns (incremented_initval, final_value,
|
||||
less_p ? GE : LE, NULL_RTX,
|
||||
mode, unsigned_p, labels[1]);
|
||||
predict_insn_def (get_last_insn (), PRED_LOOP_CONDITION,
|
||||
TAKEN);
|
||||
JUMP_LABEL (get_last_insn ()) = labels[1];
|
||||
LABEL_NUSES (labels[1])++;
|
||||
enum rtx_code cmp_code;
|
||||
|
||||
incremented_initval
|
||||
= simplify_gen_binary (PLUS, mode, initial_value, increment);
|
||||
incremented_initval
|
||||
= force_operand (incremented_initval, NULL_RTX);
|
||||
|
||||
cmp_code = (less_p
|
||||
? (unsigned_p ? GEU : GE)
|
||||
: (unsigned_p ? LEU : LE));
|
||||
|
||||
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
|
||||
|
@ -986,12 +987,12 @@ unroll_loop (loop, insn_count, strength_reduce_p)
|
|||
cmp_code = LE;
|
||||
}
|
||||
|
||||
emit_cmp_and_jump_insns (diff, GEN_INT (abs_inc * cmp_const),
|
||||
cmp_code, NULL_RTX, mode, 0, labels[i]);
|
||||
JUMP_LABEL (get_last_insn ()) = labels[i];
|
||||
LABEL_NUSES (labels[i])++;
|
||||
predict_insn (get_last_insn (), PRED_LOOP_PRECONDITIONING,
|
||||
REG_BR_PROB_BASE / (unroll_number - i));
|
||||
insn = simplify_cmp_and_jump_insns (cmp_code, mode, diff,
|
||||
GEN_INT (abs_inc*cmp_const),
|
||||
labels[i]);
|
||||
if (insn)
|
||||
predict_insn (insn, PRED_LOOP_PRECONDITIONING,
|
||||
REG_BR_PROB_BASE / (unroll_number - i));
|
||||
}
|
||||
|
||||
/* If the increment is greater than one, then we need another branch,
|
||||
|
@ -1019,10 +1020,8 @@ unroll_loop (loop, insn_count, strength_reduce_p)
|
|||
cmp_code = GE;
|
||||
}
|
||||
|
||||
emit_cmp_and_jump_insns (diff, GEN_INT (cmp_const), cmp_code,
|
||||
NULL_RTX, mode, 0, labels[0]);
|
||||
JUMP_LABEL (get_last_insn ()) = labels[0];
|
||||
LABEL_NUSES (labels[0])++;
|
||||
simplify_cmp_and_jump_insns (cmp_code, mode, diff,
|
||||
GEN_INT (cmp_const), labels[0]);
|
||||
}
|
||||
|
||||
sequence = get_insns ();
|
||||
|
@ -1324,6 +1323,43 @@ unroll_loop (loop, insn_count, strength_reduce_p)
|
|||
free (map->reg_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
|
||||
so that the unrolled copies of the loop body don't need exit tests.
|
||||
|
|
Loading…
Add table
Reference in a new issue