diff --git a/Cargo.lock b/Cargo.lock index d1d6b36af03..d6300bc75cb 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2319,6 +2319,7 @@ name = "noirc_evaluator" version = "0.10.5" dependencies = [ "acvm", + "fxhash", "im", "iter-extended", "noirc_abi", diff --git a/crates/noirc_evaluator/Cargo.toml b/crates/noirc_evaluator/Cargo.toml index b838f936ee6..7e4265b2488 100644 --- a/crates/noirc_evaluator/Cargo.toml +++ b/crates/noirc_evaluator/Cargo.toml @@ -11,6 +11,7 @@ noirc_frontend.workspace = true noirc_errors.workspace = true noirc_abi.workspace = true acvm.workspace = true +fxhash = "0.2.1" iter-extended.workspace = true thiserror.workspace = true num-bigint = "0.4" diff --git a/crates/noirc_evaluator/src/brillig/brillig_gen.rs b/crates/noirc_evaluator/src/brillig/brillig_gen.rs index a1e82bbf443..53e86a00e75 100644 --- a/crates/noirc_evaluator/src/brillig/brillig_gen.rs +++ b/crates/noirc_evaluator/src/brillig/brillig_gen.rs @@ -4,13 +4,10 @@ pub(crate) mod brillig_directive; pub(crate) mod brillig_fn; pub(crate) mod brillig_slice_ops; -use crate::ssa::ir::{function::Function, post_order::PostOrder}; - -use std::collections::HashMap; - use self::{brillig_block::BrilligBlock, brillig_fn::FunctionContext}; - use super::brillig_ir::{artifact::BrilligArtifact, BrilligContext}; +use crate::ssa::ir::{function::Function, post_order::PostOrder}; +use fxhash::FxHashMap as HashMap; /// Converting an SSA function into Brillig bytecode. pub(crate) fn convert_ssa_function(func: &Function, enable_debug_trace: bool) -> BrilligArtifact { @@ -18,8 +15,10 @@ pub(crate) fn convert_ssa_function(func: &Function, enable_debug_trace: bool) -> reverse_post_order.extend_from_slice(PostOrder::with_function(func).as_slice()); reverse_post_order.reverse(); - let mut function_context = - FunctionContext { function_id: func.id(), ssa_value_to_brillig_variable: HashMap::new() }; + let mut function_context = FunctionContext { + function_id: func.id(), + ssa_value_to_brillig_variable: HashMap::default(), + }; let mut brillig_context = BrilligContext::new(enable_debug_trace); diff --git a/crates/noirc_evaluator/src/brillig/brillig_gen/brillig_fn.rs b/crates/noirc_evaluator/src/brillig/brillig_gen/brillig_fn.rs index bfce26f4fac..1ea16fd375e 100644 --- a/crates/noirc_evaluator/src/brillig/brillig_gen/brillig_fn.rs +++ b/crates/noirc_evaluator/src/brillig/brillig_gen/brillig_fn.rs @@ -1,5 +1,3 @@ -use std::collections::HashMap; - use acvm::brillig_vm::brillig::{HeapArray, HeapVector, RegisterIndex, RegisterOrMemory}; use iter_extended::vecmap; @@ -15,6 +13,7 @@ use crate::{ value::ValueId, }, }; +use fxhash::FxHashMap as HashMap; pub(crate) struct FunctionContext { pub(crate) function_id: FunctionId, diff --git a/crates/noirc_evaluator/src/brillig/brillig_gen/brillig_slice_ops.rs b/crates/noirc_evaluator/src/brillig/brillig_gen/brillig_slice_ops.rs index facc4766722..e46cc55c3ea 100644 --- a/crates/noirc_evaluator/src/brillig/brillig_gen/brillig_slice_ops.rs +++ b/crates/noirc_evaluator/src/brillig/brillig_gen/brillig_slice_ops.rs @@ -311,7 +311,6 @@ impl<'block> BrilligBlock<'block> { #[cfg(test)] mod tests { - use std::collections::HashMap; use std::vec; use acvm::acir::brillig::{HeapVector, Value}; @@ -323,11 +322,12 @@ mod tests { use crate::brillig::brillig_ir::tests::{create_and_run_vm, create_context}; use crate::brillig::brillig_ir::BrilligContext; use crate::ssa::ir::map::Id; + use fxhash::FxHashMap as HashMap; fn create_test_environment() -> (FunctionContext, BrilligContext) { let function_context = FunctionContext { function_id: Id::test_new(0), - ssa_value_to_brillig_variable: HashMap::new(), + ssa_value_to_brillig_variable: HashMap::default(), }; let brillig_context = create_context(); (function_context, brillig_context) diff --git a/crates/noirc_evaluator/src/ssa/acir_gen/acir_ir/acir_variable.rs b/crates/noirc_evaluator/src/ssa/acir_gen/acir_ir/acir_variable.rs index f9f112ba622..9ac8291cadb 100644 --- a/crates/noirc_evaluator/src/ssa/acir_gen/acir_ir/acir_variable.rs +++ b/crates/noirc_evaluator/src/ssa/acir_gen/acir_ir/acir_variable.rs @@ -20,8 +20,8 @@ use acvm::{ FieldElement, }; use acvm::{BlackBoxFunctionSolver, BlackBoxResolutionError}; +use fxhash::FxHashMap as HashMap; use iter_extended::{try_vecmap, vecmap}; -use std::collections::HashMap; use std::{borrow::Cow, hash::Hash}; #[derive(Clone, Debug, PartialEq, Eq, Hash)] diff --git a/crates/noirc_evaluator/src/ssa/acir_gen/mod.rs b/crates/noirc_evaluator/src/ssa/acir_gen/mod.rs index 157cccf06f5..42a50f66bc4 100644 --- a/crates/noirc_evaluator/src/ssa/acir_gen/mod.rs +++ b/crates/noirc_evaluator/src/ssa/acir_gen/mod.rs @@ -1,7 +1,7 @@ //! This file holds the pass to convert from Noir's SSA IR to ACIR. mod acir_ir; -use std::collections::{HashMap, HashSet}; +use std::collections::HashSet; use std::fmt::Debug; use std::ops::RangeInclusive; @@ -29,6 +29,7 @@ use acvm::{ acir::{circuit::opcodes::BlockId, native_types::Expression}, FieldElement, }; +use fxhash::FxHashMap as HashMap; use iter_extended::{try_vecmap, vecmap}; use noirc_frontend::Distinctness; @@ -147,11 +148,11 @@ impl Context { let current_side_effects_enabled_var = acir_context.add_constant(FieldElement::one()); Context { - ssa_values: HashMap::new(), + ssa_values: HashMap::default(), current_side_effects_enabled_var, acir_context, initialized_arrays: HashSet::new(), - memory_blocks: HashMap::new(), + memory_blocks: HashMap::default(), max_block_id: 0, } } @@ -1227,7 +1228,7 @@ mod tests { let ssa = builder.finish(); let context = Context::new(); - let mut acir = context.convert_ssa(ssa, Brillig::default(), &HashMap::new()).unwrap(); + let mut acir = context.convert_ssa(ssa, Brillig::default(), &HashMap::default()).unwrap(); let expected_opcodes = vec![Opcode::Arithmetic(&Expression::one() - &Expression::from(Witness(1)))]; diff --git a/crates/noirc_evaluator/src/ssa/ir/cfg.rs b/crates/noirc_evaluator/src/ssa/ir/cfg.rs index eccb9ce587c..dbc4c29183e 100644 --- a/crates/noirc_evaluator/src/ssa/ir/cfg.rs +++ b/crates/noirc_evaluator/src/ssa/ir/cfg.rs @@ -1,9 +1,10 @@ -use std::collections::{BTreeSet, HashMap}; +use std::collections::BTreeSet; use super::{ basic_block::{BasicBlock, BasicBlockId}, function::Function, }; +use fxhash::FxHashMap as HashMap; /// A container for the successors and predecessors of some Block. #[derive(Clone, Default)] @@ -33,7 +34,8 @@ impl ControlFlowGraph { // it later comes to describe any edges after calling compute. let entry_block = func.entry_block(); let empty_node = CfgNode { predecessors: BTreeSet::new(), successors: BTreeSet::new() }; - let data = HashMap::from([(entry_block, empty_node)]); + let mut data = HashMap::default(); + data.insert(entry_block, empty_node); let mut cfg = ControlFlowGraph { data }; cfg.compute(func); diff --git a/crates/noirc_evaluator/src/ssa/ir/dfg.rs b/crates/noirc_evaluator/src/ssa/ir/dfg.rs index ea00ad3bbc1..73914c54674 100644 --- a/crates/noirc_evaluator/src/ssa/ir/dfg.rs +++ b/crates/noirc_evaluator/src/ssa/ir/dfg.rs @@ -1,4 +1,4 @@ -use std::{borrow::Cow, collections::HashMap}; +use std::borrow::Cow; use crate::ssa::ir::instruction::SimplifyResult; @@ -14,6 +14,7 @@ use super::{ }; use acvm::FieldElement; +use fxhash::FxHashMap as HashMap; use iter_extended::vecmap; use noirc_errors::Location; diff --git a/crates/noirc_evaluator/src/ssa/ir/dom.rs b/crates/noirc_evaluator/src/ssa/ir/dom.rs index df9a6c9a3a5..da55a593f9e 100644 --- a/crates/noirc_evaluator/src/ssa/ir/dom.rs +++ b/crates/noirc_evaluator/src/ssa/ir/dom.rs @@ -4,11 +4,12 @@ //! Dominator trees are useful for tasks such as identifying back-edges in loop analysis or //! calculating dominance frontiers. -use std::{cmp::Ordering, collections::HashMap}; +use std::cmp::Ordering; use super::{ basic_block::BasicBlockId, cfg::ControlFlowGraph, function::Function, post_order::PostOrder, }; +use fxhash::FxHashMap as HashMap; /// Dominator tree node. We keep one of these per reachable block. #[derive(Clone, Default)] @@ -121,7 +122,7 @@ impl DominatorTree { /// Allocate and compute a dominator tree from a pre-computed control flow graph and /// post-order counterpart. pub(crate) fn with_cfg_and_post_order(cfg: &ControlFlowGraph, post_order: &PostOrder) -> Self { - let mut dom_tree = DominatorTree { nodes: HashMap::new(), cache: HashMap::new() }; + let mut dom_tree = DominatorTree { nodes: HashMap::default(), cache: HashMap::default() }; dom_tree.compute_dominator_tree(cfg, post_order); dom_tree } diff --git a/crates/noirc_evaluator/src/ssa/ir/function_inserter.rs b/crates/noirc_evaluator/src/ssa/ir/function_inserter.rs index d9aee785016..68ece87c7c7 100644 --- a/crates/noirc_evaluator/src/ssa/ir/function_inserter.rs +++ b/crates/noirc_evaluator/src/ssa/ir/function_inserter.rs @@ -1,5 +1,3 @@ -use std::collections::HashMap; - use iter_extended::vecmap; use super::{ @@ -9,6 +7,7 @@ use super::{ instruction::{Instruction, InstructionId}, value::ValueId, }; +use fxhash::FxHashMap as HashMap; /// The FunctionInserter can be used to help modify existing Functions /// and map old values to new values after re-inserting optimized versions @@ -21,7 +20,7 @@ pub(crate) struct FunctionInserter<'f> { impl<'f> FunctionInserter<'f> { pub(crate) fn new(function: &'f mut Function) -> FunctionInserter<'f> { - Self { function, values: HashMap::new() } + Self { function, values: HashMap::default() } } /// Resolves a ValueId to its new, updated value. diff --git a/crates/noirc_evaluator/src/ssa/ir/map.rs b/crates/noirc_evaluator/src/ssa/ir/map.rs index bb0da6a8558..66f8ea91a3e 100644 --- a/crates/noirc_evaluator/src/ssa/ir/map.rs +++ b/crates/noirc_evaluator/src/ssa/ir/map.rs @@ -1,5 +1,5 @@ +use fxhash::FxHashMap as HashMap; use std::{ - collections::HashMap, hash::Hash, sync::atomic::{AtomicUsize, Ordering}, }; @@ -218,7 +218,7 @@ impl SparseMap { impl Default for SparseMap { fn default() -> Self { - Self { storage: HashMap::new() } + Self { storage: HashMap::default() } } } @@ -272,7 +272,7 @@ impl TwoWayMap { impl Default for TwoWayMap { fn default() -> Self { - Self { key_to_value: HashMap::new(), value_to_key: HashMap::new() } + Self { key_to_value: HashMap::default(), value_to_key: HashMap::default() } } } diff --git a/crates/noirc_evaluator/src/ssa/opt/array_use.rs b/crates/noirc_evaluator/src/ssa/opt/array_use.rs index 5b45d768e1f..cfa97cee551 100644 --- a/crates/noirc_evaluator/src/ssa/opt/array_use.rs +++ b/crates/noirc_evaluator/src/ssa/opt/array_use.rs @@ -1,5 +1,3 @@ -use std::collections::HashMap; - use crate::ssa::{ ir::{ basic_block::BasicBlockId, @@ -10,13 +8,14 @@ use crate::ssa::{ }, ssa_gen::Ssa, }; +use fxhash::FxHashMap as HashMap; impl Ssa { /// Map arrays with the last instruction that uses it /// For this we simply process all the instructions in execution order /// and update the map whenever there is a match pub(crate) fn find_last_array_uses(&self) -> HashMap { - let mut array_use = HashMap::new(); + let mut array_use = HashMap::default(); for func in self.functions.values() { let mut reverse_post_order = PostOrder::with_function(func).into_vec(); reverse_post_order.reverse(); diff --git a/crates/noirc_evaluator/src/ssa/opt/constant_folding.rs b/crates/noirc_evaluator/src/ssa/opt/constant_folding.rs index 295353989b2..06bb1716dde 100644 --- a/crates/noirc_evaluator/src/ssa/opt/constant_folding.rs +++ b/crates/noirc_evaluator/src/ssa/opt/constant_folding.rs @@ -1,4 +1,4 @@ -use std::collections::{HashMap, HashSet}; +use std::collections::HashSet; use iter_extended::vecmap; @@ -12,6 +12,7 @@ use crate::ssa::{ }, ssa_gen::Ssa, }; +use fxhash::FxHashMap as HashMap; impl Ssa { /// Performs constant folding on each instruction. @@ -56,7 +57,7 @@ impl Context { let instructions = function.dfg[block].take_instructions(); // Cache of instructions without any side-effects along with their outputs. - let mut cached_instruction_results: HashMap> = HashMap::new(); + let mut cached_instruction_results: HashMap> = HashMap::default(); for instruction_id in instructions { self.push_instruction(function, block, instruction_id, &mut cached_instruction_results); diff --git a/crates/noirc_evaluator/src/ssa/opt/defunctionalize.rs b/crates/noirc_evaluator/src/ssa/opt/defunctionalize.rs index cf2c4585e88..783458a358d 100644 --- a/crates/noirc_evaluator/src/ssa/opt/defunctionalize.rs +++ b/crates/noirc_evaluator/src/ssa/opt/defunctionalize.rs @@ -4,7 +4,7 @@ //! with a non-literal target can be replaced with a call to an apply function. //! The apply function is a dispatch function that takes the function id as a parameter //! and dispatches to the correct target. -use std::collections::{BTreeMap, BTreeSet, HashMap, HashSet}; +use std::collections::{BTreeMap, BTreeSet, HashSet}; use acvm::FieldElement; use iter_extended::vecmap; @@ -20,6 +20,7 @@ use crate::ssa::{ }, ssa_gen::Ssa, }; +use fxhash::FxHashMap as HashMap; /// Represents an 'apply' function created by this pass to dispatch higher order functions to. /// Pseudocode of an `apply` function is given below: @@ -245,7 +246,7 @@ fn create_apply_functions( ssa: &mut Ssa, variants_map: BTreeMap>, ) -> HashMap { - let mut apply_functions = HashMap::new(); + let mut apply_functions = HashMap::default(); for (signature, variants) in variants_map.into_iter() { assert!( !variants.is_empty(), diff --git a/crates/noirc_evaluator/src/ssa/opt/flatten_cfg.rs b/crates/noirc_evaluator/src/ssa/opt/flatten_cfg.rs index e0d1d508674..5a311500704 100644 --- a/crates/noirc_evaluator/src/ssa/opt/flatten_cfg.rs +++ b/crates/noirc_evaluator/src/ssa/opt/flatten_cfg.rs @@ -131,7 +131,8 @@ //! v11 = mul v4, Field 12 //! v12 = add v10, v11 //! store v12 at v5 (new store) -use std::collections::{BTreeMap, HashMap, HashSet}; +use fxhash::FxHashMap as HashMap; +use std::collections::{BTreeMap, HashSet}; use acvm::FieldElement; use iter_extended::vecmap; @@ -218,7 +219,7 @@ fn flatten_function_cfg(function: &mut Function) { let mut context = Context { inserter: FunctionInserter::new(function), cfg, - store_values: HashMap::new(), + store_values: HashMap::default(), local_allocations: HashSet::new(), branch_ends, conditions: Vec::new(), @@ -587,7 +588,7 @@ impl<'f> Context<'f> { // args that will be merged by inline_branch_end. Since jmpifs don't have // block arguments, it is safe to use the jmpif block here. last_block: jmpif_block, - store_values: HashMap::new(), + store_values: HashMap::default(), local_allocations: HashSet::new(), } } else { diff --git a/crates/noirc_evaluator/src/ssa/opt/flatten_cfg/branch_analysis.rs b/crates/noirc_evaluator/src/ssa/opt/flatten_cfg/branch_analysis.rs index 02583a40dcd..59bee00936a 100644 --- a/crates/noirc_evaluator/src/ssa/opt/flatten_cfg/branch_analysis.rs +++ b/crates/noirc_evaluator/src/ssa/opt/flatten_cfg/branch_analysis.rs @@ -19,9 +19,9 @@ //! //! This algorithm will remember each join point found in `find_join_point_of_branches` and //! the resulting map from each split block to each join block is returned. -use std::collections::HashMap; use crate::ssa::ir::{basic_block::BasicBlockId, cfg::ControlFlowGraph, function::Function}; +use fxhash::FxHashMap as HashMap; /// Returns a `HashMap` mapping blocks that start a branch (i.e. blocks terminated with jmpif) to /// their corresponding blocks that end the branch. @@ -61,7 +61,7 @@ struct Context<'cfg> { impl<'cfg> Context<'cfg> { fn new(cfg: &'cfg ControlFlowGraph) -> Self { - Self { cfg, branch_ends: HashMap::new() } + Self { cfg, branch_ends: HashMap::default() } } fn find_join_point_of_branches( diff --git a/crates/noirc_evaluator/src/ssa/opt/inlining.rs b/crates/noirc_evaluator/src/ssa/opt/inlining.rs index 1d09fea59f8..07b524ebc96 100644 --- a/crates/noirc_evaluator/src/ssa/opt/inlining.rs +++ b/crates/noirc_evaluator/src/ssa/opt/inlining.rs @@ -2,7 +2,7 @@ //! The purpose of this pass is to inline the instructions of each function call //! within the function caller. If all function calls are known, there will only //! be a single function remaining when the pass finishes. -use std::collections::{BTreeSet, HashMap, HashSet}; +use std::collections::{BTreeSet, HashSet}; use iter_extended::{btree_map, vecmap}; @@ -17,6 +17,7 @@ use crate::ssa::{ }, ssa_gen::Ssa, }; +use fxhash::FxHashMap as HashMap; /// An arbitrary limit to the maximum number of recursive call /// frames at any point in time. @@ -189,9 +190,9 @@ impl<'function> PerFunctionContext<'function> { Self { context, source_function, - blocks: HashMap::new(), - instructions: HashMap::new(), - values: HashMap::new(), + blocks: HashMap::default(), + instructions: HashMap::default(), + values: HashMap::default(), inlining_entry: false, } } diff --git a/crates/noirc_evaluator/src/ssa/opt/unrolling.rs b/crates/noirc_evaluator/src/ssa/opt/unrolling.rs index 2788c8ecf31..2dcd983f2e6 100644 --- a/crates/noirc_evaluator/src/ssa/opt/unrolling.rs +++ b/crates/noirc_evaluator/src/ssa/opt/unrolling.rs @@ -12,7 +12,7 @@ //! //! Note that this pass also often creates superfluous jmp instructions in the //! program that will need to be removed by a later simplify cfg pass. -use std::collections::{HashMap, HashSet}; +use std::collections::HashSet; use crate::{ errors::RuntimeError, @@ -31,6 +31,7 @@ use crate::{ ssa_gen::Ssa, }, }; +use fxhash::FxHashMap as HashMap; impl Ssa { /// Unroll all loops in each SSA function. @@ -307,9 +308,9 @@ impl<'f> LoopIteration<'f> { loop_, insert_block, source_block, - blocks: HashMap::new(), - original_blocks: HashMap::new(), - visited_blocks: HashSet::new(), + blocks: HashMap::default(), + original_blocks: HashMap::default(), + visited_blocks: HashSet::default(), induction_value: None, } } diff --git a/crates/noirc_evaluator/src/ssa/ssa_gen/context.rs b/crates/noirc_evaluator/src/ssa/ssa_gen/context.rs index e5a982912ee..5631aa8d351 100644 --- a/crates/noirc_evaluator/src/ssa/ssa_gen/context.rs +++ b/crates/noirc_evaluator/src/ssa/ssa_gen/context.rs @@ -1,4 +1,3 @@ -use std::collections::HashMap; use std::rc::Rc; use std::sync::{Mutex, RwLock}; @@ -19,6 +18,7 @@ use crate::ssa::ir::types::{NumericType, Type}; use crate::ssa::ir::value::ValueId; use super::value::{Tree, Value, Values}; +use fxhash::FxHashMap as HashMap; /// The FunctionContext is the main context object for translating a /// function into SSA form during the SSA-gen pass. @@ -94,7 +94,7 @@ impl<'a> FunctionContext<'a> { .1; let builder = FunctionBuilder::new(function_name, function_id, runtime); - let mut this = Self { definitions: HashMap::new(), builder, shared_context }; + let mut this = Self { definitions: HashMap::default(), builder, shared_context }; this.add_parameters_to_scope(parameters); this }