diff options
Diffstat (limited to 'gcc/dojump.c')
-rw-r--r-- | gcc/dojump.c | 82 |
1 files changed, 58 insertions, 24 deletions
diff --git a/gcc/dojump.c b/gcc/dojump.c index 3f04eacabb7..ee12d761eee 100644 --- a/gcc/dojump.c +++ b/gcc/dojump.c @@ -311,32 +311,66 @@ do_jump_1 (enum tree_code code, tree op0, tree op1, break; case TRUTH_ANDIF_EXPR: - if (if_false_label == NULL_RTX) - { - drop_through_label = gen_label_rtx (); - do_jump (op0, drop_through_label, NULL_RTX, prob); - do_jump (op1, NULL_RTX, if_true_label, prob); - } - else - { - do_jump (op0, if_false_label, NULL_RTX, prob); - do_jump (op1, if_false_label, if_true_label, prob); - } - break; + { + /* Spread the probability that the expression is false evenly between + the two conditions. So the first condition is false half the total + probability of being false. The second condition is false the other + half of the total probability of being false, so its jump has a false + probability of half the total, relative to the probability we + reached it (i.e. the first condition was true). */ + int op0_prob = -1; + int op1_prob = -1; + if (prob != -1) + { + int false_prob = inv (prob); + int op0_false_prob = false_prob / 2; + int op1_false_prob = GCOV_COMPUTE_SCALE ((false_prob / 2), + inv (op0_false_prob)); + /* Get the probability that each jump below is true. */ + op0_prob = inv (op0_false_prob); + op1_prob = inv (op1_false_prob); + } + if (if_false_label == NULL_RTX) + { + drop_through_label = gen_label_rtx (); + do_jump (op0, drop_through_label, NULL_RTX, op0_prob); + do_jump (op1, NULL_RTX, if_true_label, op1_prob); + } + else + { + do_jump (op0, if_false_label, NULL_RTX, op0_prob); + do_jump (op1, if_false_label, if_true_label, op1_prob); + } + break; + } case TRUTH_ORIF_EXPR: - if (if_true_label == NULL_RTX) - { - drop_through_label = gen_label_rtx (); - do_jump (op0, NULL_RTX, drop_through_label, prob); - do_jump (op1, if_false_label, NULL_RTX, prob); - } - else - { - do_jump (op0, NULL_RTX, if_true_label, prob); - do_jump (op1, if_false_label, if_true_label, prob); - } - break; + { + /* Spread the probability evenly between the two conditions. So + the first condition has half the total probability of being true. + The second condition has the other half of the total probability, + so its jump has a probability of half the total, relative to + the probability we reached it (i.e. the first condition was false). */ + int op0_prob = -1; + int op1_prob = -1; + if (prob != -1) + { + op0_prob = prob / 2; + op1_prob = GCOV_COMPUTE_SCALE ((prob / 2), inv (op0_prob)); + } + if (if_true_label == NULL_RTX) + { + drop_through_label = gen_label_rtx (); + do_jump (op0, NULL_RTX, drop_through_label, op0_prob); + do_jump (op1, if_false_label, NULL_RTX, op1_prob); + } + else + { + do_jump (op0, NULL_RTX, if_true_label, op0_prob); + do_jump (op1, if_false_label, if_true_label, op1_prob); + } + break; + } default: gcc_unreachable (); |