@@ -237,7 +237,7 @@ def __init__(self, json_format: SMS_T):
237237 # We determine which elements must be computed in order to compute certain instruction
238238 self ._values_used = {}
239239 for instr_id in self ._relevant_ops :
240- self ._compute_values_used (self ._id2instr [instr_id ], self ._relevant_ops , self . _values_used )
240+ self ._compute_values_used (self ._id2instr [instr_id ], self ._values_used )
241241
242242 # Determine which topmost elements can be reused in the graph
243243 self ._top_can_be_used = {}
@@ -321,7 +321,8 @@ def select_ops(self, direct_g: nx.DiGraph):
321321 or direct_g .out_degree (instr ["id" ]) == 0 ]
322322 return relevant_operations
323323
324- def _compute_top_can_used (self , instr : instr_JSON_T , top_can_be_used : Dict [var_id_T , Set [var_id_T ]]) -> Set [var_id_T ]:
324+ def _compute_top_can_used (self , instr : instr_JSON_T , top_can_be_used : Dict [var_id_T , Set [var_id_T ]]) -> Set [
325+ var_id_T ]:
325326 """
326327 Computes for each instruction if the topmost element of the stack can be reused directly
327328 at some point. It considers commutative operations
@@ -352,8 +353,7 @@ def _compute_top_can_used(self, instr: instr_JSON_T, top_can_be_used: Dict[var_i
352353 top_can_be_used [instr ["id" ]] = current_uses
353354 return current_uses
354355
355- def _compute_values_used (self , instr : instr_JSON_T , relevant_ops : List [instr_id_T ],
356- value_uses : Dict [var_id_T , Set [var_id_T ]]) -> Set [var_id_T ]:
356+ def _compute_values_used (self , instr : instr_JSON_T , value_uses : Dict [var_id_T , Set [var_id_T ]]) -> Set [var_id_T ]:
357357 """
358358 For a given instruction, determines which stack elements must be computed
359359 """
@@ -367,14 +367,11 @@ def _compute_values_used(self, instr: instr_JSON_T, relevant_ops: List[instr_id_
367367 if instr_bef is not None :
368368 instr_bef_id = instr_bef ["id" ]
369369 if instr_bef_id not in value_uses :
370- current_uses .update (self ._compute_values_used (instr_bef , relevant_ops , value_uses ))
370+ current_uses .update (self ._compute_values_used (instr_bef , value_uses ))
371371 else :
372372 current_uses .update (value_uses [instr_bef_id ])
373- # Add only instructions that are relevant to our context
374- if instr_bef_id in relevant_ops :
375- current_uses .add (stack_var )
376- else :
377- current_uses .add (stack_var )
373+ current_uses .add (stack_var )
374+
378375 value_uses [instr ["id" ]] = current_uses
379376 return current_uses
380377
@@ -418,6 +415,8 @@ def greedy(self) -> List[instr_id_T]:
418415 self .debug_logger .debug_choose_computation (next_id , cstate )
419416
420417 terms_to_dup = self ._identify_subterms_to_dup (next_instr , cstate )
418+ self .debug_logger .debug_terms_to_dup (terms_to_dup )
419+
421420 ops = self .compute_instr (next_instr , cstate , terms_to_dup )
422421
423422 # Cheap instructions are just computed, there is no need to erase elements from the lists
@@ -530,15 +529,17 @@ def _score_candidate(self, candidates: List[instr_id_T], cstate: SymbolicState)
530529 assert candidate is not None , "Loop of _score_candidate must assign one candidate"
531530 return candidate
532531
533- def _le_ranked_options (self , option1 : Tuple [bool , Dict [var_id_T , int ]], option2 : Tuple [bool , Dict [var_id_T , int ]]) -> bool :
532+ def _le_ranked_options (self , option1 : Tuple [bool , Dict [var_id_T , int ]],
533+ option2 : Tuple [bool , Dict [var_id_T , int ]]) -> bool :
534534 # First we prioritize whether it can reuse the topmost element
535535 if option1 [0 ] != option2 [0 ]:
536536 return option2 [0 ]
537537 opt1_deepest = max (option1 [1 ].values (), default = - 1 )
538538 opt2_deepest = max (option2 [1 ].values (), default = - 1 )
539539 return opt1_deepest <= opt2_deepest
540540
541- def compute_instr (self , instr : instr_JSON_T , cstate : SymbolicState , terms_to_dup : List [var_id_T ]) -> List [instr_id_T ]:
541+ def compute_instr (self , instr : instr_JSON_T , cstate : SymbolicState , terms_to_dup : List [var_id_T ]) -> List [
542+ instr_id_T ]:
542543 """
543544 Given an instr, the current state and the terms that need to be duplicated, computes the corresponding term.
544545 This function is separated from compute_op because there
@@ -557,16 +558,10 @@ def compute_instr(self, instr: instr_JSON_T, cstate: SymbolicState, terms_to_dup
557558
558559 for stack_var in input_vars :
559560 top_elem = cstate .top_stack ()
560- if first_element and top_elem is not None and top_elem == stack_var :
561- if cstate .var_uses [top_elem ] < self ._var_total_uses [top_elem ]:
562- top_instr = self ._var2instr .get (top_elem , None )
563-
564- # Only storee it in a local if needed
565- if not cheap (top_instr ):
566- seq .extend (self .move_top_to_position (top_elem , cstate ))
567- else :
568- seq .extend (self .compute_var (top_elem , cstate ))
569-
561+ # If we can reuse the first element and this element must be not consumed elsewhere
562+ if first_element and top_elem is not None and top_elem == stack_var and \
563+ cstate .var_uses [top_elem ] == self ._var_total_uses [top_elem ]:
564+ self .fixed_elements += 1
570565 else :
571566 # Otherwise, we must return generate it with a recursive call
572567 seq .extend (self .compute_var (stack_var , cstate ))
@@ -667,11 +662,10 @@ def solve_permutation(self, cstate: SymbolicState) -> List[instr_id_T]:
667662
668663
669664class DebugLogger :
670-
671665 """
672666 Class that contains the multiple debugging messages for the greedy algorithm
673667 """
674-
668+
675669 def __init__ (self ):
676670 self ._logger = logging .getLogger ("greedy" )
677671
@@ -681,7 +675,7 @@ def debug_initial(self, ops: List[instr_id_T]):
681675 self ._logger .debug ("" )
682676
683677 def debug_loop (self , dep_graph , optg : List [instr_id_T ],
684- cstate : SymbolicState ):
678+ cstate : SymbolicState ):
685679 self ._logger .debug ("---- While loop ----" )
686680 self ._logger .debug (f"Ops not computed { list (dep_graph .nodes )} " )
687681 self ._logger .debug (f"Ops computed: { optg } " )
@@ -694,7 +688,8 @@ def debug_pop(self, var_top: var_id_T, cstate: SymbolicState):
694688 self ._logger .debug (f'State { cstate } ' )
695689 self ._logger .debug ("" )
696690
697- def debug_rank_candidates (self , candidate : instr_id_T , candidate_score : Tuple [bool , Dict [var_id_T , int ]], chosen : bool ):
691+ def debug_rank_candidates (self , candidate : instr_id_T , candidate_score : Tuple [bool , Dict [var_id_T , int ]],
692+ chosen : bool ):
698693 self ._logger .debug ("---- Score candidate ----" )
699694 self ._logger .debug (f"Candidate { candidate } " )
700695 self ._logger .debug (f'Candidate score { candidate_score } ' )
@@ -707,6 +702,11 @@ def debug_choose_computation(self, next_id: instr_id_T, cstate: SymbolicState):
707702 self ._logger .debug (cstate )
708703 self ._logger .debug ("" )
709704
705+ def debug_terms_to_dup (self , terms_to_dup : List [var_id_T ]):
706+ self ._logger .debug ("---- Terms to duplicate before computation ----" )
707+ self ._logger .debug (terms_to_dup )
708+ self ._logger .debug ("" )
709+
710710 def debug_after_permutation (self , cstate : SymbolicState , optg : List [instr_id_T ]):
711711 self ._logger .debug ("---- State after solving permutation ----" )
712712 self ._logger .debug (cstate )
0 commit comments