-
Notifications
You must be signed in to change notification settings - Fork 3.4k
Explicitly recognise asm_float_zero #5046
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
Explicitly recognise asm_float_zero #5046
Conversation
Thanks! Looks correct. We should just add a test for this. I suggest adding it to
I'm surprised fuzzing didn't catch it - perhaps the fuzzer doesn't return floats? Otherwise, PRECISE_F32 + emterpreter don't have much overlap in the suite, and we do have some wasm + emterpreter tests, which as you say, would catch this if we returned a float, but they happen to not have that... |
It turns out my explanation for why this is happening is wrong. After I was unable to come up with a test, I looked again - Instead, it turns out that this is an optimization performed by
You can optimize this directly with
I guess registerizeHarder figures that the final return is dead, so it can replace it with whatever (possibly it shouldn't, given that optimizeFrounds tries so hard not to). So in fact, the combination of conditions required to see this issue is "have a float-returning function with an if/else at the end of the function with each branch returning something and being sufficiently complex that llvm does not attempt a simplification to just use the single dead return statement at the end of the function to return the value from the two branches (i.e. avoiding As you might imagine with the description above, it's actually pretty hard to come up with a test case here because llvm on Click to see unreduced asm.js for function
So, thoughts? I'm not really sure how to create a test case that doesn't heavily depend on details of the LLVM optimizer. |
Interesting. My guess is that there is special code in registerizeHarder to handle the final return in a function, which is special in asm.js, e.g. it must exist, even if right before it is an if-else which never returns, so sounds related to what you see there. One theory is it is removing it, then re-introducing a new return to ensure one exists, and it does that last part wrong. For testing, I'd say just add to |
Ok, I've added a couple of tests.
|
Great, thanks! We'll need to bump the version number so the c++ optimizer gets rebuilt. I'll do that later (til then the bots might show an error on that test). |
Looks like this broke |
Hmm, the test may be invalid, this is the right area,
Perhaps we are missing the declaration of |
Ah no, it's something else. PR coming soon. |
…w we detect f0 properly (since #5046), so we do notice float operations in more cases, which is why this went unnoticed before. we do all emterpreter math in doubles anyhow, so this just requires us to accept float ops and emit the same double ops
…cessary as no… (#5129) * support float versions of binary operations, which is necessary as now we detect f0 properly (since #5046), so we do notice float operations in more cases, which is why this went unnoticed before. we do all emterpreter math in doubles anyhow, so this just requires us to accept float ops and emit the same double ops * improve emterpreter makeBinary assertion message
With the bitcode I have, llvm (in
-O3
) generates (before any js opts) a return as follows:return +(+0);
with-s WASM=0
return Math_fround((Math_fround(+0)));
with-s WASM=1
(becausePRECISE_F32
is always enabled with wasm)Emscripten then performs JS opts (presumably to prepare for the emterpreter) in three steps:
asmPreciseF32 asm eliminate simplifyExpressions emitJSON
(native)asmPreciseF32 asm receiveJSON localCSE safeLabelSetting emitJSON
(non-native)asmPreciseF32 asm receiveJSON optimizeFrounds registerizeHarder asmLastOpts
(native)+(+0)
simplifies to+0
, but, courtesy ofoptimizeFrounds
,Math_fround((Math_fround(+0)));
simplifies to the variablef0
. Now theemterpretify
step is unable to figure out what the return type is (when detecting return type, the asmData isn't ready yet so isn't passed todetectType
and the variable type can't be detected). This PR explicitly matches against the global float zero.So the report in #5031 is more accurately expressed as "
-s EMTERPRETIFY=1
does not work withPRECISE_F32=1
", it's just that wasm made it obvious. I'm somewhat surprised that no code you've tested has exhibited this issue, but maybe code that returns aMath_fround
call is relatively rare and so is emterpreter testing with binaryen?