8145322: Code generated from unsafe loops can be slightly improved
Summary: improve code generated from checkIndex and unsafe loops
Reviewed-by: kvn, thartmann
--- a/hotspot/src/cpu/x86/vm/x86_32.ad Mon Jan 11 14:23:35 2016 +0100
+++ b/hotspot/src/cpu/x86/vm/x86_32.ad Mon Jan 11 16:33:27 2016 +0100
@@ -1009,6 +1009,7 @@
__ 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 @@
"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"
--- a/hotspot/src/cpu/x86/vm/x86_64.ad Mon Jan 11 14:23:35 2016 +0100
+++ b/hotspot/src/cpu/x86/vm/x86_64.ad Mon Jan 11 16:33:27 2016 +0100
@@ -1079,6 +1079,7 @@
__ 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);
--- a/hotspot/src/share/vm/opto/castnode.cpp Mon Jan 11 14:23:35 2016 +0100
+++ b/hotspot/src/share/vm/opto/castnode.cpp Mon Jan 11 16:33:27 2016 +0100
@@ -215,6 +215,68 @@
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.
--- a/hotspot/src/share/vm/opto/castnode.hpp Mon Jan 11 14:23:35 2016 +0100
+++ b/hotspot/src/share/vm/opto/castnode.hpp Mon Jan 11 16:33:27 2016 +0100
@@ -68,6 +68,7 @@
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-------------------------------------
--- a/hotspot/src/share/vm/opto/cfgnode.cpp Mon Jan 11 14:23:35 2016 +0100
+++ b/hotspot/src/share/vm/opto/cfgnode.cpp Mon Jan 11 16:33:27 2016 +0100
@@ -903,23 +903,25 @@
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);
}
}
}
--- a/hotspot/src/share/vm/opto/loopnode.cpp Mon Jan 11 14:23:35 2016 +0100
+++ b/hotspot/src/share/vm/opto/loopnode.cpp Mon Jan 11 16:33:27 2016 +0100
@@ -815,6 +815,11 @@
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 @@
// 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.
}
--- a/hotspot/src/share/vm/opto/superword.cpp Mon Jan 11 14:23:35 2016 +0100
+++ b/hotspot/src/share/vm/opto/superword.cpp Mon Jan 11 16:33:27 2016 +0100
@@ -3438,10 +3438,12 @@
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);)