@@ -745,6 +745,11 @@ void PhaseIdealLoop::do_peeling(IdealLoopTree *loop, Node_List &old_new) {
745745 cl->set_trip_count (cl->trip_count () - 1 );
746746 if (cl->is_main_loop ()) {
747747 cl->set_normal_loop ();
748+ if (cl->is_multiversion ()) {
749+ // Peeling also destroys the connection of the main loop
750+ // to the multiversion_if.
751+ cl->set_no_multiversion ();
752+ }
748753#ifndef PRODUCT
749754 if (PrintOpto && VerifyLoopOptimizations) {
750755 tty->print (" Peeling a 'main' loop; resetting to 'normal' " );
@@ -1174,8 +1179,9 @@ bool IdealLoopTree::policy_range_check(PhaseIdealLoop* phase, bool provisional,
11741179 if (!bol->is_Bool ()) {
11751180 assert (bol->is_OpaqueNotNull () ||
11761181 bol->is_OpaqueTemplateAssertionPredicate () ||
1177- bol->is_OpaqueInitializedAssertionPredicate (),
1178- " Opaque node of a non-null-check or an Assertion Predicate" );
1182+ bol->is_OpaqueInitializedAssertionPredicate () ||
1183+ bol->is_OpaqueMultiversioning (),
1184+ " Opaque node of a non-null-check or an Assertion Predicate or Multiversioning" );
11791185 continue ;
11801186 }
11811187 if (bol->as_Bool ()->_test ._test == BoolTest::ne) {
@@ -3354,6 +3360,23 @@ bool IdealLoopTree::iteration_split_impl(PhaseIdealLoop *phase, Node_List &old_n
33543360 // Do nothing special to pre- and post- loops
33553361 if (cl->is_pre_loop () || cl->is_post_loop ()) return true ;
33563362
3363+ // With multiversioning, we create a fast_loop and a slow_loop, and a multiversion_if that
3364+ // decides which loop is taken at runtime. At first, the multiversion_if always takes the
3365+ // fast_loop, and we only optimize the fast_loop. Since we are not sure if we will ever use
3366+ // the slow_loop, we delay optimizations for it, so we do not waste compile time and code
3367+ // size. If we never change the condition of the multiversion_if, the slow_loop is eventually
3368+ // folded away after loop-opts. While optimizing the fast_loop, we may want to perform some
3369+ // speculative optimization, for which we need a runtime-check. We add this runtime-check
3370+ // condition to the multiversion_if. Now, it becomes possible to execute the slow_loop at
3371+ // runtime, and we resume optimizations for slow_loop ("un-delay" it).
3372+ // TLDR: If the slow_loop is still in "delay" mode, check if the multiversion_if was changed
3373+ // and we should now resume optimizations for it.
3374+ if (cl->is_multiversion_delayed_slow_loop () &&
3375+ !phase->try_resume_optimizations_for_delayed_slow_loop (this )) {
3376+ // We are still delayed, so wait with further loop-opts.
3377+ return true ;
3378+ }
3379+
33573380 // Compute loop trip count from profile data
33583381 compute_profile_trip_cnt (phase);
33593382
@@ -3413,6 +3436,12 @@ bool IdealLoopTree::iteration_split_impl(PhaseIdealLoop *phase, Node_List &old_n
34133436 if (!phase->may_require_nodes (estimate)) {
34143437 return false ;
34153438 }
3439+
3440+ // We are going to add pre-loop and post-loop.
3441+ // But should we also multi-version for auto-vectorization speculative
3442+ // checks, i.e. fast and slow-paths?
3443+ phase->maybe_multiversion_for_auto_vectorization_runtime_checks (this , old_new);
3444+
34163445 phase->insert_pre_post_loops (this , old_new, peel_only);
34173446 }
34183447 // Adjust the pre- and main-loop limits to let the pre and post loops run
0 commit comments