26
26
27
27
import static jdk .graal .compiler .nodeinfo .NodeCycles .CYCLES_1 ;
28
28
import static jdk .graal .compiler .nodeinfo .NodeSize .SIZE_2 ;
29
+ import static jdk .graal .compiler .nodes .extended .BranchProbabilityNode .VERY_FAST_PATH_PROBABILITY ;
29
30
30
31
import java .util .ArrayList ;
31
32
import java .util .Arrays ;
@@ -1438,13 +1439,15 @@ assert trueSuccessor().hasNoUsages() && falseSuccessor().hasNoUsages() : Asserti
1438
1439
if (merge == falseEnd .merge () && trueSuccessor ().anchored ().isEmpty () && falseSuccessor ().anchored ().isEmpty ()) {
1439
1440
PhiNode singlePhi = null ;
1440
1441
int distinct = 0 ;
1442
+ boolean allConstant = true ;
1441
1443
for (PhiNode phi : merge .phis ()) {
1442
1444
ValueNode trueValue = phi .valueAt (trueEnd );
1443
1445
ValueNode falseValue = phi .valueAt (falseEnd );
1444
1446
if (trueValue != falseValue ) {
1445
1447
distinct ++;
1446
1448
singlePhi = phi ;
1447
1449
}
1450
+ allConstant &= (trueValue .isConstant () && falseValue .isConstant ());
1448
1451
}
1449
1452
if (distinct == 0 ) {
1450
1453
/*
@@ -1457,14 +1460,57 @@ assert trueSuccessor().hasNoUsages() && falseSuccessor().hasNoUsages() : Asserti
1457
1460
// Fortify: Suppress Null Dereference false positive
1458
1461
assert singlePhi != null ;
1459
1462
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
+
1460
1504
ValueNode trueValue = singlePhi .valueAt (trueEnd );
1461
1505
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
+ }
1468
1514
}
1469
1515
/*-
1470
1516
* Remove this pattern:
0 commit comments