| /* | |
| * Copyright 2021 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_ir_reorderer_h | |
| #define wasm_ir_reorderer_h | |
| #include <ir/effects.h> | |
| #include <wasm-builder.h> | |
| namespace wasm { | |
| // | |
| // Given two expressions that appear in a specific order - first and then | |
| // second - this helper can create a sequence in which we return the value of | |
| // the first. If the two expressions can be reordered, this simply returns | |
| // | |
| // (second, first) | |
| // | |
| // If side effects prevent that, it will use a local to save the value of the | |
| // first, and return it at the end, | |
| // | |
| // (temp = first, second, temp) | |
| // | |
| // The first expression is assumed to not be unreachable (otherwise, there is no | |
| // value to get the result of). If the second is unreachable, this returns | |
| // something with type unreachable (that avoids returning something with a | |
| // concrete type, which might replace something with unreachable type - we want | |
| // to keep the type the same, in most cases). | |
| inline Expression* getResultOfFirst(Expression* first, | |
| Expression* second, | |
| Function* func, | |
| Module* wasm, | |
| const PassOptions& passOptions) { | |
| assert(first->type.isConcrete()); | |
| Builder builder(*wasm); | |
| if (second->type == Type::unreachable) { | |
| // No value is actually consumed here. Emit something with unreachable type. | |
| // (Note that if we continued to the canReorder code after us, and emitted | |
| // second followed by first, then the block would have a concrete type due | |
| // to the last element having such a type - which would not have unreachable | |
| // type.) | |
| return builder.makeSequence(builder.makeDrop(first), second); | |
| } | |
| if (EffectAnalyzer::canReorder(passOptions, *wasm, first, second)) { | |
| return builder.makeSequence(second, first); | |
| } | |
| auto type = first->type; | |
| auto index = Builder::addVar(func, type); | |
| return builder.makeBlock({builder.makeLocalSet(index, first), | |
| second, | |
| builder.makeLocalGet(index, type)}); | |
| } | |
| } // namespace wasm | |
| #endif // wasm_ir_reorderer_h |