Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

eliminate -fwrapv #20584

Closed
wants to merge 1 commit into from
Closed

eliminate -fwrapv #20584

wants to merge 1 commit into from

Conversation

tonycoz
Copy link
Contributor

@tonycoz tonycoz commented Dec 5, 2022

This was added late in the 5.20 release cycle to eliminate optimizations done by gcc that reflect the limits of well-defined behavior from the C standard.

Recent testing and updates mean that such behavior has been eliminated in the core itself, so remove what was intended to be a temporary change (at least to me.)

The fixes the last remnants of #13690.

Now we just need to eliminate the need for -fno-strict-aliasing, which was also "only temporary" 34d1710

This was added late in the 5.20 release cycle to eliminate
optimizations done by gcc that reflect the limits of well-defined
behavior from the C standard.

Recent testing and updates mean that such behaviour has been
eliminated in the core itself, so remove what was intended to
be a temporary change (at least to me.)
@xenu
Copy link
Member

xenu commented Dec 5, 2022

Unless there are benchmarks that show that -fwrapv noticeably decreases Perl's performance, I really don't see the point in asking the compiler to punish us with more UB.

@demerphq
Copy link
Collaborator

demerphq commented Dec 5, 2022

@xenu @tonycoz can you provide a bit more explanation about this for the uninitiated?

@jkeenan
Copy link
Contributor

jkeenan commented Dec 5, 2022

Unless there are benchmarks that show that -fwrapv noticeably decreases Perl's performance, I really don't see the point in asking the compiler to punish us with more UB.

How would we benchmark this, before and after the change?

@tonycoz
Copy link
Contributor Author

tonycoz commented Dec 5, 2022

The -fwrapv was originally added as a workaround for undefined behavior in perl.

Leaving it in masks undefined behavior defined by the C standard and means for our most common test cases (gcc) we aren't testing against what the C standard defines (or undefines).

Leaving -fwrapv in for gcc doesn't stop this being undefined behavior for other implementations.

I certainly expected it to be removed when I proposed the change.

@xenu
Copy link
Member

xenu commented Dec 5, 2022

Leaving -fwrapv in for gcc doesn't stop this being undefined behavior for other implementations.

I agree we should avoid relying on signed integer overflow to keep our code portable.

Leaving it in masks undefined behavior defined by the C standard and means for our most common test cases (gcc) we aren't testing against what the C standard defines (or undefines).

The problem is that signed integer overflow doesn't cause hard errors. The compiler can silently and subtly break the code in ways that our test suite won't detect, even with with ASan. The behaviour is unpredictable, it varies from compiler to compiler and it may change in the future versions. It's scary. There's a reason why so many C codebases (for example, the Linux kernel) use both -fwrapv and -fno-strict-aliasing. Frankly, the C standard is broken.

My personal opinion is we should catch accidental signed overflows in our CI with e.g. ASan, but -fwrapv should stay enabled in production builds.

@iabyn
Copy link
Contributor

iabyn commented Dec 6, 2022 via email

@tonycoz
Copy link
Contributor Author

tonycoz commented Dec 8, 2022

You've largely convinced me, though we'll need to find a similar option for MSVC, since that also optimizes assuming no signed integer overflows (the mentioned switch wasn't accepted for me in compiler explorer).

I haven't been able to find any documentation of the optimization changes caused by -fwrapv in gcc (though the MSVC article gives one example for its optimization), but -fno-strict-aliasing has fairly obvious effects, eg:

int f(int * p1, float *p2) {
    if (*p1 == 2)
       *p2 = 0;
    
    return *p1;
}

Compiles to:

f:
        movl    (%rdi), %eax
        cmpl    $2, %eax
        je      .L4
        ret
.L4:
        movl    $0x00000000, (%rsi)
        movl    (%rdi), %eax  ; extra memory access added by -fno-strict-aliasing
        ret

Unfortunately perl uses type punning so extensively that I don't think we'll ever be able to use strict aliasing, though maybe we'll be able to use restrict in some places strategically to avoid this type of de-optimization.

Closing.

@tonycoz tonycoz closed this Dec 8, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

5 participants