8270090: C2: LCM may prioritize CheckCastPP nodes over projections

Reviewed-by: thartmann, kvn
This commit is contained in:
Roberto Castañeda Lozano 2022-04-11 06:37:57 +00:00
parent 755bfcb2d4
commit 8ebea443f3

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 1998, 2021, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1998, 2022, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -488,9 +488,10 @@ void PhaseCFG::implicit_null_check(Block* block, Node *proj, Node *val, int allo
//------------------------------select-----------------------------------------
// Select a nice fellow from the worklist to schedule next. If there is only
// one choice, then use it. Projections take top priority for correctness
// reasons - if I see a projection, then it is next. There are a number of
// Select a nice fellow from the worklist to schedule next. If there is only one
// choice, then use it. CreateEx nodes must start their blocks and are selected
// eagerly. After them, projections take top priority for correctness. Next
// after projections are constants and CheckCastPP nodes. There are a number of
// other special cases, for instructions that consume condition codes, et al.
// These are chosen immediately. Some instructions are required to immediately
// precede the last instruction in the block, and these are taken last. Of the
@ -528,15 +529,34 @@ Node* PhaseCFG::select(
Node *n = worklist[i]; // Get Node on worklist
int iop = n->is_Mach() ? n->as_Mach()->ideal_Opcode() : 0;
if( n->is_Proj() || // Projections always win
n->Opcode()== Op_Con || // So does constant 'Top'
iop == Op_CreateEx || // Create-exception must start block
iop == Op_CheckCastPP
) {
if (iop == Op_CreateEx) {
// CreateEx must start the block (after Phi and Parm nodes which are
// pre-scheduled): select it right away.
worklist.map(i,worklist.pop());
return n;
}
uint n_choice = 2;
if (n->is_Proj()) {
// Projections should follow their parents.
n_choice = 5;
} else if (n->Opcode() == Op_Con || iop == Op_CheckCastPP) {
// Constants and CheckCastPP nodes have higher priority than the rest of
// the nodes tested below.
n_choice = 4;
}
if (n_choice >= 4 && choice < n_choice) {
// n is a constant, a projection, or a CheckCastPP node: record as current
// winner, but keep looking for higher-priority nodes in the worklist.
choice = n_choice;
// Latency and score are only used to break ties among low-priority nodes.
latency = 0;
score = 0;
idx = i;
continue;
}
// Final call in a block must be adjacent to 'catch'
Node *e = block->end();
if( e->is_Catch() && e->in(0)->in(0) == n )
@ -555,8 +575,6 @@ Node* PhaseCFG::select(
}
}
uint n_choice = 2;
// See if this instruction is consumed by a branch. If so, then (as the
// branch is the last instruction in the basic block) force it to the
// end of the basic block
@ -1060,10 +1078,6 @@ bool PhaseCFG::schedule_local(Block* block, GrowableArray<int>& ready_cnt, Vecto
// of the phi to be scheduled first. The select() method breaks
// ties in scheduling by worklist order.
delay.push(m);
} else if (m->is_Mach() && m->as_Mach()->ideal_Opcode() == Op_CreateEx) {
// Force the CreateEx to the top of the list so it's processed
// first and ends up at the start of the block.
worklist.insert(0, m);
} else {
worklist.push(m); // Then on to worklist!
}