< prev index next >
src/share/vm/opto/loopopts.cpp
Print this page
rev 8961 : [mq]: diff-shenandoah.patch
@@ -31,10 +31,11 @@
#include "opto/matcher.hpp"
#include "opto/mulnode.hpp"
#include "opto/movenode.hpp"
#include "opto/opaquenode.hpp"
#include "opto/rootnode.hpp"
+#include "opto/shenandoahSupport.hpp"
#include "opto/subnode.hpp"
//=============================================================================
//------------------------------split_thru_phi---------------------------------
// Split Node 'n' through merge point if there is enough win.
@@ -65,10 +66,13 @@
Node *x;
Node* the_clone = NULL;
if (region->in(i) == C->top()) {
x = C->top(); // Dead path? Use a dead data op
} else {
+#ifdef ASSERT
+ if (n->is_ShenandoahBarrier()) { n->as_ShenandoahBarrier()->check_invariants(); }
+#endif
x = n->clone(); // Else clone up the data op
the_clone = x; // Remember for possible deletion.
// Alter data node to use pre-phi inputs
if (n->in(0) == region)
x->set_req( 0, region->in(i) );
@@ -109,10 +113,11 @@
_igvn.set_type(x, t);
// If x is a TypeNode, capture any more-precise type permanently into Node
// otherwise it will be not updated during igvn->transform since
// igvn->type(x) is set to x->Value() already.
x->raise_bottom_type(t);
+ if (x->Opcode() != Op_ShenandoahWriteBarrier) {
Node *y = x->Identity(&_igvn);
if (y != x) {
wins++;
x = y;
} else {
@@ -125,10 +130,14 @@
// We do not need register_new_node_with_optimizer
// because set_type has already been called.
_igvn._worklist.push(x);
}
}
+ } else {
+ // wins++;
+ _igvn._worklist.push(x);
+ }
}
if (x != the_clone && the_clone != NULL)
_igvn.remove_dead_node(the_clone);
phi->set_req( i, x );
}
@@ -192,10 +201,42 @@
}
return phi;
}
+void PhaseIdealLoop::split_mem_thru_phi(Node* n, Node* r, Node* phi) {
+ if (n->Opcode() == Op_ShenandoahWriteBarrier) {
+#ifdef ASSERT
+ n->as_ShenandoahBarrier()->check_invariants();
+#endif
+ if (n->has_out_with(Op_ShenandoahWBMemProj)) {
+ Node* old_mem_phi = n->in(ShenandoahBarrierNode::Memory);
+ assert(r->is_Region(), "need region to control phi");
+ assert(phi->is_Phi(), "expect phi");
+ Node* memphi = PhiNode::make(r, old_mem_phi, Type::MEMORY, C->alias_type(n->adr_type())->adr_type());
+ for (uint i = 1; i < r->req(); i++) {
+ Node* wb = phi->in(i);
+ if (wb->Opcode() == Op_ShenandoahWriteBarrier) {
+ assert(! wb->has_out_with(Op_ShenandoahWBMemProj), "new clone does not have mem proj");
+ Node* new_proj = new ShenandoahWBMemProjNode(wb);
+ register_new_node(new_proj, r->in(i));
+ memphi->set_req(i, new_proj);
+ } else {
+ if (old_mem_phi->is_Phi() && old_mem_phi->in(0) == r) {
+ memphi->set_req(i, old_mem_phi->in(i));
+ }
+ }
+ }
+ register_new_node(memphi, r);
+ Node* old_mem_out = n->find_out_with(Op_ShenandoahWBMemProj);
+ assert(old_mem_out != NULL, "expect memory projection");
+ _igvn.replace_node(old_mem_out, memphi);
+ }
+ assert(! n->has_out_with(Op_ShenandoahWBMemProj), "no more memory outs");
+ }
+}
+
//------------------------------dominated_by------------------------------------
// Replace the dominated test with an obvious true or false. Place it on the
// IGVN worklist for later cleanup. Move control-dependent data Nodes on the
// live path up to the dominating control.
void PhaseIdealLoop::dominated_by( Node *prevdom, Node *iff, bool flip, bool exclude_loop_predicate ) {
@@ -932,16 +973,22 @@
Node *phi = split_thru_phi( n, n_blk, policy );
if (!phi) return n;
// Found a Phi to split thru!
// Replace 'n' with the new phi
+ split_mem_thru_phi(n, n_blk, phi);
_igvn.replace_node( n, phi );
// Moved a load around the loop, 'en-registering' something.
if (n_blk->is_Loop() && n->is_Load() &&
!phi->in(LoopNode::LoopBackControl)->is_Load())
C->set_major_progress();
+ // Moved a barrier around the loop, 'en-registering' something.
+ if (n_blk->is_Loop() && n->is_ShenandoahBarrier() &&
+ !phi->in(LoopNode::LoopBackControl)->is_ShenandoahBarrier())
+ C->set_major_progress();
+
return phi;
}
static bool merge_point_too_heavy(Compile* C, Node* region) {
// Bail out if the region and its phis have too many users.
@@ -1080,13 +1127,15 @@
Node *phi = split_thru_phi( n, n_ctrl, policy );
if( !phi ) return;
// Found a Phi to split thru!
// Replace 'n' with the new phi
+ assert(n->Opcode() != Op_ShenandoahWriteBarrier, "not with write barriers yet");
_igvn.replace_node( n, phi );
// Now split the bool up thru the phi
+ assert(bol->Opcode() != Op_ShenandoahWriteBarrier, "not with write barriers yet");
Node *bolphi = split_thru_phi( bol, n_ctrl, -1 );
guarantee(bolphi != NULL, "null boolean phi node");
_igvn.replace_node( bol, bolphi );
assert( iff->in(1) == bolphi, "" );
@@ -1094,10 +1143,11 @@
if( bolphi->Value(&_igvn)->singleton() )
return;
// Conditional-move? Must split up now
if( !iff->is_If() ) {
+ assert(iff->Opcode() != Op_ShenandoahWriteBarrier, "not with write barriers yet");
Node *cmovphi = split_thru_phi( iff, n_ctrl, -1 );
_igvn.replace_node( iff, cmovphi );
return;
}
@@ -1227,11 +1277,11 @@
// tried setting control edges on the x's to force them to
// not combine, but the matching gets worried when it tries
// to fold a StoreP and an AddP together (as part of an
// address expression) and the AddP and StoreP have
// different controls.
- if (!x->is_Load() && !x->is_DecodeNarrowPtr()) _igvn._worklist.yank(x);
+ if (!x->is_Load() && !x->is_DecodeNarrowPtr() && !x->is_ShenandoahBarrier()) _igvn._worklist.yank(x);
}
_igvn.remove_dead_node(n);
}
}
}
@@ -1500,10 +1550,20 @@
// Step 1: Clone the loop body. Make the old->new mapping.
uint i;
for( i = 0; i < loop->_body.size(); i++ ) {
Node *old = loop->_body.at(i);
+#ifdef ASSERT
+ if (old->Opcode() == Op_ShenandoahWriteBarrier) {
+ Node* memproj = old->find_out_with(Op_ShenandoahWBMemProj);
+ assert(memproj == NULL || (loop->is_member(get_loop(has_ctrl(memproj) ? get_ctrl(memproj) : memproj))), "WB's mem-proj must be in loop too");
+ }
+ if (old->Opcode() == Op_ShenandoahWBMemProj) {
+ Node* wb = old->in(0);
+ assert(loop->is_member(get_loop(has_ctrl(wb) ? get_ctrl(wb) : wb)), "WB must be in loop too");
+ }
+#endif
Node *nnn = old->clone();
old_new.map( old->_idx, nnn );
if (C->do_vector_loop()) {
cm.verify_insert_and_clone(old, nnn, cm.clone_idx());
}
@@ -1690,24 +1750,25 @@
// merge point. NOW we do need a Phi here. Each loop exit value
// is now merged with the peeled body exit; each exit gets its own
// private Phi and those Phis need to be merged here.
Node *phi;
if( prev->is_Region() ) {
- if( idx == 0 ) { // Updating control edge?
+ if( idx == 0 && use->Opcode() != Op_ShenandoahWBMemProj) { // Updating control edge?
phi = prev; // Just use existing control
} else { // Else need a new Phi
phi = PhiNode::make( prev, old );
// Now recursively fix up the new uses of old!
- for( uint i = 1; i < prev->req(); i++ ) {
+ uint first = use->Opcode() != Op_ShenandoahWBMemProj ? 1 : 0;
+ for( uint i = first; i < prev->req(); i++ ) {
worklist.push(phi); // Onto worklist once for each 'old' input
}
}
} else {
// Get new RegionNode merging old and new loop exits
prev = old_new[prev->_idx];
assert( prev, "just made this in step 7" );
- if( idx == 0 ) { // Updating control edge?
+ if( idx == 0 && use->Opcode() != Op_ShenandoahWBMemProj) { // Updating control edge?
phi = prev; // Just use existing control
} else { // Else need a new Phi
// Make a new Phi merging data values properly
phi = PhiNode::make( prev, old );
phi->set_req( 1, nnn );
@@ -2186,10 +2247,11 @@
//------------------------------ clone_for_use_outside_loop -------------------------------------
// clone "n" for uses that are outside of loop
int PhaseIdealLoop::clone_for_use_outside_loop( IdealLoopTree *loop, Node* n, Node_List& worklist ) {
int cloned = 0;
assert(worklist.size() == 0, "should be empty");
+ assert(n->Opcode() != Op_ShenandoahWriteBarrier, "not with write barriers yet");
for (DUIterator_Fast jmax, j = n->fast_outs(jmax); j < jmax; j++) {
Node* use = n->fast_out(j);
if( !loop->is_member(get_loop(has_ctrl(use) ? get_ctrl(use) : use)) ) {
worklist.push(use);
}
@@ -2202,10 +2264,11 @@
if (use->in(j) == n) break;
}
assert(j < use->req(), "must be there");
// clone "n" and insert it between the inputs of "n" and the use outside the loop
+ assert(n->Opcode() != Op_ShenandoahWriteBarrier, "not with write barriers");
Node* n_clone = n->clone();
_igvn.replace_input_of(use, j, n_clone);
cloned++;
Node* use_c;
if (!use->is_Phi()) {
@@ -2248,10 +2311,11 @@
worklist.push(use);
}
}
if (worklist.size() > 0) {
// clone "n" and insert it between inputs of "n" and the use
+ assert(n->Opcode() != Op_ShenandoahWriteBarrier, "not with write barriers");
Node* n_clone = n->clone();
loop->_body.push(n_clone);
_igvn.register_new_node_with_optimizer(n_clone);
set_ctrl(n_clone, get_ctrl(n));
sink_list.push(n_clone);
< prev index next >