8145322: Code generated from unsafe loops can be slightly improved
authorroland
Mon, 11 Jan 2016 16:33:27 +0100
changeset 35549 3415401a6b6e
parent 35547 0ee84aa8e705
child 35550 633a22d66bd7
8145322: Code generated from unsafe loops can be slightly improved Summary: improve code generated from checkIndex and unsafe loops Reviewed-by: kvn, thartmann
hotspot/src/cpu/x86/vm/x86_32.ad
hotspot/src/cpu/x86/vm/x86_64.ad
hotspot/src/share/vm/opto/castnode.cpp
hotspot/src/share/vm/opto/castnode.hpp
hotspot/src/share/vm/opto/cfgnode.cpp
hotspot/src/share/vm/opto/loopnode.cpp
hotspot/src/share/vm/opto/superword.cpp
--- 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);)