aboutsummaryrefslogtreecommitdiff
path: root/gcc/unroll.c
diff options
context:
space:
mode:
authorRichard Henderson <rth@redhat.com>2002-09-27 15:41:07 -0700
committerRichard Henderson <rth@gcc.gnu.org>2002-09-27 15:41:07 -0700
commit5d0f3df7fd16da381bf0bb583a0355ef6c103e81 (patch)
tree7e0a28e0b76a37c3b7c0624eb5479e0e6776d55c /gcc/unroll.c
parentd3d09886b33d802d5803e9f74cf70c9fa36a3f98 (diff)
downloadgcc-5d0f3df7fd16da381bf0bb583a0355ef6c103e81.zip
gcc-5d0f3df7fd16da381bf0bb583a0355ef6c103e81.tar.gz
gcc-5d0f3df7fd16da381bf0bb583a0355ef6c103e81.tar.bz2
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
Diffstat (limited to 'gcc/unroll.c')
-rw-r--r--gcc/unroll.c124
1 files changed, 80 insertions, 44 deletions
diff --git a/gcc/unroll.c b/gcc/unroll.c
index c1c0059..126b5868 100644
--- a/gcc/unroll.c
+++ b/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.