@@ -1,5 +1,31 @@
2014-10-29 David Malcolm <dmalcolm@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 <dmalcolm@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
@@ -120,6 +120,7 @@ struct gomp_sections;
struct gomp_single;
struct gomp_target;
struct gomp_teams;
+struct gpredict;
union section;
typedef union section section;
@@ -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)
@@ -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:
@@ -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);
@@ -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)
@@ -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. */
}