/*
* 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.
*
*/
#ifndef SHARE_VM_OPTO_NODE_HPP
#define SHARE_VM_OPTO_NODE_HPP
#include "libadt/vectset.hpp"
#include "opto/compile.hpp"
// Portions of code courtesy of Clifford Click
// Optimization - Graph Style
class AbstractLockNode;
class AddNode;
class AddPNode;
class AliasInfo;
class AllocateArrayNode;
class AllocateNode;
class Block;
class Block_Array;
class BoolNode;
class BoxLockNode;
class CMoveNode;
class CallDynamicJavaNode;
class CallJavaNode;
class CallLeafNode;
class CallNode;
class CallRuntimeNode;
class CallStaticJavaNode;
class CatchNode;
class CatchProjNode;
class CheckCastPPNode;
class ClearArrayNode;
class CmpNode;
class CodeBuffer;
class ConstraintCastNode;
class ConNode;
class CountedLoopNode;
class CountedLoopEndNode;
class DecodeNNode;
class EncodePNode;
class FastLockNode;
class FastUnlockNode;
class IfNode;
class IfFalseNode;
class IfTrueNode;
class InitializeNode;
class JVMState;
class JumpNode;
class JumpProjNode;
class LoadNode;
class LoadStoreNode;
class LockNode;
class LoopNode;
class MachBranchNode;
class MachCallDynamicJavaNode;
class MachCallJavaNode;
class MachCallLeafNode;
class MachCallNode;
class MachCallRuntimeNode;
class MachCallStaticJavaNode;
class MachConstantBaseNode;
class MachConstantNode;
class MachGotoNode;
class MachIfNode;
class MachNode;
class MachNullCheckNode;
class MachProjNode;
class MachReturnNode;
class MachSafePointNode;
class MachSpillCopyNode;
class MachTempNode;
class Matcher;
class MemBarNode;
class MemBarStoreStoreNode;
class MemNode;
class MergeMemNode;
class MulNode;
class MultiNode;
class MultiBranchNode;
class NeverBranchNode;
class Node;
class Node_Array;
class Node_List;
class Node_Stack;
class NullCheckNode;
class OopMap;
class ParmNode;
class PCTableNode;
class PhaseCCP;
class PhaseGVN;
class PhaseIterGVN;
class PhaseRegAlloc;
class PhaseTransform;
class PhaseValues;
class PhiNode;
class Pipeline;
class ProjNode;
class RegMask;
class RegionNode;
class RootNode;
class SafePointNode;
class SafePointScalarObjectNode;
class StartNode;
class State;
class StoreNode;
class SubNode;
class Type;
class TypeNode;
class UnlockNode;
class VectorNode;
class LoadVectorNode;
class StoreVectorNode;
class VectorSet;
extern "C" {
typedef int (*C_sort_func_t)(const void *, const void *);
}
// The type of all node counts and indexes.
// It must hold at least 16 bits, but must also be fast to load and store.
// This type, if less than 32 bits, could limit the number of possible nodes.
// (To make this type platform-specific, move to globalDefinitions_xxx.hpp.)
typedef unsigned int node_idx_t;
#ifndef OPTO_DU_ITERATOR_ASSERT
#ifdef ASSERT
#else
#define OPTO_DU_ITERATOR_ASSERT 0
#endif
#endif //OPTO_DU_ITERATOR_ASSERT
class DUIterator;
class DUIterator_Fast;
class DUIterator_Last;
#else
#endif
// Node Sentinel
// Unknown count frequency
//------------------------------Node-------------------------------------------
// Nodes define actions in the program. They create values, which have types.
// They are both vertices in a directed graph and program primitives. Nodes
// are labeled; the label is the "opcode", the primitive function in the lambda
// calculus sense that gives meaning to the Node. Node inputs are ordered (so
// that "a-b" is different from "b-a"). The inputs to a Node are the inputs to
// the Node's function. These inputs also define a Type equation for the Node.
// Solving these Type equations amounts to doing dataflow analysis.
// Control and data are uniformly represented in the graph. Finally, Nodes
// have a unique dense integer index which is used to index into side arrays
// whenever I have phase-specific information.
class Node {
friend class VMStructs;
// Lots of restrictions on cloning Nodes
public:
friend class Compile;
friend class DUIterator_Common;
friend class DUIterator;
friend class DUIterator_Fast;
friend class DUIterator_Last;
#endif
// Because Nodes come and go, I define an Arena of Node structures to pull
// from. This should allow fast access to node creation & deletion. This
// field is a local cache of a value defined in some "program fragment" for
// which these Nodes are just a part of.
// New Operator that takes a Compile pointer, this will eventually
// be the "new" New operator.
#ifdef ASSERT
#endif
return (void*)n;
}
// Delete is a NOP
void operator delete( void *ptr ) {}
// Fancy destructor; eagerly attempt to reclaim Node numberings and storage
void destruct();
// Create a new Node. Required is the number is of inputs required for
// semantic correctness.
// Create a new Node with given input edges.
// This version requires use of the "edge-count" new.
// E.g. new (C,3) FooNode( C, NULL, left, right );
// Clone an inherited Node given only the base Node type.
// Clone a Node, immediately supplying one or two new edges.
// The first and second arguments, if non-null, replace in(1) and in(2),
// respectively.
return nn;
}
private:
// Shared setup for the above constructors.
// Handles all interactions with Compile::current.
// Puts initial values in all Node fields except _idx.
// Returns the initial value for _idx, which cannot
// be initialized by assignment.
//----------------- input edge handling
protected:
friend class PhaseCFG; // Access to address of _in array elements
// Input edges are split into two categories. Required edges are required
// for semantic correctness; order is important and NULLs are allowed.
// Precedence edges are used to help determine execution order and are
// added, e.g., for scheduling purposes. They are unordered and not
// duplicated; they have no embedded NULLs. Edges from 0 to _cnt-1
// are required, from _cnt to _max-1 are precedence edges.
// Output edges are an unordered list of def-use edges which exactly
// correspond to required input edges which point from other nodes
// to this one. Thus the count of the output edges is the number of
// users of this node.
// Grow the actual input array to the next larger power-of-2 bigger than len.
// Grow the output array to the next larger power-of-2 bigger than len.
public:
// to index into auxiliary arrays of data and bitvectors.
// It is declared const to defend against inadvertant assignment,
// since it is used by clients as a naked field.
// Get the (read-only) number of input edges
// Get the (read-only) number of output edges
// Iterate over the out-edges of this node. Deletions are illegal.
inline DUIterator outs() const;
// Use this when the out array might have changed to suppress asserts.
// Does the node have an out at this position? (Used for iteration.)
inline bool has_out(DUIterator& i) const;
// Iterate over the out-edges of this node. All changes are illegal.
// Iterate over the out-edges of this node, deleting one at a time.
// The inline bodies of all these methods are after the iterator definitions.
#else
// Iterate over the out-edges of this node. Deletions are illegal.
// This iteration uses integral indexes, to decouple from array reallocations.
// Use this when the out array might have changed to suppress asserts.
// Reference to the i'th output Node. Error if out of bounds.
// Does the node have an out at this position? (Used for iteration.)
// Iterate over the out-edges of this node. All changes are illegal.
// This iteration uses a pointer internal to the out array.
// Assign a limit pointer to the reference argument:
// Return the base pointer:
return out;
}
// Iterate over the out-edges of this node, deleting one at a time.
// This iteration uses a pointer internal to the out array.
// Assign a limit pointer to the reference argument:
// Return the pointer to the start of the iteration:
}
#endif
// Reference to the i'th input Node. Error if out of bounds.
Node* in(uint i) const { assert(i < _max, err_msg_res("oob: i=%d, _max=%d", i, _max)); return _in[i]; }
// Reference to the i'th output Node. Error if out of bounds.
// Use this accessor sparingly. We are going trying to use iterators instead.
// Return the unique out edge.
// Delete out edge at position 'i' by moving last out edge to position 'i'
void raw_del_out(uint i) {
// Record that a change happened here.
#endif
// Smash the old edge so it can't be used accidentally.
}
#ifdef ASSERT
bool is_dead() const;
#endif
// Check whether node has become unreachable
// Set a required input edge, also updates corresponding output edge
"remove node from hash table before modifying it");
(*p) = n;
}
// Light version of set_req() to init inputs after node creation.
assert( i == 0 && this == n ||
is_not_dead(n), "can not use dead node");
"remove node from hash table before modifying it");
_in[i] = n;
}
// Find first occurrence of n among my edges:
// NULL out all inputs to eliminate incoming Def-Use edges.
// Return the number of edges between 'n' and 'this'
// Quickly, return true if and only if I am Compile::current()->top().
bool is_top() const {
}
// Reaffirm invariants for is_top. (Only from Compile::set_cached_top_node.)
void setup_is_top();
// Strip away casting. (It is depth-limited.)
// Return whether two Nodes are equivalent, after stripping casting.
bool eqv_uncast(const Node* n) const {
}
private:
// Add an output edge to the end of the list
if (is_top()) return;
}
// Delete an output edge
if (is_top()) return;
// Find and remove n
do {
} while (*--outp != n);
// Smash the old edge so it can't be used accidentally.
// Record that a change happened here.
#endif
}
public:
// Globally replace this node by a given new node, updating all uses.
// Globally replace this node by a given new node, updating all uses
// and cutting input edges of old node.
disconnect_inputs(NULL, c);
}
// Find the one non-null required input. RegionNode only
Node *nonnull_req() const;
// Add or remove precedence edges
_in[i] = n;
}
// Set this node's index, used by cisc_version to replace current node
}
// Swap input edge order. (Edge indexes i1 and i2 are usually 1 and 2.)
// Def-Use info is unchanged
// If this node is in the hash table, make sure it doesn't need a rehash.
}
// Iterators over input Nodes for a Node X are written as:
// for( i = 0; i < X.req(); i++ ) ... X[i] ...
// NOTE: Required edges can contain embedded NULL pointers.
//----------------- Other Node Properties
// Generate class id for some ideal nodes to avoid virtual query
// methods is_<Node>().
// Class id is the set of bits corresponded to the node class and all its
// super classes so that queries for super classes are also valid.
// Subclasses of the same super class have different assigned bit
// (the third parameter in the macro DEFINE_CLASS_ID).
// Classes with deeper hierarchy are declared first.
// Classes with the same hierarchy depth are sorted by usage frequency.
//
// The query method masks the bits to cut off bits of subclasses
// and then compare the result with the class id
// (see the macro DEFINE_CLASS_QUERY below).
//
// Class_MachCall=30, ClassMask_MachCall=31
// 12 8 4 0
// 0 0 0 0 0 0 0 0 1 1 1 1 0
// | | | |
// | | | Bit_Mach=2
// | | Bit_MachReturn=4
// | Bit_MachSafePoint=8
// Bit_MachCall=16
//
// Class_CountedLoop=56, ClassMask_CountedLoop=63
// 12 8 4 0
// 0 0 0 0 0 0 0 1 1 1 0 0 0
// | | |
// | | Bit_Region=8
// | Bit_Loop=16
// Bit_CountedLoop=32
// This enum is used only for C2 ideal and mach nodes with is_<node>() methods
// so that it's values fits into 16 bits.
enum NodeClasses {
};
// Flags are sorted by usage frequency.
enum NodeFlags {
};
private:
protected:
// These methods should be called from constructors only.
_class_id = c; // cast out const
}
}
}
public:
// Return a dense integer opcode number
virtual int Opcode() const;
// Virtual inherited Node size
// Other interesting Node properties
} \
} \
}
// duplicate of is_MachSpillCopy()
bool is_SpillCopy () const {
}
// The data node which is safe to leave in dead loop during IGVN optimization.
bool is_dead_loop_safe() const {
}
// is_Copy() returns copied edge index (0 or 1)
virtual bool is_CFG() const { return false; }
// If this node is control-dependent on a test, can it be
// rerouted to a dominating equivalent test? This is usually
// true of non-CFG nodes, but can be false for operations which
// depend for their correct sequencing on more than one test.
// (In that case, hoisting to a dominating test may silently
// skip some other important test.)
// When building basic blocks, I need to have a notion of block beginning
// Nodes, next block selector Nodes (block enders), and next block
// projections. These calls need to work on their machine equivalents. The
// Ideal beginning Nodes are RootNode, RegionNode and StartNode.
bool is_block_start() const {
if ( is_Region() )
else
return is_Start();
}
// Goto and Return. This call also returns the block ending Node.
virtual const Node *is_block_proj() const;
// The node is a "macro" node which needs to be expanded before matching
// The node is expensive: the best control is set during loop opts
//----------------- Optimization
// Get the worst-case Type output for this Node.
virtual const class Type *bottom_type() const;
// If we find a better type for a node, try to record it permanently.
// Return true if this node actually changed.
// Be sure to do the hash_delete game in the "rehash" variant.
// or NULL if none. The address type is conservatively wide.
// Returns non-null for calls, membars, loads, stores, etc.
// Returns TypePtr::BOTTOM if the node touches memory "broadly".
// Return an existing node which computes the same function as this node.
// The optimistic combined algorithm requires this to return a Node which
// is a small number of steps away (e.g., one of my inputs).
// Return the set of values this Node can take on at runtime.
// Return a node which is more "ideal" than the current node.
// The invariants on this call are subtle. If in doubt, read the
// treatise in node.cpp above the default implemention AND TEST WITH
// +VerifyIterativeGVN!
// Some nodes have specific Ideal subgraph transformations only if they are
// unique users of specific nodes. Such nodes should be put on IGVN worklist
// for the transformations to happen.
bool has_special_unique_user() const;
// Skip Proj and CatchProj nodes chains. Check for Null and Top.
// Check if 'this' node dominates or equal to 'sub'.
protected:
public:
// Idealize graph, using DU info. Done after constant propagation
// See if there is valid pipeline info
static const Pipeline *pipeline_class();
// Compute the latency from the def to this instruction of the ith input node
// Hash & compare functions, for pessimistic value numbering
// If the hash function returns the special sentinel value NO_HASH,
// the node is guaranteed never to compare equal to any other node.
// If we accidentally generate a hash with value NO_HASH the node
// won't go into the table and we'll lose a little optimization.
enum { NO_HASH = 0 };
// Operation appears to be iteratively computed (such as an induction variable)
// It is possible for this operation to return false for a loop-varying
// value, if it appears (by local graph inspection) to be computed by a simple conditional.
bool is_iteratively_computed();
// Determine if a node is Counted loop induction variable.
// The method is defined in loopnode.cpp.
const Node* is_loop_iv() const;
// Return a node with opcode "opc" and same inputs as "this" if one can
// be found; Otherwise return NULL;
// Return the unique control out if only one. Null if none or more than one.
Node* unique_ctrl_out();
//----------------- Code Generation
// Ideal register class for Matching. Zero means unmatched instruction
// (these are cloned instead of converted to machine nodes).
// Do we Match on this edge index or not? Generally false for Control
// and true for everything else. Weird for calls & returns.
// Register class output is returned in
virtual const RegMask &out_RegMask() const;
// Register class input is expected in
// Should we clone rather than spill this instruction?
bool rematerialize() const;
// Return JVM State Object if this Node carries debug info, or NULL otherwise
// Print as assembly
// Emit bytes starting at parameter 'ptr'
// Bump 'ptr' by the number of output bytes
// Size of instruction in bytes
// Convenience function to extract an integer constant from a node.
// If it is not an integer constant (either Con, CastII, or Mach),
// return value_if_unknown.
const TypeInt* t = find_int_type();
}
// Return the constant, knowing it is an integer constant already
const TypeInt* t = find_int_type();
return t->get_con();
}
// Here's where the work is done. Can produce non-constant int types too.
const TypeInt* find_int_type() const;
// Same thing for long (and intptr_t, via type.hpp):
const TypeLong* t = find_long_type();
return t->get_con();
}
const TypeLong* t = find_long_type();
}
const TypeLong* find_long_type() const;
const TypePtr* get_ptr_type() const;
// These guys are called by code generated by ADLC:
intptr_t get_narrowcon() const;
// Nodes which are pinned into basic blocks
virtual bool pinned() const { return false; }
// Nodes which use memory without consuming it, hence need antidependences
// More specifically, needs_anti_dependence_check returns true iff the node
// (a) does a load, and (b) does not perform a store (except perhaps to a
// stack slot or some other unaliased location).
bool needs_anti_dependence_check() const;
// Return which operand this instruction may cisc-spill. In other words,
// return operand position that can convert from reg to memory access
//----------------- Graph walking
public:
// Walk and apply member functions recursively.
// Supplied (this) pointer is root.
static void packregion( Node &n, void* );
private:
//----------------- Printing, etc
public:
#ifndef PRODUCT
void verify() const; // Check Def-Use info for my subgraph
static void verify_recur(const Node *n, int verify_depth, VectorSet &old_space, VectorSet &new_space);
// This call defines a class-unique string used to identify class instances
virtual const char *Name() const;
// RegMask Print Functions
static int _in_dump_cnt;
void fast_dump() const {
if (in(i))
else
}
#endif
#ifdef ASSERT
void verify_construction();
static void init_NodeProperty();
#endif
#endif
};
//-----------------------------------------------------------------------------
// Iterators over DU info, and associated Node functions.
// Common code for assertion checking on DU iterators.
#ifdef ASSERT
protected:
void verify_resync();
// The VDUI_ONLY macro protects code conditionalized on VerifyDUIterators
#else
#define I_VDUI_ONLY(i,x) { }
#endif //ASSERT
};
// Default DU iterator. Allows appends onto the out array.
// Allows deletion from the out array only at the current point.
// Usage:
// for (DUIterator i = x->outs(); x->has_out(i); i++) {
// Node* y = x->out(i);
// ...
// }
// Compiles in product mode to a unsigned integer index, which indexes
// onto a repeatedly reloaded base pointer of x->_out. The loop predicate
// also reloads x->_outcnt. If you delete, you must perform "--i" just
// before continuing the loop. You must delete only the last-produced
// edge. You must delete only a single copy of the last-produced edge,
// or else you must delete all copies at once (the first time the edge
// is produced by the iterator).
friend class Node;
// This is the index which provides the product-mode behavior.
// Whatever the product-mode version of the system does to the
// DUI index is done to this index. All other fields in
// this class are used only for assertion checking.
#ifdef ASSERT
void verify_increment(); // Verify an increment operation.
void verify_resync(); // Verify that we can back up over a deletion.
void verify_finish(); // Verify that the loop terminated properly.
void refresh(); // Resample verification info.
#endif
public:
// initialize to garbage; clear _vdui to disable asserts
void operator++(int dummy_to_specify_postfix_op)
void operator--()
~DUIterator()
{ VDUI_ONLY(verify_finish()); }
};
{ return DUIterator(this, 0); }
{ I_VDUI_ONLY(i, i.refresh()); return i; }
// Faster DU iterator. Disallows insertions into the out array.
// Allows deletion from the out array only at the current point.
// Usage:
// for (DUIterator_Fast imax, i = x->fast_outs(imax); i < imax; i++) {
// Node* y = x->fast_out(i);
// ...
// }
// Compiles in product mode to raw Node** pointer arithmetic, with
// no reloading of pointers from the original node x. If you delete,
// you must perform "--i; --imax" just before continuing the loop.
// If you delete multiple copies of the same edge, you must decrement
// imax, but not i, multiple times: "--i, imax -= num_edges".
friend class Node;
friend class DUIterator_Last;
// This is the pointer which provides the product-mode behavior.
// Whatever the product-mode version of the system does to the
// DUI pointer is done to this pointer. All other fields in
// this class are used only for assertion checking.
#ifdef ASSERT
void verify_limit();
void verify_resync();
void verify_relimit(uint n);
#endif
// Note: offset must be signed, since -1 is sometimes passed
public:
// initialize to garbage; clear _vdui to disable asserts
void operator++(int dummy_to_specify_postfix_op)
void operator--()
void operator-=(uint n) // applied to the limit only
}
};
// Assign a limit pointer to the reference argument:
// Return the base pointer:
return DUIterator_Fast(this, 0);
}
I_VDUI_ONLY(i, i.verify(this));
}
// Faster DU iterator. Requires each successive edge to be removed.
// Does not allow insertion of any edges.
// Usage:
// for (DUIterator_Last imin, i = x->last_outs(imin); i >= imin; i -= num_edges) {
// Node* y = x->last_out(i);
// ...
// }
// Compiles in product mode to raw Node** pointer arithmetic, with
// no reloading of pointers from the original node x.
friend class Node;
#ifdef ASSERT
void verify_limit();
#endif
// Note: offset must be signed, since -1 is sometimes passed
void operator<(int) {} // do not use
public:
DUIterator_Last() { }
// initialize to garbage
void operator--()
void operator-=(uint n)
}
{ DUIterator_Fast::operator=(that); }
};
// Assign a limit pointer to the reference argument:
imin = DUIterator_Last(this, 0);
// Return the initial pointer:
}
I_VDUI_ONLY(i, i.verify(this));
}
#endif //OPTO_DU_ITERATOR_ASSERT
// An Iterator that truly follows the iterator pattern. Doesn't
// support deletion but could be made to.
//
// for (SimpleDUIterator i(n); i.has_next(); i.next()) {
// Node* m = i.get();
//
private:
public:
void next() { i++; }
};
//-----------------------------------------------------------------------------
// Map dense integer indices to Nodes. Uses classic doubling-array trick.
// Abstractly provides an infinite array of Node*'s, initialized to NULL.
// Note that the constructor just zeros things, and since I use Arena
// allocation I do not need a destructor to reclaim storage.
friend class VMStructs;
protected:
public:
for( int i = 0; i < OptoNodeListSize; i++ ) {
}
}
// Extend the mapping: index i maps to Node *n.
void clear(); // Set all entries to NULL, keep storage
void dump() const;
};
friend class VMStructs;
public:
if (at(e) == n) return true;
}
return false;
}
void dump() const;
};
//------------------------------Unique_Node_List-------------------------------
friend class VMStructs;
public:
Unique_Node_List() : Node_List(), _in_worklist(Thread::current()->resource_area()), _clock_index(0) {}
}
_in_worklist >>= b->_idx;
return b;
}
_in_worklist >>= b->_idx;
return b;
}
void clear() {
_clock_index = 0;
}
// Used after parsing to remove useless nodes before Iterative GVN
#ifndef PRODUCT
#endif
};
// Inline definition of Compile::record_for_igvn must be deferred to this point.
}
//------------------------------Node_Stack-------------------------------------
class Node_Stack {
friend class VMStructs;
protected:
struct INode {
};
void grow();
public:
}
}
void pop() {
--_inode_top;
}
++_inode_top;
}
return _inode_top->node;
}
}
return _inode_top->indx;
}
}
_inode_top->node = n;
}
_inode_top->indx = i;
}
uint size_max() const { return (uint)pointer_delta(_inode_max, _inodes, sizeof(INode)); } // Max size
uint size() const { return (uint)pointer_delta((_inode_top+1), _inodes, sizeof(INode)); } // Current size
// Node_Stack is used to map nodes.
};
//-----------------------------Node_Notes--------------------------------------
// Debugging or profiling annotations loosely and sparsely associated
// with some nodes. See Compile::node_notes_at for the accessor.
friend class VMStructs;
public:
}
// True if there is nothing here.
bool is_clear() {
}
// Make there be nothing here.
void clear() {
}
// Make a new, clean node notes.
return nn;
}
(*nn) = (*this);
return nn;
}
// Absorb any information from source.
bool changed = false;
changed = true;
}
}
return changed;
}
};
// Inlined accessors for Compile::node_nodes that require the preceding class:
inline Node_Notes*
if (grow_by >= 0) {
}
// (Every element of arr is a sub-array of length _node_notes_block_size.)
}
inline bool
return false; // nothing to write => write nothing
}
//------------------------------TypeNode---------------------------------------
// Node with a Type constant.
protected:
public:
// If this node is in the hash table, make sure it doesn't need a rehash.
}
}
virtual const Type *bottom_type() const;
#ifndef PRODUCT
#endif
};
#endif // SHARE_VM_OPTO_NODE_HPP