diff options
Diffstat (limited to 'src/ir/ExpressionAnalyzer.cpp')
-rw-r--r-- | src/ir/ExpressionAnalyzer.cpp | 220 |
1 files changed, 105 insertions, 115 deletions
diff --git a/src/ir/ExpressionAnalyzer.cpp b/src/ir/ExpressionAnalyzer.cpp index fcbd29665..aaab9050c 100644 --- a/src/ir/ExpressionAnalyzer.cpp +++ b/src/ir/ExpressionAnalyzer.cpp @@ -14,19 +14,19 @@ * limitations under the License. */ -#include "support/hash.h" -#include "support/small_vector.h" -#include "wasm.h" -#include "wasm-traversal.h" #include "ir/iteration.h" #include "ir/load-utils.h" #include "ir/utils.h" +#include "support/hash.h" +#include "support/small_vector.h" +#include "wasm-traversal.h" +#include "wasm.h" namespace wasm { // Given a stack of expressions, checks if the topmost is used as a result. -// For example, if the parent is a block and the node is before the last position, -// it is not used. +// For example, if the parent is a block and the node is before the last +// position, it is not used. bool ExpressionAnalyzer::isResultUsed(ExpressionStack& stack, Function* func) { for (int i = int(stack.size()) - 2; i >= 0; i--) { auto* curr = stack[i]; @@ -35,18 +35,22 @@ bool ExpressionAnalyzer::isResultUsed(ExpressionStack& stack, Function* func) { if (curr->is<Block>()) { auto* block = curr->cast<Block>(); for (size_t j = 0; j < block->list.size() - 1; j++) { - if (block->list[j] == above) return false; + if (block->list[j] == above) + return false; } assert(block->list.back() == above); // continue down } else if (curr->is<If>()) { auto* iff = curr->cast<If>(); - if (above == iff->condition) return true; - if (!iff->ifFalse) return false; + if (above == iff->condition) + return true; + if (!iff->ifFalse) + return false; assert(above == iff->ifTrue || above == iff->ifFalse); // continue down } else { - if (curr->is<Drop>()) return false; + if (curr->is<Drop>()) + return false; return true; // all other node types use the result } } @@ -62,19 +66,23 @@ bool ExpressionAnalyzer::isResultDropped(ExpressionStack& stack) { if (curr->is<Block>()) { auto* block = curr->cast<Block>(); for (size_t j = 0; j < block->list.size() - 1; j++) { - if (block->list[j] == above) return false; + if (block->list[j] == above) + return false; } assert(block->list.back() == above); // continue down } else if (curr->is<If>()) { auto* iff = curr->cast<If>(); - if (above == iff->condition) return false; - if (!iff->ifFalse) return false; + if (above == iff->condition) + return false; + if (!iff->ifFalse) + return false; assert(above == iff->ifTrue || above == iff->ifFalse); // continue down } else { - if (curr->is<Drop>()) return true; // dropped - return false; // all other node types use the result + if (curr->is<Drop>()) + return true; // dropped + return false; // all other node types use the result } } return false; @@ -98,8 +106,7 @@ bool ExpressionAnalyzer::isResultDropped(ExpressionStack& stack) { namespace { -template<typename T> -void visitImmediates(Expression* curr, T& visitor) { +template<typename T> void visitImmediates(Expression* curr, T& visitor) { struct ImmediateVisitor : public OverriddenVisitor<ImmediateVisitor> { T& visitor; @@ -107,35 +114,22 @@ void visitImmediates(Expression* curr, T& visitor) { this->visit(curr); } - void visitBlock(Block* curr) { - visitor.visitScopeName(curr->name); - } - void visitIf(If* curr) { - } - void visitLoop(Loop* curr) { - visitor.visitScopeName(curr->name); - } - void visitBreak(Break* curr) { - visitor.visitScopeName(curr->name); - } + void visitBlock(Block* curr) { visitor.visitScopeName(curr->name); } + void visitIf(If* curr) {} + void visitLoop(Loop* curr) { visitor.visitScopeName(curr->name); } + void visitBreak(Break* curr) { visitor.visitScopeName(curr->name); } void visitSwitch(Switch* curr) { for (auto target : curr->targets) { visitor.visitScopeName(target); } visitor.visitScopeName(curr->default_); } - void visitCall(Call* curr) { - visitor.visitNonScopeName(curr->target); - } + void visitCall(Call* curr) { visitor.visitNonScopeName(curr->target); } void visitCallIndirect(CallIndirect* curr) { visitor.visitNonScopeName(curr->fullType); } - void visitGetLocal(GetLocal* curr) { - visitor.visitIndex(curr->index); - } - void visitSetLocal(SetLocal* curr) { - visitor.visitIndex(curr->index); - } + void visitGetLocal(GetLocal* curr) { visitor.visitIndex(curr->index); } + void visitSetLocal(SetLocal* curr) { visitor.visitIndex(curr->index); } void visitGetGlobal(GetGlobal* curr) { visitor.visitNonScopeName(curr->name); } @@ -187,52 +181,37 @@ void visitImmediates(Expression* curr, T& visitor) { visitor.visitInt(x); } } - void visitSIMDBitselect(SIMDBitselect* curr) { - } - void visitSIMDShift(SIMDShift* curr) { - visitor.visitInt(curr->op); - } + void visitSIMDBitselect(SIMDBitselect* curr) {} + void visitSIMDShift(SIMDShift* curr) { visitor.visitInt(curr->op); } void visitMemoryInit(MemoryInit* curr) { visitor.visitIndex(curr->segment); } - void visitDataDrop(DataDrop* curr) { - visitor.visitIndex(curr->segment); - } - void visitMemoryCopy(MemoryCopy* curr) { - } - void visitMemoryFill(MemoryFill* curr) { - } - void visitConst(Const* curr) { - visitor.visitLiteral(curr->value); - } - void visitUnary(Unary* curr) { - visitor.visitInt(curr->op); - } - void visitBinary(Binary* curr) { - visitor.visitInt(curr->op); - } - void visitSelect(Select* curr) { - } - void visitDrop(Drop* curr) { - } - void visitReturn(Return* curr) { - } + void visitDataDrop(DataDrop* curr) { visitor.visitIndex(curr->segment); } + void visitMemoryCopy(MemoryCopy* curr) {} + void visitMemoryFill(MemoryFill* curr) {} + void visitConst(Const* curr) { visitor.visitLiteral(curr->value); } + void visitUnary(Unary* curr) { visitor.visitInt(curr->op); } + void visitBinary(Binary* curr) { visitor.visitInt(curr->op); } + void visitSelect(Select* curr) {} + void visitDrop(Drop* curr) {} + void visitReturn(Return* curr) {} void visitHost(Host* curr) { visitor.visitInt(curr->op); visitor.visitNonScopeName(curr->nameOperand); } - void visitNop(Nop* curr) { - } - void visitUnreachable(Unreachable* curr) { - } + void visitNop(Nop* curr) {} + void visitUnreachable(Unreachable* curr) {} } singleton(curr, visitor); } } // namespace -bool ExpressionAnalyzer::flexibleEqual(Expression* left, Expression* right, ExprComparer comparer) { +bool ExpressionAnalyzer::flexibleEqual(Expression* left, + Expression* right, + ExprComparer comparer) { struct Comparer { - std::map<Name, Name> rightNames; // for each name on the left, the corresponding name on the right + // for each name on the left, the corresponding name on the right + std::map<Name, Name> rightNames; std::vector<Expression*> leftStack; std::vector<Expression*> rightStack; @@ -259,13 +238,15 @@ bool ExpressionAnalyzer::flexibleEqual(Expression* left, Expression* right, Expr // Comparison is by value, except for names, which must match. bool operator==(const Immediates& other) { - if (scopeNames.size() != other.scopeNames.size()) return false; + if (scopeNames.size() != other.scopeNames.size()) + return false; for (Index i = 0; i < scopeNames.size(); i++) { auto leftName = scopeNames[i]; auto rightName = other.scopeNames[i]; auto iter = parent.rightNames.find(leftName); - // If it's not found, that means it was defined out of the expression being compared, - // in which case we can just treat it literally - it must be exactly identical. + // If it's not found, that means it was defined out of the expression + // being compared, in which case we can just treat it literally - it + // must be exactly identical. if (iter != parent.rightNames.end()) { leftName = iter->second; } @@ -273,18 +254,22 @@ bool ExpressionAnalyzer::flexibleEqual(Expression* left, Expression* right, Expr return false; } } - if (nonScopeNames != other.nonScopeNames) return false; - if (ints != other.ints) return false; - if (literals != other.literals) return false; - if (types != other.types) return false; - if (indexes != other.indexes) return false; - if (addresses != other.addresses) return false; + if (nonScopeNames != other.nonScopeNames) + return false; + if (ints != other.ints) + return false; + if (literals != other.literals) + return false; + if (types != other.types) + return false; + if (indexes != other.indexes) + return false; + if (addresses != other.addresses) + return false; return true; } - bool operator!=(const Immediates& other) { - return !(*this == other); - } + bool operator!=(const Immediates& other) { return !(*this == other); } void clear() { scopeNames.clear(); @@ -298,7 +283,8 @@ bool ExpressionAnalyzer::flexibleEqual(Expression* left, Expression* right, Expr }; bool noteNames(Name left, Name right) { - if (left.is() != right.is()) return false; + if (left.is() != right.is()) + return false; if (left.is()) { assert(rightNames.find(left) == rightNames.end()); rightNames[left] = right; @@ -307,8 +293,7 @@ bool ExpressionAnalyzer::flexibleEqual(Expression* left, Expression* right, Expr } bool compare(Expression* left, Expression* right, ExprComparer comparer) { - Immediates leftImmediates(*this), - rightImmediates(*this); + Immediates leftImmediates(*this), rightImmediates(*this); // The empty name is the same on both sides. rightNames[Name()] = Name(); @@ -321,21 +306,28 @@ bool ExpressionAnalyzer::flexibleEqual(Expression* left, Expression* right, Expr leftStack.pop_back(); right = rightStack.back(); rightStack.pop_back(); - if (!left != !right) return false; - if (!left) continue; - if (comparer(left, right)) continue; // comparison hook, before all the rest + if (!left != !right) + return false; + if (!left) + continue; + if (comparer(left, right)) + continue; // comparison hook, before all the rest // continue with normal structural comparison - if (left->_id != right->_id) return false; + if (left->_id != right->_id) + return false; // Blocks and loops introduce scoping. if (auto* block = left->dynCast<Block>()) { - if (!noteNames(block->name, right->cast<Block>()->name)) return false; + if (!noteNames(block->name, right->cast<Block>()->name)) + return false; } else if (auto* loop = left->dynCast<Loop>()) { - if (!noteNames(loop->name, right->cast<Loop>()->name)) return false; + if (!noteNames(loop->name, right->cast<Loop>()->name)) + return false; } else { // For all other nodes, compare their immediate values visitImmediates(left, leftImmediates); visitImmediates(right, rightImmediates); - if (leftImmediates != rightImmediates) return false; + if (leftImmediates != rightImmediates) + return false; leftImmediates.clear(); rightImmediates.clear(); } @@ -349,10 +341,13 @@ bool ExpressionAnalyzer::flexibleEqual(Expression* left, Expression* right, Expr rightStack.push_back(child); counter--; } - // The number of child nodes must match (e.g. return has an optional one). - if (counter != 0) return false; + // The number of child nodes must match (e.g. return has an optional + // one). + if (counter != 0) + return false; } - if (leftStack.size() > 0 || rightStack.size() > 0) return false; + if (leftStack.size() > 0 || rightStack.size() > 0) + return false; return true; } }; @@ -366,7 +361,8 @@ HashType ExpressionAnalyzer::hash(Expression* curr) { HashType digest = 0; Index internalCounter = 0; - std::map<Name, Index> internalNames; // for each internal name, its unique id + // for each internal name, its unique id + std::map<Name, Index> internalNames; ExpressionStack stack; void noteScopeName(Name curr) { @@ -381,7 +377,8 @@ HashType ExpressionAnalyzer::hash(Expression* curr) { while (stack.size() > 0) { curr = stack.back(); stack.pop_back(); - if (!curr) continue; + if (!curr) + continue; hash(curr->_id); // we often don't need to hash the type, as it is tied to other values // we are hashing anyhow, but there are exceptions: for example, a @@ -413,9 +410,7 @@ HashType ExpressionAnalyzer::hash(Expression* curr) { } } - void hash(HashType hash) { - digest = rehash(digest, hash); - } + void hash(HashType hash) { digest = rehash(digest, hash); } void hash64(uint64_t hash) { digest = rehash(rehash(digest, HashType(hash >> 32)), HashType(hash)); } @@ -424,28 +419,23 @@ HashType ExpressionAnalyzer::hash(Expression* curr) { // Names are relative, we give the same hash for // (block $x (br $x)) // (block $y (br $y)) - static_assert(sizeof(Index) == sizeof(int32_t), "wasm64 will need changes here"); + static_assert(sizeof(Index) == sizeof(int32_t), + "wasm64 will need changes here"); assert(internalNames.find(curr) != internalNames.end()); return hash(internalNames[curr]); } - void visitNonScopeName(Name curr) { - return hash64(uint64_t(curr.str)); - } - void visitInt(int32_t curr) { - hash(curr); - } - void visitLiteral(Literal curr) { - hash(std::hash<Literal>()(curr)); - } - void visitType(Type curr) { - hash(int32_t(curr)); - } + void visitNonScopeName(Name curr) { return hash64(uint64_t(curr.str)); } + void visitInt(int32_t curr) { hash(curr); } + void visitLiteral(Literal curr) { hash(std::hash<Literal>()(curr)); } + void visitType(Type curr) { hash(int32_t(curr)); } void visitIndex(Index curr) { - static_assert(sizeof(Index) == sizeof(int32_t), "wasm64 will need changes here"); + static_assert(sizeof(Index) == sizeof(int32_t), + "wasm64 will need changes here"); hash(int32_t(curr)); } void visitAddress(Address curr) { - static_assert(sizeof(Address) == sizeof(int32_t), "wasm64 will need changes here"); + static_assert(sizeof(Address) == sizeof(int32_t), + "wasm64 will need changes here"); hash(int32_t(curr)); } }; |