< prev index next >

src/share/vm/opto/compile.cpp

Print this page

        

*** 36,45 **** --- 36,46 ---- #include "opto/addnode.hpp" #include "opto/block.hpp" #include "opto/c2compiler.hpp" #include "opto/callGenerator.hpp" #include "opto/callnode.hpp" + #include "opto/castnode.hpp" #include "opto/cfgnode.hpp" #include "opto/chaitin.hpp" #include "opto/compile.hpp" #include "opto/connode.hpp" #include "opto/convertnode.hpp"
*** 400,409 **** --- 401,417 ---- Node* n = C->macro_node(i); if (!useful.member(n)) { remove_macro_node(n); } } + // Remove useless CastII nodes with range check dependency + for (int i = range_check_cast_count() - 1; i >= 0; i--) { + Node* cast = range_check_cast_node(i); + if (!useful.member(cast)) { + remove_range_check_cast(cast); + } + } // Remove useless expensive node for (int i = C->expensive_count()-1; i >= 0; i--) { Node* n = C->expensive_node(i); if (!useful.member(n)) { remove_expensive_node(n);
*** 1176,1185 **** --- 1184,1194 ---- _intrinsics = NULL; _macro_nodes = new(comp_arena()) GrowableArray<Node*>(comp_arena(), 8, 0, NULL); _predicate_opaqs = new(comp_arena()) GrowableArray<Node*>(comp_arena(), 8, 0, NULL); _expensive_nodes = new(comp_arena()) GrowableArray<Node*>(comp_arena(), 8, 0, NULL); + _range_check_casts = new(comp_arena()) GrowableArray<Node*>(comp_arena(), 8, 0, NULL); register_library_intrinsics(); } //---------------------------init_start---------------------------------------- // Install the StartNode on this compile object.
*** 1922,1931 **** --- 1931,1956 ---- igvn.replace_node(n, n->in(1)); } assert(predicate_count()==0, "should be clean!"); } + void Compile::add_range_check_cast(Node* n) { + assert(n->isa_CastII()->has_range_check(), "CastII should have range check dependency"); + assert(!_range_check_casts->contains(n), "duplicate entry in range check casts"); + _range_check_casts->append(n); + } + + // Remove all range check dependent CastIINodes. + void Compile::remove_range_check_casts(PhaseIterGVN &igvn) { + for (int i = range_check_cast_count(); i > 0; i--) { + Node* cast = range_check_cast_node(i-1); + assert(cast->isa_CastII()->has_range_check(), "CastII should have range check dependency"); + igvn.replace_node(cast, cast->in(1)); + } + assert(range_check_cast_count() == 0, "should be empty"); + } + // StringOpts and late inlining of string methods void Compile::inline_string_calls(bool parse_time) { { // remove useless nodes to make the usage analysis simpler ResourceMark rm;
*** 2282,2291 **** --- 2307,2322 ---- // at least to this point, even if no loop optimizations were done. TracePhase tp("idealLoopVerify", &timers[_t_idealLoopVerify]); PhaseIdealLoop::verify(igvn); } + if (range_check_cast_count() > 0) { + // No more loop optimizations. Remove all range check dependent CastIINodes. + C->remove_range_check_casts(igvn); + igvn.optimize(); + } + { TracePhase tp("macroExpand", &timers[_t_macroExpand]); PhaseMacroExpand mex(igvn); if (mex.expand_macro_nodes()) { assert(failing(), "must bail out w/ explicit message");
*** 3085,3094 **** --- 3116,3135 ---- } break; #endif + #ifdef ASSERT + case Op_CastII: + // Verify that all range check dependent CastII nodes were removed. + if (n->isa_CastII()->has_range_check()) { + n->dump(3); + assert(false, "Range check dependent CastII node was not removed"); + } + break; + #endif + case Op_ModI: if (UseDivMod) { // Check if a%b and a/b both exist Node* d = n->find_similar(Op_DivI); if (d) {
*** 3960,3970 **** } return SSC_full_test; } ! Node* Compile::conv_I2X_index(PhaseGVN *phase, Node* idx, const TypeInt* sizetype) { #ifdef _LP64 // The scaled index operand to AddP must be a clean 64-bit value. // Java allows a 32-bit int to be incremented to a negative // value, which appears in a 64-bit register as a large // positive number. Using that large positive number as an --- 4001,4011 ---- } return SSC_full_test; } ! Node* Compile::conv_I2X_index(PhaseGVN* phase, Node* idx, const TypeInt* sizetype, Node* ctrl) { #ifdef _LP64 // The scaled index operand to AddP must be a clean 64-bit value. // Java allows a 32-bit int to be incremented to a negative // value, which appears in a 64-bit register as a large // positive number. Using that large positive number as an
*** 3974,3989 **** // a type assertion that its value is known to be a small positive // number. (The prior range check has ensured this.) // This assertion is used by ConvI2LNode::Ideal. int index_max = max_jint - 1; // array size is max_jint, index is one less if (sizetype != NULL) index_max = sizetype->_hi - 1; ! const TypeLong* lidxtype = TypeLong::make(CONST64(0), index_max, Type::WidenMax); ! idx = phase->transform(new ConvI2LNode(idx, lidxtype)); #endif return idx; } // The message about the current inlining is accumulated in // _print_inlining_stream and transfered into the _print_inlining_list // once we know whether inlining succeeds or not. For regular // inlining, messages are appended to the buffer pointed by // _print_inlining_idx in the _print_inlining_list. For late inlining, --- 4015,4048 ---- // a type assertion that its value is known to be a small positive // number. (The prior range check has ensured this.) // This assertion is used by ConvI2LNode::Ideal. int index_max = max_jint - 1; // array size is max_jint, index is one less if (sizetype != NULL) index_max = sizetype->_hi - 1; ! const TypeInt* iidxtype = TypeInt::make(0, index_max, Type::WidenMax); ! idx = constrained_convI2L(phase, idx, iidxtype, ctrl); #endif return idx; } + // Convert integer value to a narrowed long type dependent on ctrl (for example, a range check) + Node* Compile::constrained_convI2L(PhaseGVN* phase, Node* value, const TypeInt* itype, Node* ctrl) { + if (ctrl != NULL) { + // Express control dependency by a CastII node with a narrow type. + value = new CastIINode(value, itype, false, true /* range check dependency */); + // Make the CastII node dependent on the control input to prevent the narrowed ConvI2L + // node from floating above the range check during loop optimizations. Otherwise, the + // ConvI2L node may be eliminated independently of the range check, causing the data path + // to become TOP while the control path is still there (although it's unreachable). + value->set_req(0, ctrl); + // Save CastII node to remove it after loop optimizations. + phase->C->add_range_check_cast(value); + value = phase->transform(value); + } + const TypeLong* ltype = TypeLong::make(itype->_lo, itype->_hi, itype->_widen); + return phase->transform(new ConvI2LNode(value, ltype)); + } + // The message about the current inlining is accumulated in // _print_inlining_stream and transfered into the _print_inlining_list // once we know whether inlining succeeds or not. For regular // inlining, messages are appended to the buffer pointed by // _print_inlining_idx in the _print_inlining_list. For late inlining,
< prev index next >