8267988: C2: assert(!addp->is_AddP() || addp->in(AddPNode::Base)->is_top() || addp->in(AddPNode::Base) == n->in(AddPNode::Base)) failed: Base pointers must match (addp 1301)

Reviewed-by: chagedorn, vlivanov, kvn
This commit is contained in:
Roland Westrelin 2021-06-16 07:36:07 +00:00
parent b18de6cf79
commit 4d545a1f86
8 changed files with 148 additions and 63 deletions

View file

@ -1406,7 +1406,7 @@ void ShenandoahBarrierC2Support::pin_and_expand(PhaseIdealLoop* phase) {
} }
if (addr->Opcode() == Op_AddP) { if (addr->Opcode() == Op_AddP) {
Node* orig_base = addr->in(AddPNode::Base); Node* orig_base = addr->in(AddPNode::Base);
Node* base = new CheckCastPPNode(ctrl, orig_base, orig_base->bottom_type(), true); Node* base = new CheckCastPPNode(ctrl, orig_base, orig_base->bottom_type(), ConstraintCastNode::StrongDependency);
phase->register_new_node(base, ctrl); phase->register_new_node(base, ctrl);
if (addr->in(AddPNode::Base) == addr->in((AddPNode::Address))) { if (addr->in(AddPNode::Base) == addr->in((AddPNode::Address))) {
// Field access // Field access

View file

@ -39,7 +39,7 @@ Node* ConstraintCastNode::Identity(PhaseGVN* phase) {
if (dom != NULL) { if (dom != NULL) {
return dom; return dom;
} }
if (_carry_dependency) { if (_dependency != RegularDependency) {
return this; return this;
} }
return phase->type(in(1))->higher_equal_speculative(_type) ? in(1) : this; return phase->type(in(1))->higher_equal_speculative(_type) ? in(1) : this;
@ -82,46 +82,46 @@ Node *ConstraintCastNode::Ideal(PhaseGVN *phase, bool can_reshape) {
} }
bool ConstraintCastNode::cmp(const Node &n) const { bool ConstraintCastNode::cmp(const Node &n) const {
return TypeNode::cmp(n) && ((ConstraintCastNode&)n)._carry_dependency == _carry_dependency; return TypeNode::cmp(n) && ((ConstraintCastNode&)n)._dependency == _dependency;
} }
uint ConstraintCastNode::size_of() const { uint ConstraintCastNode::size_of() const {
return sizeof(*this); return sizeof(*this);
} }
Node* ConstraintCastNode::make_cast(int opcode, Node* c, Node *n, const Type *t, bool carry_dependency) { Node* ConstraintCastNode::make_cast(int opcode, Node* c, Node *n, const Type *t, DependencyType dependency) {
switch(opcode) { switch(opcode) {
case Op_CastII: { case Op_CastII: {
Node* cast = new CastIINode(n, t, carry_dependency); Node* cast = new CastIINode(n, t, dependency);
cast->set_req(0, c); cast->set_req(0, c);
return cast; return cast;
} }
case Op_CastLL: { case Op_CastLL: {
Node* cast = new CastLLNode(n, t, carry_dependency); Node* cast = new CastLLNode(n, t, dependency);
cast->set_req(0, c); cast->set_req(0, c);
return cast; return cast;
} }
case Op_CastPP: { case Op_CastPP: {
Node* cast = new CastPPNode(n, t, carry_dependency); Node* cast = new CastPPNode(n, t, dependency);
cast->set_req(0, c); cast->set_req(0, c);
return cast; return cast;
} }
case Op_CastFF: { case Op_CastFF: {
Node* cast = new CastFFNode(n, t, carry_dependency); Node* cast = new CastFFNode(n, t, dependency);
cast->set_req(0, c); cast->set_req(0, c);
return cast; return cast;
} }
case Op_CastDD: { case Op_CastDD: {
Node* cast = new CastDDNode(n, t, carry_dependency); Node* cast = new CastDDNode(n, t, dependency);
cast->set_req(0, c); cast->set_req(0, c);
return cast; return cast;
} }
case Op_CastVV: { case Op_CastVV: {
Node* cast = new CastVVNode(n, t, carry_dependency); Node* cast = new CastVVNode(n, t, dependency);
cast->set_req(0, c); cast->set_req(0, c);
return cast; return cast;
} }
case Op_CheckCastPP: return new CheckCastPPNode(c, n, t, carry_dependency); case Op_CheckCastPP: return new CheckCastPPNode(c, n, t, dependency);
default: default:
fatal("Bad opcode %d", opcode); fatal("Bad opcode %d", opcode);
} }
@ -131,10 +131,10 @@ Node* ConstraintCastNode::make_cast(int opcode, Node* c, Node *n, const Type *t,
Node* ConstraintCastNode::make(Node* c, Node *n, const Type *t, BasicType bt) { Node* ConstraintCastNode::make(Node* c, Node *n, const Type *t, BasicType bt) {
switch(bt) { switch(bt) {
case T_INT: { case T_INT: {
return make_cast(Op_CastII, c, n, t, false); return make_cast(Op_CastII, c, n, t, RegularDependency);
} }
case T_LONG: { case T_LONG: {
return make_cast(Op_CastLL, c, n, t, false); return make_cast(Op_CastLL, c, n, t, RegularDependency);
} }
default: default:
fatal("Bad basic type %s", type2name(bt)); fatal("Bad basic type %s", type2name(bt));
@ -143,6 +143,9 @@ Node* ConstraintCastNode::make(Node* c, Node *n, const Type *t, BasicType bt) {
} }
TypeNode* ConstraintCastNode::dominating_cast(PhaseGVN* gvn, PhaseTransform* pt) const { TypeNode* ConstraintCastNode::dominating_cast(PhaseGVN* gvn, PhaseTransform* pt) const {
if (_dependency == UnconditionalDependency) {
return NULL;
}
Node* val = in(1); Node* val = in(1);
Node* ctl = in(0); Node* ctl = in(0);
int opc = Opcode(); int opc = Opcode();
@ -183,8 +186,8 @@ TypeNode* ConstraintCastNode::dominating_cast(PhaseGVN* gvn, PhaseTransform* pt)
#ifndef PRODUCT #ifndef PRODUCT
void ConstraintCastNode::dump_spec(outputStream *st) const { void ConstraintCastNode::dump_spec(outputStream *st) const {
TypeNode::dump_spec(st); TypeNode::dump_spec(st);
if (_carry_dependency) { if (_dependency != RegularDependency) {
st->print(" carry dependency"); st->print(" %s dependency", _dependency == StrongDependency ? "strong" : "unconditional");
} }
} }
#endif #endif
@ -194,7 +197,7 @@ const Type* CastIINode::Value(PhaseGVN* phase) const {
// Try to improve the type of the CastII if we recognize a CmpI/If // Try to improve the type of the CastII if we recognize a CmpI/If
// pattern. // pattern.
if (_carry_dependency) { if (_dependency != RegularDependency) {
if (in(0) != NULL && in(0)->in(0) != NULL && in(0)->in(0)->is_If()) { if (in(0) != NULL && in(0)->in(0) != NULL && in(0)->in(0)->is_If()) {
assert(in(0)->is_IfFalse() || in(0)->is_IfTrue(), "should be If proj"); assert(in(0)->is_IfFalse() || in(0)->is_IfTrue(), "should be If proj");
Node* proj = in(0); Node* proj = in(0);
@ -255,8 +258,8 @@ const Type* CastIINode::Value(PhaseGVN* phase) const {
return res; return res;
} }
static Node* find_or_make_CastII(PhaseIterGVN* igvn, Node* parent, Node* control, const TypeInt* type, bool carry_dependency) { static Node* find_or_make_CastII(PhaseIterGVN* igvn, Node* parent, Node* control, const TypeInt* type, ConstraintCastNode::DependencyType dependency) {
Node* n = new CastIINode(parent, type, carry_dependency); Node* n = new CastIINode(parent, type, dependency);
n->set_req(0, control); n->set_req(0, control);
Node* existing = igvn->hash_find_insert(n); Node* existing = igvn->hash_find_insert(n);
if (existing != NULL) { if (existing != NULL) {
@ -289,8 +292,8 @@ Node *CastIINode::Ideal(PhaseGVN *phase, bool can_reshape) {
Node* x = z->in(1); Node* x = z->in(1);
Node* y = z->in(2); Node* y = z->in(2);
Node* cx = find_or_make_CastII(igvn, x, in(0), rx->is_int(), _carry_dependency); Node* cx = find_or_make_CastII(igvn, x, in(0), rx->is_int(), _dependency);
Node* cy = find_or_make_CastII(igvn, y, in(0), ry->is_int(), _carry_dependency); Node* cy = find_or_make_CastII(igvn, y, in(0), ry->is_int(), _dependency);
switch (op) { switch (op) {
case Op_AddI: return new AddINode(cx, cy); case Op_AddI: return new AddINode(cx, cy);
case Op_SubI: return new SubINode(cx, cy); case Op_SubI: return new SubINode(cx, cy);
@ -377,7 +380,7 @@ Node* CheckCastPPNode::Identity(PhaseGVN* phase) {
if (dom != NULL) { if (dom != NULL) {
return dom; return dom;
} }
if (_carry_dependency) { if (_dependency != RegularDependency) {
return this; return this;
} }
const Type* t = phase->type(in(1)); const Type* t = phase->type(in(1));
@ -573,20 +576,20 @@ Node* CastP2XNode::Identity(PhaseGVN* phase) {
return this; return this;
} }
Node* ConstraintCastNode::make_cast_for_type(Node* c, Node* in, const Type* type) { Node* ConstraintCastNode::make_cast_for_type(Node* c, Node* in, const Type* type, DependencyType dependency) {
Node* cast= NULL; Node* cast= NULL;
if (type->isa_int()) { if (type->isa_int()) {
cast = make_cast(Op_CastII, c, in, type, true); cast = make_cast(Op_CastII, c, in, type, dependency);
} else if (type->isa_long()) { } else if (type->isa_long()) {
cast = make_cast(Op_CastLL, c, in, type, true); cast = make_cast(Op_CastLL, c, in, type, dependency);
} else if (type->isa_float()) { } else if (type->isa_float()) {
cast = make_cast(Op_CastFF, c, in, type, true); cast = make_cast(Op_CastFF, c, in, type, dependency);
} else if (type->isa_double()) { } else if (type->isa_double()) {
cast = make_cast(Op_CastDD, c, in, type, true); cast = make_cast(Op_CastDD, c, in, type, dependency);
} else if (type->isa_vect()) { } else if (type->isa_vect()) {
cast = make_cast(Op_CastVV, c, in, type, true); cast = make_cast(Op_CastVV, c, in, type, dependency);
} else if (type->isa_ptr()) { } else if (type->isa_ptr()) {
cast = make_cast(Op_CastPP, c, in, type, true); cast = make_cast(Op_CastPP, c, in, type, dependency);
} }
return cast; return cast;
} }

View file

@ -32,15 +32,21 @@
//------------------------------ConstraintCastNode----------------------------- //------------------------------ConstraintCastNode-----------------------------
// cast to a different range // cast to a different range
class ConstraintCastNode: public TypeNode { class ConstraintCastNode: public TypeNode {
public:
enum DependencyType {
RegularDependency, // if cast doesn't improve input type, cast can be removed
StrongDependency, // leave cast in even if _type doesn't improve input type, can be replaced by stricter dominating cast if one exist
UnconditionalDependency // leave cast in unconditionally
};
protected: protected:
// Can this node be removed post CCP or does it carry a required dependency? const DependencyType _dependency;
const bool _carry_dependency;
virtual bool cmp( const Node &n ) const; virtual bool cmp( const Node &n ) const;
virtual uint size_of() const; virtual uint size_of() const;
public: public:
ConstraintCastNode(Node *n, const Type *t, bool carry_dependency) ConstraintCastNode(Node *n, const Type *t, DependencyType dependency)
: TypeNode(t,2), _carry_dependency(carry_dependency) { : TypeNode(t,2), _dependency(dependency) {
init_class_id(Class_ConstraintCast); init_class_id(Class_ConstraintCast);
init_req(1, n); init_req(1, n);
} }
@ -49,10 +55,10 @@ class ConstraintCastNode: public TypeNode {
virtual Node *Ideal(PhaseGVN *phase, bool can_reshape); virtual Node *Ideal(PhaseGVN *phase, bool can_reshape);
virtual int Opcode() const; virtual int Opcode() const;
virtual uint ideal_reg() const = 0; virtual uint ideal_reg() const = 0;
virtual bool depends_only_on_test() const { return !_carry_dependency; } virtual bool depends_only_on_test() const { return _dependency == RegularDependency; }
bool carry_dependency() const { return _carry_dependency; } bool carry_dependency() const { return _dependency != RegularDependency; }
TypeNode* dominating_cast(PhaseGVN* gvn, PhaseTransform* pt) const; TypeNode* dominating_cast(PhaseGVN* gvn, PhaseTransform* pt) const;
static Node* make_cast(int opcode, Node* c, Node *n, const Type *t, bool carry_dependency); static Node* make_cast(int opcode, Node* c, Node *n, const Type *t, DependencyType dependency);
static Node* make(Node* c, Node *n, const Type *t, BasicType bt); static Node* make(Node* c, Node *n, const Type *t, BasicType bt);
virtual bool operates_on(BasicType bt, bool signed_int) const { virtual bool operates_on(BasicType bt, bool signed_int) const {
assert(bt == T_INT || bt == T_LONG, "unsupported"); assert(bt == T_INT || bt == T_LONG, "unsupported");
@ -63,7 +69,7 @@ class ConstraintCastNode: public TypeNode {
virtual void dump_spec(outputStream *st) const; virtual void dump_spec(outputStream *st) const;
#endif #endif
static Node* make_cast_for_type(Node* c, Node* in, const Type* type); static Node* make_cast_for_type(Node* c, Node* in, const Type* type, DependencyType dependency);
}; };
//------------------------------CastIINode------------------------------------- //------------------------------CastIINode-------------------------------------
@ -76,12 +82,12 @@ class CastIINode: public ConstraintCastNode {
virtual uint size_of() const; virtual uint size_of() const;
public: public:
CastIINode(Node* n, const Type* t, bool carry_dependency = false, bool range_check_dependency = false) CastIINode(Node* n, const Type* t, DependencyType dependency = RegularDependency, bool range_check_dependency = false)
: ConstraintCastNode(n, t, carry_dependency), _range_check_dependency(range_check_dependency) { : ConstraintCastNode(n, t, dependency), _range_check_dependency(range_check_dependency) {
init_class_id(Class_CastII); init_class_id(Class_CastII);
} }
CastIINode(Node* ctrl, Node* n, const Type* t, bool carry_dependency = false, bool range_check_dependency = false) CastIINode(Node* ctrl, Node* n, const Type* t, DependencyType dependency = RegularDependency, bool range_check_dependency = false)
: ConstraintCastNode(n, t, carry_dependency), _range_check_dependency(range_check_dependency) { : ConstraintCastNode(n, t, dependency), _range_check_dependency(range_check_dependency) {
init_class_id(Class_CastII); init_class_id(Class_CastII);
init_req(0, ctrl); init_req(0, ctrl);
} }
@ -110,13 +116,13 @@ class CastIINode: public ConstraintCastNode {
class CastLLNode: public ConstraintCastNode { class CastLLNode: public ConstraintCastNode {
public: public:
CastLLNode(Node* ctrl, Node* n, const Type* t, bool carry_dependency = false) CastLLNode(Node* ctrl, Node* n, const Type* t, DependencyType dependency = RegularDependency)
: ConstraintCastNode(n, t, carry_dependency) { : ConstraintCastNode(n, t, dependency) {
init_class_id(Class_CastLL); init_class_id(Class_CastLL);
init_req(0, ctrl); init_req(0, ctrl);
} }
CastLLNode(Node* n, const Type* t, bool carry_dependency = false) CastLLNode(Node* n, const Type* t, DependencyType dependency = RegularDependency)
: ConstraintCastNode(n, t, carry_dependency){ : ConstraintCastNode(n, t, dependency){
init_class_id(Class_CastLL); init_class_id(Class_CastLL);
} }
virtual bool operates_on(BasicType bt, bool signed_int) const { virtual bool operates_on(BasicType bt, bool signed_int) const {
@ -129,8 +135,8 @@ public:
class CastFFNode: public ConstraintCastNode { class CastFFNode: public ConstraintCastNode {
public: public:
CastFFNode(Node* n, const Type* t, bool carry_dependency = false) CastFFNode(Node* n, const Type* t, DependencyType dependency = RegularDependency)
: ConstraintCastNode(n, t, carry_dependency){ : ConstraintCastNode(n, t, dependency){
init_class_id(Class_CastFF); init_class_id(Class_CastFF);
} }
virtual int Opcode() const; virtual int Opcode() const;
@ -139,8 +145,8 @@ public:
class CastDDNode: public ConstraintCastNode { class CastDDNode: public ConstraintCastNode {
public: public:
CastDDNode(Node* n, const Type* t, bool carry_dependency = false) CastDDNode(Node* n, const Type* t, DependencyType dependency = RegularDependency)
: ConstraintCastNode(n, t, carry_dependency){ : ConstraintCastNode(n, t, dependency){
init_class_id(Class_CastDD); init_class_id(Class_CastDD);
} }
virtual int Opcode() const; virtual int Opcode() const;
@ -149,8 +155,8 @@ public:
class CastVVNode: public ConstraintCastNode { class CastVVNode: public ConstraintCastNode {
public: public:
CastVVNode(Node* n, const Type* t, bool carry_dependency = false) CastVVNode(Node* n, const Type* t, DependencyType dependency = RegularDependency)
: ConstraintCastNode(n, t, carry_dependency){ : ConstraintCastNode(n, t, dependency){
init_class_id(Class_CastVV); init_class_id(Class_CastVV);
} }
virtual int Opcode() const; virtual int Opcode() const;
@ -162,8 +168,8 @@ public:
// cast pointer to pointer (different type) // cast pointer to pointer (different type)
class CastPPNode: public ConstraintCastNode { class CastPPNode: public ConstraintCastNode {
public: public:
CastPPNode (Node *n, const Type *t, bool carry_dependency = false) CastPPNode (Node *n, const Type *t, DependencyType dependency = RegularDependency)
: ConstraintCastNode(n, t, carry_dependency) { : ConstraintCastNode(n, t, dependency) {
} }
virtual int Opcode() const; virtual int Opcode() const;
virtual uint ideal_reg() const { return Op_RegP; } virtual uint ideal_reg() const { return Op_RegP; }
@ -173,8 +179,8 @@ class CastPPNode: public ConstraintCastNode {
// for _checkcast, cast pointer to pointer (different type), without JOIN, // for _checkcast, cast pointer to pointer (different type), without JOIN,
class CheckCastPPNode: public ConstraintCastNode { class CheckCastPPNode: public ConstraintCastNode {
public: public:
CheckCastPPNode(Node *c, Node *n, const Type *t, bool carry_dependency = false) CheckCastPPNode(Node *c, Node *n, const Type *t, DependencyType dependency = RegularDependency)
: ConstraintCastNode(n, t, carry_dependency) { : ConstraintCastNode(n, t, dependency) {
init_class_id(Class_CheckCastPP); init_class_id(Class_CheckCastPP);
init_req(0, c); init_req(0, c);
} }

View file

@ -1975,7 +1975,7 @@ Node *PhiNode::Ideal(PhaseGVN *phase, bool can_reshape) {
if (phi_type->isa_ptr()) { if (phi_type->isa_ptr()) {
const Type* uin_type = phase->type(uin); const Type* uin_type = phase->type(uin);
if (!phi_type->isa_oopptr() && !uin_type->isa_oopptr()) { if (!phi_type->isa_oopptr() && !uin_type->isa_oopptr()) {
cast = ConstraintCastNode::make_cast(Op_CastPP, r, uin, phi_type, true); cast = ConstraintCastNode::make_cast(Op_CastPP, r, uin, phi_type, ConstraintCastNode::StrongDependency);
} else { } else {
// Use a CastPP for a cast to not null and a CheckCastPP for // Use a CastPP for a cast to not null and a CheckCastPP for
// a cast to a new klass (and both if both null-ness and // a cast to a new klass (and both if both null-ness and
@ -1985,7 +1985,7 @@ Node *PhiNode::Ideal(PhaseGVN *phase, bool can_reshape) {
// null, uin's type must be casted to not null // null, uin's type must be casted to not null
if (phi_type->join(TypePtr::NOTNULL) == phi_type->remove_speculative() && if (phi_type->join(TypePtr::NOTNULL) == phi_type->remove_speculative() &&
uin_type->join(TypePtr::NOTNULL) != uin_type->remove_speculative()) { uin_type->join(TypePtr::NOTNULL) != uin_type->remove_speculative()) {
cast = ConstraintCastNode::make_cast(Op_CastPP, r, uin, TypePtr::NOTNULL, true); cast = ConstraintCastNode::make_cast(Op_CastPP, r, uin, TypePtr::NOTNULL, ConstraintCastNode::StrongDependency);
} }
// If the type of phi and uin, both casted to not null, // If the type of phi and uin, both casted to not null,
@ -1997,14 +1997,14 @@ Node *PhiNode::Ideal(PhaseGVN *phase, bool can_reshape) {
cast = phase->transform(cast); cast = phase->transform(cast);
n = cast; n = cast;
} }
cast = ConstraintCastNode::make_cast(Op_CheckCastPP, r, n, phi_type, true); cast = ConstraintCastNode::make_cast(Op_CheckCastPP, r, n, phi_type, ConstraintCastNode::StrongDependency);
} }
if (cast == NULL) { if (cast == NULL) {
cast = ConstraintCastNode::make_cast(Op_CastPP, r, uin, phi_type, true); cast = ConstraintCastNode::make_cast(Op_CastPP, r, uin, phi_type, ConstraintCastNode::StrongDependency);
} }
} }
} else { } else {
cast = ConstraintCastNode::make_cast_for_type(r, uin, phi_type); cast = ConstraintCastNode::make_cast_for_type(r, uin, phi_type, ConstraintCastNode::StrongDependency);
} }
assert(cast != NULL, "cast should be set"); assert(cast != NULL, "cast should be set");
cast = phase->transform(cast); cast = phase->transform(cast);

View file

@ -4135,7 +4135,7 @@ Node* Compile::conv_I2X_index(PhaseGVN* phase, Node* idx, const TypeInt* sizetyp
Node* Compile::constrained_convI2L(PhaseGVN* phase, Node* value, const TypeInt* itype, Node* ctrl, bool carry_dependency) { Node* Compile::constrained_convI2L(PhaseGVN* phase, Node* value, const TypeInt* itype, Node* ctrl, bool carry_dependency) {
if (ctrl != NULL) { if (ctrl != NULL) {
// Express control dependency by a CastII node with a narrow type. // Express control dependency by a CastII node with a narrow type.
value = new CastIINode(value, itype, carry_dependency, true /* range check dependency */); value = new CastIINode(value, itype, carry_dependency ? ConstraintCastNode::StrongDependency : ConstraintCastNode::RegularDependency, true /* range check dependency */);
// Make the CastII node dependent on the control input to prevent the narrowed ConvI2L // Make the CastII node dependent on the control input to prevent the narrowed ConvI2L
// node from floating above the range check during loop optimizations. Otherwise, the // node from floating above the range check during loop optimizations. Otherwise, the
// ConvI2L node may be eliminated independently of the range check, causing the data path // ConvI2L node may be eliminated independently of the range check, causing the data path

View file

@ -1193,7 +1193,7 @@ Node *PhaseIdealLoop::clone_up_backedge_goo(Node *back_ctrl, Node *preheader_ctr
} }
Node* PhaseIdealLoop::cast_incr_before_loop(Node* incr, Node* ctrl, Node* loop) { Node* PhaseIdealLoop::cast_incr_before_loop(Node* incr, Node* ctrl, Node* loop) {
Node* castii = new CastIINode(incr, TypeInt::INT, true); Node* castii = new CastIINode(incr, TypeInt::INT, ConstraintCastNode::StrongDependency);
castii->set_req(0, ctrl); castii->set_req(0, ctrl);
register_new_node(castii, ctrl); register_new_node(castii, ctrl);
for (DUIterator_Fast imax, i = incr->fast_outs(imax); i < imax; i++) { for (DUIterator_Fast imax, i = incr->fast_outs(imax); i < imax; i++) {

View file

@ -1503,7 +1503,15 @@ void PhaseIdealLoop::try_sink_out_of_loop(Node* n) {
assert(!n_loop->is_member(get_loop(x_ctrl)), "should have moved out of loop"); assert(!n_loop->is_member(get_loop(x_ctrl)), "should have moved out of loop");
register_new_node(x, x_ctrl); register_new_node(x, x_ctrl);
if (x->in(0) == NULL && !x->is_DecodeNarrowPtr()) { // Chain of AddP: (AddP base (AddP base )) must keep the same base after sinking so:
// 1- We don't add a CastPP here when the first one is sunk so if the second one is not, their bases remain
// the same.
// (see 2- below)
assert(!x->is_AddP() || !x->in(AddPNode::Address)->is_AddP() ||
x->in(AddPNode::Address)->in(AddPNode::Base) == x->in(AddPNode::Base) ||
!x->in(AddPNode::Address)->in(AddPNode::Base)->eqv_uncast(x->in(AddPNode::Base)), "unexpected AddP shape");
if (x->in(0) == NULL && !x->is_DecodeNarrowPtr() &&
!(x->is_AddP() && x->in(AddPNode::Address)->is_AddP() && x->in(AddPNode::Address)->in(AddPNode::Base) == x->in(AddPNode::Base))) {
assert(!x->is_Load(), "load should be pinned"); assert(!x->is_Load(), "load should be pinned");
// Use a cast node to pin clone out of loop // Use a cast node to pin clone out of loop
Node* cast = NULL; Node* cast = NULL;
@ -1511,11 +1519,22 @@ void PhaseIdealLoop::try_sink_out_of_loop(Node* n) {
Node* in = x->in(k); Node* in = x->in(k);
if (in != NULL && n_loop->is_member(get_loop(get_ctrl(in)))) { if (in != NULL && n_loop->is_member(get_loop(get_ctrl(in)))) {
const Type* in_t = _igvn.type(in); const Type* in_t = _igvn.type(in);
cast = ConstraintCastNode::make_cast_for_type(x_ctrl, in, in_t); cast = ConstraintCastNode::make_cast_for_type(x_ctrl, in, in_t, ConstraintCastNode::UnconditionalDependency);
} }
if (cast != NULL) { if (cast != NULL) {
register_new_node(cast, x_ctrl); register_new_node(cast, x_ctrl);
x->replace_edge(in, cast); x->replace_edge(in, cast);
// Chain of AddP:
// 2- A CastPP of the base is only added now that both AddP nodes are sunk
if (x->is_AddP() && k == AddPNode::Base) {
for (DUIterator_Fast imax, i = x->fast_outs(imax); i < imax; i++) {
Node* u = x->fast_out(i);
if (u->is_AddP() && u->in(AddPNode::Base) == n->in(AddPNode::Base)) {
_igvn.replace_input_of(u, AddPNode::Base, cast);
assert(u->find_out_with(Op_AddP) == NULL, "more than 2 chained AddP nodes?");
}
}
}
break; break;
} }
} }

View file

@ -0,0 +1,57 @@
/*
* Copyright (c) 2021, Red Hat, 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.
*
* 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.
*/
/**
* @test
* @bug 8267988
* @summary C2: assert(!addp->is_AddP() || addp->in(AddPNode::Base)->is_top() || addp->in(AddPNode::Base) == n->in(AddPNode::Base)) failed: Base pointers must match (addp 1301)
*
* @run main/othervm -Xcomp -XX:CompileOnly=TestAddPChainWithDifferentBase TestAddPChainWithDifferentBase
*
*/
public class TestAddPChainWithDifferentBase {
static int x;
static int iArrFld[] = new int[400];
public static void main(String[] strArr) {
test();
}
static void test() {
int i6, i7 = 9, i8, i9 = 138;
for (i6 = 7; i6 > 1; i6 -= 3) {
for (i8 = i6; i8 < 4; i8++) {
try {
iArrFld[i8] = (52691 / i8);
i7 = (iArrFld[i8 + 1] % i9);
i7 = (412419036 / iArrFld[i8]);
} catch (ArithmeticException a_e) {
}
i9 += 13;
}
}
x = i7;
}
}