diff --git a/hercules_ir/src/dot.rs b/hercules_ir/src/dot.rs
index 8efabd7a99157b9bb8b40e5abe76d2d42513bb79..5ccda9dc6bf39c016ba44b6eb1085679288d5c54 100644
--- a/hercules_ir/src/dot.rs
+++ b/hercules_ir/src/dot.rs
@@ -16,6 +16,7 @@ use crate::*;
 pub fn xdot_module(
     module: &ir::Module,
     reverse_postorders: &Vec<Vec<NodeID>>,
+    typing: Option<&ModuleTyping>,
     doms: Option<&Vec<DomTree>>,
     fork_join_maps: Option<&Vec<HashMap<NodeID, NodeID>>>,
     devices: Option<&Vec<Device>>,
@@ -30,6 +31,7 @@ pub fn xdot_module(
     write_dot(
         &module,
         &reverse_postorders,
+        typing,
         doms,
         fork_join_maps,
         devices,
@@ -53,6 +55,7 @@ pub fn xdot_module(
 pub fn write_dot<W: Write>(
     module: &ir::Module,
     reverse_postorders: &Vec<Vec<NodeID>>,
+    typing: Option<&ModuleTyping>,
     doms: Option<&Vec<DomTree>>,
     fork_join_maps: Option<&Vec<HashMap<NodeID, NodeID>>>,
     devices: Option<&Vec<Device>>,
@@ -89,6 +92,7 @@ pub fn write_dot<W: Write>(
                 function_id,
                 color,
                 module,
+                typing,
                 &function.schedules[node_id.idx()],
                 w,
             )?;
@@ -249,6 +253,7 @@ fn write_node<W: Write>(
     function_id: FunctionID,
     color: &str,
     module: &Module,
+    typing: Option<&ModuleTyping>,
     schedules: &Vec<Schedule>,
     w: &mut W,
 ) -> std::fmt::Result {
@@ -331,30 +336,37 @@ fn write_node<W: Write>(
     } else {
         format!("{} ({})", node.upper_case_name(), suffix)
     };
+    let xlabel = format!("{}", node_id.idx());
+    let mut tylabel = String::new();
+    if let Some(ty) = typing.map(|typing| typing[function_id.idx()][node_id.idx()]) {
+        module.write_type(ty, &mut tylabel)?;
+    }
 
     let mut iter = schedules.into_iter();
     if let Some(first) = iter.next() {
-        let subtitle = iter.fold(format!("{:?}", first), |b, i| format!("{}, {:?}", b, i));
+        let schedules = iter.fold(format!("{:?}", first), |b, i| format!("{}, {:?}", b, i));
         write!(
             w,
-            "{}_{}_{} [xlabel={}, label=<{}<BR /><FONT POINT-SIZE=\"8\">{}</FONT>>, color={}];\n",
+            "{}_{}_{} [xlabel={}, label=<{}<BR /><FONT POINT-SIZE=\"8\">{}</FONT><BR /><FONT POINT-SIZE=\"8\">{}</FONT>>, color={}];\n",
             node.lower_case_name(),
             function_id.idx(),
             node_id.idx(),
-            node_id.idx(),
+            xlabel,
             label,
-            subtitle,
+            tylabel,
+            schedules,
             color
         )?;
     } else {
         write!(
             w,
-            "{}_{}_{} [xlabel={}, label=\"{}\", color={}];\n",
+            "{}_{}_{} [xlabel={}, label=<{}<BR /><FONT POINT-SIZE=\"8\">{}</FONT>>, color={}];\n",
             node.lower_case_name(),
             function_id.idx(),
             node_id.idx(),
-            node_id.idx(),
+            xlabel,
             label,
+            tylabel,
             color
         )?;
     }
diff --git a/hercules_ir/src/ir.rs b/hercules_ir/src/ir.rs
index d8a124e2cfefde8ea10c3ecbe67b6a6b9a93c690..0b271e857df2269cbdfc51e223424141435558c6 100644
--- a/hercules_ir/src/ir.rs
+++ b/hercules_ir/src/ir.rs
@@ -628,6 +628,7 @@ pub fn dynamic_constants_bottom_up(
     dynamic_constants: &Vec<DynamicConstant>,
 ) -> impl Iterator<Item = DynamicConstantID> + '_ {
     let mut visited = bitvec![u8, Lsb0; 0; dynamic_constants.len()];
+    let mut invalid = bitvec![u8, Lsb0; 0; dynamic_constants.len()];
     let mut stack = (0..dynamic_constants.len())
         .map(DynamicConstantID::new)
         .collect::<Vec<DynamicConstantID>>();
@@ -647,13 +648,16 @@ pub fn dynamic_constants_bottom_up(
                     // We have to yield the children of this node before
                     // this node itself. We keep track of which nodes have
                     // yielded using visited.
-                    if left.idx() >= visited.len() || right.idx() >= visited.len() {
+                    if left.idx() >= visited.len()
+                        || right.idx() >= visited.len()
+                        || invalid[left.idx()]
+                        || invalid[right.idx()]
+                    {
                         // This is an invalid dynamic constant and should be
                         // skipped.
+                        invalid.set(id.idx(), true);
                         continue;
-                    }
-                    let can_yield = visited[left.idx()] && visited[right.idx()];
-                    if can_yield {
+                    } else if visited[left.idx()] && visited[right.idx()] {
                         visited.set(id.idx(), true);
                         yield id;
                     } else {
diff --git a/hercules_opt/src/gcm.rs b/hercules_opt/src/gcm.rs
index 0c7665bfe153dec310369575885074314eebad96..b5822a519a5ca204db3a80d581493ea37ded511b 100644
--- a/hercules_opt/src/gcm.rs
+++ b/hercules_opt/src/gcm.rs
@@ -1163,11 +1163,12 @@ fn object_allocation(
                 Node::Call {
                     control: _,
                     function: callee,
-                    dynamic_constants: _,
+                    ref dynamic_constants,
                     args: _,
                 } => {
+                    let dynamic_constants = dynamic_constants.clone();
                     for device in BACKED_DEVICES {
-                        if let Some(callee_backing_size) = backing_allocations[&callee]
+                        if let Some(mut callee_backing_size) = backing_allocations[&callee]
                             .get(&device)
                             .map(|(callee_total, _)| *callee_total)
                         {
@@ -1177,6 +1178,27 @@ fn object_allocation(
                             // in the callee, so just assume the largest alignment.
                             *total = align(&mut edit, *total, LARGEST_ALIGNMENT);
                             offsets.insert(id, *total);
+                            // Substitute the dynamic constant parameters in the
+                            // callee's backing size.
+                            let first_dc = edit.num_dynamic_constants() + 10000;
+                            for (p_idx, dc_n) in zip(0..dynamic_constants.len(), first_dc..) {
+                                let dc_a =
+                                    edit.add_dynamic_constant(DynamicConstant::Parameter(p_idx));
+                                callee_backing_size = substitute_dynamic_constants(
+                                    dc_a,
+                                    DynamicConstantID::new(dc_n),
+                                    callee_backing_size,
+                                    &mut edit,
+                                );
+                            }
+                            for (dc_n, dc_b) in zip(first_dc.., dynamic_constants.iter()) {
+                                callee_backing_size = substitute_dynamic_constants(
+                                    DynamicConstantID::new(dc_n),
+                                    *dc_b,
+                                    callee_backing_size,
+                                    &mut edit,
+                                );
+                            }
                             *total = edit.add_dynamic_constant(DynamicConstant::Add(
                                 *total,
                                 callee_backing_size,
diff --git a/hercules_opt/src/inline.rs b/hercules_opt/src/inline.rs
index 064e3d73a1d9604ca5b284fe52b8c2e8c5a0339e..1d2bac97d848ace910d614a42743c6ea5fe3aa9e 100644
--- a/hercules_opt/src/inline.rs
+++ b/hercules_opt/src/inline.rs
@@ -179,7 +179,7 @@ fn inline_func(
                     // as the new references we just made in the first step. We
                     // actually want to institute all the updates
                     // *simultaneously*, hence the two step maneuver.
-                    let first_dc = edit.num_dynamic_constants() + 100;
+                    let first_dc = edit.num_dynamic_constants() + 10000;
                     for (dc_a, dc_n) in zip(dcs_a, first_dc..) {
                         substitute_dynamic_constants_in_node(
                             *dc_a,
diff --git a/hercules_opt/src/interprocedural_sroa.rs b/hercules_opt/src/interprocedural_sroa.rs
index 49fbcbbd712fad2977c64fd2ca1d9643bd95d74c..f597cd80347d94a7c927d6fe085d80f843e280eb 100644
--- a/hercules_opt/src/interprocedural_sroa.rs
+++ b/hercules_opt/src/interprocedural_sroa.rs
@@ -320,7 +320,7 @@ fn compress_return_products(editors: &mut Vec<FunctionEditor>, all_callsites_edi
                 let mut substituted = old_return_type_ids[function_id.idx()];
 
                 assert_eq!(old_dcs.len(), new_dcs.len());
-                let first_dc = edit.num_dynamic_constants() + 100;
+                let first_dc = edit.num_dynamic_constants() + 10000;
                 for (dc_a, dc_n) in zip(old_dcs, first_dc..) {
                     substituted = substitute_dynamic_constants_in_type(
                         dc_a,
@@ -424,7 +424,7 @@ fn remove_return_singletons(editors: &mut Vec<FunctionEditor>, all_callsites_edi
             if singleton_removed[function.idx()] {
                 let edit_successful = editor.edit(|mut edit| {
                     let mut substituted = old_return_type_ids[function.idx()];
-                    let first_dc = edit.num_dynamic_constants() + 100;
+                    let first_dc = edit.num_dynamic_constants() + 10000;
                     let dc_params: Vec<_> = (0..dc_args.len())
                         .map(|param_idx| {
                             edit.add_dynamic_constant(DynamicConstant::Parameter(param_idx))
diff --git a/juno_scheduler/src/pm.rs b/juno_scheduler/src/pm.rs
index e62bc78dc4a6e4bb2e1c369fcd2fffc67255ea52..c388833ca6efbc5d1c4f9f7ec346980cbfc1b918 100644
--- a/juno_scheduler/src/pm.rs
+++ b/juno_scheduler/src/pm.rs
@@ -1636,12 +1636,14 @@ fn run_pass(
 
             pm.make_reverse_postorders();
             if force_analyses {
+                pm.make_typing();
                 pm.make_doms();
                 pm.make_fork_join_maps();
                 pm.make_devices();
             }
 
             let reverse_postorders = pm.reverse_postorders.take().unwrap();
+            let typing = pm.typing.take();
             let doms = pm.doms.take();
             let fork_join_maps = pm.fork_join_maps.take();
             let devices = pm.devices.take();
@@ -1650,6 +1652,7 @@ fn run_pass(
                 xdot_module(
                     module,
                     &reverse_postorders,
+                    typing.as_ref(),
                     doms.as_ref(),
                     fork_join_maps.as_ref(),
                     devices.as_ref(),