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>
PR target/51244
......@@ -559,16 +559,35 @@ compute_outgoing_frequencies (basic_block b)
f->count = b->count - e->count;
return;
}
else
{
guess_outgoing_edge_probabilities (b);
}
}
if (single_succ_p (b))
else if (single_succ_p (b))
{
e = single_succ_edge (b);
e->probability = REG_BR_PROB_BASE;
e->count = b->count;
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)
FOR_EACH_EDGE (e, ei, b->succs)
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,
{
rtx tem;
rtx dummy_label = NULL_RTX;
rtx last;
/* 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
......@@ -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,
if_true_label);
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_true_label, prob);
}
if (if_false_label)
......
......@@ -1161,13 +1161,7 @@ sjlj_emit_function_enter (rtx dispatch_label)
emit_cmp_and_jump_insns (x, const0_rtx, NE, 0,
TYPE_MODE (integer_type_node), 0,
dispatch_label);
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));
}
dispatch_label, REG_BR_PROB_BASE / 100);
#else
expand_builtin_setjmp_setup (plus_constant (Pmode, XEXP (fc, 0),
sjlj_fc_jbuf_ofs),
......
......@@ -154,7 +154,7 @@ static rtx do_store_flag (sepops, rtx, enum machine_mode);
#ifdef PUSH_ROUNDING
static void emit_single_push_insn (enum machine_mode, rtx, tree);
#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 void write_complex_part (rtx, rtx, bool);
......@@ -1483,7 +1483,7 @@ emit_block_move_via_loop (rtx x, rtx y, rtx size,
emit_label (cmp_label);
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.
......@@ -10824,10 +10824,14 @@ do_store_flag (sepops ops, rtx target, enum machine_mode mode)
#endif
/* 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
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];
enum machine_mode index_mode = SImode;
......@@ -10849,7 +10853,8 @@ try_casesi (tree index_type, tree index_expr, tree minval, tree range,
index = expand_normal (index_expr);
if (default_label)
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. */
index = convert_to_mode (index_mode, index, 0);
}
......@@ -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.
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
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;
......@@ -10916,7 +10923,8 @@ do_tablejump (rtx index, enum machine_mode mode, rtx range, rtx table_label,
if (default_label)
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.
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,
int
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;
......@@ -10977,7 +10985,7 @@ try_tablejump (tree index_type, tree index_expr, tree minval, tree range,
TYPE_MODE (TREE_TYPE (range)),
expand_normal (range),
TYPE_UNSIGNED (TREE_TYPE (range))),
table_label, default_label);
table_label, default_label, default_probability);
return 1;
}
......
......@@ -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
to a label if the comparison is true. */
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. */
extern void emit_indirect_jump (rtx);
......@@ -485,8 +485,8 @@ extern void do_compare_rtx_and_jump (rtx, rtx, enum rtx_code, int,
enum machine_mode, rtx, rtx, rtx, int);
/* Two different ways of generating switch statements. */
extern int try_casesi (tree, tree, tree, tree, rtx, rtx, rtx);
extern int try_tablejump (tree, tree, tree, tree, rtx, rtx);
extern int try_casesi (tree, tree, tree, tree, rtx, rtx, rtx, int);
extern int try_tablejump (tree, tree, tree, tree, rtx, rtx, int);
/* Functions from alias.c */
#include "alias.h"
......
......@@ -4249,11 +4249,12 @@ prepare_operand (enum insn_code icode, rtx x, int opnum, enum machine_mode mode,
we can do the branch. */
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 mode_class mclass;
enum insn_code icode;
rtx insn;
mclass = GET_MODE_CLASS (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)
gcc_assert (icode != CODE_FOR_nothing);
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
......@@ -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.).
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
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 test;
......@@ -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,
&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)
if (oldval != cmp_reg)
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,
GET_MODE (success), 1, label);
GET_MODE (success), 1, label, 0);
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>
* 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