< prev index next >
src/share/vm/opto/compile.cpp
Print this page
@@ -36,10 +36,11 @@
#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,10 +401,17 @@
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,10 +1184,11 @@
_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,10 +1931,26 @@
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,10 +2307,16 @@
// 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,10 +3116,20 @@
}
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,11 +4001,11 @@
}
return SSC_full_test;
}
-Node* Compile::conv_I2X_index(PhaseGVN *phase, Node* idx, const TypeInt* sizetype) {
+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,16 +4015,34 @@
// 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));
+ 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 >