# HG changeset patch # User kvn # Date 1400267114 25200 # Node ID 20eb4c752fb5b002b5996360adb257daf3461ffd # Parent e7dad659b819efc455e1f0c6cb750d1d0bb2363a 8042786: Proper fix for 8032566 Summary: Check for overflow cases in range checks and collapse it if we can. Reviewed-by: jrose, iveresov diff -r e7dad659b819 -r 20eb4c752fb5 hotspot/src/share/vm/opto/c2_globals.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, \ diff -r e7dad659b819 -r 20eb4c752fb5 hotspot/src/share/vm/opto/callGenerator.cpp --- 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); diff -r e7dad659b819 -r 20eb4c752fb5 hotspot/src/share/vm/opto/doCall.cpp --- 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; } diff -r e7dad659b819 -r 20eb4c752fb5 hotspot/src/share/vm/opto/ifnode.cpp --- 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 && diff -r e7dad659b819 -r 20eb4c752fb5 hotspot/src/share/vm/opto/phaseX.cpp --- 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++) { diff -r e7dad659b819 -r 20eb4c752fb5 hotspot/src/share/vm/opto/subnode.cpp --- 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 && diff -r e7dad659b819 -r 20eb4c752fb5 hotspot/src/share/vm/opto/subnode.hpp --- 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; };