@@ -146,7 +146,7 @@ impl Function {
146
146
use_constraint_info : bool ,
147
147
brillig_info : Option < BrilligInfo > ,
148
148
) {
149
- let mut context = Context :: new ( self , use_constraint_info, brillig_info) ;
149
+ let mut context = Context :: new ( use_constraint_info, brillig_info) ;
150
150
context. block_queue . push_back ( self . entry_block ( ) ) ;
151
151
152
152
while let Some ( block) = context. block_queue . pop_front ( ) {
@@ -181,8 +181,6 @@ struct Context<'a> {
181
181
182
182
// Cache of instructions without any side-effects along with their outputs.
183
183
cached_instruction_results : InstructionResultCache ,
184
-
185
- dom : DominatorTree ,
186
184
}
187
185
188
186
#[ derive( Copy , Clone ) ]
@@ -225,6 +223,14 @@ impl SimplificationCache {
225
223
}
226
224
}
227
225
}
226
+
227
+ fn get ( & self , block : BasicBlockId , dom : & mut DominatorTree ) -> Option < ValueId > {
228
+ if self . blocks . iter ( ) . any ( |b| dom. dominates ( * b, block) ) {
229
+ Some ( self . simplified )
230
+ } else {
231
+ None
232
+ }
233
+ }
228
234
}
229
235
230
236
/// HashMap from Instruction to a simplified expression that it can be replaced with based on
@@ -251,19 +257,14 @@ struct ResultCache {
251
257
}
252
258
253
259
impl < ' brillig > Context < ' brillig > {
254
- fn new (
255
- function : & Function ,
256
- use_constraint_info : bool ,
257
- brillig_info : Option < BrilligInfo < ' brillig > > ,
258
- ) -> Self {
260
+ fn new ( use_constraint_info : bool , brillig_info : Option < BrilligInfo < ' brillig > > ) -> Self {
259
261
Self {
260
262
use_constraint_info,
261
263
brillig_info,
262
264
visited_blocks : Default :: default ( ) ,
263
265
block_queue : Default :: default ( ) ,
264
266
constraint_simplification_mappings : Default :: default ( ) ,
265
267
cached_instruction_results : Default :: default ( ) ,
266
- dom : DominatorTree :: with_function ( function) ,
267
268
}
268
269
}
269
270
@@ -273,9 +274,12 @@ impl<'brillig> Context<'brillig> {
273
274
let mut side_effects_enabled_var =
274
275
function. dfg . make_constant ( FieldElement :: one ( ) , Type :: bool ( ) ) ;
275
276
277
+ let mut dom = DominatorTree :: with_function ( & function) ;
278
+
276
279
for instruction_id in instructions {
277
280
self . fold_constants_into_instruction (
278
281
& mut function. dfg ,
282
+ & mut dom,
279
283
block,
280
284
instruction_id,
281
285
& mut side_effects_enabled_var,
@@ -287,17 +291,21 @@ impl<'brillig> Context<'brillig> {
287
291
fn fold_constants_into_instruction (
288
292
& mut self ,
289
293
dfg : & mut DataFlowGraph ,
294
+ dom : & mut DominatorTree ,
290
295
mut block : BasicBlockId ,
291
296
id : InstructionId ,
292
297
side_effects_enabled_var : & mut ValueId ,
293
298
) {
294
299
let constraint_simplification_mapping = self . get_constraint_map ( * side_effects_enabled_var) ;
295
- let instruction = Self :: resolve_instruction ( id, dfg, constraint_simplification_mapping) ;
300
+
301
+ let instruction =
302
+ Self :: resolve_instruction ( id, block, dfg, dom, constraint_simplification_mapping) ;
303
+
296
304
let old_results = dfg. instruction_results ( id) . to_vec ( ) ;
297
305
298
306
// If a copy of this instruction exists earlier in the block, then reuse the previous results.
299
307
if let Some ( cache_result) =
300
- self . get_cached ( dfg, & instruction, * side_effects_enabled_var, block)
308
+ self . get_cached ( dfg, dom , & instruction, * side_effects_enabled_var, block)
301
309
{
302
310
match cache_result {
303
311
CacheResult :: Cached ( cached) => {
@@ -354,7 +362,9 @@ impl<'brillig> Context<'brillig> {
354
362
/// Fetches an [`Instruction`] by its [`InstructionId`] and fully resolves its inputs.
355
363
fn resolve_instruction (
356
364
instruction_id : InstructionId ,
365
+ block : BasicBlockId ,
357
366
dfg : & DataFlowGraph ,
367
+ dom : & mut DominatorTree ,
358
368
constraint_simplification_mapping : & HashMap < ValueId , SimplificationCache > ,
359
369
) -> Instruction {
360
370
let instruction = dfg[ instruction_id] . clone ( ) ;
@@ -365,20 +375,29 @@ impl<'brillig> Context<'brillig> {
365
375
// This allows us to reach a stable final `ValueId` for each instruction input as we add more
366
376
// constraints to the cache.
367
377
fn resolve_cache (
378
+ block : BasicBlockId ,
368
379
dfg : & DataFlowGraph ,
380
+ dom : & mut DominatorTree ,
369
381
cache : & HashMap < ValueId , SimplificationCache > ,
370
382
value_id : ValueId ,
371
383
) -> ValueId {
372
384
let resolved_id = dfg. resolve ( value_id) ;
373
385
match cache. get ( & resolved_id) {
374
- Some ( cached_value) => resolve_cache ( dfg, cache, cached_value. simplified ) ,
386
+ Some ( simplification_cache) => {
387
+ if let Some ( simplified) = simplification_cache. get ( block, dom) {
388
+ resolve_cache ( block, dfg, dom, cache, simplified)
389
+ } else {
390
+ resolved_id
391
+ }
392
+ }
375
393
None => resolved_id,
376
394
}
377
395
}
378
396
379
397
// Resolve any inputs to ensure that we're comparing like-for-like instructions.
380
- instruction
381
- . map_values ( |value_id| resolve_cache ( dfg, constraint_simplification_mapping, value_id) )
398
+ instruction. map_values ( |value_id| {
399
+ resolve_cache ( block, dfg, dom, constraint_simplification_mapping, value_id)
400
+ } )
382
401
}
383
402
384
403
/// Pushes a new [`Instruction`] into the [`DataFlowGraph`] which applies any optimizations
@@ -468,8 +487,9 @@ impl<'brillig> Context<'brillig> {
468
487
}
469
488
470
489
fn get_cached (
471
- & mut self ,
490
+ & self ,
472
491
dfg : & DataFlowGraph ,
492
+ dom : & mut DominatorTree ,
473
493
instruction : & Instruction ,
474
494
side_effects_enabled_var : ValueId ,
475
495
block : BasicBlockId ,
@@ -479,7 +499,7 @@ impl<'brillig> Context<'brillig> {
479
499
let predicate = self . use_constraint_info && instruction. requires_acir_gen_predicate ( dfg) ;
480
500
let predicate = predicate. then_some ( side_effects_enabled_var) ;
481
501
482
- results_for_instruction. get ( & predicate) ?. get ( block, & mut self . dom )
502
+ results_for_instruction. get ( & predicate) ?. get ( block, dom)
483
503
}
484
504
485
505
/// Checks if the given instruction is a call to a brillig function with all constant arguments.
0 commit comments