diff --git a/hercules_opt/src/editor.rs b/hercules_opt/src/editor.rs
index 1981b1297be06a4bf91a59fd870697aeafff4a91..2d342a88846dc334484d4ab58efd27652eeb20c5 100644
--- a/hercules_opt/src/editor.rs
+++ b/hercules_opt/src/editor.rs
@@ -462,7 +462,7 @@ impl<'a, 'b> FunctionEdit<'a, 'b> {
                 Constant::Product(id, dummy_elems.into_boxed_slice())
             }
             Type::Summation(tys) => Constant::Summation(id, 0, self.add_zero_constant(tys[0])),
-            Type::Array(tid, _) => Constant::Array(tid),
+            Type::Array(_, _) => Constant::Array(id),
         };
         self.add_constant(constant_to_construct)
     }
diff --git a/hercules_opt/src/pass.rs b/hercules_opt/src/pass.rs
index 33d7bfb3f7d476b262cac094c6b5bfbbebda925e..f69958e2f2dd51b1f2a2c26f07a281031927bbb5 100644
--- a/hercules_opt/src/pass.rs
+++ b/hercules_opt/src/pass.rs
@@ -675,7 +675,6 @@ impl PassManager {
                         self.make_doms();
                         self.make_fork_join_maps();
                         self.make_bbs();
-                        self.make_plans();
                     }
                     xdot_module(
                         &self.module,
diff --git a/hercules_opt/src/sroa.rs b/hercules_opt/src/sroa.rs
index 59ee4a8ad54cea9627ae85185fe5fe04198e72cc..67c904ffbc566b373f4b7f13f68b5cb5a77d08af 100644
--- a/hercules_opt/src/sroa.rs
+++ b/hercules_opt/src/sroa.rs
@@ -1,8 +1,7 @@
 extern crate hercules_ir;
 
-use std::collections::{BTreeMap, HashMap, LinkedList, VecDeque};
+use std::collections::{BTreeMap, HashMap, VecDeque};
 
-use self::hercules_ir::dataflow::*;
 use self::hercules_ir::ir::*;
 
 use crate::*;
@@ -41,6 +40,12 @@ use crate::*;
  *   replaced by a direct def of the field value
  */
 pub fn sroa(editor: &mut FunctionEditor, reverse_postorder: &Vec<NodeID>, types: &Vec<TypeID>) {
+    let mut types: HashMap<NodeID, TypeID> = types
+        .iter()
+        .enumerate()
+        .map(|(i, t)| (NodeID::new(i), *t))
+        .collect();
+
     // This map stores a map from NodeID to an index tree which can be used to lookup the NodeID
     // that contains the corresponding fields of the original value
     let mut field_map: HashMap<NodeID, IndexTree<NodeID>> = HashMap::new();
@@ -65,17 +70,15 @@ pub fn sroa(editor: &mut FunctionEditor, reverse_postorder: &Vec<NodeID>, types:
                 second: _,
                 third: _,
                 op: TernaryOperator::Select,
-            } if editor.get_type(types[node.idx()]).is_product() => product_nodes.push(*node),
+            } if editor.get_type(types[&node]).is_product() => product_nodes.push(*node),
 
-            Node::Read { collect, .. } if editor.get_type(types[collect.idx()]).is_product() => {
+            Node::Read { collect, .. } if editor.get_type(types[&collect]).is_product() => {
                 product_nodes.push(*node)
             }
 
             // We add all calls to the call/return list and check their arguments later
             Node::Call { .. } => call_return_nodes.push(*node),
-            Node::Return { control: _, data }
-                if editor.get_type(types[data.idx()]).is_product() =>
-            {
+            Node::Return { control: _, data } if editor.get_type(types[&data]).is_product() => {
                 call_return_nodes.push(*node)
             }
 
@@ -93,10 +96,9 @@ pub fn sroa(editor: &mut FunctionEditor, reverse_postorder: &Vec<NodeID>, types:
     for node in call_return_nodes {
         match &editor.func().nodes[node.idx()] {
             Node::Return { control, data } => {
-                assert!(editor.get_type(types[data.idx()]).is_product());
+                assert!(editor.get_type(types[&data]).is_product());
                 let control = *control;
-                let new_data =
-                    reconstruct_product(editor, types[data.idx()], *data, &mut product_nodes);
+                let new_data = reconstruct_product(editor, types[&data], *data, &mut product_nodes);
                 editor.edit(|mut edit| {
                     edit.add_node(Node::Return {
                         control,
@@ -117,18 +119,18 @@ pub fn sroa(editor: &mut FunctionEditor, reverse_postorder: &Vec<NodeID>, types:
                 let args = args.clone();
 
                 // If the call returns a product, we generate reads for each field
-                let fields = if editor.get_type(types[node.idx()]).is_product() {
-                    Some(generate_reads(editor, types[node.idx()], node))
+                let fields = if editor.get_type(types[&node]).is_product() {
+                    Some(generate_reads(editor, types[&node], node))
                 } else {
                     None
                 };
 
                 let mut new_args = vec![];
                 for arg in args {
-                    if editor.get_type(types[arg.idx()]).is_product() {
+                    if editor.get_type(types[&arg]).is_product() {
                         new_args.push(reconstruct_product(
                             editor,
-                            types[arg.idx()],
+                            types[&arg],
                             arg,
                             &mut product_nodes,
                         ));
@@ -146,6 +148,13 @@ pub fn sroa(editor: &mut FunctionEditor, reverse_postorder: &Vec<NodeID>, types:
                     let edit = edit.replace_all_uses(node, new_call)?;
                     let edit = edit.delete_node(node)?;
 
+                    // Since we've replaced uses of calls with the new node, we update the type
+                    // information so that we can retrieve the type of the new call if needed
+                    // Because the other nodes we've created so far are only used in very
+                    // particular ways (i.e. are not used by arbitrary nodes) we don't need their
+                    // type information but do for the new calls
+                    types.insert(new_call, types[&node]);
+
                     match fields {
                         None => {}
                         Some(fields) => {
@@ -195,7 +204,7 @@ pub fn sroa(editor: &mut FunctionEditor, reverse_postorder: &Vec<NodeID>, types:
     for node in product_nodes {
         match editor.func().nodes[node.idx()] {
             Node::Parameter { .. } => {
-                field_map.insert(node, generate_reads(editor, types[node.idx()], node));
+                field_map.insert(node, generate_reads(editor, types[&node], node));
             }
             Node::Constant { id } => {
                 field_map.insert(node, generate_constant_fields(editor, id));
@@ -222,7 +231,7 @@ pub fn sroa(editor: &mut FunctionEditor, reverse_postorder: &Vec<NodeID>, types:
                 Node::Phi { control, data } => {
                     let control = *control;
                     let data = data.clone();
-                    let fields = allocate_fields(editor, types[node.idx()], &mut next_id);
+                    let fields = allocate_fields(editor, types[&node], &mut next_id);
                     field_map.insert(node, fields.clone());
 
                     item = WorkItem::AllocatedPhi {
@@ -240,7 +249,7 @@ pub fn sroa(editor: &mut FunctionEditor, reverse_postorder: &Vec<NodeID>, types:
                     let control = *control;
                     let init = *init;
                     let reduct = *reduct;
-                    let fields = allocate_fields(editor, types[node.idx()], &mut next_id);
+                    let fields = allocate_fields(editor, types[&node], &mut next_id);
                     field_map.insert(node, fields.clone());
 
                     item = WorkItem::AllocatedReduce {
@@ -260,7 +269,7 @@ pub fn sroa(editor: &mut FunctionEditor, reverse_postorder: &Vec<NodeID>, types:
                     let first = *first;
                     let second = *second;
                     let third = *third;
-                    let fields = allocate_fields(editor, types[node.idx()], &mut next_id);
+                    let fields = allocate_fields(editor, types[&node], &mut next_id);
                     field_map.insert(node, fields.clone());
 
                     item = WorkItem::AllocatedTernary {
@@ -278,7 +287,7 @@ pub fn sroa(editor: &mut FunctionEditor, reverse_postorder: &Vec<NodeID>, types:
                     indices,
                 } => {
                     if let Some(index_map) = field_map.get(collect) {
-                        if editor.get_type(types[data.idx()]).is_product() {
+                        if editor.get_type(types[&data]).is_product() {
                             if let Some(data_idx) = field_map.get(data) {
                                 field_map.insert(
                                     node,
@@ -768,7 +777,7 @@ fn generate_constant(editor: &mut FunctionEditor, typ: TypeID) -> ConstantID {
             let const_id = generate_constant(editor, ts[0]);
             add_const!(editor, Constant::Summation(typ, 0, const_id))
         }
-        Type::Array(elem, _) => {
+        Type::Array(_, _) => {
             add_const!(editor, Constant::Array(typ))
         }
         Type::Control => panic!("Cannot create constant of control type"),
diff --git a/juno_frontend/src/lib.rs b/juno_frontend/src/lib.rs
index b5ce14565393217189887fe4805939ef3c4e48fb..b2af338157ac01181b4815f2add9019b27e27cab 100644
--- a/juno_frontend/src/lib.rs
+++ b/juno_frontend/src/lib.rs
@@ -147,7 +147,9 @@ pub fn compile_ir(
     if verify.verify() || verify.verify_all() {
         pm.add_pass(hercules_opt::pass::Pass::Verify);
     }
+    add_verified_pass!(pm, verify, GVN);
     add_verified_pass!(pm, verify, PhiElim);
+    add_pass!(pm, verify, DCE);
     if x_dot {
         pm.add_pass(hercules_opt::pass::Pass::Xdot(true));
     }
@@ -159,6 +161,7 @@ pub fn compile_ir(
     // We run phi-elim again because SROA can introduce new phis that might be able to be
     // simplified
     add_verified_pass!(pm, verify, PhiElim);
+    add_pass!(pm, verify, DCE);
     if x_dot {
         pm.add_pass(hercules_opt::pass::Pass::Xdot(true));
     }