@@ -402,6 +402,9 @@ void Compile::remove_useless_node(Node* dead) {
402
402
if (dead->for_post_loop_opts_igvn ()) {
403
403
remove_from_post_loop_opts_igvn (dead);
404
404
}
405
+ if (dead->for_merge_stores_igvn ()) {
406
+ remove_from_merge_stores_igvn (dead);
407
+ }
405
408
if (dead->is_Call ()) {
406
409
remove_useless_late_inlines ( &_late_inlines, dead);
407
410
remove_useless_late_inlines ( &_string_late_inlines, dead);
@@ -453,6 +456,7 @@ void Compile::disconnect_useless_nodes(Unique_Node_List& useful, Unique_Node_Lis
453
456
remove_useless_nodes (_template_assertion_predicate_opaqs, useful); // remove useless Assertion Predicate opaque nodes
454
457
remove_useless_nodes (_expensive_nodes, useful); // remove useless expensive nodes
455
458
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
456
460
remove_useless_unstable_if_traps (useful); // remove useless unstable_if traps
457
461
remove_useless_coarsened_locks (useful); // remove useless coarsened locks nodes
458
462
#ifdef ASSERT
@@ -627,6 +631,7 @@ Compile::Compile(ciEnv* ci_env, ciMethod* target, int osr_bci,
627
631
_stub_entry_point(nullptr ),
628
632
_max_node_limit(MaxNodeLimit),
629
633
_post_loop_opts_phase(false ),
634
+ _merge_stores_phase(false ),
630
635
_allow_macro_nodes(true ),
631
636
_inlining_progress(false ),
632
637
_inlining_incrementally(false ),
@@ -651,6 +656,7 @@ Compile::Compile(ciEnv* ci_env, ciMethod* target, int osr_bci,
651
656
_template_assertion_predicate_opaqs(comp_arena(), 8, 0, nullptr),
652
657
_expensive_nodes(comp_arena(), 8, 0, nullptr),
653
658
_for_post_loop_igvn(comp_arena(), 8, 0, nullptr),
659
+ _for_merge_stores_igvn(comp_arena(), 8, 0, nullptr),
654
660
_unstable_if_traps(comp_arena(), 8, 0, nullptr),
655
661
_coarsened_locks(comp_arena(), 8, 0, nullptr),
656
662
_congraph(nullptr ),
@@ -905,6 +911,7 @@ Compile::Compile(ciEnv* ci_env,
905
911
_stub_entry_point(nullptr ),
906
912
_max_node_limit(MaxNodeLimit),
907
913
_post_loop_opts_phase(false ),
914
+ _merge_stores_phase(false ),
908
915
_allow_macro_nodes(true ),
909
916
_inlining_progress(false ),
910
917
_inlining_incrementally(false ),
@@ -923,6 +930,7 @@ Compile::Compile(ciEnv* ci_env,
923
930
_log(ci_env->log ()),
924
931
_first_failure_details(nullptr ),
925
932
_for_post_loop_igvn(comp_arena(), 8, 0, nullptr),
933
+ _for_merge_stores_igvn(comp_arena(), 8, 0, nullptr),
926
934
_congraph(nullptr ),
927
935
NOT_PRODUCT(_igv_printer(nullptr ) COMMA)
928
936
_unique(0 ),
@@ -1870,6 +1878,49 @@ void Compile::process_for_post_loop_opts_igvn(PhaseIterGVN& igvn) {
1870
1878
}
1871
1879
}
1872
1880
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
+
1873
1924
void Compile::record_unstable_if_trap (UnstableIfTrap* trap) {
1874
1925
if (OptimizeUnstableIf) {
1875
1926
_unstable_if_traps.append (trap);
@@ -2429,6 +2480,8 @@ void Compile::Optimize() {
2429
2480
2430
2481
process_for_post_loop_opts_igvn (igvn);
2431
2482
2483
+ process_for_merge_stores_igvn (igvn);
2484
+
2432
2485
if (failing ()) return ;
2433
2486
2434
2487
#ifdef ASSERT
0 commit comments