Skip to content
Permalink
Browse files
8263577: C2: reachable nodes shouldn't have dead uses at the end of o…
…ptimizations

Reviewed-by: vlivanov, neliasso
  • Loading branch information
rwestrel committed Mar 16, 2021
1 parent c484d89 commit 20297a1bebfe03c45344a713ec561c97888c4750
@@ -1066,7 +1066,7 @@ void ShenandoahBarrierC2Support::fix_ctrl(Node* barrier, Node* region, const Mem
is_dominator_same_ctrl(old_c, barrier, u, phase) ||
ShenandoahBarrierSetC2::is_shenandoah_state_load(u)) {
phase->igvn().rehash_node_delayed(u);
int nb = u->replace_edge(ctrl, region);
int nb = u->replace_edge(ctrl, region, &phase->igvn());
if (u->is_CFG()) {
if (phase->idom(u) == ctrl) {
phase->set_idom(u, region, phase->dom_depth(region));
@@ -1248,7 +1248,7 @@ void ShenandoahBarrierC2Support::pin_and_expand(PhaseIdealLoop* phase) {
stack.push(u, 0);
assert(!cloned.test_set(u->_idx), "only one clone");
Node* u_clone = u->clone();
int nb = u_clone->replace_edge(n, n_clone);
int nb = u_clone->replace_edge(n, n_clone, &phase->igvn());
assert(nb > 0, "should have replaced some uses");
phase->register_new_node(u_clone, projs.catchall_catchproj);
clones.push(u_clone);
@@ -1270,7 +1270,7 @@ void ShenandoahBarrierC2Support::pin_and_expand(PhaseIdealLoop* phase) {
} else {
if (phase->is_dominator(projs.catchall_catchproj, c)) {
phase->igvn().rehash_node_delayed(u);
int nb = u->replace_edge(n, n_clone);
int nb = u->replace_edge(n, n_clone, &phase->igvn());
assert(nb > 0, "should have replaced some uses");
replaced = true;
} else if (!phase->is_dominator(projs.fallthrough_catchproj, c)) {
@@ -1288,7 +1288,8 @@ void ShenandoahBarrierC2Support::pin_and_expand(PhaseIdealLoop* phase) {
Node* nn_clone = clones.at(clones.size()-3);
assert(nn->Opcode() == nn_clone->Opcode(), "mismatch");

int nb = cmp_clone->replace_edge(nn, create_phis_on_call_return(ctrl, c, nn, nn_clone, projs, phase));
int nb = cmp_clone->replace_edge(nn, create_phis_on_call_return(ctrl, c, nn, nn_clone, projs, phase),
&phase->igvn());
assert(nb > 0, "should have replaced some uses");

phase->register_new_node(bol_clone, u->in(0));
@@ -1298,7 +1299,7 @@ void ShenandoahBarrierC2Support::pin_and_expand(PhaseIdealLoop* phase) {

} else {
phase->igvn().rehash_node_delayed(u);
int nb = u->replace_edge(n, create_phis_on_call_return(ctrl, c, n, n_clone, projs, phase));
int nb = u->replace_edge(n, create_phis_on_call_return(ctrl, c, n, n_clone, projs, phase), &phase->igvn());
assert(nb > 0, "should have replaced some uses");
}
replaced = true;
@@ -145,14 +145,8 @@ Node *AddNode::Ideal(PhaseGVN *phase, bool can_reshape) {
// The Add of the flattened expression
Node *x1 = add1->in(1);
Node *x2 = phase->makecon(add1->as_Add()->add_ring(t2, t12));
PhaseIterGVN *igvn = phase->is_IterGVN();
if (igvn) {
set_req_X(2,x2,igvn);
set_req_X(1,x1,igvn);
} else {
set_req(2,x2);
set_req(1,x1);
}
set_req_X(2, x2, phase);
set_req_X(1, x1, phase);
progress = this; // Made progress
add1 = in(1);
add1_op = add1->Opcode();
@@ -169,8 +163,8 @@ Node *AddNode::Ideal(PhaseGVN *phase, bool can_reshape) {
add2 = add1->clone();
add2->set_req(2, in(2));
add2 = phase->transform(add2);
set_req(1, add2);
set_req(2, a12);
set_req_X(1, add2, phase);
set_req_X(2, a12, phase);
progress = this;
add2 = a12;
}
@@ -642,14 +636,8 @@ Node *AddPNode::Ideal(PhaseGVN *phase, bool can_reshape) {
address = phase->transform(new AddPNode(in(Base),addp->in(Address),in(Offset)));
offset = addp->in(Offset);
}
PhaseIterGVN *igvn = phase->is_IterGVN();
if( igvn ) {
set_req_X(Address,address,igvn);
set_req_X(Offset,offset,igvn);
} else {
set_req(Address,address);
set_req(Offset,offset);
}
set_req_X(Address, address, phase);
set_req_X(Offset, offset, phase);
return this;
}
}
@@ -1123,8 +1111,8 @@ Node *MinINode::Ideal(PhaseGVN *phase, bool can_reshape) {
assert( l != l->in(1), "dead loop in MinINode::Ideal" );
r = phase->transform(new MinINode(l->in(2),r));
l = l->in(1);
set_req(1, l);
set_req(2, r);
set_req_X(1, l, phase);
set_req_X(2, r, phase);
return this;
}

@@ -625,6 +625,13 @@ Node *RegionNode::Ideal(PhaseGVN *phase, bool can_reshape) {
for (DUIterator_Last imin, i = last_outs(imin); i >= imin; --i) {
Node* n = last_out(i);
igvn->hash_delete(n); // Remove from worklist before modifying edges
if (n->outcnt() == 0) {
int uses_found = n->replace_edge(this, phase->C->top(), igvn);
if (uses_found > 1) { // (--i) done at the end of the loop.
i -= (uses_found - 1);
}
continue;
}
if( n->is_Phi() ) { // Collapse all Phis
// Eagerly replace phis to avoid regionless phis.
Node* in;
@@ -641,14 +648,8 @@ Node *RegionNode::Ideal(PhaseGVN *phase, bool can_reshape) {
}
else if( n->is_Region() ) { // Update all incoming edges
assert(n != this, "Must be removed from DefUse edges");
uint uses_found = 0;
for( uint k=1; k < n->req(); k++ ) {
if( n->in(k) == this ) {
n->set_req(k, parent_ctrl);
uses_found++;
}
}
if( uses_found > 1 ) { // (--i) done at the end of the loop.
int uses_found = n->replace_edge(this, parent_ctrl, igvn);
if (uses_found > 1) { // (--i) done at the end of the loop.
i -= (uses_found - 1);
}
}
@@ -881,6 +882,9 @@ bool RegionNode::optimize_trichotomy(PhaseIterGVN* igvn) {
// Replace bool input of iff2 with merged test
BoolNode* new_bol = new BoolNode(bol2->in(1), res);
igvn->replace_input_of(iff2, 1, igvn->transform((proj2->_con == 1) ? new_bol : new_bol->negate(igvn)));
if (new_bol->outcnt() == 0) {
igvn->remove_dead_node(new_bol);
}
}
return false;
}
@@ -1916,11 +1920,7 @@ Node *PhiNode::Ideal(PhaseGVN *phase, bool can_reshape) {
igvn->_worklist.push(r);
}
// Nuke it down
if (can_reshape) {
set_req_X(j, top, igvn);
} else {
set_req(j, top);
}
set_req_X(j, top, phase);
progress = this; // Record progress
}
}
@@ -1958,7 +1958,7 @@ Node *PhiNode::Ideal(PhaseGVN *phase, bool can_reshape) {
} else {
// We can't return top if we are in Parse phase - cut inputs only
// let Identity to handle the case.
replace_edge(uin, top);
replace_edge(uin, top, phase);
return NULL;
}
}
@@ -2227,7 +2227,7 @@ Node *PhiNode::Ideal(PhaseGVN *phase, bool can_reshape) {
m->as_MergeMem()->memory_at(alias_idx) : m;
// Update input if it is progress over what we have now
if (new_mem != ii) {
set_req(i, new_mem);
set_req_X(i, new_mem, phase->is_IterGVN());
progress = this;
}
}
@@ -2345,6 +2345,8 @@ void Compile::Optimize() {
}
} // (End scope of igvn; run destructor if necessary for asserts.)

check_no_dead_use();

process_print_inlining();

// A method with only infinite loops has no edges entering loops from root
@@ -2360,6 +2362,25 @@ void Compile::Optimize() {
DEBUG_ONLY(set_phase_optimize_finished();)
}

#ifdef ASSERT
void Compile::check_no_dead_use() const {
ResourceMark rm;
Unique_Node_List wq;
wq.push(root());
for (uint i = 0; i < wq.size(); ++i) {
Node* n = wq.at(i);
for (DUIterator_Fast jmax, j = n->fast_outs(jmax); j < jmax; j++) {
Node* u = n->fast_out(j);
if (u->outcnt() == 0 && !u->is_Con()) {
u->dump();
fatal("no reachable node should have no use");
}
wq.push(u);
}
}
}
#endif

void Compile::inline_vector_reboxing_calls() {
if (C->_vector_reboxing_late_inlines.length() > 0) {
_late_inlines_pos = C->_late_inlines.length();
@@ -1116,6 +1116,7 @@ class Compile : public Phase {
uint compute_truth_table(Unique_Node_List& partition, Unique_Node_List& inputs);
uint eval_macro_logic_op(uint func, uint op1, uint op2, uint op3);
Node* xform_to_MacroLogicV(PhaseIterGVN &igvn, const TypeVect* vt, Unique_Node_List& partitions, Unique_Node_List& inputs);
void check_no_dead_use() const NOT_DEBUG_RETURN;

public:

@@ -500,7 +500,7 @@ Node *ConvL2INode::Ideal(PhaseGVN *phase, bool can_reshape) {
if( andl_op == Op_AndL ) {
// Blow off prior masking to int
if( phase->type(andl->in(2)) == TypeLong::make( 0xFFFFFFFF ) ) {
set_req(1,andl->in(1));
set_req_X(1,andl->in(1), phase);
return this;
}
}
@@ -2769,7 +2769,7 @@ void ConnectionGraph::move_inst_mem(Node* n, GrowableArray<PhiNode *> &orig_phi
Node* m = find_inst_mem(n, general_idx, orig_phis);
assert(orig_uniq == C->unique(), "no new nodes");
igvn->hash_delete(use);
imax -= use->replace_edge(n, m);
imax -= use->replace_edge(n, m, igvn);
igvn->hash_insert(use);
record_for_optimizer(use);
--i;
@@ -1128,14 +1128,14 @@ void IfNode::improve_address_types(Node* l, Node* r, ProjNode* fail, PhaseIterGV
for (uint j = 2; j < stack.size(); j++) {
Node* n = stack.node_at(j);
Node* clone = n->clone();
int rep = clone->replace_edge(init_n, new_n);
int rep = clone->replace_edge(init_n, new_n, igvn);
assert(rep > 0, "can't find expected node?");
clone = igvn->transform(clone);
init_n = n;
new_n = clone;
}
igvn->hash_delete(use);
int rep = use->replace_edge(init_n, new_n);
int rep = use->replace_edge(init_n, new_n, igvn);
assert(rep > 0, "can't find expected node?");
igvn->transform(use);
if (init_n->outcnt() == 0) {
@@ -1364,7 +1364,7 @@ static Node *remove_useless_bool(IfNode *iff, PhaseGVN *phase) {

Node* new_bol = (flip ? phase->transform( bol2->negate(phase) ) : bol2);
assert(new_bol != iff->in(1), "must make progress");
iff->set_req(1, new_bol);
iff->set_req_X(1, new_bol, phase);
// Intervening diamond probably goes dead
phase->C->set_major_progress();
return iff;
@@ -1199,7 +1199,7 @@ Node* PhaseIdealLoop::cast_incr_before_loop(Node* incr, Node* ctrl, Node* loop)
for (DUIterator_Fast imax, i = incr->fast_outs(imax); i < imax; i++) {
Node* n = incr->fast_out(i);
if (n->is_Phi() && n->in(0) == loop) {
int nrep = n->replace_edge(incr, castii);
int nrep = n->replace_edge(incr, castii, &_igvn);
return castii;
}
}
@@ -543,7 +543,7 @@ void PhaseIdealLoop::long_loop_replace_long_iv(Node* iv_to_replace, Node* inner_
}
#endif
_igvn.rehash_node_delayed(u);
int nb = u->replace_edge(iv_to_replace, iv_replacement);
int nb = u->replace_edge(iv_to_replace, iv_replacement, &_igvn);
i -= nb;
}
}
@@ -1170,7 +1170,7 @@ bool PhaseIdealLoop::convert_to_long_loop(Node* cmp, Node* phi, IdealLoopTree* l
set_subtree_ctrl(m, false);
}
_igvn.rehash_node_delayed(u);
int nb = u->replace_edge(n, m);
int nb = u->replace_edge(n, m, &_igvn);
--i, imax -= nb;
}
}
@@ -924,7 +924,7 @@ void PhaseIdealLoop::try_move_store_after_loop(Node* n) {
Node* hook = new Node(1);
hook->init_req(0, n_ctrl); // Add an input to prevent hook from being dead
_igvn.rehash_node_delayed(phi);
int count = phi->replace_edge(n, hook);
int count = phi->replace_edge(n, hook, &_igvn);
assert(count > 0, "inconsistent phi");

// Compute latest point this store can go
@@ -892,7 +892,7 @@ bool PhaseMacroExpand::scalar_replacement(AllocateNode *alloc, GrowableArray <Sa
// to the allocated object with "sobj"
int start = jvms->debug_start();
int end = jvms->debug_end();
sfpt->replace_edges_in_range(res, sobj, start, end);
sfpt->replace_edges_in_range(res, sobj, start, end, &_igvn);
_igvn._worklist.push(sfpt);
safepoints_done.append_if_missing(sfpt); // keep it for rollback
}
@@ -967,12 +967,12 @@ void PhaseMacroExpand::process_users_of_allocation(CallNode *alloc) {

// Set control to top. IGVN will remove the remaining projections
ac->set_req(0, top());
ac->replace_edge(res, top());
ac->replace_edge(res, top(), &_igvn);

// Disconnect src right away: it can help find new
// opportunities for allocation elimination
Node* src = ac->in(ArrayCopyNode::Src);
ac->replace_edge(src, top());
ac->replace_edge(src, top(), &_igvn);
// src can be top at this point if src and dest of the
// arraycopy were the same
if (src->outcnt() == 0 && !src->is_top()) {
@@ -336,7 +336,7 @@ Node *MemNode::Ideal_common(PhaseGVN *phase, bool can_reshape) {
Node* u = ctl->fast_out(i);
if (u != ctl) {
igvn->rehash_node_delayed(u);
int nb = u->replace_edge(ctl, phase->C->top());
int nb = u->replace_edge(ctl, phase->C->top(), igvn);
--i, imax -= nb;
}
}
@@ -2650,13 +2650,9 @@ Node *StoreNode::Ideal(PhaseGVN *phase, bool can_reshape) {
if (phase->is_IterGVN()) {
phase->is_IterGVN()->rehash_node_delayed(use);
}
if (can_reshape) {
use->set_req_X(MemNode::Memory, st->in(MemNode::Memory), phase->is_IterGVN());
} else {
// It's OK to do this in the parser, since DU info is always accurate,
// and the parser always refers to nodes via SafePointNode maps.
use->set_req(MemNode::Memory, st->in(MemNode::Memory));
}
// It's OK to do this in the parser, since DU info is always accurate,
// and the parser always refers to nodes via SafePointNode maps.
use->set_req_X(MemNode::Memory, st->in(MemNode::Memory), phase);
return this;
}
st = st->in(MemNode::Memory);
@@ -2801,7 +2797,7 @@ Node *StoreNode::Ideal_masked_input(PhaseGVN *phase, uint mask) {
if( val->Opcode() == Op_AndI ) {
const TypeInt *t = phase->type( val->in(2) )->isa_int();
if( t && t->is_con() && (t->get_con() & mask) == mask ) {
set_req(MemNode::ValueIn, val->in(1));
set_req_X(MemNode::ValueIn, val->in(1), phase);
return this;
}
}
@@ -2823,7 +2819,7 @@ Node *StoreNode::Ideal_sign_extended_input(PhaseGVN *phase, int num_bits) {
if( shl->Opcode() == Op_LShiftI ) {
const TypeInt *t2 = phase->type( shl->in(2) )->isa_int();
if( t2 && t2->is_con() && (t2->get_con() == t->get_con()) ) {
set_req(MemNode::ValueIn, shl->in(1));
set_req_X(MemNode::ValueIn, shl->in(1), phase);
return this;
}
}
@@ -2934,7 +2930,7 @@ Node *StoreCMNode::Ideal(PhaseGVN *phase, bool can_reshape){
Node* my_store = in(MemNode::OopStore);
if (my_store->is_MergeMem()) {
Node* mem = my_store->as_MergeMem()->memory_at(oop_alias_idx());
set_req(MemNode::OopStore, mem);
set_req_X(MemNode::OopStore, mem, phase);
return this;
}

@@ -4734,13 +4730,13 @@ Node *MergeMemNode::Ideal(PhaseGVN *phase, bool can_reshape) {
// Warning: Do not combine this "if" with the previous "if"
// A memory slice might have be be rewritten even if it is semantically
// unchanged, if the base_memory value has changed.
set_req(i, new_in);
set_req_X(i, new_in, phase);
progress = this; // Report progress
}
}

if (new_base != old_base) {
set_req(Compile::AliasIdxBot, new_base);
set_req_X(Compile::AliasIdxBot, new_base, phase);
// Don't use set_base_memory(new_base), because we need to update du.
assert(base_memory() == new_base, "");
progress = this;

1 comment on commit 20297a1

@openjdk-notifier

This comment has been minimized.

Copy link

@openjdk-notifier openjdk-notifier bot commented on 20297a1 Mar 16, 2021

Please sign in to comment.