This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[tuples] Tuplify PREDICT_EXPR
- From: Jakub Jelinek <jakub at redhat dot com>
- To: Diego Novillo <dnovillo at google dot com>, Aldy Hernandez <aldyh at redhat dot com>
- Cc: gcc-patches at gcc dot gnu dot org
- Date: Fri, 4 Jul 2008 10:08:55 -0400
- Subject: [tuples] Tuplify PREDICT_EXPR
- Reply-to: Jakub Jelinek <jakub at redhat dot com>
Hi!
This patch gimplifies PREDICT_EXPR into a new GIMPLE_PREDICT gimple stmt
and handles it throughout the gimple passes.
Bootstrapped/regtested on x86_64-linux. Ok for tuples?
2008-07-04 Jakub Jelinek <jakub@redhat.com>
* gimple.def (GIMPLE_PREDICT): New.
* gimple.h: Update comment above GF_* flags.
(GF_PREDICT_TAKEN): New.
(gimple_build_predict): New prototype.
(gimple_predict_predictor, gimple_predict_outcome,
gimple_predict_set_predictor, gimple_predict_set_outcome): New
inlines.
* gimple.c (gss_for_code): Handle GIMPLE_PREDICT.
(gimple_size, walk_gimple_op): Likewise.
(gimple_build_predict): New function.
* gimple-pretty-print.c (dump_gimple_stmt): Handle GIMPLE_PREDICT.
* predict.c (tree_bb_level_predictions): Likewise.
* cfgexpand.c (gimple_to_tree): Likewise.
* tree-inline.c (estimate_num_insns): Likewise.
* tree-ssa-dce.c (mark_stmt_if_obviously_necessary): Likewise.
* gimple-low.c (lower_stmt): Likewise.
* tree-cfg.c (verify_types_in_gimple_seq_2): Likewise.
(verify_types_in_gimple_stmt): Likewise. Don't handle PREDICT_EXPR.
* gimplify.c (gimplify_expr): Gimplify PREDICT_EXPR into
GIMPLE_PREDICT.
* expr.c (expand_expr_real): Don't handle PREDICT_EXPR.
--- gcc/gimple.c.jj 2008-07-02 14:25:10.000000000 +0200
+++ gcc/gimple.c 2008-07-04 13:08:18.000000000 +0200
@@ -129,6 +129,7 @@ gss_for_code (enum gimple_code code)
case GIMPLE_CHANGE_DYNAMIC_TYPE: return GSS_CHANGE_DYNAMIC_TYPE;
case GIMPLE_OMP_ATOMIC_LOAD: return GSS_OMP_ATOMIC_LOAD;
case GIMPLE_OMP_ATOMIC_STORE: return GSS_OMP_ATOMIC_STORE;
+ case GIMPLE_PREDICT: return GSS_BASE;
default: gcc_unreachable ();
}
}
@@ -193,6 +194,8 @@ gimple_size (enum gimple_code code)
return sizeof (struct gimple_statement_wce);
case GIMPLE_CHANGE_DYNAMIC_TYPE:
return sizeof (struct gimple_statement_with_ops);
+ case GIMPLE_PREDICT:
+ return sizeof (struct gimple_statement_base);
default:
break;
}
@@ -1058,6 +1061,17 @@ gimple_build_omp_atomic_store (tree val)
return p;
}
+/* Build a GIMPLE_PREDICT statement. */
+
+gimple
+gimple_build_predict (enum br_predictor predictor, enum prediction outcome)
+{
+ gimple p = gimple_alloc (GIMPLE_PREDICT, 0);
+ gimple_predict_set_predictor (p, predictor);
+ gimple_predict_set_outcome (p, outcome);
+ return p;
+}
+
/* Return which gimple structure is used by T. The enums here are defined
in gsstruct.def. */
@@ -1605,6 +1619,7 @@ walk_gimple_op (gimple stmt, walk_tree_f
case GIMPLE_NOP:
case GIMPLE_RESX:
case GIMPLE_OMP_RETURN:
+ case GIMPLE_PREDICT:
break;
default:
--- gcc/gimple-pretty-print.c.jj 2008-06-27 18:54:54.000000000 +0200
+++ gcc/gimple-pretty-print.c 2008-07-04 13:16:44.000000000 +0200
@@ -1548,6 +1548,16 @@ dump_gimple_stmt (pretty_printer *buffer
dump_gimple_resx (buffer, gs, spc, 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.");
+ break;
+
default:
GIMPLE_NIY;
}
--- gcc/predict.c.jj 2008-07-02 11:37:20.000000000 +0200
+++ gcc/predict.c 2008-07-04 13:25:32.000000000 +0200
@@ -1346,13 +1346,12 @@ tree_bb_level_predictions (void)
FOR_EACH_BB (bb)
{
- gimple_stmt_iterator bsi;
+ gimple_stmt_iterator gsi;
- for (bsi = gsi_start_bb (bb); !gsi_end_p (bsi);)
+ for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi);)
{
- gimple stmt = gsi_stmt (bsi);
+ gimple stmt = gsi_stmt (gsi);
tree decl;
- bool next = false;
if (gimple_code (stmt) == GIMPLE_CALL)
{
@@ -1366,19 +1365,15 @@ tree_bb_level_predictions (void)
predict_paths_leading_to (bb, PRED_COLD_FUNCTION,
NOT_TAKEN);
}
+ else if (gimple_code (stmt) == GIMPLE_PREDICT)
+ {
+ predict_paths_leading_to (bb, gimple_predict_predictor (stmt),
+ gimple_predict_outcome (stmt));
+ gsi_remove (&gsi, true);
+ continue;
+ }
-/* FIXME tuples */
-#if 0
- case PREDICT_EXPR:
- predict_paths_leading_to (bb, PREDICT_EXPR_PREDICTOR (stmt),
- PREDICT_EXPR_OUTCOME (stmt));
- bsi_remove (&bsi, true);
- next = true;
- break;
-#endif
-
- if (!next)
- gsi_next (&bsi);
+ gsi_next (&gsi);
}
}
}
--- gcc/gimple.h.jj 2008-07-03 13:06:31.000000000 +0200
+++ gcc/gimple.h 2008-07-04 13:41:52.000000000 +0200
@@ -86,8 +86,8 @@ enum gimple_rhs_class
Values for the masks can overlap as long as the overlapping values
are never used in the same statement class.
- The maximum mask value that can be defined is 1 << 7 (i.e., each
- statement code can hold up to 8 bitflags).
+ The maximum mask value that can be defined is 1 << 15 (i.e., each
+ statement code can hold up to 16 bitflags).
Keep this list sorted. */
static const unsigned int GF_ASM_INPUT = 1 << 0;
@@ -107,6 +107,8 @@ static const unsigned int GF_OMP_RETURN_
static const unsigned int GF_OMP_SECTION_LAST = 1 << 0;
+static const unsigned int GF_PREDICT_TAKEN = 1 << 15;
+
/* Masks for selecting a pass local flag (PLF) to work on. These
masks are used by gimple_set_plf and gimple_plf. */
enum plf_mask {
@@ -804,6 +806,7 @@ gimple gimple_build_omp_single (gimple_s
gimple gimple_build_cdt (tree, tree);
gimple gimple_build_omp_atomic_load (tree, tree);
gimple gimple_build_omp_atomic_store (tree);
+gimple gimple_build_predict (enum br_predictor, enum prediction);
enum gimple_statement_structure_enum gimple_statement_structure (gimple);
enum gimple_statement_structure_enum gss_for_assign (enum tree_code);
void sort_case_labels (VEC(tree,heap) *);
@@ -4008,6 +4011,50 @@ gimple_cdt_set_location (gimple gs, tree
}
+/* Return the predictor of GIMPLE_PREDICT statement GS. */
+
+static inline enum br_predictor
+gimple_predict_predictor (gimple gs)
+{
+ GIMPLE_CHECK (gs, GIMPLE_PREDICT);
+ return (enum br_predictor) (gs->gsbase.subcode & ~GF_PREDICT_TAKEN);
+}
+
+
+/* Set the predictor of GIMPLE_PREDICT statement GS to PREDICT. */
+
+static inline void
+gimple_predict_set_predictor (gimple gs, enum br_predictor predictor)
+{
+ GIMPLE_CHECK (gs, GIMPLE_PREDICT);
+ gs->gsbase.subcode = (gs->gsbase.subcode & GF_PREDICT_TAKEN)
+ | (unsigned) predictor;
+}
+
+
+/* Return the outcome of GIMPLE_PREDICT statement GS. */
+
+static inline enum prediction
+gimple_predict_outcome (gimple gs)
+{
+ GIMPLE_CHECK (gs, GIMPLE_PREDICT);
+ return (gs->gsbase.subcode & GF_PREDICT_TAKEN) ? TAKEN : NOT_TAKEN;
+}
+
+
+/* Set the outcome of GIMPLE_PREDICT statement GS to OUTCOME. */
+
+static inline void
+gimple_predict_set_outcome (gimple gs, enum prediction outcome)
+{
+ GIMPLE_CHECK (gs, GIMPLE_PREDICT);
+ if (outcome == TAKEN)
+ gs->gsbase.subcode |= GF_PREDICT_TAKEN;
+ else
+ gs->gsbase.subcode &= ~GF_PREDICT_TAKEN;
+}
+
+
/* Return a new iterator pointing to GIMPLE_SEQ's first statement. */
static inline gimple_stmt_iterator
--- gcc/cfgexpand.c.jj 2008-06-30 10:54:01.000000000 +0200
+++ gcc/cfgexpand.c 2008-07-04 13:29:49.000000000 +0200
@@ -275,6 +275,7 @@ gimple_to_tree (gimple stmt)
break;
case GIMPLE_NOP:
+ case GIMPLE_PREDICT:
t = build1 (NOP_EXPR, void_type_node, size_zero_node);
break;
--- gcc/gimplify.c.jj 2008-07-02 12:49:47.000000000 +0200
+++ gcc/gimplify.c 2008-07-04 13:12:48.000000000 +0200
@@ -6417,9 +6417,12 @@ gimplify_expr (tree *expr_p, gimple_seq
gimple_build_goto (GOTO_DESTINATION (*expr_p)));
break;
- /* Predictions are always gimplified. */
case PREDICT_EXPR:
- goto out;
+ gimplify_seq_add_stmt (pre_p,
+ gimple_build_predict (PREDICT_EXPR_PREDICTOR (*expr_p),
+ PREDICT_EXPR_OUTCOME (*expr_p)));
+ ret = GS_ALL_DONE;
+ break;
case LABEL_EXPR:
ret = GS_ALL_DONE;
--- gcc/tree-inline.c.jj 2008-07-03 18:39:35.000000000 +0200
+++ gcc/tree-inline.c 2008-07-04 13:46:24.000000000 +0200
@@ -2921,6 +2921,7 @@ estimate_num_insns (gimple stmt, eni_wei
case GIMPLE_PHI:
case GIMPLE_RETURN:
case GIMPLE_CHANGE_DYNAMIC_TYPE:
+ case GIMPLE_PREDICT:
return 0;
case GIMPLE_ASM:
--- gcc/tree-ssa-dce.c.jj 2008-06-13 14:30:50.000000000 +0200
+++ gcc/tree-ssa-dce.c 2008-07-04 13:18:51.000000000 +0200
@@ -1,5 +1,5 @@
/* Dead code elimination pass for the GNU compiler.
- Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007
+ Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007, 2008
Free Software Foundation, Inc.
Contributed by Ben Elliston <bje@redhat.com>
and Andrew MacLeod <amacleod@redhat.com>
@@ -273,8 +273,8 @@ mark_stmt_if_obviously_necessary (gimple
can then remove the block and labels. */
switch (gimple_code (stmt))
{
- /* FIXME tuples: case PREDICT_EXPR:*/
/* FIXME tuples: remove GIMPLE_BIND*/
+ case GIMPLE_PREDICT:
case GIMPLE_BIND:
case GIMPLE_LABEL:
mark_stmt_necessary (stmt, false);
--- gcc/expr.c.jj 2008-07-02 11:37:18.000000000 +0200
+++ gcc/expr.c 2008-07-04 13:30:37.000000000 +0200
@@ -7046,7 +7046,6 @@ expand_expr_real (tree exp, rtx target,
/* Handle ERROR_MARK before anybody tries to access its type. */
if (TREE_CODE (exp) == ERROR_MARK
- || TREE_CODE (exp) == PREDICT_EXPR
|| (!GIMPLE_TUPLE_P (exp) && TREE_CODE (TREE_TYPE (exp)) == ERROR_MARK))
{
ret = CONST0_RTX (tmode);
--- gcc/gimple.def.jj 2008-06-27 18:54:54.000000000 +0200
+++ gcc/gimple.def 2008-07-04 12:49:03.000000000 +0200
@@ -343,6 +343,13 @@ DEFGSCODE(GIMPLE_OMP_SECTIONS_SWITCH, "g
CLAUSES is a TREE_LIST node holding the associated clauses. */
DEFGSCODE(GIMPLE_OMP_SINGLE, "gimple_omp_single", NULL)
+/* GIMPLE_PREDICT <PREDICT, OUTCOME> specifies a hint for branch prediction.
+
+ PREDICT is one of the predictors from predict.def.
+
+ OUTCOME is NOT_TAKEN or TAKEN. */
+DEFGSCODE(GIMPLE_PREDICT, "gimple_predict", NULL)
+
/* This node represents a cleanup expression. It is ONLY USED INTERNALLY
by the gimplifier as a placeholder for cleanups, and its uses will be
cleaned up by the time gimplification is done.
--- gcc/tree-cfg.c.jj 2008-07-02 19:57:49.000000000 +0200
+++ gcc/tree-cfg.c 2008-07-04 13:47:48.000000000 +0200
@@ -3730,6 +3730,7 @@ verify_types_in_gimple_stmt (gimple stmt
return verify_types_in_gimple_op (gimple_goto_dest (stmt));
case GIMPLE_NOP:
+ case GIMPLE_PREDICT:
return false;
case GIMPLE_SWITCH:
@@ -3739,7 +3740,6 @@ verify_types_in_gimple_stmt (gimple stmt
return verify_types_in_gimple_return (stmt);
case GIMPLE_ASM:
- case PREDICT_EXPR:
return false;
case GIMPLE_CHANGE_DYNAMIC_TYPE:
@@ -3803,6 +3803,7 @@ verify_types_in_gimple_seq_2 (gimple_seq
case GIMPLE_NOP:
case GIMPLE_RESX:
case GIMPLE_OMP_RETURN:
+ case GIMPLE_PREDICT:
break;
default:
--- gcc/gimple-low.c.jj 2008-06-13 14:30:50.000000000 +0200
+++ gcc/gimple-low.c 2008-07-04 13:22:14.000000000 +0200
@@ -288,7 +288,7 @@ lower_stmt (gimple_stmt_iterator *gsi, s
case GIMPLE_ASM:
case GIMPLE_ASSIGN:
case GIMPLE_GOTO:
- /* FIXME tuples: case PREDICT_EXPR: */
+ case GIMPLE_PREDICT:
case GIMPLE_LABEL:
case GIMPLE_SWITCH:
case GIMPLE_CHANGE_DYNAMIC_TYPE:
Jakub