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
This commit is contained in:
parent
e33da4a113
commit
ed9c79e1ea
@ -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
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
|
@ -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. */
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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, ...);
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -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:
|
||||
|
||||
|
@ -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)
|
||||
|
@ -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);
|
||||
|
100
gcc/predict.c
100
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.
|
||||
|
@ -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 *);
|
||||
|
Loading…
x
Reference in New Issue
Block a user