diff --git a/hercules_opt/src/unforkify.rs b/hercules_opt/src/unforkify.rs
index 7d158d1a0378cac55c24533a96ccd36610c8bfeb..a08d1667929e8e08fa476ae0c2f706d77f808ec7 100644
--- a/hercules_opt/src/unforkify.rs
+++ b/hercules_opt/src/unforkify.rs
@@ -118,7 +118,7 @@ pub fn unforkify(
     // control insides of the fork-join should become the successor of the true
     // projection node, and what was the use of the join should become a use of
     // the new region.
-    for l in loop_tree.bottom_up_loops().into_iter().rev() {
+    for l in loop_tree.bottom_up_loops().iter().rev() {
         if !editor.node(l.0).is_fork() {
             continue;
         }
@@ -133,7 +133,8 @@ pub fn unforkify(
         if factors.len() > 1 {
             // For now, don't convert multi-dimensional fork-joins. Rely on pass
             // that splits fork-joins.
-            break; // Because we have to unforkify top down, we can't unforkify forks that are contained 
+            // We can't unforkify, because then the outer forks reduce will depend on non-fork control.
+            break;
         }
         let join_control = nodes[join.idx()].try_join().unwrap();
         let tids: Vec<_> = editor
@@ -293,5 +294,6 @@ pub fn unforkify(
 
             Ok(edit)
         });
+        break;
     }
 }
diff --git a/juno_scheduler/src/pm.rs b/juno_scheduler/src/pm.rs
index d2772c71971638205613dc4c92eb7ac835b02983..378d873069466541daa4767db7678467791459a9 100644
--- a/juno_scheduler/src/pm.rs
+++ b/juno_scheduler/src/pm.rs
@@ -1815,25 +1815,35 @@ fn run_pass(
         }
         Pass::Unforkify => {
             assert!(args.is_empty());
-            pm.make_fork_join_maps();
-            pm.make_loops();
+            loop {
+                let mut inner_changed = false;
 
-            let fork_join_maps = pm.fork_join_maps.take().unwrap();
-            let loops = pm.loops.take().unwrap();
+                pm.make_fork_join_maps();
+                pm.make_loops();
 
-            for ((func, fork_join_map), loop_tree) in build_selection(pm, selection)
-                .into_iter()
-                .zip(fork_join_maps.iter())
-                .zip(loops.iter())
-            {
-                let Some(mut func) = func else {
-                    continue;
-                };
-                unforkify(&mut func, fork_join_map, loop_tree);
-                changed |= func.modified();
+                let fork_join_maps = pm.fork_join_maps.take().unwrap();
+                let loops = pm.loops.take().unwrap();
+
+                for ((func, fork_join_map), loop_tree) in build_selection(pm, selection.clone())
+                    .into_iter()
+                    .zip(fork_join_maps.iter())
+                    .zip(loops.iter())
+                {
+                    let Some(mut func) = func else {
+                        continue;
+                    };
+                    unforkify(&mut func, fork_join_map, loop_tree);
+                    changed |= func.modified();
+                    inner_changed |= func.modified();
+                }
+                pm.delete_gravestones();
+                pm.clear_analyses();
+
+                if !inner_changed {
+                    break;
+                }
+                break;
             }
-            pm.delete_gravestones();
-            pm.clear_analyses();
         }
         Pass::ForkCoalesce => {
             assert!(args.is_empty());