diff options
author | Jakub Jelinek <jakub@gcc.gnu.org> | 2014-03-18 12:31:04 +0100 |
---|---|---|
committer | Jakub Jelinek <jakub@gcc.gnu.org> | 2014-03-18 12:31:04 +0100 |
commit | ed9c79e1ea5c0f74b25b5ec978be1e1a3672c1d1 (patch) | |
tree | f01461267c50ab3ebcbf136cd84fd5629973931c /gcc/predict.c | |
parent | e33da4a1131dd198a2fc13b1a839a06397763855 (diff) | |
download | gcc-ed9c79e1ea5c0f74b25b5ec978be1e1a3672c1d1.zip gcc-ed9c79e1ea5c0f74b25b5ec978be1e1a3672c1d1.tar.gz gcc-ed9c79e1ea5c0f74b25b5ec978be1e1a3672c1d1.tar.bz2 |
re PR ipa/58721 (The subroutine perdida is no longer inlined in fatigue.f90)
PR ipa/58721
gcc/
* internal-fn.c: Include diagnostic-core.h.
(expand_BUILTIN_EXPECT): New function.
* gimplify.c (gimplify_call_expr): Use false instead of FALSE.
(gimplify_modify_expr): Gimplify 3 argument __builtin_expect into
IFN_BUILTIN_EXPECT call instead of __builtin_expect builtin call.
* ipa-inline-analysis.c (find_foldable_builtin_expect): Handle
IFN_BUILTIN_EXPECT.
* predict.c (expr_expected_value_1): Handle IFN_BUILTIN_EXPECT.
Revert 3 argument __builtin_expect code.
(strip_predict_hints): Handle IFN_BUILTIN_EXPECT.
* gimple-fold.c (gimple_fold_call): Likewise.
* tree.h (fold_builtin_expect): New prototype.
* builtins.c (build_builtin_expect_predicate): Add predictor
argument, if non-NULL, create 3 argument __builtin_expect.
(fold_builtin_expect): No longer static. Add ARG2 argument,
pass it through to build_builtin_expect_predicate.
(fold_builtin_2): Adjust caller.
(fold_builtin_3): Handle BUILT_IN_EXPECT.
* internal-fn.def (BUILTIN_EXPECT): New.
gcc/fortran/
* trans.c (gfc_unlikely, gfc_likely): Don't add __builtin_expect
if !optimize.
2014-03-18 Tobias Burnus <burnus@net-b.de>
PR ipa/58721
gcc/
* predict.def (PRED_FORTRAN_OVERFLOW, PRED_FORTRAN_FAIL_ALLOC,
PRED_FORTRAN_FAIL_IO, PRED_FORTRAN_WARN_ONCE, PRED_FORTRAN_SIZE_ZERO,
PRED_FORTRAN_INVALID_BOUND, PRED_FORTRAN_ABSENT_DUMMY): Add.
gcc/fortran/
* trans.h (gfc_unlikely, gfc_likely): Add predictor as argument.
(gfc_trans_io_runtime_check): Remove.
* trans-io.c (gfc_trans_io_runtime_check): Make static; add has_iostat
as argument, add predictor to block.
(set_parameter_value, gfc_trans_open, gfc_trans_close, build_filepos,
gfc_trans_inquire, gfc_trans_wait, build_dt): Update calls.
* trans.c (gfc_unlikely, gfc_likely): Add predictor as argument.
(gfc_trans_runtime_check, gfc_allocate_using_malloc,
gfc_allocate_allocatable, gfc_deallocate_with_status): Set explicitly
branch predictor.
* trans-expr.c (gfc_conv_procedure_call): Ditto.
* trans-stmt.c (gfc_trans_allocate): Ditto.
* trans-array.c (gfc_array_init_size, gfc_array_allocate): Ditto.
2014-03-18 Jan Hubicka <hubicka@ucw.cz>
PR ipa/58721
gcc/
* predict.c (combine_predictions_for_bb): Fix up formatting.
(expr_expected_value_1, expr_expected_value): Add predictor argument,
fill what it points to if non-NULL.
(tree_predict_by_opcode): Adjust caller, use the predictor.
* predict.def (PRED_COMPARE_AND_SWAP): Add.
From-SVN: r208641
Diffstat (limited to 'gcc/predict.c')
-rw-r--r-- | gcc/predict.c | 100 |
1 files changed, 76 insertions, 24 deletions
diff --git a/gcc/predict.c b/gcc/predict.c index db5eed9..249433f 100644 --- a/gcc/predict.c +++ b/gcc/predict.c @@ -956,7 +956,8 @@ combine_predictions_for_bb (basic_block bb) struct edge_prediction *pred2; int prob = probability; - for (pred2 = (struct edge_prediction *) *preds; pred2; pred2 = pred2->ep_next) + for (pred2 = (struct edge_prediction *) *preds; + pred2; pred2 = pred2->ep_next) if (pred2 != pred && pred2->ep_predictor == pred->ep_predictor) { int probability2 = pred->ep_probability; @@ -1788,16 +1789,19 @@ guess_outgoing_edge_probabilities (basic_block bb) combine_predictions_for_insn (BB_END (bb), bb); } -static tree expr_expected_value (tree, bitmap); +static tree expr_expected_value (tree, bitmap, enum br_predictor *predictor); /* Helper function for expr_expected_value. */ static tree expr_expected_value_1 (tree type, tree op0, enum tree_code code, - tree op1, bitmap visited) + tree op1, bitmap visited, enum br_predictor *predictor) { gimple def; + if (predictor) + *predictor = PRED_UNCONDITIONAL; + if (get_gimple_rhs_class (code) == GIMPLE_SINGLE_RHS) { if (TREE_CONSTANT (op0)) @@ -1822,6 +1826,7 @@ expr_expected_value_1 (tree type, tree op0, enum tree_code code, for (i = 0; i < n; i++) { tree arg = PHI_ARG_DEF (def, i); + enum br_predictor predictor2; /* If this PHI has itself as an argument, we cannot determine the string length of this argument. However, @@ -1832,7 +1837,12 @@ expr_expected_value_1 (tree type, tree op0, enum tree_code code, if (arg == PHI_RESULT (def)) continue; - new_val = expr_expected_value (arg, visited); + new_val = expr_expected_value (arg, visited, &predictor2); + + /* It is difficult to combine value predictors. Simply assume + that later predictor is weaker and take its prediction. */ + if (predictor && *predictor < predictor2) + *predictor = predictor2; if (!new_val) return NULL; if (!val) @@ -1851,14 +1861,34 @@ expr_expected_value_1 (tree type, tree op0, enum tree_code code, gimple_assign_rhs1 (def), gimple_assign_rhs_code (def), gimple_assign_rhs2 (def), - visited); + visited, predictor); } if (is_gimple_call (def)) { tree decl = gimple_call_fndecl (def); if (!decl) - return NULL; + { + if (gimple_call_internal_p (def) + && gimple_call_internal_fn (def) == IFN_BUILTIN_EXPECT) + { + gcc_assert (gimple_call_num_args (def) == 3); + tree val = gimple_call_arg (def, 0); + if (TREE_CONSTANT (val)) + return val; + if (predictor) + { + *predictor = PRED_BUILTIN_EXPECT; + tree val2 = gimple_call_arg (def, 2); + gcc_assert (TREE_CODE (val2) == INTEGER_CST + && tree_fits_uhwi_p (val2) + && tree_to_uhwi (val2) < END_PREDICTORS); + *predictor = (enum br_predictor) tree_to_uhwi (val2); + } + return gimple_call_arg (def, 1); + } + return NULL; + } if (DECL_BUILT_IN_CLASS (decl) == BUILT_IN_NORMAL) switch (DECL_FUNCTION_CODE (decl)) { @@ -1870,6 +1900,8 @@ expr_expected_value_1 (tree type, tree op0, enum tree_code code, val = gimple_call_arg (def, 0); if (TREE_CONSTANT (val)) return val; + if (predictor) + *predictor = PRED_BUILTIN_EXPECT; return gimple_call_arg (def, 1); } @@ -1888,6 +1920,8 @@ expr_expected_value_1 (tree type, tree op0, enum tree_code code, case BUILT_IN_ATOMIC_COMPARE_EXCHANGE_16: /* Assume that any given atomic operation has low contention, and thus the compare-and-swap operation succeeds. */ + if (predictor) + *predictor = PRED_COMPARE_AND_SWAP; return boolean_true_node; } } @@ -1898,10 +1932,13 @@ expr_expected_value_1 (tree type, tree op0, enum tree_code code, if (get_gimple_rhs_class (code) == GIMPLE_BINARY_RHS) { tree res; - op0 = expr_expected_value (op0, visited); + enum br_predictor predictor2; + op0 = expr_expected_value (op0, visited, predictor); if (!op0) return NULL; - op1 = expr_expected_value (op1, visited); + op1 = expr_expected_value (op1, visited, &predictor2); + if (predictor && *predictor < predictor2) + *predictor = predictor2; if (!op1) return NULL; res = fold_build2 (code, type, op0, op1); @@ -1912,7 +1949,7 @@ expr_expected_value_1 (tree type, tree op0, enum tree_code code, if (get_gimple_rhs_class (code) == GIMPLE_UNARY_RHS) { tree res; - op0 = expr_expected_value (op0, visited); + op0 = expr_expected_value (op0, visited, predictor); if (!op0) return NULL; res = fold_build1 (code, type, op0); @@ -1932,17 +1969,22 @@ expr_expected_value_1 (tree type, tree op0, enum tree_code code, implementation. */ static tree -expr_expected_value (tree expr, bitmap visited) +expr_expected_value (tree expr, bitmap visited, + enum br_predictor *predictor) { enum tree_code code; tree op0, op1; if (TREE_CONSTANT (expr)) - return expr; + { + if (predictor) + *predictor = PRED_UNCONDITIONAL; + return expr; + } extract_ops_from_tree (expr, &code, &op0, &op1); return expr_expected_value_1 (TREE_TYPE (expr), - op0, code, op1, visited); + op0, code, op1, visited, predictor); } @@ -1967,14 +2009,16 @@ strip_predict_hints (void) gsi_remove (&bi, true); continue; } - else if (gimple_code (stmt) == GIMPLE_CALL) + else if (is_gimple_call (stmt)) { tree fndecl = gimple_call_fndecl (stmt); - if (fndecl - && DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_NORMAL - && DECL_FUNCTION_CODE (fndecl) == BUILT_IN_EXPECT - && gimple_call_num_args (stmt) == 2) + if ((fndecl + && DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_NORMAL + && DECL_FUNCTION_CODE (fndecl) == BUILT_IN_EXPECT + && gimple_call_num_args (stmt) == 2) + || (gimple_call_internal_p (stmt) + && gimple_call_internal_fn (stmt) == IFN_BUILTIN_EXPECT)) { var = gimple_call_lhs (stmt); if (var) @@ -2008,6 +2052,7 @@ tree_predict_by_opcode (basic_block bb) enum tree_code cmp; bitmap visited; edge_iterator ei; + enum br_predictor predictor; if (!stmt || gimple_code (stmt) != GIMPLE_COND) return; @@ -2019,16 +2064,23 @@ tree_predict_by_opcode (basic_block bb) cmp = gimple_cond_code (stmt); type = TREE_TYPE (op0); visited = BITMAP_ALLOC (NULL); - val = expr_expected_value_1 (boolean_type_node, op0, cmp, op1, visited); + val = expr_expected_value_1 (boolean_type_node, op0, cmp, op1, visited, + &predictor); BITMAP_FREE (visited); - if (val) + if (val && TREE_CODE (val) == INTEGER_CST) { - int percent = PARAM_VALUE (BUILTIN_EXPECT_PROBABILITY); + if (predictor == PRED_BUILTIN_EXPECT) + { + int percent = PARAM_VALUE (BUILTIN_EXPECT_PROBABILITY); - gcc_assert (percent >= 0 && percent <= 100); - if (integer_zerop (val)) - percent = 100 - percent; - predict_edge (then_edge, PRED_BUILTIN_EXPECT, HITRATE (percent)); + gcc_assert (percent >= 0 && percent <= 100); + if (integer_zerop (val)) + percent = 100 - percent; + predict_edge (then_edge, PRED_BUILTIN_EXPECT, HITRATE (percent)); + } + else + predict_edge (then_edge, predictor, + integer_zerop (val) ? NOT_TAKEN : TAKEN); } /* Try "pointer heuristic." A comparison ptr == 0 is predicted as false. |