Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -81,11 +81,12 @@ case CoreOp.BranchOp bop when isPureConditionalDispatchingBlock(bop.branch().tar
&& or.op() instanceof CoreOp.ConstantOp cop -> {
// Skip intermediate conditional branch with constant boolean argument and re-target
// directly to the true or false branch, based on the constant value.
CoreOp.ConditionalBranchOp cbo = (CoreOp.ConditionalBranchOp)bop.branch().targetBlock().terminatingOp();
Block.Reference br = (Boolean)cop.value() ? cbo.trueBranch() : cbo.falseBranch();
CoreOp.ConditionalBranchOp cbo = (CoreOp.ConditionalBranchOp) bop.branch().targetBlock().terminatingOp();
Block.Reference br = (boolean) cop.value() ? cbo.trueBranch() : cbo.falseBranch();
// Remove the conditional dispatching block if all predecessor reference args are constants
if (bop.branch().targetBlock().predecessorReferences().stream()
.allMatch(r -> r.arguments().getFirst() instanceof Op.Result orr && orr.op() instanceof CoreOp.ConstantOp)) {
.allMatch(r -> r.arguments().getFirst() instanceof Op.Result orr &&
orr.op() instanceof CoreOp.ConstantOp)) {
mergedBlocks.add(bop.branch().targetBlock());
if (br.targetBlock().predecessors().size() == 1) {
// Merge the successor's target block with this block
Expand All @@ -95,17 +96,21 @@ case CoreOp.BranchOp bop when isPureConditionalDispatchingBlock(bop.branch().tar
}
b.add(CoreOp.branch(b.context().getReferenceOrCreate(br)));
}
case CoreOp.ConditionalBranchOp cbo -> {
if (!replaceConditionalBranchTarget(b, cbo, cbo.trueBranch())) {
removeUnusedBlockParameters(b, cbo.trueBranch());
}
if (!replaceConditionalBranchTarget(b, cbo, cbo.falseBranch())) {
removeUnusedBlockParameters(b, cbo.falseBranch());
}
b.add(op);
}
case CoreOp.BranchOp bop when bop.branch().targetBlock().predecessors().size() == 1 -> {
// Merge the successor's target block with this block, and so on
// The terminal branch operation is replaced with the operations in the
// successor's target block
mergeBlock(b, bop);
}
case CoreOp.ConstantOp cop when cop.resultType().equals(JavaType.BOOLEAN)
&& cop.result().uses().stream().allMatch(cr -> cr.op() instanceof CoreOp.BranchOp bop
&& isPureConditionalDispatchingBlock(bop.branch().targetBlock())) -> {
// Remove boolean ConstantOp used purelly as BranchOp successor arguments to a conditional dispatching block
}
case JavaOp.ExceptionRegionEnter ere -> {
// Cannot remove block parameters from exception handlers
removeUnusedBlockParameters(b, ere.startReference());
Expand All @@ -129,6 +134,71 @@ && isPureConditionalDispatchingBlock(bop.branch().targetBlock())) -> {
return b;
}

private boolean replaceConditionalBranchTarget(Block.Builder b,
CoreOp.ConditionalBranchOp cbo,
Block.Reference successor) {
assert cbo.successors().contains(successor);

Block target = successor.targetBlock();
if (isPureConditionalDispatchingBlock(target)) {
if (successor.arguments().getFirst() == cbo.predicateOperand()) {
/*
func @"m" (%0 : java.type:"boolean")java.type:"void" -> {
cbranch %0 ^block_1 ^block_2(%0);
->
cbranch %0 ^block_1 ^block_3;

^block_1:
branch ^block_3;

^block_2(%1 : java.type:"boolean"):
cbranch %1 ^block_3 ^block_4;

^block_3:
branch ^block_5;
*/
CoreOp.ConditionalBranchOp targetCbo = (CoreOp.ConditionalBranchOp) target.terminatingOp();
Block.Reference replacementSuccessor = cbo.trueBranch() == successor
? targetCbo.trueBranch()
: targetCbo.falseBranch();
b.context().mapReference(successor,
b.context().getReferenceOrCreate(replacementSuccessor));
return true;
} else if (successor.arguments().getFirst() instanceof Op.Result or
&& or.op() instanceof CoreOp.ConstantOp cop) {
/*
func @"m" ()java.type:"void" -> {
%false : java.type:"boolean" = constant @false;
cbranch %0 ^block_1 ^block_2(%false);
->
cbranch %0 ^block_1 ^block_3;

^block_1:
branch ^block_3;

^block_2(%1 : java.type:"boolean"):
cbranch %1 ^block_3 ^block_4;

^block_3:
branch ^block_5;
*/

CoreOp.ConditionalBranchOp targetCbo = (CoreOp.ConditionalBranchOp) target.terminatingOp();
Block.Reference replacementSuccessor = (boolean) cop.value()
? targetCbo.trueBranch()
: targetCbo.falseBranch();
b.context().mapReference(successor,
b.context().getReferenceOrCreate(replacementSuccessor));
return true;
}
}
return false;
}

/*
^b(%pred : java.type:"boolean"):
cbranch %pred ^true ^false;
*/
private static boolean isPureConditionalDispatchingBlock(Block b) {
return b.parameters().size() == 1
&& b.parameters().getFirst().type().equals(JavaType.BOOLEAN)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4597,6 +4597,9 @@ static Block.Builder lower(Block.Builder startBlock, BiFunction<Block.Builder, O
CodeType oprType = cop.result().type();
Block.Parameter arg = exit.parameter(oprType);
startBlock.context().mapValue(cop.result(), arg);
// Short circuit exit reference, with false for && and true for ||
Block.Reference shortCircuitRef = exit.reference(startBlock.add(constant(BOOLEAN,
cop instanceof ConditionalOrOp)));

// Transform bodies in reverse order
// This makes available the blocks to be referenced as successors in prior blocks
Expand All @@ -4621,9 +4624,9 @@ static Block.Builder lower(Block.Builder startBlock, BiFunction<Block.Builder, O
if (op instanceof CoreOp.YieldOp yop) {
Value p = block.context().getValue(yop.yieldValue());
if (cop instanceof ConditionalAndOp) {
block.add(conditionalBranch(p, nextPred.reference(), exit.reference(p)));
block.add(conditionalBranch(p, nextPred.reference(), shortCircuitRef));
} else {
block.add(conditionalBranch(p, exit.reference(p), nextPred.reference()));
block.add(conditionalBranch(p, shortCircuitRef, nextPred.reference()));
}
return block;
} else {
Expand Down Expand Up @@ -6138,34 +6141,25 @@ public Value targetOperand() {
}

@Override
public Block.Builder lower(Block.Builder b, BiFunction<Block.Builder, Op, Block.Builder> inherited) {
// No match block
Block.Builder endNoMatchBlock = b.block();
// Match block
Block.Builder endMatchBlock = b.block();
public Block.Builder lower(Block.Builder startBlock, BiFunction<Block.Builder, Op, Block.Builder> inherited) {
// End block
Block.Builder endBlock = b.block();
Block.Builder endBlock = startBlock.block();
Block.Parameter matchResult = endBlock.parameter(resultType());
// Map match operation result
b.context().mapValue(result(), matchResult);
startBlock.context().mapValue(result(), matchResult);
Block.Reference noMatchRef = endBlock.reference(startBlock.add(constant(BOOLEAN, false)));

List<Value> patternValues = new ArrayList<>();
Op patternYieldOp = patternBody.entryBlock().terminatingOp();
Op.Result rootPatternValue = (Op.Result) patternYieldOp.operands().get(0);
Block.Builder currentBlock = lower(endNoMatchBlock, b,
Block.Builder matchedBlock = lower(noMatchRef, startBlock,
patternValues,
rootPatternValue.op(),
b.context().getValue(targetOperand()));
currentBlock.add(branch(endMatchBlock.reference()));

// No match block
// Pass false
endNoMatchBlock.add(branch(endBlock.reference(
endNoMatchBlock.add(constant(BOOLEAN, false)))));
startBlock.context().getValue(targetOperand()));

// Match block
// Lower match body and pass true
endMatchBlock.transformBody(matchBody, patternValues, loweringTransformer(inherited, (block, op) -> {
matchedBlock.transformBody(matchBody, patternValues, loweringTransformer(inherited, (block, op) -> {
if (op instanceof CoreOp.YieldOp) {
block.add(branch(endBlock.reference(
block.add(constant(BOOLEAN, true)))));
Expand All @@ -6178,18 +6172,18 @@ public Block.Builder lower(Block.Builder b, BiFunction<Block.Builder, Op, Block.
return endBlock;
}

static Block.Builder lower(Block.Builder endNoMatchBlock, Block.Builder currentBlock,
static Block.Builder lower(Block.Reference noMatchRef, Block.Builder currentBlock,
List<Value> bindings,
Op pattern, Value target) {
return switch (pattern) {
case RecordPatternOp rp -> lowerRecordPattern(endNoMatchBlock, currentBlock, bindings, rp, target);
case TypePatternOp tp -> lowerTypePattern(endNoMatchBlock, currentBlock, bindings, tp, target);
case MatchAllPatternOp map -> lowerMatchAllPattern(currentBlock);
case RecordPatternOp rp -> lowerRecordPattern(noMatchRef, currentBlock, bindings, rp, target);
case TypePatternOp tp -> lowerTypePattern(noMatchRef, currentBlock, bindings, tp, target);
case MatchAllPatternOp _ -> lowerMatchAllPattern(currentBlock);
case null, default -> throw new UnsupportedOperationException("Unknown pattern op: " + pattern);
};
}

static Block.Builder lowerRecordPattern(Block.Builder endNoMatchBlock, Block.Builder currentBlock,
static Block.Builder lowerRecordPattern(Block.Reference noMatchRef, Block.Builder currentBlock,
List<Value> bindings,
JavaOp.PatternOps.RecordPatternOp rpOp, Value target) {
CodeType targetType = rpOp.targetType();
Expand All @@ -6198,7 +6192,7 @@ static Block.Builder lowerRecordPattern(Block.Builder endNoMatchBlock, Block.Bui

// Check if instance of target type
Op.Result isInstance = currentBlock.add(instanceOf(targetType, target));
currentBlock.add(conditionalBranch(isInstance, nextBlock.reference(), endNoMatchBlock.reference()));
currentBlock.add(conditionalBranch(isInstance, nextBlock.reference(), noMatchRef));

currentBlock = nextBlock;

Expand All @@ -6209,15 +6203,15 @@ static Block.Builder lowerRecordPattern(Block.Builder endNoMatchBlock, Block.Bui
for (int i = 0; i < dArgs.size(); i++) {
Op.Result nestedPattern = (Op.Result) dArgs.get(i);
// @@@ Handle exceptions?
Value nestedTarget = currentBlock.add(invoke(rpOp.recordReference().methodForComponent(i), target));
Value nestedTarget = currentBlock.add(invoke(rpOp.recordReference().methodForComponent(i), target));

currentBlock = lower(endNoMatchBlock, currentBlock, bindings, nestedPattern.op(), nestedTarget);
currentBlock = lower(noMatchRef, currentBlock, bindings, nestedPattern.op(), nestedTarget);
}

return currentBlock;
}

static Block.Builder lowerTypePattern(Block.Builder endNoMatchBlock, Block.Builder currentBlock,
static Block.Builder lowerTypePattern(Block.Reference noMatchRef, Block.Builder currentBlock,
List<Value> bindings,
TypePatternOp tpOp, Value target) {
CodeType targetType = tpOp.targetType();
Expand Down Expand Up @@ -6276,7 +6270,7 @@ static Block.Builder lowerTypePattern(Block.Builder endNoMatchBlock, Block.Build
if (p != null) {
// p != null, we need to perform type check at runtime
Block.Builder nextBlock = currentBlock.block();
currentBlock.add(conditionalBranch(currentBlock.add(p), nextBlock.reference(), endNoMatchBlock.reference()));
currentBlock.add(conditionalBranch(currentBlock.add(p), nextBlock.reference(), noMatchRef));
currentBlock = nextBlock;
}
if (c != null) {
Expand Down
Loading