WebKit Bugzilla
New
Browse
Log In
×
Sign in with GitHub
or
Remember my login
Create Account
·
Forgot Password
Forgotten password account recovery
RESOLVED FIXED
Bug 198106
WebAssembly: pow functions returns 0 when exponent 1.0 or -1.0
https://bugs.webkit.org/show_bug.cgi?id=198106
Summary
WebAssembly: pow functions returns 0 when exponent 1.0 or -1.0
Philipp
Reported
2019-05-22 04:37:14 PDT
This issue occured when we updated from Emscripten 1.38.6 to 1.38.30 (might appear before) but it only showed up on iOS 12.2/12.3/12.4 Beta. That's why I'm posting this here. This code has unexpected behaviour when the exponent is 1.0 or -1.0, i.e. the function returns 0. The code in C++ is: // wasm_bug.cpp #include <emscripten/bind.h> #include <cstdio> void pow_test(double exp) { printf("pow(10, %f): %f\n", exp, pow(10.0, exp)); } EMSCRIPTEN_BINDINGS() { emscripten::function("pow_test", &pow_test); } compiled with: emcc --bind -O2 wasm_bug.cpp -o out.js
Attachments
Binary from emcc v1.38.31
(43.46 KB, application/x-javascript)
2019-05-28 13:25 PDT
,
Justin Michaud
no flags
Details
Binary from emcc v1.38.31 (Wasm)
(26.88 KB, application/octet-stream)
2019-05-28 13:28 PDT
,
Justin Michaud
no flags
Details
Text format output from wabt
(296.29 KB, text/plain)
2019-05-28 13:28 PDT
,
Justin Michaud
no flags
Details
Pow test module
(60.13 KB, application/x-javascript)
2019-06-05 11:21 PDT
,
Justin Michaud
no flags
Details
Pow test module
(26.88 KB, application/octet-stream)
2019-06-05 11:21 PDT
,
Justin Michaud
no flags
Details
Patch
(3.52 KB, patch)
2019-06-05 11:25 PDT
,
Justin Michaud
no flags
Details
Formatted Diff
Diff
Patch
(6.45 KB, patch)
2019-06-05 16:44 PDT
,
Justin Michaud
no flags
Details
Formatted Diff
Diff
Patch
(6.45 KB, patch)
2019-06-05 16:46 PDT
,
Justin Michaud
no flags
Details
Formatted Diff
Diff
Show Obsolete
(5)
View All
Add attachment
proposed patch, testcase, etc.
Radar WebKit Bug Importer
Comment 1
2019-05-22 16:25:46 PDT
<
rdar://problem/51047345
>
Justin Michaud
Comment 2
2019-05-28 13:25:37 PDT
Created
attachment 370778
[details]
Binary from emcc v1.38.31
Justin Michaud
Comment 3
2019-05-28 13:28:08 PDT
Comment hidden (obsolete)
Created
attachment 370780
[details]
Binary from emcc v1.38.31 (Wasm)
> jsc -e "var Module = { onRuntimeInitialized: function() { Module.pow_test(1); } };" out.js
Should supposedly reproduce the issue.
Justin Michaud
Comment 4
2019-05-28 13:28:52 PDT
Comment hidden (obsolete)
Created
attachment 370781
[details]
Text format output from wabt
Justin Michaud
Comment 5
2019-05-28 16:46:47 PDT
Comment hidden (obsolete)
powTest (func $func25 (param $var0 f64) (local $var1 i32) (local $var2 f64) get_global $global5 set_local $var1 get_global $global5 i32.const 16 i32.add set_global $global5 get_local $var0 call $func56 set_local $var2 get_local $var1 get_local $var0 f64.store get_local $var1 i32.const 8 i32.add get_local $var2 f64.store get_local $var1 call $func55 get_local $var1 set_global $global5 ) Math.pow (func $func56 (param $var0 f64) (result f64) (local $var1 i32) (local $var2 i32) (local $var3 i32) (local $var4 i32) (local $var5 i32) (local $var6 i64) (local $var7 f64) (local $var8 f64) (local $var9 f64) (local $var10 f64) (local $var11 f64) (local $var12 f64) (local $var13 f64) (local $var14 f64) get_local $var0 i64.reinterpret/f64 tee_local $var6 i64.const 32 i64.shr_u i32.wrap/i64 tee_local $var4 i32.const 2147483647 i32.and tee_local $var1 get_local $var6 i32.wrap/i64 tee_local $var3 i32.or i32.eqz if f64.const 1 return end get_local $var1 i32.const 2146435072 i32.le_u if get_local $var1 i32.const 2146435072 i32.eq tee_local $var5 get_local $var3 i32.const 0 i32.ne i32.and i32.eqz if block $label1 block $label0 get_local $var3 i32.eqz br_if $label0 br $label1 end $label0 get_local $var5 if get_local $var0 f64.const 0.0 get_local $var4 i32.const -1 i32.gt_s select return end get_local $var1 i32.const 1072693248 i32.eq if f64.const 10 f64.const 0.1 get_local $var4 i32.const -1 i32.gt_s select return end get_local $var4 i32.const 1073741824 i32.eq if f64.const 100 return end get_local $var4 i32.const 1071644672 i32.eq if f64.const 3.1622776601683795 return end end $label1 f64.const 1 set_local $var10 get_local $var1 i32.const 1105199104 i32.gt_u if (result f64) get_local $var1 i32.const 1139802112 i32.gt_u if get_global $global4 f64.const 0.0 get_local $var4 i32.const 0 i32.gt_s select return end get_local $var10 f64.const 1e+300 f64.mul f64.const 1e+300 f64.mul get_local $var10 f64.const 1e-300 f64.mul f64.const 1e-300 f64.mul get_local $var4 i32.const 0 i32.gt_s select return else i32.const 1 tee_local $var3 i32.const 3 i32.shl i32.const 1536 i32.add f64.load tee_local $var13 f64.const 1.25 get_local $var3 i32.const 3 i32.shl i32.const 1504 i32.add f64.load tee_local $var12 f64.sub tee_local $var11 f64.const 1 get_local $var12 f64.const 1.25 f64.add f64.div tee_local $var9 f64.mul tee_local $var8 i64.reinterpret/f64 i64.const -4294967296 i64.and f64.reinterpret/i64 tee_local $var7 get_local $var7 get_local $var7 f64.mul tee_local $var14 f64.const 3 f64.add get_local $var8 get_local $var7 f64.add get_local $var9 get_local $var11 get_local $var3 i32.const 18 i32.shl i32.const 1073872896 i32.add i64.extend_u/i32 i64.const 32 i64.shl f64.reinterpret/i64 tee_local $var11 get_local $var7 f64.mul f64.sub f64.const 1.25 get_local $var11 get_local $var12 f64.sub f64.sub get_local $var7 f64.mul f64.sub f64.mul tee_local $var9 f64.mul get_local $var8 get_local $var8 f64.mul tee_local $var7 get_local $var7 f64.mul get_local $var7 get_local $var7 get_local $var7 get_local $var7 get_local $var7 f64.const 0.20697501780033842 f64.mul f64.const 0.23066074577556175 f64.add f64.mul f64.const 0.272728123808534 f64.add f64.mul f64.const 0.33333332981837743 f64.add f64.mul f64.const 0.4285714285785502 f64.add f64.mul f64.const 0.5999999999999946 f64.add f64.mul f64.add tee_local $var12 f64.add i64.reinterpret/f64 i64.const -4294967296 i64.and f64.reinterpret/i64 tee_local $var7 f64.mul tee_local $var11 get_local $var9 get_local $var7 f64.mul get_local $var8 get_local $var12 get_local $var7 f64.const -3 f64.add get_local $var14 f64.sub f64.sub f64.mul f64.add tee_local $var8 f64.add i64.reinterpret/f64 i64.const -4294967296 i64.and f64.reinterpret/i64 tee_local $var7 f64.const 0.9617967009544373 f64.mul tee_local $var9 get_local $var3 i32.const 3 i32.shl i32.const 1520 i32.add f64.load get_local $var8 get_local $var7 get_local $var11 f64.sub f64.sub f64.const 0.9617966939259756 f64.mul get_local $var7 f64.const 7.028461650952758e-9 f64.mul f64.sub f64.add tee_local $var7 f64.add f64.add f64.const 3 f64.add i64.reinterpret/f64 i64.const -4294967296 i64.and f64.reinterpret/i64 tee_local $var11 set_local $var8 get_local $var11 f64.const 3 f64.sub get_local $var13 f64.sub get_local $var9 f64.sub end set_local $var9 get_local $var7 get_local $var9 f64.sub get_local $var0 f64.mul get_local $var0 get_local $var6 i64.const -4294967296 i64.and f64.reinterpret/i64 tee_local $var7 f64.sub get_local $var8 f64.mul f64.add set_local $var0 get_local $var8 get_local $var7 f64.mul tee_local $var7 get_local $var0 f64.add tee_local $var8 i64.reinterpret/f64 tee_local $var6 i64.const 32 i64.shr_u i32.wrap/i64 set_local $var2 get_local $var6 i32.wrap/i64 set_local $var1 get_local $var2 i32.const 1083179007 i32.gt_s if get_local $var1 get_local $var2 i32.const -1083179008 i32.add i32.or if get_local $var10 f64.const 1e+300 f64.mul f64.const 1e+300 f64.mul return end get_local $var0 f64.const 8.008566259537294e-17 f64.add get_local $var8 get_local $var7 f64.sub f64.gt if get_local $var10 f64.const 1e+300 f64.mul f64.const 1e+300 f64.mul return end else get_local $var2 i32.const 2147482624 i32.and i32.const 1083231231 i32.gt_u if get_local $var1 get_local $var2 i32.const 1064252416 i32.add i32.or if get_local $var10 f64.const 1e-300 f64.mul f64.const 1e-300 f64.mul return end get_local $var0 get_local $var8 get_local $var7 f64.sub f64.le if get_local $var10 f64.const 1e-300 f64.mul f64.const 1e-300 f64.mul return end end end get_local $var2 i32.const 2147483647 i32.and tee_local $var1 i32.const 1071644672 i32.gt_u if (result i32) get_local $var7 i32.const -1048576 get_local $var2 i32.const 1048576 get_local $var1 i32.const 20 i32.shr_u i32.const -1022 i32.add i32.shr_u i32.add tee_local $var1 i32.const 20 i32.shr_u i32.const 2047 i32.and tee_local $var3 i32.const -1023 i32.add i32.shr_s get_local $var1 i32.and i64.extend_u/i32 i64.const 32 i64.shl f64.reinterpret/i64 f64.sub tee_local $var8 set_local $var7 get_local $var0 get_local $var8 f64.add i64.reinterpret/f64 set_local $var6 i32.const 0 get_local $var1 i32.const 1048575 i32.and i32.const 1048576 i32.or i32.const 1043 get_local $var3 i32.sub i32.shr_u tee_local $var1 i32.sub get_local $var1 get_local $var2 i32.const 0 i32.lt_s select else i32.const 0 end set_local $var2 get_local $var10 f64.const 1 get_local $var6 i64.const -4294967296 i64.and f64.reinterpret/i64 tee_local $var8 f64.const 0.6931471824645996 f64.mul tee_local $var9 get_local $var0 get_local $var8 get_local $var7 f64.sub f64.sub f64.const 0.6931471805599453 f64.mul get_local $var8 f64.const 1.904654299957768e-9 f64.mul f64.sub tee_local $var8 f64.add tee_local $var7 get_local $var7 get_local $var7 get_local $var7 f64.mul tee_local $var0 get_local $var0 get_local $var0 get_local $var0 get_local $var0 f64.const 4.1381367970572385e-8 f64.mul f64.const -0.0000016533902205465252 f64.add f64.mul f64.const 0.00006613756321437934 f64.add f64.mul f64.const -0.0027777777777015593 f64.add f64.mul f64.const 0.16666666666666602 f64.add f64.mul f64.sub tee_local $var0 f64.mul get_local $var0 f64.const -2 f64.add f64.div get_local $var8 get_local $var7 get_local $var9 f64.sub f64.sub tee_local $var0 get_local $var7 get_local $var0 f64.mul f64.add f64.sub get_local $var7 f64.sub f64.sub tee_local $var7 i64.reinterpret/f64 tee_local $var6 i64.const 32 i64.shr_u i32.wrap/i64 get_local $var2 i32.const 20 i32.shl i32.add tee_local $var1 i32.const 1048576 i32.lt_s if (result f64) get_local $var7 get_local $var2 call $func39 else get_local $var6 i64.const 4294967295 i64.and get_local $var1 i64.extend_u/i32 i64.const 32 i64.shl i64.or f64.reinterpret/i64 end f64.mul return end end f64.const 10 get_local $var0 f64.add ) Not sure what this does: (func $func39 (param $var0 f64) (param $var1 i32) (result f64) (local $var2 i32) (local $var3 i32) get_local $var1 i32.const 1023 i32.gt_s if get_local $var0 f64.const 8.98846567431158e+307 f64.mul tee_local $var0 f64.const 8.98846567431158e+307 f64.mul get_local $var0 get_local $var1 i32.const 2046 i32.gt_s tee_local $var2 select set_local $var0 get_local $var1 i32.const -2046 i32.add tee_local $var3 i32.const 1023 get_local $var3 i32.const 1023 i32.lt_s select get_local $var1 i32.const -1023 i32.add get_local $var2 select set_local $var1 else get_local $var1 i32.const -1022 i32.lt_s if get_local $var0 f64.const 2.2250738585072014e-308 f64.mul tee_local $var0 f64.const 2.2250738585072014e-308 f64.mul get_local $var0 get_local $var1 i32.const -2044 i32.lt_s tee_local $var2 select set_local $var0 get_local $var1 i32.const 2044 i32.add tee_local $var3 i32.const -1022 get_local $var3 i32.const -1022 i32.gt_s select get_local $var1 i32.const 1022 i32.add get_local $var2 select set_local $var1 end end get_local $var0 get_local $var1 i32.const 1023 i32.add i64.extend_u/i32 i64.const 52 i64.shl f64.reinterpret/i64 f64.mul )
Justin Michaud
Comment 6
2019-06-04 16:57:55 PDT
The following program exhibits different behavior on Mac/iOS: out.wat: (module (func (export "test") (result f64) f64.const 42 f64.const 42 i32.const -1 i32.const -1 i32.eq select )) out.js: import { test } from 'out.wasm' print("test: " + test()) Run as module with --wasmBBQUsesAir=0 --defaultB3OptLevel=0 to reproduce. iOS gives 0, Mac gives 42.
Yusuke Suzuki
Comment 7
2019-06-04 17:06:46 PDT
(In reply to Justin Michaud from
comment #6
)
> The following program exhibits different behavior on Mac/iOS: > > out.wat: > > (module > (func (export "test") (result f64) > f64.const 42 > f64.const 42 > i32.const -1 > i32.const -1 > i32.eq > select > )) > > out.js: > import { test } from 'out.wasm' > > print("test: " + test()) > > Run as module with --wasmBBQUsesAir=0 --defaultB3OptLevel=0 to reproduce. > iOS gives 0, Mac gives 42.
Nice! It sounds like a good starting point to investigate this problem.
Saam Barati
Comment 8
2019-06-04 18:49:18 PDT
(In reply to Justin Michaud from
comment #6
)
> The following program exhibits different behavior on Mac/iOS: > > out.wat: > > (module > (func (export "test") (result f64) > f64.const 42 > f64.const 42 > i32.const -1 > i32.const -1 > i32.eq > select > )) > > out.js: > import { test } from 'out.wasm' > > print("test: " + test()) > > Run as module with --wasmBBQUsesAir=0 --defaultB3OptLevel=0 to reproduce. > iOS gives 0, Mac gives 42.
If I were to guess, this is a bug in B3 strength reduction, or in B3 fold path constants
Saam Barati
Comment 9
2019-06-04 18:49:50 PDT
When I have bugs like this, I like to make B3 not run some optimization passes to isolate the issue
Justin Michaud
Comment 10
2019-06-05 11:21:07 PDT
Created
attachment 371421
[details]
Pow test module
Justin Michaud
Comment 11
2019-06-05 11:21:21 PDT
Created
attachment 371422
[details]
Pow test module
Justin Michaud
Comment 12
2019-06-05 11:25:21 PDT
Created
attachment 371423
[details]
Patch
Saam Barati
Comment 13
2019-06-05 11:27:36 PDT
Comment on
attachment 371423
[details]
Patch View in context:
https://bugs.webkit.org/attachment.cgi?id=371423&action=review
> Source/JavaScriptCore/assembler/MacroAssemblerARM64.h:2462 > + m_assembler.fcsel<64>(dest, thenCase, elseCase, ARM64Condition(cond));
Please also add a standalone testmasm test.
Saam Barati
Comment 14
2019-06-05 11:28:20 PDT
Comment on
attachment 371423
[details]
Patch View in context:
https://bugs.webkit.org/attachment.cgi?id=371423&action=review
> Source/JavaScriptCore/ChangeLog:8 > + Fix bug caused by using fcsel sX instead of fcsel dX on an f64 value in the wasm select opcode.
nit: This effects Wasm, but isn't just Wasm. It effects anyone using our macro assembler
Justin Michaud
Comment 15
2019-06-05 16:44:49 PDT
Created
attachment 371448
[details]
Patch
Justin Michaud
Comment 16
2019-06-05 16:46:17 PDT
Created
attachment 371449
[details]
Patch
WebKit Commit Bot
Comment 17
2019-06-05 17:29:00 PDT
Comment on
attachment 371449
[details]
Patch Clearing flags on attachment: 371449 Committed
r246134
: <
https://trac.webkit.org/changeset/246134
>
WebKit Commit Bot
Comment 18
2019-06-05 17:29:01 PDT
All reviewed patches have been landed. Closing bug.
Saam Barati
Comment 19
2019-06-05 18:22:38 PDT
Comment on
attachment 371449
[details]
Patch View in context:
https://bugs.webkit.org/attachment.cgi?id=371449&action=review
> Source/JavaScriptCore/assembler/testmasm.cpp:1088 > + RUN(testMoveDoubleConditionally32());
Nice!
Philipp
Comment 20
2019-08-09 06:42:56 PDT
I updated my iPad to 12.4 and tested my initial example. The problem still remains. Did this fix make it into 12.4?
CoreyDotCom
Comment 21
2019-09-13 14:36:15 PDT
Can someone please comment as to what version this is landing in and if the fix will make it to a 12.5? I work for Adobe and we have several projects being derailed because of this WASM issue. Thanks. @justin
CoreyDotCom
Comment 22
2019-09-13 14:38:23 PDT
For what it's worth it does seem fixed in ios 13 but obviously doesn't help our production users now.
Note
You need to
log in
before you can comment on or make changes to this bug.
Top of Page
Format For Printing
XML
Clone This Bug