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) ||
|
||||
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));
|
||||
}
|
||||
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;
|
||||
|
@ -104,8 +104,8 @@ Node *MulNode::Ideal(PhaseGVN *phase, bool can_reshape) {
|
||||
const Type *tcon01 = ((MulNode*)mul1)->mul_ring(t2,t12);
|
||||
if( tcon01->singleton() ) {
|
||||
// The Mul of the flattened expression
|
||||
set_req(1, mul1->in(1));
|
||||
set_req(2, phase->makecon( tcon01 ));
|
||||
set_req_X(1, mul1->in(1), phase);
|
||||
set_req_X(2, phase->makecon(tcon01), phase);
|
||||
t2 = tcon01;
|
||||
progress = this; // Made progress
|
||||
}
|
||||
@ -955,11 +955,11 @@ Node *RShiftINode::Ideal(PhaseGVN *phase, bool can_reshape) {
|
||||
// that is the job of 'Identity' calls and Identity calls only work on
|
||||
// direct inputs ('ld' is an extra Node removed from 'this'). The
|
||||
// combined optimization requires Identity only return direct inputs.
|
||||
set_req(1, ld);
|
||||
set_req(2, phase->intcon(0));
|
||||
set_req_X(1, ld, phase);
|
||||
set_req_X(2, phase->intcon(0), phase);
|
||||
return this;
|
||||
}
|
||||
else if( can_reshape &&
|
||||
else if (can_reshape &&
|
||||
ld->Opcode() == Op_LoadUS &&
|
||||
ld->outcnt() == 1 && ld->unique_out() == shl)
|
||||
// Replace zero-extension-load with sign-extension-load
|
||||
@ -971,10 +971,10 @@ Node *RShiftINode::Ideal(PhaseGVN *phase, bool can_reshape) {
|
||||
(t3 = phase->type(shl->in(2))->isa_int()) &&
|
||||
t3->is_con(24) ) {
|
||||
Node *ld = shl->in(1);
|
||||
if( ld->Opcode() == Op_LoadB ) {
|
||||
if (ld->Opcode() == Op_LoadB) {
|
||||
// Sign extension is just useless here
|
||||
set_req(1, ld);
|
||||
set_req(2, phase->intcon(0));
|
||||
set_req_X(1, ld, phase);
|
||||
set_req_X(2, phase->intcon(0), phase);
|
||||
return this;
|
||||
}
|
||||
}
|
||||
|
@ -868,14 +868,19 @@ int Node::find_edge(Node* n) {
|
||||
}
|
||||
|
||||
//----------------------------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
|
||||
uint nrep = 0;
|
||||
for (uint i = 0; i < len(); i++) {
|
||||
if (in(i) == old) {
|
||||
if (i < req()) {
|
||||
set_req(i, neww);
|
||||
if (gvn != NULL) {
|
||||
set_req_X(i, neww, gvn);
|
||||
} 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);
|
||||
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.
|
||||
*/
|
||||
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
|
||||
uint nrep = 0;
|
||||
for (int i = start; i < end; i++) {
|
||||
if (in(i) == old) {
|
||||
set_req(i, neww);
|
||||
set_req_X(i, neww, gvn);
|
||||
nrep++;
|
||||
}
|
||||
}
|
||||
|
@ -454,8 +454,8 @@ protected:
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
int replace_edge(Node* old, Node* neww);
|
||||
int replace_edges_in_range(Node* old, Node* neww, int start, int end);
|
||||
int replace_edge(Node* old, Node* neww, PhaseGVN* gvn = NULL);
|
||||
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.
|
||||
void disconnect_inputs(Compile* C);
|
||||
|
||||
@ -529,7 +529,8 @@ public:
|
||||
replace_by(new_node);
|
||||
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
|
||||
Node *nonnull_req() const;
|
||||
// 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++) {
|
||||
Node *in = dead->in(i);
|
||||
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");
|
||||
if (in->outcnt() == 0) { // Made input go dead?
|
||||
_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);
|
||||
}
|
||||
}
|
||||
|
||||
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-----------------------------------
|
||||
|
@ -525,7 +525,7 @@ public:
|
||||
// Replace ith edge of "n" with "in"
|
||||
void replace_input_of(Node* n, int i, Node* in) {
|
||||
rehash_node_delayed(n);
|
||||
n->set_req(i, in);
|
||||
n->set_req_X(i, in, this);
|
||||
}
|
||||
|
||||
// Delete ith edge of "n"
|
||||
|
@ -460,7 +460,7 @@ int PhaseChaitin::possibly_merge_multidef(Node *n, uint k, Block *block, RegToDe
|
||||
if (use == n) {
|
||||
break;
|
||||
}
|
||||
use->replace_edge(def, merge);
|
||||
use->replace_edge(def, merge, NULL);
|
||||
}
|
||||
}
|
||||
if (merge->find_edge(n->in(k)) == -1) {
|
||||
|
@ -1057,14 +1057,8 @@ Node *CmpPNode::Ideal( PhaseGVN *phase, bool can_reshape ) {
|
||||
if (k1 && (k2 || conk2)) {
|
||||
Node* lhs = k1;
|
||||
Node* rhs = (k2 != NULL) ? k2 : conk2;
|
||||
PhaseIterGVN* igvn = phase->is_IterGVN();
|
||||
if (igvn != NULL) {
|
||||
set_req_X(1, lhs, igvn);
|
||||
set_req_X(2, rhs, igvn);
|
||||
} else {
|
||||
set_req(1, lhs);
|
||||
set_req(2, rhs);
|
||||
}
|
||||
set_req_X(1, lhs, phase);
|
||||
set_req_X(2, rhs, phase);
|
||||
return this;
|
||||
}
|
||||
}
|
||||
|
@ -196,6 +196,20 @@ Node *SubTypeCheckNode::Ideal(PhaseGVN *phase, bool can_reshape) {
|
||||
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) {
|
||||
Node* subklass = NULL;
|
||||
if (sub_t->isa_oopptr()) {
|
||||
@ -205,16 +219,6 @@ Node *SubTypeCheckNode::Ideal(PhaseGVN *phase, bool can_reshape) {
|
||||
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;
|
||||
#ifdef _LP64
|
||||
chk_off_X = phase->transform(new ConvI2LNode(chk_off_X));
|
||||
|
Loading…
x
Reference in New Issue
Block a user