From cd7f11eda240bb28b3648efcaee2a29c8ed1d609 Mon Sep 17 00:00:00 2001 From: Ashelyn Rose Date: Sun, 3 Sep 2023 01:19:07 -0600 Subject: [PATCH] wasm optimizations --- scripts/wasm-life-2/game.wat | 173 +++++++++++++++++++++++++++++------ 1 file changed, 143 insertions(+), 30 deletions(-) diff --git a/scripts/wasm-life-2/game.wat b/scripts/wasm-life-2/game.wat index c0a8813..e9223f0 100644 --- a/scripts/wasm-life-2/game.wat +++ b/scripts/wasm-life-2/game.wat @@ -154,9 +154,71 @@ i32.store8 ) + (func $setNewValueAtPosition (param $row i32) (param $column i32) (param $value i32) + (local $position i32) + local.get $row + local.get $column + call $getIndexForPosition + + local.tee $position + i32.const 0 + i32.lt_s + + if + return + end + + global.get $boardBufferLength + call $getBoardPtr + i32.xor + local.get $position + i32.add + local.get $value + i32.store8 + ) + (func $getNewValueAtPosition (param $row i32) (param $column i32) (result i32) (local $count i32) + (local $current i32) + local.get $row + i32.const 1 + i32.lt_u + local.get $row + global.get $boardHeight + i32.const 1 + i32.sub + i32.ge_u + + local.get $column + i32.const 1 + i32.lt_u + + local.get $column + global.get $boardWidth + i32.const 1 + i32.sub + i32.ge_u + + ;; if any of the boundary conditions are true + i32.or + i32.or + i32.or + + if (result i32 i32) + local.get $row + local.get $column + call $getNeighborCountBoundary + else + local.get $row + local.get $column + call $getNeighborCountCenter + end + + call $getOutcomeFromCountAndCurrent + ) + + (func $getNeighborCountBoundary (param $row i32) (param $column i32) (result i32 i32) local.get $row i32.const 1 i32.sub @@ -213,6 +275,7 @@ i32.add call $getValueAtPosition + ;; sum neightbor count i32.add i32.add i32.add @@ -221,39 +284,91 @@ i32.add i32.add - ;; Exactly 3 neighbors - local.tee $count - i32.const 3 - i32.eq + ;; get current + local.get $row + local.get $column + call $getValueAtPosition + ) - if - ;; becomes or stays alive - i32.const 1 - return - end + (func $getNeighborCountCenter (param $row i32) (param $column i32) (result i32 i32) ;; neighborCount, currentValue + (local $origIndex i32) + (local $rowAbove i32) + (local $rowCenter i32) + (local $rowBelow i32) - ;; If currently dead + ;; store current cell's memory position + call $getBoardPtr local.get $row local.get $column - call $getValueAtPosition - i32.eqz - if - ;; Stay dead - i32.const 0 - return - end + call $getIndexForPosition + i32.add + local.tee $origIndex - ;; 2 neighbors - local.get $count - i32.const 2 - i32.eq - if - i32.const 1 - return - end + ;; load the three rows + i32.const 1 + i32.sub + i32.load + local.set $rowCenter - i32.const 0 - return + local.get $origIndex + i32.const 1 + i32.sub + global.get $boardWidth + i32.sub + i32.load + local.set $rowAbove + + local.get $origIndex + i32.const 1 + i32.sub + global.get $boardWidth + i32.add + i32.load + local.set $rowBelow + + ;; count the number of alive neighbors in each row + local.get $rowAbove + i32.const 0x00_01_01_01 + i32.and + i32.popcnt + + local.get $rowCenter + i32.const 0x00_01_00_01 + i32.and + i32.popcnt + + + local.get $rowBelow + i32.const 0x00_01_01_01 + i32.and + i32.popcnt + + ;; sum neighbor count + i32.add + i32.add + + ;; get current + local.get $rowCenter + i32.const 0x00_00_01_00 + i32.and + i32.popcnt + ) + + (func $getOutcomeFromCountAndCurrent (param $neighborCount i32) (param $current i32) (result i32) + ;; get sentinal value for current count + i32.const 1 + local.get $neighborCount + i32.shl + + ;; get value mask for current state + i32.const 0xC ;;alive mask (1100, 3 or 2 neighbors) + i32.const 0x8 ;;dead mask (1000, exactly three neighbors) + local.get $current + select + + ;; mask out to see if we still have a bit + i32.and + i32.popcnt ) (func $tick (export "tick") @@ -280,12 +395,10 @@ local.set $value ;; place in next board - call $swapBoards local.get $row local.get $column local.get $value - call $setValueAtPosition - call $swapBoards + call $setNewValueAtPosition ;; increment column local.get $column