diff --git a/src/hotspot/share/gc/shenandoah/shenandoahControlThread.cpp b/src/hotspot/share/gc/shenandoah/shenandoahControlThread.cpp
index fbfd8364667..c6da9794f25 100644
--- a/src/hotspot/share/gc/shenandoah/shenandoahControlThread.cpp
+++ b/src/hotspot/share/gc/shenandoah/shenandoahControlThread.cpp
@@ -354,7 +354,7 @@ void ShenandoahControlThread::service_concurrent_normal_cycle(GCCause::Cause cau
 
   // Final mark might have reclaimed some immediate garbage, kick cleanup to reclaim
   // the space. This would be the last action if there is nothing to evacuate.
-  heap->entry_cleanup();
+  heap->entry_cleanup_early();
 
   {
     ShenandoahHeapLocker locker(heap->lock());
@@ -389,7 +389,7 @@ void ShenandoahControlThread::service_concurrent_normal_cycle(GCCause::Cause cau
     heap->vmop_entry_final_updaterefs();
 
     // Update references freed up collection set, kick the cleanup to reclaim the space.
-    heap->entry_cleanup();
+    heap->entry_cleanup_complete();
   }
 
   // Cycle is complete
diff --git a/src/hotspot/share/gc/shenandoah/shenandoahHeap.cpp b/src/hotspot/share/gc/shenandoah/shenandoahHeap.cpp
index d03653109bb..95115ada568 100644
--- a/src/hotspot/share/gc/shenandoah/shenandoahHeap.cpp
+++ b/src/hotspot/share/gc/shenandoah/shenandoahHeap.cpp
@@ -1630,7 +1630,11 @@ void ShenandoahHeap::op_updaterefs() {
   update_heap_references(true);
 }
 
-void ShenandoahHeap::op_cleanup() {
+void ShenandoahHeap::op_cleanup_early() {
+  free_set()->recycle_trash();
+}
+
+void ShenandoahHeap::op_cleanup_complete() {
   free_set()->recycle_trash();
 }
 
@@ -1950,7 +1954,7 @@ void ShenandoahHeap::op_degenerated(ShenandoahDegenPoint point) {
         ShenandoahCodeRoots::disarm_nmethods();
       }
 
-      op_cleanup();
+      op_cleanup_early();
 
     case _degenerated_evac:
       // If heuristics thinks we should do the cycle, this flag would be set,
@@ -2013,7 +2017,7 @@ void ShenandoahHeap::op_degenerated(ShenandoahDegenPoint point) {
         }
       }
 
-      op_cleanup();
+      op_cleanup_complete();
       break;
 
     default:
@@ -2921,17 +2925,30 @@ void ShenandoahHeap::entry_strong_roots() {
   op_strong_roots();
 }
 
-void ShenandoahHeap::entry_cleanup() {
+void ShenandoahHeap::entry_cleanup_early() {
   static const char* msg = "Concurrent cleanup";
   ShenandoahConcurrentPhase gc_phase(msg,  true /* log_heap_usage */);
   EventMark em("%s", msg);
 
-  ShenandoahGCSubPhase phase(ShenandoahPhaseTimings::conc_cleanup);
+  ShenandoahGCSubPhase phase(ShenandoahPhaseTimings::conc_cleanup_early);
 
   // This phase does not use workers, no need for setup
 
   try_inject_alloc_failure();
-  op_cleanup();
+  op_cleanup_early();
+}
+
+void ShenandoahHeap::entry_cleanup_complete() {
+  static const char* msg = "Concurrent cleanup";
+  ShenandoahConcurrentPhase gc_phase(msg,  true /* log_heap_usage */);
+  EventMark em("%s", msg);
+
+  ShenandoahGCSubPhase phase(ShenandoahPhaseTimings::conc_cleanup_complete);
+
+  // This phase does not use workers, no need for setup
+
+  try_inject_alloc_failure();
+  op_cleanup_complete();
 }
 
 void ShenandoahHeap::entry_reset() {
diff --git a/src/hotspot/share/gc/shenandoah/shenandoahHeap.hpp b/src/hotspot/share/gc/shenandoah/shenandoahHeap.hpp
index 8533dcd30c2..723b7c817be 100644
--- a/src/hotspot/share/gc/shenandoah/shenandoahHeap.hpp
+++ b/src/hotspot/share/gc/shenandoah/shenandoahHeap.hpp
@@ -400,9 +400,10 @@ public:
   void entry_weak_roots();
   void entry_class_unloading();
   void entry_strong_roots();
-  void entry_cleanup();
+  void entry_cleanup_early();
   void entry_evac();
   void entry_updaterefs();
+  void entry_cleanup_complete();
   void entry_uncommit(double shrink_before);
 
 private:
@@ -422,10 +423,11 @@ private:
   void op_weak_roots();
   void op_class_unloading();
   void op_strong_roots();
-  void op_cleanup();
+  void op_cleanup_early();
   void op_conc_evac();
   void op_stw_evac();
   void op_updaterefs();
+  void op_cleanup_complete();
   void op_uncommit(double shrink_before);
 
   // Messages for GC trace events, they have to be immortal for
diff --git a/src/hotspot/share/gc/shenandoah/shenandoahPhaseTimings.hpp b/src/hotspot/share/gc/shenandoah/shenandoahPhaseTimings.hpp
index a3e4c5d7b99..4884021d39f 100644
--- a/src/hotspot/share/gc/shenandoah/shenandoahPhaseTimings.hpp
+++ b/src/hotspot/share/gc/shenandoah/shenandoahPhaseTimings.hpp
@@ -57,6 +57,8 @@ class outputStream;
   // end
 
 #define SHENANDOAH_GC_PHASE_DO(f)                                                      \
+  f(conc_reset,                                     "Concurrent Reset")                \
+                                                                                       \
   f(init_mark_gross,                                "Pause Init Mark (G)")             \
   f(init_mark,                                      "Pause Init Mark (N)")             \
   f(make_parsable,                                  "  Make Parsable")                 \
@@ -65,6 +67,9 @@ class outputStream;
   SHENANDOAH_GC_PAR_PHASE_DO(scan_,                 "    S: ", f)                      \
   f(resize_tlabs,                                   "  Resize TLABs")                  \
                                                                                        \
+  f(conc_mark,                                      "Concurrent Marking")              \
+  f(conc_preclean,                                  "Concurrent Precleaning")          \
+                                                                                       \
   f(final_mark_gross,                               "Pause Final Mark (G)")            \
   f(final_mark,                                     "Pause Final Mark (N)")            \
   f(update_roots,                                   "  Update Roots")                  \
@@ -84,10 +89,18 @@ class outputStream;
   f(init_evac,                                      "  Initial Evacuation")            \
   SHENANDOAH_GC_PAR_PHASE_DO(evac_,                 "    E: ", f)                      \
                                                                                        \
+  f(conc_weak_roots,                                "Concurrent Weak Roots")           \
+  f(conc_cleanup_early,                             "Concurrent Cleanup")              \
+  f(conc_class_unloading,                           "Concurrent Class Unloading")      \
+  f(conc_strong_roots,                              "Concurrent Strong Roots")         \
+  f(conc_evac,                                      "Concurrent Evacuation")           \
+                                                                                       \
   f(init_update_refs_gross,                         "Pause Init  Update Refs (G)")     \
   f(init_update_refs,                               "Pause Init  Update Refs (N)")     \
   f(init_update_refs_retire_gclabs,                 "  Retire GCLABs")                 \
                                                                                        \
+  f(conc_update_refs,                               "Concurrent Update Refs")          \
+                                                                                       \
   f(final_update_refs_gross,                        "Pause Final Update Refs (G)")     \
   f(final_update_refs,                              "Pause Final Update Refs (N)")     \
   f(final_update_refs_finish_work,                  "  Finish Work")                   \
@@ -97,6 +110,8 @@ class outputStream;
   f(final_update_refs_trash_cset,                   "  Trash Collection Set")          \
   f(final_update_refs_rebuild_freeset,              "  Rebuild Free Set")              \
                                                                                        \
+  f(conc_cleanup_complete,                          "Concurrent Cleanup")              \
+                                                                                       \
   f(degen_gc_gross,                                 "Pause Degenerated GC (G)")        \
   f(degen_gc,                                       "Pause Degenerated GC (N)")        \
   f(degen_gc_update_roots,                          "  Degen Update Roots")            \
@@ -128,17 +143,6 @@ class outputStream;
   f(full_gc_copy_objects_rebuild,                   "    Rebuild Region Sets")         \
   f(full_gc_resize_tlabs,                           "  Resize TLABs")                  \
                                                                                        \
-  /* Longer concurrent phases at the end */                                            \
-  f(conc_reset,                                     "Concurrent Reset")                \
-  f(conc_mark,                                      "Concurrent Marking")              \
-  f(conc_preclean,                                  "Concurrent Precleaning")          \
-  f(conc_weak_roots,                                "Concurrent Weak Roots")           \
-  f(conc_class_unloading,                           "Concurrent Class Unloading")      \
-  f(conc_strong_roots,                              "Concurrent Strong Roots")         \
-  f(conc_evac,                                      "Concurrent Evacuation")           \
-  f(conc_update_refs,                               "Concurrent Update Refs")          \
-  f(conc_cleanup,                                   "Concurrent Cleanup")              \
-                                                                                       \
   f(conc_uncommit,                                  "Concurrent Uncommit")             \
                                                                                        \
   /* Unclassified */                                                                   \