Skip to content

Commit 0076dc6

Browse files
committed
#18 Fix var uses + handle case in which computations can be reused
1 parent 8ceb48f commit 0076dc6

1 file changed

Lines changed: 26 additions & 26 deletions

File tree

‎src/greedy/greedy_new_version.py‎

Lines changed: 26 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -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

669664
class 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

Comments
 (0)