8145322: Code generated from unsafe loops can be slightly improved

Improve code generated from checkIndex and unsafe loops

Reviewed-by: kvn, thartmann
This commit is contained in:
Roland Westrelin 2016-01-11 16:33:27 +01:00
parent 5be1924e89
commit 631c143469
7 changed files with 93 additions and 18 deletions

View File

@ -1009,6 +1009,7 @@ static int vec_stack_to_stack_helper(CodeBuffer *cbuf, bool do_size, int src_off
__ vmovdqu(xmm0, Address(rsp, src_offset));
__ vmovdqu(Address(rsp, dst_offset), xmm0);
__ vmovdqu(xmm0, Address(rsp, -32));
break;
case Op_VecZ:
__ evmovdqul(Address(rsp, -64), xmm0, 2);
__ evmovdqul(xmm0, Address(rsp, src_offset), 2);
@ -1049,6 +1050,7 @@ static int vec_stack_to_stack_helper(CodeBuffer *cbuf, bool do_size, int src_off
"vmovdqu [rsp + #%d], xmm0\n\t"
"vmovdqu xmm0, [rsp - #32]",
src_offset, dst_offset);
break;
case Op_VecZ:
st->print("vmovdqu [rsp - #64], xmm0\t# 512-bit mem-mem spill\n\t"
"vmovdqu xmm0, [rsp + #%d]\n\t"

View File

@ -1079,6 +1079,7 @@ static void vec_stack_to_stack_helper(CodeBuffer *cbuf, int src_offset,
__ vmovdqu(xmm0, Address(rsp, src_offset));
__ vmovdqu(Address(rsp, dst_offset), xmm0);
__ vmovdqu(xmm0, Address(rsp, -32));
break;
case Op_VecZ:
__ evmovdqul(Address(rsp, -64), xmm0, 2);
__ evmovdqul(xmm0, Address(rsp, src_offset), 2);

View File

@ -215,6 +215,68 @@ const Type *CastIINode::Value(PhaseTransform *phase) const {
return res;
}
Node *CastIINode::Ideal(PhaseGVN *phase, bool can_reshape) {
Node* progress = ConstraintCastNode::Ideal(phase, can_reshape);
if (progress != NULL) {
return progress;
}
// transform:
// (CastII (AddI x const)) -> (AddI (CastII x) const)
// So the AddI has a chance to be optimized out
if (in(1)->Opcode() == Op_AddI) {
Node* in2 = in(1)->in(2);
const TypeInt* in2_t = phase->type(in2)->isa_int();
if (in2_t != NULL && in2_t->singleton()) {
int in2_const = in2_t->_lo;
const TypeInt* current_type = _type->is_int();
jlong new_lo_long = ((jlong)current_type->_lo) - in2_const;
jlong new_hi_long = ((jlong)current_type->_hi) - in2_const;
int new_lo = (int)new_lo_long;
int new_hi = (int)new_hi_long;
if (((jlong)new_lo) == new_lo_long && ((jlong)new_hi) == new_hi_long) {
Node* in1 = in(1)->in(1);
CastIINode* new_cast = (CastIINode*)clone();
AddINode* new_add = (AddINode*)in(1)->clone();
new_cast->set_type(TypeInt::make(new_lo, new_hi, current_type->_widen));
new_cast->set_req(1, in1);
new_add->set_req(1, phase->transform(new_cast));
return new_add;
}
}
}
// Similar to ConvI2LNode::Ideal() for the same reasons
if (can_reshape && !phase->C->major_progress()) {
const TypeInt* this_type = this->type()->is_int();
const TypeInt* in_type = phase->type(in(1))->isa_int();
if (in_type != NULL && this_type != NULL &&
(in_type->_lo != this_type->_lo ||
in_type->_hi != this_type->_hi)) {
int lo1 = this_type->_lo;
int hi1 = this_type->_hi;
int w1 = this_type->_widen;
if (lo1 >= 0) {
// Keep a range assertion of >=0.
lo1 = 0; hi1 = max_jint;
} else if (hi1 < 0) {
// Keep a range assertion of <0.
lo1 = min_jint; hi1 = -1;
} else {
lo1 = min_jint; hi1 = max_jint;
}
const TypeInt* wtype = TypeInt::make(MAX2(in_type->_lo, lo1),
MIN2(in_type->_hi, hi1),
MAX2((int)in_type->_widen, w1));
if (wtype != type()) {
set_type(wtype);
return this;
}
}
}
return NULL;
}
//=============================================================================
//------------------------------Identity---------------------------------------
// If input is already higher or equal to cast type, then this is an identity.

View File

@ -68,6 +68,7 @@ class CastIINode: public ConstraintCastNode {
virtual int Opcode() const;
virtual uint ideal_reg() const { return Op_RegI; }
virtual const Type *Value( PhaseTransform *phase ) const;
virtual Node *Ideal(PhaseGVN *phase, bool can_reshape);
};
//------------------------------CastPPNode-------------------------------------

View File

@ -903,23 +903,25 @@ const Type *PhiNode::Value( PhaseTransform *phase ) const {
return Type::TOP;
// Check for trip-counted loop. If so, be smarter.
CountedLoopNode *l = r->is_CountedLoop() ? r->as_CountedLoop() : NULL;
if( l && l->can_be_counted_loop(phase) &&
((const Node*)l->phi() == this) ) { // Trip counted loop!
CountedLoopNode* l = r->is_CountedLoop() ? r->as_CountedLoop() : NULL;
if (l && l->can_be_counted_loop(phase) &&
((const Node*)l->phi() == this)) { // Trip counted loop!
// protect against init_trip() or limit() returning NULL
const Node *init = l->init_trip();
const Node *limit = l->limit();
if( init != NULL && limit != NULL && l->stride_is_con() ) {
const TypeInt *lo = init ->bottom_type()->isa_int();
const TypeInt *hi = limit->bottom_type()->isa_int();
if( lo && hi ) { // Dying loops might have TOP here
int stride = l->stride_con();
if( stride < 0 ) { // Down-counter loop
const TypeInt *tmp = lo; lo = hi; hi = tmp;
stride = -stride;
const Node* stride = l->stride();
if (init != NULL && limit != NULL && stride != NULL) {
const TypeInt* lo = phase->type(init)->isa_int();
const TypeInt* hi = phase->type(limit)->isa_int();
const TypeInt* stride_t = phase->type(stride)->isa_int();
if (lo != NULL && hi != NULL && stride_t != NULL) { // Dying loops might have TOP here
assert(stride_t->_hi >= stride_t->_lo, "bad stride type");
if (stride_t->_hi < 0) { // Down-counter loop
swap(lo, hi);
return TypeInt::make(MIN2(lo->_lo, hi->_lo) , hi->_hi, 3);
} else if (stride_t->_lo >= 0) {
return TypeInt::make(lo->_lo, MAX2(lo->_hi, hi->_hi), 3);
}
if( lo->_hi < hi->_lo ) // Reversed endpoints are well defined :-(
return TypeInt::make(lo->_lo,hi->_hi,3);
}
}
}

View File

@ -815,6 +815,11 @@ bool PhaseIdealLoop::is_counted_loop( Node *x, IdealLoopTree *loop ) {
C->print_method(PHASE_AFTER_CLOOPS, 3);
// Capture bounds of the loop in the induction variable Phi before
// subsequent transformation (iteration splitting) obscures the
// bounds
l->phi()->as_Phi()->set_type(l->phi()->Value(&_igvn));
return true;
}
@ -3483,7 +3488,7 @@ void PhaseIdealLoop::build_loop_late( VectorSet &visited, Node_List &worklist, N
// Second pass finds latest legal placement, and ideal loop placement.
void PhaseIdealLoop::build_loop_late_post( Node *n ) {
if (n->req() == 2 && n->Opcode() == Op_ConvI2L && !C->major_progress() && !_verify_only) {
if (n->req() == 2 && (n->Opcode() == Op_ConvI2L || n->Opcode() == Op_CastII) && !C->major_progress() && !_verify_only) {
_igvn._worklist.push(n); // Maybe we'll normalize it, if no more loops.
}

View File

@ -3438,10 +3438,12 @@ bool SWPointer::offset_plus_k(Node* n, bool negate) {
if (opc == Op_ConvI2L) {
n = n->in(1);
}
_negate_invar = negate;
_invar = n;
NOT_PRODUCT(_tracer.offset_plus_k_10(n, _invar, _negate_invar, _offset);)
return true;
if (n->bottom_type()->isa_int()) {
_negate_invar = negate;
_invar = n;
NOT_PRODUCT(_tracer.offset_plus_k_10(n, _invar, _negate_invar, _offset);)
return true;
}
}
NOT_PRODUCT(_tracer.offset_plus_k_11(n);)