/*
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*
*/
#include "precompiled.hpp"
#include "memory/allocation.inline.hpp"
#include "opto/callnode.hpp"
#include "opto/connode.hpp"
#include "opto/loopnode.hpp"
//------------------------------split_thru_region------------------------------
// Split Node 'n' through merge point.
}
r->init_req(i, x);
}
// Record region
return r;
}
//------------------------------split_up---------------------------------------
// Split block-local op up through the phis to empty the current block
if( n->is_CFG() ) {
return false;
}
return false; // Not block local
if( n->is_Phi() ) return false; // Local PHIs are expected
// Recursively split-up inputs
// Got split recursively and self went dead?
if (n->outcnt() == 0)
return true;
}
}
// Check for needing to clone-up a compare. Can't do that, it forces
// another (nested) split-if transform. Instead, clone it "down".
if( n->is_Cmp() ) {
// sequence can have no other users and it must all reside in the split-if
// private, per-use versions of the Cmp and Bool are made. These sink to
// the CMove block. If the CMove is in the split-if block, then in the
// Must clone down
#ifndef PRODUCT
if( PrintOpto && VerifyLoopOptimizations ) {
n->dump();
}
#endif
// Clone down any block-local BoolNode uses of this CmpNode
continue;
}
}
// Recursively sink any BoolNode
#ifndef PRODUCT
if( PrintOpto && VerifyLoopOptimizations ) {
}
#endif
// Uses are either IfNodes or CMoves
// Get control block of either the CMove or the If input
}
--i;
}
}
// Clone down this CmpNode
}
_igvn.remove_dead_node( n );
return true;
}
}
// See if splitting-up a Store. Any anti-dep loads must go up as
// well. An anti-dep load might be in the wrong block, because in
// memory to be alive twice. This only works if we do the same
// operations on anti-dep loads as we do their killing stores.
// Get store's memory slice
// Get memory-phi anti-dep loads will be using
// Hoist any anti-dep load to the splitting block;
// it will then "split-up".
if( load->is_Load() && alias_idx == C->get_alias_index(_igvn.type(load->in(MemNode::Address))->is_ptr()) )
}
}
// Found some other Node; must clone it up
#ifndef PRODUCT
if( PrintOpto && VerifyLoopOptimizations ) {
n->dump();
}
#endif
// ConvI2L may have type information on it which becomes invalid if
// it moves up in the graph so change any clones so widen the type
// to TypeLong::INT when pushing it up.
}
// Now actually split-up this guy. One copy per control path merging.
// Widen the type of the ConvI2L when pushing up.
}
}
}
// Announce phi to optimizer
// Remove cloned-up value from optimizer; use phi instead
// (There used to be a self-recursive call to split_up() here,
// but it is not needed. All necessary forward walking is done
// by do_split_if() below.)
return true;
}
//------------------------------register_new_node------------------------------
}
//------------------------------small_cache------------------------------------
};
//------------------------------spinup-----------------------------------------
// "Spin up" the dominator tree, starting at the use site and stopping when we
// find the post-dominating point.
// We must be at the merge point which post-dominates 'new_false' and
// 'new_true'. Figure out which edges into the RegionNode eventually lead up
// to false and which to true. Put in a PhiNode to merge values; plug in
// the appropriate false-arm or true-arm values. If some path leads to the
// original IF, then insert a Phi recursively.
Node *PhaseIdealLoop::spinup( Node *iff_dom, Node *new_false, Node *new_true, Node *use_blk, Node *def, small_cache *cache ) {
return use_blk;
// Here's the "spinup" the dominator tree loop. Do a cache-check
// along the way, in case we've come this way before.
while( n != iff_dom ) { // Found post-dominating point?
prior_n = n;
n = idom(n); // Search higher
if( s ) return s; // Cache hit!
}
} else {
// This method handles both control uses (looking for Regions) or data
// uses (looking for Phis). If looking for a control use, then we need
// to insert a Region instead of a Phi; however Regions always exist
// previously (the hash_find_insert below would always hit) so we can
// return the existing Region.
} else {
// Need a Phi here
// Search for both true and false on all paths till find one.
if( t ) { // See if we already have this one
// phi_post will not be used, so kill it
phi_post = t;
} else {
}
}
}
// Update cache everywhere
n = use_blk; // Get path input
// Spin-up the idom tree again, basically doing path-compression.
// Insert cache entries along the way, so that if we ever hit this
// point in the IDOM tree again we'll stop immediately on a cache hit.
while( n != iff_dom ) { // Found post-dominating point?
prior_n = n;
n = idom(n); // Search higher
} // End of while not gone high enough
return phi_post;
}
//------------------------------find_use_block---------------------------------
// Find the block a USE is in. Normally USE's are in the same block as the
// using instruction. For Phi-USE's, the USE is in the predecessor block
// along the corresponding path.
Node *PhaseIdealLoop::find_use_block( Node *use, Node *def, Node *old_false, Node *new_false, Node *old_true, Node *new_true ) {
// CFG uses are their own block
return use;
// Grab the first Phi use; there may be many.
// Each will be handled as a separate iteration of
// the "while( phi->outcnt() )" loop.
uint j;
break;
}
// Normal (non-phi) use
// Some uses are directly attached to the old (and going away)
// false and true branches.
}
}
}
return use_blk;
}
//------------------------------handle_use-------------------------------------
// Handle uses of the merge point. Basically, split-if makes the merge point
// go away so all uses of the merge point must go away as well. Most block
// local uses have already been split-up, through the merge point. Uses from
// far below the merge point can't always be split up (e.g., phi-uses are
// pinned) and it makes too much stuff live. Instead we use a path-based
// solution to move uses down.
//
// If the use is along the pre-split-CFG true branch, then the new use will
// be from the post-split-CFG true merge point. Vice-versa for the false
// path. Some uses will be along both paths; then we sink the use to the
// post-dominating location; we may need to insert a Phi there.
void PhaseIdealLoop::handle_use( Node *use, Node *def, small_cache *cache, Node *region_dom, Node *new_false, Node *new_true, Node *old_false, Node *old_true ) {
if( !use_blk ) return; // He's dead, Jim
// Walk up the dominator tree until I hit either the old IfFalse, the old
// IfTrue or the old If. Insert Phis where needed.
// Found where this USE goes. Re-point him.
uint i;
break;
}
//------------------------------do_split_if------------------------------------
// Found an If getting its condition-code input from a Phi in the same block.
// Split thru the Region.
#ifndef PRODUCT
if( PrintOpto && VerifyLoopOptimizations )
if (TraceLoopOpts) {
}
#endif
C->set_major_progress();
// We are going to clone this test (and the control flow with it) up through
// the incoming merge point. We need to empty the current basic block.
// Clone any instructions which must be in this block up through the merge
// point.
DUIterator i, j;
bool progress = true;
while (progress) {
progress = false;
if( n == region ) continue;
// The IF to be split is OK.
if( n == iff ) continue;
if( !n->is_Phi() ) { // Found pinned memory op or such
i = region->refresh_out_pos(i);
progress = true;
}
continue;
}
// Recursively split up all users of a Phi
// If m is dead, throw it away, and declare progress
// fall through
}
// fall through
} else {
continue;
}
// Something unpredictable changed.
// Tell the iterators to refresh themselves, and rerun the loop.
i = region->refresh_out_pos(i);
j = region->refresh_out_pos(j);
progress = true;
}
}
}
// Now we have no instructions in the block containing the IF.
// Split the IF.
// paths. This makes 'new_iff' go dead.
// Replace 'If' projection of a Region with a Region of
// 'If' projections.
// Setup dominator info
// Check for splitting loop tails
// Replace in the graph with lazy-update mechanism
// Record bits for later xforms
} else {
}
}
// Lazy replace IDOM info with the region's dominator
// Now make the original merge point go dead, by handling all its uses.
// Preload some control flow in region-cache
// Now handle all uses of the splitting block
continue; // No roll-back of DUIterator
// Need a per-def cache. Phi represents a def, so make a cache
// Inspect all Phi uses to make the Phi go dead
// Compute the new DEF for this USE. New DEF depends on the path
// taken from the original DEF to the USE. The new DEF may be some
// collection of PHI's merging values from different paths. The Phis
// inserted depend only on the location of the USE. We use a
// 2-element cache to handle multiple uses from the same block.
} // End of while phi has uses
// Remove the dead Phi
} else {
// Random memory op guarded by Region. Compute new DEF for USE.
}
// Every path above deletes a use of the region, except for the region
// self-cycle (which is needed by handle_use calling find_use_block
// calling get_ctrl calling get_ctrl_no_update looking for dead
// regions). So roll back the DUIterator innards.
--k;
} // End of while merge point has phis
// Any leftover bits in the splitting block must not have depended on local
// Phi inputs (these have already been split-up). Hence it's safe to hoist
// these guys to the dominating point.
#ifndef PRODUCT
if( VerifyLoopOptimizations ) verify();
#endif
}