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:
parent
5be1924e89
commit
631c143469
@ -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"
|
||||
|
@ -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);
|
||||
|
@ -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.
|
||||
|
@ -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-------------------------------------
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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.
|
||||
}
|
||||
|
||||
|
@ -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);)
|
||||
|
Loading…
Reference in New Issue
Block a user