Wed, 27 Jan 2016 09:02:51 +0100
6675699: need comprehensive fix for unconstrained ConvI2L with narrowed type
Summary: Emit CastII to make narrow ConvI2L dependent on the corresponding range check.
Reviewed-by: kvn, roland
1.1 --- a/src/share/vm/opto/compile.cpp Mon Jan 25 08:46:19 2016 +0000 1.2 +++ b/src/share/vm/opto/compile.cpp Wed Jan 27 09:02:51 2016 +0100 1.3 @@ -412,6 +412,13 @@ 1.4 remove_macro_node(n); 1.5 } 1.6 } 1.7 + // Remove useless CastII nodes with range check dependency 1.8 + for (int i = range_check_cast_count() - 1; i >= 0; i--) { 1.9 + Node* cast = range_check_cast_node(i); 1.10 + if (!useful.member(cast)) { 1.11 + remove_range_check_cast(cast); 1.12 + } 1.13 + } 1.14 // Remove useless expensive node 1.15 for (int i = C->expensive_count()-1; i >= 0; i--) { 1.16 Node* n = C->expensive_node(i); 1.17 @@ -1148,6 +1155,7 @@ 1.18 _macro_nodes = new(comp_arena()) GrowableArray<Node*>(comp_arena(), 8, 0, NULL); 1.19 _predicate_opaqs = new(comp_arena()) GrowableArray<Node*>(comp_arena(), 8, 0, NULL); 1.20 _expensive_nodes = new(comp_arena()) GrowableArray<Node*>(comp_arena(), 8, 0, NULL); 1.21 + _range_check_casts = new(comp_arena()) GrowableArray<Node*>(comp_arena(), 8, 0, NULL); 1.22 register_library_intrinsics(); 1.23 } 1.24 1.25 @@ -1876,6 +1884,22 @@ 1.26 assert(predicate_count()==0, "should be clean!"); 1.27 } 1.28 1.29 +void Compile::add_range_check_cast(Node* n) { 1.30 + assert(n->isa_CastII()->has_range_check(), "CastII should have range check dependency"); 1.31 + assert(!_range_check_casts->contains(n), "duplicate entry in range check casts"); 1.32 + _range_check_casts->append(n); 1.33 +} 1.34 + 1.35 +// Remove all range check dependent CastIINodes. 1.36 +void Compile::remove_range_check_casts(PhaseIterGVN &igvn) { 1.37 + for (int i = range_check_cast_count(); i > 0; i--) { 1.38 + Node* cast = range_check_cast_node(i-1); 1.39 + assert(cast->isa_CastII()->has_range_check(), "CastII should have range check dependency"); 1.40 + igvn.replace_node(cast, cast->in(1)); 1.41 + } 1.42 + assert(range_check_cast_count() == 0, "should be empty"); 1.43 +} 1.44 + 1.45 // StringOpts and late inlining of string methods 1.46 void Compile::inline_string_calls(bool parse_time) { 1.47 { 1.48 @@ -2218,6 +2242,12 @@ 1.49 PhaseIdealLoop::verify(igvn); 1.50 } 1.51 1.52 + if (range_check_cast_count() > 0) { 1.53 + // No more loop optimizations. Remove all range check dependent CastIINodes. 1.54 + C->remove_range_check_casts(igvn); 1.55 + igvn.optimize(); 1.56 + } 1.57 + 1.58 { 1.59 NOT_PRODUCT( TracePhase t2("macroExpand", &_t_macroExpand, TimeCompiler); ) 1.60 PhaseMacroExpand mex(igvn); 1.61 @@ -2987,6 +3017,16 @@ 1.62 1.63 #endif 1.64 1.65 +#ifdef ASSERT 1.66 + case Op_CastII: 1.67 + // Verify that all range check dependent CastII nodes were removed. 1.68 + if (n->isa_CastII()->has_range_check()) { 1.69 + n->dump(3); 1.70 + assert(false, "Range check dependent CastII node was not removed"); 1.71 + } 1.72 + break; 1.73 +#endif 1.74 + 1.75 case Op_ModI: 1.76 if (UseDivMod) { 1.77 // Check if a%b and a/b both exist 1.78 @@ -4024,6 +4064,24 @@ 1.79 } 1.80 } 1.81 1.82 +// Convert integer value to a narrowed long type dependent on ctrl (for example, a range check) 1.83 +Node* Compile::constrained_convI2L(PhaseGVN* phase, Node* value, const TypeInt* itype, Node* ctrl) { 1.84 + if (ctrl != NULL) { 1.85 + // Express control dependency by a CastII node with a narrow type. 1.86 + value = new (phase->C) CastIINode(value, itype, false, true /* range check dependency */); 1.87 + // Make the CastII node dependent on the control input to prevent the narrowed ConvI2L 1.88 + // node from floating above the range check during loop optimizations. Otherwise, the 1.89 + // ConvI2L node may be eliminated independently of the range check, causing the data path 1.90 + // to become TOP while the control path is still there (although it's unreachable). 1.91 + value->set_req(0, ctrl); 1.92 + // Save CastII node to remove it after loop optimizations. 1.93 + phase->C->add_range_check_cast(value); 1.94 + value = phase->transform(value); 1.95 + } 1.96 + const TypeLong* ltype = TypeLong::make(itype->_lo, itype->_hi, itype->_widen); 1.97 + return phase->transform(new (phase->C) ConvI2LNode(value, ltype)); 1.98 +} 1.99 + 1.100 // Auxiliary method to support randomized stressing/fuzzing. 1.101 // 1.102 // This method can be called the arbitrary number of times, with current count
2.1 --- a/src/share/vm/opto/compile.hpp Mon Jan 25 08:46:19 2016 +0000 2.2 +++ b/src/share/vm/opto/compile.hpp Wed Jan 27 09:02:51 2016 +0100 2.3 @@ -75,6 +75,7 @@ 2.4 class JVMState; 2.5 class Type; 2.6 class TypeData; 2.7 +class TypeInt; 2.8 class TypePtr; 2.9 class TypeOopPtr; 2.10 class TypeFunc; 2.11 @@ -334,6 +335,7 @@ 2.12 GrowableArray<Node*>* _macro_nodes; // List of nodes which need to be expanded before matching. 2.13 GrowableArray<Node*>* _predicate_opaqs; // List of Opaque1 nodes for the loop predicates. 2.14 GrowableArray<Node*>* _expensive_nodes; // List of nodes that are expensive to compute and that we'd better not let the GVN freely common 2.15 + GrowableArray<Node*>* _range_check_casts; // List of CastII nodes with a range check dependency 2.16 ConnectionGraph* _congraph; 2.17 #ifndef PRODUCT 2.18 IdealGraphPrinter* _printer; 2.19 @@ -669,7 +671,7 @@ 2.20 void set_congraph(ConnectionGraph* congraph) { _congraph = congraph;} 2.21 void add_macro_node(Node * n) { 2.22 //assert(n->is_macro(), "must be a macro node"); 2.23 - assert(!_macro_nodes->contains(n), " duplicate entry in expand list"); 2.24 + assert(!_macro_nodes->contains(n), "duplicate entry in expand list"); 2.25 _macro_nodes->append(n); 2.26 } 2.27 void remove_macro_node(Node * n) { 2.28 @@ -689,10 +691,23 @@ 2.29 } 2.30 } 2.31 void add_predicate_opaq(Node * n) { 2.32 - assert(!_predicate_opaqs->contains(n), " duplicate entry in predicate opaque1"); 2.33 + assert(!_predicate_opaqs->contains(n), "duplicate entry in predicate opaque1"); 2.34 assert(_macro_nodes->contains(n), "should have already been in macro list"); 2.35 _predicate_opaqs->append(n); 2.36 } 2.37 + 2.38 + // Range check dependent CastII nodes that can be removed after loop optimizations 2.39 + void add_range_check_cast(Node* n); 2.40 + void remove_range_check_cast(Node* n) { 2.41 + if (_range_check_casts->contains(n)) { 2.42 + _range_check_casts->remove(n); 2.43 + } 2.44 + } 2.45 + Node* range_check_cast_node(int idx) const { return _range_check_casts->at(idx); } 2.46 + int range_check_cast_count() const { return _range_check_casts->length(); } 2.47 + // Remove all range check dependent CastIINodes. 2.48 + void remove_range_check_casts(PhaseIterGVN &igvn); 2.49 + 2.50 // remove the opaque nodes that protect the predicates so that the unused checks and 2.51 // uncommon traps will be eliminated from the graph. 2.52 void cleanup_loop_predicates(PhaseIterGVN &igvn); 2.53 @@ -1201,6 +1216,9 @@ 2.54 // Definitions of pd methods 2.55 static void pd_compiler2_init(); 2.56 2.57 + // Convert integer value to a narrowed long type dependent on ctrl (for example, a range check) 2.58 + static Node* constrained_convI2L(PhaseGVN* phase, Node* value, const TypeInt* itype, Node* ctrl); 2.59 + 2.60 // Auxiliary method for randomized fuzzing/stressing 2.61 static bool randomized_select(int count); 2.62 };
3.1 --- a/src/share/vm/opto/connode.cpp Mon Jan 25 08:46:19 2016 +0000 3.2 +++ b/src/share/vm/opto/connode.cpp Wed Jan 27 09:02:51 2016 +0100 3.3 @@ -535,6 +535,9 @@ 3.4 if (_carry_dependency) { 3.5 st->print(" carry dependency"); 3.6 } 3.7 + if (_range_check_dependency) { 3.8 + st->print(" range check dependency"); 3.9 + } 3.10 } 3.11 #endif 3.12 3.13 @@ -994,7 +997,8 @@ 3.14 } 3.15 3.16 #ifdef _LP64 3.17 - // Convert ConvI2L(AddI(x, y)) to AddL(ConvI2L(x), ConvI2L(y)) , 3.18 + // Convert ConvI2L(AddI(x, y)) to AddL(ConvI2L(x), ConvI2L(y)) or 3.19 + // ConvI2L(CastII(AddI(x, y))) to AddL(ConvI2L(CastII(x)), ConvI2L(CastII(y))), 3.20 // but only if x and y have subranges that cannot cause 32-bit overflow, 3.21 // under the assumption that x+y is in my own subrange this->type(). 3.22 3.23 @@ -1018,6 +1022,13 @@ 3.24 3.25 Node* z = in(1); 3.26 int op = z->Opcode(); 3.27 + Node* ctrl = NULL; 3.28 + if (op == Op_CastII && z->as_CastII()->has_range_check()) { 3.29 + // Skip CastII node but save control dependency 3.30 + ctrl = z->in(0); 3.31 + z = z->in(1); 3.32 + op = z->Opcode(); 3.33 + } 3.34 if (op == Op_AddI || op == Op_SubI) { 3.35 Node* x = z->in(1); 3.36 Node* y = z->in(2); 3.37 @@ -1075,9 +1086,10 @@ 3.38 rylo = -ryhi; 3.39 ryhi = -rylo0; 3.40 } 3.41 - 3.42 - Node* cx = phase->transform( new (phase->C) ConvI2LNode(x, TypeLong::make(rxlo, rxhi, widen)) ); 3.43 - Node* cy = phase->transform( new (phase->C) ConvI2LNode(y, TypeLong::make(rylo, ryhi, widen)) ); 3.44 + assert(rxlo == (int)rxlo && rxhi == (int)rxhi, "x should not overflow"); 3.45 + assert(rylo == (int)rylo && ryhi == (int)ryhi, "y should not overflow"); 3.46 + Node* cx = phase->C->constrained_convI2L(phase, x, TypeInt::make(rxlo, rxhi, widen), ctrl); 3.47 + Node* cy = phase->C->constrained_convI2L(phase, y, TypeInt::make(rylo, ryhi, widen), ctrl); 3.48 switch (op) { 3.49 case Op_AddI: return new (phase->C) AddLNode(cx, cy); 3.50 case Op_SubI: return new (phase->C) SubLNode(cx, cy);
4.1 --- a/src/share/vm/opto/connode.hpp Mon Jan 25 08:46:19 2016 +0000 4.2 +++ b/src/share/vm/opto/connode.hpp Wed Jan 27 09:02:51 2016 +0100 4.3 @@ -244,19 +244,31 @@ 4.4 private: 4.5 // Can this node be removed post CCP or does it carry a required dependency? 4.6 const bool _carry_dependency; 4.7 + // Is this node dependent on a range check? 4.8 + const bool _range_check_dependency; 4.9 4.10 protected: 4.11 virtual uint cmp( const Node &n ) const; 4.12 virtual uint size_of() const; 4.13 4.14 public: 4.15 - CastIINode(Node *n, const Type *t, bool carry_dependency = false) 4.16 - : ConstraintCastNode(n,t), _carry_dependency(carry_dependency) {} 4.17 + CastIINode(Node *n, const Type *t, bool carry_dependency = false, bool range_check_dependency = false) 4.18 + : ConstraintCastNode(n,t), _carry_dependency(carry_dependency), _range_check_dependency(range_check_dependency) { 4.19 + init_class_id(Class_CastII); 4.20 + } 4.21 virtual int Opcode() const; 4.22 virtual uint ideal_reg() const { return Op_RegI; } 4.23 virtual Node *Identity( PhaseTransform *phase ); 4.24 virtual const Type *Value( PhaseTransform *phase ) const; 4.25 virtual Node *Ideal_DU_postCCP( PhaseCCP * ); 4.26 + const bool has_range_check() { 4.27 + #ifdef _LP64 4.28 + return _range_check_dependency; 4.29 + #else 4.30 + assert(!_range_check_dependency, "Should not have range check dependency"); 4.31 + return false; 4.32 + #endif 4.33 + } 4.34 #ifndef PRODUCT 4.35 virtual void dump_spec(outputStream *st) const; 4.36 #endif
5.1 --- a/src/share/vm/opto/graphKit.cpp Mon Jan 25 08:46:19 2016 +0000 5.2 +++ b/src/share/vm/opto/graphKit.cpp Wed Jan 27 09:02:51 2016 +0100 5.3 @@ -1645,7 +1645,7 @@ 5.4 5.5 //-------------------------array_element_address------------------------- 5.6 Node* GraphKit::array_element_address(Node* ary, Node* idx, BasicType elembt, 5.7 - const TypeInt* sizetype) { 5.8 + const TypeInt* sizetype, Node* ctrl) { 5.9 uint shift = exact_log2(type2aelembytes(elembt)); 5.10 uint header = arrayOopDesc::base_offset_in_bytes(elembt); 5.11 5.12 @@ -1670,9 +1670,9 @@ 5.13 // number. (The prior range check has ensured this.) 5.14 // This assertion is used by ConvI2LNode::Ideal. 5.15 int index_max = max_jint - 1; // array size is max_jint, index is one less 5.16 - if (sizetype != NULL) index_max = sizetype->_hi - 1; 5.17 - const TypeLong* lidxtype = TypeLong::make(CONST64(0), index_max, Type::WidenMax); 5.18 - idx = _gvn.transform( new (C) ConvI2LNode(idx, lidxtype) ); 5.19 + if (sizetype != NULL) index_max = sizetype->_hi - 1; 5.20 + const TypeInt* iidxtype = TypeInt::make(0, index_max, Type::WidenMax); 5.21 + idx = C->constrained_convI2L(&_gvn, idx, iidxtype, ctrl); 5.22 #endif 5.23 Node* scale = _gvn.transform( new (C) LShiftXNode(idx, intcon(shift)) ); 5.24 return basic_plus_adr(ary, base, scale); 5.25 @@ -3491,10 +3491,6 @@ 5.26 5.27 Node* initial_slow_cmp = _gvn.transform( new (C) CmpUNode( length, intcon( fast_size_limit ) ) ); 5.28 Node* initial_slow_test = _gvn.transform( new (C) BoolNode( initial_slow_cmp, BoolTest::gt ) ); 5.29 - if (initial_slow_test->is_Bool()) { 5.30 - // Hide it behind a CMoveI, or else PhaseIdealLoop::split_up will get sick. 5.31 - initial_slow_test = initial_slow_test->as_Bool()->as_int_value(&_gvn); 5.32 - } 5.33 5.34 // --- Size Computation --- 5.35 // array_size = round_to_heap(array_header + (length << elem_shift)); 5.36 @@ -3540,13 +3536,35 @@ 5.37 Node* lengthx = ConvI2X(length); 5.38 Node* headerx = ConvI2X(header_size); 5.39 #ifdef _LP64 5.40 - { const TypeLong* tllen = _gvn.find_long_type(lengthx); 5.41 - if (tllen != NULL && tllen->_lo < 0) { 5.42 + { const TypeInt* tilen = _gvn.find_int_type(length); 5.43 + if (tilen != NULL && tilen->_lo < 0) { 5.44 // Add a manual constraint to a positive range. Cf. array_element_address. 5.45 - jlong size_max = arrayOopDesc::max_array_length(T_BYTE); 5.46 - if (size_max > tllen->_hi) size_max = tllen->_hi; 5.47 - const TypeLong* tlcon = TypeLong::make(CONST64(0), size_max, Type::WidenMin); 5.48 - lengthx = _gvn.transform( new (C) ConvI2LNode(length, tlcon)); 5.49 + jlong size_max = fast_size_limit; 5.50 + if (size_max > tilen->_hi) size_max = tilen->_hi; 5.51 + const TypeInt* tlcon = TypeInt::make(0, size_max, Type::WidenMin); 5.52 + 5.53 + // Only do a narrow I2L conversion if the range check passed. 5.54 + IfNode* iff = new (C) IfNode(control(), initial_slow_test, PROB_MIN, COUNT_UNKNOWN); 5.55 + _gvn.transform(iff); 5.56 + RegionNode* region = new (C) RegionNode(3); 5.57 + _gvn.set_type(region, Type::CONTROL); 5.58 + lengthx = new (C) PhiNode(region, TypeLong::LONG); 5.59 + _gvn.set_type(lengthx, TypeLong::LONG); 5.60 + 5.61 + // Range check passed. Use ConvI2L node with narrow type. 5.62 + Node* passed = IfFalse(iff); 5.63 + region->init_req(1, passed); 5.64 + // Make I2L conversion control dependent to prevent it from 5.65 + // floating above the range check during loop optimizations. 5.66 + lengthx->init_req(1, C->constrained_convI2L(&_gvn, length, tlcon, passed)); 5.67 + 5.68 + // Range check failed. Use ConvI2L with wide type because length may be invalid. 5.69 + region->init_req(2, IfTrue(iff)); 5.70 + lengthx->init_req(2, ConvI2X(length)); 5.71 + 5.72 + set_control(region); 5.73 + record_for_igvn(region); 5.74 + record_for_igvn(lengthx); 5.75 } 5.76 } 5.77 #endif 5.78 @@ -3577,6 +3595,11 @@ 5.79 Node *mem = reset_memory(); 5.80 set_all_memory(mem); // Create new memory state 5.81 5.82 + if (initial_slow_test->is_Bool()) { 5.83 + // Hide it behind a CMoveI, or else PhaseIdealLoop::split_up will get sick. 5.84 + initial_slow_test = initial_slow_test->as_Bool()->as_int_value(&_gvn); 5.85 + } 5.86 + 5.87 // Create the AllocateArrayNode and its result projections 5.88 AllocateArrayNode* alloc 5.89 = new (C) AllocateArrayNode(C, AllocateArrayNode::alloc_type(TypeInt::INT),
6.1 --- a/src/share/vm/opto/graphKit.hpp Mon Jan 25 08:46:19 2016 +0000 6.2 +++ b/src/share/vm/opto/graphKit.hpp Wed Jan 27 09:02:51 2016 +0100 6.3 @@ -626,7 +626,9 @@ 6.4 // Return addressing for an array element. 6.5 Node* array_element_address(Node* ary, Node* idx, BasicType elembt, 6.6 // Optional constraint on the array size: 6.7 - const TypeInt* sizetype = NULL); 6.8 + const TypeInt* sizetype = NULL, 6.9 + // Optional control dependency (for example, on range check) 6.10 + Node* ctrl = NULL); 6.11 6.12 // Return a load of array element at idx. 6.13 Node* load_array_element(Node* ctl, Node* ary, Node* idx, const TypeAryPtr* arytype);
7.1 --- a/src/share/vm/opto/loopTransform.cpp Mon Jan 25 08:46:19 2016 +0000 7.2 +++ b/src/share/vm/opto/loopTransform.cpp Wed Jan 27 09:02:51 2016 +0100 7.3 @@ -2438,7 +2438,7 @@ 7.4 7.5 //============================================================================= 7.6 // Process all the loops in the loop tree and replace any fill 7.7 -// patterns with an intrisc version. 7.8 +// patterns with an intrinsic version. 7.9 bool PhaseIdealLoop::do_intrinsify_fill() { 7.10 bool changed = false; 7.11 for (LoopTreeIterator iter(_ltree_root); !iter.done(); iter.next()) { 7.12 @@ -2536,8 +2536,9 @@ 7.13 } 7.14 7.15 // Make sure the address expression can be handled. It should be 7.16 - // head->phi * elsize + con. head->phi might have a ConvI2L. 7.17 + // head->phi * elsize + con. head->phi might have a ConvI2L(CastII()). 7.18 Node* elements[4]; 7.19 + Node* cast = NULL; 7.20 Node* conv = NULL; 7.21 bool found_index = false; 7.22 int count = store->in(MemNode::Address)->as_AddP()->unpack_offsets(elements, ARRAY_SIZE(elements)); 7.23 @@ -2552,6 +2553,12 @@ 7.24 conv = value; 7.25 value = value->in(1); 7.26 } 7.27 + if (value->Opcode() == Op_CastII && 7.28 + value->as_CastII()->has_range_check()) { 7.29 + // Skip range check dependent CastII nodes 7.30 + cast = value; 7.31 + value = value->in(1); 7.32 + } 7.33 #endif 7.34 if (value != head->phi()) { 7.35 msg = "unhandled shift in address"; 7.36 @@ -2564,9 +2571,16 @@ 7.37 } 7.38 } 7.39 } else if (n->Opcode() == Op_ConvI2L && conv == NULL) { 7.40 - if (n->in(1) == head->phi()) { 7.41 + conv = n; 7.42 + n = n->in(1); 7.43 + if (n->Opcode() == Op_CastII && 7.44 + n->as_CastII()->has_range_check()) { 7.45 + // Skip range check dependent CastII nodes 7.46 + cast = n; 7.47 + n = n->in(1); 7.48 + } 7.49 + if (n == head->phi()) { 7.50 found_index = true; 7.51 - conv = n; 7.52 } else { 7.53 msg = "unhandled input to ConvI2L"; 7.54 } 7.55 @@ -2625,6 +2639,7 @@ 7.56 // Address elements are ok 7.57 if (con) ok.set(con->_idx); 7.58 if (shift) ok.set(shift->_idx); 7.59 + if (cast) ok.set(cast->_idx); 7.60 if (conv) ok.set(conv->_idx); 7.61 7.62 for (uint i = 0; msg == NULL && i < lpt->_body.size(); i++) {
8.1 --- a/src/share/vm/opto/loopopts.cpp Mon Jan 25 08:46:19 2016 +0000 8.2 +++ b/src/share/vm/opto/loopopts.cpp Wed Jan 27 09:02:51 2016 +0100 8.3 @@ -772,6 +772,9 @@ 8.4 #ifdef _LP64 8.5 if (m->Opcode() == Op_ConvI2L) 8.6 return false; 8.7 + if (m->is_CastII() && m->isa_CastII()->has_range_check()) { 8.8 + return false; 8.9 + } 8.10 #endif 8.11 } 8.12 }
9.1 --- a/src/share/vm/opto/node.cpp Mon Jan 25 08:46:19 2016 +0000 9.2 +++ b/src/share/vm/opto/node.cpp Wed Jan 27 09:02:51 2016 +0100 9.3 @@ -521,6 +521,11 @@ 9.4 C->add_macro_node(n); 9.5 if (is_expensive()) 9.6 C->add_expensive_node(n); 9.7 + // If the cloned node is a range check dependent CastII, add it to the list. 9.8 + CastIINode* cast = n->isa_CastII(); 9.9 + if (cast != NULL && cast->has_range_check()) { 9.10 + C->add_range_check_cast(cast); 9.11 + } 9.12 9.13 n->set_idx(C->next_unique()); // Get new unique index as well 9.14 debug_only( n->verify_construction() ); 9.15 @@ -649,6 +654,11 @@ 9.16 if (is_expensive()) { 9.17 compile->remove_expensive_node(this); 9.18 } 9.19 + CastIINode* cast = isa_CastII(); 9.20 + if (cast != NULL && cast->has_range_check()) { 9.21 + compile->remove_range_check_cast(cast); 9.22 + } 9.23 + 9.24 if (is_SafePoint()) { 9.25 as_SafePoint()->delete_replaced_nodes(); 9.26 } 9.27 @@ -1344,6 +1354,10 @@ 9.28 if (dead->is_expensive()) { 9.29 igvn->C->remove_expensive_node(dead); 9.30 } 9.31 + CastIINode* cast = dead->isa_CastII(); 9.32 + if (cast != NULL && cast->has_range_check()) { 9.33 + igvn->C->remove_range_check_cast(cast); 9.34 + } 9.35 igvn->C->record_dead_node(dead->_idx); 9.36 // Kill all inputs to the dead guy 9.37 for (uint i=0; i < dead->req(); i++) {
10.1 --- a/src/share/vm/opto/node.hpp Mon Jan 25 08:46:19 2016 +0000 10.2 +++ b/src/share/vm/opto/node.hpp Wed Jan 27 09:02:51 2016 +0100 10.3 @@ -54,6 +54,7 @@ 10.4 class CatchNode; 10.5 class CatchProjNode; 10.6 class CheckCastPPNode; 10.7 +class CastIINode; 10.8 class ClearArrayNode; 10.9 class CmpNode; 10.10 class CodeBuffer; 10.11 @@ -603,6 +604,7 @@ 10.12 DEFINE_CLASS_ID(Type, Node, 2) 10.13 DEFINE_CLASS_ID(Phi, Type, 0) 10.14 DEFINE_CLASS_ID(ConstraintCast, Type, 1) 10.15 + DEFINE_CLASS_ID(CastII, ConstraintCast, 0) 10.16 DEFINE_CLASS_ID(CheckCastPP, Type, 2) 10.17 DEFINE_CLASS_ID(CMove, Type, 3) 10.18 DEFINE_CLASS_ID(SafePointScalarObject, Type, 4) 10.19 @@ -727,6 +729,7 @@ 10.20 DEFINE_CLASS_QUERY(Catch) 10.21 DEFINE_CLASS_QUERY(CatchProj) 10.22 DEFINE_CLASS_QUERY(CheckCastPP) 10.23 + DEFINE_CLASS_QUERY(CastII) 10.24 DEFINE_CLASS_QUERY(ConstraintCast) 10.25 DEFINE_CLASS_QUERY(ClearArray) 10.26 DEFINE_CLASS_QUERY(CMove)
11.1 --- a/src/share/vm/opto/parse2.cpp Mon Jan 25 08:46:19 2016 +0000 11.2 +++ b/src/share/vm/opto/parse2.cpp Wed Jan 27 09:02:51 2016 +0100 11.3 @@ -154,7 +154,9 @@ 11.4 // Check for always knowing you are throwing a range-check exception 11.5 if (stopped()) return top(); 11.6 11.7 - Node* ptr = array_element_address(ary, idx, type, sizetype); 11.8 + // Make array address computation control dependent to prevent it 11.9 + // from floating above the range check during loop optimizations. 11.10 + Node* ptr = array_element_address(ary, idx, type, sizetype, control()); 11.11 11.12 if (result2 != NULL) *result2 = elemtype; 11.13 11.14 @@ -457,9 +459,12 @@ 11.15 #ifdef _LP64 11.16 // Clean the 32-bit int into a real 64-bit offset. 11.17 // Otherwise, the jint value 0 might turn into an offset of 0x0800000000. 11.18 - const TypeLong* lkeytype = TypeLong::make(CONST64(0), num_cases-1, Type::WidenMin); 11.19 - key_val = _gvn.transform( new (C) ConvI2LNode(key_val, lkeytype) ); 11.20 + const TypeInt* ikeytype = TypeInt::make(0, num_cases-1, Type::WidenMin); 11.21 + // Make I2L conversion control dependent to prevent it from 11.22 + // floating above the range check during loop optimizations. 11.23 + key_val = C->constrained_convI2L(&_gvn, key_val, ikeytype, control()); 11.24 #endif 11.25 + 11.26 // Shift the value by wordsize so we have an index into the table, rather 11.27 // than a switch value 11.28 Node *shiftWord = _gvn.MakeConX(wordSize);
12.1 --- a/src/share/vm/opto/phaseX.cpp Mon Jan 25 08:46:19 2016 +0000 12.2 +++ b/src/share/vm/opto/phaseX.cpp Wed Jan 27 09:02:51 2016 +0100 12.3 @@ -1339,6 +1339,10 @@ 12.4 if (dead->is_expensive()) { 12.5 C->remove_expensive_node(dead); 12.6 } 12.7 + CastIINode* cast = dead->isa_CastII(); 12.8 + if (cast != NULL && cast->has_range_check()) { 12.9 + C->remove_range_check_cast(cast); 12.10 + } 12.11 } 12.12 } // while (_stack.is_nonempty()) 12.13 }
13.1 --- a/src/share/vm/opto/superword.cpp Mon Jan 25 08:46:19 2016 +0000 13.2 +++ b/src/share/vm/opto/superword.cpp Wed Jan 27 09:02:51 2016 +0100 13.3 @@ -2388,6 +2388,11 @@ 13.4 return true; 13.5 } 13.6 } else if (opc == Op_ConvI2L) { 13.7 + if (n->in(1)->Opcode() == Op_CastII && 13.8 + n->in(1)->as_CastII()->has_range_check()) { 13.9 + // Skip range check dependent CastII nodes 13.10 + n = n->in(1); 13.11 + } 13.12 if (scaled_iv_plus_offset(n->in(1))) { 13.13 return true; 13.14 }
14.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 14.2 +++ b/test/compiler/loopopts/TestLoopPeeling.java Wed Jan 27 09:02:51 2016 +0100 14.3 @@ -0,0 +1,100 @@ 14.4 +/* 14.5 + * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. 14.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 14.7 + * 14.8 + * This code is free software; you can redistribute it and/or modify it 14.9 + * under the terms of the GNU General Public License version 2 only, as 14.10 + * published by the Free Software Foundation. 14.11 + * 14.12 + * This code is distributed in the hope that it will be useful, but WITHOUT 14.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 14.14 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14.15 + * version 2 for more details (a copy is included in the LICENSE file that 14.16 + * accompanied this code). 14.17 + * 14.18 + * You should have received a copy of the GNU General Public License version 14.19 + * 2 along with this work; if not, write to the Free Software Foundation, 14.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 14.21 + * 14.22 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 14.23 + * or visit www.oracle.com if you need additional information or have any 14.24 + * questions. 14.25 + */ 14.26 + 14.27 +/* 14.28 + * @test 14.29 + * @bug 8078262 14.30 + * @summary Tests correct dominator information after loop peeling. 14.31 + * @run main/othervm -Xcomp -XX:CompileCommand=compileonly,TestLoopPeeling::test* TestLoopPeeling 14.32 + */ 14.33 +public class TestLoopPeeling { 14.34 + 14.35 + public int[] array = new int[100]; 14.36 + 14.37 + public static void main(String args[]) { 14.38 + TestLoopPeeling test = new TestLoopPeeling(); 14.39 + try { 14.40 + test.testArrayAccess(0, 1); 14.41 + test.testArrayAllocation(0, 1); 14.42 + } catch (Exception e) { 14.43 + // Ignore exceptions 14.44 + } 14.45 + } 14.46 + 14.47 + public void testArrayAccess(int index, int inc) { 14.48 + int storeIndex = -1; 14.49 + 14.50 + for (; index < 10; index += inc) { 14.51 + // This loop invariant check triggers loop peeling because it can 14.52 + // be moved out of the loop (see 'IdealLoopTree::policy_peeling'). 14.53 + if (inc == 42) return; 14.54 + 14.55 + // This loop variant usage of LShiftL( ConvI2L( Phi(storeIndex) ) ) 14.56 + // prevents the split if optimization that would otherwise clone the 14.57 + // LShiftL and ConvI2L nodes and assign them to their corresponding array 14.58 + // address computation (see 'PhaseIdealLoop::split_if_with_blocks_post'). 14.59 + if (storeIndex > 0 && array[storeIndex] == 42) return; 14.60 + 14.61 + if (index == 42) { 14.62 + // This store and the corresponding range check are moved out of the 14.63 + // loop and both used after old loop and the peeled iteration exit. 14.64 + // For the peeled iteration, storeIndex is always -1 and the ConvI2L 14.65 + // is replaced by TOP. However, the range check is not folded because 14.66 + // we don't do the split if optimization in PhaseIdealLoop2. 14.67 + // As a result, we have a (dead) control path from the peeled iteration 14.68 + // to the StoreI but the data path is removed. 14.69 + array[storeIndex] = 1; 14.70 + return; 14.71 + } 14.72 + 14.73 + storeIndex++; 14.74 + } 14.75 + } 14.76 + 14.77 + public byte[] testArrayAllocation(int index, int inc) { 14.78 + int allocationCount = -1; 14.79 + byte[] result; 14.80 + 14.81 + for (; index < 10; index += inc) { 14.82 + // This loop invariant check triggers loop peeling because it can 14.83 + // be moved out of the loop (see 'IdealLoopTree::policy_peeling'). 14.84 + if (inc == 42) return null; 14.85 + 14.86 + if (index == 42) { 14.87 + // This allocation and the corresponding size check are moved out of the 14.88 + // loop and both used after old loop and the peeled iteration exit. 14.89 + // For the peeled iteration, allocationCount is always -1 and the ConvI2L 14.90 + // is replaced by TOP. However, the size check is not folded because 14.91 + // we don't do the split if optimization in PhaseIdealLoop2. 14.92 + // As a result, we have a (dead) control path from the peeled iteration 14.93 + // to the allocation but the data path is removed. 14.94 + result = new byte[allocationCount]; 14.95 + return result; 14.96 + } 14.97 + 14.98 + allocationCount++; 14.99 + } 14.100 + return null; 14.101 + } 14.102 +} 14.103 +