diff options
author | Richard Henderson <rth@redhat.com> | 2002-09-27 15:41:07 -0700 |
---|---|---|
committer | Richard Henderson <rth@gcc.gnu.org> | 2002-09-27 15:41:07 -0700 |
commit | 5d0f3df7fd16da381bf0bb583a0355ef6c103e81 (patch) | |
tree | 7e0a28e0b76a37c3b7c0624eb5479e0e6776d55c /gcc/unroll.c | |
parent | d3d09886b33d802d5803e9f74cf70c9fa36a3f98 (diff) | |
download | gcc-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.c | 124 |
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. |