+
+/* Like expand_builtin_expect, except do this in a jump context. This is
+ called from do_jump if the conditional is a __builtin_expect. Return either
+ a SEQUENCE of insns to emit the jump or NULL if we cannot optimize
+ __builtin_expect. We need to optimize this at jump time so that machines
+ like the PowerPC don't turn the test into a SCC operation, and then jump
+ based on the test being 0/1. */
+
+rtx
+expand_builtin_expect_jump (exp, if_false_label, if_true_label)
+ tree exp;
+ rtx if_false_label;
+ rtx if_true_label;
+{
+ tree arglist = TREE_OPERAND (exp, 1);
+ tree arg0 = TREE_VALUE (arglist);
+ tree arg1 = TREE_VALUE (TREE_CHAIN (arglist));
+ rtx ret = NULL_RTX;
+
+ /* Only handle __builtin_expect (test, 0) and
+ __builtin_expect (test, 1). */
+ if (TREE_CODE (TREE_TYPE (arg1)) == INTEGER_TYPE
+ && (integer_zerop (arg1) || integer_onep (arg1)))
+ {
+ int j;
+ int num_jumps = 0;
+
+ /* If we fail to locate an appropriate conditional jump, we'll
+ fall back to normal evaluation. Ensure that the expression
+ can be re-evaluated. */
+ switch (unsafe_for_reeval (arg0))
+ {
+ case 0: /* Safe. */
+ break;
+
+ case 1: /* Mildly unsafe. */
+ arg0 = unsave_expr (arg0);
+ break;
+
+ case 2: /* Wildly unsafe. */
+ return NULL_RTX;
+ }
+
+ /* Expand the jump insns. */
+ start_sequence ();
+ do_jump (arg0, if_false_label, if_true_label);
+ ret = gen_sequence ();
+ end_sequence ();
+
+ /* Now that the __builtin_expect has been validated, go through and add
+ the expect's to each of the conditional jumps. If we run into an
+ error, just give up and generate the 'safe' code of doing a SCC
+ operation and then doing a branch on that. */
+ for (j = 0; j < XVECLEN (ret, 0); j++)
+ {
+ rtx insn = XVECEXP (ret, 0, j);
+ rtx pattern;
+
+ if (GET_CODE (insn) == JUMP_INSN && any_condjump_p (insn)
+ && (pattern = pc_set (insn)) != NULL_RTX)
+ {
+ rtx ifelse = SET_SRC (pattern);
+ rtx label;
+ int taken;
+
+ if (GET_CODE (ifelse) != IF_THEN_ELSE)
+ continue;
+
+ if (GET_CODE (XEXP (ifelse, 1)) == LABEL_REF)
+ {
+ taken = 1;
+ label = XEXP (XEXP (ifelse, 1), 0);
+ }
+ /* An inverted jump reverses the probabilities. */
+ else if (GET_CODE (XEXP (ifelse, 2)) == LABEL_REF)
+ {
+ taken = 0;
+ label = XEXP (XEXP (ifelse, 2), 0);
+ }
+ /* We shouldn't have to worry about conditional returns during
+ the expansion stage, but handle it gracefully anyway. */
+ else if (GET_CODE (XEXP (ifelse, 1)) == RETURN)
+ {
+ taken = 1;
+ label = NULL_RTX;
+ }
+ /* An inverted return reverses the probabilities. */
+ else if (GET_CODE (XEXP (ifelse, 2)) == RETURN)
+ {
+ taken = 0;
+ label = NULL_RTX;
+ }
+ else
+ continue;
+
+ /* If the test is expected to fail, reverse the
+ probabilities. */
+ if (integer_zerop (arg1))
+ taken = 1 - taken;
+
+ /* If we are jumping to the false label, reverse the
+ probabilities. */
+ if (label == NULL_RTX)
+ ; /* conditional return */
+ else if (label == if_false_label)
+ taken = 1 - taken;
+ else if (label != if_true_label)
+ continue;
+
+ num_jumps++;
+ predict_insn_def (insn, PRED_BUILTIN_EXPECT, taken);
+ }
+ }
+
+ /* If no jumps were modified, fail and do __builtin_expect the normal
+ way. */
+ if (num_jumps == 0)
+ ret = NULL_RTX;
+ }
+
+ return ret;
+}