aboutsummaryrefslogtreecommitdiff
path: root/gcc/predict.c
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/predict.c')
-rw-r--r--gcc/predict.c66
1 files changed, 66 insertions, 0 deletions
diff --git a/gcc/predict.c b/gcc/predict.c
index 2cae39a5798..958dbf925b8 100644
--- a/gcc/predict.c
+++ b/gcc/predict.c
@@ -180,4 +180,70 @@ estimate_probability (loops_info)
REG_NOTES (last_insn));
}
}
+
+/* __builtin_expect dropped tokens into the insn stream describing
+ expected values of registers. Generate branch probabilities
+ based off these values. */
+static rtx find_expected_value PARAMS ((rtx, rtx));
+
+void
+expected_value_to_br_prob ()
+{
+ rtx insn, cond, ev = NULL_RTX, ev_reg;
+
+ for (insn = get_insns (); insn ; insn = NEXT_INSN (insn))
+ {
+ switch (GET_CODE (insn))
+ {
+ case NOTE:
+ /* Look for expected value notes. */
+ if (NOTE_LINE_NUMBER (insn) == NOTE_INSN_EXPECTED_VALUE)
+ {
+ ev = NOTE_EXPECTED_VALUE (insn);
+ ev_reg = XEXP (ev, 0);
+ }
+ continue;
+
+ case CODE_LABEL:
+ /* Never propagate across labels. */
+ ev = NULL_RTX;
+ continue;
+
+ default:
+ /* Look for insns that clobber the EV register. */
+ if (ev && reg_set_p (ev_reg, insn))
+ ev = NULL_RTX;
+ continue;
+
+ case JUMP_INSN:
+ /* Look for simple conditional branches. If we havn't got an
+ expected value yet, no point going further. */
+ if (GET_CODE (insn) != JUMP_INSN || ev == NULL_RTX)
+ continue;
+ if (! condjump_p (insn) || simplejump_p (insn))
+ continue;
+ break;
+ }
+
+ /* Collect the branch condition, hopefully relative to EV_REG. */
+ cond = XEXP (SET_SRC (PATTERN (insn)), 0);
+ cond = canonicalize_condition (insn, cond, 0, NULL, ev_reg);
+ if (! cond || XEXP (cond, 0) != ev_reg)
+ continue;
+
+ /* Substitute and simplify. Given that the expression we're
+ building involves two constants, we should wind up with either
+ true or false. */
+ cond = gen_rtx_fmt_ee (GET_CODE (cond), VOIDmode,
+ XEXP (ev, 1), XEXP (cond, 1));
+ cond = simplify_rtx (cond);
+
+ /* Turn the condition into a scaled branch probability. */
+ if (cond == const1_rtx)
+ cond = GEN_INT (REG_BR_PROB_BASE);
+ else if (cond != const0_rtx)
+ abort ();
+ REG_NOTES (insn) = alloc_EXPR_LIST (REG_BR_PROB, cond, REG_NOTES (insn));
+ }
+}