diff options
Diffstat (limited to 'src/dataflow/utils.h')
-rw-r--r-- | src/dataflow/utils.h | 145 |
1 files changed, 145 insertions, 0 deletions
diff --git a/src/dataflow/utils.h b/src/dataflow/utils.h new file mode 100644 index 000000000..5328e6ab7 --- /dev/null +++ b/src/dataflow/utils.h @@ -0,0 +1,145 @@ +/* + * Copyright 2018 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. + */ + +// +// DataFlow IR is an SSA representation. It can be built from the main +// Binaryen IR. +// +// THe main initial use case was an IR that could easily be converted to +// Souper IR, and the design favors that. +// + +#ifndef wasm_dataflow_utils_h +#define wasm_dataflow_utils_h + +#include "wasm.h" +#include "wasm-printing.h" +#include "dataflow/node.h" + +namespace wasm { + +namespace DataFlow { + +inline std::ostream& dump(Node* node, std::ostream& o, size_t indent = 0) { + auto doIndent = [&]() { + for (size_t i = 0; i < indent; i++) o << ' '; + }; + doIndent(); + o << '[' << node << ' '; + switch (node->type) { + case Node::Type::Var: o << "var " << printType(node->wasmType) << ' ' << node; break; + case Node::Type::Expr: { + o << "expr "; + WasmPrinter::printExpression(node->expr, o, true); + break; + } + case Node::Type::Phi: o << "phi " << node->index; break; + case Node::Type::Cond: o << "cond " << node->index; break; + case Node::Type::Block: { + // don't print the conds - they would recurse + o << "block (" << node->values.size() << " conds)]\n"; + return o; + } + case Node::Type::Zext: o << "zext"; break; + case Node::Type::Bad: o << "bad"; break; + default: WASM_UNREACHABLE(); + } + if (!node->values.empty()) { + o << '\n'; + for (auto* value : node->values) { + dump(value, o, indent + 1); + } + doIndent(); + } + o << "] (origin: " << (void*)(node->origin) << ")\n"; + return o; +} + +inline std::ostream& dump(Graph& graph, std::ostream& o) { + for (auto& node : graph.nodes) { + o << "NODE " << node.get() << ": "; + dump(node.get(), o); + if (auto* set = graph.getSet(node.get())) { + o << " and that is set to local " << set->index << '\n'; + } + } + return o; +} + +// Checks if the inputs are all identical - something we could +// probably optimize. Returns false if irrelevant. +inline bool allInputsIdentical(Node* node) { + switch (node->type) { + case Node::Type::Expr: { + if (node->expr->is<Binary>()) { + return *(node->getValue(0)) == *(node->getValue(1)); + } else if (node->expr->is<Select>()) { + return *(node->getValue(1)) == *(node->getValue(2)); + } + break; + } + case Node::Type::Phi: { + auto* first = node->getValue(1); + // Check if any of the others are not equal + for (Index i = 2; i < node->values.size(); i++) { + auto* curr = node->getValue(i); + if (*first != *curr) { + return false; + } + } + return true; + } + default: {} + } + return false; +} + +// Checks if the inputs are all constant - something we could +// probably optimize. Returns false if irrelevant. +inline bool allInputsConstant(Node* node) { + switch (node->type) { + case Node::Type::Expr: { + if (node->expr->is<Unary>()) { + return node->getValue(0)->isConst(); + } else if (node->expr->is<Binary>()) { + return node->getValue(0)->isConst() && + node->getValue(1)->isConst(); + } else if (node->expr->is<Select>()) { + return node->getValue(0)->isConst() && + node->getValue(1)->isConst() && + node->getValue(2)->isConst(); + } + break; + } + case Node::Type::Phi: { + // Check if any of the others are not equal + for (Index i = 1; i < node->values.size(); i++) { + if (!node->getValue(i)->isConst()) { + return false; + } + } + return true; + } + default: {} + } + return false; +} + +} // namespace DataFlow + +} // namespace wasm + +#endif // wasm_dataflow_utils |