diff --git a/optimizer/src/main/java/dev/cel/optimizer/optimizers/BUILD.bazel b/optimizer/src/main/java/dev/cel/optimizer/optimizers/BUILD.bazel index 27932360..38267774 100644 --- a/optimizer/src/main/java/dev/cel/optimizer/optimizers/BUILD.bazel +++ b/optimizer/src/main/java/dev/cel/optimizer/optimizers/BUILD.bazel @@ -52,6 +52,7 @@ java_library( "//optimizer:ast_optimizer", "//optimizer:mutable_ast", "//parser:operator", + "@maven//:com_google_errorprone_error_prone_annotations", "@maven//:com_google_guava_guava", "@maven//:org_jspecify_jspecify", ], diff --git a/optimizer/src/main/java/dev/cel/optimizer/optimizers/SubexpressionOptimizer.java b/optimizer/src/main/java/dev/cel/optimizer/optimizers/SubexpressionOptimizer.java index ee2ec067..a8e431ab 100644 --- a/optimizer/src/main/java/dev/cel/optimizer/optimizers/SubexpressionOptimizer.java +++ b/optimizer/src/main/java/dev/cel/optimizer/optimizers/SubexpressionOptimizer.java @@ -14,6 +14,7 @@ package dev.cel.optimizer.optimizers; +import static com.google.common.base.Preconditions.checkNotNull; import static com.google.common.collect.ImmutableList.toImmutableList; import static com.google.common.collect.ImmutableSet.toImmutableSet; import static java.util.Arrays.stream; @@ -25,6 +26,7 @@ import com.google.common.collect.ImmutableSet; import com.google.common.collect.Iterables; import com.google.common.collect.Streams; +import com.google.errorprone.annotations.CanIgnoreReturnValue; import dev.cel.bundle.CelBuilder; import dev.cel.checker.Standard; import dev.cel.common.CelAbstractSyntaxTree; @@ -52,6 +54,7 @@ import dev.cel.optimizer.MutableAst.MangledComprehensionAst; import dev.cel.parser.Operator; import java.util.ArrayList; +import java.util.Arrays; import java.util.HashMap; import java.util.HashSet; import java.util.List; @@ -84,6 +87,12 @@ * */ public class SubexpressionOptimizer implements CelAstOptimizer { + private static final ImmutableSet CSE_DEFAULT_ELIMINABLE_FUNCTIONS = + Streams.concat( + stream(Operator.values()).map(Operator::getFunction), + stream(Standard.Function.values()).map(Standard.Function::getFunction), + stream(CelOptionalLibrary.Function.values()).map(Function::getFunction)) + .collect(toImmutableSet()); private static final SubexpressionOptimizer INSTANCE = new SubexpressionOptimizer(SubexpressionOptimizerOptions.newBuilder().build()); private static final String BIND_IDENTIFIER_PREFIX = "@r"; @@ -91,18 +100,12 @@ public class SubexpressionOptimizer implements CelAstOptimizer { private static final String MANGLED_COMPREHENSION_RESULT_PREFIX = "@x"; private static final String CEL_BLOCK_FUNCTION = "cel.@block"; private static final String BLOCK_INDEX_PREFIX = "@index"; - private static final ImmutableSet CSE_ALLOWED_FUNCTIONS = - Streams.concat( - stream(Operator.values()).map(Operator::getFunction), - stream(Standard.Function.values()).map(Standard.Function::getFunction), - stream(CelOptionalLibrary.Function.values()).map(Function::getFunction)) - .collect(toImmutableSet()); - private static final Extension CEL_BLOCK_AST_EXTENSION_TAG = Extension.create("cel_block", Version.of(1L, 1L), Component.COMPONENT_RUNTIME); private final SubexpressionOptimizerOptions cseOptions; private final MutableAst mutableAst; + private final ImmutableSet cseEliminableFunctions; /** * Returns a default instance of common subexpression elimination optimizer with preconfigured @@ -359,7 +362,7 @@ private Stream getAllCseCandidatesStream( return CelNavigableAst.fromAst(ast) .getRoot() .allNodes() - .filter(SubexpressionOptimizer::canEliminate) + .filter(this::canEliminate) .map(CelNavigableExpr::expr) .filter(expr -> areSemanticallyEqual(cseCandidate, expr)); } @@ -423,7 +426,7 @@ private Optional findCseCandidateWithRecursionDepth( CelNavigableAst.fromAst(ast) .getRoot() .allNodes(TraversalOrder.POST_ORDER) - .filter(SubexpressionOptimizer::canEliminate) + .filter(this::canEliminate) .filter(node -> node.height() <= recursionLimit) .filter(node -> !areSemanticallyEqual(ast.getExpr(), node.expr())) .collect(toImmutableList()); @@ -462,18 +465,18 @@ private Optional findCseCandidateWithCommonSubexpr(CelAbstract CelNavigableAst.fromAst(ast) .getRoot() .allNodes(TraversalOrder.PRE_ORDER) - .filter(SubexpressionOptimizer::canEliminate) + .filter(this::canEliminate) .collect(toImmutableList()); return findCseCandidateWithCommonSubexpr(allNodes); } - private static boolean canEliminate(CelNavigableExpr navigableExpr) { + private boolean canEliminate(CelNavigableExpr navigableExpr) { return !navigableExpr.getKind().equals(Kind.CONSTANT) && !navigableExpr.getKind().equals(Kind.IDENT) && !navigableExpr.expr().identOrDefault().name().startsWith(BIND_IDENTIFIER_PREFIX) && !navigableExpr.expr().selectOrDefault().testOnly() - && containsAllowedFunctionOnly(navigableExpr) + && containsEliminableFunctionOnly(navigableExpr) && isWithinInlineableComprehension(navigableExpr); } @@ -507,13 +510,13 @@ private boolean areSemanticallyEqual(CelExpr expr1, CelExpr expr2) { return normalizeForEquality(expr1).equals(normalizeForEquality(expr2)); } - private static boolean containsAllowedFunctionOnly(CelNavigableExpr navigableExpr) { + private boolean containsEliminableFunctionOnly(CelNavigableExpr navigableExpr) { return navigableExpr .allNodes() .allMatch( node -> { if (node.getKind().equals(Kind.CALL)) { - return CSE_ALLOWED_FUNCTIONS.contains(node.expr().call().function()); + return cseEliminableFunctions.contains(node.expr().call().function()); } return true; @@ -580,6 +583,8 @@ public abstract static class SubexpressionOptimizerOptions { public abstract int subexpressionMaxRecursionDepth(); + public abstract ImmutableSet eliminableFunctions(); + /** Builder for configuring the {@link SubexpressionOptimizerOptions}. */ @AutoValue.Builder public abstract static class Builder { @@ -630,11 +635,34 @@ public abstract static class Builder { */ public abstract Builder subexpressionMaxRecursionDepth(int value); + abstract ImmutableSet.Builder eliminableFunctionsBuilder(); + + /** + * Adds a collection of custom functions that will be a candidate for common subexpression + * elimination. By default, standard functions are eliminable. + * + *

Note that the implementation of custom functions must be free of side effects. + */ + @CanIgnoreReturnValue + public Builder addEliminableFunctions(Iterable functions) { + checkNotNull(functions); + this.eliminableFunctionsBuilder().addAll(functions); + return this; + } + + /** See {@link #addEliminableFunctions(Iterable)}. */ + @CanIgnoreReturnValue + public Builder addEliminableFunctions(String... functions) { + return addEliminableFunctions(Arrays.asList(functions)); + } + public abstract SubexpressionOptimizerOptions build(); Builder() {} } + abstract Builder toBuilder(); + /** Returns a new options builder with recommended defaults pre-configured. */ public static Builder newBuilder() { return new AutoValue_SubexpressionOptimizer_SubexpressionOptimizerOptions.Builder() @@ -650,5 +678,10 @@ public static Builder newBuilder() { private SubexpressionOptimizer(SubexpressionOptimizerOptions cseOptions) { this.cseOptions = cseOptions; this.mutableAst = MutableAst.newInstance(cseOptions.iterationLimit()); + this.cseEliminableFunctions = + ImmutableSet.builder() + .addAll(CSE_DEFAULT_ELIMINABLE_FUNCTIONS) + .addAll(cseOptions.eliminableFunctions()) + .build(); } } diff --git a/optimizer/src/test/java/dev/cel/optimizer/optimizers/SubexpressionOptimizerBaselineTest.java b/optimizer/src/test/java/dev/cel/optimizer/optimizers/SubexpressionOptimizerBaselineTest.java index 8590ff58..278a7997 100644 --- a/optimizer/src/test/java/dev/cel/optimizer/optimizers/SubexpressionOptimizerBaselineTest.java +++ b/optimizer/src/test/java/dev/cel/optimizer/optimizers/SubexpressionOptimizerBaselineTest.java @@ -39,6 +39,7 @@ import dev.cel.parser.CelStandardMacro; import dev.cel.parser.CelUnparser; import dev.cel.parser.CelUnparserFactory; +import dev.cel.runtime.CelRuntime.CelFunctionBinding; import dev.cel.testing.BaselineTestCase; import dev.cel.testing.testdata.proto3.TestAllTypesProto.NestedTestAllTypes; import dev.cel.testing.testdata.proto3.TestAllTypesProto.TestAllTypes; @@ -68,6 +69,13 @@ public class SubexpressionOptimizerBaselineTest extends BaselineTestCase { .build(); private static final Cel CEL = newCelBuilder().build(); + private static final SubexpressionOptimizerOptions OPTIMIZER_COMMON_OPTIONS = + SubexpressionOptimizerOptions.newBuilder() + .populateMacroCalls(true) + .enableCelBlock(true) + .addEliminableFunctions("pure_custom_func") + .build(); + private String overriddenBaseFilePath = ""; @Before @@ -287,8 +295,16 @@ private static CelBuilder newCelBuilder() { .addRuntimeLibraries(CelOptionalLibrary.INSTANCE) .addFunctionDeclarations( CelFunctionDecl.newFunctionDeclaration( - "custom_func", - newGlobalOverload("custom_func_overload", SimpleType.INT, SimpleType.INT))) + "pure_custom_func", + newGlobalOverload("pure_custom_func_overload", SimpleType.INT, SimpleType.INT)), + CelFunctionDecl.newFunctionDeclaration( + "non_pure_custom_func", + newGlobalOverload("non_pure_custom_func_overload", SimpleType.INT, SimpleType.INT))) + .addFunctionBindings( + // This is pure, but for the purposes of excluding it as a CSE candidate, pretend that + // it isn't. + CelFunctionBinding.from("non_pure_custom_func_overload", Long.class, val -> val), + CelFunctionBinding.from("pure_custom_func_overload", Long.class, val -> val)) .addVar("x", SimpleType.DYN) .addVar("opt_x", OptionalType.create(SimpleType.DYN)) .addVar("msg", StructTypeReference.create(TestAllTypes.getDescriptor().getFullName())); @@ -302,70 +318,26 @@ private static CelOptimizer newCseOptimizer(Cel cel, SubexpressionOptimizerOptio @SuppressWarnings("Immutable") // Test only private enum CseTestOptimizer { - CASCADED_BINDS( - SubexpressionOptimizerOptions.newBuilder() - .populateMacroCalls(true) - .enableCelBlock(false) - .build()), - BLOCK_COMMON_SUBEXPR_ONLY( - SubexpressionOptimizerOptions.newBuilder() - .populateMacroCalls(true) - .enableCelBlock(true) - .build()), + CASCADED_BINDS(OPTIMIZER_COMMON_OPTIONS.toBuilder().enableCelBlock(false).build()), + BLOCK_COMMON_SUBEXPR_ONLY(OPTIMIZER_COMMON_OPTIONS), BLOCK_RECURSION_DEPTH_1( - SubexpressionOptimizerOptions.newBuilder() - .populateMacroCalls(true) - .enableCelBlock(true) - .subexpressionMaxRecursionDepth(1) - .build()), + OPTIMIZER_COMMON_OPTIONS.toBuilder().subexpressionMaxRecursionDepth(1).build()), BLOCK_RECURSION_DEPTH_2( - SubexpressionOptimizerOptions.newBuilder() - .populateMacroCalls(true) - .enableCelBlock(true) - .subexpressionMaxRecursionDepth(2) - .build()), + OPTIMIZER_COMMON_OPTIONS.toBuilder().subexpressionMaxRecursionDepth(2).build()), BLOCK_RECURSION_DEPTH_3( - SubexpressionOptimizerOptions.newBuilder() - .populateMacroCalls(true) - .enableCelBlock(true) - .subexpressionMaxRecursionDepth(3) - .build()), + OPTIMIZER_COMMON_OPTIONS.toBuilder().subexpressionMaxRecursionDepth(3).build()), BLOCK_RECURSION_DEPTH_4( - SubexpressionOptimizerOptions.newBuilder() - .populateMacroCalls(true) - .enableCelBlock(true) - .subexpressionMaxRecursionDepth(4) - .build()), + OPTIMIZER_COMMON_OPTIONS.toBuilder().subexpressionMaxRecursionDepth(4).build()), BLOCK_RECURSION_DEPTH_5( - SubexpressionOptimizerOptions.newBuilder() - .populateMacroCalls(true) - .enableCelBlock(true) - .subexpressionMaxRecursionDepth(5) - .build()), + OPTIMIZER_COMMON_OPTIONS.toBuilder().subexpressionMaxRecursionDepth(5).build()), BLOCK_RECURSION_DEPTH_6( - SubexpressionOptimizerOptions.newBuilder() - .populateMacroCalls(true) - .enableCelBlock(true) - .subexpressionMaxRecursionDepth(6) - .build()), + OPTIMIZER_COMMON_OPTIONS.toBuilder().subexpressionMaxRecursionDepth(6).build()), BLOCK_RECURSION_DEPTH_7( - SubexpressionOptimizerOptions.newBuilder() - .populateMacroCalls(true) - .enableCelBlock(true) - .subexpressionMaxRecursionDepth(7) - .build()), + OPTIMIZER_COMMON_OPTIONS.toBuilder().subexpressionMaxRecursionDepth(7).build()), BLOCK_RECURSION_DEPTH_8( - SubexpressionOptimizerOptions.newBuilder() - .populateMacroCalls(true) - .enableCelBlock(true) - .subexpressionMaxRecursionDepth(8) - .build()), + OPTIMIZER_COMMON_OPTIONS.toBuilder().subexpressionMaxRecursionDepth(8).build()), BLOCK_RECURSION_DEPTH_9( - SubexpressionOptimizerOptions.newBuilder() - .populateMacroCalls(true) - .enableCelBlock(true) - .subexpressionMaxRecursionDepth(9) - .build()); + OPTIMIZER_COMMON_OPTIONS.toBuilder().subexpressionMaxRecursionDepth(9).build()); private final CelOptimizer celOptimizer; @@ -507,7 +479,16 @@ private enum CseTestCase { "('h' + 'e' + 'l' + 'l' + 'o' + ' world').matches('hello')"), CALL_BOTH_ARGUMENT_TARGET_NESTED_NO_COMMON_SUBEXPR( "('h' + 'e' + 'l' + 'l' + 'o' + ' world').matches('w' + 'o' + 'r' + 'l' + 'd')"), - ; + CUSTOM_FUNCTION_INELIMINABLE( + "non_pure_custom_func(msg.oneof_type.payload.single_int64) +" + + " non_pure_custom_func(msg.oneof_type.payload.single_int32) +" + + " non_pure_custom_func(msg.oneof_type.payload.single_int64) +" + + " non_pure_custom_func(msg.single_int64)"), + CUSTOM_FUNCTION_ELIMINABLE( + "pure_custom_func(msg.oneof_type.payload.single_int64) +" + + " pure_custom_func(msg.oneof_type.payload.single_int32) +" + + " pure_custom_func(msg.oneof_type.payload.single_int64) +" + + " pure_custom_func(msg.single_int64)"); private final String source; CseTestCase(String source) { diff --git a/optimizer/src/test/java/dev/cel/optimizer/optimizers/SubexpressionOptimizerTest.java b/optimizer/src/test/java/dev/cel/optimizer/optimizers/SubexpressionOptimizerTest.java index f09a7e9c..3668d776 100644 --- a/optimizer/src/test/java/dev/cel/optimizer/optimizers/SubexpressionOptimizerTest.java +++ b/optimizer/src/test/java/dev/cel/optimizer/optimizers/SubexpressionOptimizerTest.java @@ -41,11 +41,9 @@ import dev.cel.common.navigation.CelNavigableAst; import dev.cel.common.navigation.CelNavigableExpr; import dev.cel.common.types.ListType; -import dev.cel.common.types.OptionalType; import dev.cel.common.types.SimpleType; import dev.cel.common.types.StructTypeReference; import dev.cel.extensions.CelExtensions; -import dev.cel.extensions.CelOptionalLibrary; import dev.cel.optimizer.CelOptimizationException; import dev.cel.optimizer.CelOptimizer; import dev.cel.optimizer.CelOptimizerFactory; @@ -107,18 +105,15 @@ public class SubexpressionOptimizerTest { private static CelBuilder newCelBuilder() { return CelFactory.standardCelBuilder() .addMessageTypes(TestAllTypes.getDescriptor()) - .setContainer("dev.cel.testing.testdata.proto3") .setStandardMacros(CelStandardMacro.STANDARD_MACROS) .setOptions( CelOptions.current().enableTimestampEpoch(true).populateMacroCalls(true).build()) - .addCompilerLibraries(CelOptionalLibrary.INSTANCE, CelExtensions.bindings()) - .addRuntimeLibraries(CelOptionalLibrary.INSTANCE) + .addCompilerLibraries(CelExtensions.bindings()) .addFunctionDeclarations( CelFunctionDecl.newFunctionDeclaration( - "custom_func", - newGlobalOverload("custom_func_overload", SimpleType.INT, SimpleType.INT))) + "non_pure_custom_func", + newGlobalOverload("non_pure_custom_func_overload", SimpleType.INT, SimpleType.INT))) .addVar("x", SimpleType.DYN) - .addVar("opt_x", OptionalType.create(SimpleType.DYN)) .addVar("msg", StructTypeReference.create(TestAllTypes.getDescriptor().getFullName())); } @@ -156,9 +151,10 @@ private enum CseNoOpTestCase { // Constants and identifiers within a function CONST_WITHIN_FUNCTION("size(\"hello\" + \"hello\" + \"hello\")"), IDENT_WITHIN_FUNCTION("string(x + x + x)"), - // Non-standard functions are considered non-pure for time being - NON_STANDARD_FUNCTION_1("custom_func(1) + custom_func(1)"), - NON_STANDARD_FUNCTION_2("1 + custom_func(1) + 1 + custom_func(1)"), + // Non-standard functions that have not been explicitly added as a candidate are not + // optimized. + NON_STANDARD_FUNCTION_1("non_pure_custom_func(1) + non_pure_custom_func(1)"), + NON_STANDARD_FUNCTION_2("1 + non_pure_custom_func(1) + 1 + non_pure_custom_func(1)"), // Duplicated but nested calls. NESTED_FUNCTION("int(timestamp(int(timestamp(1000000000))))"), // This cannot be optimized. Extracting the common subexpression would presence test diff --git a/optimizer/src/test/resources/subexpression_ast_block_common_subexpr_only.baseline b/optimizer/src/test/resources/subexpression_ast_block_common_subexpr_only.baseline index 1b0adb21..960821d8 100644 --- a/optimizer/src/test/resources/subexpression_ast_block_common_subexpr_only.baseline +++ b/optimizer/src/test/resources/subexpression_ast_block_common_subexpr_only.baseline @@ -2922,3 +2922,148 @@ CALL [12] { } } } +Test case: CUSTOM_FUNCTION_INELIMINABLE +Source: non_pure_custom_func(msg.oneof_type.payload.single_int64) + non_pure_custom_func(msg.oneof_type.payload.single_int32) + non_pure_custom_func(msg.oneof_type.payload.single_int64) + non_pure_custom_func(msg.single_int64) +=====> +CALL [1] { + function: cel.@block + args: { + CREATE_LIST [2] { + elements: { + SELECT [3] { + SELECT [4] { + IDENT [5] { + name: msg + }.oneof_type + }.payload + } + SELECT [6] { + IDENT [7] { + name: @index0 + }.single_int64 + } + } + } + CALL [8] { + function: _+_ + args: { + CALL [9] { + function: _+_ + args: { + CALL [10] { + function: _+_ + args: { + CALL [11] { + function: non_pure_custom_func + args: { + IDENT [12] { + name: @index1 + } + } + } + CALL [13] { + function: non_pure_custom_func + args: { + SELECT [14] { + IDENT [15] { + name: @index0 + }.single_int32 + } + } + } + } + } + CALL [16] { + function: non_pure_custom_func + args: { + IDENT [17] { + name: @index1 + } + } + } + } + } + CALL [18] { + function: non_pure_custom_func + args: { + SELECT [19] { + IDENT [20] { + name: msg + }.single_int64 + } + } + } + } + } + } +} +Test case: CUSTOM_FUNCTION_ELIMINABLE +Source: pure_custom_func(msg.oneof_type.payload.single_int64) + pure_custom_func(msg.oneof_type.payload.single_int32) + pure_custom_func(msg.oneof_type.payload.single_int64) + pure_custom_func(msg.single_int64) +=====> +CALL [1] { + function: cel.@block + args: { + CREATE_LIST [2] { + elements: { + SELECT [3] { + SELECT [4] { + IDENT [5] { + name: msg + }.oneof_type + }.payload + } + CALL [6] { + function: pure_custom_func + args: { + SELECT [7] { + IDENT [8] { + name: @index0 + }.single_int64 + } + } + } + } + } + CALL [9] { + function: _+_ + args: { + CALL [10] { + function: _+_ + args: { + CALL [11] { + function: _+_ + args: { + IDENT [12] { + name: @index1 + } + CALL [13] { + function: pure_custom_func + args: { + SELECT [14] { + IDENT [15] { + name: @index0 + }.single_int32 + } + } + } + } + } + IDENT [16] { + name: @index1 + } + } + } + CALL [17] { + function: pure_custom_func + args: { + SELECT [18] { + IDENT [19] { + name: msg + }.single_int64 + } + } + } + } + } + } +} diff --git a/optimizer/src/test/resources/subexpression_ast_block_recursion_depth_1.baseline b/optimizer/src/test/resources/subexpression_ast_block_recursion_depth_1.baseline index 77f95f1a..a8b6c243 100644 --- a/optimizer/src/test/resources/subexpression_ast_block_recursion_depth_1.baseline +++ b/optimizer/src/test/resources/subexpression_ast_block_recursion_depth_1.baseline @@ -3708,3 +3708,181 @@ CALL [1] { } } } +Test case: CUSTOM_FUNCTION_INELIMINABLE +Source: non_pure_custom_func(msg.oneof_type.payload.single_int64) + non_pure_custom_func(msg.oneof_type.payload.single_int32) + non_pure_custom_func(msg.oneof_type.payload.single_int64) + non_pure_custom_func(msg.single_int64) +=====> +CALL [1] { + function: cel.@block + args: { + CREATE_LIST [2] { + elements: { + SELECT [3] { + IDENT [4] { + name: msg + }.oneof_type + } + SELECT [5] { + IDENT [6] { + name: @index0 + }.payload + } + SELECT [7] { + IDENT [8] { + name: @index1 + }.single_int64 + } + SELECT [9] { + IDENT [10] { + name: msg + }.single_int64 + } + SELECT [11] { + IDENT [12] { + name: @index1 + }.single_int32 + } + } + } + CALL [13] { + function: _+_ + args: { + CALL [14] { + function: _+_ + args: { + CALL [15] { + function: _+_ + args: { + CALL [16] { + function: non_pure_custom_func + args: { + IDENT [17] { + name: @index2 + } + } + } + CALL [18] { + function: non_pure_custom_func + args: { + IDENT [19] { + name: @index4 + } + } + } + } + } + CALL [20] { + function: non_pure_custom_func + args: { + IDENT [21] { + name: @index2 + } + } + } + } + } + CALL [22] { + function: non_pure_custom_func + args: { + IDENT [23] { + name: @index3 + } + } + } + } + } + } +} +Test case: CUSTOM_FUNCTION_ELIMINABLE +Source: pure_custom_func(msg.oneof_type.payload.single_int64) + pure_custom_func(msg.oneof_type.payload.single_int32) + pure_custom_func(msg.oneof_type.payload.single_int64) + pure_custom_func(msg.single_int64) +=====> +CALL [1] { + function: cel.@block + args: { + CREATE_LIST [2] { + elements: { + SELECT [3] { + IDENT [4] { + name: msg + }.oneof_type + } + SELECT [5] { + IDENT [6] { + name: @index0 + }.payload + } + SELECT [7] { + IDENT [8] { + name: @index1 + }.single_int64 + } + CALL [9] { + function: pure_custom_func + args: { + IDENT [10] { + name: @index2 + } + } + } + SELECT [11] { + IDENT [12] { + name: msg + }.single_int64 + } + CALL [13] { + function: pure_custom_func + args: { + IDENT [14] { + name: @index4 + } + } + } + SELECT [15] { + IDENT [16] { + name: @index1 + }.single_int32 + } + CALL [17] { + function: pure_custom_func + args: { + IDENT [18] { + name: @index6 + } + } + } + CALL [19] { + function: _+_ + args: { + IDENT [20] { + name: @index3 + } + IDENT [21] { + name: @index7 + } + } + } + CALL [22] { + function: _+_ + args: { + IDENT [23] { + name: @index8 + } + IDENT [24] { + name: @index3 + } + } + } + } + } + CALL [25] { + function: _+_ + args: { + IDENT [26] { + name: @index9 + } + IDENT [27] { + name: @index5 + } + } + } + } +} diff --git a/optimizer/src/test/resources/subexpression_ast_block_recursion_depth_2.baseline b/optimizer/src/test/resources/subexpression_ast_block_recursion_depth_2.baseline index 5a2a4272..ff087237 100644 --- a/optimizer/src/test/resources/subexpression_ast_block_recursion_depth_2.baseline +++ b/optimizer/src/test/resources/subexpression_ast_block_recursion_depth_2.baseline @@ -3567,3 +3567,172 @@ CALL [1] { } } } +Test case: CUSTOM_FUNCTION_INELIMINABLE +Source: non_pure_custom_func(msg.oneof_type.payload.single_int64) + non_pure_custom_func(msg.oneof_type.payload.single_int32) + non_pure_custom_func(msg.oneof_type.payload.single_int64) + non_pure_custom_func(msg.single_int64) +=====> +CALL [1] { + function: cel.@block + args: { + CREATE_LIST [2] { + elements: { + SELECT [3] { + IDENT [4] { + name: msg + }.oneof_type + } + SELECT [5] { + IDENT [6] { + name: @index0 + }.payload + } + SELECT [7] { + IDENT [8] { + name: @index1 + }.single_int64 + } + SELECT [9] { + IDENT [10] { + name: msg + }.single_int64 + } + SELECT [11] { + IDENT [12] { + name: @index1 + }.single_int32 + } + } + } + CALL [13] { + function: _+_ + args: { + CALL [14] { + function: _+_ + args: { + CALL [15] { + function: _+_ + args: { + CALL [16] { + function: non_pure_custom_func + args: { + IDENT [17] { + name: @index2 + } + } + } + CALL [18] { + function: non_pure_custom_func + args: { + IDENT [19] { + name: @index4 + } + } + } + } + } + CALL [20] { + function: non_pure_custom_func + args: { + IDENT [21] { + name: @index2 + } + } + } + } + } + CALL [22] { + function: non_pure_custom_func + args: { + IDENT [23] { + name: @index3 + } + } + } + } + } + } +} +Test case: CUSTOM_FUNCTION_ELIMINABLE +Source: pure_custom_func(msg.oneof_type.payload.single_int64) + pure_custom_func(msg.oneof_type.payload.single_int32) + pure_custom_func(msg.oneof_type.payload.single_int64) + pure_custom_func(msg.single_int64) +=====> +CALL [1] { + function: cel.@block + args: { + CREATE_LIST [2] { + elements: { + SELECT [3] { + IDENT [4] { + name: msg + }.oneof_type + } + SELECT [5] { + IDENT [6] { + name: @index0 + }.payload + } + SELECT [7] { + IDENT [8] { + name: @index1 + }.single_int64 + } + CALL [9] { + function: pure_custom_func + args: { + IDENT [10] { + name: @index2 + } + } + } + CALL [11] { + function: pure_custom_func + args: { + SELECT [12] { + IDENT [13] { + name: msg + }.single_int64 + } + } + } + CALL [14] { + function: pure_custom_func + args: { + SELECT [15] { + IDENT [16] { + name: @index1 + }.single_int32 + } + } + } + CALL [17] { + function: _+_ + args: { + CALL [18] { + function: _+_ + args: { + IDENT [19] { + name: @index3 + } + IDENT [20] { + name: @index5 + } + } + } + IDENT [21] { + name: @index3 + } + } + } + } + } + CALL [22] { + function: _+_ + args: { + IDENT [23] { + name: @index6 + } + IDENT [24] { + name: @index4 + } + } + } + } +} diff --git a/optimizer/src/test/resources/subexpression_ast_block_recursion_depth_3.baseline b/optimizer/src/test/resources/subexpression_ast_block_recursion_depth_3.baseline index bf930a9e..a0ff868b 100644 --- a/optimizer/src/test/resources/subexpression_ast_block_recursion_depth_3.baseline +++ b/optimizer/src/test/resources/subexpression_ast_block_recursion_depth_3.baseline @@ -3357,3 +3357,172 @@ CALL [1] { } } } +Test case: CUSTOM_FUNCTION_INELIMINABLE +Source: non_pure_custom_func(msg.oneof_type.payload.single_int64) + non_pure_custom_func(msg.oneof_type.payload.single_int32) + non_pure_custom_func(msg.oneof_type.payload.single_int64) + non_pure_custom_func(msg.single_int64) +=====> +CALL [1] { + function: cel.@block + args: { + CREATE_LIST [2] { + elements: { + SELECT [3] { + IDENT [4] { + name: msg + }.oneof_type + } + SELECT [5] { + IDENT [6] { + name: @index0 + }.payload + } + SELECT [7] { + IDENT [8] { + name: @index1 + }.single_int64 + } + SELECT [9] { + IDENT [10] { + name: msg + }.single_int64 + } + SELECT [11] { + IDENT [12] { + name: @index1 + }.single_int32 + } + } + } + CALL [13] { + function: _+_ + args: { + CALL [14] { + function: _+_ + args: { + CALL [15] { + function: _+_ + args: { + CALL [16] { + function: non_pure_custom_func + args: { + IDENT [17] { + name: @index2 + } + } + } + CALL [18] { + function: non_pure_custom_func + args: { + IDENT [19] { + name: @index4 + } + } + } + } + } + CALL [20] { + function: non_pure_custom_func + args: { + IDENT [21] { + name: @index2 + } + } + } + } + } + CALL [22] { + function: non_pure_custom_func + args: { + IDENT [23] { + name: @index3 + } + } + } + } + } + } +} +Test case: CUSTOM_FUNCTION_ELIMINABLE +Source: pure_custom_func(msg.oneof_type.payload.single_int64) + pure_custom_func(msg.oneof_type.payload.single_int32) + pure_custom_func(msg.oneof_type.payload.single_int64) + pure_custom_func(msg.single_int64) +=====> +CALL [1] { + function: cel.@block + args: { + CREATE_LIST [2] { + elements: { + SELECT [3] { + IDENT [4] { + name: msg + }.oneof_type + } + SELECT [5] { + IDENT [6] { + name: @index0 + }.payload + } + SELECT [7] { + IDENT [8] { + name: @index1 + }.single_int64 + } + CALL [9] { + function: pure_custom_func + args: { + IDENT [10] { + name: @index2 + } + } + } + CALL [11] { + function: pure_custom_func + args: { + SELECT [12] { + IDENT [13] { + name: msg + }.single_int64 + } + } + } + CALL [14] { + function: _+_ + args: { + IDENT [15] { + name: @index3 + } + CALL [16] { + function: pure_custom_func + args: { + SELECT [17] { + IDENT [18] { + name: @index1 + }.single_int32 + } + } + } + } + } + CALL [19] { + function: _+_ + args: { + IDENT [20] { + name: @index5 + } + IDENT [21] { + name: @index3 + } + } + } + } + } + CALL [22] { + function: _+_ + args: { + IDENT [23] { + name: @index6 + } + IDENT [24] { + name: @index4 + } + } + } + } +} diff --git a/optimizer/src/test/resources/subexpression_ast_block_recursion_depth_4.baseline b/optimizer/src/test/resources/subexpression_ast_block_recursion_depth_4.baseline index c51cefac..71a44069 100644 --- a/optimizer/src/test/resources/subexpression_ast_block_recursion_depth_4.baseline +++ b/optimizer/src/test/resources/subexpression_ast_block_recursion_depth_4.baseline @@ -3324,3 +3324,169 @@ CALL [1] { } } } +Test case: CUSTOM_FUNCTION_INELIMINABLE +Source: non_pure_custom_func(msg.oneof_type.payload.single_int64) + non_pure_custom_func(msg.oneof_type.payload.single_int32) + non_pure_custom_func(msg.oneof_type.payload.single_int64) + non_pure_custom_func(msg.single_int64) +=====> +CALL [1] { + function: cel.@block + args: { + CREATE_LIST [2] { + elements: { + SELECT [3] { + IDENT [4] { + name: msg + }.oneof_type + } + SELECT [5] { + IDENT [6] { + name: @index0 + }.payload + } + SELECT [7] { + IDENT [8] { + name: @index1 + }.single_int64 + } + SELECT [9] { + IDENT [10] { + name: msg + }.single_int64 + } + SELECT [11] { + IDENT [12] { + name: @index1 + }.single_int32 + } + } + } + CALL [13] { + function: _+_ + args: { + CALL [14] { + function: _+_ + args: { + CALL [15] { + function: _+_ + args: { + CALL [16] { + function: non_pure_custom_func + args: { + IDENT [17] { + name: @index2 + } + } + } + CALL [18] { + function: non_pure_custom_func + args: { + IDENT [19] { + name: @index4 + } + } + } + } + } + CALL [20] { + function: non_pure_custom_func + args: { + IDENT [21] { + name: @index2 + } + } + } + } + } + CALL [22] { + function: non_pure_custom_func + args: { + IDENT [23] { + name: @index3 + } + } + } + } + } + } +} +Test case: CUSTOM_FUNCTION_ELIMINABLE +Source: pure_custom_func(msg.oneof_type.payload.single_int64) + pure_custom_func(msg.oneof_type.payload.single_int32) + pure_custom_func(msg.oneof_type.payload.single_int64) + pure_custom_func(msg.single_int64) +=====> +CALL [1] { + function: cel.@block + args: { + CREATE_LIST [2] { + elements: { + SELECT [3] { + IDENT [4] { + name: msg + }.oneof_type + } + SELECT [5] { + IDENT [6] { + name: @index0 + }.payload + } + SELECT [7] { + IDENT [8] { + name: @index1 + }.single_int64 + } + CALL [9] { + function: pure_custom_func + args: { + IDENT [10] { + name: @index2 + } + } + } + CALL [11] { + function: pure_custom_func + args: { + SELECT [12] { + IDENT [13] { + name: msg + }.single_int64 + } + } + } + CALL [14] { + function: _+_ + args: { + CALL [15] { + function: _+_ + args: { + IDENT [16] { + name: @index3 + } + CALL [17] { + function: pure_custom_func + args: { + SELECT [18] { + IDENT [19] { + name: @index1 + }.single_int32 + } + } + } + } + } + IDENT [20] { + name: @index3 + } + } + } + } + } + CALL [21] { + function: _+_ + args: { + IDENT [22] { + name: @index5 + } + IDENT [23] { + name: @index4 + } + } + } + } +} diff --git a/optimizer/src/test/resources/subexpression_ast_block_recursion_depth_5.baseline b/optimizer/src/test/resources/subexpression_ast_block_recursion_depth_5.baseline index 092b2247..d5d799e1 100644 --- a/optimizer/src/test/resources/subexpression_ast_block_recursion_depth_5.baseline +++ b/optimizer/src/test/resources/subexpression_ast_block_recursion_depth_5.baseline @@ -3297,3 +3297,169 @@ CALL [1] { } } } +Test case: CUSTOM_FUNCTION_INELIMINABLE +Source: non_pure_custom_func(msg.oneof_type.payload.single_int64) + non_pure_custom_func(msg.oneof_type.payload.single_int32) + non_pure_custom_func(msg.oneof_type.payload.single_int64) + non_pure_custom_func(msg.single_int64) +=====> +CALL [1] { + function: cel.@block + args: { + CREATE_LIST [2] { + elements: { + SELECT [3] { + IDENT [4] { + name: msg + }.oneof_type + } + SELECT [5] { + IDENT [6] { + name: @index0 + }.payload + } + SELECT [7] { + IDENT [8] { + name: @index1 + }.single_int64 + } + SELECT [9] { + IDENT [10] { + name: msg + }.single_int64 + } + SELECT [11] { + IDENT [12] { + name: @index1 + }.single_int32 + } + } + } + CALL [13] { + function: _+_ + args: { + CALL [14] { + function: _+_ + args: { + CALL [15] { + function: _+_ + args: { + CALL [16] { + function: non_pure_custom_func + args: { + IDENT [17] { + name: @index2 + } + } + } + CALL [18] { + function: non_pure_custom_func + args: { + IDENT [19] { + name: @index4 + } + } + } + } + } + CALL [20] { + function: non_pure_custom_func + args: { + IDENT [21] { + name: @index2 + } + } + } + } + } + CALL [22] { + function: non_pure_custom_func + args: { + IDENT [23] { + name: @index3 + } + } + } + } + } + } +} +Test case: CUSTOM_FUNCTION_ELIMINABLE +Source: pure_custom_func(msg.oneof_type.payload.single_int64) + pure_custom_func(msg.oneof_type.payload.single_int32) + pure_custom_func(msg.oneof_type.payload.single_int64) + pure_custom_func(msg.single_int64) +=====> +CALL [1] { + function: cel.@block + args: { + CREATE_LIST [2] { + elements: { + SELECT [3] { + IDENT [4] { + name: msg + }.oneof_type + } + SELECT [5] { + IDENT [6] { + name: @index0 + }.payload + } + SELECT [7] { + IDENT [8] { + name: @index1 + }.single_int64 + } + CALL [9] { + function: pure_custom_func + args: { + IDENT [10] { + name: @index2 + } + } + } + CALL [11] { + function: pure_custom_func + args: { + SELECT [12] { + IDENT [13] { + name: msg + }.single_int64 + } + } + } + CALL [14] { + function: _+_ + args: { + CALL [15] { + function: _+_ + args: { + IDENT [16] { + name: @index3 + } + CALL [17] { + function: pure_custom_func + args: { + SELECT [18] { + IDENT [19] { + name: @index1 + }.single_int32 + } + } + } + } + } + IDENT [20] { + name: @index3 + } + } + } + } + } + CALL [21] { + function: _+_ + args: { + IDENT [22] { + name: @index5 + } + IDENT [23] { + name: @index4 + } + } + } + } +} diff --git a/optimizer/src/test/resources/subexpression_ast_block_recursion_depth_6.baseline b/optimizer/src/test/resources/subexpression_ast_block_recursion_depth_6.baseline index fb329bab..a2ecbc77 100644 --- a/optimizer/src/test/resources/subexpression_ast_block_recursion_depth_6.baseline +++ b/optimizer/src/test/resources/subexpression_ast_block_recursion_depth_6.baseline @@ -3291,3 +3291,169 @@ CALL [1] { } } } +Test case: CUSTOM_FUNCTION_INELIMINABLE +Source: non_pure_custom_func(msg.oneof_type.payload.single_int64) + non_pure_custom_func(msg.oneof_type.payload.single_int32) + non_pure_custom_func(msg.oneof_type.payload.single_int64) + non_pure_custom_func(msg.single_int64) +=====> +CALL [1] { + function: cel.@block + args: { + CREATE_LIST [2] { + elements: { + SELECT [3] { + IDENT [4] { + name: msg + }.oneof_type + } + SELECT [5] { + IDENT [6] { + name: @index0 + }.payload + } + SELECT [7] { + IDENT [8] { + name: @index1 + }.single_int64 + } + SELECT [9] { + IDENT [10] { + name: msg + }.single_int64 + } + SELECT [11] { + IDENT [12] { + name: @index1 + }.single_int32 + } + } + } + CALL [13] { + function: _+_ + args: { + CALL [14] { + function: _+_ + args: { + CALL [15] { + function: _+_ + args: { + CALL [16] { + function: non_pure_custom_func + args: { + IDENT [17] { + name: @index2 + } + } + } + CALL [18] { + function: non_pure_custom_func + args: { + IDENT [19] { + name: @index4 + } + } + } + } + } + CALL [20] { + function: non_pure_custom_func + args: { + IDENT [21] { + name: @index2 + } + } + } + } + } + CALL [22] { + function: non_pure_custom_func + args: { + IDENT [23] { + name: @index3 + } + } + } + } + } + } +} +Test case: CUSTOM_FUNCTION_ELIMINABLE +Source: pure_custom_func(msg.oneof_type.payload.single_int64) + pure_custom_func(msg.oneof_type.payload.single_int32) + pure_custom_func(msg.oneof_type.payload.single_int64) + pure_custom_func(msg.single_int64) +=====> +CALL [1] { + function: cel.@block + args: { + CREATE_LIST [2] { + elements: { + SELECT [3] { + IDENT [4] { + name: msg + }.oneof_type + } + SELECT [5] { + IDENT [6] { + name: @index0 + }.payload + } + SELECT [7] { + IDENT [8] { + name: @index1 + }.single_int64 + } + CALL [9] { + function: pure_custom_func + args: { + IDENT [10] { + name: @index2 + } + } + } + CALL [11] { + function: pure_custom_func + args: { + SELECT [12] { + IDENT [13] { + name: msg + }.single_int64 + } + } + } + CALL [14] { + function: _+_ + args: { + CALL [15] { + function: _+_ + args: { + IDENT [16] { + name: @index3 + } + CALL [17] { + function: pure_custom_func + args: { + SELECT [18] { + IDENT [19] { + name: @index1 + }.single_int32 + } + } + } + } + } + IDENT [20] { + name: @index3 + } + } + } + } + } + CALL [21] { + function: _+_ + args: { + IDENT [22] { + name: @index5 + } + IDENT [23] { + name: @index4 + } + } + } + } +} diff --git a/optimizer/src/test/resources/subexpression_ast_block_recursion_depth_7.baseline b/optimizer/src/test/resources/subexpression_ast_block_recursion_depth_7.baseline index c318f877..973b97c3 100644 --- a/optimizer/src/test/resources/subexpression_ast_block_recursion_depth_7.baseline +++ b/optimizer/src/test/resources/subexpression_ast_block_recursion_depth_7.baseline @@ -3285,3 +3285,169 @@ CALL [1] { } } } +Test case: CUSTOM_FUNCTION_INELIMINABLE +Source: non_pure_custom_func(msg.oneof_type.payload.single_int64) + non_pure_custom_func(msg.oneof_type.payload.single_int32) + non_pure_custom_func(msg.oneof_type.payload.single_int64) + non_pure_custom_func(msg.single_int64) +=====> +CALL [1] { + function: cel.@block + args: { + CREATE_LIST [2] { + elements: { + SELECT [3] { + IDENT [4] { + name: msg + }.oneof_type + } + SELECT [5] { + IDENT [6] { + name: @index0 + }.payload + } + SELECT [7] { + IDENT [8] { + name: @index1 + }.single_int64 + } + SELECT [9] { + IDENT [10] { + name: msg + }.single_int64 + } + SELECT [11] { + IDENT [12] { + name: @index1 + }.single_int32 + } + } + } + CALL [13] { + function: _+_ + args: { + CALL [14] { + function: _+_ + args: { + CALL [15] { + function: _+_ + args: { + CALL [16] { + function: non_pure_custom_func + args: { + IDENT [17] { + name: @index2 + } + } + } + CALL [18] { + function: non_pure_custom_func + args: { + IDENT [19] { + name: @index4 + } + } + } + } + } + CALL [20] { + function: non_pure_custom_func + args: { + IDENT [21] { + name: @index2 + } + } + } + } + } + CALL [22] { + function: non_pure_custom_func + args: { + IDENT [23] { + name: @index3 + } + } + } + } + } + } +} +Test case: CUSTOM_FUNCTION_ELIMINABLE +Source: pure_custom_func(msg.oneof_type.payload.single_int64) + pure_custom_func(msg.oneof_type.payload.single_int32) + pure_custom_func(msg.oneof_type.payload.single_int64) + pure_custom_func(msg.single_int64) +=====> +CALL [1] { + function: cel.@block + args: { + CREATE_LIST [2] { + elements: { + SELECT [3] { + IDENT [4] { + name: msg + }.oneof_type + } + SELECT [5] { + IDENT [6] { + name: @index0 + }.payload + } + SELECT [7] { + IDENT [8] { + name: @index1 + }.single_int64 + } + CALL [9] { + function: pure_custom_func + args: { + IDENT [10] { + name: @index2 + } + } + } + CALL [11] { + function: pure_custom_func + args: { + SELECT [12] { + IDENT [13] { + name: msg + }.single_int64 + } + } + } + CALL [14] { + function: _+_ + args: { + CALL [15] { + function: _+_ + args: { + IDENT [16] { + name: @index3 + } + CALL [17] { + function: pure_custom_func + args: { + SELECT [18] { + IDENT [19] { + name: @index1 + }.single_int32 + } + } + } + } + } + IDENT [20] { + name: @index3 + } + } + } + } + } + CALL [21] { + function: _+_ + args: { + IDENT [22] { + name: @index5 + } + IDENT [23] { + name: @index4 + } + } + } + } +} diff --git a/optimizer/src/test/resources/subexpression_ast_block_recursion_depth_8.baseline b/optimizer/src/test/resources/subexpression_ast_block_recursion_depth_8.baseline index 10e94e55..67f1b130 100644 --- a/optimizer/src/test/resources/subexpression_ast_block_recursion_depth_8.baseline +++ b/optimizer/src/test/resources/subexpression_ast_block_recursion_depth_8.baseline @@ -3279,3 +3279,169 @@ CALL [1] { } } } +Test case: CUSTOM_FUNCTION_INELIMINABLE +Source: non_pure_custom_func(msg.oneof_type.payload.single_int64) + non_pure_custom_func(msg.oneof_type.payload.single_int32) + non_pure_custom_func(msg.oneof_type.payload.single_int64) + non_pure_custom_func(msg.single_int64) +=====> +CALL [1] { + function: cel.@block + args: { + CREATE_LIST [2] { + elements: { + SELECT [3] { + IDENT [4] { + name: msg + }.oneof_type + } + SELECT [5] { + IDENT [6] { + name: @index0 + }.payload + } + SELECT [7] { + IDENT [8] { + name: @index1 + }.single_int64 + } + SELECT [9] { + IDENT [10] { + name: msg + }.single_int64 + } + SELECT [11] { + IDENT [12] { + name: @index1 + }.single_int32 + } + } + } + CALL [13] { + function: _+_ + args: { + CALL [14] { + function: _+_ + args: { + CALL [15] { + function: _+_ + args: { + CALL [16] { + function: non_pure_custom_func + args: { + IDENT [17] { + name: @index2 + } + } + } + CALL [18] { + function: non_pure_custom_func + args: { + IDENT [19] { + name: @index4 + } + } + } + } + } + CALL [20] { + function: non_pure_custom_func + args: { + IDENT [21] { + name: @index2 + } + } + } + } + } + CALL [22] { + function: non_pure_custom_func + args: { + IDENT [23] { + name: @index3 + } + } + } + } + } + } +} +Test case: CUSTOM_FUNCTION_ELIMINABLE +Source: pure_custom_func(msg.oneof_type.payload.single_int64) + pure_custom_func(msg.oneof_type.payload.single_int32) + pure_custom_func(msg.oneof_type.payload.single_int64) + pure_custom_func(msg.single_int64) +=====> +CALL [1] { + function: cel.@block + args: { + CREATE_LIST [2] { + elements: { + SELECT [3] { + IDENT [4] { + name: msg + }.oneof_type + } + SELECT [5] { + IDENT [6] { + name: @index0 + }.payload + } + SELECT [7] { + IDENT [8] { + name: @index1 + }.single_int64 + } + CALL [9] { + function: pure_custom_func + args: { + IDENT [10] { + name: @index2 + } + } + } + CALL [11] { + function: pure_custom_func + args: { + SELECT [12] { + IDENT [13] { + name: msg + }.single_int64 + } + } + } + CALL [14] { + function: _+_ + args: { + CALL [15] { + function: _+_ + args: { + IDENT [16] { + name: @index3 + } + CALL [17] { + function: pure_custom_func + args: { + SELECT [18] { + IDENT [19] { + name: @index1 + }.single_int32 + } + } + } + } + } + IDENT [20] { + name: @index3 + } + } + } + } + } + CALL [21] { + function: _+_ + args: { + IDENT [22] { + name: @index5 + } + IDENT [23] { + name: @index4 + } + } + } + } +} diff --git a/optimizer/src/test/resources/subexpression_ast_block_recursion_depth_9.baseline b/optimizer/src/test/resources/subexpression_ast_block_recursion_depth_9.baseline index 0988f15f..fc16cdf8 100644 --- a/optimizer/src/test/resources/subexpression_ast_block_recursion_depth_9.baseline +++ b/optimizer/src/test/resources/subexpression_ast_block_recursion_depth_9.baseline @@ -3276,3 +3276,169 @@ CALL [1] { } } } +Test case: CUSTOM_FUNCTION_INELIMINABLE +Source: non_pure_custom_func(msg.oneof_type.payload.single_int64) + non_pure_custom_func(msg.oneof_type.payload.single_int32) + non_pure_custom_func(msg.oneof_type.payload.single_int64) + non_pure_custom_func(msg.single_int64) +=====> +CALL [1] { + function: cel.@block + args: { + CREATE_LIST [2] { + elements: { + SELECT [3] { + IDENT [4] { + name: msg + }.oneof_type + } + SELECT [5] { + IDENT [6] { + name: @index0 + }.payload + } + SELECT [7] { + IDENT [8] { + name: @index1 + }.single_int64 + } + SELECT [9] { + IDENT [10] { + name: msg + }.single_int64 + } + SELECT [11] { + IDENT [12] { + name: @index1 + }.single_int32 + } + } + } + CALL [13] { + function: _+_ + args: { + CALL [14] { + function: _+_ + args: { + CALL [15] { + function: _+_ + args: { + CALL [16] { + function: non_pure_custom_func + args: { + IDENT [17] { + name: @index2 + } + } + } + CALL [18] { + function: non_pure_custom_func + args: { + IDENT [19] { + name: @index4 + } + } + } + } + } + CALL [20] { + function: non_pure_custom_func + args: { + IDENT [21] { + name: @index2 + } + } + } + } + } + CALL [22] { + function: non_pure_custom_func + args: { + IDENT [23] { + name: @index3 + } + } + } + } + } + } +} +Test case: CUSTOM_FUNCTION_ELIMINABLE +Source: pure_custom_func(msg.oneof_type.payload.single_int64) + pure_custom_func(msg.oneof_type.payload.single_int32) + pure_custom_func(msg.oneof_type.payload.single_int64) + pure_custom_func(msg.single_int64) +=====> +CALL [1] { + function: cel.@block + args: { + CREATE_LIST [2] { + elements: { + SELECT [3] { + IDENT [4] { + name: msg + }.oneof_type + } + SELECT [5] { + IDENT [6] { + name: @index0 + }.payload + } + SELECT [7] { + IDENT [8] { + name: @index1 + }.single_int64 + } + CALL [9] { + function: pure_custom_func + args: { + IDENT [10] { + name: @index2 + } + } + } + CALL [11] { + function: pure_custom_func + args: { + SELECT [12] { + IDENT [13] { + name: msg + }.single_int64 + } + } + } + CALL [14] { + function: _+_ + args: { + CALL [15] { + function: _+_ + args: { + IDENT [16] { + name: @index3 + } + CALL [17] { + function: pure_custom_func + args: { + SELECT [18] { + IDENT [19] { + name: @index1 + }.single_int32 + } + } + } + } + } + IDENT [20] { + name: @index3 + } + } + } + } + } + CALL [21] { + function: _+_ + args: { + IDENT [22] { + name: @index5 + } + IDENT [23] { + name: @index4 + } + } + } + } +} diff --git a/optimizer/src/test/resources/subexpression_ast_cascaded_binds.baseline b/optimizer/src/test/resources/subexpression_ast_cascaded_binds.baseline index 0dd7c673..08e58405 100644 --- a/optimizer/src/test/resources/subexpression_ast_cascaded_binds.baseline +++ b/optimizer/src/test/resources/subexpression_ast_cascaded_binds.baseline @@ -3892,3 +3892,218 @@ CALL [12] { } } } +Test case: CUSTOM_FUNCTION_INELIMINABLE +Source: non_pure_custom_func(msg.oneof_type.payload.single_int64) + non_pure_custom_func(msg.oneof_type.payload.single_int32) + non_pure_custom_func(msg.oneof_type.payload.single_int64) + non_pure_custom_func(msg.single_int64) +=====> +CALL [1] { + function: _+_ + args: { + COMPREHENSION [2] { + iter_var: #unused + iter_range: { + CREATE_LIST [3] { + elements: { + } + } + } + accu_var: @r0 + accu_init: { + SELECT [4] { + SELECT [5] { + IDENT [6] { + name: msg + }.oneof_type + }.payload + } + } + loop_condition: { + CONSTANT [7] { value: false } + } + loop_step: { + IDENT [8] { + name: @r0 + } + } + result: { + COMPREHENSION [9] { + iter_var: #unused + iter_range: { + CREATE_LIST [10] { + elements: { + } + } + } + accu_var: @r1 + accu_init: { + SELECT [11] { + IDENT [12] { + name: @r0 + }.single_int64 + } + } + loop_condition: { + CONSTANT [13] { value: false } + } + loop_step: { + IDENT [14] { + name: @r1 + } + } + result: { + CALL [15] { + function: _+_ + args: { + CALL [16] { + function: _+_ + args: { + CALL [17] { + function: non_pure_custom_func + args: { + IDENT [18] { + name: @r1 + } + } + } + CALL [19] { + function: non_pure_custom_func + args: { + SELECT [20] { + IDENT [21] { + name: @r0 + }.single_int32 + } + } + } + } + } + CALL [22] { + function: non_pure_custom_func + args: { + IDENT [23] { + name: @r1 + } + } + } + } + } + } + } + } + } + CALL [24] { + function: non_pure_custom_func + args: { + SELECT [25] { + IDENT [26] { + name: msg + }.single_int64 + } + } + } + } +} +Test case: CUSTOM_FUNCTION_ELIMINABLE +Source: pure_custom_func(msg.oneof_type.payload.single_int64) + pure_custom_func(msg.oneof_type.payload.single_int32) + pure_custom_func(msg.oneof_type.payload.single_int64) + pure_custom_func(msg.single_int64) +=====> +CALL [1] { + function: _+_ + args: { + COMPREHENSION [2] { + iter_var: #unused + iter_range: { + CREATE_LIST [3] { + elements: { + } + } + } + accu_var: @r0 + accu_init: { + SELECT [4] { + SELECT [5] { + IDENT [6] { + name: msg + }.oneof_type + }.payload + } + } + loop_condition: { + CONSTANT [7] { value: false } + } + loop_step: { + IDENT [8] { + name: @r0 + } + } + result: { + COMPREHENSION [9] { + iter_var: #unused + iter_range: { + CREATE_LIST [10] { + elements: { + } + } + } + accu_var: @r1 + accu_init: { + CALL [11] { + function: pure_custom_func + args: { + SELECT [12] { + IDENT [13] { + name: @r0 + }.single_int64 + } + } + } + } + loop_condition: { + CONSTANT [14] { value: false } + } + loop_step: { + IDENT [15] { + name: @r1 + } + } + result: { + CALL [16] { + function: _+_ + args: { + CALL [17] { + function: _+_ + args: { + IDENT [18] { + name: @r1 + } + CALL [19] { + function: pure_custom_func + args: { + SELECT [20] { + IDENT [21] { + name: @r0 + }.single_int32 + } + } + } + } + } + IDENT [22] { + name: @r1 + } + } + } + } + } + } + } + CALL [23] { + function: pure_custom_func + args: { + SELECT [24] { + IDENT [25] { + name: msg + }.single_int64 + } + } + } + } +} diff --git a/optimizer/src/test/resources/subexpression_unparsed.baseline b/optimizer/src/test/resources/subexpression_unparsed.baseline index 73e3507f..f820ae1e 100644 --- a/optimizer/src/test/resources/subexpression_unparsed.baseline +++ b/optimizer/src/test/resources/subexpression_unparsed.baseline @@ -621,3 +621,35 @@ Result: true [BLOCK_RECURSION_DEPTH_7]: cel.@block(["w" + "o" + "r" + "l" + "d", "h" + "e" + "l" + "l" + "o" + " world"], @index1.matches(@index0)) [BLOCK_RECURSION_DEPTH_8]: cel.@block(["w" + "o" + "r" + "l" + "d", "h" + "e" + "l" + "l" + "o" + " world"], @index1.matches(@index0)) [BLOCK_RECURSION_DEPTH_9]: cel.@block(["w" + "o" + "r" + "l" + "d", "h" + "e" + "l" + "l" + "o" + " world"], @index1.matches(@index0)) + +Test case: CUSTOM_FUNCTION_INELIMINABLE +Source: non_pure_custom_func(msg.oneof_type.payload.single_int64) + non_pure_custom_func(msg.oneof_type.payload.single_int32) + non_pure_custom_func(msg.oneof_type.payload.single_int64) + non_pure_custom_func(msg.single_int64) +=====> +Result: 31 +[CASCADED_BINDS]: cel.bind(@r0, msg.oneof_type.payload, cel.bind(@r1, @r0.single_int64, non_pure_custom_func(@r1) + non_pure_custom_func(@r0.single_int32) + non_pure_custom_func(@r1))) + non_pure_custom_func(msg.single_int64) +[BLOCK_COMMON_SUBEXPR_ONLY]: cel.@block([msg.oneof_type.payload, @index0.single_int64], non_pure_custom_func(@index1) + non_pure_custom_func(@index0.single_int32) + non_pure_custom_func(@index1) + non_pure_custom_func(msg.single_int64)) +[BLOCK_RECURSION_DEPTH_1]: cel.@block([msg.oneof_type, @index0.payload, @index1.single_int64, msg.single_int64, @index1.single_int32], non_pure_custom_func(@index2) + non_pure_custom_func(@index4) + non_pure_custom_func(@index2) + non_pure_custom_func(@index3)) +[BLOCK_RECURSION_DEPTH_2]: cel.@block([msg.oneof_type, @index0.payload, @index1.single_int64, msg.single_int64, @index1.single_int32], non_pure_custom_func(@index2) + non_pure_custom_func(@index4) + non_pure_custom_func(@index2) + non_pure_custom_func(@index3)) +[BLOCK_RECURSION_DEPTH_3]: cel.@block([msg.oneof_type, @index0.payload, @index1.single_int64, msg.single_int64, @index1.single_int32], non_pure_custom_func(@index2) + non_pure_custom_func(@index4) + non_pure_custom_func(@index2) + non_pure_custom_func(@index3)) +[BLOCK_RECURSION_DEPTH_4]: cel.@block([msg.oneof_type, @index0.payload, @index1.single_int64, msg.single_int64, @index1.single_int32], non_pure_custom_func(@index2) + non_pure_custom_func(@index4) + non_pure_custom_func(@index2) + non_pure_custom_func(@index3)) +[BLOCK_RECURSION_DEPTH_5]: cel.@block([msg.oneof_type, @index0.payload, @index1.single_int64, msg.single_int64, @index1.single_int32], non_pure_custom_func(@index2) + non_pure_custom_func(@index4) + non_pure_custom_func(@index2) + non_pure_custom_func(@index3)) +[BLOCK_RECURSION_DEPTH_6]: cel.@block([msg.oneof_type, @index0.payload, @index1.single_int64, msg.single_int64, @index1.single_int32], non_pure_custom_func(@index2) + non_pure_custom_func(@index4) + non_pure_custom_func(@index2) + non_pure_custom_func(@index3)) +[BLOCK_RECURSION_DEPTH_7]: cel.@block([msg.oneof_type, @index0.payload, @index1.single_int64, msg.single_int64, @index1.single_int32], non_pure_custom_func(@index2) + non_pure_custom_func(@index4) + non_pure_custom_func(@index2) + non_pure_custom_func(@index3)) +[BLOCK_RECURSION_DEPTH_8]: cel.@block([msg.oneof_type, @index0.payload, @index1.single_int64, msg.single_int64, @index1.single_int32], non_pure_custom_func(@index2) + non_pure_custom_func(@index4) + non_pure_custom_func(@index2) + non_pure_custom_func(@index3)) +[BLOCK_RECURSION_DEPTH_9]: cel.@block([msg.oneof_type, @index0.payload, @index1.single_int64, msg.single_int64, @index1.single_int32], non_pure_custom_func(@index2) + non_pure_custom_func(@index4) + non_pure_custom_func(@index2) + non_pure_custom_func(@index3)) + +Test case: CUSTOM_FUNCTION_ELIMINABLE +Source: pure_custom_func(msg.oneof_type.payload.single_int64) + pure_custom_func(msg.oneof_type.payload.single_int32) + pure_custom_func(msg.oneof_type.payload.single_int64) + pure_custom_func(msg.single_int64) +=====> +Result: 31 +[CASCADED_BINDS]: cel.bind(@r0, msg.oneof_type.payload, cel.bind(@r1, pure_custom_func(@r0.single_int64), @r1 + pure_custom_func(@r0.single_int32) + @r1)) + pure_custom_func(msg.single_int64) +[BLOCK_COMMON_SUBEXPR_ONLY]: cel.@block([msg.oneof_type.payload, pure_custom_func(@index0.single_int64)], @index1 + pure_custom_func(@index0.single_int32) + @index1 + pure_custom_func(msg.single_int64)) +[BLOCK_RECURSION_DEPTH_1]: cel.@block([msg.oneof_type, @index0.payload, @index1.single_int64, pure_custom_func(@index2), msg.single_int64, pure_custom_func(@index4), @index1.single_int32, pure_custom_func(@index6), @index3 + @index7, @index8 + @index3], @index9 + @index5) +[BLOCK_RECURSION_DEPTH_2]: cel.@block([msg.oneof_type, @index0.payload, @index1.single_int64, pure_custom_func(@index2), pure_custom_func(msg.single_int64), pure_custom_func(@index1.single_int32), @index3 + @index5 + @index3], @index6 + @index4) +[BLOCK_RECURSION_DEPTH_3]: cel.@block([msg.oneof_type, @index0.payload, @index1.single_int64, pure_custom_func(@index2), pure_custom_func(msg.single_int64), @index3 + pure_custom_func(@index1.single_int32), @index5 + @index3], @index6 + @index4) +[BLOCK_RECURSION_DEPTH_4]: cel.@block([msg.oneof_type, @index0.payload, @index1.single_int64, pure_custom_func(@index2), pure_custom_func(msg.single_int64), @index3 + pure_custom_func(@index1.single_int32) + @index3], @index5 + @index4) +[BLOCK_RECURSION_DEPTH_5]: cel.@block([msg.oneof_type, @index0.payload, @index1.single_int64, pure_custom_func(@index2), pure_custom_func(msg.single_int64), @index3 + pure_custom_func(@index1.single_int32) + @index3], @index5 + @index4) +[BLOCK_RECURSION_DEPTH_6]: cel.@block([msg.oneof_type, @index0.payload, @index1.single_int64, pure_custom_func(@index2), pure_custom_func(msg.single_int64), @index3 + pure_custom_func(@index1.single_int32) + @index3], @index5 + @index4) +[BLOCK_RECURSION_DEPTH_7]: cel.@block([msg.oneof_type, @index0.payload, @index1.single_int64, pure_custom_func(@index2), pure_custom_func(msg.single_int64), @index3 + pure_custom_func(@index1.single_int32) + @index3], @index5 + @index4) +[BLOCK_RECURSION_DEPTH_8]: cel.@block([msg.oneof_type, @index0.payload, @index1.single_int64, pure_custom_func(@index2), pure_custom_func(msg.single_int64), @index3 + pure_custom_func(@index1.single_int32) + @index3], @index5 + @index4) +[BLOCK_RECURSION_DEPTH_9]: cel.@block([msg.oneof_type, @index0.payload, @index1.single_int64, pure_custom_func(@index2), pure_custom_func(msg.single_int64), @index3 + pure_custom_func(@index1.single_int32) + @index3], @index5 + @index4)