8042786: Proper fix for 8032566
authorkvn
Fri, 16 May 2014 12:05:14 -0700
changeset 24479 20eb4c752fb5
parent 24478 e7dad659b819
child 24480 e8a8b38149fb
8042786: Proper fix for 8032566 Summary: Check for overflow cases in range checks and collapse it if we can. Reviewed-by: jrose, iveresov
hotspot/src/share/vm/opto/c2_globals.hpp
hotspot/src/share/vm/opto/callGenerator.cpp
hotspot/src/share/vm/opto/doCall.cpp
hotspot/src/share/vm/opto/ifnode.cpp
hotspot/src/share/vm/opto/phaseX.cpp
hotspot/src/share/vm/opto/subnode.cpp
hotspot/src/share/vm/opto/subnode.hpp
--- a/hotspot/src/share/vm/opto/c2_globals.hpp	Mon Jan 27 10:20:51 2014 -0800
+++ b/hotspot/src/share/vm/opto/c2_globals.hpp	Fri May 16 12:05:14 2014 -0700
@@ -452,7 +452,7 @@
   notproduct(bool, PrintEliminateLocks, false,                              \
           "Print out when locks are eliminated")                            \
                                                                             \
-  product(bool, EliminateAutoBox, false,                                    \
+  product(bool, EliminateAutoBox, true,                                     \
           "Control optimizations for autobox elimination")                  \
                                                                             \
   diagnostic(bool, UseImplicitStableValues, true,                           \
--- a/hotspot/src/share/vm/opto/callGenerator.cpp	Mon Jan 27 10:20:51 2014 -0800
+++ b/hotspot/src/share/vm/opto/callGenerator.cpp	Fri May 16 12:05:14 2014 -0700
@@ -391,7 +391,7 @@
   }
 
   // Setup default node notes to be picked up by the inlining
-  Node_Notes* old_nn = C->default_node_notes();
+  Node_Notes* old_nn = C->node_notes_at(call->_idx);
   if (old_nn != NULL) {
     Node_Notes* entry_nn = old_nn->clone(C);
     entry_nn->set_jvms(jvms);
--- a/hotspot/src/share/vm/opto/doCall.cpp	Mon Jan 27 10:20:51 2014 -0800
+++ b/hotspot/src/share/vm/opto/doCall.cpp	Fri May 16 12:05:14 2014 -0700
@@ -364,7 +364,7 @@
 bool Compile::should_delay_boxing_inlining(ciMethod* call_method, JVMState* jvms) {
   if (eliminate_boxing() && call_method->is_boxing_method()) {
     set_has_boxed_value(true);
-    return true;
+    return aggressive_unboxing();
   }
   return false;
 }
--- a/hotspot/src/share/vm/opto/ifnode.cpp	Mon Jan 27 10:20:51 2014 -0800
+++ b/hotspot/src/share/vm/opto/ifnode.cpp	Fri May 16 12:05:14 2014 -0700
@@ -673,7 +673,7 @@
 //           /    Region
 //
 Node* IfNode::fold_compares(PhaseGVN* phase) {
-  if (!phase->C->eliminate_boxing() || Opcode() != Op_If) return NULL;
+  if (Opcode() != Op_If) return NULL;
 
   Node* this_cmp = in(1)->in(1);
   if (this_cmp != NULL && this_cmp->Opcode() == Op_CmpI &&
--- a/hotspot/src/share/vm/opto/phaseX.cpp	Mon Jan 27 10:20:51 2014 -0800
+++ b/hotspot/src/share/vm/opto/phaseX.cpp	Fri May 16 12:05:14 2014 -0700
@@ -1393,6 +1393,15 @@
           _worklist.push(u);
       }
     }
+    // If changed AddI/SubI inputs, check CmpU for range check optimization.
+    if (use_op == Op_AddI || use_op == Op_SubI) {
+      for (DUIterator_Fast i2max, i2 = use->fast_outs(i2max); i2 < i2max; i2++) {
+        Node* u = use->fast_out(i2);
+        if (u->is_Cmp() && (u->Opcode() == Op_CmpU)) {
+          _worklist.push(u);
+        }
+      }
+    }
     // If changed AddP inputs, check Stores for loop invariant
     if( use_op == Op_AddP ) {
       for (DUIterator_Fast i2max, i2 = use->fast_outs(i2max); i2 < i2max; i2++) {
--- a/hotspot/src/share/vm/opto/subnode.cpp	Mon Jan 27 10:20:51 2014 -0800
+++ b/hotspot/src/share/vm/opto/subnode.cpp	Fri May 16 12:05:14 2014 -0700
@@ -80,7 +80,7 @@
 
 //------------------------------Value------------------------------------------
 // A subtract node differences it's two inputs.
-const Type *SubNode::Value( PhaseTransform *phase ) const {
+const Type* SubNode::Value_common(PhaseTransform *phase) const {
   const Node* in1 = in(1);
   const Node* in2 = in(2);
   // Either input is TOP ==> the result is TOP
@@ -97,6 +97,16 @@
   if( t1 == Type::BOTTOM || t2 == Type::BOTTOM )
     return bottom_type();
 
+  return NULL;
+}
+
+const Type* SubNode::Value(PhaseTransform *phase) const {
+  const Type* t = Value_common(phase);
+  if (t != NULL) {
+    return t;
+  }
+  const Type* t1 = phase->type(in(1));
+  const Type* t2 = phase->type(in(2));
   return sub(t1,t2);            // Local flavor of type subtraction
 
 }
@@ -570,6 +580,81 @@
   return TypeInt::CC;                   // else use worst case results
 }
 
+const Type* CmpUNode::Value(PhaseTransform *phase) const {
+  const Type* t = SubNode::Value_common(phase);
+  if (t != NULL) {
+    return t;
+  }
+  const Node* in1 = in(1);
+  const Node* in2 = in(2);
+  const Type* t1 = phase->type(in1);
+  const Type* t2 = phase->type(in2);
+  assert(t1->isa_int(), "CmpU has only Int type inputs");
+  if (t2 == TypeInt::INT) { // Compare to bottom?
+    return bottom_type();
+  }
+  uint in1_op = in1->Opcode();
+  if (in1_op == Op_AddI || in1_op == Op_SubI) {
+    // The problem rise when result of AddI(SubI) may overflow
+    // signed integer value. Let say the input type is
+    // [256, maxint] then +128 will create 2 ranges due to
+    // overflow: [minint, minint+127] and [384, maxint].
+    // But C2 type system keep only 1 type range and as result
+    // it use general [minint, maxint] for this case which we
+    // can't optimize.
+    //
+    // Make 2 separate type ranges based on types of AddI(SubI) inputs
+    // and compare results of their compare. If results are the same
+    // CmpU node can be optimized.
+    const Node* in11 = in1->in(1);
+    const Node* in12 = in1->in(2);
+    const Type* t11 = (in11 == in1) ? Type::TOP : phase->type(in11);
+    const Type* t12 = (in12 == in1) ? Type::TOP : phase->type(in12);
+    // Skip cases when input types are top or bottom.
+    if ((t11 != Type::TOP) && (t11 != TypeInt::INT) &&
+        (t12 != Type::TOP) && (t12 != TypeInt::INT)) {
+      const TypeInt *r0 = t11->is_int();
+      const TypeInt *r1 = t12->is_int();
+      jlong lo_r0 = r0->_lo;
+      jlong hi_r0 = r0->_hi;
+      jlong lo_r1 = r1->_lo;
+      jlong hi_r1 = r1->_hi;
+      if (in1_op == Op_SubI) {
+        jlong tmp = hi_r1;
+        hi_r1 = -lo_r1;
+        lo_r1 = -tmp;
+        // Note, for substructing [minint,x] type range
+        // long arithmetic provides correct overflow answer.
+        // The confusion come from the fact that in 32-bit
+        // -minint == minint but in 64-bit -minint == maxint+1.
+      }
+      jlong lo_long = lo_r0 + lo_r1;
+      jlong hi_long = hi_r0 + hi_r1;
+      int lo_tr1 = min_jint;
+      int hi_tr1 = (int)hi_long;
+      int lo_tr2 = (int)lo_long;
+      int hi_tr2 = max_jint;
+      bool underflow = lo_long != (jlong)lo_tr2;
+      bool overflow  = hi_long != (jlong)hi_tr1;
+      // Use sub(t1, t2) when there is no overflow (one type range)
+      // or when both overflow and underflow (too complex).
+      if ((underflow != overflow) && (hi_tr1 < lo_tr2)) {
+        // Overflow only on one boundary, compare 2 separate type ranges.
+        int w = MAX2(r0->_widen, r1->_widen); // _widen does not matter here
+        const TypeInt* tr1 = TypeInt::make(lo_tr1, hi_tr1, w);
+        const TypeInt* tr2 = TypeInt::make(lo_tr2, hi_tr2, w);
+        const Type* cmp1 = sub(tr1, t2);
+        const Type* cmp2 = sub(tr2, t2);
+        if (cmp1 == cmp2) {
+          return cmp1; // Hit!
+        }
+      }
+    }
+  }
+
+  return sub(t1, t2);            // Local flavor of type subtraction
+}
+
 bool CmpUNode::is_index_range_check() const {
   // Check for the "(X ModI Y) CmpU Y" shape
   return (in(1)->Opcode() == Op_ModI &&
--- a/hotspot/src/share/vm/opto/subnode.hpp	Mon Jan 27 10:20:51 2014 -0800
+++ b/hotspot/src/share/vm/opto/subnode.hpp	Fri May 16 12:05:14 2014 -0700
@@ -50,6 +50,7 @@
   // Compute a new Type for this node.  Basically we just do the pre-check,
   // then call the virtual add() to set the type.
   virtual const Type *Value( PhaseTransform *phase ) const;
+  const Type* Value_common( PhaseTransform *phase ) const;
 
   // Supplied function returns the subtractend of the inputs.
   // This also type-checks the inputs for sanity.  Guaranteed never to
@@ -158,6 +159,7 @@
   CmpUNode( Node *in1, Node *in2 ) : CmpNode(in1,in2) {}
   virtual int Opcode() const;
   virtual const Type *sub( const Type *, const Type * ) const;
+  const Type *Value( PhaseTransform *phase ) const;
   bool is_index_range_check() const;
 };