@@ -5817,7 +5817,8 @@ impl Function {
58175817 // (It's used more individually and differently than the paper)
58185818 // TODO: Update comments to consider block params rather than phi nodes and demarcate differences from the algorithm clearly
58195819 // TODO: Fix input arguments. We need block params, not just the phi
5820- /// If all possible phi values are the same, replace the phi with the value
5820+ // If all possible phi values are the same, replace the phi with the value
5821+ // TODO: Add Max's optimization about not checking the first block. Maybe do this by keeping track of all changing edges and using a worklist?
58215822
58225823 /// Sometimes block params can only come from one place and safely removed as block params.
58235824 /// Trivial block param removal increases the efficacy of CFG-based optimization passes.
@@ -5872,105 +5873,108 @@ impl Function {
58725873
58735874 while updated {
58745875
5875- for (row, block) in predecessor_domain.iter_mut().zip(&self.blocks) {
5876- row.resize(block.params.len(), ParamValue::None);
5877- }
5878- updated = false;
5876+ for (row, block) in predecessor_domain.iter_mut().zip(&self.blocks) {
5877+ row.resize(block.params.len(), ParamValue::None);
5878+ }
5879+ updated = false;
58795880
5880- // Scan through each jump, collecting edges from CondBranch and Jump insns.
5881- for (block_id, insn_index) in &terminators {
5882- let insn_id = self.blocks[block_id.0].insns[*insn_index];
5883- let mut edges: Vec<BranchEdge> = vec![];
5881+ // TODO: Maybe move this outside the loop somehow? probably can't immediately, but we could keep track of a worklist of edges that change maybe?
5882+ // And only use the changed ones like a worklist? And then instead of looping to fixpoint we use a worklist based approach?
5883+ //
5884+ // Scan through each jump, collecting edges from CondBranch and Jump insns.
5885+ for (block_id, insn_index) in &terminators {
5886+ let insn_id = self.blocks[block_id.0].insns[*insn_index];
5887+ let mut edges: Vec<BranchEdge> = vec![];
58845888
5885- match self.find(insn_id) {
5886- Insn::CondBranch { if_true, if_false, .. } => {
5887- edges.push(if_true);
5888- edges.push(if_false);
5889- }
5890- Insn::Jump(edge) => {
5891- edges.push(edge);
5889+ match self.find(insn_id) {
5890+ Insn::CondBranch { if_true, if_false, .. } => {
5891+ edges.push(if_true);
5892+ edges.push(if_false);
5893+ }
5894+ Insn::Jump(edge) => {
5895+ edges.push(edge);
5896+ }
5897+ _ => {}
58925898 }
5893- _ => {}
5894- }
58955899
5896- // Update the states
5897- for BranchEdge { target: block_id, args: params } in edges {
5898- for (i, param) in params.iter().enumerate().rev() {
5899- let param = self.find_id(*param);
5900- // If the param is the same as passed into the block, it is a self loop
5901- // We ignore self loops because they do not provide new information
5902- if param == self.find_id(self.blocks[block_id.0].params[i]) {
5903- continue
5904- }
5905- let state = &mut predecessor_domain[block_id.0][i];
5906- match *state {
5907- ParamValue::None => {
5908- *state = ParamValue::One(param);
5909- },
5910- ParamValue::One(value) => {
5911- if value != param {
5912- *state = ParamValue::Multiple;
5900+ // Use the results of abstract interpretation to update the states
5901+ // Perform abstract interpretation
5902+ for BranchEdge { target: block_id, args: params } in edges {
5903+ for (i, param) in params.iter().enumerate().rev() {
5904+ let param = self.find_id(*param);
5905+ // If the param is the same as passed into the block, it is a self loop and provides no new predecessor information.
5906+ if param == self.find_id(self.blocks[block_id.0].params[i]) {
5907+ continue
5908+ }
5909+ let state = &mut predecessor_domain[block_id.0][i];
5910+ match *state {
5911+ ParamValue::None => {
5912+ *state = ParamValue::One(param);
5913+ },
5914+ ParamValue::One(value) => {
5915+ if value != param {
5916+ *state = ParamValue::Multiple;
5917+ }
59135918 }
5919+ ParamValue::Multiple => {},
59145920 }
5915- ParamValue::Multiple => {},
59165921 }
59175922 }
59185923 }
5919- }
59205924
5921- // Remove the trivial block params and fix up our SSA representation
5922- // This is done by as follows.
5923- // 1. Replace uses of the trivial params with the concretized value
5924- // 2. Remove trivial params from the basic block definition
5925- // 3. Remove trivial params from each CondBranch and Jump that targets the basic block that was just updated
5926- for (block_id, block) in predecessor_domain.iter().enumerate() {
5927- // TODO: Don't do this
5928- let block_id = BlockId(block_id);
5925+ // Remove the trivial block params and fix up our SSA representation
5926+ // This is done by as follows.
5927+ // 1. Replace uses of the trivial params with the concretized value
5928+ // 2. Remove trivial params from the basic block definition
5929+ // 3. Remove trivial params from each CondBranch and Jump that targets the basic block that was just updated
5930+ for (block_id, block) in predecessor_domain.iter().enumerate() {
5931+ // TODO: Don't do this
5932+ let block_id = BlockId(block_id);
59295933
5930- let trivial_indices: Vec<usize> = block.iter().enumerate()
5931- .filter_map(|(idx, state)|
5932- matches!(state, ParamValue::One(_)).then_some(idx)
5933- ).collect();
5934+ let trivial_indices: Vec<usize> = block.iter().enumerate()
5935+ .filter_map(|(idx, state)|
5936+ matches!(state, ParamValue::One(_)).then_some(idx)
5937+ ).collect();
59345938
5935- // Replace uses of the trivial params with the concretized value
5936- for param_index in &trivial_indices {
5937- if let ParamValue::One(insn_id) = block[*param_index] {
5938- self.make_equal_to(self.blocks[block_id.0].params[*param_index], insn_id);
5939- updated = true;
5939+ // Replace uses of the trivial params with the concretized value
5940+ for param_index in &trivial_indices {
5941+ if let ParamValue::One(insn_id) = block[*param_index] {
5942+ self.make_equal_to(self.blocks[block_id.0].params[*param_index], insn_id);
5943+ updated = true;
5944+ }
59405945 }
5941- }
59425946
5943- // Update the block
5944- prune_vec_by_indices(&mut self.blocks[block_id.0].params, &trivial_indices);
5947+ // Update the block
5948+ prune_vec_by_indices(&mut self.blocks[block_id.0].params, &trivial_indices);
59455949
5946- // Update the terminators (basic blocks can only branch at the terminator. This is where block params are passed)
5947- for (jump_block_id, index) in &terminators {
5948- let cond_insn_id = self.blocks[jump_block_id.0].insns[*index];
5949- match self.find(cond_insn_id) {
5950- Insn::Jump(edge) => {
5951- if edge.target == block_id {
5952- let edge = prune_branch_edge(edge, &trivial_indices);
5953- self.insns[cond_insn_id.0] = Insn::Jump(edge);
5950+ // Update the terminators (basic blocks can only branch at the terminator. This is where block params are passed)
5951+ for (jump_block_id, index) in &terminators {
5952+ let cond_insn_id = self.blocks[jump_block_id.0].insns[*index];
5953+ match self.find(cond_insn_id) {
5954+ Insn::Jump(edge) => {
5955+ if edge.target == block_id {
5956+ let edge = prune_branch_edge(edge, &trivial_indices);
5957+ self.insns[cond_insn_id.0] = Insn::Jump(edge);
5958+ }
59545959 }
5960+ Insn::CondBranch { val, if_true, if_false } => {
5961+ let if_true = if if_true.target == block_id {
5962+ prune_branch_edge(if_true, &trivial_indices)
5963+ } else {
5964+ if_true
5965+ };
5966+ let if_false = if if_false.target == block_id {
5967+ prune_branch_edge(if_false, &trivial_indices)
5968+ } else {
5969+ if_false
5970+ };
5971+ self.insns[cond_insn_id.0] = Insn::CondBranch{ val, if_true, if_false };
5972+ }
5973+ _ => {}
59555974 }
5956- Insn::CondBranch { val, if_true, if_false } => {
5957- let if_true = if if_true.target == block_id {
5958- prune_branch_edge(if_true, &trivial_indices)
5959- } else {
5960- if_true
5961- };
5962- let if_false = if if_false.target == block_id {
5963- prune_branch_edge(if_false, &trivial_indices)
5964- } else {
5965- if_false
5966- };
5967- self.insns[cond_insn_id.0] = Insn::CondBranch{ val, if_true, if_false };
5968- }
5969- _ => {}
59705975 }
59715976 }
59725977 }
5973- }
59745978
59755979 }
59765980
0 commit comments