8263577: C2: reachable nodes shouldn't have dead uses at the end of optimizations
Reviewed-by: vlivanov, neliasso
This commit is contained in:
parent
c484d89042
commit
20297a1beb
@ -1066,7 +1066,7 @@ void ShenandoahBarrierC2Support::fix_ctrl(Node* barrier, Node* region, const Mem
|
|||||||
is_dominator_same_ctrl(old_c, barrier, u, phase) ||
|
is_dominator_same_ctrl(old_c, barrier, u, phase) ||
|
||||||
ShenandoahBarrierSetC2::is_shenandoah_state_load(u)) {
|
ShenandoahBarrierSetC2::is_shenandoah_state_load(u)) {
|
||||||
phase->igvn().rehash_node_delayed(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 (u->is_CFG()) {
|
||||||
if (phase->idom(u) == ctrl) {
|
if (phase->idom(u) == ctrl) {
|
||||||
phase->set_idom(u, region, phase->dom_depth(region));
|
phase->set_idom(u, region, phase->dom_depth(region));
|
||||||
@ -1248,7 +1248,7 @@ void ShenandoahBarrierC2Support::pin_and_expand(PhaseIdealLoop* phase) {
|
|||||||
stack.push(u, 0);
|
stack.push(u, 0);
|
||||||
assert(!cloned.test_set(u->_idx), "only one clone");
|
assert(!cloned.test_set(u->_idx), "only one clone");
|
||||||
Node* u_clone = u->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");
|
assert(nb > 0, "should have replaced some uses");
|
||||||
phase->register_new_node(u_clone, projs.catchall_catchproj);
|
phase->register_new_node(u_clone, projs.catchall_catchproj);
|
||||||
clones.push(u_clone);
|
clones.push(u_clone);
|
||||||
@ -1270,7 +1270,7 @@ void ShenandoahBarrierC2Support::pin_and_expand(PhaseIdealLoop* phase) {
|
|||||||
} else {
|
} else {
|
||||||
if (phase->is_dominator(projs.catchall_catchproj, c)) {
|
if (phase->is_dominator(projs.catchall_catchproj, c)) {
|
||||||
phase->igvn().rehash_node_delayed(u);
|
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");
|
assert(nb > 0, "should have replaced some uses");
|
||||||
replaced = true;
|
replaced = true;
|
||||||
} else if (!phase->is_dominator(projs.fallthrough_catchproj, c)) {
|
} 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);
|
Node* nn_clone = clones.at(clones.size()-3);
|
||||||
assert(nn->Opcode() == nn_clone->Opcode(), "mismatch");
|
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");
|
assert(nb > 0, "should have replaced some uses");
|
||||||
|
|
||||||
phase->register_new_node(bol_clone, u->in(0));
|
phase->register_new_node(bol_clone, u->in(0));
|
||||||
@ -1298,7 +1299,7 @@ void ShenandoahBarrierC2Support::pin_and_expand(PhaseIdealLoop* phase) {
|
|||||||
|
|
||||||
} else {
|
} else {
|
||||||
phase->igvn().rehash_node_delayed(u);
|
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");
|
assert(nb > 0, "should have replaced some uses");
|
||||||
}
|
}
|
||||||
replaced = true;
|
replaced = true;
|
||||||
|
@ -145,14 +145,8 @@ Node *AddNode::Ideal(PhaseGVN *phase, bool can_reshape) {
|
|||||||
// The Add of the flattened expression
|
// The Add of the flattened expression
|
||||||
Node *x1 = add1->in(1);
|
Node *x1 = add1->in(1);
|
||||||
Node *x2 = phase->makecon(add1->as_Add()->add_ring(t2, t12));
|
Node *x2 = phase->makecon(add1->as_Add()->add_ring(t2, t12));
|
||||||
PhaseIterGVN *igvn = phase->is_IterGVN();
|
set_req_X(2, x2, phase);
|
||||||
if (igvn) {
|
set_req_X(1, x1, phase);
|
||||||
set_req_X(2,x2,igvn);
|
|
||||||
set_req_X(1,x1,igvn);
|
|
||||||
} else {
|
|
||||||
set_req(2,x2);
|
|
||||||
set_req(1,x1);
|
|
||||||
}
|
|
||||||
progress = this; // Made progress
|
progress = this; // Made progress
|
||||||
add1 = in(1);
|
add1 = in(1);
|
||||||
add1_op = add1->Opcode();
|
add1_op = add1->Opcode();
|
||||||
@ -169,8 +163,8 @@ Node *AddNode::Ideal(PhaseGVN *phase, bool can_reshape) {
|
|||||||
add2 = add1->clone();
|
add2 = add1->clone();
|
||||||
add2->set_req(2, in(2));
|
add2->set_req(2, in(2));
|
||||||
add2 = phase->transform(add2);
|
add2 = phase->transform(add2);
|
||||||
set_req(1, add2);
|
set_req_X(1, add2, phase);
|
||||||
set_req(2, a12);
|
set_req_X(2, a12, phase);
|
||||||
progress = this;
|
progress = this;
|
||||||
add2 = a12;
|
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)));
|
address = phase->transform(new AddPNode(in(Base),addp->in(Address),in(Offset)));
|
||||||
offset = addp->in(Offset);
|
offset = addp->in(Offset);
|
||||||
}
|
}
|
||||||
PhaseIterGVN *igvn = phase->is_IterGVN();
|
set_req_X(Address, address, phase);
|
||||||
if( igvn ) {
|
set_req_X(Offset, offset, phase);
|
||||||
set_req_X(Address,address,igvn);
|
|
||||||
set_req_X(Offset,offset,igvn);
|
|
||||||
} else {
|
|
||||||
set_req(Address,address);
|
|
||||||
set_req(Offset,offset);
|
|
||||||
}
|
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1123,8 +1111,8 @@ Node *MinINode::Ideal(PhaseGVN *phase, bool can_reshape) {
|
|||||||
assert( l != l->in(1), "dead loop in MinINode::Ideal" );
|
assert( l != l->in(1), "dead loop in MinINode::Ideal" );
|
||||||
r = phase->transform(new MinINode(l->in(2),r));
|
r = phase->transform(new MinINode(l->in(2),r));
|
||||||
l = l->in(1);
|
l = l->in(1);
|
||||||
set_req(1, l);
|
set_req_X(1, l, phase);
|
||||||
set_req(2, r);
|
set_req_X(2, r, phase);
|
||||||
return this;
|
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) {
|
for (DUIterator_Last imin, i = last_outs(imin); i >= imin; --i) {
|
||||||
Node* n = last_out(i);
|
Node* n = last_out(i);
|
||||||
igvn->hash_delete(n); // Remove from worklist before modifying edges
|
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
|
if( n->is_Phi() ) { // Collapse all Phis
|
||||||
// Eagerly replace phis to avoid regionless phis.
|
// Eagerly replace phis to avoid regionless phis.
|
||||||
Node* in;
|
Node* in;
|
||||||
@ -641,13 +648,7 @@ Node *RegionNode::Ideal(PhaseGVN *phase, bool can_reshape) {
|
|||||||
}
|
}
|
||||||
else if( n->is_Region() ) { // Update all incoming edges
|
else if( n->is_Region() ) { // Update all incoming edges
|
||||||
assert(n != this, "Must be removed from DefUse edges");
|
assert(n != this, "Must be removed from DefUse edges");
|
||||||
uint uses_found = 0;
|
int uses_found = n->replace_edge(this, parent_ctrl, igvn);
|
||||||
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.
|
if (uses_found > 1) { // (--i) done at the end of the loop.
|
||||||
i -= (uses_found - 1);
|
i -= (uses_found - 1);
|
||||||
}
|
}
|
||||||
@ -881,6 +882,9 @@ bool RegionNode::optimize_trichotomy(PhaseIterGVN* igvn) {
|
|||||||
// Replace bool input of iff2 with merged test
|
// Replace bool input of iff2 with merged test
|
||||||
BoolNode* new_bol = new BoolNode(bol2->in(1), res);
|
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)));
|
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;
|
return false;
|
||||||
}
|
}
|
||||||
@ -1916,11 +1920,7 @@ Node *PhiNode::Ideal(PhaseGVN *phase, bool can_reshape) {
|
|||||||
igvn->_worklist.push(r);
|
igvn->_worklist.push(r);
|
||||||
}
|
}
|
||||||
// Nuke it down
|
// Nuke it down
|
||||||
if (can_reshape) {
|
set_req_X(j, top, phase);
|
||||||
set_req_X(j, top, igvn);
|
|
||||||
} else {
|
|
||||||
set_req(j, top);
|
|
||||||
}
|
|
||||||
progress = this; // Record progress
|
progress = this; // Record progress
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1958,7 +1958,7 @@ Node *PhiNode::Ideal(PhaseGVN *phase, bool can_reshape) {
|
|||||||
} else {
|
} else {
|
||||||
// We can't return top if we are in Parse phase - cut inputs only
|
// We can't return top if we are in Parse phase - cut inputs only
|
||||||
// let Identity to handle the case.
|
// let Identity to handle the case.
|
||||||
replace_edge(uin, top);
|
replace_edge(uin, top, phase);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -2227,7 +2227,7 @@ Node *PhiNode::Ideal(PhaseGVN *phase, bool can_reshape) {
|
|||||||
m->as_MergeMem()->memory_at(alias_idx) : m;
|
m->as_MergeMem()->memory_at(alias_idx) : m;
|
||||||
// Update input if it is progress over what we have now
|
// Update input if it is progress over what we have now
|
||||||
if (new_mem != ii) {
|
if (new_mem != ii) {
|
||||||
set_req(i, new_mem);
|
set_req_X(i, new_mem, phase->is_IterGVN());
|
||||||
progress = this;
|
progress = this;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2345,6 +2345,8 @@ void Compile::Optimize() {
|
|||||||
}
|
}
|
||||||
} // (End scope of igvn; run destructor if necessary for asserts.)
|
} // (End scope of igvn; run destructor if necessary for asserts.)
|
||||||
|
|
||||||
|
check_no_dead_use();
|
||||||
|
|
||||||
process_print_inlining();
|
process_print_inlining();
|
||||||
|
|
||||||
// A method with only infinite loops has no edges entering loops from root
|
// 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();)
|
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() {
|
void Compile::inline_vector_reboxing_calls() {
|
||||||
if (C->_vector_reboxing_late_inlines.length() > 0) {
|
if (C->_vector_reboxing_late_inlines.length() > 0) {
|
||||||
_late_inlines_pos = C->_late_inlines.length();
|
_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 compute_truth_table(Unique_Node_List& partition, Unique_Node_List& inputs);
|
||||||
uint eval_macro_logic_op(uint func, uint op1, uint op2, uint op3);
|
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);
|
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:
|
public:
|
||||||
|
|
||||||
|
@ -500,7 +500,7 @@ Node *ConvL2INode::Ideal(PhaseGVN *phase, bool can_reshape) {
|
|||||||
if( andl_op == Op_AndL ) {
|
if( andl_op == Op_AndL ) {
|
||||||
// Blow off prior masking to int
|
// Blow off prior masking to int
|
||||||
if( phase->type(andl->in(2)) == TypeLong::make( 0xFFFFFFFF ) ) {
|
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;
|
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);
|
Node* m = find_inst_mem(n, general_idx, orig_phis);
|
||||||
assert(orig_uniq == C->unique(), "no new nodes");
|
assert(orig_uniq == C->unique(), "no new nodes");
|
||||||
igvn->hash_delete(use);
|
igvn->hash_delete(use);
|
||||||
imax -= use->replace_edge(n, m);
|
imax -= use->replace_edge(n, m, igvn);
|
||||||
igvn->hash_insert(use);
|
igvn->hash_insert(use);
|
||||||
record_for_optimizer(use);
|
record_for_optimizer(use);
|
||||||
--i;
|
--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++) {
|
for (uint j = 2; j < stack.size(); j++) {
|
||||||
Node* n = stack.node_at(j);
|
Node* n = stack.node_at(j);
|
||||||
Node* clone = n->clone();
|
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?");
|
assert(rep > 0, "can't find expected node?");
|
||||||
clone = igvn->transform(clone);
|
clone = igvn->transform(clone);
|
||||||
init_n = n;
|
init_n = n;
|
||||||
new_n = clone;
|
new_n = clone;
|
||||||
}
|
}
|
||||||
igvn->hash_delete(use);
|
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?");
|
assert(rep > 0, "can't find expected node?");
|
||||||
igvn->transform(use);
|
igvn->transform(use);
|
||||||
if (init_n->outcnt() == 0) {
|
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);
|
Node* new_bol = (flip ? phase->transform( bol2->negate(phase) ) : bol2);
|
||||||
assert(new_bol != iff->in(1), "must make progress");
|
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
|
// Intervening diamond probably goes dead
|
||||||
phase->C->set_major_progress();
|
phase->C->set_major_progress();
|
||||||
return iff;
|
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++) {
|
for (DUIterator_Fast imax, i = incr->fast_outs(imax); i < imax; i++) {
|
||||||
Node* n = incr->fast_out(i);
|
Node* n = incr->fast_out(i);
|
||||||
if (n->is_Phi() && n->in(0) == loop) {
|
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;
|
return castii;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -543,7 +543,7 @@ void PhaseIdealLoop::long_loop_replace_long_iv(Node* iv_to_replace, Node* inner_
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
_igvn.rehash_node_delayed(u);
|
_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;
|
i -= nb;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1170,7 +1170,7 @@ bool PhaseIdealLoop::convert_to_long_loop(Node* cmp, Node* phi, IdealLoopTree* l
|
|||||||
set_subtree_ctrl(m, false);
|
set_subtree_ctrl(m, false);
|
||||||
}
|
}
|
||||||
_igvn.rehash_node_delayed(u);
|
_igvn.rehash_node_delayed(u);
|
||||||
int nb = u->replace_edge(n, m);
|
int nb = u->replace_edge(n, m, &_igvn);
|
||||||
--i, imax -= nb;
|
--i, imax -= nb;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -924,7 +924,7 @@ void PhaseIdealLoop::try_move_store_after_loop(Node* n) {
|
|||||||
Node* hook = new Node(1);
|
Node* hook = new Node(1);
|
||||||
hook->init_req(0, n_ctrl); // Add an input to prevent hook from being dead
|
hook->init_req(0, n_ctrl); // Add an input to prevent hook from being dead
|
||||||
_igvn.rehash_node_delayed(phi);
|
_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");
|
assert(count > 0, "inconsistent phi");
|
||||||
|
|
||||||
// Compute latest point this store can go
|
// 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"
|
// to the allocated object with "sobj"
|
||||||
int start = jvms->debug_start();
|
int start = jvms->debug_start();
|
||||||
int end = jvms->debug_end();
|
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);
|
_igvn._worklist.push(sfpt);
|
||||||
safepoints_done.append_if_missing(sfpt); // keep it for rollback
|
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
|
// Set control to top. IGVN will remove the remaining projections
|
||||||
ac->set_req(0, top());
|
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
|
// Disconnect src right away: it can help find new
|
||||||
// opportunities for allocation elimination
|
// opportunities for allocation elimination
|
||||||
Node* src = ac->in(ArrayCopyNode::Src);
|
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
|
// src can be top at this point if src and dest of the
|
||||||
// arraycopy were the same
|
// arraycopy were the same
|
||||||
if (src->outcnt() == 0 && !src->is_top()) {
|
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);
|
Node* u = ctl->fast_out(i);
|
||||||
if (u != ctl) {
|
if (u != ctl) {
|
||||||
igvn->rehash_node_delayed(u);
|
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;
|
--i, imax -= nb;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -2650,13 +2650,9 @@ Node *StoreNode::Ideal(PhaseGVN *phase, bool can_reshape) {
|
|||||||
if (phase->is_IterGVN()) {
|
if (phase->is_IterGVN()) {
|
||||||
phase->is_IterGVN()->rehash_node_delayed(use);
|
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,
|
// 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.
|
// and the parser always refers to nodes via SafePointNode maps.
|
||||||
use->set_req(MemNode::Memory, st->in(MemNode::Memory));
|
use->set_req_X(MemNode::Memory, st->in(MemNode::Memory), phase);
|
||||||
}
|
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
st = st->in(MemNode::Memory);
|
st = st->in(MemNode::Memory);
|
||||||
@ -2801,7 +2797,7 @@ Node *StoreNode::Ideal_masked_input(PhaseGVN *phase, uint mask) {
|
|||||||
if( val->Opcode() == Op_AndI ) {
|
if( val->Opcode() == Op_AndI ) {
|
||||||
const TypeInt *t = phase->type( val->in(2) )->isa_int();
|
const TypeInt *t = phase->type( val->in(2) )->isa_int();
|
||||||
if( t && t->is_con() && (t->get_con() & mask) == mask ) {
|
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;
|
return this;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -2823,7 +2819,7 @@ Node *StoreNode::Ideal_sign_extended_input(PhaseGVN *phase, int num_bits) {
|
|||||||
if( shl->Opcode() == Op_LShiftI ) {
|
if( shl->Opcode() == Op_LShiftI ) {
|
||||||
const TypeInt *t2 = phase->type( shl->in(2) )->isa_int();
|
const TypeInt *t2 = phase->type( shl->in(2) )->isa_int();
|
||||||
if( t2 && t2->is_con() && (t2->get_con() == t->get_con()) ) {
|
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;
|
return this;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -2934,7 +2930,7 @@ Node *StoreCMNode::Ideal(PhaseGVN *phase, bool can_reshape){
|
|||||||
Node* my_store = in(MemNode::OopStore);
|
Node* my_store = in(MemNode::OopStore);
|
||||||
if (my_store->is_MergeMem()) {
|
if (my_store->is_MergeMem()) {
|
||||||
Node* mem = my_store->as_MergeMem()->memory_at(oop_alias_idx());
|
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;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -4734,13 +4730,13 @@ Node *MergeMemNode::Ideal(PhaseGVN *phase, bool can_reshape) {
|
|||||||
// Warning: Do not combine this "if" with the previous "if"
|
// Warning: Do not combine this "if" with the previous "if"
|
||||||
// A memory slice might have be be rewritten even if it is semantically
|
// A memory slice might have be be rewritten even if it is semantically
|
||||||
// unchanged, if the base_memory value has changed.
|
// unchanged, if the base_memory value has changed.
|
||||||
set_req(i, new_in);
|
set_req_X(i, new_in, phase);
|
||||||
progress = this; // Report progress
|
progress = this; // Report progress
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (new_base != old_base) {
|
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.
|
// Don't use set_base_memory(new_base), because we need to update du.
|
||||||
assert(base_memory() == new_base, "");
|
assert(base_memory() == new_base, "");
|
||||||
progress = this;
|
progress = this;
|
||||||
|
@ -104,8 +104,8 @@ Node *MulNode::Ideal(PhaseGVN *phase, bool can_reshape) {
|
|||||||
const Type *tcon01 = ((MulNode*)mul1)->mul_ring(t2,t12);
|
const Type *tcon01 = ((MulNode*)mul1)->mul_ring(t2,t12);
|
||||||
if( tcon01->singleton() ) {
|
if( tcon01->singleton() ) {
|
||||||
// The Mul of the flattened expression
|
// The Mul of the flattened expression
|
||||||
set_req(1, mul1->in(1));
|
set_req_X(1, mul1->in(1), phase);
|
||||||
set_req(2, phase->makecon( tcon01 ));
|
set_req_X(2, phase->makecon(tcon01), phase);
|
||||||
t2 = tcon01;
|
t2 = tcon01;
|
||||||
progress = this; // Made progress
|
progress = this; // Made progress
|
||||||
}
|
}
|
||||||
@ -955,8 +955,8 @@ Node *RShiftINode::Ideal(PhaseGVN *phase, bool can_reshape) {
|
|||||||
// that is the job of 'Identity' calls and Identity calls only work on
|
// that is the job of 'Identity' calls and Identity calls only work on
|
||||||
// direct inputs ('ld' is an extra Node removed from 'this'). The
|
// direct inputs ('ld' is an extra Node removed from 'this'). The
|
||||||
// combined optimization requires Identity only return direct inputs.
|
// combined optimization requires Identity only return direct inputs.
|
||||||
set_req(1, ld);
|
set_req_X(1, ld, phase);
|
||||||
set_req(2, phase->intcon(0));
|
set_req_X(2, phase->intcon(0), phase);
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
else if (can_reshape &&
|
else if (can_reshape &&
|
||||||
@ -973,8 +973,8 @@ Node *RShiftINode::Ideal(PhaseGVN *phase, bool can_reshape) {
|
|||||||
Node *ld = shl->in(1);
|
Node *ld = shl->in(1);
|
||||||
if (ld->Opcode() == Op_LoadB) {
|
if (ld->Opcode() == Op_LoadB) {
|
||||||
// Sign extension is just useless here
|
// Sign extension is just useless here
|
||||||
set_req(1, ld);
|
set_req_X(1, ld, phase);
|
||||||
set_req(2, phase->intcon(0));
|
set_req_X(2, phase->intcon(0), phase);
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -868,14 +868,19 @@ int Node::find_edge(Node* n) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
//----------------------------replace_edge-------------------------------------
|
//----------------------------replace_edge-------------------------------------
|
||||||
int Node::replace_edge(Node* old, Node* neww) {
|
int Node::replace_edge(Node* old, Node* neww, PhaseGVN* gvn) {
|
||||||
if (old == neww) return 0; // nothing to do
|
if (old == neww) return 0; // nothing to do
|
||||||
uint nrep = 0;
|
uint nrep = 0;
|
||||||
for (uint i = 0; i < len(); i++) {
|
for (uint i = 0; i < len(); i++) {
|
||||||
if (in(i) == old) {
|
if (in(i) == old) {
|
||||||
if (i < req()) {
|
if (i < req()) {
|
||||||
set_req(i, neww);
|
if (gvn != NULL) {
|
||||||
|
set_req_X(i, neww, gvn);
|
||||||
} else {
|
} else {
|
||||||
|
set_req(i, neww);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
assert(gvn == NULL || gvn->is_IterGVN() == NULL, "no support for igvn here");
|
||||||
assert(find_prec_edge(neww) == -1, "spec violation: duplicated prec edge (node %d -> %d)", _idx, neww->_idx);
|
assert(find_prec_edge(neww) == -1, "spec violation: duplicated prec edge (node %d -> %d)", _idx, neww->_idx);
|
||||||
set_prec(i, neww);
|
set_prec(i, neww);
|
||||||
}
|
}
|
||||||
@ -888,12 +893,12 @@ int Node::replace_edge(Node* old, Node* neww) {
|
|||||||
/**
|
/**
|
||||||
* Replace input edges in the range pointing to 'old' node.
|
* Replace input edges in the range pointing to 'old' node.
|
||||||
*/
|
*/
|
||||||
int Node::replace_edges_in_range(Node* old, Node* neww, int start, int end) {
|
int Node::replace_edges_in_range(Node* old, Node* neww, int start, int end, PhaseGVN* gvn) {
|
||||||
if (old == neww) return 0; // nothing to do
|
if (old == neww) return 0; // nothing to do
|
||||||
uint nrep = 0;
|
uint nrep = 0;
|
||||||
for (int i = start; i < end; i++) {
|
for (int i = start; i < end; i++) {
|
||||||
if (in(i) == old) {
|
if (in(i) == old) {
|
||||||
set_req(i, neww);
|
set_req_X(i, neww, gvn);
|
||||||
nrep++;
|
nrep++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -454,8 +454,8 @@ protected:
|
|||||||
}
|
}
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
int replace_edge(Node* old, Node* neww);
|
int replace_edge(Node* old, Node* neww, PhaseGVN* gvn = NULL);
|
||||||
int replace_edges_in_range(Node* old, Node* neww, int start, int end);
|
int replace_edges_in_range(Node* old, Node* neww, int start, int end, PhaseGVN* gvn);
|
||||||
// NULL out all inputs to eliminate incoming Def-Use edges.
|
// NULL out all inputs to eliminate incoming Def-Use edges.
|
||||||
void disconnect_inputs(Compile* C);
|
void disconnect_inputs(Compile* C);
|
||||||
|
|
||||||
@ -530,6 +530,7 @@ public:
|
|||||||
disconnect_inputs(c);
|
disconnect_inputs(c);
|
||||||
}
|
}
|
||||||
void set_req_X(uint i, Node *n, PhaseIterGVN *igvn);
|
void set_req_X(uint i, Node *n, PhaseIterGVN *igvn);
|
||||||
|
void set_req_X(uint i, Node *n, PhaseGVN *gvn);
|
||||||
// Find the one non-null required input. RegionNode only
|
// Find the one non-null required input. RegionNode only
|
||||||
Node *nonnull_req() const;
|
Node *nonnull_req() const;
|
||||||
// Add or remove precedence edges
|
// Add or remove precedence edges
|
||||||
|
@ -1360,7 +1360,7 @@ void PhaseIterGVN::remove_globally_dead_node( Node *dead ) {
|
|||||||
for (uint i = 0; i < dead->req(); i++) {
|
for (uint i = 0; i < dead->req(); i++) {
|
||||||
Node *in = dead->in(i);
|
Node *in = dead->in(i);
|
||||||
if (in != NULL && in != C->top()) { // Points to something?
|
if (in != NULL && in != C->top()) { // Points to something?
|
||||||
int nrep = dead->replace_edge(in, NULL); // Kill edges
|
int nrep = dead->replace_edge(in, NULL, this); // Kill edges
|
||||||
assert((nrep > 0), "sanity");
|
assert((nrep > 0), "sanity");
|
||||||
if (in->outcnt() == 0) { // Made input go dead?
|
if (in->outcnt() == 0) { // Made input go dead?
|
||||||
_stack.push(in, PROCESS_INPUTS); // Recursively remove
|
_stack.push(in, PROCESS_INPUTS); // Recursively remove
|
||||||
@ -2113,7 +2113,15 @@ void Node::set_req_X( uint i, Node *n, PhaseIterGVN *igvn ) {
|
|||||||
|
|
||||||
BarrierSet::barrier_set()->barrier_set_c2()->enqueue_useful_gc_barrier(igvn, old);
|
BarrierSet::barrier_set()->barrier_set_c2()->enqueue_useful_gc_barrier(igvn, old);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Node::set_req_X(uint i, Node *n, PhaseGVN *gvn) {
|
||||||
|
PhaseIterGVN* igvn = gvn->is_IterGVN();
|
||||||
|
if (igvn == NULL) {
|
||||||
|
set_req(i, n);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
set_req_X(i, n, igvn);
|
||||||
}
|
}
|
||||||
|
|
||||||
//-------------------------------replace_by-----------------------------------
|
//-------------------------------replace_by-----------------------------------
|
||||||
|
@ -525,7 +525,7 @@ public:
|
|||||||
// Replace ith edge of "n" with "in"
|
// Replace ith edge of "n" with "in"
|
||||||
void replace_input_of(Node* n, int i, Node* in) {
|
void replace_input_of(Node* n, int i, Node* in) {
|
||||||
rehash_node_delayed(n);
|
rehash_node_delayed(n);
|
||||||
n->set_req(i, in);
|
n->set_req_X(i, in, this);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Delete ith edge of "n"
|
// Delete ith edge of "n"
|
||||||
|
@ -460,7 +460,7 @@ int PhaseChaitin::possibly_merge_multidef(Node *n, uint k, Block *block, RegToDe
|
|||||||
if (use == n) {
|
if (use == n) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
use->replace_edge(def, merge);
|
use->replace_edge(def, merge, NULL);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (merge->find_edge(n->in(k)) == -1) {
|
if (merge->find_edge(n->in(k)) == -1) {
|
||||||
|
@ -1057,14 +1057,8 @@ Node *CmpPNode::Ideal( PhaseGVN *phase, bool can_reshape ) {
|
|||||||
if (k1 && (k2 || conk2)) {
|
if (k1 && (k2 || conk2)) {
|
||||||
Node* lhs = k1;
|
Node* lhs = k1;
|
||||||
Node* rhs = (k2 != NULL) ? k2 : conk2;
|
Node* rhs = (k2 != NULL) ? k2 : conk2;
|
||||||
PhaseIterGVN* igvn = phase->is_IterGVN();
|
set_req_X(1, lhs, phase);
|
||||||
if (igvn != NULL) {
|
set_req_X(2, rhs, phase);
|
||||||
set_req_X(1, lhs, igvn);
|
|
||||||
set_req_X(2, rhs, igvn);
|
|
||||||
} else {
|
|
||||||
set_req(1, lhs);
|
|
||||||
set_req(2, rhs);
|
|
||||||
}
|
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -196,6 +196,20 @@ Node *SubTypeCheckNode::Ideal(PhaseGVN *phase, bool can_reshape) {
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Node *p1 = phase->transform(new AddPNode(superklass, superklass, phase->MakeConX(in_bytes(Klass::super_check_offset_offset()))));
|
||||||
|
Node* m = phase->C->immutable_memory();
|
||||||
|
LoadINode* chk_off_ld = new LoadINode(NULL, m, p1, phase->type(p1)->is_ptr(), TypeInt::INT, MemNode::unordered);
|
||||||
|
Node *chk_off = phase->transform(chk_off_ld);
|
||||||
|
int cacheoff_con = in_bytes(Klass::secondary_super_cache_offset());
|
||||||
|
bool might_be_cache = (phase->find_int_con(chk_off, cacheoff_con) == cacheoff_con);
|
||||||
|
|
||||||
|
if (might_be_cache) {
|
||||||
|
if (phase->is_IterGVN()) {
|
||||||
|
phase->is_IterGVN()->_worklist.push(chk_off_ld);
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
if (super_t->singleton() && subk != NULL && phase->C->static_subtype_check(superk, subk) == Compile::SSC_full_test) {
|
if (super_t->singleton() && subk != NULL && phase->C->static_subtype_check(superk, subk) == Compile::SSC_full_test) {
|
||||||
Node* subklass = NULL;
|
Node* subklass = NULL;
|
||||||
if (sub_t->isa_oopptr()) {
|
if (sub_t->isa_oopptr()) {
|
||||||
@ -205,16 +219,6 @@ Node *SubTypeCheckNode::Ideal(PhaseGVN *phase, bool can_reshape) {
|
|||||||
subklass = obj_or_subklass;
|
subklass = obj_or_subklass;
|
||||||
}
|
}
|
||||||
|
|
||||||
Node *p1 = phase->transform(new AddPNode(superklass, superklass, phase->MakeConX(in_bytes(Klass::super_check_offset_offset()))));
|
|
||||||
Node* m = phase->C->immutable_memory();
|
|
||||||
Node *chk_off = phase->transform(new LoadINode(NULL, m, p1, phase->type(p1)->is_ptr(), TypeInt::INT, MemNode::unordered));
|
|
||||||
int cacheoff_con = in_bytes(Klass::secondary_super_cache_offset());
|
|
||||||
bool might_be_cache = (phase->find_int_con(chk_off, cacheoff_con) == cacheoff_con);
|
|
||||||
|
|
||||||
if (might_be_cache) {
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
Node *chk_off_X = chk_off;
|
Node *chk_off_X = chk_off;
|
||||||
#ifdef _LP64
|
#ifdef _LP64
|
||||||
chk_off_X = phase->transform(new ConvI2LNode(chk_off_X));
|
chk_off_X = phase->transform(new ConvI2LNode(chk_off_X));
|
||||||
|
Loading…
x
Reference in New Issue
Block a user