diff --git a/hercules_opt/src/ccp.rs b/hercules_opt/src/ccp.rs index cf3a0919585b4254ff4d3f6996755c063bca68d6..b8eb57ca513197bcd638f48106bed4d14a364539 100644 --- a/hercules_opt/src/ccp.rs +++ b/hercules_opt/src/ccp.rs @@ -383,8 +383,14 @@ fn ccp_flow_function( }), // If node has only one output, if doesn't directly handle crossover of // reachability and constant propagation. Read handles that. - Node::If { control, cond: _ } => inputs[control.idx()].clone(), - Node::Match { control, sum: _ } => inputs[control.idx()].clone(), + Node::If { control, cond } => { + assert!(!inputs[control.idx()].is_reachable() || inputs[cond.idx()].is_reachable()); + inputs[control.idx()].clone() + } + Node::Match { control, sum } => { + assert!(!inputs[control.idx()].is_reachable() || inputs[sum.idx()].is_reachable()); + inputs[control.idx()].clone() + } Node::Fork { control, factors: _, @@ -426,9 +432,21 @@ fn ccp_flow_function( // TODO: At least for now, reduce nodes always produce unknown values. Node::Reduce { control, - init: _, - reduct: _, - } => inputs[control.idx()].clone(), + init, + reduct, + } => { + let reachability = inputs[control.idx()].reachability.clone(); + if reachability == ReachabilityLattice::Reachable { + assert!(inputs[init.idx()].is_reachable()); + let mut constant = inputs[init.idx()].constant.clone(); + if inputs[reduct.idx()].is_reachable() { + constant = ConstantLattice::meet(&constant, &inputs[reduct.idx()].constant); + } + CCPLattice { reachability, constant } + } else { + CCPLattice { reachability, constant: ConstantLattice::top() } + } + }, Node::Return { control, data } => inputs[control.idx()].clone(), Node::Parameter { index: _ } => CCPLattice::bottom(), // A constant node is the "source" of concrete constant lattice values.