diff --git a/src/hotspot/share/opto/c2_globals.hpp b/src/hotspot/share/opto/c2_globals.hpp index f470049bf7e..c9decf7884e 100644 --- a/src/hotspot/share/opto/c2_globals.hpp +++ b/src/hotspot/share/opto/c2_globals.hpp @@ -694,7 +694,9 @@ "Print progress during Iterative Global Value Numbering") \ \ develop(uint, VerifyIterativeGVN, 0, \ - "Verify Iterative Global Value Numbering =EDCBA, with:" \ + "Verify Iterative Global Value Numbering =FEDCBA, with:" \ + " F: verify Node::Ideal does not return nullptr if the node" \ + "hash has changed" \ " E: verify node specific invariants" \ " D: verify Node::Identity did not miss opportunities" \ " C: verify Node::Ideal did not miss opportunities" \ diff --git a/src/hotspot/share/opto/cfgnode.cpp b/src/hotspot/share/opto/cfgnode.cpp index efa0b55e2c2..053c0fdbcc0 100644 --- a/src/hotspot/share/opto/cfgnode.cpp +++ b/src/hotspot/share/opto/cfgnode.cpp @@ -2243,7 +2243,7 @@ Node *PhiNode::Ideal(PhaseGVN *phase, bool can_reshape) { PhaseIterGVN* igvn = phase->is_IterGVN(); if (wait_for_cast_input_igvn(igvn)) { igvn->_worklist.push(this); - return nullptr; + return progress; } uncasted = true; uin = unique_input(phase, true); @@ -2320,6 +2320,7 @@ Node *PhiNode::Ideal(PhaseGVN *phase, bool can_reshape) { PhaseIterGVN* igvn = phase->is_IterGVN(); for (uint i = 1; i < req(); i++) { set_req_X(i, cast, igvn); + progress = this; } uin = cast; } @@ -2338,7 +2339,7 @@ Node *PhiNode::Ideal(PhaseGVN *phase, bool can_reshape) { #endif // Identity may not return the expected uin, if it has to wait for the region, in irreducible case assert(ident == uin || ident->is_top() || must_wait_for_region_in_irreducible_loop(phase), "Identity must clean this up"); - return nullptr; + return progress; } Node* opt = nullptr; @@ -2529,7 +2530,7 @@ Node *PhiNode::Ideal(PhaseGVN *phase, bool can_reshape) { // Phi references itself through all other inputs then splitting the // Phi through memory merges would create dead loop at later stage. if (ii == top) { - return nullptr; // Delay optimization until graph is cleaned. + return progress; // Delay optimization until graph is cleaned. } if (ii->is_MergeMem()) { MergeMemNode* n = ii->as_MergeMem(); diff --git a/src/hotspot/share/opto/phaseX.cpp b/src/hotspot/share/opto/phaseX.cpp index 1e4cd42e09a..3f8fa7aeeb6 100644 --- a/src/hotspot/share/opto/phaseX.cpp +++ b/src/hotspot/share/opto/phaseX.cpp @@ -2126,9 +2126,15 @@ Node *PhaseIterGVN::transform_old(Node* n) { DEBUG_ONLY(dead_loop_check(k);) DEBUG_ONLY(bool is_new = (k->outcnt() == 0);) C->remove_modified_node(k); +#ifndef PRODUCT + uint hash_before = is_verify_Ideal_return() ? k->hash() : 0; +#endif Node* i = apply_ideal(k, /*can_reshape=*/true); assert(i != k || is_new || i->outcnt() > 0, "don't return dead nodes"); #ifndef PRODUCT + if (is_verify_Ideal_return()) { + assert(k->outcnt() == 0 || i != nullptr || hash_before == k->hash(), "hash changed after Ideal returned nullptr for %s", k->Name()); + } verify_step(k); #endif @@ -2152,9 +2158,15 @@ Node *PhaseIterGVN::transform_old(Node* n) { // Try idealizing again DEBUG_ONLY(is_new = (k->outcnt() == 0);) C->remove_modified_node(k); +#ifndef PRODUCT + uint hash_before = is_verify_Ideal_return() ? k->hash() : 0; +#endif i = apply_ideal(k, /*can_reshape=*/true); assert(i != k || is_new || (i->outcnt() > 0), "don't return dead nodes"); #ifndef PRODUCT + if (is_verify_Ideal_return()) { + assert(k->outcnt() == 0 || i != nullptr || hash_before == k->hash(), "hash changed after Ideal returned nullptr for %s", k->Name()); + } verify_step(k); #endif DEBUG_ONLY(loop_count++;) diff --git a/src/hotspot/share/opto/phaseX.hpp b/src/hotspot/share/opto/phaseX.hpp index 3f75aab8980..b50b47f8403 100644 --- a/src/hotspot/share/opto/phaseX.hpp +++ b/src/hotspot/share/opto/phaseX.hpp @@ -621,6 +621,10 @@ public: // '-XX:VerifyIterativeGVN=10000' return ((VerifyIterativeGVN % 100000) / 10000) == 1; } + static bool is_verify_Ideal_return() { + // '-XX:VerifyIterativeGVN=100000' + return ((VerifyIterativeGVN % 1000000) / 100000) == 1; + } protected: // Sub-quadratic implementation of '-XX:VerifyIterativeGVN=1' (Use-Def verification). julong _verify_counter; diff --git a/src/hotspot/share/runtime/flags/jvmFlagConstraintsCompiler.cpp b/src/hotspot/share/runtime/flags/jvmFlagConstraintsCompiler.cpp index 63d3424b3ed..4700b7951cc 100644 --- a/src/hotspot/share/runtime/flags/jvmFlagConstraintsCompiler.cpp +++ b/src/hotspot/share/runtime/flags/jvmFlagConstraintsCompiler.cpp @@ -306,7 +306,7 @@ JVMFlag::Error TypeProfileLevelConstraintFunc(uint value, bool verbose) { } JVMFlag::Error VerifyIterativeGVNConstraintFunc(uint value, bool verbose) { - const int max_modes = 5; + const int max_modes = 6; uint original_value = value; for (int i = 0; i < max_modes; i++) { if (value % 10 > 1) {