hotspot/src/share/vm/opto/cfgnode.hpp
Print this page
rev 611 : Merge
*** 1,10 ****
#ifdef USE_PRAGMA_IDENT_HDR
#pragma ident "@(#)cfgnode.hpp 1.117 07/10/23 13:12:52 JVM"
#endif
/*
! * Copyright 1997-2006 Sun Microsystems, Inc. All Rights Reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
--- 1,10 ----
#ifdef USE_PRAGMA_IDENT_HDR
#pragma ident "@(#)cfgnode.hpp 1.117 07/10/23 13:12:52 JVM"
#endif
/*
! * Copyright 1997-2008 Sun Microsystems, Inc. All Rights Reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*** 111,149 ****
// paths to the RegionNode. For speed reasons (to avoid another pass) we
// can turn PhiNodes into copys in-place by NULL'ing out their RegionNode
// input in slot 0.
class PhiNode : public TypeNode {
const TypePtr* const _adr_type; // non-null only for Type::MEMORY nodes.
// Size is bigger to hold the _adr_type field.
virtual uint hash() const; // Check the type
virtual uint cmp( const Node &n ) const;
virtual uint size_of() const { return sizeof(*this); }
- // Determine a unique non-trivial input, if any.
- // Ignore casts if it helps. Return NULL on failure.
- Node* unique_input(PhaseTransform *phase);
// Determine if CMoveNode::is_cmove_id can be used at this join point.
Node* is_cmove_id(PhaseTransform* phase, int true_path);
public:
// Node layout (parallels RegionNode):
enum { Region, // Control input is the Phi's region.
Input // Input values are [1..len)
};
! PhiNode( Node *r, const Type *t, const TypePtr* at = NULL )
! : TypeNode(t,r->req()), _adr_type(at) {
init_class_id(Class_Phi);
init_req(0, r);
verify_adr_type();
}
// create a new phi with in edges matching r and set (initially) to x
static PhiNode* make( Node* r, Node* x );
// extra type arguments override the new phi's bottom_type and adr_type
static PhiNode* make( Node* r, Node* x, const Type *t, const TypePtr* at = NULL );
// create a new phi with narrowed memory type
PhiNode* slice_memory(const TypePtr* adr_type) const;
// like make(r, x), but does not initialize the in edges to x
static PhiNode* make_blank( Node* r, Node* x );
// Accessors
RegionNode* region() const { Node* r = in(Region); assert(!r || r->is_Region(), ""); return (RegionNode*)r; }
--- 111,159 ----
// paths to the RegionNode. For speed reasons (to avoid another pass) we
// can turn PhiNodes into copys in-place by NULL'ing out their RegionNode
// input in slot 0.
class PhiNode : public TypeNode {
const TypePtr* const _adr_type; // non-null only for Type::MEMORY nodes.
+ const int _inst_id; // Instance id of the memory slice.
+ const int _inst_index; // Alias index of the instance memory slice.
+ // Array elements references have the same alias_idx but different offset.
+ const int _inst_offset; // Offset of the instance memory slice.
// Size is bigger to hold the _adr_type field.
virtual uint hash() const; // Check the type
virtual uint cmp( const Node &n ) const;
virtual uint size_of() const { return sizeof(*this); }
// Determine if CMoveNode::is_cmove_id can be used at this join point.
Node* is_cmove_id(PhaseTransform* phase, int true_path);
public:
// Node layout (parallels RegionNode):
enum { Region, // Control input is the Phi's region.
Input // Input values are [1..len)
};
! PhiNode( Node *r, const Type *t, const TypePtr* at = NULL,
! const int iid = TypeOopPtr::InstanceTop,
! const int iidx = Compile::AliasIdxTop,
! const int ioffs = Type::OffsetTop )
! : TypeNode(t,r->req()),
! _adr_type(at),
! _inst_id(iid),
! _inst_index(iidx),
! _inst_offset(ioffs)
! {
init_class_id(Class_Phi);
init_req(0, r);
verify_adr_type();
}
// create a new phi with in edges matching r and set (initially) to x
static PhiNode* make( Node* r, Node* x );
// extra type arguments override the new phi's bottom_type and adr_type
static PhiNode* make( Node* r, Node* x, const Type *t, const TypePtr* at = NULL );
// create a new phi with narrowed memory type
PhiNode* slice_memory(const TypePtr* adr_type) const;
+ PhiNode* split_out_instance(const TypePtr* at, PhaseIterGVN *igvn) const;
// like make(r, x), but does not initialize the in edges to x
static PhiNode* make_blank( Node* r, Node* x );
// Accessors
RegionNode* region() const { Node* r = in(Region); assert(!r || r->is_Region(), ""); return (RegionNode*)r; }
*** 153,171 ****
--- 163,199 ----
DEBUG_ONLY(const Node* r = _in[Region];)
assert(r != NULL && r->is_Region(), "Not valid control");
return NULL; // not a copy!
}
+ bool is_tripcount() const;
+
+ // Determine a unique non-trivial input, if any.
+ // Ignore casts if it helps. Return NULL on failure.
+ Node* unique_input(PhaseTransform *phase);
+
// Check for a simple dead loop.
enum LoopSafety { Safe = 0, Unsafe, UnsafeLoop };
LoopSafety simple_data_loop_check(Node *in) const;
// Is it unsafe data loop? It becomes a dead loop if this phi node removed.
bool is_unsafe_data_reference(Node *in) const;
int is_diamond_phi() const;
virtual int Opcode() const;
virtual bool pinned() const { return in(0) != 0; }
virtual const TypePtr *adr_type() const { verify_adr_type(true); return _adr_type; }
+
+ const int inst_id() const { return _inst_id; }
+ const int inst_index() const { return _inst_index; }
+ const int inst_offset() const { return _inst_offset; }
+ bool is_same_inst_field(const Type* tp, int id, int index, int offset) {
+ return type()->basic_type() == tp->basic_type() &&
+ inst_id() == id &&
+ inst_index() == index &&
+ inst_offset() == offset &&
+ type()->higher_equal(tp);
+ }
+
virtual const Type *Value( PhaseTransform *phase ) const;
virtual Node *Identity( PhaseTransform *phase );
virtual Node *Ideal(PhaseGVN *phase, bool can_reshape);
virtual const RegMask &out_RegMask() const;
virtual const RegMask &in_RegMask(uint) const;
*** 219,228 ****
--- 247,258 ----
class MultiBranchNode : public MultiNode {
public:
MultiBranchNode( uint required ) : MultiNode(required) {
init_class_id(Class_MultiBranch);
}
+ // returns required number of users to be well formed.
+ virtual int required_outcnt() const = 0;
};
//------------------------------IfNode-----------------------------------------
// Output selected Control, based on a boolean test
class IfNode : public MultiBranchNode {
*** 308,317 ****
--- 338,348 ----
virtual int Opcode() const;
virtual bool pinned() const { return true; }
virtual const Type *bottom_type() const { return TypeTuple::IFBOTH; }
virtual Node *Ideal(PhaseGVN *phase, bool can_reshape);
virtual const Type *Value( PhaseTransform *phase ) const;
+ virtual int required_outcnt() const { return 2; }
virtual const RegMask &out_RegMask() const;
void dominated_by(Node* prev_dom, PhaseIterGVN* igvn);
int is_range_check(Node* &range, Node* &index, jint &offset);
Node* fold_compares(PhaseGVN* phase);
static Node* up_one_dom(Node* curr, bool linear_only = false);
*** 366,375 ****
--- 397,407 ----
virtual int Opcode() const;
virtual const Type *Value( PhaseTransform *phase ) const;
virtual Node *Ideal(PhaseGVN *phase, bool can_reshape);
virtual const Type *bottom_type() const;
virtual bool pinned() const { return true; }
+ virtual int required_outcnt() const { return _size; }
};
//------------------------------JumpNode---------------------------------------
// Indirect branch. Uses PCTable above to implement a switch statement.
// It emits as a table load and local branch.
*** 479,489 ****
public:
NeverBranchNode( Node *ctrl ) : MultiBranchNode(1) { init_req(0,ctrl); }
virtual int Opcode() const;
virtual bool pinned() const { return true; };
virtual const Type *bottom_type() const { return TypeTuple::IFBOTH; }
!
virtual void emit(CodeBuffer &cbuf, PhaseRegAlloc *ra_) const { }
virtual uint size(PhaseRegAlloc *ra_) const { return 0; }
#ifndef PRODUCT
virtual void format( PhaseRegAlloc *, outputStream *st ) const;
#endif
--- 511,523 ----
public:
NeverBranchNode( Node *ctrl ) : MultiBranchNode(1) { init_req(0,ctrl); }
virtual int Opcode() const;
virtual bool pinned() const { return true; };
virtual const Type *bottom_type() const { return TypeTuple::IFBOTH; }
! virtual const Type *Value( PhaseTransform *phase ) const;
! virtual Node *Ideal(PhaseGVN *phase, bool can_reshape);
! virtual int required_outcnt() const { return 2; }
virtual void emit(CodeBuffer &cbuf, PhaseRegAlloc *ra_) const { }
virtual uint size(PhaseRegAlloc *ra_) const { return 0; }
#ifndef PRODUCT
virtual void format( PhaseRegAlloc *, outputStream *st ) const;
#endif