aboutsummaryrefslogtreecommitdiff
path: root/gcc/predict.c
diff options
context:
space:
mode:
authorDehao Chen <dehao@google.com>2012-10-08 16:45:21 +0000
committerDehao Chen <dehao@google.com>2012-10-08 16:45:21 +0000
commitc92323c354ceaf453e4b733e7f8102781e6dca68 (patch)
tree675e200d78e6ed4df9b534e2184161059261b725 /gcc/predict.c
parentba4f42206297ac09bf6ed5f3ea1955eb23fd98a0 (diff)
gcc:
2012-10-08 Dehao Chen <dehao@google.com> * predict.c (predict_loops): Predict for short-circuit conditions. (predict_extra_loop_exits): New Function. testsuite: 2012-10-08 Dehao Chen <dehao@google.com> * g++.dg/predict-loop-exit-1.C: New. * g++.dg/predict-loop-exit-2.C: New. * g++.dg/predict-loop-exit-3.C: New. git-svn-id: https://gcc.gnu.org/svn/gcc/trunk@192215 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc/predict.c')
-rw-r--r--gcc/predict.c84
1 files changed, 83 insertions, 1 deletions
diff --git a/gcc/predict.c b/gcc/predict.c
index f0db9f40330..49173998c87 100644
--- a/gcc/predict.c
+++ b/gcc/predict.c
@@ -1296,7 +1296,87 @@ predict_iv_comparison (struct loop *loop, basic_block bb,
predict_edge_def (then_edge, PRED_LOOP_IV_COMPARE_GUESS, NOT_TAKEN);
}
}
-
+
+/* Predict for extra loop exits that will lead to EXIT_EDGE. The extra loop
+ exits are resulted from short-circuit conditions that will generate an
+ if_tmp. E.g.:
+
+ if (foo() || global > 10)
+ break;
+
+ This will be translated into:
+
+ BB3:
+ loop header...
+ BB4:
+ if foo() goto BB6 else goto BB5
+ BB5:
+ if global > 10 goto BB6 else goto BB7
+ BB6:
+ goto BB7
+ BB7:
+ iftmp = (PHI 0(BB5), 1(BB6))
+ if iftmp == 1 goto BB8 else goto BB3
+ BB8:
+ outside of the loop...
+
+ The edge BB7->BB8 is loop exit because BB8 is outside of the loop.
+ From the dataflow, we can infer that BB4->BB6 and BB5->BB6 are also loop
+ exits. This function takes BB7->BB8 as input, and finds out the extra loop
+ exits to predict them using PRED_LOOP_EXIT. */
+
+static void
+predict_extra_loop_exits (edge exit_edge)
+{
+ unsigned i;
+ bool check_value_one;
+ gimple phi_stmt;
+ tree cmp_rhs, cmp_lhs;
+ gimple cmp_stmt = last_stmt (exit_edge->src);
+
+ if (!cmp_stmt || gimple_code (cmp_stmt) != GIMPLE_COND)
+ return;
+ cmp_rhs = gimple_cond_rhs (cmp_stmt);
+ cmp_lhs = gimple_cond_lhs (cmp_stmt);
+ if (!TREE_CONSTANT (cmp_rhs)
+ || !(integer_zerop (cmp_rhs) || integer_onep (cmp_rhs)))
+ return;
+ if (TREE_CODE (cmp_lhs) != SSA_NAME)
+ return;
+
+ /* If check_value_one is true, only the phi_args with value '1' will lead
+ to loop exit. Otherwise, only the phi_args with value '0' will lead to
+ loop exit. */
+ check_value_one = (((integer_onep (cmp_rhs))
+ ^ (gimple_cond_code (cmp_stmt) == EQ_EXPR))
+ ^ ((exit_edge->flags & EDGE_TRUE_VALUE) != 0));
+
+ phi_stmt = SSA_NAME_DEF_STMT (cmp_lhs);
+ if (!phi_stmt || gimple_code (phi_stmt) != GIMPLE_PHI)
+ return;
+
+ for (i = 0; i < gimple_phi_num_args (phi_stmt); i++)
+ {
+ edge e1;
+ edge_iterator ei;
+ tree val = gimple_phi_arg_def (phi_stmt, i);
+ edge e = gimple_phi_arg_edge (phi_stmt, i);
+
+ if (!TREE_CONSTANT (val) || !(integer_zerop (val) || integer_onep (val)))
+ continue;
+ if ((check_value_one ^ integer_onep (val)) == 1)
+ continue;
+ if (EDGE_COUNT (e->src->succs) != 1)
+ {
+ predict_paths_leading_to_edge (e, PRED_LOOP_EXIT, NOT_TAKEN);
+ continue;
+ }
+
+ FOR_EACH_EDGE (e1, ei, e->src->preds)
+ predict_paths_leading_to_edge (e1, PRED_LOOP_EXIT, NOT_TAKEN);
+ }
+}
+
/* Predict edge probabilities by exploiting loop structure. */
static void
@@ -1332,6 +1412,8 @@ predict_loops (void)
int probability;
enum br_predictor predictor;
+ predict_extra_loop_exits (ex);
+
if (number_of_iterations_exit (loop, ex, &niter_desc, false))
niter = niter_desc.niter;
if (!niter || TREE_CODE (niter_desc.niter) != INTEGER_CST)