Skip to content

Commit

Permalink
8336782: [lworld] CallStaticJavaNode::remove_useless_allocation does …
Browse files Browse the repository at this point in the history
…not handle dying subgraph
  • Loading branch information
TobiHartmann committed Aug 15, 2024
1 parent 5ccdcef commit 2b99b78
Show file tree
Hide file tree
Showing 2 changed files with 26 additions and 28 deletions.
52 changes: 25 additions & 27 deletions src/hotspot/share/opto/callnode.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1125,9 +1125,9 @@ bool CallStaticJavaNode::cmp( const Node &n ) const {

Node* CallStaticJavaNode::Ideal(PhaseGVN* phase, bool can_reshape) {
if (can_reshape && uncommon_trap_request() != 0) {
if (remove_useless_allocation(phase, in(0), in(TypeFunc::Memory), in(TypeFunc::Parms))) {
PhaseIterGVN* igvn = phase->is_IterGVN();
if (remove_unknown_flat_array_load(igvn, in(0), in(TypeFunc::Memory), in(TypeFunc::Parms))) {
if (!in(0)->is_Region()) {
PhaseIterGVN* igvn = phase->is_IterGVN();
igvn->replace_input_of(this, 0, phase->C->top());
}
return this;
Expand Down Expand Up @@ -1186,16 +1186,13 @@ int CallStaticJavaNode::extract_uncommon_trap_request(const Node* call) {
return call->in(TypeFunc::Parms)->bottom_type()->is_int()->get_con();
}

bool CallStaticJavaNode::remove_useless_allocation(PhaseGVN *phase, Node* ctl, Node* mem, Node* unc_arg) {
// Split if can cause the flat array branch of an array load to
// end in an uncommon trap. In that case, the allocation of the
// loaded value and its initialization is useless. Eliminate it. use
// the jvm state of the allocation to create a new uncommon trap
// call at the load.
// Split if can cause the flat array branch of an array load with unknown type (see
// Parse::array_load) to end in an uncommon trap. In that case, the call to
// 'load_unknown_inline' is useless. Replace it with an uncommon trap with the same JVMState.
bool CallStaticJavaNode::remove_unknown_flat_array_load(PhaseIterGVN* igvn, Node* ctl, Node* mem, Node* unc_arg) {
if (ctl == nullptr || ctl->is_top() || mem == nullptr || mem->is_top() || !mem->is_MergeMem()) {
return false;
}
PhaseIterGVN* igvn = phase->is_IterGVN();
if (ctl->is_Region()) {
bool res = false;
for (uint i = 1; i < ctl->req(); i++) {
Expand All @@ -1206,17 +1203,17 @@ bool CallStaticJavaNode::remove_useless_allocation(PhaseGVN *phase, Node* ctl, N
mms.set_memory(m->in(i));
}
}
if (remove_useless_allocation(phase, ctl->in(i), mm, unc_arg)) {
if (remove_unknown_flat_array_load(igvn, ctl->in(i), mm, unc_arg)) {
res = true;
if (!ctl->in(i)->is_Region()) {
igvn->replace_input_of(ctl, i, phase->C->top());
igvn->replace_input_of(ctl, i, igvn->C->top());
}
}
igvn->remove_dead_node(mm);
}
return res;
}
// verify the control flow is ok
// Verify the control flow is ok
Node* call = ctl;
MemBarNode* membar = nullptr;
for (;;) {
Expand All @@ -1225,7 +1222,7 @@ bool CallStaticJavaNode::remove_useless_allocation(PhaseGVN *phase, Node* ctl, N
}
if (call->is_Proj() || call->is_Catch() || call->is_MemBar()) {
call = call->in(0);
} else if (call->Opcode() == Op_CallStaticJava &&
} else if (call->Opcode() == Op_CallStaticJava && !call->in(0)->is_top() &&
call->as_Call()->entry_point() == OptoRuntime::load_unknown_inline_Java()) {
assert(call->in(0)->is_Proj() && call->in(0)->in(0)->is_MemBar(), "missing membar");
membar = call->in(0)->in(0)->as_MemBar();
Expand All @@ -1236,21 +1233,21 @@ bool CallStaticJavaNode::remove_useless_allocation(PhaseGVN *phase, Node* ctl, N
}

JVMState* jvms = call->jvms();
if (phase->C->too_many_traps(jvms->method(), jvms->bci(), Deoptimization::trap_request_reason(uncommon_trap_request()))) {
if (igvn->C->too_many_traps(jvms->method(), jvms->bci(), Deoptimization::trap_request_reason(uncommon_trap_request()))) {
return false;
}

Node* alloc_mem = call->in(TypeFunc::Memory);
if (alloc_mem == nullptr || alloc_mem->is_top()) {
Node* call_mem = call->in(TypeFunc::Memory);
if (call_mem == nullptr || call_mem->is_top()) {
return false;
}
if (!alloc_mem->is_MergeMem()) {
alloc_mem = MergeMemNode::make(alloc_mem);
igvn->register_new_node_with_optimizer(alloc_mem);
if (!call_mem->is_MergeMem()) {
call_mem = MergeMemNode::make(call_mem);
igvn->register_new_node_with_optimizer(call_mem);
}

// and that there's no unexpected side effect
for (MergeMemStream mms2(mem->as_MergeMem(), alloc_mem->as_MergeMem()); mms2.next_non_empty2(); ) {
// Verify that there's no unexpected side effect
for (MergeMemStream mms2(mem->as_MergeMem(), call_mem->as_MergeMem()); mms2.next_non_empty2(); ) {
Node* m1 = mms2.is_empty() ? mms2.base_memory() : mms2.memory();
Node* m2 = mms2.memory2();

Expand Down Expand Up @@ -1280,8 +1277,8 @@ bool CallStaticJavaNode::remove_useless_allocation(PhaseGVN *phase, Node* ctl, N
}
}
}
if (alloc_mem->outcnt() == 0) {
igvn->remove_dead_node(alloc_mem);
if (call_mem->outcnt() == 0) {
igvn->remove_dead_node(call_mem);
}

// Remove membar preceding the call
Expand All @@ -1298,13 +1295,14 @@ bool CallStaticJavaNode::remove_useless_allocation(PhaseGVN *phase, Node* ctl, N
unc->set_cnt(PROB_UNLIKELY_MAG(4));
unc->copy_call_debug_info(igvn, call->as_CallStaticJava());

igvn->replace_input_of(call, 0, phase->C->top());
// Replace the call with an uncommon trap
igvn->replace_input_of(call, 0, igvn->C->top());

igvn->register_new_node_with_optimizer(unc);

Node* ctrl = phase->transform(new ProjNode(unc, TypeFunc::Control));
Node* halt = phase->transform(new HaltNode(ctrl, call->in(TypeFunc::FramePtr), "uncommon trap returned which should never happen"));
igvn->add_input_to(phase->C->root(), halt);
Node* ctrl = igvn->transform(new ProjNode(unc, TypeFunc::Control));
Node* halt = igvn->transform(new HaltNode(ctrl, call->in(TypeFunc::FramePtr), "uncommon trap returned which should never happen"));
igvn->add_input_to(igvn->C->root(), halt);

return true;
}
Expand Down
2 changes: 1 addition & 1 deletion src/hotspot/share/opto/callnode.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -819,7 +819,7 @@ class CallStaticJavaNode : public CallJavaNode {
virtual bool cmp( const Node &n ) const;
virtual uint size_of() const; // Size is bigger

bool remove_useless_allocation(PhaseGVN *phase, Node* ctl, Node* mem, Node* unc_arg);
bool remove_unknown_flat_array_load(PhaseIterGVN* phase, Node* ctl, Node* mem, Node* unc_arg);

public:
CallStaticJavaNode(Compile* C, const TypeFunc* tf, address addr, ciMethod* method)
Expand Down

0 comments on commit 2b99b78

Please sign in to comment.