]> gcc.gnu.org Git - gcc.git/commitdiff
re PR ipa/58721 (The subroutine perdida is no longer inlined in fatigue.f90)
authorJakub Jelinek <jakub@gcc.gnu.org>
Tue, 18 Mar 2014 11:31:04 +0000 (12:31 +0100)
committerJakub Jelinek <jakub@gcc.gnu.org>
Tue, 18 Mar 2014 11:31:04 +0000 (12:31 +0100)
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

18 files changed:
gcc/ChangeLog
gcc/builtins.c
gcc/fortran/ChangeLog
gcc/fortran/trans-array.c
gcc/fortran/trans-expr.c
gcc/fortran/trans-intrinsic.c
gcc/fortran/trans-io.c
gcc/fortran/trans-stmt.c
gcc/fortran/trans.c
gcc/fortran/trans.h
gcc/gimple-fold.c
gcc/gimplify.c
gcc/internal-fn.c
gcc/internal-fn.def
gcc/ipa-inline-analysis.c
gcc/predict.c
gcc/predict.def
gcc/tree.h

index 681ec52ce75e18d9701dc73f83348a7cacf8d146..85060d1d5db1dc6c520369a24aad0c11305f49e8 100644 (file)
@@ -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
index e4846c8e6d7d337b7da45b63db7a23aff5f0ee5e..dd57b1ae42a1aeee2749c4619fcd945dec87c9a7 100644 (file)
@@ -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;
     }
index ce4063edd0684db1927fedd5d2a840808213f0be..78dbc5d38926f172881648f959e2759cdeb0f022 100644 (file)
@@ -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
index dee422cc13024680a977b6bc22715b913ca288e1..8c4afb098bf7b2fe8eea2439821ef313bd69d71a 100644 (file)
@@ -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
index 269fcc5c86c59e17119ea581baf50e5c62099851..f5350bb5ba9d35a9f09db9d003e879ab2fa0d7b6 100644 (file)
@@ -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);
index 75bd20ae04a11cbc17c5a58f7fdb146c31920b80..e21d52fece9d4bfdda138c6b2aec9cd575fd015b 100644 (file)
@@ -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.  */
 
index 853e77d62f52b2b413936e823466fdd2e3956c27..d15159857d00a1fc5c66c4b6a2c7199a98a99805 100644 (file)
@@ -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);
index c7ff7a8cb8eb3dfc38c6cc6a33fe2b440fa097b6..1a9068c0f466a36eb928b34f1607766515f952e8 100644 (file)
@@ -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);
index 073e34f0eb577928d4c6579fc32e3a8b55545288..5961c267e8c98607f6e0d7cda93e997bda43bd42 100644 (file)
@@ -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;
 }
index 5fb0cbf2289d921bea8dc79278afdb6341e28062..4ae68c6cb859313035ad46aae6aa81b4e0747fdd 100644 (file)
@@ -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, ...);
index 5de44457aa80ca539ce4ec5989a0bf1e07ab6041..eafdb2dd51498acde33d0f1b0f110db8fb4e2282 100644 (file)
@@ -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;
 }
index ff341d43bf325b052972d77e71004ec4b3d52dac..ad2178dd914c8a8cbe2e333cb6010dca5f975add 100644 (file)
@@ -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);
index 568a96b94b130700f03f6b7f2d661493304497fa..9926ec2808be9134cd2f8d1cb45d57225deca734 100644 (file)
@@ -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:
 
index 379b35241b51f263cf6a93999ceba4c7d156c92a..31dc4c9cacd5a949a28283521d56c1608418d8cb 100644 (file)
@@ -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)
index 6cd5dc1c2e57be49e8670b908b8af213c5f7e0c8..98f42ef1e55e7ea94c817491d9bdaed55fac75ce 100644 (file)
@@ -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);
index db5eed910a3630f05820b125e052d5556ed7e05a..249433f912952979a71835087d8a9bd323a760d7 100644 (file)
@@ -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);
 }
 \f
-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);
 }
 
 \f
@@ -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.
index f4eddc5f8a8c1a133a274e7482aa565004f38f37..145330cbed02cd497f51cbfd4adb54f7f146ae7f 100644 (file)
@@ -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)
index 0dc8d0dcd4f572f4b5c204740607ca80e83b487e..71d68321a5500805f51f19d8670711e6f4f4608a 100644 (file)
@@ -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 *);
This page took 0.107643 seconds and 5 git commands to generate.