[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
This commit is contained in:
parent
07a1164095
commit
a4da41e127
11 changed files with 509 additions and 134 deletions
|
@ -1,3 +1,43 @@
|
|||
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)
|
||||
|
|
20
gcc/dojump.c
20
gcc/dojump.c
|
@ -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),
|
||||
|
|
28
gcc/expr.c
28
gcc/expr.c
|
@ -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"
|
||||
|
|
28
gcc/optabs.c
28
gcc/optabs.c
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
404
gcc/stmt.c
404
gcc/stmt.c
|
@ -94,11 +94,15 @@ struct case_node
|
|||
tree low; /* Lowest index value for this label */
|
||||
tree high; /* Highest index value for this label */
|
||||
tree code_label; /* Label to jump to when node matches */
|
||||
int prob; /* Probability of taking this case. */
|
||||
/* Probability of reaching subtree rooted at this node */
|
||||
int subtree_prob;
|
||||
};
|
||||
|
||||
typedef struct case_node case_node;
|
||||
typedef struct case_node *case_node_ptr;
|
||||
|
||||
extern basic_block label_to_block_fn (struct function *, tree);
|
||||
|
||||
static int n_occurrences (int, const char *);
|
||||
static bool tree_conflicts_with_clobbers_p (tree, HARD_REG_SET *);
|
||||
|
@ -112,7 +116,7 @@ static void balance_case_nodes (case_node_ptr *, case_node_ptr);
|
|||
static int node_has_low_bound (case_node_ptr, tree);
|
||||
static int node_has_high_bound (case_node_ptr, tree);
|
||||
static int node_is_bounded (case_node_ptr, tree);
|
||||
static void emit_case_nodes (rtx, case_node_ptr, rtx, tree);
|
||||
static void emit_case_nodes (rtx, case_node_ptr, rtx, int, tree);
|
||||
|
||||
/* Return the rtx-label that corresponds to a LABEL_DECL,
|
||||
creating it if necessary. */
|
||||
|
@ -1648,23 +1652,29 @@ expand_stack_restore (tree var)
|
|||
fixup_args_size_notes (prev, get_last_insn (), 0);
|
||||
}
|
||||
|
||||
/* Generate code to jump to LABEL if OP0 and OP1 are equal in mode MODE. */
|
||||
/* Generate code to jump to LABEL if OP0 and OP1 are equal in mode MODE. PROB
|
||||
is the probability of jumping to LABEL. */
|
||||
static void
|
||||
do_jump_if_equal (enum machine_mode mode, rtx op0, rtx op1, rtx label,
|
||||
int unsignedp)
|
||||
int unsignedp, int prob)
|
||||
{
|
||||
gcc_assert (prob <= REG_BR_PROB_BASE);
|
||||
do_compare_rtx_and_jump (op0, op1, EQ, unsignedp, mode,
|
||||
NULL_RTX, NULL_RTX, label, -1);
|
||||
NULL_RTX, NULL_RTX, label, prob);
|
||||
}
|
||||
|
||||
/* Do the insertion of a case label into case_list. The labels are
|
||||
fed to us in descending order from the sorted vector of case labels used
|
||||
in the tree part of the middle end. So the list we construct is
|
||||
sorted in ascending order. */
|
||||
sorted in ascending order.
|
||||
|
||||
LABEL is the case label to be inserted. LOW and HIGH are the bounds
|
||||
against which the index is compared to jump to LABEL and PROB is the
|
||||
estimated probability LABEL is reached from the switch statement. */
|
||||
|
||||
static struct case_node *
|
||||
add_case_node (struct case_node *head, tree low, tree high,
|
||||
tree label, alloc_pool case_node_pool)
|
||||
tree label, int prob, alloc_pool case_node_pool)
|
||||
{
|
||||
struct case_node *r;
|
||||
|
||||
|
@ -1677,6 +1687,8 @@ add_case_node (struct case_node *head, tree low, tree high,
|
|||
r->high = high;
|
||||
r->code_label = label;
|
||||
r->parent = r->left = NULL;
|
||||
r->prob = prob;
|
||||
r->subtree_prob = prob;
|
||||
r->right = head;
|
||||
return r;
|
||||
}
|
||||
|
@ -1778,6 +1790,8 @@ expand_switch_as_decision_tree_p (tree range,
|
|||
|
||||
/* Generate a decision tree, switching on INDEX_EXPR and jumping to
|
||||
one of the labels in CASE_LIST or to the DEFAULT_LABEL.
|
||||
DEFAULT_PROB is the estimated probability that it jumps to
|
||||
DEFAULT_LABEL.
|
||||
|
||||
We generate a binary decision tree to select the appropriate target
|
||||
code. This is done as follows:
|
||||
|
@ -1803,7 +1817,8 @@ expand_switch_as_decision_tree_p (tree range,
|
|||
|
||||
static void
|
||||
emit_case_decision_tree (tree index_expr, tree index_type,
|
||||
struct case_node *case_list, rtx default_label)
|
||||
struct case_node *case_list, rtx default_label,
|
||||
int default_prob)
|
||||
{
|
||||
rtx index = expand_normal (index_expr);
|
||||
|
||||
|
@ -1839,15 +1854,47 @@ emit_case_decision_tree (tree index_expr, tree index_type,
|
|||
dump_case_nodes (dump_file, case_list, indent_step, 0);
|
||||
}
|
||||
|
||||
emit_case_nodes (index, case_list, default_label, index_type);
|
||||
emit_case_nodes (index, case_list, default_label, default_prob, index_type);
|
||||
if (default_label)
|
||||
emit_jump (default_label);
|
||||
}
|
||||
|
||||
/* Return the sum of probabilities of outgoing edges of basic block BB. */
|
||||
|
||||
static int
|
||||
get_outgoing_edge_probs (basic_block bb)
|
||||
{
|
||||
edge e;
|
||||
edge_iterator ei;
|
||||
int prob_sum = 0;
|
||||
FOR_EACH_EDGE(e, ei, bb->succs)
|
||||
prob_sum += e->probability;
|
||||
return prob_sum;
|
||||
}
|
||||
|
||||
/* Computes the conditional probability of jumping to a target if the branch
|
||||
instruction is executed.
|
||||
TARGET_PROB is the estimated probability of jumping to a target relative
|
||||
to some basic block BB.
|
||||
BASE_PROB is the probability of reaching the branch instruction relative
|
||||
to the same basic block BB. */
|
||||
|
||||
static inline int
|
||||
conditional_probability (int target_prob, int base_prob)
|
||||
{
|
||||
if (base_prob > 0)
|
||||
{
|
||||
gcc_assert (target_prob >= 0);
|
||||
gcc_assert (target_prob <= base_prob);
|
||||
return RDIV (target_prob * REG_BR_PROB_BASE, base_prob);
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Generate a dispatch tabler, switching on INDEX_EXPR and jumping to
|
||||
one of the labels in CASE_LIST or to the DEFAULT_LABEL.
|
||||
MINVAL, MAXVAL, and RANGE are the extrema and range of the case
|
||||
labels in CASE_LIST.
|
||||
labels in CASE_LIST. STMT_BB is the basic block containing the statement.
|
||||
|
||||
First, a jump insn is emitted. First we try "casesi". If that
|
||||
fails, try "tablejump". A target *must* have one of them (or both).
|
||||
|
@ -1860,19 +1907,27 @@ emit_case_decision_tree (tree index_expr, tree index_type,
|
|||
static void
|
||||
emit_case_dispatch_table (tree index_expr, tree index_type,
|
||||
struct case_node *case_list, rtx default_label,
|
||||
tree minval, tree maxval, tree range)
|
||||
tree minval, tree maxval, tree range,
|
||||
basic_block stmt_bb)
|
||||
{
|
||||
int i, ncases;
|
||||
struct case_node *n;
|
||||
rtx *labelvec;
|
||||
rtx fallback_label = label_rtx (case_list->code_label);
|
||||
rtx table_label = gen_label_rtx ();
|
||||
bool has_gaps = false;
|
||||
edge default_edge = EDGE_SUCC(stmt_bb, 0);
|
||||
int default_prob = default_edge->probability;
|
||||
int base = get_outgoing_edge_probs (stmt_bb);
|
||||
bool try_with_tablejump = false;
|
||||
|
||||
int new_default_prob = conditional_probability (default_prob,
|
||||
base);
|
||||
|
||||
if (! try_casesi (index_type, index_expr, minval, range,
|
||||
table_label, default_label, fallback_label))
|
||||
table_label, default_label, fallback_label,
|
||||
new_default_prob))
|
||||
{
|
||||
bool ok;
|
||||
|
||||
/* Index jumptables from zero for suitable values of minval to avoid
|
||||
a subtraction. For the rationale see:
|
||||
"http://gcc.gnu.org/ml/gcc-patches/2001-10/msg01234.html". */
|
||||
|
@ -1882,11 +1937,9 @@ emit_case_dispatch_table (tree index_expr, tree index_type,
|
|||
{
|
||||
minval = build_int_cst (index_type, 0);
|
||||
range = maxval;
|
||||
has_gaps = true;
|
||||
}
|
||||
|
||||
ok = try_tablejump (index_type, index_expr, minval, range,
|
||||
table_label, default_label);
|
||||
gcc_assert (ok);
|
||||
try_with_tablejump = true;
|
||||
}
|
||||
|
||||
/* Get table of labels to jump to, in order of case index. */
|
||||
|
@ -1921,8 +1974,48 @@ emit_case_dispatch_table (tree index_expr, tree index_type,
|
|||
default_label = fallback_label;
|
||||
for (i = 0; i < ncases; i++)
|
||||
if (labelvec[i] == 0)
|
||||
labelvec[i] = gen_rtx_LABEL_REF (Pmode, default_label);
|
||||
{
|
||||
has_gaps = true;
|
||||
labelvec[i] = gen_rtx_LABEL_REF (Pmode, default_label);
|
||||
}
|
||||
|
||||
if (has_gaps)
|
||||
{
|
||||
/* There is at least one entry in the jump table that jumps
|
||||
to default label. The default label can either be reached
|
||||
through the indirect jump or the direct conditional jump
|
||||
before that. Split the probability of reaching the
|
||||
default label among these two jumps. */
|
||||
new_default_prob = conditional_probability (default_prob/2,
|
||||
base);
|
||||
default_prob /= 2;
|
||||
base -= default_prob;
|
||||
}
|
||||
else
|
||||
{
|
||||
base -= default_prob;
|
||||
default_prob = 0;
|
||||
}
|
||||
|
||||
default_edge->probability = default_prob;
|
||||
|
||||
/* We have altered the probability of the default edge. So the probabilities
|
||||
of all other edges need to be adjusted so that it sums up to
|
||||
REG_BR_PROB_BASE. */
|
||||
if (base)
|
||||
{
|
||||
edge e;
|
||||
edge_iterator ei;
|
||||
FOR_EACH_EDGE (e, ei, stmt_bb->succs)
|
||||
e->probability = RDIV (e->probability * REG_BR_PROB_BASE, base);
|
||||
}
|
||||
|
||||
if (try_with_tablejump)
|
||||
{
|
||||
bool ok = try_tablejump (index_type, index_expr, minval, range,
|
||||
table_label, default_label, new_default_prob);
|
||||
gcc_assert (ok);
|
||||
}
|
||||
/* Output the table. */
|
||||
emit_label (table_label);
|
||||
|
||||
|
@ -1939,6 +2032,36 @@ emit_case_dispatch_table (tree index_expr, tree index_type,
|
|||
emit_barrier ();
|
||||
}
|
||||
|
||||
/* Reset the aux field of all outgoing edges of basic block BB. */
|
||||
|
||||
static inline void
|
||||
reset_out_edges_aux (basic_block bb)
|
||||
{
|
||||
edge e;
|
||||
edge_iterator ei;
|
||||
FOR_EACH_EDGE(e, ei, bb->succs)
|
||||
e->aux = (void *)0;
|
||||
}
|
||||
|
||||
/* Compute the number of case labels that correspond to each outgoing edge of
|
||||
STMT. Record this information in the aux field of the edge. */
|
||||
|
||||
static inline void
|
||||
compute_cases_per_edge (gimple stmt)
|
||||
{
|
||||
basic_block bb = gimple_bb (stmt);
|
||||
reset_out_edges_aux (bb);
|
||||
int ncases = gimple_switch_num_labels (stmt);
|
||||
for (int i = ncases - 1; i >= 1; --i)
|
||||
{
|
||||
tree elt = gimple_switch_label (stmt, i);
|
||||
tree lab = CASE_LABEL (elt);
|
||||
basic_block case_bb = label_to_block_fn (cfun, lab);
|
||||
edge case_edge = find_edge (bb, case_bb);
|
||||
case_edge->aux = (void *)((long)(case_edge->aux) + 1);
|
||||
}
|
||||
}
|
||||
|
||||
/* Terminate a case (Pascal/Ada) or switch (C) statement
|
||||
in which ORIG_INDEX is the expression to be tested.
|
||||
If ORIG_TYPE is not NULL, it is the original ORIG_INDEX
|
||||
|
@ -1956,6 +2079,7 @@ expand_case (gimple stmt)
|
|||
tree index_expr = gimple_switch_index (stmt);
|
||||
tree index_type = TREE_TYPE (index_expr);
|
||||
tree elt;
|
||||
basic_block bb = gimple_bb (stmt);
|
||||
|
||||
/* A list of case labels; it is first built as a list and it may then
|
||||
be rearranged into a nearly balanced binary tree. */
|
||||
|
@ -1981,6 +2105,8 @@ expand_case (gimple stmt)
|
|||
|
||||
/* Find the default case target label. */
|
||||
default_label = label_rtx (CASE_LABEL (gimple_switch_default_label (stmt)));
|
||||
edge default_edge = EDGE_SUCC(bb, 0);
|
||||
int default_prob = default_edge->probability;
|
||||
|
||||
/* Get upper and lower bounds of case values. */
|
||||
elt = gimple_switch_label (stmt, 1);
|
||||
|
@ -1999,7 +2125,9 @@ expand_case (gimple stmt)
|
|||
uniq = 0;
|
||||
count = 0;
|
||||
struct pointer_set_t *seen_labels = pointer_set_create ();
|
||||
for (i = gimple_switch_num_labels (stmt) - 1; i >= 1; --i)
|
||||
compute_cases_per_edge (stmt);
|
||||
|
||||
for (i = ncases - 1; i >= 1; --i)
|
||||
{
|
||||
elt = gimple_switch_label (stmt, i);
|
||||
tree low = CASE_LOW (elt);
|
||||
|
@ -2041,10 +2169,15 @@ expand_case (gimple stmt)
|
|||
TREE_INT_CST_LOW (high),
|
||||
TREE_INT_CST_HIGH (high));
|
||||
|
||||
case_list = add_case_node (case_list, low, high, lab,
|
||||
case_node_pool);
|
||||
basic_block case_bb = label_to_block_fn (cfun, lab);
|
||||
edge case_edge = find_edge (bb, case_bb);
|
||||
case_list = add_case_node (
|
||||
case_list, low, high, lab,
|
||||
case_edge->probability / (long)(case_edge->aux),
|
||||
case_node_pool);
|
||||
}
|
||||
pointer_set_destroy (seen_labels);
|
||||
reset_out_edges_aux (bb);
|
||||
|
||||
/* cleanup_tree_cfg removes all SWITCH_EXPR with a single
|
||||
destination, such as one with a default case only.
|
||||
|
@ -2060,11 +2193,12 @@ expand_case (gimple stmt)
|
|||
|
||||
if (expand_switch_as_decision_tree_p (range, uniq, count))
|
||||
emit_case_decision_tree (index_expr, index_type,
|
||||
case_list, default_label);
|
||||
case_list, default_label,
|
||||
default_prob);
|
||||
else
|
||||
emit_case_dispatch_table (index_expr, index_type,
|
||||
case_list, default_label,
|
||||
minval, maxval, range);
|
||||
minval, maxval, range, bb);
|
||||
|
||||
reorder_insns (NEXT_INSN (before_case), get_last_insn (), before_case);
|
||||
|
||||
|
@ -2126,7 +2260,7 @@ expand_sjlj_dispatch_table (rtx dispatch_index,
|
|||
{
|
||||
tree elt = VEC_index (tree, dispatch_table, i);
|
||||
rtx lab = label_rtx (CASE_LABEL (elt));
|
||||
do_jump_if_equal (index_mode, index, zero, lab, 0);
|
||||
do_jump_if_equal (index_mode, index, zero, lab, 0, -1);
|
||||
force_expand_binop (index_mode, sub_optab,
|
||||
index, CONST1_RTX (index_mode),
|
||||
index, 0, OPTAB_DIRECT);
|
||||
|
@ -2150,12 +2284,12 @@ expand_sjlj_dispatch_table (rtx dispatch_index,
|
|||
tree elt = VEC_index (tree, dispatch_table, i);
|
||||
tree low = CASE_LOW (elt);
|
||||
tree lab = CASE_LABEL (elt);
|
||||
case_list = add_case_node (case_list, low, low, lab, case_node_pool);
|
||||
case_list = add_case_node (case_list, low, low, lab, 0, case_node_pool);
|
||||
}
|
||||
|
||||
emit_case_dispatch_table (index_expr, index_type,
|
||||
case_list, default_label,
|
||||
minval, maxval, range);
|
||||
minval, maxval, range, NULL);
|
||||
emit_label (default_label);
|
||||
free_alloc_pool (case_node_pool);
|
||||
}
|
||||
|
@ -2237,6 +2371,9 @@ balance_case_nodes (case_node_ptr *head, case_node_ptr parent)
|
|||
/* Optimize each of the two split parts. */
|
||||
balance_case_nodes (&np->left, np);
|
||||
balance_case_nodes (&np->right, np);
|
||||
np->subtree_prob = np->prob;
|
||||
np->subtree_prob += np->left->subtree_prob;
|
||||
np->subtree_prob += np->right->subtree_prob;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -2244,8 +2381,12 @@ balance_case_nodes (case_node_ptr *head, case_node_ptr parent)
|
|||
but fill in `parent' fields. */
|
||||
np = *head;
|
||||
np->parent = parent;
|
||||
np->subtree_prob = np->prob;
|
||||
for (; np->right; np = np->right)
|
||||
np->right->parent = np;
|
||||
{
|
||||
np->right->parent = np;
|
||||
(*head)->subtree_prob += np->right->subtree_prob;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -2358,6 +2499,7 @@ node_is_bounded (case_node_ptr node, tree index_type)
|
|||
&& node_has_high_bound (node, index_type));
|
||||
}
|
||||
|
||||
|
||||
/* Emit step-by-step code to select a case for the value of INDEX.
|
||||
The thus generated decision tree follows the form of the
|
||||
case-node binary tree NODE, whose nodes represent test conditions.
|
||||
|
@ -2386,10 +2528,12 @@ node_is_bounded (case_node_ptr node, tree index_type)
|
|||
|
||||
static void
|
||||
emit_case_nodes (rtx index, case_node_ptr node, rtx default_label,
|
||||
tree index_type)
|
||||
int default_prob, tree index_type)
|
||||
{
|
||||
/* If INDEX has an unsigned type, we must make unsigned branches. */
|
||||
int unsignedp = TYPE_UNSIGNED (index_type);
|
||||
int probability;
|
||||
int prob = node->prob, subtree_prob = node->subtree_prob;
|
||||
enum machine_mode mode = GET_MODE (index);
|
||||
enum machine_mode imode = TYPE_MODE (index_type);
|
||||
|
||||
|
@ -2404,15 +2548,17 @@ emit_case_nodes (rtx index, case_node_ptr node, rtx default_label,
|
|||
|
||||
else if (tree_int_cst_equal (node->low, node->high))
|
||||
{
|
||||
probability = conditional_probability (prob, subtree_prob + default_prob);
|
||||
/* Node is single valued. First see if the index expression matches
|
||||
this node and then check our children, if any. */
|
||||
|
||||
do_jump_if_equal (mode, index,
|
||||
convert_modes (mode, imode,
|
||||
expand_normal (node->low),
|
||||
unsignedp),
|
||||
label_rtx (node->code_label), unsignedp);
|
||||
|
||||
label_rtx (node->code_label), unsignedp, probability);
|
||||
/* Since this case is taken at this point, reduce its weight from
|
||||
subtree_weight. */
|
||||
subtree_prob -= prob;
|
||||
if (node->right != 0 && node->left != 0)
|
||||
{
|
||||
/* This node has children on both sides.
|
||||
|
@ -2423,26 +2569,35 @@ emit_case_nodes (rtx index, case_node_ptr node, rtx default_label,
|
|||
|
||||
if (node_is_bounded (node->right, index_type))
|
||||
{
|
||||
probability = conditional_probability (
|
||||
node->right->prob,
|
||||
subtree_prob + default_prob);
|
||||
emit_cmp_and_jump_insns (index,
|
||||
convert_modes
|
||||
(mode, imode,
|
||||
expand_normal (node->high),
|
||||
unsignedp),
|
||||
GT, NULL_RTX, mode, unsignedp,
|
||||
label_rtx (node->right->code_label));
|
||||
emit_case_nodes (index, node->left, default_label, index_type);
|
||||
label_rtx (node->right->code_label),
|
||||
probability);
|
||||
emit_case_nodes (index, node->left, default_label, default_prob,
|
||||
index_type);
|
||||
}
|
||||
|
||||
else if (node_is_bounded (node->left, index_type))
|
||||
{
|
||||
probability = conditional_probability (
|
||||
node->left->prob,
|
||||
subtree_prob + default_prob);
|
||||
emit_cmp_and_jump_insns (index,
|
||||
convert_modes
|
||||
(mode, imode,
|
||||
expand_normal (node->high),
|
||||
unsignedp),
|
||||
LT, NULL_RTX, mode, unsignedp,
|
||||
label_rtx (node->left->code_label));
|
||||
emit_case_nodes (index, node->right, default_label, index_type);
|
||||
label_rtx (node->left->code_label),
|
||||
probability);
|
||||
emit_case_nodes (index, node->right, default_label, default_prob, index_type);
|
||||
}
|
||||
|
||||
/* If both children are single-valued cases with no
|
||||
|
@ -2460,21 +2615,27 @@ emit_case_nodes (rtx index, case_node_ptr node, rtx default_label,
|
|||
|
||||
/* See if the value matches what the right hand side
|
||||
wants. */
|
||||
probability = conditional_probability (
|
||||
node->right->prob,
|
||||
subtree_prob + default_prob);
|
||||
do_jump_if_equal (mode, index,
|
||||
convert_modes (mode, imode,
|
||||
expand_normal (node->right->low),
|
||||
unsignedp),
|
||||
label_rtx (node->right->code_label),
|
||||
unsignedp);
|
||||
unsignedp, probability);
|
||||
|
||||
/* See if the value matches what the left hand side
|
||||
wants. */
|
||||
probability = conditional_probability (
|
||||
node->left->prob,
|
||||
subtree_prob + default_prob);
|
||||
do_jump_if_equal (mode, index,
|
||||
convert_modes (mode, imode,
|
||||
expand_normal (node->left->low),
|
||||
unsignedp),
|
||||
label_rtx (node->left->code_label),
|
||||
unsignedp);
|
||||
unsignedp, probability);
|
||||
}
|
||||
|
||||
else
|
||||
|
@ -2486,6 +2647,12 @@ emit_case_nodes (rtx index, case_node_ptr node, rtx default_label,
|
|||
= build_decl (curr_insn_location (),
|
||||
LABEL_DECL, NULL_TREE, NULL_TREE);
|
||||
|
||||
/* The default label could be reached either through the right
|
||||
subtree or the left subtree. Divide the probability
|
||||
equally. */
|
||||
probability = conditional_probability (
|
||||
node->right->subtree_prob + default_prob/2,
|
||||
subtree_prob + default_prob);
|
||||
/* See if the value is on the right. */
|
||||
emit_cmp_and_jump_insns (index,
|
||||
convert_modes
|
||||
|
@ -2493,11 +2660,13 @@ emit_case_nodes (rtx index, case_node_ptr node, rtx default_label,
|
|||
expand_normal (node->high),
|
||||
unsignedp),
|
||||
GT, NULL_RTX, mode, unsignedp,
|
||||
label_rtx (test_label));
|
||||
label_rtx (test_label),
|
||||
probability);
|
||||
default_prob /= 2;
|
||||
|
||||
/* Value must be on the left.
|
||||
Handle the left-hand subtree. */
|
||||
emit_case_nodes (index, node->left, default_label, index_type);
|
||||
emit_case_nodes (index, node->left, default_label, default_prob, index_type);
|
||||
/* If left-hand subtree does nothing,
|
||||
go to default. */
|
||||
if (default_label)
|
||||
|
@ -2505,7 +2674,7 @@ emit_case_nodes (rtx index, case_node_ptr node, rtx default_label,
|
|||
|
||||
/* Code branches here for the right-hand subtree. */
|
||||
expand_label (test_label);
|
||||
emit_case_nodes (index, node->right, default_label, index_type);
|
||||
emit_case_nodes (index, node->right, default_label, default_prob, index_type);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2523,28 +2692,38 @@ emit_case_nodes (rtx index, case_node_ptr node, rtx default_label,
|
|||
{
|
||||
if (!node_has_low_bound (node, index_type))
|
||||
{
|
||||
probability = conditional_probability (
|
||||
default_prob/2,
|
||||
subtree_prob + default_prob);
|
||||
emit_cmp_and_jump_insns (index,
|
||||
convert_modes
|
||||
(mode, imode,
|
||||
expand_normal (node->high),
|
||||
unsignedp),
|
||||
LT, NULL_RTX, mode, unsignedp,
|
||||
default_label);
|
||||
default_label,
|
||||
probability);
|
||||
default_prob /= 2;
|
||||
}
|
||||
|
||||
emit_case_nodes (index, node->right, default_label, index_type);
|
||||
emit_case_nodes (index, node->right, default_label, default_prob, index_type);
|
||||
}
|
||||
else
|
||||
/* We cannot process node->right normally
|
||||
since we haven't ruled out the numbers less than
|
||||
this node's value. So handle node->right explicitly. */
|
||||
do_jump_if_equal (mode, index,
|
||||
convert_modes
|
||||
(mode, imode,
|
||||
expand_normal (node->right->low),
|
||||
unsignedp),
|
||||
label_rtx (node->right->code_label), unsignedp);
|
||||
}
|
||||
{
|
||||
probability = conditional_probability (
|
||||
node->right->subtree_prob,
|
||||
subtree_prob + default_prob);
|
||||
/* We cannot process node->right normally
|
||||
since we haven't ruled out the numbers less than
|
||||
this node's value. So handle node->right explicitly. */
|
||||
do_jump_if_equal (mode, index,
|
||||
convert_modes
|
||||
(mode, imode,
|
||||
expand_normal (node->right->low),
|
||||
unsignedp),
|
||||
label_rtx (node->right->code_label), unsignedp, probability);
|
||||
}
|
||||
}
|
||||
|
||||
else if (node->right == 0 && node->left != 0)
|
||||
{
|
||||
|
@ -2554,27 +2733,38 @@ emit_case_nodes (rtx index, case_node_ptr node, rtx default_label,
|
|||
{
|
||||
if (!node_has_high_bound (node, index_type))
|
||||
{
|
||||
probability = conditional_probability (
|
||||
default_prob/2,
|
||||
subtree_prob + default_prob);
|
||||
emit_cmp_and_jump_insns (index,
|
||||
convert_modes
|
||||
(mode, imode,
|
||||
expand_normal (node->high),
|
||||
unsignedp),
|
||||
GT, NULL_RTX, mode, unsignedp,
|
||||
default_label);
|
||||
default_label,
|
||||
probability);
|
||||
default_prob /= 2;
|
||||
}
|
||||
|
||||
emit_case_nodes (index, node->left, default_label, index_type);
|
||||
emit_case_nodes (index, node->left, default_label,
|
||||
default_prob, index_type);
|
||||
}
|
||||
else
|
||||
/* We cannot process node->left normally
|
||||
since we haven't ruled out the numbers less than
|
||||
this node's value. So handle node->left explicitly. */
|
||||
do_jump_if_equal (mode, index,
|
||||
convert_modes
|
||||
(mode, imode,
|
||||
expand_normal (node->left->low),
|
||||
unsignedp),
|
||||
label_rtx (node->left->code_label), unsignedp);
|
||||
{
|
||||
probability = conditional_probability (
|
||||
node->left->subtree_prob,
|
||||
subtree_prob + default_prob);
|
||||
/* We cannot process node->left normally
|
||||
since we haven't ruled out the numbers less than
|
||||
this node's value. So handle node->left explicitly. */
|
||||
do_jump_if_equal (mode, index,
|
||||
convert_modes
|
||||
(mode, imode,
|
||||
expand_normal (node->left->low),
|
||||
unsignedp),
|
||||
label_rtx (node->left->code_label), unsignedp, probability);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
|
@ -2593,15 +2783,21 @@ emit_case_nodes (rtx index, case_node_ptr node, rtx default_label,
|
|||
tree test_label = 0;
|
||||
|
||||
if (node_is_bounded (node->right, index_type))
|
||||
/* Right hand node is fully bounded so we can eliminate any
|
||||
testing and branch directly to the target code. */
|
||||
emit_cmp_and_jump_insns (index,
|
||||
convert_modes
|
||||
(mode, imode,
|
||||
expand_normal (node->high),
|
||||
unsignedp),
|
||||
GT, NULL_RTX, mode, unsignedp,
|
||||
label_rtx (node->right->code_label));
|
||||
{
|
||||
/* Right hand node is fully bounded so we can eliminate any
|
||||
testing and branch directly to the target code. */
|
||||
probability = conditional_probability (
|
||||
node->right->subtree_prob,
|
||||
subtree_prob + default_prob);
|
||||
emit_cmp_and_jump_insns (index,
|
||||
convert_modes
|
||||
(mode, imode,
|
||||
expand_normal (node->high),
|
||||
unsignedp),
|
||||
GT, NULL_RTX, mode, unsignedp,
|
||||
label_rtx (node->right->code_label),
|
||||
probability);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Right hand node requires testing.
|
||||
|
@ -2609,27 +2805,36 @@ emit_case_nodes (rtx index, case_node_ptr node, rtx default_label,
|
|||
|
||||
test_label = build_decl (curr_insn_location (),
|
||||
LABEL_DECL, NULL_TREE, NULL_TREE);
|
||||
probability = conditional_probability (
|
||||
node->right->subtree_prob + default_prob/2,
|
||||
subtree_prob + default_prob);
|
||||
emit_cmp_and_jump_insns (index,
|
||||
convert_modes
|
||||
(mode, imode,
|
||||
expand_normal (node->high),
|
||||
unsignedp),
|
||||
GT, NULL_RTX, mode, unsignedp,
|
||||
label_rtx (test_label));
|
||||
label_rtx (test_label),
|
||||
probability);
|
||||
default_prob /= 2;
|
||||
}
|
||||
|
||||
/* Value belongs to this node or to the left-hand subtree. */
|
||||
|
||||
probability = conditional_probability (
|
||||
prob,
|
||||
subtree_prob + default_prob);
|
||||
emit_cmp_and_jump_insns (index,
|
||||
convert_modes
|
||||
(mode, imode,
|
||||
expand_normal (node->low),
|
||||
unsignedp),
|
||||
GE, NULL_RTX, mode, unsignedp,
|
||||
label_rtx (node->code_label));
|
||||
label_rtx (node->code_label),
|
||||
probability);
|
||||
|
||||
/* Handle the left-hand subtree. */
|
||||
emit_case_nodes (index, node->left, default_label, index_type);
|
||||
emit_case_nodes (index, node->left, default_label, default_prob, index_type);
|
||||
|
||||
/* If right node had to be handled later, do that now. */
|
||||
|
||||
|
@ -2641,7 +2846,7 @@ emit_case_nodes (rtx index, case_node_ptr node, rtx default_label,
|
|||
emit_jump (default_label);
|
||||
|
||||
expand_label (test_label);
|
||||
emit_case_nodes (index, node->right, default_label, index_type);
|
||||
emit_case_nodes (index, node->right, default_label, default_prob, index_type);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2651,26 +2856,35 @@ emit_case_nodes (rtx index, case_node_ptr node, rtx default_label,
|
|||
if they are possible. */
|
||||
if (!node_has_low_bound (node, index_type))
|
||||
{
|
||||
probability = conditional_probability (
|
||||
default_prob/2,
|
||||
subtree_prob + default_prob);
|
||||
emit_cmp_and_jump_insns (index,
|
||||
convert_modes
|
||||
(mode, imode,
|
||||
expand_normal (node->low),
|
||||
unsignedp),
|
||||
LT, NULL_RTX, mode, unsignedp,
|
||||
default_label);
|
||||
default_label,
|
||||
probability);
|
||||
default_prob /= 2;
|
||||
}
|
||||
|
||||
/* Value belongs to this node or to the right-hand subtree. */
|
||||
|
||||
probability = conditional_probability (
|
||||
prob,
|
||||
subtree_prob + default_prob);
|
||||
emit_cmp_and_jump_insns (index,
|
||||
convert_modes
|
||||
(mode, imode,
|
||||
expand_normal (node->high),
|
||||
unsignedp),
|
||||
LE, NULL_RTX, mode, unsignedp,
|
||||
label_rtx (node->code_label));
|
||||
label_rtx (node->code_label),
|
||||
probability);
|
||||
|
||||
emit_case_nodes (index, node->right, default_label, index_type);
|
||||
emit_case_nodes (index, node->right, default_label, default_prob, index_type);
|
||||
}
|
||||
|
||||
else if (node->right == 0 && node->left != 0)
|
||||
|
@ -2679,26 +2893,35 @@ emit_case_nodes (rtx index, case_node_ptr node, rtx default_label,
|
|||
if they are possible. */
|
||||
if (!node_has_high_bound (node, index_type))
|
||||
{
|
||||
probability = conditional_probability (
|
||||
default_prob/2,
|
||||
subtree_prob + default_prob);
|
||||
emit_cmp_and_jump_insns (index,
|
||||
convert_modes
|
||||
(mode, imode,
|
||||
expand_normal (node->high),
|
||||
unsignedp),
|
||||
GT, NULL_RTX, mode, unsignedp,
|
||||
default_label);
|
||||
default_label,
|
||||
probability);
|
||||
default_prob /= 2;
|
||||
}
|
||||
|
||||
/* Value belongs to this node or to the left-hand subtree. */
|
||||
|
||||
probability = conditional_probability (
|
||||
prob,
|
||||
subtree_prob + default_prob);
|
||||
emit_cmp_and_jump_insns (index,
|
||||
convert_modes
|
||||
(mode, imode,
|
||||
expand_normal (node->low),
|
||||
unsignedp),
|
||||
GE, NULL_RTX, mode, unsignedp,
|
||||
label_rtx (node->code_label));
|
||||
label_rtx (node->code_label),
|
||||
probability);
|
||||
|
||||
emit_case_nodes (index, node->left, default_label, index_type);
|
||||
emit_case_nodes (index, node->left, default_label, default_prob, index_type);
|
||||
}
|
||||
|
||||
else
|
||||
|
@ -2711,24 +2934,32 @@ emit_case_nodes (rtx index, case_node_ptr node, rtx default_label,
|
|||
|
||||
if (!high_bound && low_bound)
|
||||
{
|
||||
probability = conditional_probability (
|
||||
default_prob,
|
||||
subtree_prob + default_prob);
|
||||
emit_cmp_and_jump_insns (index,
|
||||
convert_modes
|
||||
(mode, imode,
|
||||
expand_normal (node->high),
|
||||
unsignedp),
|
||||
GT, NULL_RTX, mode, unsignedp,
|
||||
default_label);
|
||||
default_label,
|
||||
probability);
|
||||
}
|
||||
|
||||
else if (!low_bound && high_bound)
|
||||
{
|
||||
probability = conditional_probability (
|
||||
default_prob,
|
||||
subtree_prob + default_prob);
|
||||
emit_cmp_and_jump_insns (index,
|
||||
convert_modes
|
||||
(mode, imode,
|
||||
expand_normal (node->low),
|
||||
unsignedp),
|
||||
LT, NULL_RTX, mode, unsignedp,
|
||||
default_label);
|
||||
default_label,
|
||||
probability);
|
||||
}
|
||||
else if (!low_bound && !high_bound)
|
||||
{
|
||||
|
@ -2748,8 +2979,11 @@ emit_case_nodes (rtx index, case_node_ptr node, rtx default_label,
|
|||
high, low),
|
||||
NULL_RTX, mode, EXPAND_NORMAL);
|
||||
|
||||
probability = conditional_probability (
|
||||
default_prob,
|
||||
subtree_prob + default_prob);
|
||||
emit_cmp_and_jump_insns (new_index, new_bound, GT, NULL_RTX,
|
||||
mode, 1, default_label);
|
||||
mode, 1, default_label, probability);
|
||||
}
|
||||
|
||||
emit_jump (label_rtx (node->code_label));
|
||||
|
|
|
@ -1,3 +1,7 @@
|
|||
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,
|
||||
|
|
40
gcc/testsuite/gcc.dg/tree-prof/switch-case-1.c
Normal file
40
gcc/testsuite/gcc.dg/tree-prof/switch-case-1.c
Normal file
|
@ -0,0 +1,40 @@
|
|||
/* { 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" } } */
|
40
gcc/testsuite/gcc.dg/tree-prof/switch-case-2.c
Normal file
40
gcc/testsuite/gcc.dg/tree-prof/switch-case-2.c
Normal file
|
@ -0,0 +1,40 @@
|
|||
/* { 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" } } */
|
Loading…
Add table
Reference in a new issue