-
Notifications
You must be signed in to change notification settings - Fork 151
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
tests: Avoid UB with abs of minimum integral value #262
Conversation
The most negative number doesn't have an absolute value that can be represented in the same type.
But it's not UB, which is why this corner case should still be tested. short a = -32768;
short b = std::abs(a); means |
C++11, C++14, and C++17 seem to disagree, the relevant passage reads:
So strictly speaking, my classification as UB is wrong but a test relying on implementation-defined behavior should still be fixed. If you agree that this should be fixed, I'll change the commit message. |
For the record, the change that removed the above text is cplusplus/draft@3b7ee00. P1236R1 is marked as done in Clang 9, so I still don't understand where 32767 comes from... |
Ah, I briefly forgot one important point: While the test failure is about
|
Right. After we made signed integers be two's complement in C++20 there's no need for implementation-defined behavior here anymore. But implementation-defined means the compiler must document the behavior and stick to it. For x86 that behavior is whatever the hardware does for all the compilers I checked. Yes, for |
To motivate testing & supporting this corner case: if you port scalar code over to Vc you want as few silent behavior changes as possible. Even if the use of |
I understand that, but please note that there's no guarantee that |
yes, I've seen that and it might be a good idea to test SHORT_MIN explicitly even |
I think what's really required here is to understand where the value 32767 comes from. I've tried to reproduce this locally with a custom build of Clang 11, both with |
https://godbolt.org/z/hGsaY1 It may be due to an old libstdc++ that clang 11 is using on this machine |
That's with GCC 6.3.0? I don't get this with Clang 11.
AFAICT Clang expands the call to |
found it. Clang 11 autovectorizes the scalar vpmovsxwd ymm1,xmm0
vextracti128 xmm2,ymm1,0x1
vcvtdq2pd ymm2,xmm2
vcvtdq2pd ymm1,xmm1
vmovupd ymm3,YMMWORD PTR [rsp+0x80]
vandpd ymm1,ymm1,ymm3
vandpd ymm2,ymm2,ymm3
vcvttpd2dq xmm2,ymm2
vcvttpd2dq xmm1,ymm1
vpackssdw xmm1,xmm1,xmm2 So it converts to two AVX double vectors, evaluates |
Adding |
Hm, I don't see this locally either. I'm looking at |
I'll merge your fix and will add: using T = typename V::value_type;
if (std::is_same<T, short>::value)
{
const V a = std::numeric_limits<T>::lowest();
COMPARE(abs(a), a);
} |
In fact I think they provided a templated version of |
My addition leads to failure on old libstdc++ when a |
Alternatively, you'll have to cast the argument to |
37d48ab should fix it for good now |
The most negative number doesn't have an absolute value that can
be represented in the same type.