summaryrefslogtreecommitdiff
path: root/src/wasm/wasm-binary.cpp
diff options
context:
space:
mode:
authorAlon Zakai <azakai@google.com>2024-07-18 11:21:23 -0700
committerGitHub <noreply@github.com>2024-07-18 11:21:23 -0700
commitb91966f7999175e8b03da9a7a9dcdb07e4749fb1 (patch)
tree10e8a1decebfb26ff32bd0d28a5ed5c343aa8f04 /src/wasm/wasm-binary.cpp
parent08436189d3f35c958872b34bf8b0a8575e186d27 (diff)
downloadbinaryen-b91966f7999175e8b03da9a7a9dcdb07e4749fb1.tar.gz
binaryen-b91966f7999175e8b03da9a7a9dcdb07e4749fb1.tar.bz2
binaryen-b91966f7999175e8b03da9a7a9dcdb07e4749fb1.zip
Monomorphize all the things (#6760)
Previously call operands were monomorphized (considered as part of the call context, so we can create a specialized function with those operands fixed) if they were constant or had a different type than the function parameter's type. This generalizes that to pull in pretty much all the code we possibly can, including nested code. For example: (call $foo (struct.new $struct (i32.const 10) (local.get $x) (local.get $y) ) ) This can turn into (call $foo_mono (local.get $x) (local.get $y) ) The struct.new and even one of the struct.new's children is moved into the called function, replacing the original ref argument with two other ones. If the original called function was this: (func $foo (param $ref (ref ..)) .. ) then the monomorphized function then looks like this: (func $foo_mono (param $x i32) (param $y i32) (local $ref (ref ..)) (local.set $ref (struct.new $struct (i32.const 10) (local.get $x) (local.get $y) ) ) .. ) The struct.new and its constant child appear here, and we read the parameters. To do this, generalize the code that creates the call context to accept everything that is impossible to copy (like a local.get) or that would be tricky and likely unworthwhile (like another call or a tuple). Also check for effect interactions, as this code motion does some reordering. For this to work, we need to adjust how we compute the costs we compare when deciding what to monomorphize. Before we just compared the called function to the monomorphized called function, which was good enough when the call context only contained consts, but now it can contain arbitrarily nested code. The proper comparison is between these two: * Old function + call context * New monomorphized function Including the call context makes this a fair comparison. In the example above, the struct.new and the i32.const are part of the call context, and so they are in the monomorphized function, so if we didn't count them in other function we'd decide not to optimize anything with a large context. The new functionality is tested in a new file. A few parts of existing tests needed changes to not become pointless after this improvement, namely by replacing stuff that we now optimize with things that we don't like replacing an i32.eqz with a local.get. There are also a handful of test outcomes that change in CAREFUL mode due to the new cost analysis.
Diffstat (limited to 'src/wasm/wasm-binary.cpp')
0 files changed, 0 insertions, 0 deletions