@@ -402,6 +402,9 @@ void Compile::remove_useless_node(Node* dead) {
402402 if (dead->for_post_loop_opts_igvn ()) {
403403 remove_from_post_loop_opts_igvn (dead);
404404 }
405+ if (dead->for_merge_stores_igvn ()) {
406+ remove_from_merge_stores_igvn (dead);
407+ }
405408 if (dead->is_Call ()) {
406409 remove_useless_late_inlines ( &_late_inlines, dead);
407410 remove_useless_late_inlines ( &_string_late_inlines, dead);
@@ -453,6 +456,7 @@ void Compile::disconnect_useless_nodes(Unique_Node_List& useful, Unique_Node_Lis
453456 remove_useless_nodes (_template_assertion_predicate_opaqs, useful); // remove useless Assertion Predicate opaque nodes
454457 remove_useless_nodes (_expensive_nodes, useful); // remove useless expensive nodes
455458 remove_useless_nodes (_for_post_loop_igvn, useful); // remove useless node recorded for post loop opts IGVN pass
459+ remove_useless_nodes (_for_merge_stores_igvn, useful); // remove useless node recorded for merge stores IGVN pass
456460 remove_useless_unstable_if_traps (useful); // remove useless unstable_if traps
457461 remove_useless_coarsened_locks (useful); // remove useless coarsened locks nodes
458462#ifdef ASSERT
@@ -627,6 +631,7 @@ Compile::Compile(ciEnv* ci_env, ciMethod* target, int osr_bci,
627631 _stub_entry_point(nullptr ),
628632 _max_node_limit(MaxNodeLimit),
629633 _post_loop_opts_phase(false ),
634+ _merge_stores_phase(false ),
630635 _allow_macro_nodes(true ),
631636 _inlining_progress(false ),
632637 _inlining_incrementally(false ),
@@ -651,6 +656,7 @@ Compile::Compile(ciEnv* ci_env, ciMethod* target, int osr_bci,
651656 _template_assertion_predicate_opaqs(comp_arena(), 8, 0, nullptr),
652657 _expensive_nodes(comp_arena(), 8, 0, nullptr),
653658 _for_post_loop_igvn(comp_arena(), 8, 0, nullptr),
659+ _for_merge_stores_igvn(comp_arena(), 8, 0, nullptr),
654660 _unstable_if_traps(comp_arena(), 8, 0, nullptr),
655661 _coarsened_locks(comp_arena(), 8, 0, nullptr),
656662 _congraph(nullptr ),
@@ -905,6 +911,7 @@ Compile::Compile(ciEnv* ci_env,
905911 _stub_entry_point(nullptr ),
906912 _max_node_limit(MaxNodeLimit),
907913 _post_loop_opts_phase(false ),
914+ _merge_stores_phase(false ),
908915 _allow_macro_nodes(true ),
909916 _inlining_progress(false ),
910917 _inlining_incrementally(false ),
@@ -923,6 +930,7 @@ Compile::Compile(ciEnv* ci_env,
923930 _log(ci_env->log ()),
924931 _first_failure_details(nullptr ),
925932 _for_post_loop_igvn(comp_arena(), 8, 0, nullptr),
933+ _for_merge_stores_igvn(comp_arena(), 8, 0, nullptr),
926934 _congraph(nullptr ),
927935 NOT_PRODUCT(_igv_printer(nullptr ) COMMA)
928936 _unique(0 ),
@@ -1870,6 +1878,49 @@ void Compile::process_for_post_loop_opts_igvn(PhaseIterGVN& igvn) {
18701878 }
18711879}
18721880
1881+ void Compile::record_for_merge_stores_igvn (Node* n) {
1882+ if (!n->for_merge_stores_igvn ()) {
1883+ assert (!_for_merge_stores_igvn.contains (n), " duplicate" );
1884+ n->add_flag (Node::NodeFlags::Flag_for_merge_stores_igvn);
1885+ _for_merge_stores_igvn.append (n);
1886+ }
1887+ }
1888+
1889+ void Compile::remove_from_merge_stores_igvn (Node* n) {
1890+ n->remove_flag (Node::NodeFlags::Flag_for_merge_stores_igvn);
1891+ _for_merge_stores_igvn.remove (n);
1892+ }
1893+
1894+ // We need to wait with merging stores until RangeCheck smearing has removed the RangeChecks during
1895+ // the post loops IGVN phase. If we do it earlier, then there may still be some RangeChecks between
1896+ // the stores, and we merge the wrong sequence of stores.
1897+ // Example:
1898+ // StoreI RangeCheck StoreI StoreI RangeCheck StoreI
1899+ // Apply MergeStores:
1900+ // StoreI RangeCheck [ StoreL ] RangeCheck StoreI
1901+ // Remove more RangeChecks:
1902+ // StoreI [ StoreL ] StoreI
1903+ // But now it would have been better to do this instead:
1904+ // [ StoreL ] [ StoreL ]
1905+ //
1906+ // Note: we allow stores to merge in this dedicated IGVN round, and any later IGVN round,
1907+ // since we never unset _merge_stores_phase.
1908+ void Compile::process_for_merge_stores_igvn (PhaseIterGVN& igvn) {
1909+ C->set_merge_stores_phase ();
1910+
1911+ if (_for_merge_stores_igvn.length () > 0 ) {
1912+ while (_for_merge_stores_igvn.length () > 0 ) {
1913+ Node* n = _for_merge_stores_igvn.pop ();
1914+ n->remove_flag (Node::NodeFlags::Flag_for_merge_stores_igvn);
1915+ igvn._worklist .push (n);
1916+ }
1917+ igvn.optimize ();
1918+ if (failing ()) return ;
1919+ assert (_for_merge_stores_igvn.length () == 0 , " no more delayed nodes allowed" );
1920+ print_method (PHASE_AFTER_MERGE_STORES, 3 );
1921+ }
1922+ }
1923+
18731924void Compile::record_unstable_if_trap (UnstableIfTrap* trap) {
18741925 if (OptimizeUnstableIf) {
18751926 _unstable_if_traps.append (trap);
@@ -2429,6 +2480,8 @@ void Compile::Optimize() {
24292480
24302481 process_for_post_loop_opts_igvn (igvn);
24312482
2483+ process_for_merge_stores_igvn (igvn);
2484+
24322485 if (failing ()) return ;
24332486
24342487#ifdef ASSERT
0 commit comments