summaryrefslogtreecommitdiff
path: root/src/dataflow/utils.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/dataflow/utils.h')
-rw-r--r--src/dataflow/utils.h145
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