8255670: Improve C2's detection of modified nodes
Reviewed-by: kvn, thartmann, roland
This commit is contained in:
parent
5652030f16
commit
83abfa5d82
@ -77,13 +77,8 @@ static bool commute(PhaseGVN* phase, Node* add) {
|
||||
|
||||
if ((in11 == in21 && in12 == in22) ||
|
||||
(in11 == in22 && in12 == in21)) {
|
||||
add->set_req(1, in11);
|
||||
add->set_req(2, in12);
|
||||
PhaseIterGVN* igvn = phase->is_IterGVN();
|
||||
if (igvn) {
|
||||
igvn->_worklist.push(in1);
|
||||
igvn->_worklist.push(in2);
|
||||
}
|
||||
add->set_req_X(1, in11, phase);
|
||||
add->set_req_X(2, in12, phase);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@ -632,12 +627,7 @@ Node *AddPNode::Ideal(PhaseGVN *phase, bool can_reshape) {
|
||||
const Type *t22 = phase->type( add->in(2) );
|
||||
if( t22->singleton() && (t22 != Type::TOP) ) { // Right input is an add of a constant?
|
||||
set_req(Address, phase->transform(new AddPNode(in(Base),in(Address),add->in(1))));
|
||||
set_req(Offset, add->in(2));
|
||||
PhaseIterGVN* igvn = phase->is_IterGVN();
|
||||
if (add->outcnt() == 0 && igvn) {
|
||||
// add disconnected.
|
||||
igvn->_worklist.push((Node*)add);
|
||||
}
|
||||
set_req_X(Offset, add->in(2), phase); // puts add on igvn worklist if needed
|
||||
return this; // Made progress
|
||||
}
|
||||
}
|
||||
|
@ -1454,7 +1454,7 @@ void SafePointNode::disconnect_from_root(PhaseIterGVN *igvn) {
|
||||
assert(Opcode() == Op_SafePoint, "only value for safepoint in loops");
|
||||
int nb = igvn->C->root()->find_prec_edge(this);
|
||||
if (nb != -1) {
|
||||
igvn->C->root()->rm_prec(nb);
|
||||
igvn->delete_precedence_of(igvn->C->root(), nb);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1611,7 +1611,7 @@ Node* AllocateArrayNode::Ideal(PhaseGVN *phase, bool can_reshape) {
|
||||
frame = phase->transform(frame);
|
||||
// Halt & Catch Fire
|
||||
Node* halt = new HaltNode(nproj, frame, "unexpected negative array length");
|
||||
phase->C->root()->add_req(halt);
|
||||
igvn->add_input_to(phase->C->root(), halt);
|
||||
phase->transform(halt);
|
||||
|
||||
igvn->replace_node(catchproj, phase->C->top());
|
||||
|
@ -1005,7 +1005,6 @@ bool IfNode::fold_compares_helper(ProjNode* proj, ProjNode* success, ProjNode* f
|
||||
if (failtype->_lo > failtype->_hi) {
|
||||
// previous if determines the result of this if so
|
||||
// replace Bool with constant
|
||||
igvn->_worklist.push(in(1));
|
||||
igvn->replace_input_of(this, 1, igvn->intcon(success->_con));
|
||||
return true;
|
||||
}
|
||||
@ -1055,7 +1054,6 @@ bool IfNode::fold_compares_helper(ProjNode* proj, ProjNode* success, ProjNode* f
|
||||
Node* newbool = igvn->transform(new BoolNode(newcmp, cond));
|
||||
|
||||
igvn->replace_input_of(dom_iff, 1, igvn->intcon(proj->_con));
|
||||
igvn->_worklist.push(in(1));
|
||||
igvn->replace_input_of(this, 1, newbool);
|
||||
|
||||
return true;
|
||||
|
@ -176,9 +176,8 @@ ProjNode* PhaseIdealLoop::create_new_if_for_predicate(ProjNode* cont_proj, Node*
|
||||
register_control(if_cont, lp, new_iff);
|
||||
register_control(if_uct, get_loop(rgn), new_iff);
|
||||
|
||||
// if_uct to rgn
|
||||
_igvn.hash_delete(rgn);
|
||||
rgn->add_req(if_uct);
|
||||
_igvn.add_input_to(rgn, if_uct);
|
||||
|
||||
// When called from beautify_loops() idom is not constructed yet.
|
||||
if (_idom != NULL) {
|
||||
Node* ridom = idom(rgn);
|
||||
|
@ -1568,7 +1568,7 @@ Node* PhaseIdealLoop::clone_skeleton_predicate_and_initialize(Node* iff, Node* n
|
||||
register_new_node(frame, C->start());
|
||||
// It's impossible for the predicate to fail at runtime. Use an Halt node.
|
||||
Node* halt = new HaltNode(other_proj, frame, "duplicated predicate failed which is impossible");
|
||||
C->root()->add_req(halt);
|
||||
_igvn.add_input_to(C->root(), halt);
|
||||
new_iff->set_req(0, input_proj);
|
||||
|
||||
register_control(new_iff, outer_loop == _ltree_root ? _ltree_root : outer_loop->_parent, input_proj);
|
||||
@ -2998,7 +2998,7 @@ Node* PhaseIdealLoop::add_range_check_predicate(IdealLoopTree* loop, CountedLoop
|
||||
register_new_node(frame, C->start());
|
||||
Node* halt = new HaltNode(iffalse, frame, "range check predicate failed which is impossible");
|
||||
register_control(halt, _ltree_root, iffalse);
|
||||
C->root()->add_req(halt);
|
||||
_igvn.add_input_to(C->root(), halt);
|
||||
return iftrue;
|
||||
}
|
||||
|
||||
|
@ -611,7 +611,7 @@ void PhaseIdealLoop::add_empty_predicate(Deoptimization::DeoptReason reason, Nod
|
||||
register_control(ctrl, _ltree_root, unc);
|
||||
Node* halt = new HaltNode(ctrl, frame, "uncommon trap returned which should never happen" PRODUCT_ONLY(COMMA /*reachable*/false));
|
||||
register_control(halt, _ltree_root, ctrl);
|
||||
C->root()->add_req(halt);
|
||||
_igvn.add_input_to(C->root(), halt);
|
||||
|
||||
_igvn.replace_input_of(inner_head, LoopNode::EntryControl, iftrue);
|
||||
set_idom(inner_head, iftrue, dom_depth(inner_head));
|
||||
@ -621,7 +621,7 @@ void PhaseIdealLoop::add_empty_predicate(Deoptimization::DeoptReason reason, Nod
|
||||
// Find a safepoint node that dominates the back edge. We need a
|
||||
// SafePointNode so we can use its jvm state to create empty
|
||||
// predicates.
|
||||
static bool no_side_effect_since_safepoint(Compile* C, Node* x, Node* mem, MergeMemNode* mm) {
|
||||
static bool no_side_effect_since_safepoint(Compile* C, Node* x, Node* mem, MergeMemNode* mm, PhaseIdealLoop* phase) {
|
||||
SafePointNode* safepoint = NULL;
|
||||
for (DUIterator_Fast imax, i = x->fast_outs(imax); i < imax; i++) {
|
||||
Node* u = x->fast_out(i);
|
||||
@ -630,6 +630,11 @@ static bool no_side_effect_since_safepoint(Compile* C, Node* x, Node* mem, Merge
|
||||
if (u->adr_type() == TypePtr::BOTTOM) {
|
||||
if (m->is_MergeMem() && mem->is_MergeMem()) {
|
||||
if (m != mem DEBUG_ONLY(|| true)) {
|
||||
// MergeMemStream can modify m, for example to adjust the length to mem.
|
||||
// This is unfortunate, and probably unnecessary. But as it is, we need
|
||||
// to add m to the igvn worklist, else we may have a modified node that
|
||||
// is not on the igvn worklist.
|
||||
phase->igvn()._worklist.push(m);
|
||||
for (MergeMemStream mms(m->as_MergeMem(), mem->as_MergeMem()); mms.next_non_empty2(); ) {
|
||||
if (!mms.is_empty()) {
|
||||
if (mms.memory() != mms.memory2()) {
|
||||
@ -705,7 +710,7 @@ SafePointNode* PhaseIdealLoop::find_safepoint(Node* back_control, Node* x, Ideal
|
||||
}
|
||||
}
|
||||
#endif
|
||||
if (!no_side_effect_since_safepoint(C, x, mem, mm)) {
|
||||
if (!no_side_effect_since_safepoint(C, x, mem, mm, this)) {
|
||||
safepoint = NULL;
|
||||
} else {
|
||||
assert(mm == NULL|| _igvn.transform(mm) == mem->as_MergeMem()->base_memory(), "all memory state should have been processed");
|
||||
@ -4171,17 +4176,11 @@ bool PhaseIdealLoop::process_expensive_nodes() {
|
||||
}
|
||||
// Do the actual moves
|
||||
if (n1->in(0) != c1) {
|
||||
_igvn.hash_delete(n1);
|
||||
n1->set_req(0, c1);
|
||||
_igvn.hash_insert(n1);
|
||||
_igvn._worklist.push(n1);
|
||||
_igvn.replace_input_of(n1, 0, c1);
|
||||
progress = true;
|
||||
}
|
||||
if (n2->in(0) != c2) {
|
||||
_igvn.hash_delete(n2);
|
||||
n2->set_req(0, c2);
|
||||
_igvn.hash_insert(n2);
|
||||
_igvn._worklist.push(n2);
|
||||
_igvn.replace_input_of(n2, 0, c2);
|
||||
progress = true;
|
||||
}
|
||||
}
|
||||
@ -5109,8 +5108,7 @@ int PhaseIdealLoop::build_loop_tree_impl( Node *n, int pre_order ) {
|
||||
assert(cfg != NULL, "must find the control user of m");
|
||||
uint k = 0; // Probably cfg->in(0)
|
||||
while( cfg->in(k) != m ) k++; // But check in case cfg is a Region
|
||||
cfg->set_req( k, if_t ); // Now point to NeverBranch
|
||||
_igvn._worklist.push(cfg);
|
||||
_igvn.replace_input_of(cfg, k, if_t); // Now point to NeverBranch
|
||||
|
||||
// Now create the never-taken loop exit
|
||||
Node *if_f = new CProjNode( iff, 1 );
|
||||
@ -5125,7 +5123,7 @@ int PhaseIdealLoop::build_loop_tree_impl( Node *n, int pre_order ) {
|
||||
Node* halt = new HaltNode(if_f, frame, "never-taken loop exit reached");
|
||||
_igvn.register_new_node_with_optimizer(halt);
|
||||
set_loop(halt, l);
|
||||
C->root()->add_req(halt);
|
||||
_igvn.add_input_to(C->root(), halt);
|
||||
}
|
||||
set_loop(C->root(), _ltree_root);
|
||||
}
|
||||
|
@ -394,10 +394,7 @@ Node *MemNode::Ideal_common(PhaseGVN *phase, bool can_reshape) {
|
||||
}
|
||||
|
||||
if (mem != old_mem) {
|
||||
set_req(MemNode::Memory, mem);
|
||||
if (can_reshape && old_mem->outcnt() == 0 && igvn != NULL) {
|
||||
igvn->_worklist.push(old_mem);
|
||||
}
|
||||
set_req_X(MemNode::Memory, mem, phase);
|
||||
if (phase->type(mem) == Type::TOP) return NodeSentinel;
|
||||
return this;
|
||||
}
|
||||
|
@ -73,13 +73,8 @@ Node *MulNode::Ideal(PhaseGVN *phase, bool can_reshape) {
|
||||
if (real_mul && in1->is_Sub() && in2->is_Sub()) {
|
||||
if (phase->type(in1->in(1))->is_zero_type() &&
|
||||
phase->type(in2->in(1))->is_zero_type()) {
|
||||
set_req(1, in1->in(2));
|
||||
set_req(2, in2->in(2));
|
||||
PhaseIterGVN* igvn = phase->is_IterGVN();
|
||||
if (igvn) {
|
||||
igvn->_worklist.push(in1);
|
||||
igvn->_worklist.push(in2);
|
||||
}
|
||||
set_req_X(1, in1->in(2), phase);
|
||||
set_req_X(2, in2->in(2), phase);
|
||||
in1 = in(1);
|
||||
in2 = in(2);
|
||||
progress = this;
|
||||
@ -97,13 +92,8 @@ Node *MulNode::Ideal(PhaseGVN *phase, bool can_reshape) {
|
||||
|
||||
if ((in11 == in21 && in12 == in22) ||
|
||||
(in11 == in22 && in12 == in21)) {
|
||||
set_req(1, in11);
|
||||
set_req(2, in12);
|
||||
PhaseIterGVN* igvn = phase->is_IterGVN();
|
||||
if (igvn) {
|
||||
igvn->_worklist.push(in1);
|
||||
igvn->_worklist.push(in2);
|
||||
}
|
||||
set_req_X(1, in11, phase);
|
||||
set_req_X(2, in12, phase);
|
||||
in1 = in(1);
|
||||
in2 = in(2);
|
||||
progress = this;
|
||||
|
@ -572,6 +572,7 @@ Node *Node::clone() const {
|
||||
n->as_SafePoint()->clone_jvms(C);
|
||||
n->as_SafePoint()->clone_replaced_nodes();
|
||||
}
|
||||
Compile::current()->record_modified_node(n);
|
||||
return n; // Return the clone
|
||||
}
|
||||
|
||||
@ -781,6 +782,7 @@ void Node::add_req( Node *n ) {
|
||||
}
|
||||
_in[_cnt++] = n; // Stuff over old prec edge
|
||||
if (n != NULL) n->add_out((Node *)this);
|
||||
Compile::current()->record_modified_node(this);
|
||||
}
|
||||
|
||||
//---------------------------add_req_batch-------------------------------------
|
||||
@ -819,6 +821,7 @@ void Node::add_req_batch( Node *n, uint m ) {
|
||||
n->add_out((Node *)this);
|
||||
}
|
||||
}
|
||||
Compile::current()->record_modified_node(this);
|
||||
}
|
||||
|
||||
//------------------------------del_req----------------------------------------
|
||||
@ -865,6 +868,7 @@ void Node::ins_req( uint idx, Node *n ) {
|
||||
}
|
||||
_in[idx] = n; // Stuff over old required edge
|
||||
if (n != NULL) n->add_out((Node *)this); // Add reciprocal def-use edge
|
||||
Compile::current()->record_modified_node(this);
|
||||
}
|
||||
|
||||
//-----------------------------find_edge---------------------------------------
|
||||
@ -1042,6 +1046,7 @@ void Node::add_prec( Node *n ) {
|
||||
#ifdef ASSERT
|
||||
while ((++i)<_max) { assert(_in[i] == NULL, "spec violation: Gap in prec edges (node %d)", _idx); }
|
||||
#endif
|
||||
Compile::current()->record_modified_node(this);
|
||||
}
|
||||
|
||||
//------------------------------rm_prec----------------------------------------
|
||||
@ -1053,6 +1058,7 @@ void Node::rm_prec( uint j ) {
|
||||
if (_in[j] == NULL) return; // Avoid spec violation: Gap in prec edges.
|
||||
_in[j]->del_out((Node *)this);
|
||||
close_prec_gap_at(j);
|
||||
Compile::current()->record_modified_node(this);
|
||||
}
|
||||
|
||||
//------------------------------size_of----------------------------------------
|
||||
|
@ -559,6 +559,7 @@ public:
|
||||
if (_in[i] != NULL) _in[i]->del_out((Node *)this);
|
||||
_in[i] = n;
|
||||
n->add_out((Node *)this);
|
||||
Compile::current()->record_modified_node(this);
|
||||
}
|
||||
|
||||
// Set this node's index, used by cisc_version to replace current node
|
||||
|
@ -531,12 +531,24 @@ public:
|
||||
n->set_req_X(i, in, this);
|
||||
}
|
||||
|
||||
// Add "in" as input (req) of "n"
|
||||
void add_input_to(Node* n, Node* in) {
|
||||
rehash_node_delayed(n);
|
||||
n->add_req(in);
|
||||
}
|
||||
|
||||
// Delete ith edge of "n"
|
||||
void delete_input_of(Node* n, int i) {
|
||||
rehash_node_delayed(n);
|
||||
n->del_req(i);
|
||||
}
|
||||
|
||||
// Delete precedence edge i of "n"
|
||||
void delete_precedence_of(Node* n, int i) {
|
||||
rehash_node_delayed(n);
|
||||
n->rm_prec(i);
|
||||
}
|
||||
|
||||
bool delay_transform() const { return _delay_transform; }
|
||||
|
||||
void set_delay_transform(bool delay) {
|
||||
|
Loading…
Reference in New Issue
Block a user