Ping.
Thanks,
Kyrill

> On 17 Jul 2026, at 15:25, Kyrylo Tkachov <[email protected]> wrote:
> 
> From: Kyrylo Tkachov <[email protected]>
> 
> average_cost computes
> 
>  ELSE_COST + P * (THEN_COST - ELSE_COST)
> 
> profile_probability::apply now rounds signed initialized values to the nearest
> integer, with halfway values away from zero.  That signed rounding can still
> give different integer costs when equivalent CFG arms are reversed.  Unknown
> probabilities have the same issue for odd cost differences because apply
> truncates them toward zero.
> 
> Write the documented weighted average as
> 
>  ELSE_COST + P * (THEN_COST - ELSE_COST)
> 
> when THEN_COST is at least ELSE_COST, and as
> 
>  THEN_COST + (1 - P) * (ELSE_COST - THEN_COST)
> 
> otherwise.  Both forms start with the cheaper arm and scale a nonnegative
> cost difference by the probability of the costlier arm.  Reversing the CFG
> arms therefore keeps the same base, magnitude, probability, and rounded
> result.  Cast the costlier arm to gcov_type before subtraction.
> 
> Add an x86 test with the same costs and probabilities represented using
> reversed CFG arms.  The scaled cost difference is an exact halfway value.
> The apply-only compiler makes opposite profitability decisions for the two
> orientations.  With this change both forms convert to conditional moves.
> 
> Bootstrapped and tested on aarch64-linux-gnu and x86_64-linux.
> Ok for trunk?
> Thanks,
> Kyrill
> 
> gcc/ChangeLog:
> 
> PR tree-optimization/125557
> * ifcvt.cc (average_cost): Scale a nonnegative cost difference using
> the probability of the more expensive arm.
> 
> gcc/testsuite/ChangeLog:
> 
> PR tree-optimization/125557
> * gcc.target/i386/ifcvt-average-cost-1.c: New test.
> 
> Signed-off-by: Kyrylo Tkachov <[email protected]>
> ---
> gcc/ifcvt.cc                                  | 13 ++++++--
> .../gcc.target/i386/ifcvt-average-cost-1.c    | 32 +++++++++++++++++++
> 2 files changed, 43 insertions(+), 2 deletions(-)
> create mode 100644 gcc/testsuite/gcc.target/i386/ifcvt-average-cost-1.c
> 
> diff --git a/gcc/ifcvt.cc b/gcc/ifcvt.cc
> index 6a76fec66cb..928483a347c 100644
> --- a/gcc/ifcvt.cc
> +++ b/gcc/ifcvt.cc
> @@ -4309,11 +4309,20 @@ bb_ok_for_noce_convert_multiple_sets (basic_block 
> test_bb, unsigned *cost)
> /* Compute average of two given costs weighted by relative probabilities
>    of respective basic blocks in an IF-THEN-ELSE.  E is the IF-THEN edge.
>    With P as the probability to take the IF-THEN branch, return
> -   P * THEN_COST + (1 - P) * ELSE_COST.  */
> +   P * THEN_COST + (1 - P) * ELSE_COST.  Evaluate this as
> +   ELSE_COST + P * (THEN_COST - ELSE_COST) when THEN_COST >= ELSE_COST, and
> +   THEN_COST + (1 - P) * (ELSE_COST - THEN_COST) otherwise.  Both forms pass
> +   a nonnegative value to profile_probability::apply and make its rounding
> +   independent of the CFG arm order.  */
> static unsigned
> average_cost (unsigned then_cost, unsigned else_cost, edge e)
> {
> -  return else_cost + e->probability.apply ((signed) (then_cost - else_cost));
> +  if (then_cost < else_cost)
> +    return then_cost
> +      + e->probability.invert ().apply ((gcov_type) else_cost - then_cost);
> +
> +  return else_cost
> +    + e->probability.apply ((gcov_type) then_cost - else_cost);
> }
> 
> /* Given a simple IF-THEN-JOIN or IF-THEN-ELSE-JOIN block, attempt to convert
> diff --git a/gcc/testsuite/gcc.target/i386/ifcvt-average-cost-1.c 
> b/gcc/testsuite/gcc.target/i386/ifcvt-average-cost-1.c
> new file mode 100644
> index 00000000000..98ca361cb69
> --- /dev/null
> +++ b/gcc/testsuite/gcc.target/i386/ifcvt-average-cost-1.c
> @@ -0,0 +1,32 @@
> +/* { dg-do compile } */
> +/* { dg-require-effective-target lp64 } */
> +/* { dg-options "-O2 -mtune=generic 
> --param=max-rtl-if-conversion-unpredictable-cost=0 -fdump-rtl-ce1" } */
> +
> +/* These functions describe the same branch probabilities and arm costs with
> +   the arms reversed.  The scaled cost difference is exactly halfway between
> +   two integers.  */
> +long
> +then_cheaper (long c, long a, long b)
> +{
> +  long x;
> +  if (__builtin_expect_with_probability (c != 0, 0, 0.9375))
> +    x = a ^ b;
> +  else
> +    x = b * 3 + 1;
> +  return x;
> +}
> +
> +long
> +then_costlier (long c, long a, long b)
> +{
> +  long x;
> +  if (__builtin_expect_with_probability (c == 0, 1, 0.9375))
> +    x = b * 3 + 1;
> +  else
> +    x = a ^ b;
> +  return x;
> +}
> +
> +/* { dg-final { scan-rtl-dump-times "if-conversion succeeded through 
> noce_try_cmove_arith" 2 "ce1" } } */
> +/* { dg-final { scan-assembler-times {\tcmov} 2 } } */
> +/* { dg-final { scan-assembler-not {\tj(e|ne)\t} } } */
> -- 
> 2.50.1 (Apple Git-155)
> 

Reply via email to