Strip only selected predictors after early tree passes (PR tree-optimization/85799).
authorMartin Liska <mliska@suse.cz>
Fri, 10 Aug 2018 09:31:51 +0000 (11:31 +0200)
committerMartin Liska <marxin@gcc.gnu.org>
Fri, 10 Aug 2018 09:31:51 +0000 (09:31 +0000)
2018-08-10  Martin Liska  <mliska@suse.cz>

        PR tree-optimization/85799
* passes.def: Add argument for pass_strip_predict_hints.
* predict.c (class pass_strip_predict_hints): Add new argument
        early_p.
(strip_predictor_early): New function.
(pass_strip_predict_hints::execute): Call the function to
        strip predictors.
(strip_predict_hints): New function.
* predict.def: Fix comment.
2018-08-10  Martin Liska  <mliska@suse.cz>

        PR tree-optimization/85799
* gcc.dg/pr85799.c: New test.

From-SVN: r263465

gcc/ChangeLog
gcc/passes.def
gcc/predict.c
gcc/predict.def
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.dg/pr85799.c [new file with mode: 0644]

index 1cebb9c5befa87610aa3109c505239252a8556cb..5edaf2414b6101b2eba13b97c9cf1c3e2cd1236d 100644 (file)
@@ -1,3 +1,15 @@
+2018-08-10  Martin Liska  <mliska@suse.cz>
+
+        PR tree-optimization/85799
+       * passes.def: Add argument for pass_strip_predict_hints.
+       * predict.c (class pass_strip_predict_hints): Add new argument
+        early_p.
+       (strip_predictor_early): New function.
+       (pass_strip_predict_hints::execute): Call the function to
+        strip predictors.
+       (strip_predict_hints): New function.
+       * predict.def: Fix comment.
+
 2018-08-10  Thomas Preud'homme  <thomas.preudhomme@linaro.org>
 
        * Makefile.in: Clarify which tm.texi to copy over to assert the
index 2a8fbc2efbefcbe3da03a2466343cc3f355018be..7f4b3479a35f99879e887d574acffb96b02fe5f9 100644 (file)
@@ -98,7 +98,7 @@ along with GCC; see the file COPYING3.  If not see
             early optimizations again.  It is thus good idea to do this
              late.  */
          NEXT_PASS (pass_split_functions);
-         NEXT_PASS (pass_strip_predict_hints);
+         NEXT_PASS (pass_strip_predict_hints, true /* early_p */);
       POP_INSERT_PASSES ()
       NEXT_PASS (pass_release_ssa_names);
       NEXT_PASS (pass_rebuild_cgraph_edges);
@@ -183,7 +183,7 @@ along with GCC; see the file COPYING3.  If not see
       NEXT_PASS (pass_remove_cgraph_callee_edges);
       /* Initial scalar cleanups before alias computation.
         They ensure memory accesses are not indirect wherever possible.  */
-      NEXT_PASS (pass_strip_predict_hints);
+      NEXT_PASS (pass_strip_predict_hints, false /* early_p */);
       NEXT_PASS (pass_ccp, true /* nonzero_p */);
       NEXT_PASS (pass_post_ipa_warn);
       /* After CCP we rewrite no longer addressed locals into SSA
@@ -348,7 +348,7 @@ along with GCC; see the file COPYING3.  If not see
   NEXT_PASS (pass_all_optimizations_g);
   PUSH_INSERT_PASSES_WITHIN (pass_all_optimizations_g)
       NEXT_PASS (pass_remove_cgraph_callee_edges);
-      NEXT_PASS (pass_strip_predict_hints);
+      NEXT_PASS (pass_strip_predict_hints, false /* early_p */);
       /* Lower remaining pieces of GIMPLE.  */
       NEXT_PASS (pass_lower_complex);
       NEXT_PASS (pass_lower_vector_ssa);
index 96ae10f1319a6593dd0856a599adfca7c5b97190..abbafdae74ac8c4232457462434dcdf9c7be14cd 100644 (file)
@@ -3884,38 +3884,28 @@ make_pass_profile (gcc::context *ctxt)
   return new pass_profile (ctxt);
 }
 
-namespace {
+/* Return true when PRED predictor should be removed after early
+   tree passes.  Most of the predictors are beneficial to survive
+   as early inlining can also distribute then into caller's bodies.  */
 
-const pass_data pass_data_strip_predict_hints =
-{
-  GIMPLE_PASS, /* type */
-  "*strip_predict_hints", /* name */
-  OPTGROUP_NONE, /* optinfo_flags */
-  TV_BRANCH_PROB, /* tv_id */
-  PROP_cfg, /* properties_required */
-  0, /* properties_provided */
-  0, /* properties_destroyed */
-  0, /* todo_flags_start */
-  0, /* todo_flags_finish */
-};
-
-class pass_strip_predict_hints : public gimple_opt_pass
+static bool
+strip_predictor_early (enum br_predictor pred)
 {
-public:
-  pass_strip_predict_hints (gcc::context *ctxt)
-    : gimple_opt_pass (pass_data_strip_predict_hints, ctxt)
-  {}
-
-  /* opt_pass methods: */
-  opt_pass * clone () { return new pass_strip_predict_hints (m_ctxt); }
-  virtual unsigned int execute (function *);
-
-}; // class pass_strip_predict_hints
+  switch (pred)
+    {
+    case PRED_TREE_EARLY_RETURN:
+      return true;
+    default:
+      return false;
+    }
+}
 
 /* Get rid of all builtin_expect calls and GIMPLE_PREDICT statements
-   we no longer need.  */
+   we no longer need.  EARLY is set to true when called from early
+   optimizations.  */
+
 unsigned int
