gcc/ChangeLog.gimple-classes: * coretypes.h (struct gpredict): Add forward declaration. * doc/gimple.texi (Class hierarchy of GIMPLE statements): Add gpredict. * gimple-pretty-print.c (pp_gimple_stmt_1): Within case GIMPLE_PREDICT, add local "predict_stmt" via a checked cast and use it in place of "stmt". * gimple.c (gimple_build_predict): Strengthen return type and local "p" from gimple to gpredict *. * gimple.h (struct gpredict): New subclass of gimple_statement_base, adding invariant that code is GIMPLE_PREDICT. (is_a_helper <gpredict *>::test): New. (gimple_build_predict): Strengthen return type from gimple to gpredict *. (gimple_predict_predictor): Strengthen param from const_gimple to const gpredict *. (gimple_predict_outcome): Likewise. (gimple_predict_set_predictor): Strengthen param from gimple to gpredict *. (gimple_predict_set_outcome): Likewise. * predict.c (tree_bb_level_predictions): Convert check for GIMPLE_PREDICT to a dyn_cast, introducing local "predict_stmt" and using it in place of "stmt" for typesafety. --- gcc/ChangeLog.gimple-classes | 26 ++++++++++++++++++++++++++ gcc/coretypes.h | 1 + gcc/doc/gimple.texi | 3 ++- gcc/gimple-pretty-print.c | 18 +++++++++++------- gcc/gimple.c | 4 ++-- gcc/gimple.h | 31 +++++++++++++++++++++++-------- gcc/predict.c | 7 ++++--- 7 files changed, 69 insertions(+), 21 deletions(-)
diff --git a/gcc/ChangeLog.gimple-classes b/gcc/ChangeLog.gimple-classes index 07c12cd..7d9dfb3 100644 --- a/gcc/ChangeLog.gimple-classes +++ b/gcc/ChangeLog.gimple-classes @@ -1,5 +1,31 @@ 2014-10-29 David Malcolm <dmalc...@redhat.com> + * coretypes.h (struct gpredict): Add forward declaration. + * doc/gimple.texi (Class hierarchy of GIMPLE statements): Add + gpredict. + * gimple-pretty-print.c (pp_gimple_stmt_1): Within case + GIMPLE_PREDICT, add local "predict_stmt" via a checked cast and + use it in place of "stmt". + * gimple.c (gimple_build_predict): Strengthen return type and + local "p" from gimple to gpredict *. + * gimple.h (struct gpredict): New subclass of + gimple_statement_base, adding invariant that code is + GIMPLE_PREDICT. + (is_a_helper <gpredict *>::test): New. + (gimple_build_predict): Strengthen return type from gimple to + gpredict *. + (gimple_predict_predictor): Strengthen param from const_gimple to + const gpredict *. + (gimple_predict_outcome): Likewise. + (gimple_predict_set_predictor): Strengthen param from gimple to + gpredict *. + (gimple_predict_set_outcome): Likewise. + * predict.c (tree_bb_level_predictions): Convert check for + GIMPLE_PREDICT to a dyn_cast, introducing local "predict_stmt" and + using it in place of "stmt" for typesafety. + +2014-10-29 David Malcolm <dmalc...@redhat.com> + * gimple.h (gimple_eh_filter_types): Strengthen param from const_gimple to const geh_filter *. (gimple_eh_filter_types_ptr): Strengthen param from gimple to diff --git a/gcc/coretypes.h b/gcc/coretypes.h index 6e9f7b2..190d9a1 100644 --- a/gcc/coretypes.h +++ b/gcc/coretypes.h @@ -120,6 +120,7 @@ struct gomp_sections; struct gomp_single; struct gomp_target; struct gomp_teams; +struct gpredict; union section; typedef union section section; diff --git a/gcc/doc/gimple.texi b/gcc/doc/gimple.texi index de7345e..887710a 100644 --- a/gcc/doc/gimple.texi +++ b/gcc/doc/gimple.texi @@ -305,7 +305,8 @@ kinds, along with their relationships to @code{GSS_} values (layouts) and | used for 4 codes: GIMPLE_ERROR_MARK | GIMPLE_NOP | GIMPLE_OMP_SECTIONS_SWITCH - | GIMPLE_PREDICT + + gpredict + | code: GIMPLE_PREDICT | + gimple_statement_with_ops_base | | (no GSS layout) diff --git a/gcc/gimple-pretty-print.c b/gcc/gimple-pretty-print.c index 864f636..91a20d5 100644 --- a/gcc/gimple-pretty-print.c +++ b/gcc/gimple-pretty-print.c @@ -2248,13 +2248,17 @@ pp_gimple_stmt_1 (pretty_printer *buffer, gimple gs, int spc, int flags) break; case GIMPLE_PREDICT: - pp_string (buffer, "// predicted "); - if (gimple_predict_outcome (gs)) - pp_string (buffer, "likely by "); - else - pp_string (buffer, "unlikely by "); - pp_string (buffer, predictor_name (gimple_predict_predictor (gs))); - pp_string (buffer, " predictor."); + { + gpredict *predict_stmt = as_a <gpredict *> (gs); + pp_string (buffer, "// predicted "); + if (gimple_predict_outcome (predict_stmt)) + pp_string (buffer, "likely by "); + else + pp_string (buffer, "unlikely by "); + pp_string (buffer, + predictor_name (gimple_predict_predictor (predict_stmt))); + pp_string (buffer, " predictor."); + } break; case GIMPLE_TRANSACTION: diff --git a/gcc/gimple.c b/gcc/gimple.c index 1421afe..b58c9db 100644 --- a/gcc/gimple.c +++ b/gcc/gimple.c @@ -1136,10 +1136,10 @@ gimple_build_transaction (gimple_seq body, tree label) /* Build a GIMPLE_PREDICT statement. PREDICT is one of the predictors from predict.def, OUTCOME is NOT_TAKEN or TAKEN. */ -gimple +gpredict * gimple_build_predict (enum br_predictor predictor, enum prediction outcome) { - gimple p = gimple_alloc (GIMPLE_PREDICT, 0); + gpredict *p = as_a <gpredict *> (gimple_alloc (GIMPLE_PREDICT, 0)); /* Ensure all the predictors fit into the lower bits of the subcode. */ gcc_assert ((int) END_PREDICTORS <= GF_PREDICT_TAKEN); gimple_predict_set_predictor (p, predictor); diff --git a/gcc/gimple.h b/gcc/gimple.h index 0b09165..582bbbb 100644 --- a/gcc/gimple.h +++ b/gcc/gimple.h @@ -834,6 +834,16 @@ struct GTY((tag("GSS_WITH_MEM_OPS"))) /* no additional fields; this uses the layout for GSS_WITH_MEM_OPS. */ }; +/* A statement with the invariant that + stmt->code == GIMPLE_PREDICT + i.e. a hint for branch prediction. */ + +struct GTY(()) + gpredict : public gimple_statement_base +{ + /* no additional fields; this uses the layout for GSS_BASE. */ +}; + template <> template <> inline bool @@ -1061,6 +1071,14 @@ is_a_helper <gphi *>::test (gimple gs) template <> template <> inline bool +is_a_helper <gpredict *>::test (gimple gs) +{ + return gs->code == GIMPLE_PREDICT; +} + +template <> +template <> +inline bool is_a_helper <greturn *>::test (gimple gs) { return gs->code == GIMPLE_RETURN; @@ -1348,7 +1366,7 @@ gomp_teams *gimple_build_omp_teams (gimple_seq, tree); gomp_atomic_load *gimple_build_omp_atomic_load (tree, tree); gomp_atomic_store *gimple_build_omp_atomic_store (tree); gtransaction *gimple_build_transaction (gimple_seq, tree); -gimple gimple_build_predict (enum br_predictor, enum prediction); +gpredict *gimple_build_predict (enum br_predictor, enum prediction); extern void gimple_seq_add_stmt (gimple_seq *, gimple); extern void gimple_seq_add_stmt_without_update (gimple_seq *, gimple); void gimple_seq_add_seq (gimple_seq *, gimple_seq); @@ -5438,9 +5456,8 @@ is_gimple_resx (const_gimple gs) /* Return the predictor of GIMPLE_PREDICT statement GS. */ static inline enum br_predictor -gimple_predict_predictor (gimple gs) +gimple_predict_predictor (const gpredict *gs) { - GIMPLE_CHECK (gs, GIMPLE_PREDICT); return (enum br_predictor) (gs->subcode & ~GF_PREDICT_TAKEN); } @@ -5448,9 +5465,8 @@ gimple_predict_predictor (gimple gs) /* Set the predictor of GIMPLE_PREDICT statement GS to PREDICT. */ static inline void -gimple_predict_set_predictor (gimple gs, enum br_predictor predictor) +gimple_predict_set_predictor (gpredict *gs, enum br_predictor predictor) { - GIMPLE_CHECK (gs, GIMPLE_PREDICT); gs->subcode = (gs->subcode & GF_PREDICT_TAKEN) | (unsigned) predictor; } @@ -5459,9 +5475,8 @@ gimple_predict_set_predictor (gimple gs, enum br_predictor predictor) /* Return the outcome of GIMPLE_PREDICT statement GS. */ static inline enum prediction -gimple_predict_outcome (gimple gs) +gimple_predict_outcome (const gpredict *gs) { - GIMPLE_CHECK (gs, GIMPLE_PREDICT); return (gs->subcode & GF_PREDICT_TAKEN) ? TAKEN : NOT_TAKEN; } @@ -5469,7 +5484,7 @@ gimple_predict_outcome (gimple gs) /* Set the outcome of GIMPLE_PREDICT statement GS to OUTCOME. */ static inline void -gimple_predict_set_outcome (gimple gs, enum prediction outcome) +gimple_predict_set_outcome (gpredict *gs, enum prediction outcome) { GIMPLE_CHECK (gs, GIMPLE_PREDICT); if (outcome == TAKEN) diff --git a/gcc/predict.c b/gcc/predict.c index 352417a..fad0f10 100644 --- a/gcc/predict.c +++ b/gcc/predict.c @@ -2204,10 +2204,11 @@ tree_bb_level_predictions (void) predict_paths_leading_to (bb, PRED_COLD_FUNCTION, NOT_TAKEN); } - else if (gimple_code (stmt) == GIMPLE_PREDICT) + else if (gpredict *predict_stmt = dyn_cast <gpredict *> (stmt)) { - predict_paths_leading_to (bb, gimple_predict_predictor (stmt), - gimple_predict_outcome (stmt)); + predict_paths_leading_to (bb, + gimple_predict_predictor (predict_stmt), + gimple_predict_outcome (predict_stmt)); /* Keep GIMPLE_PREDICT around so early inlining will propagate hints to callers. */ } -- 1.7.11.7