struct histogram_value **);
static void insn_values_to_profile (rtx, unsigned *, struct histogram_value **);
static rtx gen_divmod_fixed_value (enum machine_mode, enum rtx_code, rtx, rtx,
- rtx, gcov_type);
-static rtx gen_mod_pow2 (enum machine_mode, enum rtx_code, rtx, rtx, rtx);
+ rtx, gcov_type, int);
+static rtx gen_mod_pow2 (enum machine_mode, enum rtx_code, rtx, rtx, rtx, int);
static rtx gen_mod_subtract (enum machine_mode, enum rtx_code, rtx, rtx, rtx,
- int);
+ int, int, int);
static bool divmod_fixed_value_transform (rtx insn);
static bool mod_pow2_value_transform (rtx);
static bool mod_subtract_transform (rtx);
}
/* Generate code for transformation 1 (with MODE and OPERATION, operands OP1
- and OP2 whose value is expected to be VALUE and result TARGET). */
+ and OP2, whose value is expected to be VALUE, result TARGET and
+ probability of taking the optimal path PROB). */
static rtx
gen_divmod_fixed_value (enum machine_mode mode, enum rtx_code operation,
- rtx target, rtx op1, rtx op2, gcov_type value)
+ rtx target, rtx op1, rtx op2, gcov_type value,
+ int prob)
{
- rtx tmp, tmp1;
+ rtx tmp, tmp1, jump;
rtx neq_label = gen_label_rtx ();
rtx end_label = gen_label_rtx ();
rtx sequence;
do_compare_rtx_and_jump (tmp, GEN_INT (value), NE, 0, mode, NULL_RTX,
NULL_RTX, neq_label);
- tmp1 = simplify_gen_binary (operation, mode, copy_rtx (op1), GEN_INT (value));
+
+ /* Add branch probability to jump we just created. */
+ jump = get_last_insn ();
+ REG_NOTES (jump) = gen_rtx_EXPR_LIST (REG_BR_PROB,
+ GEN_INT (REG_BR_PROB_BASE - prob),
+ REG_NOTES (jump));
+
+ tmp1 = simplify_gen_binary (operation, mode,
+ copy_rtx (op1), GEN_INT (value));
tmp1 = force_operand (tmp1, target);
if (tmp1 != target)
emit_move_insn (copy_rtx (target), copy_rtx (tmp1));
emit_barrier ();
emit_label (neq_label);
- tmp1 = simplify_gen_binary (operation, mode, copy_rtx (op1), copy_rtx (tmp));
+ tmp1 = simplify_gen_binary (operation, mode,
+ copy_rtx (op1), copy_rtx (tmp));
tmp1 = force_operand (tmp1, target);
if (tmp1 != target)
emit_move_insn (copy_rtx (target), copy_rtx (tmp1));
enum machine_mode mode;
gcov_type val, count, all;
edge e;
+ int prob;
set = single_set (insn);
if (!set)
fprintf (dump_file, "Div/mod by constant transformation on insn %d\n",
INSN_UID (insn));
+ /* Compute probability of taking the optimal path. */
+ prob = (count * REG_BR_PROB_BASE + all / 2) / all;
+
e = split_block (BLOCK_FOR_INSN (insn), PREV_INSN (insn));
delete_insn (insn);
insert_insn_on_edge (
- gen_divmod_fixed_value (mode, code, set_dest, op1, op2, val), e);
+ gen_divmod_fixed_value (mode, code, set_dest,
+ op1, op2, val, prob), e);
return true;
}
/* Generate code for transformation 2 (with MODE and OPERATION, operands OP1
- and OP2 and result TARGET). */
+ and OP2, result TARGET and probability of taking the optimal path PROB). */
static rtx
gen_mod_pow2 (enum machine_mode mode, enum rtx_code operation, rtx target,
- rtx op1, rtx op2)
+ rtx op1, rtx op2, int prob)
{
- rtx tmp, tmp1, tmp2, tmp3;
+ rtx tmp, tmp1, tmp2, tmp3, jump;
rtx neq_label = gen_label_rtx ();
rtx end_label = gen_label_rtx ();
rtx sequence;
0, OPTAB_WIDEN);
do_compare_rtx_and_jump (tmp2, const0_rtx, NE, 0, mode, NULL_RTX,
NULL_RTX, neq_label);
+
+ /* Add branch probability to jump we just created. */
+ jump = get_last_insn ();
+ REG_NOTES (jump) = gen_rtx_EXPR_LIST (REG_BR_PROB,
+ GEN_INT (REG_BR_PROB_BASE - prob),
+ REG_NOTES (jump));
+
tmp3 = expand_simple_binop (mode, AND, op1, tmp1, target,
0, OPTAB_WIDEN);
if (tmp3 != target)
enum machine_mode mode;
gcov_type wrong_values, count;
edge e;
- int i;
+ int i, all, prob;
set = single_set (insn);
if (!set)
fprintf (dump_file, "Mod power of 2 transformation on insn %d\n",
INSN_UID (insn));
+ /* Compute probability of taking the optimal path. */
+ all = count + wrong_values;
+ prob = (count * REG_BR_PROB_BASE + all / 2) / all;
+
e = split_block (BLOCK_FOR_INSN (insn), PREV_INSN (insn));
delete_insn (insn);
insert_insn_on_edge (
- gen_mod_pow2 (mode, code, set_dest, op1, op2), e);
+ gen_mod_pow2 (mode, code, set_dest, op1, op2, prob), e);
return true;
}
/* Generate code for transformations 3 and 4 (with MODE and OPERATION,
- operands OP1 and OP2, result TARGET and at most SUB subtractions). */
+ operands OP1 and OP2, result TARGET, at most SUB subtractions, and
+ probability of taking the optimal path(s) PROB1 and PROB2). */
static rtx
gen_mod_subtract (enum machine_mode mode, enum rtx_code operation,
- rtx target, rtx op1, rtx op2, int sub)
+ rtx target, rtx op1, rtx op2, int sub, int prob1, int prob2)
{
- rtx tmp, tmp1;
+ rtx tmp, tmp1, jump;
rtx end_label = gen_label_rtx ();
rtx sequence;
int i;
emit_move_insn (target, copy_rtx (op1));
do_compare_rtx_and_jump (target, tmp, LTU, 0, mode, NULL_RTX,
NULL_RTX, end_label);
-
+
+ /* Add branch probability to jump we just created. */
+ jump = get_last_insn ();
+ REG_NOTES (jump) = gen_rtx_EXPR_LIST (REG_BR_PROB,
+ GEN_INT (prob1), REG_NOTES (jump));
for (i = 0; i < sub; i++)
{
emit_move_insn (target, tmp1);
do_compare_rtx_and_jump (target, tmp, LTU, 0, mode, NULL_RTX,
NULL_RTX, end_label);
+
+ /* Add branch probability to jump we just created. */
+ jump = get_last_insn ();
+ REG_NOTES (jump) = gen_rtx_EXPR_LIST (REG_BR_PROB,
+ GEN_INT (prob2), REG_NOTES (jump));
}
tmp1 = simplify_gen_binary (operation, mode, copy_rtx (target), copy_rtx (tmp));
enum machine_mode mode;
gcov_type wrong_values, counts[2], count, all;
edge e;
- int i;
+ int i, prob1, prob2;
set = single_set (insn);
if (!set)
fprintf (dump_file, "Mod subtract transformation on insn %d\n",
INSN_UID (insn));
+ /* Compute probability of taking the optimal path(s). */
+ prob1 = (counts[0] * REG_BR_PROB_BASE + all / 2) / all;
+ prob2 = (counts[1] * REG_BR_PROB_BASE + all / 2) / all;
+
e = split_block (BLOCK_FOR_INSN (insn), PREV_INSN (insn));
delete_insn (insn);
insert_insn_on_edge (
- gen_mod_subtract (mode, code, set_dest, op1, op2, i), e);
+ gen_mod_subtract (mode, code, set_dest,
+ op1, op2, i, prob1, prob2), e);
return true;
}