1.1 --- a/micropython/opt.py Thu Sep 01 00:35:47 2011 +0200
1.2 +++ b/micropython/opt.py Mon Sep 05 00:16:33 2011 +0200
1.3 @@ -52,6 +52,9 @@
1.4 # control-flow operations will flush the "active" instruction.
1.5
1.6 self.active = None
1.7 + self.saved_value_op = None
1.8 + self.saved_value_block = None
1.9 + self.saved_value_pos = None
1.10
1.11 # Instructions providing the active value.
1.12
1.13 @@ -83,6 +86,7 @@
1.14 collecting the active instructions from each of the blocks otherwise.
1.15 """
1.16
1.17 + self.store_active_value()
1.18 self.clear_active()
1.19
1.20 # Make a new collection of instructions for a new block.
1.21 @@ -111,7 +115,8 @@
1.22
1.23 "Set the value-providing active instruction."
1.24
1.25 - if isinstance(op, current_value_instructions) and op.target == "working":
1.26 + if affects_register(op, "working"):
1.27 + self.store_active_value()
1.28 self.active_values.clear()
1.29 self.active_values.add(op)
1.30
1.31 @@ -157,6 +162,36 @@
1.32
1.33 self.active = None
1.34
1.35 + # Permit the active value to be requested and restored.
1.36 +
1.37 + def request_active_value(self, temp, block, pos):
1.38 +
1.39 + """
1.40 + Request the current active value so that if the value is changed, a
1.41 + temporary storage element or equivalent will be allocated.
1.42 + """
1.43 +
1.44 + self.store_active_value()
1.45 + self.saved_value_op = temp
1.46 + self.saved_value_block = block
1.47 + self.saved_value_pos = pos
1.48 +
1.49 + def store_active_value(self):
1.50 +
1.51 + "Store the requested active value"
1.52 +
1.53 + if self.saved_value_op is not None:
1.54 + self.translation.set_temp(self.saved_value_op, self.saved_value_block, self.saved_value_pos)
1.55 + self.ignore_active_value()
1.56 +
1.57 + def ignore_active_value(self):
1.58 +
1.59 + "Ignore the active value."
1.60 +
1.61 + self.saved_value_op = None
1.62 + self.saved_value_block = None
1.63 + self.saved_value_pos = None
1.64 +
1.65 # Optimisation tests.
1.66
1.67 def should_optimise_constant_storage(self):
1.68 @@ -218,15 +253,17 @@
1.69 LoadName, LoadTemp, LoadAddress
1.70 ))
1.71
1.72 - def is_resultant_no_operation(self, instruction):
1.73 + def is_resultant_no_operation(self, instruction, last_op=None):
1.74
1.75 """
1.76 Return whether 'instruction' merely stores its input where the input
1.77 originally came from.
1.78 """
1.79
1.80 - return (
1.81 - isinstance(instruction, StoreTemp) and instruction.target == instruction.source
1.82 + last_op = last_op or self.translation.last_op()
1.83 + return last_op and last_op.attr == instruction.attr and (
1.84 + isinstance(instruction, StoreTemp) and isinstance(last_op, LoadTemp) or
1.85 + isinstance(instruction, StoreAddress) and isinstance(last_op, LoadAddress)
1.86 )
1.87
1.88 # Convenience tests on outputs.
1.89 @@ -377,7 +414,7 @@
1.90 value to be stored such that instead of subsequently accessing the
1.91 temporary storage, that instruction is substituted.
1.92
1.93 - If no optimisation can be achieved, a StoreTemp instruction is produced
1.94 + If no optimisation can be achieved, temporary storage is requested
1.95 and the appropriate LoadTemp instruction is returned.
1.96
1.97 Restriction: for use only in situations where the source of the
1.98 @@ -388,7 +425,7 @@
1.99 if self.should_optimise_temp_storage() and \
1.100 self.have_temp_compatible_access():
1.101
1.102 - # Remove the active value contributor.
1.103 + # Remove the active value contributor if possible.
1.104
1.105 removed = self.remove_active_value()
1.106 if removed is not None:
1.107 @@ -398,9 +435,14 @@
1.108 self.translation.ensure_temp(removed)
1.109 return removed
1.110
1.111 + # Otherwise, just leave it in place, but return the instruction.
1.112 +
1.113 + else:
1.114 + return self.get_active_value()
1.115 +
1.116 return self.translation.get_temp()
1.117
1.118 - def optimise_away_no_operations(self, instruction):
1.119 + def optimise_away_no_operations(self, instruction, last_op=None):
1.120
1.121 """
1.122 Optimise away operations which just store their inputs in the place
1.123 @@ -408,7 +450,7 @@
1.124 """
1.125
1.126 return self.should_optimise_away_no_operations() and \
1.127 - self.is_resultant_no_operation(instruction)
1.128 + self.is_resultant_no_operation(instruction, last_op)
1.129
1.130 def optimise_unused_results(self):
1.131