2626
2727import static jdk .graal .compiler .nodeinfo .NodeCycles .CYCLES_1 ;
2828import static jdk .graal .compiler .nodeinfo .NodeSize .SIZE_2 ;
29+ import static jdk .graal .compiler .nodes .extended .BranchProbabilityNode .VERY_FAST_PATH_PROBABILITY ;
2930
3031import java .util .ArrayList ;
3132import java .util .Arrays ;
@@ -1438,13 +1439,15 @@ assert trueSuccessor().hasNoUsages() && falseSuccessor().hasNoUsages() : Asserti
14381439 if (merge == falseEnd .merge () && trueSuccessor ().anchored ().isEmpty () && falseSuccessor ().anchored ().isEmpty ()) {
14391440 PhiNode singlePhi = null ;
14401441 int distinct = 0 ;
1442+ boolean allConstant = true ;
14411443 for (PhiNode phi : merge .phis ()) {
14421444 ValueNode trueValue = phi .valueAt (trueEnd );
14431445 ValueNode falseValue = phi .valueAt (falseEnd );
14441446 if (trueValue != falseValue ) {
14451447 distinct ++;
14461448 singlePhi = phi ;
14471449 }
1450+ allConstant &= (trueValue .isConstant () && falseValue .isConstant ());
14481451 }
14491452 if (distinct == 0 ) {
14501453 /*
@@ -1457,14 +1460,57 @@ assert trueSuccessor().hasNoUsages() && falseSuccessor().hasNoUsages() : Asserti
14571460 // Fortify: Suppress Null Dereference false positive
14581461 assert singlePhi != null ;
14591462
1463+ boolean shouldTryToCanonicalizeConditional = true ;
1464+ if (!allConstant &&
1465+ predecessor () instanceof AbstractBeginNode prevBegin &&
1466+ predecessor ().predecessor () instanceof IfNode precedingIf &&
1467+ precedingIf .probability (prevBegin ) < VERY_FAST_PATH_PROBABILITY ) {
1468+ AbstractBeginNode otherSuccessor = precedingIf .successor (true ) == prevBegin ? precedingIf .successor (false ) : precedingIf .successor (true );
1469+ if (otherSuccessor .next () instanceof AbstractEndNode otherEnd && otherEnd .merge () == merge ) {
1470+ /**
1471+ * We have a shape like this (omitting begin/end pairs):
1472+ *
1473+ * <pre>
1474+ * If // precedingIf
1475+ * | \
1476+ * | If // this
1477+ * | | \
1478+ * | | |
1479+ * Merge
1480+ * </pre>
1481+ *
1482+ * For example, fully unrolling a loop that has side exits can give this
1483+ * shape, where all the unrolled iterations' side exits meet up at one
1484+ * merge.
1485+ * <p/>
1486+ *
1487+ * If we replace this node by a floating conditional, the preceding If
1488+ * will then be in a shape where its ends meet up at the same merge, so
1489+ * we will get here and turn it into a conditional too. If there are
1490+ * more preceding ifs in the cascade, we would turn them into
1491+ * conditionals too, and so on. Overall we would move all the code
1492+ * controlled by a sequence of Ifs into one block where everything is
1493+ * computed unconditionally and we then pick out the result we want.
1494+ * This is unlikely to be worth it in general.
1495+ * <p/>
1496+ *
1497+ * We only allow this transformation if all phi inputs are constants,
1498+ * this allows us to cover some useful cases (see TrichotomyTest).
1499+ */
1500+ shouldTryToCanonicalizeConditional = false ;
1501+ }
1502+ }
1503+
14601504 ValueNode trueValue = singlePhi .valueAt (trueEnd );
14611505 ValueNode falseValue = singlePhi .valueAt (falseEnd );
1462- ValueNode conditional = canonicalizeConditionalCascade (tool , trueValue , falseValue );
1463- if (conditional != null ) {
1464- conditional = proxyReplacement (conditional );
1465- singlePhi .setValueAt (trueEnd , conditional );
1466- removeThroughFalseBranch (tool , merge );
1467- return true ;
1506+ if (shouldTryToCanonicalizeConditional ) {
1507+ ValueNode conditional = canonicalizeConditionalCascade (tool , trueValue , falseValue );
1508+ if (conditional != null ) {
1509+ conditional = proxyReplacement (conditional );
1510+ singlePhi .setValueAt (trueEnd , conditional );
1511+ removeThroughFalseBranch (tool , merge );
1512+ return true ;
1513+ }
14681514 }
14691515 /*-
14701516 * Remove this pattern:
0 commit comments