diff --git a/b_asic/gui_utils/icons.py b/b_asic/gui_utils/icons.py
index 85fa6c818eafe920ef5e771d37a38f3086d96dc2..4bd348a886bb12d8a81716f208d4d9382db3af13 100644
--- a/b_asic/gui_utils/icons.py
+++ b/b_asic/gui_utils/icons.py
@@ -33,6 +33,9 @@ ICONS = {
     'full-screen-exit': 'mdi6.fullscreen-exit',
     'warning': 'fa5s.exclamation-triangle',
     'port-numbers': 'fa5s.hashtag',
+    'swap': 'fa5s.arrows-alt-v',
+    'asap': 'fa5s.fast-backward',
+    'alap': 'fa5s.fast-forward',
 }
 
 
diff --git a/b_asic/schedule.py b/b_asic/schedule.py
index db668d10c300123e86666ed0f04181207afe4b12..a4655e076b73193af06817cb75cdb3116bc520b5 100644
--- a/b_asic/schedule.py
+++ b/b_asic/schedule.py
@@ -644,6 +644,56 @@ class Schedule:
         self._start_times[graph_id] = new_start
         return self
 
+    def move_operation_alap(self, graph_id: GraphID) -> "Schedule":
+        """
+        Move an operation as late as possible in the schedule.
+
+        This is basically the same as::
+
+            schedule.move_operation(graph_id, schedule.forward_slack(graph_id))
+
+        but Outputs will only move to the end of the schedule.
+
+        Parameters
+        ----------
+        graph_id : GraphID
+            The graph id of the operation to move.
+        """
+        op = self._sfg.find_by_id(graph_id)
+        if op is None:
+            raise ValueError(f"No operation with graph_id {graph_id!r} in schedule")
+        if isinstance(op, Output):
+            self.move_operation(
+                graph_id, self.schedule_time - self._start_times[graph_id]
+            )
+        else:
+            self.move_operation(graph_id, self.forward_slack(graph_id))
+        return self
+
+    def move_operation_asap(self, graph_id: GraphID) -> "Schedule":
+        """
+        Move an operation as soon as possible in the schedule.
+
+        This is basically the same as::
+
+            schedule.move_operation(graph_id, -schedule.backward_slack(graph_id))
+
+        but Inputs will only move to the start of the schedule.
+
+        Parameters
+        ----------
+        graph_id : GraphID
+            The graph id of the operation to move.
+        """
+        op = self._sfg.find_by_id(graph_id)
+        if op is None:
+            raise ValueError(f"No operation with graph_id {graph_id!r} in schedule")
+        if isinstance(op, Input):
+            self.move_operation(graph_id, -self._start_times[graph_id])
+        else:
+            self.move_operation(graph_id, -self.backward_slack(graph_id))
+        return self
+
     def _remove_delays_no_laps(self) -> None:
         """Remove delay elements without updating laps. Used when loading schedule."""
         delay_list = self._sfg.find_by_type_name(Delay.type_name())
diff --git a/b_asic/scheduler_gui/operation_item.py b/b_asic/scheduler_gui/operation_item.py
index c84529fafe27b5b7569e6ca60c4a68faa6579e01..e6d823e03397b57adcfb79a94a2814460606f97c 100644
--- a/b_asic/scheduler_gui/operation_item.py
+++ b/b_asic/scheduler_gui/operation_item.py
@@ -21,8 +21,10 @@ from qtpy.QtWidgets import (
     QMenu,
 )
 
-# B-ASIC
 from b_asic.graph_component import GraphID
+
+# B-ASIC
+from b_asic.gui_utils.icons import get_icon
 from b_asic.operation import Operation
 from b_asic.scheduler_gui._preferences import (
     OPERATION_EXECUTION_TIME_INACTIVE,
@@ -305,10 +307,20 @@ class OperationItem(QGraphicsItemGroup):
 
     def _open_context_menu(self):
         menu = QMenu()
-        swap = QAction("Swap")
+        swap = QAction(get_icon('swap'), "Swap")
         menu.addAction(swap)
         swap.setEnabled(self._operation.is_swappable)
         swap.triggered.connect(self._swap_io)
+        slacks = self._parent._schedule.slacks(self._operation.graph_id)
+        asap = QAction(get_icon('asap'), "Move as soon as possible")
+        asap.triggered.connect(self._move_asap)
+        asap.setEnabled(slacks[0] > 0)
+        menu.addAction(asap)
+        alap = QAction(get_icon('alap'), "Move as late as possible")
+        alap.triggered.connect(self._move_alap)
+        alap.setEnabled(slacks[1] > 0)
+        menu.addAction(alap)
+        menu.addSeparator()
         execution_time_plot = QAction(
             f"Show execution times for {self._operation.type_name()}"
         )
@@ -321,3 +333,9 @@ class OperationItem(QGraphicsItemGroup):
 
     def _execution_time_plot(self, event=None) -> None:
         self._parent._execution_time_plot(self._operation.type_name())
+
+    def _move_asap(self, event=None):
+        self._parent._schedule.move_operation_asap(self._operation.graph_id)
+
+    def _move_alap(self, event=None):
+        self._parent._schedule.move_operation_alap(self._operation.graph_id)