8151988: Hotspot deoptimizes div/mod pair usage

Don't remove control edge of Mod node until DivMod node matching

Reviewed-by: kvn
This commit is contained in:
Vivek Deshpande 2016-08-23 12:26:05 -07:00
parent bed33a8972
commit 82de2bf10e
2 changed files with 32 additions and 26 deletions
hotspot/src/share/vm/opto

@ -3159,45 +3159,65 @@ void Compile::final_graph_reshaping_impl( Node *n, Final_Reshape_Counts &frc) {
break;
#endif
case Op_ModI:
case Op_ModI: {
Node* di = NULL;
if (UseDivMod) {
// Check if a%b and a/b both exist
Node* d = n->find_similar(Op_DivI);
if (d) {
di = n->find_similar(Op_DivI);
if (di) {
// Replace them with a fused divmod if supported
if (Matcher::has_match_rule(Op_DivModI)) {
DivModINode* divmod = DivModINode::make(n);
d->subsume_by(divmod->div_proj(), this);
di->subsume_by(divmod->div_proj(), this);
n->subsume_by(divmod->mod_proj(), this);
} else {
// replace a%b with a-((a/b)*b)
Node* mult = new MulINode(d, d->in(2));
Node* sub = new SubINode(d->in(1), mult);
Node* mult = new MulINode(di, di->in(2));
Node* sub = new SubINode(di->in(1), mult);
n->subsume_by(sub, this);
}
}
}
if (di == NULL) {
// Remove useless control edge in case of not mod-zero.
const Type *t = n->in(2)->bottom_type();
const TypeInt *ti = t->is_int();
if (n->in(0) && (ti->_hi < 0 || ti->_lo > 0)) {
n->set_req(0, NULL);
}
}
break;
}
case Op_ModL:
case Op_ModL: {
Node* dl = NULL;
if (UseDivMod) {
// Check if a%b and a/b both exist
Node* d = n->find_similar(Op_DivL);
if (d) {
dl = n->find_similar(Op_DivL);
if (dl) {
// Replace them with a fused divmod if supported
if (Matcher::has_match_rule(Op_DivModL)) {
DivModLNode* divmod = DivModLNode::make(n);
d->subsume_by(divmod->div_proj(), this);
dl->subsume_by(divmod->div_proj(), this);
n->subsume_by(divmod->mod_proj(), this);
} else {
// replace a%b with a-((a/b)*b)
Node* mult = new MulLNode(d, d->in(2));
Node* sub = new SubLNode(d->in(1), mult);
Node* mult = new MulLNode(dl, dl->in(2));
Node* sub = new SubLNode(dl->in(1), mult);
n->subsume_by(sub, this);
}
}
}
if (dl == NULL) {
// Remove useless control edge in case of not mod-zero.
const Type *t = n->in(2)->bottom_type();
const TypeLong *tl = t->is_long();
if (n->in(0) && (tl->_hi < 0 || tl->_lo > 0)) {
n->set_req(0, NULL);
}
}
break;
}
case Op_LoadVector:
case Op_StoreVector:

@ -853,13 +853,6 @@ Node *ModINode::Ideal(PhaseGVN *phase, bool can_reshape) {
if( t == Type::TOP ) return NULL;
const TypeInt *ti = t->is_int();
// Check for useless control input
// Check for excluding mod-zero case
if( in(0) && (ti->_hi < 0 || ti->_lo > 0) ) {
set_req(0, NULL); // Yank control input
return this;
}
// See if we are MOD'ing by 2^k or 2^k-1.
if( !ti->is_con() ) return NULL;
jint con = ti->get_con();
@ -1024,13 +1017,6 @@ Node *ModLNode::Ideal(PhaseGVN *phase, bool can_reshape) {
if( t == Type::TOP ) return NULL;
const TypeLong *tl = t->is_long();
// Check for useless control input
// Check for excluding mod-zero case
if( in(0) && (tl->_hi < 0 || tl->_lo > 0) ) {
set_req(0, NULL); // Yank control input
return this;
}
// See if we are MOD'ing by 2^k or 2^k-1.
if( !tl->is_con() ) return NULL;
jlong con = tl->get_con();