-pass_strip_predict_hints::execute (function *fun)
+strip_predict_hints (function *fun, bool early)
 {
   basic_block bb;
   gimple *ass_stmt;
@@ -3931,15 +3921,20 @@ pass_strip_predict_hints::execute (function *fun)
 
          if (gimple_code (stmt) == GIMPLE_PREDICT)
            {
-             gsi_remove (&bi, true);
-             changed = true;
-             continue;
+             if (!early
+                 || strip_predictor_early (gimple_predict_predictor (stmt)))
+               {
+                 gsi_remove (&bi, true);
+                 changed = true;
+                 continue;
+               }
            }
          else if (is_gimple_call (stmt))
            {
              tree fndecl = gimple_call_fndecl (stmt);
 
-             if ((fndecl
+             if ((!early
+                  && fndecl
                   && DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_NORMAL
                   && DECL_FUNCTION_CODE (fndecl) == BUILT_IN_EXPECT
                   && gimple_call_num_args (stmt) == 2)
@@ -3967,6 +3962,49 @@ pass_strip_predict_hints::execute (function *fun)
   return changed ? TODO_cleanup_cfg : 0;
 }
 
+namespace {
+
+const pass_data pass_data_strip_predict_hints =
+{
+  GIMPLE_PASS, /* type */
+  "*strip_predict_hints", /* name */
+  OPTGROUP_NONE, /* optinfo_flags */
+  TV_BRANCH_PROB, /* tv_id */
+  PROP_cfg, /* properties_required */
+  0, /* properties_provided */
+  0, /* properties_destroyed */
+  0, /* todo_flags_start */
+  0, /* todo_flags_finish */
+};
+
+class pass_strip_predict_hints : public gimple_opt_pass
+{
+public:
+  pass_strip_predict_hints (gcc::context *ctxt)
+    : gimple_opt_pass (pass_data_strip_predict_hints, ctxt)
+  {}
+
+  /* opt_pass methods: */
+  opt_pass * clone () { return new pass_strip_predict_hints (m_ctxt); }
+  void set_pass_param (unsigned int n, bool param)
+    {
+      gcc_assert (n == 0);
+      early_p = param;
+    }
+
+  virtual unsigned int execute (function *);
+
+private:
+  bool early_p;
+
+}; // class pass_strip_predict_hints
+
+unsigned int
+pass_strip_predict_hints::execute (function *fun)
+{
+  return strip_predict_hints (fun, early_p);
+}
+
 } // anon namespace
 
 gimple_opt_pass *
index 76e6590cc961c3c8541a1fdaef333a36549ddd4b..c0709aa6473c46f497008abaa4106d59029966df 100644 (file)
@@ -22,7 +22,7 @@ along with GCC; see the file COPYING3.  If not see
      DEF_PREDICTOR (ENUM, NAME, HITRATE)
 
    This macro will be called once for each predictor.  The ENUM will
-   be of type `enum predictor', and will enumerate all supported
+   be of type `enum br_predictor', and will enumerate all supported
    predictors.  The order of DEF_PREDICTOR calls is important, as
    in the first match combining heuristics, the predictor appearing
    first in this file will win.
index 1e915bc1a0aa03c7aab2e93440fb3b01da623d5a..8a2ed682f651d301f0d4cf2d4a5c7f82a6d04c85 100644 (file)
@@ -1,3 +1,8 @@
+2018-08-10  Martin Liska  <mliska@suse.cz>
+
+        PR tree-optimization/85799
+       * gcc.dg/pr85799.c: New test.
+
 2018-08-09  Jeff Law  <law@redhat.com>
 
        PR middle-end/86897
diff --git a/gcc/testsuite/gcc.dg/pr85799.c b/gcc/testsuite/gcc.dg/pr85799.c
new file mode 100644 (file)
index 0000000..0e93785
--- /dev/null
@@ -0,0 +1,19 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -fdump-tree-profile_estimate" } */
+
+void unlikely();
+void likely();
+
+inline int expect_false(int b) {
+    return __builtin_expect(b, 0);
+}
+
+void inline_func_hint(int b) {
+    if (expect_false(b)) {
+        unlikely();
+    } else {
+        likely();
+    }
+}
+
+/* { dg-final { scan-tree-dump "_builtin_expect heuristics of edge" "profile_estimate"} } */