predict.c (predict_loops): Predict for short-circuit conditions.

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.

From-SVN: r192215
This commit is contained in:
Dehao Chen 2012-10-08 16:45:21 +00:00 committed by Dehao Chen
parent 2512a443d6
commit 16fdb75f78
6 changed files with 133 additions and 1 deletions

View File

@ -1,3 +1,8 @@
2012-10-08 Dehao Chen <dehao@google.com>
* predict.c (predict_loops): Predict for short-circuit conditions.
(predict_extra_loop_exits): New Function.
2012-10-08 Steven Bosscher <steven@gcc.gnu.org>
* bitmap.h (bitmap_and_into): Update prototype.

View File

@ -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)

View File

@ -1,3 +1,9 @@
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.
2012-10-08 Rainer Orth <ro@CeBiTec.Uni-Bielefeld.DE>
* gcc.target/i386/pr54445-1.c: Require tls_runtime, add tls options.

View File

@ -0,0 +1,13 @@
/* { dg-do compile } */
/* { dg-options "-O2 -fdump-tree-profile_estimate" } */
int g;
int foo();
void test() {
while (foo() && g < 10)
g++;
return;
}
/* { dg-final { scan-tree-dump-times "loop exit heuristics:" 3 "profile_estimate"} } */
/* { dg-final { cleanup-tree-dump "profile_estimate" } } */

View File

@ -0,0 +1,13 @@
/* { dg-do compile } */
/* { dg-options "-O2 -fdump-tree-profile_estimate" } */
int g;
int foo();
void test() {
while (foo() || g < 10)
g++;
return;
}
/* { dg-final { scan-tree-dump-times "loop exit heuristics:" 2 "profile_estimate"} } */
/* { dg-final { cleanup-tree-dump "profile_estimate" } } */

View File

@ -0,0 +1,13 @@
/* { dg-do compile } */
/* { dg-options "-O2 -fdump-tree-profile_estimate" } */
int g;
int foo();
void test() {
while (foo() && (g < 10 || g > 20))
g++;
return;
}
/* { dg-final { scan-tree-dump-times "loop exit heuristics:" 3 "profile_estimate"} } */
/* { dg-final { cleanup-tree-dump "profile_estimate" } } */