/* * Copyright 2022 WebAssembly Community Group participants * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #ifndef wasm_pass_param_utils_h #define wasm_pass_param_utils_h #include "pass.h" #include "support/sorted_vector.h" #include "wasm.h" // Helper code for passes that manipulate function parameters, specifically // checking if they are used and removing them if so. This is closely tied to // the internals of those passes, and so is not in /ir/ (it would be inside the // pass .cpp file, but there is more than one). namespace wasm::ParamUtils { // Find which parameters are actually used in the function, that is, that the // values arriving in the parameter are read. This ignores values set in the // function, like this: // // function foo(x) { // x = 10; // bar(x); // read of a param index, but not the param value passed in. // } // // This is an actual use: // // function foo(x) { // bar(x); // read of a param value // } std::unordered_set getUsedParams(Function* func, Module* module); // The outcome of an attempt to remove a parameter(s). enum RemovalOutcome { // We removed successfully. Success = 0, // We failed, but only because of fixable nested effects. The caller can move // those effects out (e.g. using ChildLocalizer, or the helper localizeCallsTo // below) and repeat. Failure = 1, }; // Try to remove a parameter from a set of functions and replace it with a local // instead. This may not succeed if the parameter type cannot be used in a // local, or if we hit another limitation, in which case this returns false and // does nothing. If we succeed then the parameter is removed both from the // functions and from the calls to it, which are passed in (the caller must // ensure to pass in all relevant calls and call_refs). // // This does not check if removing the parameter would change the semantics // (say, if the parameter's value is used), which the caller is assumed to do. // // This assumes that the set of functions all have the same signature. The main // use cases are either to send a single function, or to send a set of functions // that all have the same heap type (and so if they all do not use some // parameter, it can be removed from them all). // // This does *not* update the types in call_refs. It is assumed that the caller // will be updating types, which is simpler as there may be other locations that // need adjusting and it is easier to do it all in one place. Also, the caller // can update all the types at once throughout the program after making // multiple calls to removeParameter(). RemovalOutcome removeParameter(const std::vector& funcs, Index index, const std::vector& calls, const std::vector& callRefs, Module* module, PassRunner* runner); // The same as removeParameter, but gets a sorted list of indexes. It tries to // remove them all, and returns which we removed, as well as an indication as // to whether we might remove more if effects were not in the way (specifically, // we return Success if we removed any index, Failure if we removed none, and // FailureDueToEffects if at least one index could have been removed but for // effects). std::pair removeParameters(const std::vector& funcs, SortedVector indexes, const std::vector& calls, const std::vector& callRefs, Module* module, PassRunner* runner); // Given a set of functions and the calls and call_refs that reach them, find // which parameters are passed the same constant value in all the calls. For // each such parameter, apply it inside the function, that is, do a local.set of // that value in the function. The parameter's incoming value is then ignored, // which allows other optimizations to remove it. // // Returns the indexes that were optimized. SortedVector applyConstantValues(const std::vector& funcs, const std::vector& calls, const std::vector& callRefs, Module* module); // Helper that localizes all calls to a set of targets, in an entire module. // This basically calls ChildLocalizer in each function, on the relevant calls. // This is useful when we get FailureDueToEffects, see above. // // The set of targets can be function names (the individual functions we want to // handle calls towards) or heap types (which will then include all functions // with those types). // // The onChange() callback is called when we modify a function. void localizeCallsTo(const std::unordered_set& callTargets, Module& wasm, PassRunner* runner, std::function onChange); void localizeCallsTo(const std::unordered_set& callTargets, Module& wasm, PassRunner* runner); } // namespace wasm::ParamUtils #endif // wasm_pass_param_utils_h