+apply_return_prediction (void)
+{
+ gimple return_stmt = NULL;
+ tree return_val;
+ edge e;
+ gimple phi;
+ int phi_num_args, i;
+ enum br_predictor pred;
+ enum prediction direction;
+ edge_iterator ei;
+
+ FOR_EACH_EDGE (e, ei, EXIT_BLOCK_PTR->preds)
+ {
+ return_stmt = last_stmt (e->src);
+ if (return_stmt
+ && gimple_code (return_stmt) == GIMPLE_RETURN)
+ break;
+ }
+ if (!e)
+ return;
+ return_val = gimple_return_retval (return_stmt);
+ if (!return_val)
+ return;
+ if (TREE_CODE (return_val) != SSA_NAME
+ || !SSA_NAME_DEF_STMT (return_val)
+ || gimple_code (SSA_NAME_DEF_STMT (return_val)) != GIMPLE_PHI)
+ return;
+ phi = SSA_NAME_DEF_STMT (return_val);
+ phi_num_args = gimple_phi_num_args (phi);
+ pred = return_prediction (PHI_ARG_DEF (phi, 0), &direction);
+
+ /* Avoid the degenerate case where all return values form the function
+ belongs to same category (ie they are all positive constants)
+ so we can hardly say something about them. */
+ for (i = 1; i < phi_num_args; i++)
+ if (pred != return_prediction (PHI_ARG_DEF (phi, i), &direction))
+ break;
+ if (i != phi_num_args)
+ for (i = 0; i < phi_num_args; i++)
+ {
+ pred = return_prediction (PHI_ARG_DEF (phi, i), &direction);
+ if (pred != PRED_NO_PREDICTION)
+ predict_paths_leading_to (gimple_phi_arg_edge (phi, i)->src, pred,
+ direction);
+ }
+}
+
+/* Look for basic block that contains unlikely to happen events
+ (such as noreturn calls) and mark all paths leading to execution
+ of this basic blocks as unlikely. */
+
+static void
+tree_bb_level_predictions (void)
+{
+ basic_block bb;
+ bool has_return_edges = false;
+ edge e;
+ edge_iterator ei;
+
+ FOR_EACH_EDGE (e, ei, EXIT_BLOCK_PTR->preds)
+ if (!(e->flags & (EDGE_ABNORMAL | EDGE_FAKE | EDGE_EH)))
+ {
+ has_return_edges = true;
+ break;
+ }
+
+ apply_return_prediction ();
+
+ FOR_EACH_BB (bb)
+ {
+ gimple_stmt_iterator gsi;
+
+ for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi))
+ {
+ gimple stmt = gsi_stmt (gsi);
+ tree decl;
+
+ if (is_gimple_call (stmt))
+ {
+ if ((gimple_call_flags (stmt) & ECF_NORETURN)
+ && has_return_edges)
+ predict_paths_leading_to (bb, PRED_NORETURN,
+ NOT_TAKEN);
+ decl = gimple_call_fndecl (stmt);
+ if (decl
+ && lookup_attribute ("cold",
+ DECL_ATTRIBUTES (decl)))
+ predict_paths_leading_to (bb, PRED_COLD_FUNCTION,
+ NOT_TAKEN);
+ }
+ else if (gimple_code (stmt) == GIMPLE_PREDICT)
+ {
+ predict_paths_leading_to (bb, gimple_predict_predictor (stmt),
+ gimple_predict_outcome (stmt));
+ /* Keep GIMPLE_PREDICT around so early inlining will propagate
+ hints to callers. */
+ }
+ }
+ }
+}
+
+#ifdef ENABLE_CHECKING
+
+/* Callback for pointer_map_traverse, asserts that the pointer map is
+ empty. */
+
+static bool
+assert_is_empty (const void *key ATTRIBUTE_UNUSED, void **value,
+ void *data ATTRIBUTE_UNUSED)
+{
+ gcc_assert (!*value);
+ return false;
+}
+#endif
+
+/* Predict branch probabilities and estimate profile of the tree CFG. */
+static unsigned int