develooper Front page | perl.perl5.porters | Postings from June 2020

float arith slowdown and S_lossless_NV_to_IV()

Dave Mitchell
June 8, 2020 14:27
float arith slowdown and S_lossless_NV_to_IV()
Message ID:
In 5.31.1, a bunch of arithmetic op code was consolidated with this commit:

    commit 3a019afd6f6291c3249c254b5c01e244e4ec83ab
    Author:     Karl Williamson <>
    AuthorDate: Sun Apr 28 17:42:44 2019 -0600
    Commit:     Karl Williamson <>
    CommitDate: Fri May 24 17:09:30 2019 -0600

        Create fcn for lossless conversion of NV to IV
        Essentially the same code was being used in three places, and had
        undefined C behavior for some inputs.
        This consolidates the code into one inline function, and rewrites it to
        avoid undefined behavior.

However, this makes a lot of the arithmetic benchmarks run slower where
they have float+float or float+int args. For example,
expr::arith::add_lex_ni jumped from 129 to 145 instruction reads.

This is because of changes like:

    -            if (
    -#if defined(NAN_COMPARE_BROKEN) && defined(Perl_isnan)
    -                !Perl_isnan(nl) && nl == (NV)(il = (IV)nl)
    -                && !Perl_isnan(nr) && nr == (NV)(ir = (IV)nr)
    -                nl == (NV)(il = (IV)nl) && nr == (NV)(ir = (IV)nr)
    -                )
    +            if (lossless_NV_to_IV(nl, &il) && lossless_NV_to_IV(nr, &ir)) {

For decent platforms where NAN_COMPARE_BROKEN is not true, the old
condition was just

    if ( nl == (NV)(il = (IV)nl) && nr == (NV)(ir = (IV)nr) ) { ... }

while the new condition involves 2 'calls' to the inline
S_lossless_NV_to_IV() function, which happens to do more work, like
checking for NaN. I'm not sure if the extra checks are necessary, or are
just unnecessarily slowing things down.

Please note that ash-trays are provided for the use of smokers,
whereas the floor is provided for the use of all patrons.
    -- Bill Royston Perl Programming lists via nntp and http.
Comments to Ask Bjørn Hansen at | Group listing | About