8265767: compiler/eliminateAutobox/TestIntBoxing.java crashes on arm32 after 8264649 in debug VMs
Reviewed-by: kvn, thartmann
This commit is contained in:
parent
05e601748a
commit
ee5bba0dc4
@ -1367,10 +1367,10 @@ Node* StoreNode::convert_to_reinterpret_store(PhaseGVN& gvn, Node* val, const Ty
|
|||||||
// merging a newly allocated object and a load from the cache.
|
// merging a newly allocated object and a load from the cache.
|
||||||
// We want to replace this load with the original incoming
|
// We want to replace this load with the original incoming
|
||||||
// argument to the valueOf call.
|
// argument to the valueOf call.
|
||||||
Node* LoadNode::eliminate_autobox(PhaseGVN* phase) {
|
Node* LoadNode::eliminate_autobox(PhaseIterGVN* igvn) {
|
||||||
assert(phase->C->eliminate_boxing(), "sanity");
|
assert(igvn->C->eliminate_boxing(), "sanity");
|
||||||
intptr_t ignore = 0;
|
intptr_t ignore = 0;
|
||||||
Node* base = AddPNode::Ideal_base_and_offset(in(Address), phase, ignore);
|
Node* base = AddPNode::Ideal_base_and_offset(in(Address), igvn, ignore);
|
||||||
if ((base == NULL) || base->is_Phi()) {
|
if ((base == NULL) || base->is_Phi()) {
|
||||||
// Push the loads from the phi that comes from valueOf up
|
// Push the loads from the phi that comes from valueOf up
|
||||||
// through it to allow elimination of the loads and the recovery
|
// through it to allow elimination of the loads and the recovery
|
||||||
@ -1404,7 +1404,7 @@ Node* LoadNode::eliminate_autobox(PhaseGVN* phase) {
|
|||||||
if (count > 0 && elements[0]->is_Con() &&
|
if (count > 0 && elements[0]->is_Con() &&
|
||||||
(count == 1 ||
|
(count == 1 ||
|
||||||
(count == 2 && elements[1]->Opcode() == Op_LShiftX &&
|
(count == 2 && elements[1]->Opcode() == Op_LShiftX &&
|
||||||
elements[1]->in(2) == phase->intcon(shift)))) {
|
elements[1]->in(2) == igvn->intcon(shift)))) {
|
||||||
ciObjArray* array = base_type->const_oop()->as_obj_array();
|
ciObjArray* array = base_type->const_oop()->as_obj_array();
|
||||||
// Fetch the box object cache[0] at the base of the array and get its value
|
// Fetch the box object cache[0] at the base of the array and get its value
|
||||||
ciInstance* box = array->obj_at(0)->as_instance();
|
ciInstance* box = array->obj_at(0)->as_instance();
|
||||||
@ -1431,43 +1431,45 @@ Node* LoadNode::eliminate_autobox(PhaseGVN* phase) {
|
|||||||
// Add up all the offsets making of the address of the load
|
// Add up all the offsets making of the address of the load
|
||||||
Node* result = elements[0];
|
Node* result = elements[0];
|
||||||
for (int i = 1; i < count; i++) {
|
for (int i = 1; i < count; i++) {
|
||||||
result = phase->transform(new AddXNode(result, elements[i]));
|
result = igvn->transform(new AddXNode(result, elements[i]));
|
||||||
}
|
}
|
||||||
// Remove the constant offset from the address and then
|
// Remove the constant offset from the address and then
|
||||||
result = phase->transform(new AddXNode(result, phase->MakeConX(-(int)offset)));
|
result = igvn->transform(new AddXNode(result, igvn->MakeConX(-(int)offset)));
|
||||||
// remove the scaling of the offset to recover the original index.
|
// remove the scaling of the offset to recover the original index.
|
||||||
if (result->Opcode() == Op_LShiftX && result->in(2) == phase->intcon(shift)) {
|
if (result->Opcode() == Op_LShiftX && result->in(2) == igvn->intcon(shift)) {
|
||||||
// Peel the shift off directly but wrap it in a dummy node
|
// Peel the shift off directly but wrap it in a dummy node
|
||||||
// since Ideal can't return existing nodes
|
// since Ideal can't return existing nodes
|
||||||
result = new RShiftXNode(result->in(1), phase->intcon(0));
|
igvn->_worklist.push(result); // remove dead node later
|
||||||
|
result = new RShiftXNode(result->in(1), igvn->intcon(0));
|
||||||
} else if (result->is_Add() && result->in(2)->is_Con() &&
|
} else if (result->is_Add() && result->in(2)->is_Con() &&
|
||||||
result->in(1)->Opcode() == Op_LShiftX &&
|
result->in(1)->Opcode() == Op_LShiftX &&
|
||||||
result->in(1)->in(2) == phase->intcon(shift)) {
|
result->in(1)->in(2) == igvn->intcon(shift)) {
|
||||||
// We can't do general optimization: ((X<<Z) + Y) >> Z ==> X + (Y>>Z)
|
// We can't do general optimization: ((X<<Z) + Y) >> Z ==> X + (Y>>Z)
|
||||||
// but for boxing cache access we know that X<<Z will not overflow
|
// but for boxing cache access we know that X<<Z will not overflow
|
||||||
// (there is range check) so we do this optimizatrion by hand here.
|
// (there is range check) so we do this optimizatrion by hand here.
|
||||||
Node* add_con = new RShiftXNode(result->in(2), phase->intcon(shift));
|
igvn->_worklist.push(result); // remove dead node later
|
||||||
result = new AddXNode(result->in(1)->in(1), phase->transform(add_con));
|
Node* add_con = new RShiftXNode(result->in(2), igvn->intcon(shift));
|
||||||
|
result = new AddXNode(result->in(1)->in(1), igvn->transform(add_con));
|
||||||
} else {
|
} else {
|
||||||
result = new RShiftXNode(result, phase->intcon(shift));
|
result = new RShiftXNode(result, igvn->intcon(shift));
|
||||||
}
|
}
|
||||||
#ifdef _LP64
|
#ifdef _LP64
|
||||||
if (bt != T_LONG) {
|
if (bt != T_LONG) {
|
||||||
result = new ConvL2INode(phase->transform(result));
|
result = new ConvL2INode(igvn->transform(result));
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
if (bt == T_LONG) {
|
if (bt == T_LONG) {
|
||||||
result = new ConvI2LNode(phase->transform(result));
|
result = new ConvI2LNode(igvn->transform(result));
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
// Boxing/unboxing can be done from signed & unsigned loads (e.g. LoadUB -> ... -> LoadB pair).
|
// Boxing/unboxing can be done from signed & unsigned loads (e.g. LoadUB -> ... -> LoadB pair).
|
||||||
// Need to preserve unboxing load type if it is unsigned.
|
// Need to preserve unboxing load type if it is unsigned.
|
||||||
switch(this->Opcode()) {
|
switch(this->Opcode()) {
|
||||||
case Op_LoadUB:
|
case Op_LoadUB:
|
||||||
result = new AndINode(phase->transform(result), phase->intcon(0xFF));
|
result = new AndINode(igvn->transform(result), igvn->intcon(0xFF));
|
||||||
break;
|
break;
|
||||||
case Op_LoadUS:
|
case Op_LoadUS:
|
||||||
result = new AndINode(phase->transform(result), phase->intcon(0xFFFF));
|
result = new AndINode(igvn->transform(result), igvn->intcon(0xFFFF));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
@ -1760,7 +1762,8 @@ Node *LoadNode::Ideal(PhaseGVN *phase, bool can_reshape) {
|
|||||||
(t_oop->is_known_instance_field() ||
|
(t_oop->is_known_instance_field() ||
|
||||||
t_oop->is_ptr_to_boxed_value())) {
|
t_oop->is_ptr_to_boxed_value())) {
|
||||||
PhaseIterGVN *igvn = phase->is_IterGVN();
|
PhaseIterGVN *igvn = phase->is_IterGVN();
|
||||||
if (igvn != NULL && igvn->_worklist.member(opt_mem)) {
|
assert(igvn != NULL, "must be PhaseIterGVN when can_reshape is true");
|
||||||
|
if (igvn->_worklist.member(opt_mem)) {
|
||||||
// Delay this transformation until memory Phi is processed.
|
// Delay this transformation until memory Phi is processed.
|
||||||
igvn->_worklist.push(this);
|
igvn->_worklist.push(this);
|
||||||
return NULL;
|
return NULL;
|
||||||
@ -1770,7 +1773,7 @@ Node *LoadNode::Ideal(PhaseGVN *phase, bool can_reshape) {
|
|||||||
if (result != NULL) return result;
|
if (result != NULL) return result;
|
||||||
|
|
||||||
if (t_oop->is_ptr_to_boxed_value()) {
|
if (t_oop->is_ptr_to_boxed_value()) {
|
||||||
Node* result = eliminate_autobox(phase);
|
Node* result = eliminate_autobox(igvn);
|
||||||
if (result != NULL) return result;
|
if (result != NULL) return result;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -248,7 +248,7 @@ public:
|
|||||||
Node* split_through_phi(PhaseGVN *phase);
|
Node* split_through_phi(PhaseGVN *phase);
|
||||||
|
|
||||||
// Recover original value from boxed values
|
// Recover original value from boxed values
|
||||||
Node *eliminate_autobox(PhaseGVN *phase);
|
Node *eliminate_autobox(PhaseIterGVN *igvn);
|
||||||
|
|
||||||
// Compute a new Type for this node. Basically we just do the pre-check,
|
// Compute a new Type for this node. Basically we just do the pre-check,
|
||||||
// then call the virtual add() to set the type.
|
// then call the virtual add() to set the type.
|
||||||
|
Loading…
x
Reference in New Issue
Block a user