Skip to content

Commit

Permalink
fix: Fix poor handling of aliased references in flattening pass causi…
Browse files Browse the repository at this point in the history
…ng some values to be zeroed (noir-lang#6434)

Co-authored-by: Tom French <[email protected]>
Co-authored-by: Tom French <[email protected]>
  • Loading branch information
3 people authored Nov 15, 2024
1 parent 852c87a commit 8932dac
Show file tree
Hide file tree
Showing 5 changed files with 133 additions and 220 deletions.
22 changes: 17 additions & 5 deletions compiler/noirc_evaluator/src/ssa/ir/instruction.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,11 +14,12 @@ use fxhash::FxHasher;
use iter_extended::vecmap;
use noirc_frontend::hir_def::types::Type as HirType;

use crate::ssa::opt::flatten_cfg::value_merger::ValueMerger;
use crate::ssa::{ir::function::RuntimeType, opt::flatten_cfg::value_merger::ValueMerger};

use super::{
basic_block::BasicBlockId,
dfg::{CallStack, DataFlowGraph},
function::Function,
map::Id,
types::{NumericType, Type},
value::{Value, ValueId},
Expand Down Expand Up @@ -363,12 +364,12 @@ impl Instruction {
}
}

pub(crate) fn can_eliminate_if_unused(&self, dfg: &DataFlowGraph) -> bool {
pub(crate) fn can_eliminate_if_unused(&self, function: &Function) -> bool {
use Instruction::*;
match self {
Binary(binary) => {
if matches!(binary.operator, BinaryOp::Div | BinaryOp::Mod) {
if let Some(rhs) = dfg.get_numeric_constant(binary.rhs) {
if let Some(rhs) = function.dfg.get_numeric_constant(binary.rhs) {
rhs != FieldElement::zero()
} else {
false
Expand All @@ -386,15 +387,26 @@ impl Instruction {
| IfElse { .. }
| ArraySet { .. } => true,

// Store instructions must be removed by DIE in acir code, any load
// instructions should already be unused by that point.
//
// Note that this check assumes that it is being performed after the flattening
// pass and after the last mem2reg pass. This is currently the case for the DIE
// pass where this check is done, but does mean that we cannot perform mem2reg
// after the DIE pass.
Store { .. } => {
matches!(function.runtime(), RuntimeType::Acir(_))
&& function.reachable_blocks().len() == 1
}

Constrain(..)
| Store { .. }
| EnableSideEffectsIf { .. }
| IncrementRc { .. }
| DecrementRc { .. }
| RangeCheck { .. } => false,

// Some `Intrinsic`s have side effects so we must check what kind of `Call` this is.
Call { func, .. } => match dfg[*func] {
Call { func, .. } => match function.dfg[*func] {
// Explicitly allows removal of unused ec operations, even if they can fail
Value::Intrinsic(Intrinsic::BlackBox(BlackBoxFunc::MultiScalarMul))
| Value::Intrinsic(Intrinsic::BlackBox(BlackBoxFunc::EmbeddedCurveAdd)) => true,
Expand Down
2 changes: 1 addition & 1 deletion compiler/noirc_evaluator/src/ssa/opt/die.rs
Original file line number Diff line number Diff line change
Expand Up @@ -172,7 +172,7 @@ impl Context {
fn is_unused(&self, instruction_id: InstructionId, function: &Function) -> bool {
let instruction = &function.dfg[instruction_id];

if instruction.can_eliminate_if_unused(&function.dfg) {
if instruction.can_eliminate_if_unused(function) {
let results = function.dfg.instruction_results(instruction_id);
results.iter().all(|result| !self.used_values.contains(result))
} else if let Instruction::Call { func, arguments } = instruction {
Expand Down
Loading

0 comments on commit 8932dac

Please sign in to comment.