From 4ca05f765ca6ec99b7582d357520ca217265677d Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Tue, 14 May 2024 10:10:54 -0700 Subject: LocalCSE: Check effects/generativity early (#6587) Previously we checked late, and as a result might end up failing to optimize when a sub-pattern could have worked. E.g. (call (A) ) (call (A) ) The call cannot be optimized, but the A pattern repeats. Before this PR we'd greedily focus on the entire call and then fail. After this PR we skip the call before we commit to which patterns to try to optimize, so we succeed. Add a isShallowlyGenerative helper here as we compute this step by step as we go. Also remove a parameter to the generativity code (it did not use the features it was passed). --- src/ir/properties.cpp | 45 +++++++++++++++++++++++++++++---------------- 1 file changed, 29 insertions(+), 16 deletions(-) (limited to 'src/ir/properties.cpp') diff --git a/src/ir/properties.cpp b/src/ir/properties.cpp index 05dae897e..1346f6cad 100644 --- a/src/ir/properties.cpp +++ b/src/ir/properties.cpp @@ -19,27 +19,40 @@ namespace wasm::Properties { -bool isGenerative(Expression* curr, FeatureSet features) { - struct Scanner : public PostWalker { - bool generative = false; +namespace { - void visitCall(Call* curr) { - // TODO: We could in principle look at the called function to see if it is - // generative. To do that we'd need to compute generativity like we - // compute global effects (we can't just peek from here, as the - // other function might be modified in parallel). - generative = true; - } - void visitCallIndirect(CallIndirect* curr) { generative = true; } - void visitCallRef(CallRef* curr) { generative = true; } - void visitStructNew(StructNew* curr) { generative = true; } - void visitArrayNew(ArrayNew* curr) { generative = true; } - void visitArrayNewFixed(ArrayNewFixed* curr) { generative = true; } - } scanner; +struct GenerativityScanner : public PostWalker { + bool generative = false; + + void visitCall(Call* curr) { + // TODO: We could in principle look at the called function to see if it is + // generative. To do that we'd need to compute generativity like we + // compute global effects (we can't just peek from here, as the + // other function might be modified in parallel). + generative = true; + } + void visitCallIndirect(CallIndirect* curr) { generative = true; } + void visitCallRef(CallRef* curr) { generative = true; } + void visitStructNew(StructNew* curr) { generative = true; } + void visitArrayNew(ArrayNew* curr) { generative = true; } + void visitArrayNewFixed(ArrayNewFixed* curr) { generative = true; } +}; + +} // anonymous namespace + +bool isGenerative(Expression* curr) { + GenerativityScanner scanner; scanner.walk(curr); return scanner.generative; } +// As above, but only checks |curr| and not children. +bool isShallowlyGenerative(Expression* curr) { + GenerativityScanner scanner; + scanner.visit(curr); + return scanner.generative; +} + // Checks an expression in a shallow manner (i.e., does not check children) as // to whether it is valid in a wasm constant expression. static bool isValidInConstantExpression(Module& wasm, Expression* expr) { -- cgit v1.2.3