From 6bc8ec41824f50f7fb57dc1112736415042fe7c3 Mon Sep 17 00:00:00 2001 From: Russel Arbore <russel.jma@gmail.com> Date: Sun, 24 Nov 2024 23:10:52 -0800 Subject: [PATCH] Fix inlining DC substitution --- hercules_ir/src/ir.rs | 8 +++---- hercules_opt/src/editor.rs | 10 ++++++--- hercules_opt/src/inline.rs | 43 +++++++++++++++++++++++++++++++++++--- hercules_opt/src/pass.rs | 1 + 4 files changed, 52 insertions(+), 10 deletions(-) diff --git a/hercules_ir/src/ir.rs b/hercules_ir/src/ir.rs index ed340a76..c4ab9b3e 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 a75ea38a..1981b129 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 720717b0..6f6df573 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 f5e0a9ad..33d7bfb3 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); } } -- GitLab