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
Possible bug when using -O2/-O3 in clang 13 for ARMv7 #52669
Comments
The good news is, it does reproduce in our of our armv8 dev containers. Your instructions were spot on, thanks! Built with the config from our quick bot: https://lab.llvm.org/buildbot/#/builders/171/builds/7188
Bisect found this change:
https://reviews.llvm.org/D92270 I'm not 100% sure of the "why" of the bug here, but I'm going to read more about it today. Others have reported issues with the change. |
Can you explain how you know that, is there a single place in WebKit that this happens? It would be good to compare what the code is doing to the reproducers that have already been logged against the change. Might be able to match one of those against what WebKit is doing. Certainly a few mention fp to int conversions. |
We store the inf value in a union: https://github.com/mikhailramalho/WebKit/blob/main/Source/JavaScriptCore/runtime/JSCJSValue.h#L95 But before it reaches the store, we do the following check: which is undefined behavior so maybe the value is being marked as poison and that's why it returns a different value every time? |
The line causing the issue is: https://github.com/mikhailramalho/WebKit/blob/main/Source/JavaScriptCore/runtime/JSGlobalObject.cpp#L706 Compiling with
9218868437227405312 is inf. When compiling with
You can see the poison and no store. |
Thanks. That there is a change in clang's ouptut is very clear. Off the top of my head I don't know whether we'd call this a regression or simply a change in UB which clang would be allowed to do (though there is sometimes argument to keep it as is). To be honest, I don't think I'm qualified to do so but the authors of that patch are. So with your knowledge of what WebKit is doing exactly, could you make a small reproducer in C? I did observe simple double to int32_t casts changing behaviour but wasn't sure of WebKit's exact use case and I don't want to miss communicate it. |
(not sure if this will be relevant, we'll see if it looks anything like your reproducer) https://reviews.llvm.org/D115804 just landed which means we use a saturating cast when the
|
Hi,
I tried adding the flag and it seems to work, but I still think that WebKit is correct here: while there is an undef behavior, that call checks if the double can be represented as an int32_t but never actually uses the int32_t. The path is:
But here Here's the bytecode generated by -O0:
Where the store is double. Here's the bytecode with -O3 using clang 12.1 and clang 13 if I revert the change in https://github.com/llvm/llvm-project/blob/main/llvm/lib/IR/ConstantFold.cpp#L462:
My guess is that clang is changing the store from double to i64, which then results in a poison value because the original type of the constant is a double. Does that make sense? Sorry, I'm not an expert on the optimizations LLVM performs so this is a wild guess. I'll try to remove the undef behavior call from WebKit, then I'll try to use bugpoint or llvm-reduce to try to reduce the generated bytecode (the -O1 is 306793 LOC). |
Why is canBeStrictInt32 false? It also performs a double -> int32_t cast on infinity, and as such is UB. |
Right, so you're saying that since there is undefined behavior there, clang can decide that |
Yes. We specify branch on poison as undefined behavior, though currently it will just pick one of the two branches. I think on the LLVM side everything is fine here, because the source program has undefined behavior. The only bit I find concerning is
because this problem should be caught by |
On Thu, 16 Dec 2021, 15:55 Nikita Popov, ***@***.***> wrote:
But here canBeStrictInt32 is false, so it jumps to the next statement in
JSValue::JSValue and stores as a double. But doing the check, does it
poisons both sides of the branch?
Why is canBeStrictInt32 false? It also performs a double -> int32_t cast
on infinity, and as such is UB.
Right, so you're saying that since there is undefined behavior there,
clang can decide that canBeStrictInt32 is true? That would explain the
problem.
Yes. We specify branch on poison as undefined behavior, though currently
it will just pick one of the two branches.
I think on the LLVM side everything is fine here, because the source
program has undefined behavior. The only bit I find concerning is
Using either -O2 or -O3 with address or the undef behavior sanitizers
doesn't trigger the issue.
because this problem *should* be caught by -fsanitize=float-cast-overflow.
IIRC undef behaviour does complain about it but we get the expected result,
the Infinity constant is initialized.
Is -fsanitize=float-cast-overflow enabled by default if we use
-fsanitize=address? I'll try it again tomorrow.
—
… Reply to this email directly, view it on GitHub
<#52669 (comment)>,
or unsubscribe
<https://github.com/notifications/unsubscribe-auth/AAKEJH452HB4QLXJWI552U3URI7ZVANCNFSM5J6YY2RQ>
.
Triage notifications on the go with GitHub Mobile for iOS
<https://apps.apple.com/app/apple-store/id1477376905?ct=notification-email&mt=8&pt=524675>
or Android
<https://play.google.com/store/apps/details?id=com.github.android&referrer=utm_campaign%3Dnotification-email%26utm_medium%3Demail%26utm_source%3Dgithub>.
You are receiving this because you authored the thread.Message ID:
***@***.***>
|
Ah okay, that's fine then.
It's not part of |
Closing this issue as it was an undefined behavior on WebKit. |
When I build JSC using either -O2 or -O3, I get random garbage when querying for the "Infinity" constant from javascript, as if the constant was not being initialized. The variable is being initialized correctly, that I'm sure.
Some tests I did:
It seems like some optimization introduced by -O2 is causing the issue.
Steps to reproduce:
To build JSC, you need to get WebKit from https://github.com/WebKit/WebKit (shallow clone is a friend here), and run:
$ ./Tools/Scripts/build-jsc --Release --jsc-only '--cmakeargs=-DCMAKE_CXX_COMPILER=<path-to-clang-13>/bin/clang++ -DCMAKE_C_COMPILER=<path-to-clang-13>/bin/clang'
Release by default builds with
-O3 -DNDEBUG
. JSC will be built inWebKitBuild/Release/bin/jsc
.To build the debug version, you must replace
--release
by--debug
, and JSC will be built inWebKitBuild/Debug/bin/jsc
. To rebuild, you can either remove the WebKitBuild dir, or go in WebKitBuild/Release/ and do a ninja clean + ninja.The program I'm using is:
JSC built in release mode (the value infinity changes every time):
Expected output:
I'm running the tests in:
The text was updated successfully, but these errors were encountered: