Skip to content
Closed
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
80 changes: 37 additions & 43 deletions src/hotspot/share/opto/ifnode.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1015,63 +1015,57 @@ bool IfNode::fold_compares_helper(ProjNode* proj, ProjNode* success, ProjNode* f
const TypeInt* type2 = filtered_int_type(igvn, n, fail);
if (type2 != nullptr) {
failtype = failtype->join(type2)->is_int();
if (failtype->_lo > failtype->_hi) {
if (failtype->empty()) {
// previous if determines the result of this if so
// replace Bool with constant
igvn->replace_input_of(this, 1, igvn->intcon(success->_con));
return true;
}
}
}
lo = nullptr;
hi = nullptr;
return false;
}

assert(lo != nullptr && hi != nullptr, "sanity");
Node* hook = new Node(lo); // Add a use to lo to prevent him from dying
// Merge the two compares into a single unsigned compare by building (CmpU (n - lo) (hi - lo))
Node* adjusted_val = igvn->transform(new SubINode(n, lo));
if (adjusted_lim == nullptr) {
adjusted_lim = igvn->transform(new SubINode(hi, lo));
}
hook->destruct(igvn);

if (lo && hi) {
Node* hook = new Node(1);
hook->init_req(0, lo); // Add a use to lo to prevent him from dying
// Merge the two compares into a single unsigned compare by building (CmpU (n - lo) (hi - lo))
Node* adjusted_val = igvn->transform(new SubINode(n, lo));
if (adjusted_lim == nullptr) {
adjusted_lim = igvn->transform(new SubINode(hi, lo));
if (igvn->type(adjusted_lim)->is_int()->_lo < 0 &&
!igvn->C->post_loop_opts_phase()) {
// If range check elimination applies to this comparison, it includes code to protect from overflows that may
// cause the main loop to be skipped entirely. Delay this transformation.
// Example:
// for (int i = 0; i < limit; i++) {
// if (i < max_jint && i > min_jint) {...
// }
// Comparisons folded as:
// i - min_jint - 1 <u -2
// when RC applies, main loop limit becomes:
// min(limit, max(-2 + min_jint + 1, min_jint))
// = min(limit, min_jint)
// = min_jint
if (adjusted_val->outcnt() == 0) {
igvn->remove_dead_node(adjusted_val);
}
hook->destruct(igvn);

int lo = igvn->type(adjusted_lim)->is_int()->_lo;
if (lo < 0) {
// If range check elimination applies to this comparison, it includes code to protect from overflows that may
// cause the main loop to be skipped entirely. Delay this transformation.
// Example:
// for (int i = 0; i < limit; i++) {
// if (i < max_jint && i > min_jint) {...
// }
// Comparisons folded as:
// i - min_jint - 1 <u -2
// when RC applies, main loop limit becomes:
// min(limit, max(-2 + min_jint + 1, min_jint))
// = min(limit, min_jint)
// = min_jint
if (!igvn->C->post_loop_opts_phase()) {
if (adjusted_val->outcnt() == 0) {
igvn->remove_dead_node(adjusted_val);
}
if (adjusted_lim->outcnt() == 0) {
igvn->remove_dead_node(adjusted_lim);
}
igvn->C->record_for_post_loop_opts_igvn(this);
return false;
}
if (adjusted_lim->outcnt() == 0) {
igvn->remove_dead_node(adjusted_lim);
}
igvn->C->record_for_post_loop_opts_igvn(this);
return false;
}

Node* newcmp = igvn->transform(new CmpUNode(adjusted_val, adjusted_lim));
Node* newbool = igvn->transform(new BoolNode(newcmp, cond));
Node* newcmp = igvn->transform(new CmpUNode(adjusted_val, adjusted_lim));
Node* newbool = igvn->transform(new BoolNode(newcmp, cond));

igvn->replace_input_of(dom_iff, 1, igvn->intcon(proj->_con));
igvn->replace_input_of(this, 1, newbool);
igvn->replace_input_of(dom_iff, 1, igvn->intcon(proj->_con));
igvn->replace_input_of(this, 1, newbool);

return true;
}
return false;
return true;
}

// Merge the branches that trap for this If and the dominating If into
Expand Down