Skip to content

Commit 8037ccd

Browse files
authored
Merge pull request eclipse-omr#7297 from a7ehuo/fix-VirtualGuardHeadMerger-1
Do not continue to merge back cold path if guard2 block has been removed
2 parents e9f1832 + 3f7c770 commit 8037ccd

File tree

1 file changed

+32
-5
lines changed

1 file changed

+32
-5
lines changed

compiler/optimizer/VirtualGuardHeadMerger.cpp

Lines changed: 32 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -284,20 +284,23 @@ static void moveBlockAfterDest(TR::CFG *cfg, TR::Block *toMove, TR::Block *dest)
284284
}
285285

286286
// This opt tries to reduce merge backs from cold code that are the result of inliner
287-
// gnerated nopable virtual guards
287+
// generated nopable virtual guards
288288
// It looks for one basic pattern
289289
//
290290
// guard1 -> cold1
291291
// BBEND
292292
// BBSTART
293293
// guard2 -> cold2
294-
// if guard1 is the guard for a method which calls the method guard2 protects or cold1 is
295-
// a predecessor of cold2 (a situation commonly greated by virtual guard tail splitter) we
296-
// can transform the guards as follows when guard1 and guard2 a
294+
//
295+
// If guard1 is the guard for a method which calls the method guard2 protects or cold1 is
296+
// a predecessor of cold2 (a situation commonly created by virtual guard tail splitter) we
297+
// can transform the guards as follows:
298+
//
297299
// guard1 -> cold1
298300
// BBEND
299301
// BBSTART
300302
// guard2 -> cold1
303+
//
301304
// This is safe because there are no trees between the guards and calling the caller will
302305
// result in the call to the callee if we need to patch guard2. cold2 and its mergebacks
303306
// can then be eliminated
@@ -383,6 +386,14 @@ int32_t TR_VirtualGuardHeadMerger::perform() {
383386
// scan for candidate guards to merge with guard1 identified above
384387
for (TR::Block *nextBlock = block->getNextBlock(); nextBlock; nextBlock = nextBlock->getNextBlock())
385388
{
389+
if (block->nodeIsRemoved() || nextBlock->nodeIsRemoved())
390+
{
391+
if (trace())
392+
traceMsg(comp(), "block block_%d %p (%d) or nextBlock block_%d %p (%d) has been removed\n",
393+
block->getNumber(), block, block->nodeIsRemoved(), nextBlock->getNumber(), nextBlock, nextBlock->nodeIsRemoved());
394+
break;
395+
}
396+
386397
if (!(nextBlock->getPredecessors().size() == 1) ||
387398
!nextBlock->hasPredecessor(block))
388399
{
@@ -467,6 +478,22 @@ int32_t TR_VirtualGuardHeadMerger::perform() {
467478
if (guard2->getBranchDestination() != guard1->getBranchDestination())
468479
guard2Block->changeBranchDestination(guard1->getBranchDestination(), cfg);
469480

481+
// changeBranchDestination tries to remove unreachable blocks after the removal of the old edge
482+
// from guard2 to cold2. Rarely, a previous transformation in this pass could have made
483+
// guard2Block unreachable without removing it, in which case it might have been removed just now.
484+
// Normally, if all relevant blocks are removed, later moveBlockAfterDest will not cause any issue
485+
// since it will be just moving around all unreachable blocks. However, in an even more rare case,
486+
// if some of the blocks are removed and some of them are not (eg, guard2Block and the previous block
487+
// of guard2Block are removed but the next block of guard2Block is still valid), moveBlockAfterDest
488+
// could end up joining an invalid/removed block with a valid block. Therefore, if guard2Block
489+
// is no longer valid, it should not proceed.
490+
if (guard2Block->nodeIsRemoved())
491+
{
492+
if (trace())
493+
traceMsg(comp(), "guard2Block block_%d %p has been removed after changeBranchDestination\n", guard2Block->getNumber(), guard2Block);
494+
break;
495+
}
496+
470497
if (guard2Tree != guard2Block->getFirstRealTreeTop())
471498
{
472499
cfg->setStructure(NULL);
@@ -477,7 +504,7 @@ int32_t TR_VirtualGuardHeadMerger::perform() {
477504
// 2, it might contain live monitor, moving it up above a guard can affect the monitor's live range
478505
if (!isStopTheWorldGuard(guard2))
479506
{
480-
// the block created above guard2 contains only privarg treetops or monitor stores if
507+
// the block created above guard2 contains only privarg treetops or monitor stores if
481508
// guard2 is a runtime-patchable guard and is safe to merge. We need to move the priv
482509
// args up to the runtime insert point and leave the monitor stores in place
483510
// It's safe to do so because there is no data dependency between the monitor store and

0 commit comments

Comments
 (0)