8168770: Fix for 8151988 causes performance regression on SPARC
Reversed and re-implemented fix for 8151988 to eagerly cut off control input of Div and Mod nodes. Reviewed-by: kvn
This commit is contained in:
parent
797316e4f1
commit
dd45be3f41
@ -3173,65 +3173,45 @@ void Compile::final_graph_reshaping_impl( Node *n, Final_Reshape_Counts &frc) {
|
||||
break;
|
||||
#endif
|
||||
|
||||
case Op_ModI: {
|
||||
Node* di = NULL;
|
||||
case Op_ModI:
|
||||
if (UseDivMod) {
|
||||
// Check if a%b and a/b both exist
|
||||
di = n->find_similar(Op_DivI);
|
||||
if (di) {
|
||||
Node* d = n->find_similar(Op_DivI);
|
||||
if (d) {
|
||||
// Replace them with a fused divmod if supported
|
||||
if (Matcher::has_match_rule(Op_DivModI)) {
|
||||
DivModINode* divmod = DivModINode::make(n);
|
||||
di->subsume_by(divmod->div_proj(), this);
|
||||
d->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(di, di->in(2));
|
||||
Node* sub = new SubINode(di->in(1), mult);
|
||||
Node* mult = new MulINode(d, d->in(2));
|
||||
Node* sub = new SubINode(d->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: {
|
||||
Node* dl = NULL;
|
||||
case Op_ModL:
|
||||
if (UseDivMod) {
|
||||
// Check if a%b and a/b both exist
|
||||
dl = n->find_similar(Op_DivL);
|
||||
if (dl) {
|
||||
Node* d = n->find_similar(Op_DivL);
|
||||
if (d) {
|
||||
// Replace them with a fused divmod if supported
|
||||
if (Matcher::has_match_rule(Op_DivModL)) {
|
||||
DivModLNode* divmod = DivModLNode::make(n);
|
||||
dl->subsume_by(divmod->div_proj(), this);
|
||||
d->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(dl, dl->in(2));
|
||||
Node* sub = new SubLNode(dl->in(1), mult);
|
||||
Node* mult = new MulLNode(d, d->in(2));
|
||||
Node* sub = new SubLNode(d->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:
|
||||
|
@ -474,16 +474,19 @@ Node *DivINode::Ideal(PhaseGVN *phase, bool can_reshape) {
|
||||
|
||||
const TypeInt *ti = t->isa_int();
|
||||
if( !ti ) return NULL;
|
||||
|
||||
// Check for useless control input
|
||||
// Check for excluding div-zero case
|
||||
if (in(0) && (ti->_hi < 0 || ti->_lo > 0)) {
|
||||
set_req(0, NULL); // Yank control input
|
||||
return this;
|
||||
}
|
||||
|
||||
if( !ti->is_con() ) return NULL;
|
||||
jint i = ti->get_con(); // Get divisor
|
||||
|
||||
if (i == 0) return NULL; // Dividing by zero constant does not idealize
|
||||
|
||||
if (in(0) != NULL) {
|
||||
phase->igvn_rehash_node_delayed(this);
|
||||
set_req(0, NULL); // Dividing by a not-zero constant; no faulting
|
||||
}
|
||||
|
||||
// Dividing by MININT does not optimize as a power-of-2 shift.
|
||||
if( i == min_jint ) return NULL;
|
||||
|
||||
@ -576,16 +579,19 @@ Node *DivLNode::Ideal( PhaseGVN *phase, bool can_reshape) {
|
||||
|
||||
const TypeLong *tl = t->isa_long();
|
||||
if( !tl ) return NULL;
|
||||
|
||||
// Check for useless control input
|
||||
// Check for excluding div-zero case
|
||||
if (in(0) && (tl->_hi < 0 || tl->_lo > 0)) {
|
||||
set_req(0, NULL); // Yank control input
|
||||
return this;
|
||||
}
|
||||
|
||||
if( !tl->is_con() ) return NULL;
|
||||
jlong l = tl->get_con(); // Get divisor
|
||||
|
||||
if (l == 0) return NULL; // Dividing by zero constant does not idealize
|
||||
|
||||
if (in(0) != NULL) {
|
||||
phase->igvn_rehash_node_delayed(this);
|
||||
set_req(0, NULL); // Dividing by a not-zero constant; no faulting
|
||||
}
|
||||
|
||||
// Dividing by MINLONG does not optimize as a power-of-2 shift.
|
||||
if( l == min_jlong ) return NULL;
|
||||
|
||||
@ -853,6 +859,13 @@ 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();
|
||||
@ -1017,6 +1030,13 @@ 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();
|
||||
|
Loading…
Reference in New Issue
Block a user