Re: [patch, Fortran] Fix PR 125914, suboptimal code for (-1.0)**integer(8)

Harald Anlauf <[email protected]> Sun, 21 Jun 2026 21:53:25 +0200
Newsgroups gmane.comp.gcc.patches,gmane.comp.gcc.fortran
Message-ID <[email protected]>
Hi Thomas!

Am 21.06.26 um 4:46 PM schrieb Thomas Koenig:
> Hello world,
> 
> what it says in the ChangeLog entry. Regression-tested (and the test
> case makes sure there is no wrong-code regression).
> 
> OK for trunk?
> 
> Best regards
> 
>      Thomas
> 
> Rewrite (-1.0)**n to (real) (1 - (n & 1) << 1)).
> 
> The problem was that the optimization done for PR 57073 uses powi and
> friends, so it only applied to default integer exponent. The test
> case has an integer(kind=8) exponent, which is is calculated by
> calling a gfortran library function.
> 
> There are two possible approaches: One would be to convert all
> integer types to default integer (because only the lowest-value
> bit matters to the result) and call the right __builtin_powi function.
> However, the generated code is suboptimal, see PR 125919.  I therefore
> chose the variant which currently generates the best code.

This is OK.

> This requires the change to the power_6.f90 test case.

I am somewhat confused by the dg-pattern here.  It is

  ! { dg-final { scan-tree-dump-not "__builtin_powif"  "optimized" } }

In principle you do not want to see the __builtin_powif in the
original dump.  If someone chose to add an optimization that expands
the __builtin_powif to something else, you do not realize it.

(This is not your fault, though.)

I find your testcase power_10.f90 quite interesting.  It rather tests
floating-point arithmetic and may fail at different optimization levels
because of tests like

+  if (s4 /= 2.30965209) stop 11
(plus several more).

Please convince yourself and also test with other compilers.
Either add a suitable tolerance, or just test what needs to be
tested.

(One option: one can compare compile-time with run-time results,
which possibly makes it easier to trace testsuite fallout.)
Maybe use something like
   real, parameter :: expected(*) = [((-1.0)**i,i=-10,10)]
etc.

The patch is OK with the above suitably considered.

Thanks,
Harald

> gcc/fortran/ChangeLog:
> 
>      PR fortran/125914
>      * trans-expr.cc (gfc_conv_power_op): Rewrite (-1.0)**n into
>      (real) (1 - (n & 1) << 1)).
> 
> gcc/testsuite/ChangeLog:
> 
>      PR fortran/125914
>      * gfortran.dg/power_6.f90: Remove scans for powi.
>      * gfortran.dg/power_10.f90: New test.