Commit a4da41e1 by Easwaran Raman Committed by Easwaran Raman

[multiple changes]

2012-10-15   Easwaran Raman  <eraman@google.com>

        * optabs.c (emit_cmp_and_jump_insn_1): Add a new parameter to
        specificy the probability of taking the jump.
        (emit_cmp_and_jump_insns): Likewise.
        (expand_compare_and_swap_loop): Make the jump predicted not taken.
        * dojump.c (do_compare_rtx_and_jump): Remove the code attaching
        REG_BR_PROB note and pass probability to emit_cmp_and_jump_insns.
        * cfgbuild.c (compute_outgoing_frequencies): Do not guess outgoing
        probabilities for branches with more than two successors.
        * expr.c (emit_block_move_via_loop): Predict the loop backedge loop
        to be highly taken.
        (try_casesi): Pass the probability of jumping to the default label.
        (try_tablejump): Likewise.
        (do_tablejump): Likewise.
        * expr.h (try_tablejump): Add a new parameter.
        (try_casesi): Likewise.
        (emit_cmp_and_jump_insns): Add probability as default parameter with a
        default value of -1.
        * except.c (sjlj_emit_function_enter): Pass probability to
        emit_cmp_and_jump_insns.
        * stmt.c (case_node): Add new fields PROB and SUBTREE_PROB.
        (do_jump_if_equal): Pass probability for REG_BR_PROB note.
        (add_case_node): Pass estimated probability of jumping to the case
        label.
        (emit_case_decision_tree): Pass default_prob to emit_case_nodes.
        (get_outgoing_edge_probs): New function.
        (conditional_probability): Likewise.
        (reset_out_edges_aux): Likewise.
        (compute_cases_per_edge): Likewise.
        (emit_case_dispatch_table): Update probabilities of edges coming out
        of the switch statement.
        (expand_case): Compute and propagate default edge probability to
        emit_case_dispatch_table.
        (expand_sjlj_dispatch_table): Update calls to add_case_node and
        emit_case_dispatch_table.
        (balance_case_nodes): Update subtree_prob values.
        (emit_case_nodes): Compute edge probabilities and add pass them to
        emit_cmp_and_jump_insns.

testsuite/ChangeLog:
2012-10-15   Easwaran Raman  <eraman@google.com> 
        * gcc.dg/tree-prof/switch-case-1.c: New test case.
        * gcc.dg/tree-prof/switch-case-2.c: New test case.

