Skip to content
Permalink
Browse files

8238765: PhaseCFG::schedule_pinned_nodes cannot handle precedence edg…

…es from unmatched CFG nodes correctly

Fix PhaseCFG::schedule_pinned_nodes to correctly handle precedence edges from unmatched CFG nodes.

Reviewed-by: roland, neliasso, kvn
  • Loading branch information
Christian Hagedorn
Christian Hagedorn committed Feb 17, 2020
1 parent cf4291d commit b369aefc7919e5982b7473795026a96d8f03827e
Showing with 73 additions and 15 deletions.
  1. +4 −1 src/hotspot/share/opto/block.hpp
  2. +69 −14 src/hotspot/share/opto/gcm.cpp
@@ -500,7 +500,10 @@ class PhaseCFG : public Phase {

CFGLoop* create_loop_tree();
bool is_dominator(Node* dom_node, Node* node);

bool is_CFG(Node* n);
bool is_control_proj_or_safepoint(Node* n);
Block* find_block_for_node(Node* n);
bool is_dominating_control(Node* dom_ctrl, Node* n);
#ifndef PRODUCT
bool _trace_opto_pipelining; // tracing flag
#endif
@@ -103,11 +103,14 @@ void PhaseCFG::replace_block_proj_ctrl( Node *n ) {
}

bool PhaseCFG::is_dominator(Node* dom_node, Node* node) {
assert(is_CFG(node) && is_CFG(dom_node), "node and dom_node must be CFG nodes");
if (dom_node == node) {
return true;
}
Block* d = get_block_for_node(dom_node);
Block* n = get_block_for_node(node);
Block* d = find_block_for_node(dom_node);
Block* n = find_block_for_node(node);
assert(n != NULL && d != NULL, "blocks must exist");

if (d == n) {
if (dom_node->is_block_start()) {
return true;
@@ -121,21 +124,74 @@ bool PhaseCFG::is_dominator(Node* dom_node, Node* node) {
if (node->is_block_proj()) {
return true;
}

assert(is_control_proj_or_safepoint(node), "node must be control projection or safepoint");
assert(is_control_proj_or_safepoint(dom_node), "dom_node must be control projection or safepoint");

// Neither 'node' nor 'dom_node' is a block start or block projection.
// Check if 'dom_node' is above 'node' in the control graph.
if (is_dominating_control(dom_node, node)) {
return true;
}

#ifdef ASSERT
node->dump();
dom_node->dump();
// If 'dom_node' does not dominate 'node' then 'node' has to dominate 'dom_node'
if (!is_dominating_control(node, dom_node)) {
node->dump();
dom_node->dump();
assert(false, "neither dom_node nor node dominates the other");
}
#endif
fatal("unhandled");

return false;
}
return d->dom_lca(n) == d;
}

bool PhaseCFG::is_CFG(Node* n) {
return n->is_block_proj() || n->is_block_start() || is_control_proj_or_safepoint(n);
}

bool PhaseCFG::is_control_proj_or_safepoint(Node* n) {
bool result = (n->is_Mach() && n->as_Mach()->ideal_Opcode() == Op_SafePoint) || (n->is_Proj() && n->as_Proj()->bottom_type() == Type::CONTROL);
assert(!result || (n->is_Mach() && n->as_Mach()->ideal_Opcode() == Op_SafePoint)
|| (n->is_Proj() && n->as_Proj()->_con == 0), "If control projection, it must be projection 0");
return result;
}

Block* PhaseCFG::find_block_for_node(Node* n) {
if (n->is_block_start() || n->is_block_proj()) {
return get_block_for_node(n);
} else {
// Walk the control graph up if 'n' is not a block start nor a block projection. In this case 'n' must be
// an unmatched control projection or a not yet matched safepoint precedence edge in the middle of a block.
assert(is_control_proj_or_safepoint(n), "must be control projection or safepoint");
Node* ctrl = n->in(0);
while (!ctrl->is_block_start()) {
ctrl = ctrl->in(0);
}
return get_block_for_node(ctrl);
}
}

// Walk up the control graph from 'n' and check if 'dom_ctrl' is found.
bool PhaseCFG::is_dominating_control(Node* dom_ctrl, Node* n) {
Node* ctrl = n->in(0);
while (!ctrl->is_block_start()) {
if (ctrl == dom_ctrl) {
return true;
}
ctrl = ctrl->in(0);
}
return false;
}


//------------------------------schedule_pinned_nodes--------------------------
// Set the basic block for Nodes pinned into blocks
void PhaseCFG::schedule_pinned_nodes(VectorSet &visited) {
// Allocate node stack of size C->live_nodes()+8 to avoid frequent realloc
GrowableArray <Node *> spstack(C->live_nodes() + 8);
GrowableArray <Node*> spstack(C->live_nodes() + 8);
spstack.push(_root);
while (spstack.is_nonempty()) {
Node* node = spstack.pop();
@@ -160,20 +216,19 @@ void PhaseCFG::schedule_pinned_nodes(VectorSet &visited) {
for (uint i = node->len()-1; i >= node->req(); i--) {
Node* m = node->in(i);
if (m == NULL) continue;
// Skip the precedence edge if the test that guarded a CastPP:
// - was optimized out during escape analysis
// (OptimizePtrCompare): the CastPP's control isn't an end of
// block.
// - is moved in the branch of a dominating If: the control of
// the CastPP is then a Region.
if (m->is_block_proj() || m->is_block_start()) {

// Only process precedence edges that are CFG nodes. Safepoints and control projections can be in the middle of a block
if (is_CFG(m)) {
node->rm_prec(i);
if (n == NULL) {
n = m;
} else {
assert(is_dominator(n, m) || is_dominator(m, n), "one must dominate the other");
n = is_dominator(n, m) ? m : n;
}
} else {
assert(node->is_Mach(), "sanity");
assert(node->as_Mach()->ideal_Opcode() == Op_StoreCM, "must be StoreCM node");
}
}
if (n != NULL) {
@@ -185,7 +240,7 @@ void PhaseCFG::schedule_pinned_nodes(VectorSet &visited) {
}

// process all inputs that are non NULL
for (int i = node->req() - 1; i >= 0; --i) {
for (int i = node->req()-1; i >= 0; --i) {
if (node->in(i) != NULL) {
spstack.push(node->in(i));
}

0 comments on commit b369aef

Please sign in to comment.