diff a/src/jdk.incubator.code/share/classes/jdk/incubator/code/dialect/java/ControlFlowBooleanExpressionOp.java b/src/jdk.incubator.code/share/classes/jdk/incubator/code/dialect/java/ControlFlowBooleanExpressionOp.java --- /dev/null +++ b/src/jdk.incubator.code/share/classes/jdk/incubator/code/dialect/java/ControlFlowBooleanExpressionOp.java @@ -0,0 +1,255 @@ +/* + * Copyright (c) 2026, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package jdk.incubator.code.dialect.java; + +import jdk.incubator.code.*; +import jdk.incubator.code.dialect.core.CoreOp; + +import java.util.*; +import java.util.function.BiFunction; + +import static jdk.incubator.code.Op.Lowerable.loweringTransformer; + +/** + * An operation characteristic indicating that an operation can model a boolean expression whose evaluation contains + * control flow. Such operations can lower themselves using a supplied continuation for its boolean result to produce + * simpler control flow graphs. + *
+ * For example, consider the following code, in which a boolean expression is used by a {@code while} statement: + * {@snippet lang = java: + * while (a && (b || c)) { + * ... + * } + * } + * The result of the {@code while} loop's boolean expression determines whether the loop body is executed or the loop + * finishes. If {@code a} is {@code true} and {@code b} or {@code c} is {@code true} then the loop body is executed. + * Conversely, if {@code a} is {@code false} or {@code b} and {@code c} is {@code false} then the loop finishes. + *
+ * The code model for this code contains a while operation, modeling the {@code while} statement. When the while
+ * operation lowers itself it creates a boolean result continuation containing block references to the blocks associated
+ * with start of executing the loop body and the loop finishing, referred to respectively as true and false branch
+ * references.
+ * That boolean result continuation is used when lowering operation's predicate body, which models the boolean
+ * expression, the conditional-and operation modeling the conditional-and expression. The continuation is passed along
+ * when lowering the sub-expressions, and when needed the continuation is operated on to continue with a boolean result
+ * or to obtain block references for a statically known boolean result. Consequently, the lowering of the boolean
+ * expression will directly branch to the while operation's continuation's true and false branch references. This is far
+ * more preferable than creating localized control flow behavior that joins to blocks whose boolean block parameter
+ * represents an intermediate boolean result; a result that is then used by a conditional branch operations to continue
+ * towards the blocks of the lowered while operation.
+ */
+interface ControlFlowBooleanExpressionOp extends Op.Lowerable {
+
+ ContextStackArg
+ * If the lowering of a boolean expression operation needs to continue with expression's boolean result value,
+ * then it can invoke {@link #continueWith(Block.Builder, Value) continueWith}. Otherwise, if lowering statically
+ * knows the value of the expression and requires a block reference targeting a continuing block corresponding to
+ * that known value , then it can invoke {@link #referenceFor(Block.Builder, boolean) referenceFor}.
+ */
+ sealed interface BooleanResultContinuation
+ permits ConditionalBranchContinuation, BranchWithArgumentContinuation {
+ /**
+ * Continues with the result of a boolean expression.
+ *
+ * @param block the block to add a block terminating operation
+ * @param result the boolean result.
+ */
+ void continueWith(Block.Builder block, Value result);
+
+ /**
+ * Creates a block reference to branch to continue the result of the boolean expression when the result is
+ * statically known.
+ *
+ * @param block the block to add any necessary operations
+ * @param result the static boolean result
+ * @return the block reference to continue the result
+ */
+ Block.Reference referenceFor(Block.Builder block, boolean result);
+
+ /**
+ * Creates a conditional branch continuation from this continuation to be used as the continuation of a boolean
+ * expression.
+ *
+ * @param negatesExpression true if the result of the expression is negated
+ * @return the conditional branch continuation
+ */
+ default ConditionalBranchContinuation forExpression(Block.Builder block, boolean negatesExpression) {
+ Block.Reference trueRef = referenceFor(block, !negatesExpression);
+ Block.Reference falseRef = referenceFor(block, negatesExpression);
+ return new ConditionalBranchContinuation(trueRef, falseRef);
+ }
+ }
+
+ /**
+ * Represents a boolean result continuation as block references to blocks corresponding to continuing the
+ * {@code true} result and the {@code false} result.
+ *
+ * @param trueRef the block reference to a block corresponding to continuing the {@code true} result
+ * @param falseRef the block reference to a block corresponding to continuing the {@code false} result
+ */
+ record ConditionalBranchContinuation(
+ Block.Reference trueRef,
+ Block.Reference falseRef) implements BooleanResultContinuation {
+ @Override
+ public void continueWith(Block.Builder block, Value result) {
+ // result will be present in a model being built, so only its operation structure can be queried
+ if (result instanceof Op.Result opResult
+ && opResult.op() instanceof CoreOp.ConstantOp constant
+ && constant.value() instanceof Boolean booleanValue) {
+ block.add(CoreOp.branch(
+ booleanValue ? trueRef : falseRef));
+ } else {
+ block.add(CoreOp.conditionalBranch(result, trueRef, falseRef));
+ }
+ }
+
+ @Override
+ public Block.Reference referenceFor(Block.Builder block, boolean result) {
+ return result ? trueRef : falseRef;
+ }
+
+ @Override
+ public ConditionalBranchContinuation forExpression(Block.Builder block, boolean negatesExpression) {
+ return !negatesExpression
+ ? this
+ : new ConditionalBranchContinuation(falseRef, trueRef);
+ }
+ }
+
+ /**
+ * Represents a boolean result continuation as a result block with a boolean parameter, whose value corresponds to
+ * continuing the {@code true} result and the {@code false} result.
+ *
+ * @param resultBlock the result block with a boolean parameter corresponding to continuing the {@code true}
+ * and {@code false} result
+ */
+ record BranchWithArgumentContinuation(Block.Builder resultBlock) implements BooleanResultContinuation {
+ @Override
+ public void continueWith(Block.Builder block, Value result) {
+ block.add(CoreOp.branch(resultBlock.reference(result)));
+ }
+
+ @Override
+ public Block.Reference referenceFor(Block.Builder block, boolean result) {
+ return resultBlock.reference(block.add(CoreOp.constant(JavaType.BOOLEAN, result)));
+ }
+ }
+
+ record BooleanExpressionSuffix(ControlFlowBooleanExpressionOp expression, boolean negatesExpression) {
+ }
+
+ private static BooleanExpressionSuffix findBooleanExpressionSuffix(Body body) {
+ if (body.blocks().size() != 1) {
+ return null;
+ }
+
+ Block block = body.entryBlock();
+
+ // Find suffix of
+ // ControlFlowBooleanExpressionOp
+ // NotOp *
+ // CoreOp.YieldOp
+
+ Op.Terminating yop = block.terminatingOp();
+ if (!(yop instanceof CoreOp.YieldOp)) {
+ return null;
+ }
+
+ boolean negatesExpression = false;
+ Op next = yop;
+ Op expression = null;
+ List