Fix probabilities for jump table (PR tree-optimization/86702).
authorMartin Liska <mliska@suse.cz>
Mon, 27 Aug 2018 12:17:54 +0000 (14:17 +0200)
committerMartin Liska <marxin@gcc.gnu.org>
Mon, 27 Aug 2018 12:17:54 +0000 (12:17 +0000)
2018-08-27  Martin Liska  <mliska@suse.cz>

        PR tree-optimization/86702
* tree-switch-conversion.c (jump_table_cluster::emit):
        Make probabilities even for values in jump table
        according to number of cases handled.
(switch_decision_tree::compute_cases_per_edge): Pass
        argument to reset_out_edges_aux function.
(switch_decision_tree::analyze_switch_statement): Likewise.
* tree-switch-conversion.h (switch_decision_tree::reset_out_edges_aux):
        Make it static.

From-SVN: r263877

gcc/ChangeLog
gcc/tree-switch-conversion.c
gcc/tree-switch-conversion.h

index 40a8735a44610b7bfffc3a51f5402aaad02a3559..b39f12fe03702e53cbfb1c62a5e83144e1736599 100644 (file)
@@ -1,3 +1,15 @@
+2018-08-27  Martin Liska  <mliska@suse.cz>
+
+        PR tree-optimization/86702
+       * tree-switch-conversion.c (jump_table_cluster::emit):
+        Make probabilities even for values in jump table
+        according to number of cases handled.
+       (switch_decision_tree::compute_cases_per_edge): Pass
+        argument to reset_out_edges_aux function.
+       (switch_decision_tree::analyze_switch_statement): Likewise.
+       * tree-switch-conversion.h (switch_decision_tree::reset_out_edges_aux):
+        Make it static.
+
 2018-08-27  Martin Liska  <mliska@suse.cz>
 
        * cfgexpand.c (expand_asm_stmt): Use label_to_block and pass
index ef08bdc990dcb773eeb1bfc6d7a5a6f87cc2cdcd..00a463b1dde8497c279c0bd2ecd9252ddf383983 100644 (file)
@@ -1061,6 +1061,9 @@ void
 jump_table_cluster::emit (tree index_expr, tree,
                          tree default_label_expr, basic_block default_bb)
 {
+  unsigned HOST_WIDE_INT range = get_range (get_low (), get_high ());
+  unsigned HOST_WIDE_INT nondefault_range = 0;
+
   /* For jump table we just emit a new gswitch statement that will
      be latter lowered to jump table.  */
   auto_vec <tree> labels;
@@ -1077,6 +1080,39 @@ jump_table_cluster::emit (tree index_expr, tree,
                                    unshare_expr (default_label_expr), labels);
   gimple_stmt_iterator gsi = gsi_start_bb (m_case_bb);
   gsi_insert_after (&gsi, s, GSI_NEW_STMT);
+
+  /* Set up even probabilities for all cases.  */
+  for (unsigned i = 0; i < m_cases.length (); i++)
+    {
+      simple_cluster *sc = static_cast<simple_cluster *> (m_cases[i]);
+      edge case_edge = find_edge (m_case_bb, sc->m_case_bb);
+      unsigned HOST_WIDE_INT case_range
+       = sc->get_range (sc->get_low (), sc->get_high ());
+      nondefault_range += case_range;
+
+      /* case_edge->aux is number of values in a jump-table that are covered
+        by the case_edge.  */
+      case_edge->aux = (void *) ((intptr_t) (case_edge->aux) + case_range);
+    }
+
+  edge default_edge = gimple_switch_default_edge (cfun, s);
+  default_edge->probability = profile_probability::never ();
+
+  for (unsigned i = 0; i < m_cases.length (); i++)
+    {
+      simple_cluster *sc = static_cast<simple_cluster *> (m_cases[i]);
+      edge case_edge = find_edge (m_case_bb, sc->m_case_bb);
+      case_edge->probability
+       = profile_probability::always ().apply_scale ((intptr_t)case_edge->aux,
+                                                     range);
+    }
+
+  /* Number of non-default values is probability of default edge.  */
+  default_edge->probability
+    += profile_probability::always ().apply_scale (nondefault_range,
+                                                  range).invert ();
+
+  switch_decision_tree::reset_out_edges_aux (s);
 }
 
 /* Find jump tables of given CLUSTERS, where all members of the vector
@@ -1568,7 +1604,7 @@ bit_test_cluster::hoist_edge_and_branch_if_true (gimple_stmt_iterator *gsip,
 void
 switch_decision_tree::compute_cases_per_edge ()
 {
-  reset_out_edges_aux ();
+  reset_out_edges_aux (m_switch);
   int ncases = gimple_switch_num_labels (m_switch);
   for (int i = ncases - 1; i >= 1; --i)
     {
@@ -1610,7 +1646,7 @@ switch_decision_tree::analyze_switch_statement ()
       m_case_bbs.quick_push (case_edge->dest);
     }
 
-  reset_out_edges_aux ();
+  reset_out_edges_aux (m_switch);
 
   /* Find jump table clusters.  */
   vec<cluster *> output = jump_table_cluster::find_jump_tables (clusters);
index 4beac785f0581dd9fb33ae668ca193e9b6bcd84b..af2f47a07e69998fb9f43308b8bed671892753de 100644 (file)
@@ -513,10 +513,6 @@ struct switch_decision_tree
   /* Attempt to expand CLUSTERS as a decision tree.  Return true when
      expanded.  */
   bool try_switch_expansion (vec<cluster *> &clusters);
-
-  /* Reset the aux field of all outgoing edges of switch basic block.  */
-  inline void reset_out_edges_aux ();
-
   /* Compute the number of case labels that correspond to each outgoing edge of
      switch statement.  Record this information in the aux field of the edge.
      */
@@ -576,6 +572,9 @@ struct switch_decision_tree
                                              basic_block label_bb,
                                              profile_probability prob);
 
+  /* Reset the aux field of all outgoing edges of switch basic block.  */
+  static inline void reset_out_edges_aux (gswitch *swtch);
+
   /* Switch statement.  */
   gswitch *m_switch;
 
@@ -838,9 +837,9 @@ struct switch_conversion
 };
 
 void
-switch_decision_tree::reset_out_edges_aux ()
+switch_decision_tree::reset_out_edges_aux (gswitch *swtch)
 {
-  basic_block bb = gimple_bb (m_switch);
+  basic_block bb = gimple_bb (swtch);
   edge e;
   edge_iterator ei;
   FOR_EACH_EDGE (e, ei, bb->succs)