https://gcc.gnu.org/bugzilla/show_bug.cgi?id=98212
Jakub Jelinek <jakub at gcc dot gnu.org> changed: What |Removed |Added ---------------------------------------------------------------------------- CC| |hubicka at gcc dot gnu.org --- Comment #5 from Jakub Jelinek <jakub at gcc dot gnu.org> --- So, for the corge case, do_compare_rtx_and_jump is called with EQ, if_false_label non-NULL, if_true_label NULL (i.e. fall through) and prob of 10%. The target doesn't support it and so x == y is being split into x ord y && x u== y. first_prob is computed as 10.9% and prob 91.74%, it is expanded as if (x unord y) goto if_false_label; // prob of goto 89.1% if (x u== y) goto dummy; // prob of goto 91.74% goto if_false_label; dummy:; 1133 profile_probability cprob 1134 = profile_probability::guessed_always (); 1135 if (first_code == UNORDERED) 1136 cprob = cprob.apply_scale (1, 100); 1137 else if (first_code == ORDERED) 1138 cprob = cprob.apply_scale (99, 100); 1139 else 1140 cprob = profile_probability::even (); 1141 /* We want to split: 1142 if (x) goto t; // prob; 1143 into 1144 if (a) goto t; // first_prob; 1145 if (b) goto t; // prob; 1146 such that the overall probability of jumping to t 1147 remains the same and first_prob is prob * cprob. */ 1148 if (and_them) ... 1151 prob = prob.invert (); 1152 profile_probability first_prob = prob.split (cprob).invert (); 1153 prob = prob.invert (); The comment only describes how !and_them looks like, for and_them it is actually: if (x) goto t; // prob; goto f; into: if (a) goto f; // 1 - first_prob; if (b) goto t; // prob; goto f; (at least for the case where we have both f and t). prob.split is documented as: Split *THIS (ORIG) probability into 2 probabilities, such that the returned one (FIRST) is *THIS * CPROB and *THIS is adjusted (SECOND) so that FIRST + FIRST.invert () * SECOND == ORIG. This is useful e.g. when splitting a conditional branch like: if (cond) goto lab; // ORIG probability into if (cond1) goto lab; // FIRST = ORIG * CPROB probability if (cond2) goto lab; // SECOND probability So, if we talk about baz above with prob of jumping to t 90%, the computed first_prob is 1-((1-90%)*99%), so 90.1%, which means if (op0 unord op1) goto f; with 8.9% probability. For corge prob of jumping to t is 10%, the computed first_prob is 1-((1-10%)*99%), so 10.9% which means if (op0 unord op1) goto f; // with 89.1% probability. NaNs are never that common! if (op0 uneq op1) goto t; // with 91.74% probability. I think the right thing would be to for these < 50% initial prop and ORDERED first_code would be to use something like: profile_probability first_prob = prob.split (cprob).invert (); without the two prob = prob.invert (); around it. With: --- gcc/dojump.c.jj 2020-12-09 15:11:17.042888002 +0100 +++ gcc/dojump.c 2020-12-09 20:05:59.535234206 +0100 @@ -1148,9 +1148,15 @@ do_compare_rtx_and_jump (rtx op0, rtx op if (and_them) { rtx_code_label *dest_label; - prob = prob.invert (); - profile_probability first_prob = prob.split (cprob).invert (); - prob = prob.invert (); + profile_probability first_prob; + if (prob < profile_probability::even ()) + first_prob = prob.split (cprob).invert (); + else + { + prob = prob.invert (); + first_prob = prob.split (cprob).invert (); + prob = prob.invert (); + } /* If we only jump if true, just bypass the second jump. */ if (! if_false_label) { I get the output I'm looking for, so bar/baz/qux stay the same and corge becomes: corge: ucomiss %xmm1, %xmm0 jp .L14 je .L18 .L14: ret .L18: jmp foo Honza, what do you think?