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?