diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 8222534738c..5ece63e9e3a 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,16 @@ +2004-09-23 Jan Hubicka + + * cfgexpand.c (add_reg_br_prob_note): New function. + (expand_gimple_cond_expr): Use it. + (tree_expand_cfg): No longer kill the profile. + * cfgrt.c (rtl_verify_flow_info_1): Check profile consistency + only if it is present. + * passes.c (rest_of_handle_loop_optimize): Kill the profile. + * predict.c (combine_predictions_for_insn): Set the probabilities + based on REG_BR_PROB note if present. + * predict.c (branch_prob): Profile is read only with + flag_branch_probabilities. + 2004-09-22 Kelley Cook * aclocal.m4: Add in gettext's m4 includes. diff --git a/gcc/cfgexpand.c b/gcc/cfgexpand.c index bf179fee0b6..5f8ec900286 100644 --- a/gcc/cfgexpand.c +++ b/gcc/cfgexpand.c @@ -38,6 +38,49 @@ Boston, MA 02111-1307, USA. */ #include "diagnostic.h" #include "toplev.h" +/* Verify that there is exactly single jump instruction since last and attach + REG_BR_PROB note specifying probability. + ??? We really ought to pass the probability down to RTL expanders and let it + re-distribute it when the conditional expands into multiple coniditionals. + This is however dificult to do. */ +static void +add_reg_br_prob_note (FILE *dump_file, rtx last, int probability) +{ + if (profile_status == PROFILE_ABSENT) + return; + for (last = NEXT_INSN (last); last && NEXT_INSN (last); last = NEXT_INSN (last)) + if (GET_CODE (last) == JUMP_INSN) + { + /* It is common to emit condjump-around-jump sequence when we don't know + how to reverse the conditional. Special case this. */ + if (!any_condjump_p (last) + || GET_CODE (NEXT_INSN (last)) != JUMP_INSN + || !simplejump_p (NEXT_INSN (last)) + || GET_CODE (NEXT_INSN (NEXT_INSN (last))) != BARRIER + || GET_CODE (NEXT_INSN (NEXT_INSN (NEXT_INSN (last)))) != CODE_LABEL + || NEXT_INSN (NEXT_INSN (NEXT_INSN (NEXT_INSN (last))))) + goto failed; + if (find_reg_note (last, REG_BR_PROB, 0)) + abort (); + REG_NOTES (last) + = gen_rtx_EXPR_LIST (REG_BR_PROB, + GEN_INT (REG_BR_PROB_BASE - probability), + REG_NOTES (last)); + return; + } + if (!last || GET_CODE (last) != JUMP_INSN || !any_condjump_p (last)) + goto failed; + if (find_reg_note (last, REG_BR_PROB, 0)) + abort (); + REG_NOTES (last) + = gen_rtx_EXPR_LIST (REG_BR_PROB, + GEN_INT (probability), REG_NOTES (last)); + return; +failed: + if (dump_file) + fprintf (dump_file, "Failed to add probability note\n"); +} + #ifndef LOCAL_ALIGNMENT #define LOCAL_ALIGNMENT(TYPE, ALIGNMENT) ALIGNMENT @@ -804,7 +847,7 @@ expand_gimple_cond_expr (basic_block bb, tree stmt) tree pred = COND_EXPR_COND (stmt); tree then_exp = COND_EXPR_THEN (stmt); tree else_exp = COND_EXPR_ELSE (stmt); - rtx last; + rtx last = get_last_insn (); extract_true_false_edges_from_block (bb, &true_edge, &false_edge); if (EXPR_LOCUS (stmt)) @@ -822,17 +865,20 @@ expand_gimple_cond_expr (basic_block bb, tree stmt) if (TREE_CODE (then_exp) == GOTO_EXPR && IS_EMPTY_STMT (else_exp)) { jumpif (pred, label_rtx (GOTO_DESTINATION (then_exp))); + add_reg_br_prob_note (dump_file, last, true_edge->probability); return NULL; } if (TREE_CODE (else_exp) == GOTO_EXPR && IS_EMPTY_STMT (then_exp)) { jumpifnot (pred, label_rtx (GOTO_DESTINATION (else_exp))); + add_reg_br_prob_note (dump_file, last, false_edge->probability); return NULL; } gcc_assert (TREE_CODE (then_exp) == GOTO_EXPR && TREE_CODE (else_exp) == GOTO_EXPR); jumpif (pred, label_rtx (GOTO_DESTINATION (then_exp))); + add_reg_br_prob_note (dump_file, last, true_edge->probability); last = get_last_insn (); expand_expr (else_exp, const0_rtx, VOIDmode, 0); @@ -1193,8 +1239,6 @@ tree_expand_cfg (void) basic_block bb, init_block; sbitmap blocks; - profile_status = PROFILE_ABSENT; - /* Some backends want to know that we are expanding to RTL. */ currently_expanding_to_rtl = 1; diff --git a/gcc/cfgrtl.c b/gcc/cfgrtl.c index a35fdbd5619..8664f049901 100644 --- a/gcc/cfgrtl.c +++ b/gcc/cfgrtl.c @@ -1969,7 +1969,8 @@ rtl_verify_flow_info_1 (void) && bb->succ && bb->succ->succ_next && any_condjump_p (BB_END (bb))) { - if (INTVAL (XEXP (note, 0)) != BRANCH_EDGE (bb)->probability) + if (INTVAL (XEXP (note, 0)) != BRANCH_EDGE (bb)->probability + && profile_status != PROFILE_ABSENT) { error ("verify_flow_info: REG_BR_PROB does not match cfg %wi %i", INTVAL (XEXP (note, 0)), BRANCH_EDGE (bb)->probability); diff --git a/gcc/passes.c b/gcc/passes.c index 986151b57c0..c62f2e9d480 100644 --- a/gcc/passes.c +++ b/gcc/passes.c @@ -1138,6 +1138,7 @@ rest_of_handle_loop_optimize (void) /* CFG is no longer maintained up-to-date. */ free_bb_for_insn (); + profile_status = PROFILE_ABSENT; do_prefetch = flag_prefetch_loop_arrays ? LOOP_PREFETCH : 0; diff --git a/gcc/predict.c b/gcc/predict.c index 7eaee34d2eb..cc314ecad74 100644 --- a/gcc/predict.c +++ b/gcc/predict.c @@ -438,6 +438,15 @@ combine_predictions_for_insn (rtx insn, basic_block bb) = REG_BR_PROB_BASE - combined_probability; } } + else if (bb->succ->succ_next) + { + int prob = INTVAL (XEXP (prob_note, 0)); + + BRANCH_EDGE (bb)->probability = prob; + FALLTHRU_EDGE (bb)->probability = REG_BR_PROB_BASE - prob; + } + else + bb->succ->probability = REG_BR_PROB_BASE; } /* Combine predictions into single probability and store them into CFG. diff --git a/gcc/profile.c b/gcc/profile.c index 77c5d03b15a..b83e6c3e5d9 100644 --- a/gcc/profile.c +++ b/gcc/profile.c @@ -1104,7 +1104,8 @@ branch_prob (void) } free_edge_list (el); - profile_status = PROFILE_READ; + if (flag_branch_probabilities) + profile_status = PROFILE_READ; } /* Union find algorithm implementation for the basic blocks using