diff --git a/examples/mandelbrot/assembly/index.ts b/examples/mandelbrot/assembly/index.ts index 57f2e18c..b7f2bb81 100644 --- a/examples/mandelbrot/assembly/index.ts +++ b/examples/mandelbrot/assembly/index.ts @@ -5,39 +5,47 @@ const NUM_COLORS = 2048; /** Computes a single line in the rectangle `width` x `height`. */ export function computeLine(y: u32, width: u32, height: u32, limit: u32): void { - var translateX = width / 1.6; - var translateY = height / 2.0; - var scale = 10.0 / min(3 * width, 4 * height); - var imaginary = (y - translateY) * scale; + var translateX = width * (1.0 / 1.6); + var translateY = height * (1.0 / 2.0); + var scale = 10.0 / min(3 * width, 4 * height); + var imaginary = (y - translateY) * scale; + var realOffset = translateX * scale; + var stride = (y * width) << 1; + var invLimit = 1.0 / limit; + + var minIterations = min(8, limit); + for (let x: u32 = 0; x < width; ++x) { - let real = (x - translateX) * scale; + let real = x * scale - realOffset; // Iterate until either the escape radius or iteration limit is exceeded let ix = 0.0, iy = 0.0, ixSq: f64, iySq: f64; let iteration: u32 = 0; while ((ixSq = ix * ix) + (iySq = iy * iy) <= 4.0) { - let ixNew = ixSq - iySq + real; iy = 2.0 * ix * iy + imaginary; - ix = ixNew; + ix = ixSq - iySq + real; if (iteration >= limit) break; ++iteration; } // Do a few extra iterations for quick escapes to reduce error margin - for (let minIterations = min(8, limit); iteration < minIterations; ++iteration) { + while (iteration < minIterations) { let ixNew = ix * ix - iy * iy + real; iy = 2.0 * ix * iy + imaginary; ix = ixNew; + ++iteration; } // Iteration count is a discrete value in the range [0, limit] here, but we'd like it to be // normalized in the range [0, 2047] so it maps to the gradient computed in JS. // see also: http://linas.org/art-gallery/escape/escape.html - let frac = Math.log(Math.log(Math.sqrt(ix * ix + iy * iy))) / Math.LN2; - let icol = isFinite(frac) - ? ((NUM_COLORS - 1) * clamp((iteration + 1 - frac) / limit, 0.0, 1.0)) - : NUM_COLORS - 1; - store((y * width + x) << 1, icol); + let col = NUM_COLORS - 1; + let sqd = ix * ix + iy * iy; + if (sqd > 1.0) { + let frac = Math.log2(0.5 * Math.log(sqd)); + col = ((NUM_COLORS - 1) * clamp((iteration + 1 - frac) * invLimit, 0.0, 1.0)); + } + store(stride + (x << 1), col); } } diff --git a/examples/mandelbrot/build/optimized.wasm b/examples/mandelbrot/build/optimized.wasm index f5ae8dc6..3439f616 100644 Binary files a/examples/mandelbrot/build/optimized.wasm and b/examples/mandelbrot/build/optimized.wasm differ diff --git a/examples/mandelbrot/build/optimized.wat b/examples/mandelbrot/build/optimized.wat index 97b5fa3b..7897c937 100644 --- a/examples/mandelbrot/build/optimized.wat +++ b/examples/mandelbrot/build/optimized.wat @@ -3,9 +3,8 @@ (type $FF (func (param f64) (result f64))) (type $v (func)) (import "env" "memory" (memory $0 0)) - (import "Math" "LN2" (global $~lib/bindings/Math/LN2 f64)) - (import "Math" "sqrt" (func $~lib/bindings/Math/sqrt (param f64) (result f64))) (import "Math" "log" (func $~lib/bindings/Math/log (param f64) (result f64))) + (import "Math" "log2" (func $~lib/bindings/Math/log2 (param f64) (result f64))) (table $0 1 anyfunc) (elem (i32.const 0) $null) (export "memory" (memory $0)) @@ -21,15 +20,13 @@ (local $10 f64) (local $11 f64) (local $12 f64) - get_local $1 - f64.convert_u/i32 - tee_local $6 - f64.const 1.6 - f64.div - set_local $12 + (local $13 f64) + (local $14 f64) f64.const 10 f64.const 3 - get_local $6 + get_local $1 + f64.convert_u/i32 + tee_local $8 f64.mul f64.const 4 get_local $2 @@ -42,12 +39,34 @@ get_local $0 f64.convert_u/i32 get_local $4 - f64.const 2 - f64.div + f64.const 0.5 + f64.mul f64.sub get_local $9 f64.mul set_local $10 + get_local $8 + f64.const 0.625 + f64.mul + get_local $9 + f64.mul + set_local $12 + get_local $0 + get_local $1 + i32.mul + i32.const 1 + i32.shl + set_local $0 + f64.const 1 + get_local $3 + f64.convert_u/i32 + tee_local $6 + f64.div + set_local $13 + f64.const 8 + get_local $6 + f64.min + set_local $8 loop $repeat|0 get_local $7 get_local $1 @@ -55,10 +74,10 @@ if get_local $7 f64.convert_u/i32 - get_local $12 - f64.sub get_local $9 f64.mul + get_local $12 + f64.sub set_local $11 f64.const 0 set_local $4 @@ -70,11 +89,11 @@ get_local $4 get_local $4 f64.mul - tee_local $6 + tee_local $14 get_local $5 get_local $5 f64.mul - tee_local $8 + tee_local $6 f64.add f64.const 4 f64.le @@ -88,8 +107,8 @@ get_local $10 f64.add set_local $5 + get_local $14 get_local $6 - get_local $8 f64.sub get_local $11 f64.add @@ -106,15 +125,10 @@ end end end - f64.const 8 - get_local $3 - f64.convert_u/i32 - f64.min - set_local $6 - loop $repeat|2 + loop $continue|2 get_local $2 f64.convert_u/i32 - get_local $6 + get_local $8 f64.lt if get_local $4 @@ -126,7 +140,7 @@ f64.sub get_local $11 f64.add - set_local $8 + set_local $6 f64.const 2 get_local $4 f64.mul @@ -135,22 +149,20 @@ get_local $10 f64.add set_local $5 - get_local $8 + get_local $6 set_local $4 get_local $2 i32.const 1 i32.add set_local $2 - br $repeat|2 + br $continue|2 end end - get_local $0 - get_local $1 - i32.mul get_local $7 - i32.add i32.const 1 i32.shl + get_local $0 + i32.add get_local $4 get_local $4 f64.mul @@ -158,27 +170,23 @@ get_local $5 f64.mul f64.add - call $~lib/bindings/Math/sqrt - call $~lib/bindings/Math/log - call $~lib/bindings/Math/log - get_global $~lib/bindings/Math/LN2 - f64.div tee_local $6 - get_local $6 - f64.sub - f64.const 0 - f64.eq + f64.const 1 + f64.gt if (result i32) f64.const 2047 get_local $2 i32.const 1 i32.add f64.convert_u/i32 + f64.const 0.5 get_local $6 + call $~lib/bindings/Math/log + f64.mul + call $~lib/bindings/Math/log2 f64.sub - get_local $3 - f64.convert_u/i32 - f64.div + get_local $13 + f64.mul f64.const 0 f64.max f64.const 1 diff --git a/examples/mandelbrot/build/untouched.wat b/examples/mandelbrot/build/untouched.wat index 7fd33eb0..d4e960db 100644 --- a/examples/mandelbrot/build/untouched.wat +++ b/examples/mandelbrot/build/untouched.wat @@ -1,13 +1,11 @@ (module (type $iiiiv (func (param i32 i32 i32 i32))) (type $FF (func (param f64) (result f64))) - (type $Fi (func (param f64) (result i32))) (type $FFFF (func (param f64 f64 f64) (result f64))) (type $v (func)) (import "env" "memory" (memory $0 0)) - (import "Math" "LN2" (global $~lib/bindings/Math/LN2 f64)) - (import "Math" "sqrt" (func $~lib/bindings/Math/sqrt (param f64) (result f64))) (import "Math" "log" (func $~lib/bindings/Math/log (param f64) (result f64))) + (import "Math" "log2" (func $~lib/bindings/Math/log2 (param f64) (result f64))) (table $0 1 anyfunc) (elem (i32.const 0) $null) (global $assembly/index/NUM_COLORS i32 (i32.const 2048)) @@ -15,44 +13,45 @@ (export "memory" (memory $0)) (export "table" (table $0)) (export "computeLine" (func $assembly/index/computeLine)) - (func $~lib/builtins/isFinite (; 2 ;) (type $Fi) (param $0 f64) (result i32) - get_local $0 - get_local $0 - f64.sub - f64.const 0 - f64.eq - ) - (func $assembly/index/clamp (; 3 ;) (type $FFFF) (param $0 f64) (param $1 f64) (param $2 f64) (result f64) + (func $assembly/index/clamp (; 2 ;) (type $FFFF) (param $0 f64) (param $1 f64) (param $2 f64) (result f64) get_local $0 get_local $1 f64.max get_local $2 f64.min ) - (func $assembly/index/computeLine (; 4 ;) (type $iiiiv) (param $0 i32) (param $1 i32) (param $2 i32) (param $3 i32) + (func $assembly/index/computeLine (; 3 ;) (type $iiiiv) (param $0 i32) (param $1 i32) (param $2 i32) (param $3 i32) (local $4 f64) (local $5 f64) (local $6 f64) (local $7 f64) - (local $8 i32) - (local $9 f64) + (local $8 f64) + (local $9 i32) (local $10 f64) (local $11 f64) - (local $12 f64) + (local $12 i32) (local $13 f64) - (local $14 i32) + (local $14 f64) (local $15 f64) (local $16 f64) - (local $17 i32) + (local $17 f64) + (local $18 i32) + (local $19 f64) + (local $20 i32) + (local $21 f64) get_local $1 f64.convert_u/i32 + f64.const 1 f64.const 1.6 f64.div + f64.mul set_local $4 get_local $2 f64.convert_u/i32 + f64.const 1 f64.const 2 f64.div + f64.mul set_local $5 f64.const 10 f64.const 3 @@ -73,179 +72,189 @@ get_local $6 f64.mul set_local $7 + get_local $4 + get_local $6 + f64.mul + set_local $8 + get_local $0 + get_local $1 + i32.mul + i32.const 1 + i32.shl + set_local $9 + f64.const 1 + get_local $3 + f64.convert_u/i32 + f64.div + set_local $10 + f64.const 8 + get_local $3 + f64.convert_u/i32 + f64.min + set_local $11 block $break|0 i32.const 0 - set_local $8 + set_local $12 loop $repeat|0 - get_local $8 + get_local $12 get_local $1 i32.lt_u i32.eqz br_if $break|0 block - get_local $8 + get_local $12 f64.convert_u/i32 - get_local $4 - f64.sub get_local $6 f64.mul - set_local $9 + get_local $8 + f64.sub + set_local $13 f64.const 0 - set_local $10 - f64.const 0 - set_local $11 - i32.const 0 set_local $14 + f64.const 0 + set_local $15 + i32.const 0 + set_local $18 block $break|1 loop $continue|1 - get_local $10 - get_local $10 + get_local $14 + get_local $14 f64.mul - tee_local $12 - get_local $11 - get_local $11 + tee_local $16 + get_local $15 + get_local $15 f64.mul - tee_local $13 + tee_local $17 f64.add f64.const 4 f64.le if block - get_local $12 - get_local $13 - f64.sub - get_local $9 - f64.add - set_local $15 f64.const 2 - get_local $10 + get_local $14 f64.mul - get_local $11 + get_local $15 f64.mul get_local $7 f64.add - set_local $11 - get_local $15 - set_local $10 - get_local $14 + set_local $15 + get_local $16 + get_local $17 + f64.sub + get_local $13 + f64.add + set_local $14 + get_local $18 get_local $3 i32.ge_u if br $break|1 end - get_local $14 + get_local $18 i32.const 1 i32.add - set_local $14 + set_local $18 end br $continue|1 end end end block $break|2 - f64.const 8 - get_local $3 - f64.convert_u/i32 - f64.min - set_local $15 - loop $repeat|2 - get_local $14 + loop $continue|2 + get_local $18 f64.convert_u/i32 - get_local $15 + get_local $11 f64.lt - i32.eqz - br_if $break|2 - block - get_local $10 - get_local $10 - f64.mul - get_local $11 - get_local $11 - f64.mul - f64.sub - get_local $9 - f64.add - set_local $16 - f64.const 2 - get_local $10 - f64.mul - get_local $11 - f64.mul - get_local $7 - f64.add - set_local $11 - get_local $16 - set_local $10 + if + block + get_local $14 + get_local $14 + f64.mul + get_local $15 + get_local $15 + f64.mul + f64.sub + get_local $13 + f64.add + set_local $19 + f64.const 2 + get_local $14 + f64.mul + get_local $15 + f64.mul + get_local $7 + f64.add + set_local $15 + get_local $19 + set_local $14 + get_local $18 + i32.const 1 + i32.add + set_local $18 + end + br $continue|2 end - get_local $14 - i32.const 1 - i32.add - set_local $14 - br $repeat|2 - unreachable end - unreachable end - get_local $10 - get_local $10 + get_global $assembly/index/NUM_COLORS + i32.const 1 + i32.sub + set_local $20 + get_local $14 + get_local $14 f64.mul - get_local $11 - get_local $11 + get_local $15 + get_local $15 f64.mul f64.add - call $~lib/bindings/Math/sqrt - call $~lib/bindings/Math/log - call $~lib/bindings/Math/log - get_global $~lib/bindings/Math/LN2 - f64.div - set_local $15 - get_local $15 - call $~lib/builtins/isFinite - if (result i32) + set_local $19 + get_local $19 + f64.const 1 + f64.gt + if + f64.const 0.5 + get_local $19 + call $~lib/bindings/Math/log + f64.mul + call $~lib/bindings/Math/log2 + set_local $21 get_global $assembly/index/NUM_COLORS i32.const 1 i32.sub f64.convert_s/i32 - get_local $14 + get_local $18 i32.const 1 i32.add f64.convert_u/i32 - get_local $15 + get_local $21 f64.sub - get_local $3 - f64.convert_u/i32 - f64.div + get_local $10 + f64.mul f64.const 0 f64.const 1 call $assembly/index/clamp f64.mul i32.trunc_u/f64 - else - get_global $assembly/index/NUM_COLORS - i32.const 1 - i32.sub + set_local $20 end - set_local $17 - get_local $0 - get_local $1 - i32.mul - get_local $8 - i32.add + get_local $9 + get_local $12 i32.const 1 i32.shl - get_local $17 + i32.add + get_local $20 i32.store16 end - get_local $8 + get_local $12 i32.const 1 i32.add - set_local $8 + set_local $12 br $repeat|0 unreachable end unreachable end ) - (func $null (; 5 ;) (type $v) + (func $null (; 4 ;) (type $v) ) ) diff --git a/examples/mandelbrot/index.html b/examples/mandelbrot/index.html index a0853643..1b733499 100644 --- a/examples/mandelbrot/index.html +++ b/examples/mandelbrot/index.html @@ -30,14 +30,19 @@ var ctx = cnv.getContext("2d"); var bcr = cnv.getBoundingClientRect(); // Compute the size of the viewport -var width = bcr.width | 0; +var width = bcr.width | 0; var height = bcr.height | 0; +var ratio = window.devicePixelRatio || 1; +width *= ratio; +height *= ratio; var size = width * height; var byteSize = size << 1; // discrete color indices in range [0, 2047] (here: 2b per pixel) -cnv.width = width; +cnv.width = width; cnv.height = height; +ctx.scale(ratio, ratio); + // Compute the size of and instantiate the module's memory var memory = new WebAssembly.Memory({ initial: ((byteSize + 0xffff) & ~0xffff) >>> 16 }); var mem = new Uint16Array(memory.buffer); @@ -48,7 +53,7 @@ var argb = new Uint32Array(imageData.data.buffer); fetch("build/optimized.wasm") .then(response => response.arrayBuffer()) .then(buffer => WebAssembly.instantiate(buffer, { - env: { memory: memory }, + env: { memory }, Math })) .then(module => { @@ -56,7 +61,9 @@ fetch("build/optimized.wasm") var computeLine = exports.computeLine; var updateLine = function(y) { var yx = y * width; - for (let x = 0; x < width; ++x) argb[yx + x] = colors[mem[yx + x]]; + for (let x = 0; x < width; ++x) { + argb[yx + x] = colors[mem[yx + x]]; + } }; // Compute an initial balanced version of the set. diff --git a/tests/compiler/mandelbrot.optimized.wat b/tests/compiler/mandelbrot.optimized.wat index ffa196bd..4ab4a130 100644 --- a/tests/compiler/mandelbrot.optimized.wat +++ b/tests/compiler/mandelbrot.optimized.wat @@ -186,7 +186,213 @@ f64.mul f64.add ) - (func $../../examples/mandelbrot/assembly/index/computeLine (; 1 ;) (type $iiiiv) (param $0 i32) (param $1 i32) (param $2 i32) (param $3 i32) + (func $~lib/math/NativeMath.log2 (; 1 ;) (type $FF) (param $0 f64) (result f64) + (local $1 f64) + (local $2 i32) + (local $3 i32) + (local $4 i32) + (local $5 i64) + (local $6 f64) + (local $7 f64) + (local $8 f64) + get_local $0 + i64.reinterpret/f64 + tee_local $5 + i64.const 32 + i64.shr_u + i32.wrap/i64 + tee_local $2 + i32.const 1048576 + i32.lt_u + tee_local $3 + i32.eqz + if + get_local $2 + i32.const 31 + i32.shr_u + set_local $3 + end + get_local $3 + if + get_local $5 + i64.const 1 + i64.shl + i64.const 0 + i64.eq + if + f64.const -1 + get_local $0 + get_local $0 + f64.mul + f64.div + return + end + get_local $2 + i32.const 31 + i32.shr_u + if + get_local $0 + get_local $0 + f64.sub + f64.const 0 + f64.div + return + end + i32.const -54 + set_local $4 + get_local $0 + f64.const 18014398509481984 + f64.mul + i64.reinterpret/f64 + tee_local $5 + i64.const 32 + i64.shr_u + i32.wrap/i64 + set_local $2 + else + get_local $2 + i32.const 2146435072 + i32.ge_u + if + get_local $0 + return + else + get_local $2 + i32.const 1072693248 + i32.eq + tee_local $3 + if + get_local $5 + i64.const 32 + i64.shl + i64.const 0 + i64.eq + set_local $3 + end + get_local $3 + if + f64.const 0 + return + end + end + end + get_local $2 + i32.const 614242 + i32.add + tee_local $2 + i32.const 20 + i32.shr_u + i32.const 1023 + i32.sub + get_local $4 + i32.add + set_local $4 + get_local $5 + i64.const 4294967295 + i64.and + get_local $2 + i32.const 1048575 + i32.and + i32.const 1072079006 + i32.add + i64.extend_u/i32 + i64.const 32 + i64.shl + i64.or + f64.reinterpret/i64 + f64.const 1 + f64.sub + tee_local $1 + f64.const 2 + get_local $1 + f64.add + f64.div + tee_local $6 + get_local $6 + f64.mul + tee_local $7 + get_local $7 + f64.mul + set_local $0 + get_local $1 + get_local $1 + f64.const 0.5 + get_local $1 + f64.mul + get_local $1 + f64.mul + tee_local $1 + f64.sub + i64.reinterpret/f64 + i64.const -4294967296 + i64.and + f64.reinterpret/i64 + tee_local $8 + f64.sub + get_local $1 + f64.sub + get_local $6 + get_local $1 + get_local $7 + f64.const 0.6666666666666735 + get_local $0 + f64.const 0.2857142874366239 + get_local $0 + f64.const 0.1818357216161805 + get_local $0 + f64.const 0.14798198605116586 + f64.mul + f64.add + f64.mul + f64.add + f64.mul + f64.add + f64.mul + get_local $0 + f64.const 0.3999999999940942 + get_local $0 + f64.const 0.22222198432149784 + get_local $0 + f64.const 0.15313837699209373 + f64.mul + f64.add + f64.mul + f64.add + f64.mul + f64.add + f64.add + f64.mul + f64.add + tee_local $0 + get_local $8 + f64.add + f64.const 1.6751713164886512e-10 + f64.mul + get_local $0 + f64.const 1.4426950407214463 + f64.mul + f64.add + set_local $6 + get_local $4 + f64.convert_s/i32 + tee_local $7 + get_local $8 + f64.const 1.4426950407214463 + f64.mul + tee_local $1 + f64.add + set_local $0 + get_local $6 + get_local $7 + get_local $0 + f64.sub + get_local $1 + f64.add + f64.add + get_local $0 + f64.add + ) + (func $../../examples/mandelbrot/assembly/index/computeLine (; 2 ;) (type $iiiiv) (param $0 i32) (param $1 i32) (param $2 i32) (param $3 i32) (local $4 f64) (local $5 f64) (local $6 f64) @@ -196,15 +402,13 @@ (local $10 f64) (local $11 f64) (local $12 f64) - get_local $1 - f64.convert_u/i32 - tee_local $6 - f64.const 1.6 - f64.div - set_local $12 + (local $13 f64) + (local $14 f64) f64.const 10 f64.const 3 - get_local $6 + get_local $1 + f64.convert_u/i32 + tee_local $8 f64.mul f64.const 4 get_local $2 @@ -217,12 +421,34 @@ get_local $0 f64.convert_u/i32 get_local $4 - f64.const 2 - f64.div + f64.const 0.5 + f64.mul f64.sub get_local $9 f64.mul set_local $10 + get_local $8 + f64.const 0.625 + f64.mul + get_local $9 + f64.mul + set_local $12 + get_local $0 + get_local $1 + i32.mul + i32.const 1 + i32.shl + set_local $0 + f64.const 1 + get_local $3 + f64.convert_u/i32 + tee_local $6 + f64.div + set_local $13 + f64.const 8 + get_local $6 + f64.min + set_local $8 loop $repeat|0 get_local $7 get_local $1 @@ -230,10 +456,10 @@ if get_local $7 f64.convert_u/i32 - get_local $12 - f64.sub get_local $9 f64.mul + get_local $12 + f64.sub set_local $11 f64.const 0 set_local $4 @@ -245,11 +471,11 @@ get_local $4 get_local $4 f64.mul - tee_local $6 + tee_local $14 get_local $5 get_local $5 f64.mul - tee_local $8 + tee_local $6 f64.add f64.const 4 f64.le @@ -263,8 +489,8 @@ get_local $10 f64.add set_local $5 + get_local $14 get_local $6 - get_local $8 f64.sub get_local $11 f64.add @@ -281,15 +507,10 @@ end end end - f64.const 8 - get_local $3 - f64.convert_u/i32 - f64.min - set_local $6 - loop $repeat|2 + loop $continue|2 get_local $2 f64.convert_u/i32 - get_local $6 + get_local $8 f64.lt if get_local $4 @@ -301,7 +522,7 @@ f64.sub get_local $11 f64.add - set_local $8 + set_local $6 f64.const 2 get_local $4 f64.mul @@ -310,22 +531,20 @@ get_local $10 f64.add set_local $5 - get_local $8 + get_local $6 set_local $4 get_local $2 i32.const 1 i32.add set_local $2 - br $repeat|2 + br $continue|2 end end - get_local $0 - get_local $1 - i32.mul get_local $7 - i32.add i32.const 1 i32.shl + get_local $0 + i32.add get_local $4 get_local $4 f64.mul @@ -333,27 +552,23 @@ get_local $5 f64.mul f64.add - f64.sqrt - call $~lib/math/NativeMath.log - call $~lib/math/NativeMath.log - f64.const 0.6931471805599453 - f64.div tee_local $6 - get_local $6 - f64.sub - f64.const 0 - f64.eq + f64.const 1 + f64.gt if (result i32) f64.const 2047 get_local $2 i32.const 1 i32.add f64.convert_u/i32 + f64.const 0.5 get_local $6 + call $~lib/math/NativeMath.log + f64.mul + call $~lib/math/NativeMath.log2 f64.sub - get_local $3 - f64.convert_u/i32 - f64.div + get_local $13 + f64.mul f64.const 0 f64.max f64.const 1 @@ -372,7 +587,7 @@ end end ) - (func $null (; 2 ;) (type $v) + (func $null (; 3 ;) (type $v) nop ) ) diff --git a/tests/compiler/mandelbrot.untouched.wat b/tests/compiler/mandelbrot.untouched.wat index d7bb76e9..ee048390 100644 --- a/tests/compiler/mandelbrot.untouched.wat +++ b/tests/compiler/mandelbrot.untouched.wat @@ -1,14 +1,12 @@ (module (type $iiiiv (func (param i32 i32 i32 i32))) (type $FF (func (param f64) (result f64))) - (type $Fi (func (param f64) (result i32))) (type $FFFF (func (param f64 f64 f64) (result f64))) (type $v (func)) (memory $0 0) (table $0 1 anyfunc) (elem (i32.const 0) $null) (global $../../examples/mandelbrot/assembly/index/NUM_COLORS i32 (i32.const 2048)) - (global $~lib/math/NativeMath.LN2 f64 (f64.const 0.6931471805599453)) (global $HEAP_BASE i32 (i32.const 8)) (export "memory" (memory $0)) (export "table" (table $0)) @@ -226,12 +224,261 @@ f64.mul f64.add ) - (func $~lib/builtins/isFinite (; 1 ;) (type $Fi) (param $0 f64) (result i32) + (func $~lib/math/NativeMath.log2 (; 1 ;) (type $FF) (param $0 f64) (result f64) + (local $1 i64) + (local $2 i32) + (local $3 i32) + (local $4 i32) + (local $5 f64) + (local $6 f64) + (local $7 f64) + (local $8 f64) + (local $9 f64) + (local $10 f64) + (local $11 f64) + (local $12 f64) + (local $13 f64) + (local $14 f64) + (local $15 f64) + (local $16 f64) + (local $17 f64) get_local $0 + i64.reinterpret/f64 + set_local $1 + get_local $1 + i64.const 32 + i64.shr_u + i32.wrap/i64 + set_local $2 + i32.const 0 + set_local $3 + get_local $2 + i32.const 1048576 + i32.lt_u + tee_local $4 + if (result i32) + get_local $4 + else + get_local $2 + i32.const 31 + i32.shr_u + end + if + get_local $1 + i64.const 1 + i64.shl + i64.const 0 + i64.eq + if + f64.const -1 + get_local $0 + get_local $0 + f64.mul + f64.div + return + end + get_local $2 + i32.const 31 + i32.shr_u + if + get_local $0 + get_local $0 + f64.sub + f64.const 0 + f64.div + return + end + get_local $3 + i32.const 54 + i32.sub + set_local $3 + get_local $0 + f64.const 18014398509481984 + f64.mul + set_local $0 + get_local $0 + i64.reinterpret/f64 + set_local $1 + get_local $1 + i64.const 32 + i64.shr_u + i32.wrap/i64 + set_local $2 + else + get_local $2 + i32.const 2146435072 + i32.ge_u + if + get_local $0 + return + else + get_local $2 + i32.const 1072693248 + i32.eq + tee_local $4 + if (result i32) + get_local $1 + i64.const 32 + i64.shl + i64.const 0 + i64.eq + else + get_local $4 + end + if + f64.const 0 + return + end + end + end + get_local $2 + i32.const 1072693248 + i32.const 1072079006 + i32.sub + i32.add + set_local $2 + get_local $3 + get_local $2 + i32.const 20 + i32.shr_u + i32.const 1023 + i32.sub + i32.add + set_local $3 + get_local $2 + i32.const 1048575 + i32.and + i32.const 1072079006 + i32.add + set_local $2 + get_local $2 + i64.extend_u/i32 + i64.const 32 + i64.shl + get_local $1 + i64.const 4294967295 + i64.and + i64.or + set_local $1 + get_local $1 + f64.reinterpret/i64 + set_local $0 get_local $0 + f64.const 1 f64.sub - f64.const 0 - f64.eq + set_local $5 + f64.const 0.5 + get_local $5 + f64.mul + get_local $5 + f64.mul + set_local $6 + get_local $5 + f64.const 2 + get_local $5 + f64.add + f64.div + set_local $7 + get_local $7 + get_local $7 + f64.mul + set_local $8 + get_local $8 + get_local $8 + f64.mul + set_local $9 + get_local $9 + f64.const 0.3999999999940942 + get_local $9 + f64.const 0.22222198432149784 + get_local $9 + f64.const 0.15313837699209373 + f64.mul + f64.add + f64.mul + f64.add + f64.mul + set_local $10 + get_local $8 + f64.const 0.6666666666666735 + get_local $9 + f64.const 0.2857142874366239 + get_local $9 + f64.const 0.1818357216161805 + get_local $9 + f64.const 0.14798198605116586 + f64.mul + f64.add + f64.mul + f64.add + f64.mul + f64.add + f64.mul + set_local $11 + get_local $11 + get_local $10 + f64.add + set_local $12 + get_local $5 + get_local $6 + f64.sub + set_local $13 + get_local $13 + i64.reinterpret/f64 + set_local $1 + get_local $1 + i64.const -4294967296 + i64.and + set_local $1 + get_local $1 + f64.reinterpret/i64 + set_local $13 + get_local $5 + get_local $13 + f64.sub + get_local $6 + f64.sub + get_local $7 + get_local $6 + get_local $12 + f64.add + f64.mul + f64.add + set_local $14 + get_local $13 + f64.const 1.4426950407214463 + f64.mul + set_local $15 + get_local $14 + get_local $13 + f64.add + f64.const 1.6751713164886512e-10 + f64.mul + get_local $14 + f64.const 1.4426950407214463 + f64.mul + f64.add + set_local $16 + get_local $3 + f64.convert_s/i32 + set_local $17 + get_local $17 + get_local $15 + f64.add + set_local $9 + get_local $16 + get_local $17 + get_local $9 + f64.sub + get_local $15 + f64.add + f64.add + set_local $16 + get_local $9 + set_local $15 + get_local $16 + get_local $15 + f64.add ) (func $../../examples/mandelbrot/assembly/index/clamp (; 2 ;) (type $FFFF) (param $0 f64) (param $1 f64) (param $2 f64) (result f64) get_local $0 @@ -245,25 +492,33 @@ (local $5 f64) (local $6 f64) (local $7 f64) - (local $8 i32) - (local $9 f64) + (local $8 f64) + (local $9 i32) (local $10 f64) (local $11 f64) - (local $12 f64) + (local $12 i32) (local $13 f64) - (local $14 i32) + (local $14 f64) (local $15 f64) (local $16 f64) - (local $17 i32) + (local $17 f64) + (local $18 i32) + (local $19 f64) + (local $20 i32) + (local $21 f64) get_local $1 f64.convert_u/i32 + f64.const 1 f64.const 1.6 f64.div + f64.mul set_local $4 get_local $2 f64.convert_u/i32 + f64.const 1 f64.const 2 f64.div + f64.mul set_local $5 f64.const 10 f64.const 3 @@ -284,177 +539,183 @@ get_local $6 f64.mul set_local $7 + get_local $4 + get_local $6 + f64.mul + set_local $8 + get_local $0 + get_local $1 + i32.mul + i32.const 1 + i32.shl + set_local $9 + f64.const 1 + get_local $3 + f64.convert_u/i32 + f64.div + set_local $10 + f64.const 8 + get_local $3 + f64.convert_u/i32 + f64.min + set_local $11 block $break|0 i32.const 0 - set_local $8 + set_local $12 loop $repeat|0 - get_local $8 + get_local $12 get_local $1 i32.lt_u i32.eqz br_if $break|0 block - get_local $8 + get_local $12 f64.convert_u/i32 - get_local $4 - f64.sub get_local $6 f64.mul - set_local $9 + get_local $8 + f64.sub + set_local $13 f64.const 0 - set_local $10 - f64.const 0 - set_local $11 - i32.const 0 set_local $14 + f64.const 0 + set_local $15 + i32.const 0 + set_local $18 block $break|1 loop $continue|1 - get_local $10 - get_local $10 + get_local $14 + get_local $14 f64.mul - tee_local $12 - get_local $11 - get_local $11 + tee_local $16 + get_local $15 + get_local $15 f64.mul - tee_local $13 + tee_local $17 f64.add f64.const 4 f64.le if block - get_local $12 - get_local $13 - f64.sub - get_local $9 - f64.add - set_local $15 f64.const 2 - get_local $10 + get_local $14 f64.mul - get_local $11 + get_local $15 f64.mul get_local $7 f64.add - set_local $11 - get_local $15 - set_local $10 - get_local $14 + set_local $15 + get_local $16 + get_local $17 + f64.sub + get_local $13 + f64.add + set_local $14 + get_local $18 get_local $3 i32.ge_u if br $break|1 end - get_local $14 + get_local $18 i32.const 1 i32.add - set_local $14 + set_local $18 end br $continue|1 end end end block $break|2 - f64.const 8 - get_local $3 - f64.convert_u/i32 - f64.min - set_local $15 - loop $repeat|2 - get_local $14 + loop $continue|2 + get_local $18 f64.convert_u/i32 - get_local $15 + get_local $11 f64.lt - i32.eqz - br_if $break|2 - block - get_local $10 - get_local $10 - f64.mul - get_local $11 - get_local $11 - f64.mul - f64.sub - get_local $9 - f64.add - set_local $16 - f64.const 2 - get_local $10 - f64.mul - get_local $11 - f64.mul - get_local $7 - f64.add - set_local $11 - get_local $16 - set_local $10 + if + block + get_local $14 + get_local $14 + f64.mul + get_local $15 + get_local $15 + f64.mul + f64.sub + get_local $13 + f64.add + set_local $19 + f64.const 2 + get_local $14 + f64.mul + get_local $15 + f64.mul + get_local $7 + f64.add + set_local $15 + get_local $19 + set_local $14 + get_local $18 + i32.const 1 + i32.add + set_local $18 + end + br $continue|2 end - get_local $14 - i32.const 1 - i32.add - set_local $14 - br $repeat|2 - unreachable end - unreachable end - block $~lib/math/NativeMath.sqrt|inlined.0 (result f64) - get_local $10 - get_local $10 - f64.mul - get_local $11 - get_local $11 - f64.mul - f64.add - set_local $15 - get_local $15 - f64.sqrt - end - call $~lib/math/NativeMath.log - call $~lib/math/NativeMath.log - get_global $~lib/math/NativeMath.LN2 - f64.div - set_local $15 + get_global $../../examples/mandelbrot/assembly/index/NUM_COLORS + i32.const 1 + i32.sub + set_local $20 + get_local $14 + get_local $14 + f64.mul get_local $15 - call $~lib/builtins/isFinite - if (result i32) + get_local $15 + f64.mul + f64.add + set_local $19 + get_local $19 + f64.const 1 + f64.gt + if + f64.const 0.5 + get_local $19 + call $~lib/math/NativeMath.log + f64.mul + call $~lib/math/NativeMath.log2 + set_local $21 get_global $../../examples/mandelbrot/assembly/index/NUM_COLORS i32.const 1 i32.sub f64.convert_s/i32 - get_local $14 + get_local $18 i32.const 1 i32.add f64.convert_u/i32 - get_local $15 + get_local $21 f64.sub - get_local $3 - f64.convert_u/i32 - f64.div + get_local $10 + f64.mul f64.const 0 f64.const 1 call $../../examples/mandelbrot/assembly/index/clamp f64.mul i32.trunc_u/f64 - else - get_global $../../examples/mandelbrot/assembly/index/NUM_COLORS - i32.const 1 - i32.sub + set_local $20 end - set_local $17 - get_local $0 - get_local $1 - i32.mul - get_local $8 - i32.add + get_local $9 + get_local $12 i32.const 1 i32.shl - get_local $17 + i32.add + get_local $20 i32.store16 end - get_local $8 + get_local $12 i32.const 1 i32.add - set_local $8 + set_local $12 br $repeat|0 unreachable end diff --git a/tests/compiler/std/array.optimized.wat b/tests/compiler/std/array.optimized.wat index ec3331c4..85b419a5 100644 --- a/tests/compiler/std/array.optimized.wat +++ b/tests/compiler/std/array.optimized.wat @@ -13318,13 +13318,13 @@ i32.const 0 get_global $std/array/newArr i32.load - tee_local $0 + tee_local $1 i32.load i32.const 2 i32.shr_u i32.lt_u if (result f32) - get_local $0 + get_local $1 f32.load offset=8 else unreachable @@ -13332,13 +13332,13 @@ i32.const 0 get_global $std/array/arr i32.load - tee_local $0 + tee_local $1 i32.load i32.const 2 i32.shr_u i32.lt_u if (result i32) - get_local $0 + get_local $1 i32.load offset=8 else unreachable @@ -13887,9 +13887,9 @@ i32.const 0 set_global $~argc get_global $std/array/f32ArrayTyped - set_local $1 - i32.const 0 set_local $0 + i32.const 0 + set_local $1 block $1of1 block $0of1 block $outOfRange @@ -13899,10 +13899,10 @@ unreachable end i32.const 44 - set_local $0 + set_local $1 end - get_local $1 get_local $0 + get_local $1 call $~lib/array/Array#sort drop get_global $std/array/f32ArrayTyped @@ -13919,9 +13919,9 @@ i32.const 0 set_global $~argc get_global $std/array/f64ArrayTyped - set_local $1 - i32.const 0 set_local $0 + i32.const 0 + set_local $1 block $1of153 block $0of154 block $outOfRange55 @@ -13931,10 +13931,10 @@ unreachable end i32.const 45 - set_local $0 + set_local $1 end - get_local $1 get_local $0 + get_local $1 call $~lib/array/Array#sort drop get_global $std/array/f64ArrayTyped @@ -13951,9 +13951,9 @@ i32.const 0 set_global $~argc get_global $std/array/i32ArrayTyped - set_local $1 - i32.const 0 set_local $0 + i32.const 0 + set_local $1 block $1of156 block $0of157 block $outOfRange58 @@ -13963,10 +13963,10 @@ unreachable end i32.const 46 - set_local $0 + set_local $1 end - get_local $1 get_local $0 + get_local $1 call $~lib/array/Array#sort drop get_global $std/array/i32ArrayTyped @@ -13985,9 +13985,9 @@ i32.const 0 set_global $~argc get_global $std/array/u32ArrayTyped - set_local $1 - i32.const 0 set_local $0 + i32.const 0 + set_local $1 block $1of159 block $0of160 block $outOfRange61 @@ -13997,10 +13997,10 @@ unreachable end i32.const 47 - set_local $0 + set_local $1 end - get_local $1 get_local $0 + get_local $1 call $~lib/array/Array#sort drop get_global $std/array/u32ArrayTyped