This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[PATCH] Fix PR optimization/15633
- From: Pat Haugen <pthaugen at us dot ibm dot com>
- To: gcc-patches at gcc dot gnu dot org
- Date: Mon, 24 May 2004 16:11:54 -0500
- Subject: [PATCH] Fix PR optimization/15633
The following fixes a problem where profile counters aren't propagated when
new control flow is added by the value profile transformation. This can
result in bad optimization decisions such as spilling in a hot loop.
Bootstrapped/regtested on PowerPC.
OK for mainline?
-Pat
2004-05-24 Pat Haugen <pthaugen@us.ibm.com>
PR optimization/15633
* value-prof.c (divmod_fixed_value_transform, mod_pow2_value_transform,
mod_subtract_transform): Compute probability of taking optimal path
and pass along to gen_ routine.
(gen_divmod_fixed_value, gen_mod_pow2, gen_mod_subtract): Add new
probability parameter(s). Add probability to newly created jump(s).
Index: gcc/value-prof.c
===================================================================
RCS file: /cvsroot/gcc/gcc/gcc/value-prof.c,v
retrieving revision 1.11
diff -c -3 -p -r1.11 value-prof.c
*** gcc/value-prof.c 15 May 2004 09:39:29 -0000 1.11
--- gcc/value-prof.c 24 May 2004 19:47:11 -0000
*************** static void insn_divmod_values_to_profil
*** 56,65 ****
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);
static rtx gen_mod_subtract (enum machine_mode, enum rtx_code, rtx, rtx, rtx,
! int);
static bool divmod_fixed_value_transform (rtx insn);
static bool mod_pow2_value_transform (rtx);
static bool mod_subtract_transform (rtx);
--- 56,65 ----
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, 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);
static bool divmod_fixed_value_transform (rtx insn);
static bool mod_pow2_value_transform (rtx);
static bool mod_subtract_transform (rtx);
*************** rtl_value_profile_transformations (void)
*** 365,376 ****
}
/* Generate code for transformation 1 (with MODE and OPERATION, operands OP1
! and OP2 whose value is expected to be VALUE and result TARGET). */
static rtx
gen_divmod_fixed_value (enum machine_mode mode, enum rtx_code operation,
! rtx target, rtx op1, rtx op2, gcov_type value)
{
! rtx tmp, tmp1;
rtx neq_label = gen_label_rtx ();
rtx end_label = gen_label_rtx ();
rtx sequence;
--- 365,378 ----
}
/* Generate code for transformation 1 (with MODE and OPERATION, operands OP1
! 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,
! int prob)
{
! rtx tmp, tmp1, jump;
rtx neq_label = gen_label_rtx ();
rtx end_label = gen_label_rtx ();
rtx sequence;
*************** gen_divmod_fixed_value (enum machine_mod
*** 387,392 ****
--- 389,401 ----
do_compare_rtx_and_jump (tmp, GEN_INT (value), 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));
+
tmp1 = simplify_gen_binary (operation, mode, copy_rtx (op1), GEN_INT (value));
tmp1 = force_operand (tmp1, target);
if (tmp1 != target)
*************** divmod_fixed_value_transform (rtx insn)
*** 418,423 ****
--- 427,433 ----
enum machine_mode mode;
gcov_type val, count, all;
edge e;
+ int prob;
set = single_set (insn);
if (!set)
*************** divmod_fixed_value_transform (rtx insn)
*** 462,483 ****
fprintf (dump_file, "Div/mod by constant transformation on insn %d\n",
INSN_UID (insn));
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);
return true;
}
/* Generate code for transformation 2 (with MODE and OPERATION, operands OP1
! and OP2 and result TARGET). */
static rtx
gen_mod_pow2 (enum machine_mode mode, enum rtx_code operation, rtx target,
! rtx op1, rtx op2)
{
! rtx tmp, tmp1, tmp2, tmp3;
rtx neq_label = gen_label_rtx ();
rtx end_label = gen_label_rtx ();
rtx sequence;
--- 472,497 ----
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, prob),
! e);
return true;
}
/* Generate code for transformation 2 (with MODE and OPERATION, operands OP1
! 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, int prob)
{
! rtx tmp, tmp1, tmp2, tmp3, jump;
rtx neq_label = gen_label_rtx ();
rtx end_label = gen_label_rtx ();
rtx sequence;
*************** gen_mod_pow2 (enum machine_mode mode, en
*** 498,503 ****
--- 512,524 ----
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)
*************** mod_pow2_value_transform (rtx insn)
*** 528,534 ****
enum machine_mode mode;
gcov_type wrong_values, count;
edge e;
! int i;
set = single_set (insn);
if (!set)
--- 549,555 ----
enum machine_mode mode;
gcov_type wrong_values, count;
edge e;
! int i, all, prob;
set = single_set (insn);
if (!set)
*************** mod_pow2_value_transform (rtx insn)
*** 578,599 ****
fprintf (dump_file, "Mod power of 2 transformation on insn %d\n",
INSN_UID (insn));
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);
return true;
}
/* Generate code for transformations 3 and 4 (with MODE and OPERATION,
! operands OP1 and OP2, result TARGET and at most SUB subtractions). */
static rtx
gen_mod_subtract (enum machine_mode mode, enum rtx_code operation,
! rtx target, rtx op1, rtx op2, int sub)
{
! rtx tmp, tmp1;
rtx end_label = gen_label_rtx ();
rtx sequence;
int i;
--- 599,626 ----
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, prob), e);
return true;
}
/* Generate code for transformations 3 and 4 (with MODE and OPERATION,
! 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, int prob1,
! int prob2)
{
! rtx tmp, tmp1, jump;
rtx end_label = gen_label_rtx ();
rtx sequence;
int i;
*************** gen_mod_subtract (enum machine_mode mode
*** 611,616 ****
--- 638,650 ----
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++)
*************** gen_mod_subtract (enum machine_mode mode
*** 621,626 ****
--- 655,667 ----
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));
*************** mod_subtract_transform (rtx insn)
*** 645,651 ****
enum machine_mode mode;
gcov_type wrong_values, counts[2], count, all;
edge e;
! int i;
set = single_set (insn);
if (!set)
--- 686,692 ----
enum machine_mode mode;
gcov_type wrong_values, counts[2], count, all;
edge e;
! int i, prob1, prob2;
set = single_set (insn);
if (!set)
*************** mod_subtract_transform (rtx insn)
*** 704,714 ****
fprintf (dump_file, "Mod subtract transformation on insn %d\n",
INSN_UID (insn));
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);
return true;
}
--- 745,760 ----
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, prob1, prob2),
! e);
return true;
}