Hi,
this patch splits call predictor to direct/indirect/polymorphic variant.
The motivation is that the predictor seems to do poor job on GAP benchmark
predicting that path containing an indirect call is unlikely. These calls
are quite specific, so it makes sense to have separate predictor for them.

The values was measured by Martin on SPEC2k6 and will need tweaking to get
gap performance back. I think this is OK given that we have quite small
sample of benchmarks having indirect call in the hot loop, but I would like
to do that incrementally.

Bootstrapped/regtested x86_64-linux, comitted.

Honza

        PR middle-end/77484
        * predict.def (PRED_CALL): Update hitrate.
        (PRED_INDIR_CALL, PRED_POLYMORPHIC_CALL): New predictors.
        * predict.c (tree_estimate_probability_bb): Split CALL predictor
        into direct/indirect/polymorphic variants.
Index: predict.def
===================================================================
--- predict.def (revision 243992)
+++ predict.def (working copy)
@@ -116,7 +116,13 @@ DEF_PREDICTOR (PRED_TREE_OPCODE_NONEQUAL
 DEF_PREDICTOR (PRED_TREE_FPOPCODE, "fp_opcode (on trees)", HITRATE (90), 0)
 
 /* Branch guarding call is probably taken.  */
-DEF_PREDICTOR (PRED_CALL, "call", HITRATE (67), 0)
+DEF_PREDICTOR (PRED_CALL, "call", HITRATE (55), 0)
+
+/* PRED_CALL is not very reliable predictor and it turns out to be even
+   less reliable for indirect calls and polymorphic calls.  For spec2k6
+   the predictio nis slightly in the direction of taking the call.  */
+DEF_PREDICTOR (PRED_INDIR_CALL, "indirect call", HITRATE (51), 0)
+DEF_PREDICTOR (PRED_POLYMORPHIC_CALL, "polymorphic call", HITRATE (58), 0)
 
 /* Recursive calls are usually not taken or the function will recurse
    indefinitely.  */
Index: predict.c
===================================================================
--- predict.c   (revision 243992)
+++ predict.c   (working copy)
@@ -2786,7 +2786,12 @@ tree_estimate_probability_bb (basic_bloc
                     something exceptional.  */
                  && gimple_has_side_effects (stmt))
                {
-                 predict_edge_def (e, PRED_CALL, NOT_TAKEN);
+                 if (gimple_call_fndecl (stmt))
+                   predict_edge_def (e, PRED_CALL, NOT_TAKEN);
+                 else if (virtual_method_call_p (gimple_call_fn (stmt)))
+                   predict_edge_def (e, PRED_POLYMORPHIC_CALL, TAKEN);
+                 else
+                   predict_edge_def (e, PRED_INDIR_CALL, TAKEN);
                  break;
                }
            }

Reply via email to