diff --git a/hercules_ir/src/ir.rs b/hercules_ir/src/ir.rs index ed340a7604cc2a4bc8c78f1e3743a8343fbb04ea..c4ab9b3ee56a7fc5fbdd4bd1a979f1b921360eb8 100644 --- a/hercules_ir/src/ir.rs +++ b/hercules_ir/src/ir.rs @@ -917,11 +917,11 @@ impl Index { } } - pub fn lower_case_name(&self) -> &'static str { + pub fn lower_case_name(&self) -> String { match self { - Index::Field(_) => "field", - Index::Variant(_) => "variant", - Index::Position(_) => "position", + Index::Field(idx) => format!("field {}", idx), + Index::Variant(idx) => format!("variant {}", idx), + Index::Position(idxs) => format!("position {:?}", &*idxs), } } } diff --git a/hercules_opt/src/editor.rs b/hercules_opt/src/editor.rs index a75ea38aa3b7703e7efecc952b54d9ccb8df45c6..1981b1297be06a4bf91a59fd870697aeafff4a91 100644 --- a/hercules_opt/src/editor.rs +++ b/hercules_opt/src/editor.rs @@ -244,12 +244,12 @@ impl<'a: 'b, 'b> FunctionEditor<'a> { self.edits } - pub fn node_ids(&self) -> impl Iterator<Item = NodeID> { + pub fn node_ids(&self) -> impl ExactSizeIterator<Item = NodeID> { let num = self.function.nodes.len(); (0..num).map(NodeID::new) } - pub fn dynamic_constant_ids(&self) -> impl Iterator<Item = DynamicConstantID> { + pub fn dynamic_constant_ids(&self) -> impl ExactSizeIterator<Item = DynamicConstantID> { let num = self.dynamic_constants.borrow().len(); (0..num).map(DynamicConstantID::new) } @@ -272,6 +272,10 @@ impl<'a, 'b> FunctionEdit<'a, 'b> { id.idx() >= self.editor.mutable_nodes.len() || self.editor.mutable_nodes[id.idx()] } + pub fn num_dynamic_constants(&self) -> usize { + self.editor.dynamic_constants.borrow().len() + self.added_dynamic_constants.len() + } + pub fn add_node(&mut self, node: Node) -> NodeID { let id = NodeID::new(self.editor.function.nodes.len() + self.added_nodeids.len()); // Added nodes need to have an entry in the def-use map. @@ -312,7 +316,7 @@ impl<'a, 'b> FunctionEdit<'a, 'b> { } } - pub fn replace_all_uses(mut self, old: NodeID, new: NodeID) -> Result<Self, Self> { + pub fn replace_all_uses(self, old: NodeID, new: NodeID) -> Result<Self, Self> { self.replace_all_uses_where(old, new, |_| true) } diff --git a/hercules_opt/src/inline.rs b/hercules_opt/src/inline.rs index 720717b0cdc099e1a5d35516f948f0efcbd2da61..6f6df573bbc6d2cecaad9319eff8ca917244ec41 100644 --- a/hercules_opt/src/inline.rs +++ b/hercules_opt/src/inline.rs @@ -200,8 +200,38 @@ fn inline_func( || node.is_dynamic_constant() || node.is_call() { - for (dc_a, dc_b) in zip(dcs_a, dcs_b.iter()) { - substitute_dynamic_constants_in_node(*dc_a, *dc_b, &mut node, &mut edit); + // We have to perform the subsitution in two steps. First, + // we map every dynamic constant A to a non-sense dynamic + // constant ID. Second, we map each non-sense dynamic + // constant ID to the appropriate dynamic constant B. Why + // not just do this in one step from A to B? We update + // dynamic constants one at a time, so imagine the following + // A -> B mappings: + // ID 0 -> ID 1 + // ID 1 -> ID 0 + // First, we apply the first mapping. This changes all + // references to dynamic constant 0 to dynamic constant 1. + // Then, we apply the second mapping. This updates all + // already present references to dynamic constant 1, as well + // 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 num_dcs = edit.num_dynamic_constants(); + for (dc_a, dc_n) in zip(dcs_a, num_dcs..) { + substitute_dynamic_constants_in_node( + *dc_a, + DynamicConstantID::new(dc_n), + &mut node, + &mut edit, + ); + } + for (dc_n, dc_b) in zip(num_dcs.., dcs_b.iter()) { + substitute_dynamic_constants_in_node( + DynamicConstantID::new(dc_n), + *dc_b, + &mut node, + &mut edit, + ); } } let mut uses = get_uses_mut(&mut node); @@ -267,6 +297,13 @@ fn substitute_dynamic_constants( return dc_b; } + // Since we substitute non-sense dynamic constant IDs earlier, we explicitly + // check that the provided ID to replace inside of is valid. Otherwise, + // ignore. + if dc_c.idx() >= edit.num_dynamic_constants() { + return dc_c; + } + // If C is not just A, look inside of it to possibly substitute a child DC. let dc_clone = edit.get_dynamic_constant(dc_c).clone(); match dc_clone { @@ -339,7 +376,7 @@ fn substitute_dynamic_constants_in_type( .map(|field_id| substitute_dynamic_constants_in_type(dc_a, dc_b, *field_id, edit)) .collect(); if new_fields != *fields { - edit.add_type(Type::Summation(new_fields)) + edit.add_type(Type::Product(new_fields)) } else { ty } diff --git a/hercules_opt/src/pass.rs b/hercules_opt/src/pass.rs index f5e0a9ad5ac9a081efe3016cd0dcb6430c688bc6..33d7bfb3f7d476b262cac094c6b5bfbbebda925e 100644 --- a/hercules_opt/src/pass.rs +++ b/hercules_opt/src/pass.rs @@ -788,6 +788,7 @@ impl PassManager { .expect("PANIC: Unable to write output module file contents."); } } + println!("Ran pass: {:?}", pass); } }