Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

8264586: [lworld] C2 compilation fails due to infinite loop in PhaseIterGVN::optimize #377

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
@@ -1955,9 +1955,6 @@ static bool return_val_keeps_allocations_alive(Node* ret_val) {
}

void Compile::process_inline_types(PhaseIterGVN &igvn, bool remove) {
if (_inline_type_nodes.length() == 0) {
return;
}
// Make sure that the return value does not keep an otherwise unused allocation alive
if (tf()->returns_inline_type_as_fields()) {
Node* ret = NULL;
@@ -1978,6 +1975,9 @@ void Compile::process_inline_types(PhaseIterGVN &igvn, bool remove) {
}
}
}
if (_inline_type_nodes.length() == 0) {
return;
}
if (remove) {
// Remove inline type nodes
while (_inline_type_nodes.length() > 0) {
@@ -3361,13 +3361,8 @@ void ConnectionGraph::split_unique_types(GrowableArray<Node *> &alloc_worklist,
memnode_worklist.append_if_missing(use);
}
} else if (use->Opcode() == Op_Return) {
assert(_compile->tf()->returns_inline_type_as_fields(), "must return an inline type");
// Get InlineKlass by removing the tag bit from the metadata pointer
Node* klass = use->in(TypeFunc::Parms);
intptr_t ptr = igvn->type(klass)->isa_rawptr()->get_con();
clear_nth_bit(ptr, 0);
assert(Metaspace::contains((void*)ptr), "should be klass");
assert(((InlineKlass*)ptr)->contains_oops(), "returned inline type must contain a reference field");
// Allocation is referenced by field of returned inline type
assert(_compile->tf()->returns_inline_type_as_fields(), "EA: unexpected reference by ReturnNode");
} else {
uint op = use->Opcode();
if ((op == Op_StrCompressedCopy || op == Op_StrInflatedCopy) &&
@@ -379,7 +379,7 @@ InlineTypePtrNode* InlineTypeBaseNode::buffer(GraphKit* kit, bool safe_for_repla

// Oop is non-NULL, use it
region->init_req(1, kit->control());
PhiNode* oop = PhiNode::make(region, not_null_oop, inline_ptr());
PhiNode* oop = PhiNode::make(region, not_null_oop, inline_ptr()->join_speculative(TypePtr::NOTNULL));
PhiNode* io = PhiNode::make(region, kit->i_o(), Type::ABIO);
PhiNode* mem = PhiNode::make(region, kit->merged_memory(), Type::MEMORY, TypePtr::BOTTOM);

@@ -933,3 +933,35 @@ void InlineTypeNode::remove_redundant_allocations(PhaseIterGVN* igvn, PhaseIdeal
}
}
}

Node* InlineTypePtrNode::Ideal(PhaseGVN* phase, bool can_reshape) {
if (can_reshape) {
// Remove useless InlineTypePtr nodes that might keep other nodes alive
ResourceMark rm;
Unique_Node_List users;
users.push(this);
bool useless = true;
for (uint i = 0; i < users.size(); ++i) {
Node* use = users.at(i);
if (use->is_Cmp() || use->Opcode() == Op_Return || use->Opcode() == Op_CastP2X || (use == this && i != 0) ||
(use->is_Load() && use->outcnt() == 1 && use->unique_out() == this)) {
// No need to keep track of field values, we can just use the oop
continue;
}
if (use->is_Load() || use->is_Store() || (use->is_InlineTypeBase() && use != this) || use->is_SafePoint()) {
// We need to keep track of field values to allow the use to be folded/scalarized
useless = false;
break;
}
for (DUIterator_Fast jmax, j = use->fast_outs(jmax); j < jmax; j++) {
users.push(use->fast_out(j));
}
}
if (useless) {
phase->is_IterGVN()->replace_node(this, get_oop());
return NULL;
}
}

return InlineTypeBaseNode::Ideal(phase, can_reshape);
}
@@ -168,6 +168,8 @@ class InlineTypePtrNode : public InlineTypeBaseNode {
}
}

virtual Node* Ideal(PhaseGVN* phase, bool can_reshape);

public:
virtual int Opcode() const;
};
@@ -2377,6 +2377,8 @@ bool LibraryCallKit::inline_unsafe_access(bool is_store, const BasicType type, c
if (is_store) {
const Type* val_t = _gvn.type(val);
if (!val_t->isa_inlinetype() || val_t->inline_klass() != inline_klass) {
set_map(old_map);
set_sp(old_sp);
return false;
}
}
@@ -204,6 +204,21 @@ void test13(MyValue5[] array) {
}
}

void test14(boolean b, MyValue4 val) {
for (int i = 0; i < 10; ++i) {
if (b) {
val = MyValue4.default;
}
MyValue4[] array = new MyValue4[1];
array[0] = val;

for (int j = 0; j < 5; ++j) {
for (int k = 0; k < 5; ++k) {
}
}
}
}

public static void main(String[] args) {
TestGenerated t = new TestGenerated();
EmptyValue[] array1 = { new EmptyValue() };
@@ -227,6 +242,7 @@ public static void main(String[] args) {
t.test11(array4);
t.test12();
t.test13(array5);
t.test14(false, MyValue4.default);
}
}
}