From e04d25e2e6cab2df0dfda5e4a206714a202313bc Mon Sep 17 00:00:00 2001 From: Heejin Ahn Date: Tue, 14 Apr 2020 17:27:05 -0700 Subject: Fix reuse of constant nodes in Precompute (#2764) Previously we tried to reuse `Const` node if a precomputed value is a constant node. But now we have two more kinds of constant node (`RefNull` and `RefFunc`), so we shouldn't reuse them interchangeably, meaning we shouldn't try to reuse a `Const` node when the value at hand is a `RefNull`. This correctly checks the type of node and tries to reuse only if the types of nodes match. Fixes #2759. --- src/passes/Precompute.cpp | 61 +++++++++++++++++++++++++---------------------- 1 file changed, 33 insertions(+), 28 deletions(-) (limited to 'src/passes/Precompute.cpp') diff --git a/src/passes/Precompute.cpp b/src/passes/Precompute.cpp index 0a4a691f2..d809b8b43 100644 --- a/src/passes/Precompute.cpp +++ b/src/passes/Precompute.cpp @@ -174,6 +174,37 @@ struct Precompute } while (propagate && worked); } + template void reuseConstantNode(T* curr, Flow flow) { + if (flow.values.isConcrete()) { + // reuse a const / ref.null / ref.func node if there is one + if (curr->value && flow.values.size() == 1) { + Literal singleValue = flow.getSingleValue(); + if (singleValue.type.isNumber()) { + if (auto* c = curr->value->template dynCast()) { + c->value = singleValue; + c->finalize(); + curr->finalize(); + return; + } + } else if (singleValue.type == Type::nullref && + curr->value->template is()) { + return; + } else if (singleValue.type == Type::funcref) { + if (auto* r = curr->value->template dynCast()) { + r->func = singleValue.getFunc(); + r->finalize(); + curr->finalize(); + return; + } + } + } + curr->value = flow.getConstExpression(*getModule()); + } else { + curr->value = nullptr; + } + curr->finalize(); + } + void visitExpression(Expression* curr) { // TODO: if local.get, only replace with a constant if we don't care about // size...? @@ -199,19 +230,7 @@ struct Precompute // this expression causes a return. if it's already a return, reuse the // node if (auto* ret = curr->dynCast()) { - if (flow.values.isConcrete()) { - // reuse a const value if there is one - if (ret->value && flow.values.size() == 1) { - if (auto* value = ret->value->dynCast()) { - value->value = flow.getSingleValue(); - value->finalize(); - return; - } - } - ret->value = flow.getConstExpression(*getModule()); - } else { - ret->value = nullptr; - } + reuseConstantNode(ret, flow); } else { Builder builder(*getModule()); replaceCurrent(builder.makeReturn( @@ -225,21 +244,7 @@ struct Precompute if (auto* br = curr->dynCast()) { br->name = flow.breakTo; br->condition = nullptr; - if (flow.values.isConcrete()) { - // reuse a const value if there is one - if (br->value && flow.values.size() == 1) { - if (auto* value = br->value->dynCast()) { - value->value = flow.getSingleValue(); - value->finalize(); - br->finalize(); - return; - } - } - br->value = flow.getConstExpression(*getModule()); - } else { - br->value = nullptr; - } - br->finalize(); + reuseConstantNode(br, flow); } else { Builder builder(*getModule()); replaceCurrent(builder.makeBreak( -- cgit v1.2.3