diff options
author | Alon Zakai <azakai@google.com> | 2021-04-20 18:03:54 -0700 |
---|---|---|
committer | GitHub <noreply@github.com> | 2021-04-20 18:03:54 -0700 |
commit | eb2581d89fee86ac11a1452a946f9c69d4173a48 (patch) | |
tree | 7e36052d5a1a2aaf75d00bc8b952e3ed9d26d00c /src | |
parent | 304658d67102d3ddd5aa8ea59bcc94402d8338b8 (diff) | |
download | binaryen-eb2581d89fee86ac11a1452a946f9c69d4173a48.tar.gz binaryen-eb2581d89fee86ac11a1452a946f9c69d4173a48.tar.bz2 binaryen-eb2581d89fee86ac11a1452a946f9c69d4173a48.zip |
Refactor Child*Iterator for simplicity and to allow modifications. NFC (#3826)
Instead of creating a class and doing a traversal, simply use
wasm-delegates-fields to get the children directly. This is simpler and
faster.
This requires a new way to override the behavior by ChildValueIterator.
I ended up using CRTP.
This stores pointers to the children instead of the children. This will
allow modifying the children using these classes (which is the reason
I started this refactoring - next PR will use it). This is also slightly
faster in theory as we avoid doing loads from memory to find the
children (which maybe we never get to doing if the iteration is stopped
early).
Not the goal here, but this speeds up roundtripping by 12%.
This is NFC as nothing uses the new ability to modify things yet.
Diffstat (limited to 'src')
-rw-r--r-- | src/ir/iteration.h | 102 |
1 files changed, 66 insertions, 36 deletions
diff --git a/src/ir/iteration.h b/src/ir/iteration.h index eb04a1e5f..a785fbc93 100644 --- a/src/ir/iteration.h +++ b/src/ir/iteration.h @@ -41,8 +41,9 @@ namespace wasm { // this instruction. For example, includes If::condition // but not If::ifTrue. // -template<template<class, class> class Scanner> class AbstractChildIterator { - using Self = AbstractChildIterator<Scanner>; +template<class Specific> class AbstractChildIterator { + using Self = AbstractChildIterator<Specific>; + struct Iterator { const Self& parent; Index index; @@ -55,59 +56,88 @@ template<template<class, class> class Scanner> class AbstractChildIterator { void operator++() { index++; } - Expression* operator*() { return parent.children[index]; } + Expression*& operator*() { + assert(index < parent.children.size()); + + // The vector of children is in reverse order, as that is how + // wasm-delegations-fields works. To get the order of execution, reverse + // things. + return *parent.children[parent.children.size() - 1 - index]; + } }; public: - SmallVector<Expression*, 4> children; + // The vector of children in the order emitted by wasm-delegations-fields + // (which is in reverse execution order). + SmallVector<Expression**, 4> children; AbstractChildIterator(Expression* parent) { - struct Traverser : public PostWalker<Traverser> { - Expression* parent; - SmallVector<Expression*, 4>* children; - - // We need to scan subchildren exactly once - just the parent. - bool scanned = false; - - static void scan(Traverser* self, Expression** currp) { - if (!self->scanned) { - self->scanned = true; - Scanner<Traverser, UnifiedExpressionVisitor<Traverser>>::scan(self, - currp); - } else { - // This is one of the children. Do not scan further, just note it. - self->children->push_back(*currp); - } - } - } traverser; - traverser.parent = parent; - traverser.children = &children; - traverser.walk(parent); + auto* self = (Specific*)this; + +#define DELEGATE_ID parent->_id + +#define DELEGATE_START(id) \ + auto* cast = parent->cast<id>(); \ + WASM_UNUSED(cast); + +#define DELEGATE_GET_FIELD(id, name) cast->name + +#define DELEGATE_FIELD_CHILD(id, name) self->addChild(parent, &cast->name); + +#define DELEGATE_FIELD_OPTIONAL_CHILD(id, name) \ + if (cast->name) { \ + self->addChild(parent, &cast->name); \ + } + +#define DELEGATE_FIELD_INT(id, name) +#define DELEGATE_FIELD_INT_ARRAY(id, name) +#define DELEGATE_FIELD_LITERAL(id, name) +#define DELEGATE_FIELD_NAME(id, name) +#define DELEGATE_FIELD_NAME_VECTOR(id, name) +#define DELEGATE_FIELD_SCOPE_NAME_DEF(id, name) +#define DELEGATE_FIELD_SCOPE_NAME_USE(id, name) +#define DELEGATE_FIELD_SCOPE_NAME_USE_VECTOR(id, name) +#define DELEGATE_FIELD_SIGNATURE(id, name) +#define DELEGATE_FIELD_TYPE(id, name) +#define DELEGATE_FIELD_ADDRESS(id, name) + +#include "wasm-delegations-fields.h" } Iterator begin() const { return Iterator(*this, 0); } Iterator end() const { return Iterator(*this, children.size()); } + + void addChild(Expression* parent, Expression** child) { + children.push_back(child); + } +}; + +class ChildIterator : public AbstractChildIterator<ChildIterator> { +public: + ChildIterator(Expression* parent) + : AbstractChildIterator<ChildIterator>(parent) {} }; -template<class SubType, class Visitor> -struct ValueChildScanner : PostWalker<SubType, Visitor> { - static void scan(SubType* self, Expression** currp) { - auto* curr = *currp; - if (Properties::isControlFlowStructure(curr)) { +class ValueChildIterator : public AbstractChildIterator<ValueChildIterator> { +public: + ValueChildIterator(Expression* parent) + : AbstractChildIterator<ValueChildIterator>(parent) {} + + void addChild(Expression* parent, Expression** child) { + if (Properties::isControlFlowStructure(parent)) { // If conditions are the only value children of control flow structures - if (auto* iff = curr->dynCast<If>()) { - self->pushTask(SubType::scan, &iff->condition); + if (auto* iff = parent->dynCast<If>()) { + if (child == &iff->condition) { + children.push_back(child); + } } } else { // All children on non-control flow expressions are value children - PostWalker<SubType, Visitor>::scan(self, currp); + children.push_back(child); } } }; -using ChildIterator = AbstractChildIterator<PostWalker>; -using ValueChildIterator = AbstractChildIterator<ValueChildScanner>; - // Returns true if the current expression contains a certain kind of expression, // within the given depth of BFS. If depth is -1, this searches all children. template<typename T> bool containsChild(Expression* parent, int depth = -1) { |