/*
* 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/cfgnode.hpp"
#include "opto/connode.hpp"
#include "opto/idealGraphPrinter.hpp"
#include "opto/loopnode.hpp"
#include "opto/machnode.hpp"
#include "opto/opcodes.hpp"
#include "opto/phaseX.hpp"
#include "opto/regalloc.hpp"
#include "opto/rootnode.hpp"
//=============================================================================
//------------------------------NodeHash---------------------------------------
_total_insert_probes(0), _total_inserts(0),
_insert_probes(0), _grows(0) {
// _sentinel must be in the current node space
}
//------------------------------NodeHash---------------------------------------
_total_insert_probes(0), _total_inserts(0),
_insert_probes(0), _grows(0) {
// _sentinel must be in the current node space
}
//------------------------------NodeHash---------------------------------------
// just copy in all the fields
*this = *nh;
// nh->_sentinel must be in the current node space
}
// just copy in all the fields
*this = *nh;
// nh->_sentinel must be in the current node space
}
//------------------------------hash_find--------------------------------------
// Find in hash table
// ((Node*)n)->set_hash( n->hash() );
debug_only( _lookup_misses++ );
return NULL;
}
debug_only( _look_probes++ );
if( !k ) { // ?Miss?
debug_only( _lookup_misses++ );
return NULL; // Miss!
}
while( 1 ) { // While probing hash table
goto collision; // "goto" is a speed hack...
if( n->cmp(*k) ) { // Check for any special bits
debug_only( _lookup_hits++ );
return k; // Hit!
}
}
debug_only( _look_probes++ );
if( !k ) { // ?Miss?
debug_only( _lookup_misses++ );
return NULL; // Miss!
}
}
return NULL;
}
//------------------------------hash_find_insert-------------------------------
// Find in hash table, insert if not already present
// Used to preserve unique entries in hash table
// n->set_hash( );
debug_only( _lookup_misses++ );
return NULL;
}
debug_only( _look_probes++ );
if( !k ) { // ?Miss?
debug_only( _lookup_misses++ );
check_grow(); // Grow table if insert hit limit
return NULL; // Miss!
}
else if( k == _sentinel ) {
}
while( 1 ) { // While probing hash table
goto collision; // "goto" is a speed hack...
if( n->cmp(*k) ) { // Check for any special bits
debug_only( _lookup_hits++ );
return k; // Hit!
}
}
debug_only( _look_probes++ );
if( !k ) { // ?Miss?
debug_only( _lookup_misses++ );
check_grow(); // Grow table if insert hit limit
return NULL; // Miss!
}
else if( first_sentinel == 0 && k == _sentinel ) {
}
}
return NULL;
}
//------------------------------hash_insert------------------------------------
// Insert into hash table
// // "conflict" comments -- print nodes that conflict
// bool conflict = false;
// n->set_hash();
return;
}
check_grow();
while( 1 ) { // While probing hash table
debug_only( _insert_probes++ );
if( !k || (k == _sentinel) ) break; // Found a slot
assert( k != n, "already inserted" );
// if( PrintCompilation && PrintOptoStatistics && Verbose ) { tty->print(" conflict: "); k->dump(); conflict = true; }
}
// if( conflict ) { n->dump(); }
}
//------------------------------hash_delete------------------------------------
// Replace in hash table with sentinel
Node *k;
debug_only( _delete_misses++ );
return false;
}
for( ; /* (k != NULL) && (k != _sentinel) */; ) {
debug_only( counter++ );
debug_only( _delete_probes++ );
if( !k ) { // Miss?
debug_only( _delete_misses++ );
#ifdef ASSERT
if( VerifyOpto ) {
}
#endif
return false; // Miss! Not in chain
}
else if( n == k ) {
debug_only( _delete_hits++ );
return true;
}
else {
// collision: move through table with prime offset
}
}
return false;
}
//------------------------------round_up---------------------------------------
// Round up to nearest power of 2
x += (x>>2); // Add 25% slop
if( x <16 ) return 16; // Small stuff
uint i=16;
while( i < x ) i <<= 1; // Double to fit
return i; // Return hash table size
}
//------------------------------grow-------------------------------------------
// Grow _table to next power of 2 and insert old entries
// Record old state
// Construct new table with twice the space
_grows++;
_inserts = 0;
_insert_probes = 0;
// Insert old entries into the new table
if( !m || m == _sentinel ) continue;
hash_insert(m);
}
}
//------------------------------clear------------------------------------------
// Clear all entries in _table to NULL but keep storage
#ifdef ASSERT
// Unlock all nodes upon removal from table.
if (!n || n == _sentinel) continue;
n->exit_hash_lock();
}
#endif
}
//-----------------------remove_useless_nodes----------------------------------
// Remove useless nodes from value table,
// implementation does not depend on hash function
// Dead nodes in the hash table inherited from GVN should not replace
// existing nodes, remove dead nodes.
}
}
}
#ifndef PRODUCT
//------------------------------dump-------------------------------------------
// Dump statistics for the hash table
if (WizardMode) {
if (_table[i])
}
}
tty->print(" %dp/(%dh+%dm) (%8.2f probes/lookup)\n", _look_probes, _lookup_hits, _lookup_misses, (double)_look_probes/(_lookup_hits+_lookup_misses));
tty->print(" %dp/%di (%8.2f probes/insert)\n", _total_insert_probes, _total_inserts, (double)_total_insert_probes/_total_inserts);
// sentinels increase lookup cost, but not insert cost
}
}
// Find an entry by its index value
if( !m || m == _sentinel ) continue;
}
return NULL;
}
#endif
#ifdef ASSERT
// Unlock all nodes upon destruction of table.
}
// Unlock all nodes upon replacement of table.
if (&nh == this) return;
// Do not increment hash_lock counts again.
// Instead, be sure we never again use the source table.
}
#endif
//=============================================================================
//------------------------------PhaseRemoveUseless-----------------------------
// 1) Use a breadthfirst walk to collect useful nodes reachable from root.
PhaseRemoveUseless::PhaseRemoveUseless( PhaseGVN *gvn, Unique_Node_List *worklist ) : Phase(Remove_Useless),
// Implementation requires 'UseLoopSafepoints == true' and an edge from root
// to each SafePointNode at a backward branch. Inserted in add_safepoint().
if( !UseLoopSafepoints || !OptoRemoveUseless ) return;
// Identify nodes that are reachable from below, useful.
// Update dead node list
// Remove all useless nodes from PhaseValues' recorded types
// Must be done before disconnecting nodes to preserve hash-table-invariant
// Remove all useless nodes from future worklist
// Disconnect 'useless' nodes that are adjacent to useful nodes
// Remove edges from "root" to each SafePoint at a backward branch.
// They were inserted during parsing (see add_safepoint()) to make infinite
// loops without calls or exceptions visible to root, i.e., useful.
if( n != NULL && n->is_SafePoint() ) {
--i;
}
}
}
}
//=============================================================================
//------------------------------PhaseTransform---------------------------------
{
#ifndef PRODUCT
set_allow_progress(true);
#endif
// Force allocation for currently existing nodes
}
//------------------------------PhaseTransform---------------------------------
{
#ifndef PRODUCT
set_allow_progress(true);
#endif
// Force allocation for currently existing nodes
}
//------------------------------PhaseTransform---------------------------------
// Initialize with previously generated type information
{
#ifndef PRODUCT
set_allow_progress(true);
#endif
}
}
//--------------------------------find_int_type--------------------------------
// Call type_or_null(n) to determine node's type since we might be in
// parse phase and call n->Value() may return wrong type.
// (For example, a phi node at the beginning of loop parsing is not ready.)
const Type* t = type_or_null(n);
return t->isa_int();
}
//-------------------------------find_long_type--------------------------------
// (See comment above on type_or_null.)
const Type* t = type_or_null(n);
return t->isa_long();
}
#ifndef PRODUCT
}
return;
}
}
//------------------------------dump_types-------------------------------------
}
//------------------------------dump_nodes_and_types---------------------------
}
//------------------------------dump_nodes_and_types_recur---------------------
void PhaseTransform::dump_nodes_and_types_recur( const Node *n, uint depth, bool only_ctrl, VectorSet &visited) {
if( !n ) return;
if( depth == 0 ) return;
}
n->dump();
if (type_or_null(n) != NULL) {
}
}
#endif
//=============================================================================
//------------------------------PhaseValues------------------------------------
// Set minimum table size to "255"
PhaseValues::PhaseValues( Arena *arena, uint est_max_size ) : PhaseTransform(arena, GVN), _table(arena, est_max_size) {
NOT_PRODUCT( clear_new_values(); )
}
//------------------------------PhaseValues------------------------------------
// Set minimum table size to "255"
NOT_PRODUCT( clear_new_values(); )
}
//------------------------------PhaseValues------------------------------------
// Used by +VerifyOpto. Clear out hash table but copy _types array.
NOT_PRODUCT( clear_new_values(); )
}
//------------------------------~PhaseValues-----------------------------------
#ifndef PRODUCT
PhaseValues::~PhaseValues() {
// Statistics for value progress and efficiency
if( made_transforms() != 0 ) {
} else {
}
}
}
#endif
//------------------------------makecon----------------------------------------
switch (t->base()) { // fast paths
}
if (t->is_zero_type())
return zerocon(t->basic_type());
return uncached_makecon(t);
}
//--------------------------uncached_makecon-----------------------------------
// Make an idealized constant - one of ConINode, ConPNode, etc.
if (k == NULL) {
set_type(x, t); // Missed, provide type mapping
}
} else {
x->destruct(); // Hit, destroy duplicate constant
x = k; // use existing constant
}
return x;
}
//------------------------------intcon-----------------------------------------
// Fast integer constant. Same as "transform(new ConINode(TypeInt::make(i)))"
// Small integer? Check cache! Check that cached node is not dead
return icon;
}
return icon;
}
//------------------------------longcon----------------------------------------
// Fast long constant.
// Small integer? Check cache! Check that cached node is not dead
return lcon;
}
return lcon;
}
//------------------------------zerocon-----------------------------------------
// Fast zero or null constant. Same as "transform(ConNode::make(Type::get_zero_type(bt)))"
return zcon;
return zcon;
}
//=============================================================================
//------------------------------transform--------------------------------------
// Return a node which computes the same function as this node, but in a
// faster or cheaper fashion.
return transform_no_reclaim(n);
}
//------------------------------transform--------------------------------------
// Return a node which computes the same function as this node, but
// in a faster or cheaper fashion.
NOT_PRODUCT( set_transforms(); )
// Apply the Ideal call in a loop until it no longer applies
Node *k = n;
while( 1 ) {
if( !i ) break;
k = i;
}
// If brand new node, make space in type array.
// Since I just called 'Value' to compute the set of run-time values
// for this Node, and 'Value' is non-local (and therefore expensive) I'll
// cache Value. Later requests for the local phase->type of this Node can
// use the cached Value instead of suffering with 'bottom_type'.
if (type_or_null(k) != t) {
#ifndef PRODUCT
// Do not count initial visit to node as a transformation
if (type_or_null(k) == NULL) {
set_progress();
}
#endif
set_type(k, t);
// If k is a TypeNode, capture any more-precise type permanently into Node
k->raise_bottom_type(t);
}
NOT_PRODUCT( set_progress(); )
return makecon(t); // Turn into a constant
}
// Now check for Identities
if( i != k ) { // Found? Return replacement!
NOT_PRODUCT( set_progress(); )
return i;
}
// Global Value Numbering
i = hash_find_insert(k); // Insert if new
if( i && (i != k) ) {
// Return the pre-existing node
NOT_PRODUCT( set_progress(); )
return i;
}
// Return Idealized original
return k;
}
#ifdef ASSERT
//------------------------------dead_loop_check--------------------------------
// Check for a simple dead loop when a data node references itself directly
// or through an other data node excluding cons and phis.
// Phi may reference itself in a loop
// Do 2 levels check and only data inputs.
bool no_dead_loop = true;
if (in == n) {
no_dead_loop = false;
no_dead_loop = false;
}
}
}
}
}
#endif
//=============================================================================
//------------------------------PhaseIterGVN-----------------------------------
// Initialize hash table to fresh and clean for +VerifyOpto
PhaseIterGVN::PhaseIterGVN( PhaseIterGVN *igvn, const char *dummy ) : PhaseGVN(igvn,dummy), _worklist( ),
_delay_transform(false) {
}
//------------------------------PhaseIterGVN-----------------------------------
// Initialize with previous PhaseIterGVN info; used by PhaseCCP
{
}
//------------------------------PhaseIterGVN-----------------------------------
// Initialize with previous PhaseGVN info from Parser
_delay_transform(false)
{
// Dead nodes in the hash table inherited from GVN were not treated as
// roots during def-use info creation; hence they represent an invisible
// use. Clear them out.
if( n->is_top() ) continue;
assert( false, "Parse::remove_useless_nodes missed this node");
hash_delete(n);
}
}
// Any Phis or Regions on the worklist probably had uses that could not
// make more progress because the uses were made while the Phis and Regions
// were in half-built states. Put all uses of Phis and Regions on worklist.
n->is_Type() ||
n->is_Mem() )
}
}
#ifndef PRODUCT
if (C->unique() < 1000 ||
}
for ( int i = 0; i < _verify_window_size; i++ ) {
Node* n = _verify_window[i];
if ( n == NULL ) continue;
--i; continue;
}
// Typical fanout is 1-2, so this call visits about 6 nodes.
}
}
#endif
//------------------------------init_worklist----------------------------------
// Initialize worklist for each node.
if( m ) init_worklist(m);
}
}
//------------------------------optimize---------------------------------------
#ifndef PRODUCT
{
_verify_counter = 0;
_verify_full_passes = 0;
for ( int i = 0; i < _verify_window_size; i++ ) {
_verify_window[i] = NULL;
}
}
#endif
#ifdef ASSERT
#endif
// Pull from worklist; transform node;
// If node has changed: update edge info and put uses on worklist.
"out of nodes optimizing method")) {
return;
}
if (++loop_count >= K * C->unique()) {
assert(false, "infinite loop in PhaseIterGVN::optimize");
C->record_method_not_compilable("infinite loop in PhaseIterGVN::optimize");
return;
}
#ifdef ASSERT
if (n == prev) {
if (++rep_cnt > 3) {
n->dump(4);
assert(false, "loop in Ideal transformation");
}
} else {
rep_cnt = 0;
}
prev = n;
#endif
if (TraceIterativeGVN && Verbose) {
NOT_PRODUCT( n->dump(); )
}
if (n->outcnt() != 0) {
#ifndef PRODUCT
#endif //PRODUCT
#ifndef PRODUCT
if (TraceIterativeGVN) {
if (nn != n) {
// print old node
}
n->dump();
}
} else if (nn != n) {
} else {
}
} else {
}
}
}
}
}
if( VerifyIterativeGVN && nn != n ) {
}
#endif
} else if (!n->is_top()) {
remove_dead_node(n);
}
}
#ifndef PRODUCT
C->verify_graph_edges();
if( VerifyOpto && allow_progress() ) {
// Must turn off allow_progress to enable assert and break recursion
{ // Check if any progress was missed using IterGVN
// Def-Use info enables transformations not attempted in wash-pass
// Null-check elision -- may not have reached fixpoint
// do not propagate to dominated nodes
// Fill worklist completely
igvn2.set_allow_progress(false);
igvn2.set_allow_progress(true);
}
}
if ( VerifyIterativeGVN && PrintOpto ) {
if ( _verify_counter == _verify_full_passes )
else
}
#endif
}
//------------------register_new_node_with_optimizer---------------------------
// Register a new node with the optimizer. Update the types array, the def-use
// info. Put on worklist.
set_type_bottom(n);
return n;
}
//------------------------------transform--------------------------------------
// Non-recursive: idealize Node 'n' with respect to its inputs and its value
if (_delay_transform) {
// Register the node but don't optimize for now
return n;
}
// If brand new node, make space in type array, and give it a type.
if (type_or_null(n) == NULL) {
set_type_bottom(n);
}
return transform_old(n);
}
//------------------------------transform_old----------------------------------
#ifndef PRODUCT
#endif
// Remove 'n' from hash table in case it gets modified
_table.hash_delete(n);
if( VerifyIterativeGVN ) {
}
// Apply the Ideal call in a loop until it no longer applies
Node *k = n;
#ifndef PRODUCT
if( VerifyIterativeGVN )
verify_step(k);
if( i && VerifyOpto ) {
if( !allow_progress() ) {
// Switched input to left side because this is the only use
// This IF is dead because it is dominated by an equivalent IF When
// dominating if changed, info is not propagated sparsely to 'this'
// Propagating this info further will spuriously identify other
// progress.
return i;
} else
set_progress();
} else
set_progress();
}
#endif
while( i ) {
#ifndef PRODUCT
debug_only( loop_count++; )
#endif
assert((i->_idx >= k->_idx) || i->is_top(), "Idealize should return new nodes, use Identity to return old nodes");
// Made a change; put users of original Node on worklist
add_users_to_worklist( k );
// Replacing root of transform tree?
if( k != i ) {
// Make users of old Node now use new.
subsume_node( k, i );
k = i;
}
// Try idealizing again
i = k->Ideal(this, /*can_reshape=*/true);
#ifndef PRODUCT
if( VerifyIterativeGVN )
verify_step(k);
if( i && VerifyOpto ) set_progress();
#endif
}
// If brand new node, make space in type array.
// See what kind of values 'k' takes on at runtime
// Since I just called 'Value' to compute the set of run-time values
// for this Node, and 'Value' is non-local (and therefore expensive) I'll
// cache Value. Later requests for the local phase->type of this Node can
// use the cached Value instead of suffering with 'bottom_type'.
if (t != type_or_null(k)) {
NOT_PRODUCT( set_progress(); )
set_type(k, t);
// If k is a TypeNode, capture any more-precise type permanently into Node
k->raise_bottom_type(t);
// Move users of node to worklist
add_users_to_worklist( k );
}
// If 'k' computes a constant, replace it with a constant
NOT_PRODUCT( set_progress(); )
add_users_to_worklist( k );
return con;
}
// Now check for Identities
i = k->Identity(this); // Look for a nearby replacement
if( i != k ) { // Found? Return replacement!
NOT_PRODUCT( set_progress(); )
add_users_to_worklist( k );
subsume_node( k, i ); // Everybody using k now uses i
return i;
}
// Global Value Numbering
i = hash_find_insert(k); // Check for pre-existing node
if( i && (i != k) ) {
// Return the pre-existing node if it isn't dead
NOT_PRODUCT( set_progress(); )
add_users_to_worklist( k );
subsume_node( k, i ); // Everybody using k now uses i
return i;
}
// Return Idealized original
return k;
}
//---------------------------------saturate------------------------------------
const Type* limit_type) const {
}
//------------------------------remove_globally_dead_node----------------------
// Kill a globally dead Node. All uses are also globally dead and are
// aggressively trimmed.
enum DeleteProgress {
};
while (_stack.is_nonempty()) {
NOT_PRODUCT( set_progress(); )
if (progress_state == PROCESS_INPUTS) {
// After following inputs, continue to outputs
bool recurse = false;
// Remove from hash table
// Smash all inputs to 'dead', isolating him completely
recurse = true;
in->has_special_unique_user()) {
i++;
i++;
}
}
}
// A Load that directly follows an InitializeNode is
// going away. The Stores that follow are candidates
// again to be captured by the InitializeNode.
if (n->is_Store()) {
}
}
}
} // if (in != NULL && in != C->top())
} // for (uint i = 0; i < dead->req(); i++)
if (recurse) {
continue;
}
} // if (!dead->is_Con())
} // if (progress_state == PROCESS_INPUTS)
// Aggressively kill globally dead uses
// (Rather than pushing all the outs at once, we push one at a time,
// plus the parent to resume later, because of the indefinite number
// of edge deletions per loop trip.)
// Recursively remove output edges
} else {
// Finished disconnecting all input and output edges.
// Remove dead node from iterative worklist
// Constant node that has no out-edges and has only one in-edge from
// root is usually dead. However, sometimes reshaping walk makes
// it reachable by adding use edges. So, we will NOT count Con nodes
// as dead to be conservative about the dead node count at any
// given time.
}
C->remove_macro_node(dead);
}
if (dead->is_expensive()) {
}
}
} // while (_stack.is_nonempty())
}
//------------------------------subsume_node-----------------------------------
// Remove users from node 'old' and add them to node 'nn'.
// Copy debug or profile information to the new version:
// Move users of node 'old' to node 'nn'
// use might need re-hashing (but it won't if it's a new node)
// Update use-def info as well
// We remove all occurrences of old within use->in,
// so as to avoid rehashing any node more than once.
// The hash table probe swamps any outer loop overhead.
++num_edges;
}
}
// Insert into GVN hash table if unique
// If a duplicate, 'use' will be cleaned up when pulled off worklist
if( is_in_table ) {
}
i -= num_edges; // we deleted 1 or more copies of this edge
}
// Smash all inputs to 'old', isolating him completely
remove_dead_node( old );
#ifndef PRODUCT
if( VerifyIterativeGVN ) {
for ( int i = 0; i < _verify_window_size; i++ ) {
if ( _verify_window[i] == old )
_verify_window[i] = nn;
}
}
#endif
}
//------------------------------add_users_to_worklist--------------------------
}
}
// Move users of node to worklist
// If we changed the receiver type to a call, we need to revisit
// the Catch following the call. It's looking for a non-NULL
// receiver to know when to enable the regular fall-through path
// in addition to the NullPtrException path.
if (p != NULL) {
}
}
// Look for the 'is_x2logic' pattern: "x ? : 0 : 1" and put the
// phi merging either 0 or 1 onto the worklist
}
}
}
}
}
// If changed Cast input, check Phi users for simple cycles
if (u->is_Phi())
}
}
// If changed LShift inputs, check RShift users for useless sign-ext
if( use_op == Op_LShiftI ) {
if (u->Opcode() == Op_RShiftI)
}
}
// If changed AddP inputs, check Stores for loop invariant
if (u->is_Mem())
}
}
// If changed initialization activity, check dependent Stores
}
}
if (use_op == Op_Initialize) {
}
}
}
//=============================================================================
#ifndef PRODUCT
#endif
//------------------------------PhaseCCP---------------------------------------
// Conditional Constant Propagation, ala Wegman & Zadeck
NOT_PRODUCT( clear_constants(); )
// Clear out _nodes from IterGVN. Must be clear to transform call.
analyze();
}
#ifndef PRODUCT
//------------------------------~PhaseCCP--------------------------------------
inc_invokes();
}
#endif
#ifdef ASSERT
break;
break;
}
return true;
}
#endif //ASSERT
//------------------------------analyze----------------------------------------
// Initialize all types to TOP, optimistic analysis
for (int i = C->unique() - 1; i >= 0; i--) {
}
// Push root onto worklist
// Pull from worklist; compute new value; push changes out.
// This loop is the meat of CCP.
if (t != type(n)) {
#ifndef PRODUCT
if( TracePhaseCCP ) {
t->dump();
n->dump();
}
#endif
set_type(n, t);
if( m->is_Region() ) { // New path to Region? Must recheck Phis too
}
}
// If we changed the receiver type to a call, we need to revisit
// the Catch following the call. It's looking for a non-NULL
// receiver to know when to enable the regular fall-through path
// in addition to the NullPtrException path
if (m->is_Call()) {
}
}
}
}
}
}
//------------------------------do_transform-----------------------------------
// Top level driver for the recursive transformer
// Correct leaves of new-space Nodes; they point to old-space.
}
//------------------------------transform--------------------------------------
// Given a Node in old-space, clone him into new-space.
// Convert any of his old-space children into new-space children.
return new_node; // Been there, done that, return old answer
// Allocate stack of size _nodes.Size()/2 to avoid frequent realloc
while ( trstack.is_nonempty() ) {
}
}
}
}
return new_node;
}
//------------------------------transform_once---------------------------------
// For PhaseCCP, transformation is IDENTITY unless Node computed a constant.
// Constant? Use constant Node instead
if( t->singleton() ) {
// cache my top node on the Compile instance
}
}
if( !n->is_Con() ) {
NOT_PRODUCT( inc_constants(); )
} else if( n->is_Region() ) { // Unreachable region
// Note: nn == C->top()
// Eagerly remove dead phis to avoid phis copies creation.
if( m->is_Phi() ) {
replace_node(m, nn);
--i; // deleted this phi; rescan starting with next position
}
}
}
}
return nn;
}
// If x is a TypeNode, capture any more-precise type permanently into Node
if (t != n->bottom_type()) {
hash_delete(n); // changing bottom type may force a rehash
n->raise_bottom_type(t);
}
// Idealize graph using DU info. Must clone() into new-space.
// DU info is generally used to show profitability, progress or safety
// (but generally not needed for correctness).
// TEMPORARY fix to ensure that 2nd GVN pass eliminates NULL checks
switch( n->Opcode() ) {
case Op_FastLock: // Revisit FastLocks for lock coarsening
case Op_If:
case Op_CountedLoopEnd:
case Op_Region:
case Op_Loop:
case Op_CountedLoop:
case Op_Conv2B:
case Op_Opaque1:
case Op_Opaque2:
break;
default:
break;
}
if( nn ) {
// Put users of 'n' onto worklist for second igvn transform
return nn;
}
return n;
}
//---------------------------------saturate------------------------------------
const Type* limit_type) const {
// If so, we may have widened beyond the limit type. Clip it back down.
}
return new_type;
}
//------------------------------print_statistics-------------------------------
#ifndef PRODUCT
}
#endif
//=============================================================================
#ifndef PRODUCT
#endif
//------------------------------PhasePeephole----------------------------------
// Conditional Constant Propagation, ala Wegman & Zadeck
NOT_PRODUCT( clear_peepholes(); )
}
#ifndef PRODUCT
//------------------------------~PhasePeephole---------------------------------
PhasePeephole::~PhasePeephole() {
}
#endif
//------------------------------transform--------------------------------------
return NULL;
}
//------------------------------do_transform-----------------------------------
bool method_name_not_printed = true;
// Examine each basic block
bool block_not_printed = true;
// and each instruction within a block
// block->end_idx() not valid after PhaseRegAlloc
if( n->is_Mach() ) {
int deleted_count = 0;
// check for peephole opportunities
#ifndef PRODUCT
if( PrintOptoPeephole ) {
// Print method, first time only
if( C->method() && method_name_not_printed ) {
method_name_not_printed = false;
}
// Print this block
if( Verbose && block_not_printed) {
block_not_printed = false;
}
// Print instructions being deleted
for( int i = (deleted_count - 1); i >= 0; --i ) {
}
// Print new instruction
}
#endif
// Remove old nodes from basic block and update instruction_index
// (old nodes still exist and may have edges pointing to them
// as register allocation info is stored in the allocator using
// the node index to live range mappings.)
}
// install new node after safe_instruction_index
NOT_PRODUCT( inc_peepholes(); )
}
}
}
}
}
//------------------------------print_statistics-------------------------------
#ifndef PRODUCT
}
#endif
//=============================================================================
//------------------------------set_req_X--------------------------------------
set_req(i, n);
// old goes dead?
if( old ) {
case 0:
// Put into the worklist to kill later. We do not kill it now because the
// recursive kill will delete the current node (this) if dead-loop exists
break;
case 1:
break;
case 2:
break;
case 3:
}
break;
default:
break;
}
}
}
//-------------------------------replace_by-----------------------------------
// Using def-use info, replace one node for another. Follow the def-use info
// to all users of the OLD node. Then make all uses point to the NEW node.
uses_found++;
}
}
i -= uses_found; // we deleted 1 or more copies of this edge
}
}
//=============================================================================
//-----------------------------------------------------------------------------
if( !_max ) {
_max = 1;
}
}
//------------------------------dump-------------------------------------------
#ifndef PRODUCT
}
}
}
#endif