summaryrefslogtreecommitdiff
path: root/gcc/tree-switch-conversion.c
diff options
context:
space:
mode:
authorMartin Liska <mliska@suse.cz>2018-09-03 09:51:56 +0200
committerMartin Liska <marxin@gcc.gnu.org>2018-09-03 07:51:56 +0000
commitadd4cbca8cf60d1108959de10a6c4b66d90464dc (patch)
tree42056a80e427e22c26a9f90994acf4d459f9b414 /gcc/tree-switch-conversion.c
parent106fd43fee5e964ddf3017cfd3de1046978d490d (diff)
Make __builtin_expect effective in switch statements (PR middle-end/PR59521).
2018-09-03 Martin Liska <mliska@suse.cz> PR middle-end/59521 * predict.c (set_even_probabilities): Add likely_edges argument and handle cases where we have precisely one likely edge. (combine_predictions_for_bb): Catch also likely_edges. (tree_predict_by_opcode): Handle gswitch statements. * tree-cfg.h (find_case_label_for_value): New declaration. (find_taken_edge_switch_expr): Likewise. * tree-switch-conversion.c (switch_decision_tree::balance_case_nodes): Find pivot in decision tree based on probabily, not by number of nodes. 2018-09-03 Martin Liska <mliska@suse.cz> PR middle-end/59521 * c-c++-common/pr59521-1.c: New test. * c-c++-common/pr59521-2.c: New test. * gcc.dg/tree-prof/pr59521-3.c: New test. From-SVN: r264050
Diffstat (limited to 'gcc/tree-switch-conversion.c')
-rw-r--r--gcc/tree-switch-conversion.c46
1 files changed, 22 insertions, 24 deletions
diff --git a/gcc/tree-switch-conversion.c b/gcc/tree-switch-conversion.c
index 7e4f34c71f8..d7d1c3972a0 100644
--- a/gcc/tree-switch-conversion.c
+++ b/gcc/tree-switch-conversion.c
@@ -1914,6 +1914,7 @@ switch_decision_tree::balance_case_nodes (case_tree_node **head,
int ranges = 0;
case_tree_node **npp;
case_tree_node *left;
+ profile_probability prob = profile_probability::never ();
/* Count the number of entries on branch. Also count the ranges. */
@@ -1923,6 +1924,7 @@ switch_decision_tree::balance_case_nodes (case_tree_node **head,
ranges++;
i++;
+ prob += np->m_c->m_prob;
np = np->m_right;
}
@@ -1931,39 +1933,35 @@ switch_decision_tree::balance_case_nodes (case_tree_node **head,
/* Split this list if it is long enough for that to help. */
npp = head;
left = *npp;
+ profile_probability pivot_prob = prob.apply_scale (1, 2);
- /* If there are just three nodes, split at the middle one. */
- if (i == 3)
- npp = &(*npp)->m_right;
- else
+ /* Find the place in the list that bisects the list's total cost,
+ where ranges count as 2. */
+ while (1)
{
- /* Find the place in the list that bisects the list's total cost,
- where ranges count as 2.
- Here I gets half the total cost. */
- i = (i + ranges + 1) / 2;
- while (1)
- {
- /* Skip nodes while their cost does not reach that amount. */
- if (!tree_int_cst_equal ((*npp)->m_c->get_low (),
- (*npp)->m_c->get_high ()))
- i--;
- i--;
- if (i <= 0)
- break;
- npp = &(*npp)->m_right;
- }
+ /* Skip nodes while their probability does not reach
+ that amount. */
+ prob -= (*npp)->m_c->m_prob;
+ if (prob.initialized_p ()
+ && (prob < pivot_prob || ! (*npp)->m_right))
+ break;
+ npp = &(*npp)->m_right;
}
- *head = np = *npp;
- *npp = 0;
+
+ np = *npp;
+ *npp = 0;
+ *head = np;
np->m_parent = parent;
- np->m_left = left;
+ np->m_left = left == np ? NULL : left;
/* Optimize each of the two split parts. */
balance_case_nodes (&np->m_left, np);
balance_case_nodes (&np->m_right, np);
np->m_c->m_subtree_prob = np->m_c->m_prob;
- np->m_c->m_subtree_prob += np->m_left->m_c->m_subtree_prob;
- np->m_c->m_subtree_prob += np->m_right->m_c->m_subtree_prob;
+ if (np->m_left)
+ np->m_c->m_subtree_prob += np->m_left->m_c->m_subtree_prob;
+ if (np->m_right)
+ np->m_c->m_subtree_prob += np->m_right->m_c->m_subtree_prob;
}
else
{