@@ -447,7 +447,7 @@ void RegionNode::verify_can_be_irreducible_entry() const {
447
447
}
448
448
#endif // ASSERT
449
449
450
- bool RegionNode::try_clean_mem_phi (PhaseGVN *phase ) {
450
+ void RegionNode::try_clean_mem_phis (PhaseIterGVN* igvn ) {
451
451
// Incremental inlining + PhaseStringOpts sometimes produce:
452
452
//
453
453
// cmpP with 1 top input
@@ -464,32 +464,60 @@ bool RegionNode::try_clean_mem_phi(PhaseGVN *phase) {
464
464
// replaced by If's control input but because there's still a Phi,
465
465
// the Region stays in the graph. The top input from the cmpP is
466
466
// propagated forward and a subgraph that is useful goes away. The
467
- // code below replaces the Phi with the MergeMem so that the Region
468
- // is simplified.
469
-
470
- PhiNode* phi = has_unique_phi ();
471
- if (phi && phi->type () == Type::MEMORY && req () == 3 && phi->is_diamond_phi (true )) {
472
- MergeMemNode* m = nullptr ;
473
- assert (phi->req () == 3 , " same as region" );
474
- for (uint i = 1 ; i < 3 ; ++i) {
475
- Node *mem = phi->in (i);
476
- if (mem && mem->is_MergeMem () && in (i)->outcnt () == 1 ) {
477
- // Nothing is control-dependent on path #i except the region itself.
478
- m = mem->as_MergeMem ();
479
- uint j = 3 - i;
480
- Node* other = phi->in (j);
481
- if (other && other == m->base_memory ()) {
482
- // m is a successor memory to other, and is not pinned inside the diamond, so push it out.
483
- // This will allow the diamond to collapse completely.
484
- phase->is_IterGVN ()->replace_node (phi, m);
485
- return true ;
486
- }
487
- }
467
+ // code in PhiNode::try_clean_memory_phi() replaces the Phi with the
468
+ // MergeMem in order to remove the Region if its last phi dies.
469
+
470
+ if (!is_diamond ()) {
471
+ return ;
472
+ }
473
+
474
+ for (DUIterator_Fast imax, i = fast_outs (imax); i < imax; i++) {
475
+ Node* phi = fast_out (i);
476
+ if (phi->is_Phi () && phi->as_Phi ()->try_clean_memory_phi (igvn)) {
477
+ --i;
478
+ --imax;
488
479
}
489
480
}
490
- return false ;
491
481
}
492
482
483
+ // Does this region merge a simple diamond formed by a proper IfNode?
484
+ //
485
+ // Cmp
486
+ // /
487
+ // ctrl Bool
488
+ // \ /
489
+ // IfNode
490
+ // / \
491
+ // IfFalse IfTrue
492
+ // \ /
493
+ // Region
494
+ bool RegionNode::is_diamond () const {
495
+ if (req () != 3 ) {
496
+ return false ;
497
+ }
498
+
499
+ Node* left_path = in (1 );
500
+ Node* right_path = in (2 );
501
+ if (left_path == nullptr || right_path == nullptr ) {
502
+ return false ;
503
+ }
504
+ Node* diamond_if = left_path->in (0 );
505
+ if (diamond_if == nullptr || !diamond_if->is_If () || diamond_if != right_path->in (0 )) {
506
+ // Not an IfNode merging a diamond or TOP.
507
+ return false ;
508
+ }
509
+
510
+ // Check for a proper bool/cmp
511
+ const Node* bol = diamond_if->in (1 );
512
+ if (!bol->is_Bool ()) {
513
+ return false ;
514
+ }
515
+ const Node* cmp = bol->in (1 );
516
+ if (!cmp->is_Cmp ()) {
517
+ return false ;
518
+ }
519
+ return true ;
520
+ }
493
521
// ------------------------------Ideal------------------------------------------
494
522
// Return a node which is more "ideal" than the current node. Must preserve
495
523
// the CFG, but we can still strip out dead paths.
@@ -501,10 +529,8 @@ Node *RegionNode::Ideal(PhaseGVN *phase, bool can_reshape) {
501
529
// arm of the same IF. If found, then the control-flow split is useless.
502
530
bool has_phis = false ;
503
531
if (can_reshape) { // Need DU info to check for Phi users
532
+ try_clean_mem_phis (phase->is_IterGVN ());
504
533
has_phis = (has_phi () != nullptr ); // Cache result
505
- if (has_phis && try_clean_mem_phi (phase)) {
506
- has_phis = false ;
507
- }
508
534
509
535
if (!has_phis) { // No Phi users? Nothing merging?
510
536
for (uint i = 1 ; i < req ()-1 ; i++) {
@@ -1327,42 +1353,60 @@ const Type* PhiNode::Value(PhaseGVN* phase) const {
1327
1353
return ft;
1328
1354
}
1329
1355
1330
-
1331
- // ------------------------------is_diamond_phi---------------------------------
1332
1356
// Does this Phi represent a simple well-shaped diamond merge? Return the
1333
1357
// index of the true path or 0 otherwise.
1334
- // If check_control_only is true, do not inspect the If node at the
1335
- // top, and return -1 (not an edge number) on success.
1336
- int PhiNode::is_diamond_phi (bool check_control_only) const {
1337
- // Check for a 2-path merge
1338
- Node *region = in (0 );
1339
- if ( !region ) return 0 ;
1340
- if ( region->req () != 3 ) return 0 ;
1341
- if ( req () != 3 ) return 0 ;
1342
- // Check that both paths come from the same If
1343
- Node *ifp1 = region->in (1 );
1344
- Node *ifp2 = region->in (2 );
1345
- if ( !ifp1 || !ifp2 ) return 0 ;
1346
- Node *iff = ifp1->in (0 );
1347
- if ( !iff || !iff->is_If () ) return 0 ;
1348
- if ( iff != ifp2->in (0 ) ) return 0 ;
1349
- if (check_control_only) return -1 ;
1350
- // Check for a proper bool/cmp
1351
- const Node *b = iff->in (1 );
1352
- if ( !b->is_Bool () ) return 0 ;
1353
- const Node *cmp = b->in (1 );
1354
- if ( !cmp->is_Cmp () ) return 0 ;
1355
-
1356
- // Check for branching opposite expected
1357
- if ( ifp2->Opcode () == Op_IfTrue ) {
1358
- assert ( ifp1->Opcode () == Op_IfFalse, " " );
1359
- return 2 ;
1360
- } else {
1361
- assert ( ifp1->Opcode () == Op_IfTrue, " " );
1358
+ int PhiNode::is_diamond_phi () const {
1359
+ Node* region = in (0 );
1360
+ assert (region != nullptr && region->is_Region (), " phi must have region" );
1361
+ if (!region->as_Region ()->is_diamond ()) {
1362
+ return 0 ;
1363
+ }
1364
+
1365
+ if (region->in (1 )->is_IfTrue ()) {
1366
+ assert (region->in (2 )->is_IfFalse (), " bad If" );
1362
1367
return 1 ;
1368
+ } else {
1369
+ // Flipped projections.
1370
+ assert (region->in (2 )->is_IfTrue (), " bad If" );
1371
+ return 2 ;
1363
1372
}
1364
1373
}
1365
1374
1375
+ // Do the following transformation if we find the corresponding graph shape, remove the involved memory phi and return
1376
+ // true. Otherwise, return false if the transformation cannot be applied.
1377
+ //
1378
+ // If If
1379
+ // / \ / \
1380
+ // IfFalse IfTrue /- Some Node IfFalse IfTrue
1381
+ // \ / / / \ / Some Node
1382
+ // Region / /-MergeMem ===> Region |
1383
+ // / \---Phi | MergeMem
1384
+ // [other phis] \ [other phis] |
1385
+ // use use
1386
+ bool PhiNode::try_clean_memory_phi (PhaseIterGVN* igvn) {
1387
+ if (_type != Type::MEMORY) {
1388
+ return false ;
1389
+ }
1390
+ assert (is_diamond_phi () > 0 , " sanity" );
1391
+ assert (req () == 3 , " same as region" );
1392
+ const Node* region = in (0 );
1393
+ for (uint i = 1 ; i < 3 ; i++) {
1394
+ Node* phi_input = in (i);
1395
+ if (phi_input != nullptr && phi_input->is_MergeMem () && region->in (i)->outcnt () == 1 ) {
1396
+ // Nothing is control-dependent on path #i except the region itself.
1397
+ MergeMemNode* merge_mem = phi_input->as_MergeMem ();
1398
+ uint j = 3 - i;
1399
+ Node* other_phi_input = in (j);
1400
+ if (other_phi_input != nullptr && other_phi_input == merge_mem->base_memory ()) {
1401
+ // merge_mem is a successor memory to other_phi_input, and is not pinned inside the diamond, so push it out.
1402
+ // This will allow the diamond to collapse completely if there are no other phis left.
1403
+ igvn->replace_node (this , merge_mem);
1404
+ return true ;
1405
+ }
1406
+ }
1407
+ }
1408
+ return false ;
1409
+ }
1366
1410
// ----------------------------check_cmove_id-----------------------------------
1367
1411
// Check for CMove'ing a constant after comparing against the constant.
1368
1412
// Happens all the time now, since if we compare equality vs a constant in
0 commit comments