From-SVN: r192488
parent 07a11640
2012-10-15 Easwaran Raman <eraman@google.com>
* optabs.c (emit_cmp_and_jump_insn_1): Add a new parameter to
specificy the probability of taking the jump.
(emit_cmp_and_jump_insns): Likewise.
(expand_compare_and_swap_loop): Make the jump predicted not taken.
* dojump.c (do_compare_rtx_and_jump): Remove the code attaching
REG_BR_PROB note and pass probability to emit_cmp_and_jump_insns.
* cfgbuild.c (compute_outgoing_frequencies): Do not guess outgoing
probabilities for branches with more than two successors.
* expr.c (emit_block_move_via_loop): Predict the loop backedge loop
to be highly taken.
(try_casesi): Pass the probability of jumping to the default label.
(try_tablejump): Likewise.
(do_tablejump): Likewise.
* expr.h (try_tablejump): Add a new parameter.
(try_casesi): Likewise.
(emit_cmp_and_jump_insns): Add probability as default parameter with a
default value of -1.
* except.c (sjlj_emit_function_enter): Pass probability to
emit_cmp_and_jump_insns.
* stmt.c (case_node): Add new fields PROB and SUBTREE_PROB.
(do_jump_if_equal): Pass probability for REG_BR_PROB note.
(add_case_node): Pass estimated probability of jumping to the case
label.
(emit_case_decision_tree): Pass default_prob to emit_case_nodes.
(get_outgoing_edge_probs): New function.
(conditional_probability): Likewise.
(reset_out_edges_aux): Likewise.
(compute_cases_per_edge): Likewise.
(emit_case_dispatch_table): Update probabilities of edges coming out
of the switch statement.
(expand_case): Compute and propagate default edge probability to
emit_case_dispatch_table.
(expand_sjlj_dispatch_table): Update calls to add_case_node and
emit_case_dispatch_table.
(balance_case_nodes): Update subtree_prob values.
(emit_case_nodes): Compute edge probabilities and add pass them to
emit_cmp_and_jump_insns.
2012-10-15 Oleg Endo <olegendo@gcc.gnu.org> 2012-10-15 Oleg Endo <olegendo@gcc.gnu.org>
PR target/51244 PR target/51244
...@@ -559,16 +559,35 @@ compute_outgoing_frequencies (basic_block b) ...@@ -559,16 +559,35 @@ compute_outgoing_frequencies (basic_block b)
f->count = b->count - e->count; f->count = b->count - e->count;
return; return;
} }
else
{
guess_outgoing_edge_probabilities (b);
}
} }
else if (single_succ_p (b))
if (single_succ_p (b))
{ {
e = single_succ_edge (b); e = single_succ_edge (b);
e->probability = REG_BR_PROB_BASE; e->probability = REG_BR_PROB_BASE;
e->count = b->count; e->count = b->count;
return; return;
} }
guess_outgoing_edge_probabilities (b); else
{
/* We rely on BBs with more than two successors to have sane probabilities
and do not guess them here. For BBs terminated by switch statements
expanded to jump-table jump, we have done the right thing during
expansion. For EH edges, we still guess the probabilities here. */
bool complex_edge = false;
FOR_EACH_EDGE (e, ei, b->succs)
if (e->flags & EDGE_COMPLEX)
{
complex_edge = true;
break;
}
if (complex_edge)
guess_outgoing_edge_probabilities (b);
}
if (b->count) if (b->count)
FOR_EACH_EDGE (e, ei, b->succs) FOR_EACH_EDGE (e, ei, b->succs)
e->count = ((b->count * e->probability + REG_BR_PROB_BASE / 2) e->count = ((b->count * e->probability + REG_BR_PROB_BASE / 2)
......
...@@ -886,7 +886,6 @@ do_compare_rtx_and_jump (rtx op0, rtx op1, enum rtx_code code, int unsignedp, ...@@ -886,7 +886,6 @@ do_compare_rtx_and_jump (rtx op0, rtx op1, enum rtx_code code, int unsignedp,
{ {
rtx tem; rtx tem;
rtx dummy_label = NULL_RTX; rtx dummy_label = NULL_RTX;
rtx last;
/* Reverse the comparison if that is safe and we want to jump if it is /* Reverse the comparison if that is safe and we want to jump if it is
false. Also convert to the reverse comparison if the target can false. Also convert to the reverse comparison if the target can
...@@ -1069,25 +1068,8 @@ do_compare_rtx_and_jump (rtx op0, rtx op1, enum rtx_code code, int unsignedp, ...@@ -1069,25 +1068,8 @@ do_compare_rtx_and_jump (rtx op0, rtx op1, enum rtx_code code, int unsignedp,
} }
} }
last = get_last_insn ();
emit_cmp_and_jump_insns (op0, op1, code, size, mode, unsignedp, emit_cmp_and_jump_insns (op0, op1, code, size, mode, unsignedp,
if_true_label); if_true_label, prob);
if (prob != -1 && profile_status != PROFILE_ABSENT)
{
for (last = NEXT_INSN (last);
last && NEXT_INSN (last);
last = NEXT_INSN (last))
if (JUMP_P (last))
break;
if (last
&& JUMP_P (last)
&& ! NEXT_INSN (last)
&& any_condjump_p (last))
{
gcc_assert (!find_reg_note (last, REG_BR_PROB, 0));
add_reg_note (last, REG_BR_PROB, GEN_INT (prob));
}
}
} }
if (if_false_label) if (if_false_label)
......
...@@ -1161,13 +1161,7 @@ sjlj_emit_function_enter (rtx dispatch_label) ...@@ -1161,13 +1161,7 @@ sjlj_emit_function_enter (rtx dispatch_label)
emit_cmp_and_jump_insns (x, const0_rtx, NE, 0, emit_cmp_and_jump_insns (x, const0_rtx, NE, 0,
TYPE_MODE (integer_type_node), 0, TYPE_MODE (integer_type_node), 0,
dispatch_label); dispatch_label, REG_BR_PROB_BASE / 100);
last = get_last_insn ();
if (JUMP_P (last) && any_condjump_p (last))
{
gcc_assert (!find_reg_note (last, REG_BR_PROB, 0));
add_reg_note (last, REG_BR_PROB, GEN_INT (REG_BR_PROB_BASE / 100));
}
#else #else
expand_builtin_setjmp_setup (plus_constant (Pmode, XEXP (fc, 0), expand_builtin_setjmp_setup (plus_constant (Pmode, XEXP (fc, 0),
sjlj_fc_jbuf_ofs), sjlj_fc_jbuf_ofs),
......
...@@ -154,7 +154,7 @@ static rtx do_store_flag (sepops, rtx, enum machine_mode); ...@@ -154,7 +154,7 @@ static rtx do_store_flag (sepops, rtx, enum machine_mode);
#ifdef PUSH_ROUNDING #ifdef PUSH_ROUNDING
static void emit_single_push_insn (enum machine_mode, rtx, tree); static void emit_single_push_insn (enum machine_mode, rtx, tree);
#endif #endif
static void do_tablejump (rtx, enum machine_mode, rtx, rtx, rtx); static void do_tablejump (rtx, enum machine_mode, rtx, rtx, rtx, int);
static rtx const_vector_from_tree (tree); static rtx const_vector_from_tree (tree);
static void write_complex_part (rtx, rtx, bool); static void write_complex_part (rtx, rtx, bool);
...@@ -1483,7 +1483,7 @@ emit_block_move_via_loop (rtx x, rtx y, rtx size, ...@@ -1483,7 +1483,7 @@ emit_block_move_via_loop (rtx x, rtx y, rtx size,
emit_label (cmp_label); emit_label (cmp_label);
emit_cmp_and_jump_insns (iter, size, LT, NULL_RTX, iter_mode, emit_cmp_and_jump_insns (iter, size, LT, NULL_RTX, iter_mode,
true, top_label); true, top_label, REG_BR_PROB_BASE * 90 / 100);
} }
/* Copy all or part of a value X into registers starting at REGNO. /* Copy all or part of a value X into registers starting at REGNO.
...@@ -10824,10 +10824,14 @@ do_store_flag (sepops ops, rtx target, enum machine_mode mode) ...@@ -10824,10 +10824,14 @@ do_store_flag (sepops ops, rtx target, enum machine_mode mode)
#endif #endif
/* Attempt to generate a casesi instruction. Returns 1 if successful, /* Attempt to generate a casesi instruction. Returns 1 if successful,
0 otherwise (i.e. if there is no casesi instruction). */ 0 otherwise (i.e. if there is no casesi instruction).
DEFAULT_PROBABILITY is the probability of jumping to the default
label. */
int int
try_casesi (tree index_type, tree index_expr, tree minval, tree range, try_casesi (tree index_type, tree index_expr, tree minval, tree range,
rtx table_label, rtx default_label, rtx fallback_label) rtx table_label, rtx default_label, rtx fallback_label,
int default_probability)
{ {
struct expand_operand ops[5]; struct expand_operand ops[5];
enum machine_mode index_mode = SImode; enum machine_mode index_mode = SImode;
...@@ -10849,7 +10853,8 @@ try_casesi (tree index_type, tree index_expr, tree minval, tree range, ...@@ -10849,7 +10853,8 @@ try_casesi (tree index_type, tree index_expr, tree minval, tree range,
index = expand_normal (index_expr); index = expand_normal (index_expr);
if (default_label) if (default_label)
emit_cmp_and_jump_insns (rangertx, index, LTU, NULL_RTX, emit_cmp_and_jump_insns (rangertx, index, LTU, NULL_RTX,
omode, 1, default_label); omode, 1, default_label,
default_probability);
/* Now we can safely truncate. */ /* Now we can safely truncate. */
index = convert_to_mode (index_mode, index, 0); index = convert_to_mode (index_mode, index, 0);
} }
...@@ -10895,11 +10900,13 @@ try_casesi (tree index_type, tree index_expr, tree minval, tree range, ...@@ -10895,11 +10900,13 @@ try_casesi (tree index_type, tree index_expr, tree minval, tree range,
TABLE_LABEL is a CODE_LABEL rtx for the table itself. TABLE_LABEL is a CODE_LABEL rtx for the table itself.
DEFAULT_LABEL is a CODE_LABEL rtx to jump to if the DEFAULT_LABEL is a CODE_LABEL rtx to jump to if the
index value is out of range. */ index value is out of range.
DEFAULT_PROBABILITY is the probability of jumping to
the default label. */
static void static void
do_tablejump (rtx index, enum machine_mode mode, rtx range, rtx table_label, do_tablejump (rtx index, enum machine_mode mode, rtx range, rtx table_label,
rtx default_label) rtx default_label, int default_probability)
{ {
rtx temp, vector; rtx temp, vector;
...@@ -10916,7 +10923,8 @@ do_tablejump (rtx index, enum machine_mode mode, rtx range, rtx table_label, ...@@ -10916,7 +10923,8 @@ do_tablejump (rtx index, enum machine_mode mode, rtx range, rtx table_label,
if (default_label) if (default_label)
emit_cmp_and_jump_insns (index, range, GTU, NULL_RTX, mode, 1, emit_cmp_and_jump_insns (index, range, GTU, NULL_RTX, mode, 1,
default_label); default_label, default_probability);
/* If index is in range, it must fit in Pmode. /* If index is in range, it must fit in Pmode.
Convert to Pmode so we can index with it. */ Convert to Pmode so we can index with it. */
...@@ -10959,7 +10967,7 @@ do_tablejump (rtx index, enum machine_mode mode, rtx range, rtx table_label, ...@@ -10959,7 +10967,7 @@ do_tablejump (rtx index, enum machine_mode mode, rtx range, rtx table_label,
int int
try_tablejump (tree index_type, tree index_expr, tree minval, tree range, try_tablejump (tree index_type, tree index_expr, tree minval, tree range,
rtx table_label, rtx default_label) rtx table_label, rtx default_label, int default_probability)
{ {
rtx index; rtx index;
...@@ -10977,7 +10985,7 @@ try_tablejump (tree index_type, tree index_expr, tree minval, tree range, ...@@ -10977,7 +10985,7 @@ try_tablejump (tree index_type, tree index_expr, tree minval, tree range,
TYPE_MODE (TREE_TYPE (range)), TYPE_MODE (TREE_TYPE (range)),
expand_normal (range), expand_normal (range),
TYPE_UNSIGNED (TREE_TYPE (range))), TYPE_UNSIGNED (TREE_TYPE (range))),
table_label, default_label); table_label, default_label, default_probability);
return 1; return 1;
} }
......
...@@ -190,7 +190,7 @@ extern int have_sub2_insn (rtx, rtx); ...@@ -190,7 +190,7 @@ extern int have_sub2_insn (rtx, rtx);
/* Emit a pair of rtl insns to compare two rtx's and to jump /* Emit a pair of rtl insns to compare two rtx's and to jump
to a label if the comparison is true. */ to a label if the comparison is true. */
extern void emit_cmp_and_jump_insns (rtx, rtx, enum rtx_code, rtx, extern void emit_cmp_and_jump_insns (rtx, rtx, enum rtx_code, rtx,
enum machine_mode, int, rtx); enum machine_mode, int, rtx, int prob=-1);
/* Generate code to indirectly jump to a location given in the rtx LOC. */ /* Generate code to indirectly jump to a location given in the rtx LOC. */
extern void emit_indirect_jump (rtx); extern void emit_indirect_jump (rtx);
...@@ -485,8 +485,8 @@ extern void do_compare_rtx_and_jump (rtx, rtx, enum rtx_code, int, ...@@ -485,8 +485,8 @@ extern void do_compare_rtx_and_jump (rtx, rtx, enum rtx_code, int,
enum machine_mode, rtx, rtx, rtx, int); enum machine_mode, rtx, rtx, rtx, int);
/* Two different ways of generating switch statements. */ /* Two different ways of generating switch statements. */
extern int try_casesi (tree, tree, tree, tree, rtx, rtx, rtx); extern int try_casesi (tree, tree, tree, tree, rtx, rtx, rtx, int);
extern int try_tablejump (tree, tree, tree, tree, rtx, rtx); extern int try_tablejump (tree, tree, tree, tree, rtx, rtx, int);
/* Functions from alias.c */ /* Functions from alias.c */
#include "alias.h" #include "alias.h"
......
...@@ -4249,11 +4249,12 @@ prepare_operand (enum insn_code icode, rtx x, int opnum, enum machine_mode mode, ...@@ -4249,11 +4249,12 @@ prepare_operand (enum insn_code icode, rtx x, int opnum, enum machine_mode mode,
we can do the branch. */ we can do the branch. */
static void static void
emit_cmp_and_jump_insn_1 (rtx test, enum machine_mode mode, rtx label) emit_cmp_and_jump_insn_1 (rtx test, enum machine_mode mode, rtx label, int prob)
{ {
enum machine_mode optab_mode; enum machine_mode optab_mode;
enum mode_class mclass; enum mode_class mclass;
enum insn_code icode; enum insn_code icode;
rtx insn;
mclass = GET_MODE_CLASS (mode); mclass = GET_MODE_CLASS (mode);
optab_mode = (mclass == MODE_CC) ? CCmode : mode; optab_mode = (mclass == MODE_CC) ? CCmode : mode;
...@@ -4261,7 +4262,17 @@ emit_cmp_and_jump_insn_1 (rtx test, enum machine_mode mode, rtx label) ...@@ -4261,7 +4262,17 @@ emit_cmp_and_jump_insn_1 (rtx test, enum machine_mode mode, rtx label)
gcc_assert (icode != CODE_FOR_nothing); gcc_assert (icode != CODE_FOR_nothing);
gcc_assert (insn_operand_matches (icode, 0, test)); gcc_assert (insn_operand_matches (icode, 0, test));
emit_jump_insn (GEN_FCN (icode) (test, XEXP (test, 0), XEXP (test, 1), label)); insn = emit_jump_insn (GEN_FCN (icode) (test, XEXP (test, 0),
XEXP (test, 1), label));
if (prob != -1
&& profile_status != PROFILE_ABSENT
&& insn
&& JUMP_P (insn)
&& any_condjump_p (insn))
{
gcc_assert (!find_reg_note (insn, REG_BR_PROB, 0));
add_reg_note (insn, REG_BR_PROB, GEN_INT (prob));
}
} }
/* Generate code to compare X with Y so that the condition codes are /* Generate code to compare X with Y so that the condition codes are
...@@ -4279,11 +4290,14 @@ emit_cmp_and_jump_insn_1 (rtx test, enum machine_mode mode, rtx label) ...@@ -4279,11 +4290,14 @@ emit_cmp_and_jump_insn_1 (rtx test, enum machine_mode mode, rtx label)
COMPARISON is the rtl operator to compare with (EQ, NE, GT, etc.). COMPARISON is the rtl operator to compare with (EQ, NE, GT, etc.).
It will be potentially converted into an unsigned variant based on It will be potentially converted into an unsigned variant based on
UNSIGNEDP to select a proper jump instruction. */ UNSIGNEDP to select a proper jump instruction.
PROB is the probability of jumping to LABEL. */
void void
emit_cmp_and_jump_insns (rtx x, rtx y, enum rtx_code comparison, rtx size, emit_cmp_and_jump_insns (rtx x, rtx y, enum rtx_code comparison, rtx size,
enum machine_mode mode, int unsignedp, rtx label) enum machine_mode mode, int unsignedp, rtx label,
int prob)
{ {
rtx op0 = x, op1 = y; rtx op0 = x, op1 = y;
rtx test; rtx test;
...@@ -4307,7 +4321,7 @@ emit_cmp_and_jump_insns (rtx x, rtx y, enum rtx_code comparison, rtx size, ...@@ -4307,7 +4321,7 @@ emit_cmp_and_jump_insns (rtx x, rtx y, enum rtx_code comparison, rtx size,
prepare_cmp_insn (op0, op1, comparison, size, unsignedp, OPTAB_LIB_WIDEN, prepare_cmp_insn (op0, op1, comparison, size, unsignedp, OPTAB_LIB_WIDEN,
&test, &mode); &test, &mode);
emit_cmp_and_jump_insn_1 (test, mode, label); emit_cmp_and_jump_insn_1 (test, mode, label, prob);
} }
...@@ -6952,9 +6966,9 @@ expand_compare_and_swap_loop (rtx mem, rtx old_reg, rtx new_reg, rtx seq) ...@@ -6952,9 +6966,9 @@ expand_compare_and_swap_loop (rtx mem, rtx old_reg, rtx new_reg, rtx seq)
if (oldval != cmp_reg) if (oldval != cmp_reg)
emit_move_insn (cmp_reg, oldval); emit_move_insn (cmp_reg, oldval);
/* ??? Mark this jump predicted not taken? */ /* Mark this jump predicted not taken. */
emit_cmp_and_jump_insns (success, const0_rtx, EQ, const0_rtx, emit_cmp_and_jump_insns (success, const0_rtx, EQ, const0_rtx,
GET_MODE (success), 1, label); GET_MODE (success), 1, label, 0);
return true; return true;
} }
......
2012-10-15 Easwaran Raman <eraman@google.com>
* gcc.dg/tree-prof/switch-case-1.c: New test case.
* gcc.dg/tree-prof/switch-case-2.c: New test case.
2012-10-16 Hans-Peter Nilsson <hp@bitrange.com> 2012-10-16 Hans-Peter Nilsson <hp@bitrange.com>
* gcc.dg/torture/stackalign/builtin-apply-2.c, * gcc.dg/torture/stackalign/builtin-apply-2.c,
......
/* { dg-options "-O2 -fdump-rtl-expand-all" } */
int g;
__attribute__((noinline)) void foo (int n)
{
switch (n)
{
case 1:
g++; break;
case 2:
g += 2; break;
case 3:
g += 1; break;
case 4:
g += 3; break;
case 5:
g += 4; break;
case 6:
g += 5; break;
case 7:
g += 6; break;
case 8:
g += 7; break;
case 9:
g += 8; break;
default:
g += 8; break;
}
}
int main ()
{
int i;
for (i = 0; i < 10000; i++)
foo ((i * i) % 5);
return 0;
}
/* { dg-final-use { scan-rtl-dump-times ";; basic block\[^\\n\]*count 4000" 2 "expand"} } */
/* { dg-final-use { scan-rtl-dump-times ";; basic block\[^\\n\]*count 2000" 1 "expand"} } */
/* { dg-final-use { cleanup-rtl-dump "expand" } } */
/* { dg-options "-O2 -fdump-rtl-expand-all" } */
int g;
__attribute__((noinline)) void foo (int n)
{
switch (n)
{
case 99:
g += 2; break;
case 1:
g++; break;
case 100:
g += 1; break;
case 4:
g += 3; break;
case 5:
g += 4; break;
case 6:
g += 5; break;
case 7:
g += 6; break;
case 8:
g += 7; break;
case 9:
g += 8; break;
default:
g += 8; break;
}
}
int main ()
{
int i;
for (i = 0; i < 10000; i++)
foo ((i * i) % 5);
return 0;
}
/* { dg-final-use { scan-rtl-dump-times ";; basic block\[^\\n\]*count 4000" 2 "expand"} } */
/* { dg-final-use { scan-rtl-dump-times ";; basic block\[^\\n\]*count 2000" 1 "expand"} } */
/* { dg-final-use { cleanup-rtl-dump "expand" } } */
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment