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 | |
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
-rw-r--r-- | gcc/ChangeLog | 39 | ||||
-rw-r--r-- | gcc/builtins.c | 20 | ||||
-rw-r--r-- | gcc/fortran/ChangeLog | 23 | ||||
-rw-r--r-- | gcc/fortran/trans-array.c | 18 | ||||
-rw-r--r-- | gcc/fortran/trans-expr.c | 2 | ||||
-rw-r--r-- | gcc/fortran/trans-intrinsic.c | 3 | ||||
-rw-r--r-- | gcc/fortran/trans-io.c | 55 | ||||
-rw-r--r-- | gcc/fortran/trans-stmt.c | 8 | ||||
-rw-r--r-- | gcc/fortran/trans.c | 80 | ||||
-rw-r--r-- | gcc/fortran/trans.h | 7 | ||||
-rw-r--r-- | gcc/gimple-fold.c | 14 | ||||
-rw-r--r-- | gcc/gimplify.c | 18 | ||||
-rw-r--r-- | gcc/internal-fn.c | 18 | ||||
-rw-r--r-- | gcc/internal-fn.def | 1 | ||||
-rw-r--r-- | gcc/ipa-inline-analysis.c | 5 | ||||
-rw-r--r-- | gcc/predict.c | 100 | ||||
-rw-r--r-- | gcc/predict.def | 43 | ||||
-rw-r--r-- | gcc/tree.h | 1 |
18 files changed, 354 insertions, 101 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 681ec52..85060d1 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,42 @@ +2014-03-18 Jakub Jelinek <jakub@redhat.com> + + PR ipa/58721 + * 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. + +2014-03-18 Tobias Burnus <burnus@net-b.de> + + PR ipa/58721 + * 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. + +2014-03-18 Jan Hubicka <hubicka@ucw.cz> + + PR ipa/58721 + * 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. + 2014-03-18 Eric Botcazou <ebotcazou@adacore.com> * config/sparc/sparc.c (sparc_do_work_around_errata): Speed up and use diff --git a/gcc/builtins.c b/gcc/builtins.c index e4846c8..dd57b1a 100644 --- a/gcc/builtins.c +++ b/gcc/builtins.c @@ -140,7 +140,6 @@ static rtx expand_builtin_frame_address (tree, tree); static tree stabilize_va_list_loc (location_t, tree, int); static rtx expand_builtin_expect (tree, rtx); static tree fold_builtin_constant_p (tree); -static tree fold_builtin_expect (location_t, tree, tree); static tree fold_builtin_classify_type (tree); static tree fold_builtin_strlen (location_t, tree, tree); static tree fold_builtin_inf (location_t, tree, int); @@ -6978,7 +6977,8 @@ fold_builtin_constant_p (tree arg) return it as a truthvalue. */ static tree -build_builtin_expect_predicate (location_t loc, tree pred, tree expected) +build_builtin_expect_predicate (location_t loc, tree pred, tree expected, + tree predictor) { tree fn, arg_types, pred_type, expected_type, call_expr, ret_type; @@ -6990,7 +6990,8 @@ build_builtin_expect_predicate (location_t loc, tree pred, tree expected) pred = fold_convert_loc (loc, pred_type, pred); expected = fold_convert_loc (loc, expected_type, expected); - call_expr = build_call_expr_loc (loc, fn, 2, pred, expected); + call_expr = build_call_expr_loc (loc, fn, predictor ? 3 : 2, pred, expected, + predictor); return build2 (NE_EXPR, TREE_TYPE (pred), call_expr, build_int_cst (ret_type, 0)); @@ -6999,8 +7000,8 @@ build_builtin_expect_predicate (location_t loc, tree pred, tree expected) /* Fold a call to builtin_expect with arguments ARG0 and ARG1. Return NULL_TREE if no simplification is possible. */ -static tree -fold_builtin_expect (location_t loc, tree arg0, tree arg1) +tree +fold_builtin_expect (location_t loc, tree arg0, tree arg1, tree arg2) { tree inner, fndecl, inner_arg0; enum tree_code code; @@ -7035,8 +7036,8 @@ fold_builtin_expect (location_t loc, tree arg0, tree arg1) tree op0 = TREE_OPERAND (inner, 0); tree op1 = TREE_OPERAND (inner, 1); - op0 = build_builtin_expect_predicate (loc, op0, arg1); - op1 = build_builtin_expect_predicate (loc, op1, arg1); + op0 = build_builtin_expect_predicate (loc, op0, arg1, arg2); + op1 = build_builtin_expect_predicate (loc, op1, arg1, arg2); inner = build2 (code, TREE_TYPE (inner), op0, op1); return fold_convert_loc (loc, TREE_TYPE (arg0), inner); @@ -10852,7 +10853,7 @@ fold_builtin_2 (location_t loc, tree fndecl, tree arg0, tree arg1, bool ignore) return fold_builtin_strpbrk (loc, arg0, arg1, type); case BUILT_IN_EXPECT: - return fold_builtin_expect (loc, arg0, arg1); + return fold_builtin_expect (loc, arg0, arg1, NULL_TREE); CASE_FLT_FN (BUILT_IN_POW): return fold_builtin_pow (loc, fndecl, arg0, arg1, type); @@ -11032,6 +11033,9 @@ fold_builtin_3 (location_t loc, tree fndecl, return fold_builtin_fprintf (loc, fndecl, arg0, arg2, NULL_TREE, ignore, fcode); + case BUILT_IN_EXPECT: + return fold_builtin_expect (loc, arg0, arg1, arg2); + default: break; } diff --git a/gcc/fortran/ChangeLog b/gcc/fortran/ChangeLog index ce4063e..78dbc5d 100644 --- a/gcc/fortran/ChangeLog +++ b/gcc/fortran/ChangeLog @@ -1,3 +1,26 @@ +2014-03-18 Jakub Jelinek <jakub@redhat.com> + + PR ipa/58721 + * 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 + * 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-15 Janus Weil <janus@gcc.gnu.org> PR fortran/55207 diff --git a/gcc/fortran/trans-array.c b/gcc/fortran/trans-array.c index dee422c..8c4afb0 100644 --- a/gcc/fortran/trans-array.c +++ b/gcc/fortran/trans-array.c @@ -4993,12 +4993,14 @@ gfc_array_init_size (tree descriptor, int rank, int corank, tree * poffset, TYPE_MAX_VALUE (gfc_array_index_type)), size); cond = gfc_unlikely (fold_build2_loc (input_location, LT_EXPR, - boolean_type_node, tmp, stride)); + boolean_type_node, tmp, stride), + PRED_FORTRAN_OVERFLOW); tmp = fold_build3_loc (input_location, COND_EXPR, integer_type_node, cond, integer_one_node, integer_zero_node); cond = gfc_unlikely (fold_build2_loc (input_location, EQ_EXPR, boolean_type_node, size, - gfc_index_zero_node)); + gfc_index_zero_node), + PRED_FORTRAN_SIZE_ZERO); tmp = fold_build3_loc (input_location, COND_EXPR, integer_type_node, cond, integer_zero_node, tmp); tmp = fold_build2_loc (input_location, PLUS_EXPR, integer_type_node, @@ -5095,12 +5097,14 @@ gfc_array_init_size (tree descriptor, int rank, int corank, tree * poffset, size_type_node, TYPE_MAX_VALUE (size_type_node), element_size); cond = gfc_unlikely (fold_build2_loc (input_location, LT_EXPR, - boolean_type_node, tmp, stride)); + boolean_type_node, tmp, stride), + PRED_FORTRAN_OVERFLOW); tmp = fold_build3_loc (input_location, COND_EXPR, integer_type_node, cond, integer_one_node, integer_zero_node); cond = gfc_unlikely (fold_build2_loc (input_location, EQ_EXPR, boolean_type_node, element_size, - build_int_cst (size_type_node, 0))); + build_int_cst (size_type_node, 0)), + PRED_FORTRAN_SIZE_ZERO); tmp = fold_build3_loc (input_location, COND_EXPR, integer_type_node, cond, integer_zero_node, tmp); tmp = fold_build2_loc (input_location, PLUS_EXPR, integer_type_node, @@ -5282,7 +5286,8 @@ gfc_array_allocate (gfc_se * se, gfc_expr * expr, tree status, tree errmsg, if (dimension) { cond = gfc_unlikely (fold_build2_loc (input_location, NE_EXPR, - boolean_type_node, var_overflow, integer_zero_node)); + boolean_type_node, var_overflow, integer_zero_node), + PRED_FORTRAN_OVERFLOW); tmp = fold_build3_loc (input_location, COND_EXPR, void_type_node, cond, error, gfc_finish_block (&elseblock)); } @@ -5303,7 +5308,8 @@ gfc_array_allocate (gfc_se * se, gfc_expr * expr, tree status, tree errmsg, build_int_cst (TREE_TYPE (status), 0)); gfc_add_expr_to_block (&se->pre, fold_build3_loc (input_location, COND_EXPR, void_type_node, - gfc_likely (cond), set_descriptor, + gfc_likely (cond, PRED_FORTRAN_FAIL_ALLOC), + set_descriptor, build_empty_stmt (input_location))); } else diff --git a/gcc/fortran/trans-expr.c b/gcc/fortran/trans-expr.c index 269fcc5..f5350bb 100644 --- a/gcc/fortran/trans-expr.c +++ b/gcc/fortran/trans-expr.c @@ -4099,7 +4099,7 @@ gfc_conv_procedure_call (gfc_se * se, gfc_symbol * sym, parmse.expr = fold_build3_loc (input_location, COND_EXPR, TREE_TYPE (parmse.expr), - gfc_unlikely (tmp), + gfc_unlikely (tmp, PRED_FORTRAN_ABSENT_DUMMY), fold_convert (TREE_TYPE (parmse.expr), null_pointer_node), parmse.expr); diff --git a/gcc/fortran/trans-intrinsic.c b/gcc/fortran/trans-intrinsic.c index 75bd20a..e21d52f 100644 --- a/gcc/fortran/trans-intrinsic.c +++ b/gcc/fortran/trans-intrinsic.c @@ -1196,8 +1196,7 @@ trans_image_index (gfc_se * se, gfc_expr *expr) boolean_type_node, invalid_bound, cond); } - invalid_bound = gfc_unlikely (invalid_bound); - + invalid_bound = gfc_unlikely (invalid_bound, PRED_FORTRAN_INVALID_BOUND); /* See Fortran 2008, C.10 for the following algorithm. */ diff --git a/gcc/fortran/trans-io.c b/gcc/fortran/trans-io.c index 853e77d..d151598 100644 --- a/gcc/fortran/trans-io.c +++ b/gcc/fortran/trans-io.c @@ -230,9 +230,10 @@ gfc_build_st_parameter (enum ioparam_type ptype, tree *types) Therefore, the code to set these flags must be generated before this function is used. */ -void -gfc_trans_io_runtime_check (tree cond, tree var, int error_code, - const char * msgid, stmtblock_t * pblock) +static void +gfc_trans_io_runtime_check (bool has_iostat, tree cond, tree var, + int error_code, const char * msgid, + stmtblock_t * pblock) { stmtblock_t block; tree body; @@ -246,6 +247,13 @@ gfc_trans_io_runtime_check (tree cond, tree var, int error_code, /* The code to generate the error. */ gfc_start_block (&block); + if (has_iostat) + gfc_add_expr_to_block (&block, build_predict_expr (PRED_FORTRAN_FAIL_IO, + NOT_TAKEN)); + else + gfc_add_expr_to_block (&block, build_predict_expr (PRED_NORETURN, + NOT_TAKEN)); + arg1 = gfc_build_addr_expr (NULL_TREE, var); arg2 = build_int_cst (integer_type_node, error_code), @@ -268,7 +276,6 @@ gfc_trans_io_runtime_check (tree cond, tree var, int error_code, } else { - cond = gfc_unlikely (cond); tmp = build3_v (COND_EXPR, cond, body, build_empty_stmt (input_location)); gfc_add_expr_to_block (pblock, tmp); } @@ -494,8 +501,8 @@ set_parameter_const (stmtblock_t *block, tree var, enum iofield type, st_parameter_XXX structure. This is a pass by value. */ static unsigned int -set_parameter_value (stmtblock_t *block, tree var, enum iofield type, - gfc_expr *e) +set_parameter_value (stmtblock_t *block, bool has_iostat, tree var, + enum iofield type, gfc_expr *e) { gfc_se se; tree tmp; @@ -520,18 +527,18 @@ set_parameter_value (stmtblock_t *block, tree var, enum iofield type, cond = fold_build2_loc (input_location, LT_EXPR, boolean_type_node, se.expr, fold_convert (TREE_TYPE (se.expr), val)); - gfc_trans_io_runtime_check (cond, var, LIBERROR_BAD_UNIT, - "Unit number in I/O statement too small", - &se.pre); + gfc_trans_io_runtime_check (has_iostat, cond, var, LIBERROR_BAD_UNIT, + "Unit number in I/O statement too small", + &se.pre); /* UNIT numbers should be less than the max. */ val = gfc_conv_mpz_to_tree (gfc_integer_kinds[i].huge, 4); cond = fold_build2_loc (input_location, GT_EXPR, boolean_type_node, se.expr, fold_convert (TREE_TYPE (se.expr), val)); - gfc_trans_io_runtime_check (cond, var, LIBERROR_BAD_UNIT, - "Unit number in I/O statement too large", - &se.pre); + gfc_trans_io_runtime_check (has_iostat, cond, var, LIBERROR_BAD_UNIT, + "Unit number in I/O statement too large", + &se.pre); } @@ -960,7 +967,8 @@ gfc_trans_open (gfc_code * code) mask |= set_string (&block, &post_block, var, IOPARM_open_form, p->form); if (p->recl) - mask |= set_parameter_value (&block, var, IOPARM_open_recl_in, p->recl); + mask |= set_parameter_value (&block, p->iostat, var, IOPARM_open_recl_in, + p->recl); if (p->blank) mask |= set_string (&block, &post_block, var, IOPARM_open_blank, @@ -1010,7 +1018,7 @@ gfc_trans_open (gfc_code * code) set_parameter_const (&block, var, IOPARM_common_flags, mask); if (p->unit) - set_parameter_value (&block, var, IOPARM_common_unit, p->unit); + set_parameter_value (&block, p->iostat, var, IOPARM_common_unit, p->unit); else set_parameter_const (&block, var, IOPARM_common_unit, 0); @@ -1063,7 +1071,7 @@ gfc_trans_close (gfc_code * code) set_parameter_const (&block, var, IOPARM_common_flags, mask); if (p->unit) - set_parameter_value (&block, var, IOPARM_common_unit, p->unit); + set_parameter_value (&block, p->iostat, var, IOPARM_common_unit, p->unit); else set_parameter_const (&block, var, IOPARM_common_unit, 0); @@ -1114,7 +1122,7 @@ build_filepos (tree function, gfc_code * code) set_parameter_const (&block, var, IOPARM_common_flags, mask); if (p->unit) - set_parameter_value (&block, var, IOPARM_common_unit, p->unit); + set_parameter_value (&block, p->iostat, var, IOPARM_common_unit, p->unit); else set_parameter_const (&block, var, IOPARM_common_unit, 0); @@ -1375,7 +1383,7 @@ gfc_trans_inquire (gfc_code * code) set_parameter_const (&block, var, IOPARM_common_flags, mask); if (p->unit) - set_parameter_value (&block, var, IOPARM_common_unit, p->unit); + set_parameter_value (&block, p->iostat, var, IOPARM_common_unit, p->unit); else set_parameter_const (&block, var, IOPARM_common_unit, 0); @@ -1422,12 +1430,12 @@ gfc_trans_wait (gfc_code * code) mask |= IOPARM_common_err; if (p->id) - mask |= set_parameter_value (&block, var, IOPARM_wait_id, p->id); + mask |= set_parameter_value (&block, p->iostat, var, IOPARM_wait_id, p->id); set_parameter_const (&block, var, IOPARM_common_flags, mask); if (p->unit) - set_parameter_value (&block, var, IOPARM_common_unit, p->unit); + set_parameter_value (&block, p->iostat, var, IOPARM_common_unit, p->unit); tmp = gfc_build_addr_expr (NULL_TREE, var); tmp = build_call_expr_loc (input_location, @@ -1718,7 +1726,8 @@ build_dt (tree function, gfc_code * code) IOPARM_dt_id, dt->id); if (dt->pos) - mask |= set_parameter_value (&block, var, IOPARM_dt_pos, dt->pos); + mask |= set_parameter_value (&block, dt->iostat, var, IOPARM_dt_pos, + dt->pos); if (dt->asynchronous) mask |= set_string (&block, &post_block, var, IOPARM_dt_asynchronous, @@ -1749,7 +1758,8 @@ build_dt (tree function, gfc_code * code) dt->sign); if (dt->rec) - mask |= set_parameter_value (&block, var, IOPARM_dt_rec, dt->rec); + mask |= set_parameter_value (&block, dt->iostat, var, IOPARM_dt_rec, + dt->rec); if (dt->advance) mask |= set_string (&block, &post_block, var, IOPARM_dt_advance, @@ -1801,7 +1811,8 @@ build_dt (tree function, gfc_code * code) set_parameter_const (&block, var, IOPARM_common_flags, mask); if (dt->io_unit && dt->io_unit->ts.type == BT_INTEGER) - set_parameter_value (&block, var, IOPARM_common_unit, dt->io_unit); + set_parameter_value (&block, dt->iostat, var, IOPARM_common_unit, + dt->io_unit); } else set_parameter_const (&block, var, IOPARM_common_flags, mask); diff --git a/gcc/fortran/trans-stmt.c b/gcc/fortran/trans-stmt.c index c7ff7a8..1a9068c 100644 --- a/gcc/fortran/trans-stmt.c +++ b/gcc/fortran/trans-stmt.c @@ -5107,8 +5107,8 @@ gfc_trans_allocate (gfc_code * code) boolean_type_node, stat, build_int_cst (TREE_TYPE (stat), 0)); tmp = fold_build3_loc (input_location, COND_EXPR, void_type_node, - gfc_unlikely (parm), tmp, - build_empty_stmt (input_location)); + gfc_unlikely (parm, PRED_FORTRAN_FAIL_ALLOC), + tmp, build_empty_stmt (input_location)); gfc_add_expr_to_block (&block, tmp); } @@ -5501,7 +5501,7 @@ gfc_trans_deallocate (gfc_code *code) cond = fold_build2_loc (input_location, NE_EXPR, boolean_type_node, stat, build_int_cst (TREE_TYPE (stat), 0)); tmp = fold_build3_loc (input_location, COND_EXPR, void_type_node, - gfc_unlikely (cond), + gfc_unlikely (cond, PRED_FORTRAN_FAIL_ALLOC), build1_v (GOTO_EXPR, label_errmsg), build_empty_stmt (input_location)); gfc_add_expr_to_block (&se.pre, tmp); @@ -5541,7 +5541,7 @@ gfc_trans_deallocate (gfc_code *code) cond = fold_build2_loc (input_location, NE_EXPR, boolean_type_node, stat, build_int_cst (TREE_TYPE (stat), 0)); tmp = fold_build3_loc (input_location, COND_EXPR, void_type_node, - gfc_unlikely (cond), tmp, + gfc_unlikely (cond, PRED_FORTRAN_FAIL_ALLOC), tmp, build_empty_stmt (input_location)); gfc_add_expr_to_block (&block, tmp); diff --git a/gcc/fortran/trans.c b/gcc/fortran/trans.c index 073e34f..5961c26 100644 --- a/gcc/fortran/trans.c +++ b/gcc/fortran/trans.c @@ -501,6 +501,11 @@ gfc_trans_runtime_check (bool error, bool once, tree cond, stmtblock_t * pblock, gfc_start_block (&block); + /* For error, runtime_error_at already implies PRED_NORETURN. */ + if (!error && once) + gfc_add_expr_to_block (&block, build_predict_expr (PRED_FORTRAN_WARN_ONCE, + NOT_TAKEN)); + /* The code to generate the error. */ va_start (ap, msgid); gfc_add_expr_to_block (&block, @@ -519,14 +524,12 @@ gfc_trans_runtime_check (bool error, bool once, tree cond, stmtblock_t * pblock, } else { - /* Tell the compiler that this isn't likely. */ if (once) cond = fold_build2_loc (where->lb->location, TRUTH_AND_EXPR, long_integer_type_node, tmpvar, cond); else cond = fold_convert (long_integer_type_node, cond); - cond = gfc_unlikely (cond); tmp = fold_build3_loc (where->lb->location, COND_EXPR, void_type_node, cond, body, build_empty_stmt (where->lb->location)); @@ -616,7 +619,8 @@ void gfc_allocate_using_malloc (stmtblock_t * block, tree pointer, tree size, tree status) { - tree tmp, on_error, error_cond; + tree tmp, error_cond; + stmtblock_t on_error; tree status_type = status ? TREE_TYPE (status) : NULL_TREE; /* Evaluate size only once, and make sure it has the right type. */ @@ -640,20 +644,31 @@ gfc_allocate_using_malloc (stmtblock_t * block, tree pointer, build_int_cst (size_type_node, 1))))); /* What to do in case of error. */ + gfc_start_block (&on_error); if (status != NULL_TREE) - on_error = fold_build2_loc (input_location, MODIFY_EXPR, status_type, - status, build_int_cst (status_type, LIBERROR_ALLOCATION)); + { + gfc_add_expr_to_block (&on_error, + build_predict_expr (PRED_FORTRAN_FAIL_ALLOC, + NOT_TAKEN)); + tmp = fold_build2_loc (input_location, MODIFY_EXPR, status_type, status, + build_int_cst (status_type, LIBERROR_ALLOCATION)); + gfc_add_expr_to_block (&on_error, tmp); + } else - on_error = build_call_expr_loc (input_location, gfor_fndecl_os_error, 1, + { + /* Here, os_error already implies PRED_NORETURN. */ + tmp = build_call_expr_loc (input_location, gfor_fndecl_os_error, 1, gfc_build_addr_expr (pchar_type_node, gfc_build_localized_cstring_const - ("Allocation would exceed memory limit"))); + ("Allocation would exceed memory limit"))); + gfc_add_expr_to_block (&on_error, tmp); + } error_cond = fold_build2_loc (input_location, EQ_EXPR, boolean_type_node, pointer, build_int_cst (prvoid_type_node, 0)); tmp = fold_build3_loc (input_location, COND_EXPR, void_type_node, - gfc_unlikely (error_cond), on_error, + error_cond, gfc_finish_block (&on_error), build_empty_stmt (input_location)); gfc_add_expr_to_block (block, tmp); @@ -750,7 +765,8 @@ gfc_allocate_allocatable (stmtblock_t * block, tree mem, tree size, tree token, null_mem = gfc_unlikely (fold_build2_loc (input_location, NE_EXPR, boolean_type_node, mem, - build_int_cst (type, 0))); + build_int_cst (type, 0)), + PRED_FORTRAN_FAIL_ALLOC); /* If mem is NULL, we call gfc_allocate_using_malloc or gfc_allocate_using_lib. */ @@ -770,8 +786,8 @@ gfc_allocate_allocatable (stmtblock_t * block, tree mem, tree size, tree token, cond = fold_build2_loc (input_location, NE_EXPR, boolean_type_node, status, build_zero_cst (TREE_TYPE (status))); tmp = fold_build3_loc (input_location, COND_EXPR, void_type_node, - gfc_unlikely (cond), tmp, - build_empty_stmt (input_location)); + gfc_unlikely (cond, PRED_FORTRAN_FAIL_ALLOC), + tmp, build_empty_stmt (input_location)); gfc_add_expr_to_block (&alloc_block, tmp); } } @@ -1268,8 +1284,8 @@ gfc_deallocate_with_status (tree pointer, tree status, tree errmsg, status_type, status), build_int_cst (status_type, 0)); tmp = fold_build3_loc (input_location, COND_EXPR, void_type_node, - gfc_unlikely (cond2), tmp, - build_empty_stmt (input_location)); + gfc_unlikely (cond2, PRED_FORTRAN_FAIL_ALLOC), + tmp, build_empty_stmt (input_location)); gfc_add_expr_to_block (&non_null, tmp); } } @@ -1327,8 +1343,8 @@ gfc_deallocate_with_status (tree pointer, tree status, tree errmsg, cond2 = fold_build2_loc (input_location, NE_EXPR, boolean_type_node, stat, build_zero_cst (TREE_TYPE (stat))); tmp = fold_build3_loc (input_location, COND_EXPR, void_type_node, - gfc_unlikely (cond2), tmp, - build_empty_stmt (input_location)); + gfc_unlikely (cond2, PRED_FORTRAN_FAIL_ALLOC), + tmp, build_empty_stmt (input_location)); gfc_add_expr_to_block (&non_null, tmp); } } @@ -2015,15 +2031,20 @@ gfc_finish_wrapped_block (gfc_wrapped_block* block) /* Helper function for marking a boolean expression tree as unlikely. */ tree -gfc_unlikely (tree cond) +gfc_unlikely (tree cond, enum br_predictor predictor) { tree tmp; - cond = fold_convert (long_integer_type_node, cond); - tmp = build_zero_cst (long_integer_type_node); - cond = build_call_expr_loc (input_location, - builtin_decl_explicit (BUILT_IN_EXPECT), - 2, cond, tmp); + if (optimize) + { + cond = fold_convert (long_integer_type_node, cond); + tmp = build_zero_cst (long_integer_type_node); + cond = build_call_expr_loc (input_location, + builtin_decl_explicit (BUILT_IN_EXPECT), + 3, cond, tmp, + build_int_cst (integer_type_node, + predictor)); + } cond = fold_convert (boolean_type_node, cond); return cond; } @@ -2032,15 +2053,20 @@ gfc_unlikely (tree cond) /* Helper function for marking a boolean expression tree as likely. */ tree -gfc_likely (tree cond) +gfc_likely (tree cond, enum br_predictor predictor) { tree tmp; - cond = fold_convert (long_integer_type_node, cond); - tmp = build_one_cst (long_integer_type_node); - cond = build_call_expr_loc (input_location, - builtin_decl_explicit (BUILT_IN_EXPECT), - 2, cond, tmp); + if (optimize) + { + cond = fold_convert (long_integer_type_node, cond); + tmp = build_one_cst (long_integer_type_node); + cond = build_call_expr_loc (input_location, + builtin_decl_explicit (BUILT_IN_EXPECT), + 3, cond, tmp, + build_int_cst (integer_type_node, + predictor)); + } cond = fold_convert (boolean_type_node, cond); return cond; } diff --git a/gcc/fortran/trans.h b/gcc/fortran/trans.h index 5fb0cbf..4ae68c6 100644 --- a/gcc/fortran/trans.h +++ b/gcc/fortran/trans.h @@ -21,6 +21,8 @@ along with GCC; see the file COPYING3. If not see #ifndef GFC_TRANS_H #define GFC_TRANS_H +#include "predict.h" /* For enum br_predictor and PRED_*. */ + /* Mangled symbols take the form __module__name. */ #define GFC_MAX_MANGLED_SYMBOL_LEN (GFC_MAX_SYMBOL_LEN*2+4) @@ -580,8 +582,8 @@ void gfc_generate_constructors (void); bool get_array_ctor_strlen (stmtblock_t *, gfc_constructor_base, tree *); /* Mark a condition as likely or unlikely. */ -tree gfc_likely (tree); -tree gfc_unlikely (tree); +tree gfc_likely (tree, enum br_predictor); +tree gfc_unlikely (tree, enum br_predictor); /* Return the string length of a deferred character length component. */ bool gfc_deferred_strlen (gfc_component *, tree *); @@ -630,7 +632,6 @@ tree gfc_trans_pointer_assignment (gfc_expr *, gfc_expr *); /* Initialize function decls for library functions. */ void gfc_build_intrinsic_lib_fndecls (void); /* Create function decls for IO library functions. */ -void gfc_trans_io_runtime_check (tree, tree, int, const char *, stmtblock_t *); void gfc_build_io_library_fndecls (void); /* Build a function decl for a library function. */ tree gfc_build_library_function_decl (tree, tree, int, ...); diff --git a/gcc/gimple-fold.c b/gcc/gimple-fold.c index 5de4445..eafdb2d 100644 --- a/gcc/gimple-fold.c +++ b/gcc/gimple-fold.c @@ -1181,6 +1181,20 @@ gimple_fold_call (gimple_stmt_iterator *gsi, bool inplace) else if (gimple_call_builtin_p (stmt, BUILT_IN_MD)) changed |= targetm.gimple_fold_builtin (gsi); } + else if (gimple_call_internal_p (stmt) + && gimple_call_internal_fn (stmt) == IFN_BUILTIN_EXPECT) + { + tree result = fold_builtin_expect (gimple_location (stmt), + gimple_call_arg (stmt, 0), + gimple_call_arg (stmt, 1), + gimple_call_arg (stmt, 2)); + if (result) + { + if (!update_call_from_tree (gsi, result)) + gimplify_and_update_call_from_tree (gsi, result); + changed = true; + } + } return changed; } diff --git a/gcc/gimplify.c b/gcc/gimplify.c index ff341d4..ad2178d 100644 --- a/gcc/gimplify.c +++ b/gcc/gimplify.c @@ -2215,7 +2215,7 @@ gimplify_call_expr (tree *expr_p, gimple_seq *pre_p, bool want_value) enum gimplify_status ret; int i, nargs; gimple call; - bool builtin_va_start_p = FALSE; + bool builtin_va_start_p = false; location_t loc = EXPR_LOCATION (*expr_p); gcc_assert (TREE_CODE (*expr_p) == CALL_EXPR); @@ -4566,8 +4566,20 @@ gimplify_modify_expr (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p, tree fnptrtype = TREE_TYPE (CALL_EXPR_FN (*from_p)); CALL_EXPR_FN (*from_p) = TREE_OPERAND (CALL_EXPR_FN (*from_p), 0); STRIP_USELESS_TYPE_CONVERSION (CALL_EXPR_FN (*from_p)); - assign = gimple_build_call_from_tree (*from_p); - gimple_call_set_fntype (assign, TREE_TYPE (fnptrtype)); + tree fndecl = get_callee_fndecl (*from_p); + if (fndecl + && DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_NORMAL + && DECL_FUNCTION_CODE (fndecl) == BUILT_IN_EXPECT + && call_expr_nargs (*from_p) == 3) + assign = gimple_build_call_internal (IFN_BUILTIN_EXPECT, 3, + CALL_EXPR_ARG (*from_p, 0), + CALL_EXPR_ARG (*from_p, 1), + CALL_EXPR_ARG (*from_p, 2)); + else + { + assign = gimple_build_call_from_tree (*from_p); + gimple_call_set_fntype (assign, TREE_TYPE (fnptrtype)); + } notice_special_calls (assign); if (!gimple_call_noreturn_p (assign)) gimple_call_set_lhs (assign, *to_p); diff --git a/gcc/internal-fn.c b/gcc/internal-fn.c index 568a96b..9926ec2 100644 --- a/gcc/internal-fn.c +++ b/gcc/internal-fn.c @@ -36,6 +36,7 @@ along with GCC; see the file COPYING3. If not see #include "predict.h" #include "stringpool.h" #include "tree-ssanames.h" +#include "diagnostic-core.h" /* The names of each internal function, indexed by function number. */ const char *const internal_fn_name_array[] = { @@ -865,6 +866,23 @@ expand_ABNORMAL_DISPATCHER (gimple) { } +static void +expand_BUILTIN_EXPECT (gimple stmt) +{ + /* When guessing was done, the hints should be already stripped away. */ + gcc_assert (!flag_guess_branch_prob || optimize == 0 || seen_error ()); + + rtx target; + tree lhs = gimple_call_lhs (stmt); + if (lhs) + target = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE); + else + target = const0_rtx; + rtx val = expand_expr (gimple_call_arg (stmt, 0), target, VOIDmode, EXPAND_NORMAL); + if (lhs && val != target) + emit_move_insn (target, val); +} + /* Routines to expand each internal function, indexed by function number. Each routine has the prototype: diff --git a/gcc/internal-fn.def b/gcc/internal-fn.def index 379b352..31dc4c9 100644 --- a/gcc/internal-fn.def +++ b/gcc/internal-fn.def @@ -52,3 +52,4 @@ DEF_INTERNAL_FN (UBSAN_CHECK_ADD, ECF_CONST | ECF_LEAF | ECF_NOTHROW) DEF_INTERNAL_FN (UBSAN_CHECK_SUB, ECF_CONST | ECF_LEAF | ECF_NOTHROW) DEF_INTERNAL_FN (UBSAN_CHECK_MUL, ECF_CONST | ECF_LEAF | ECF_NOTHROW) DEF_INTERNAL_FN (ABNORMAL_DISPATCHER, ECF_NORETURN) +DEF_INTERNAL_FN (BUILTIN_EXPECT, ECF_CONST | ECF_LEAF | ECF_NOTHROW) diff --git a/gcc/ipa-inline-analysis.c b/gcc/ipa-inline-analysis.c index 6cd5dc1..98f42ef 100644 --- a/gcc/ipa-inline-analysis.c +++ b/gcc/ipa-inline-analysis.c @@ -2306,7 +2306,10 @@ find_foldable_builtin_expect (basic_block bb) for (bsi = gsi_start_bb (bb); !gsi_end_p (bsi); gsi_next (&bsi)) { gimple stmt = gsi_stmt (bsi); - if (gimple_call_builtin_p (stmt, BUILT_IN_EXPECT)) + if (gimple_call_builtin_p (stmt, BUILT_IN_EXPECT) + || (is_gimple_call (stmt) + && gimple_call_internal_p (stmt) + && gimple_call_internal_fn (stmt) == IFN_BUILTIN_EXPECT)) { tree var = gimple_call_lhs (stmt); tree arg = gimple_call_arg (stmt, 0); 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. diff --git a/gcc/predict.def b/gcc/predict.def index f4eddc5..145330c 100644 --- a/gcc/predict.def +++ b/gcc/predict.def @@ -57,6 +57,11 @@ DEF_PREDICTOR (PRED_UNCONDITIONAL, "unconditional jump", PROB_ALWAYS, DEF_PREDICTOR (PRED_LOOP_ITERATIONS, "loop iterations", PROB_ALWAYS, PRED_FLAG_FIRST_MATCH) +/* Assume that any given atomic operation has low contention, + and thus the compare-and-swap operation succeeds. */ +DEF_PREDICTOR (PRED_COMPARE_AND_SWAP, "compare and swap", PROB_VERY_LIKELY, + PRED_FLAG_FIRST_MATCH) + /* Hints dropped by user via __builtin_expect feature. Note: the probability of PROB_VERY_LIKELY is now overwritten by param builtin_expect_probability with a default value of HITRATE(90). @@ -133,3 +138,41 @@ DEF_PREDICTOR (PRED_HOT_LABEL, "hot label", HITRATE (85), 0) /* Branches to cold labels are extremely unlikely. */ DEF_PREDICTOR (PRED_COLD_LABEL, "cold label", PROB_VERY_LIKELY, PRED_FLAG_FIRST_MATCH) + + +/* The following predictors are used in Fortran. */ + +/* Branch leading to an integer overflow are extremely unlikely. */ +DEF_PREDICTOR (PRED_FORTRAN_OVERFLOW, "overflow", PROB_ALWAYS, + PRED_FLAG_FIRST_MATCH) + +/* Branch leading to a failure status are unlikely. This can occur for out + of memory or when trying to allocate an already allocated allocated or + deallocating an already deallocated allocatable. This predictor only + occurs when the user explicitly asked for a return status. By default, + the code aborts, which is handled via PRED_NORETURN. */ +DEF_PREDICTOR (PRED_FORTRAN_FAIL_ALLOC, "fail alloc", PROB_VERY_LIKELY, 0) + +/* Branch leading to an I/O failure status are unlikely. This predictor is + used for I/O failures such as for invalid unit numbers. This predictor + only occurs when the user explicitly asked for a return status. By default, + the code aborts, which is handled via PRED_NORETURN. */ +DEF_PREDICTOR (PRED_FORTRAN_FAIL_IO, "fail alloc", HITRATE(85), 0) + +/* Branch leading to a run-time warning message which is printed only once + are unlikely. The print-warning branch itself can be likely or unlikely. */ +DEF_PREDICTOR (PRED_FORTRAN_WARN_ONCE, "warn once", HITRATE (75), 0) + +/* Branch belonging to a zero-sized array. */ +DEF_PREDICTOR (PRED_FORTRAN_SIZE_ZERO, "zero-sized array", HITRATE(70), 0) + +/* Branch belonging to an invalid bound index, in a context where it is + standard conform and well defined but rather pointless and, hence, rather + unlikely to occur. */ +DEF_PREDICTOR (PRED_FORTRAN_INVALID_BOUND, "zero-sized array", HITRATE(90), 0) + +/* Branch belonging to the handling of absent optional arguments. This + predictor is used when an optional dummy argument, associated with an + absent argument, is passed on as actual argument to another procedure, + which in turn has an optional argument. */ +DEF_PREDICTOR (PRED_FORTRAN_ABSENT_DUMMY, "absent dummy", HITRATE(60), 0) @@ -4548,6 +4548,7 @@ extern tree fold_builtin_stxcpy_chk (location_t, tree, tree, tree, tree, tree, b enum built_in_function); extern tree fold_builtin_stxncpy_chk (location_t, tree, tree, tree, tree, tree, bool, enum built_in_function); +extern tree fold_builtin_expect (location_t, tree, tree, tree); extern bool fold_builtin_next_arg (tree, bool); extern enum built_in_function builtin_mathfn_code (const_tree); extern tree fold_builtin_call_array (location_t, tree, tree, int, tree *); |